:Host 托管任务排队的完整原理指南)
PI-Desktop 持久化轮次队列Turn QueueHost 托管任务排队的完整原理指南【免费下载链接】PI-DesktopLocal-first AI coding agent desktop: Electron Rust host core pi Agent Harness user-installable plugins项目地址: https://gitcode.com/GitHub_Trending/pid/PI-DesktopPI-Desktop 是一款本地优先Local-first的 AI 编程智能体桌面应用采用 Electron Rust host core pi Agent Harness 架构。它最容易被忽略、却最体现工程功底的设计之一就是持久化轮次队列Turn Queue当 AI 正在干活时你继续输入的每一条提示词都会被写入 Rust 后端的 SQLite 数据库里排队重启应用也不会丢失。本文带你快速看懂这套 Host 托管的任务排队机制是如何工作的。痛点为什么轮次队列必须持久化在 AI 编程工具里一轮对话turn往往要跑几十秒甚至几分钟。这段时间里你在输入框里敲下的后续指令只能先排个队。早期设计D373 草案把队列放在渲染进程的内存里结果有两个致命问题窗口一刷新排队中的提示词就全没了——队列只存在于敲下它的那个窗口其他客户端看不见——无头headlessAgent Host 和远程控制台对这条队列完全失明。docs/adr/0213-persist-host-owned-turn-queue.md 记录了这个决策把队列移出渲染内存交给 Host 持久化。被否决的替代方案存进浏览器 localStorage同样因为对其他客户端和 Headless Host 不可见而被放弃。队列存在哪里Rust host-core 独占的 SQLite 表项目的冻结决策 12 规定SQLite 由 Rust host-core 独占。所以队列不是一个文件而是一张数据库表turn_queueschema v15 引入v18 增加优先级列由 host-core 提供写入面而不是让某个模块自己写文件。表结构的核心字段包括session_id外键级联删除删会话时队列自动清空principalidempotency_keyinput_hash幂等三件套content/attachments_json/permission_mode提示词内容、附件与权限模式快照position入队顺序priority可空被立即发送提升后的优先级块序号。建表语句见 docs/spec/03-runtime/04-data-storage.md 的 §4.6b存储与迁移逻辑在 crates/host-core/src/turn_queue.rs。每次迁移如 v14→v15都是纯增量并保留pi.sqlite.v14.bak备份老库升级后原有行保持 FIFO 顺序照常工作——这一点有专门的测试覆盖。四个 RPC 方法 一个排序操作队列的全部控制面host-core 只暴露一组只写数据、绝不决定执行的 RPC 方法见 crates/host-core/src/rpc/mod.rsRPC 方法作用关键约束session.queuePush入队一条提示词按(session, principal, idempotencyKey)幂等内容哈希一致则返回已有条目不一致则报IDEMPOTENCY_CONFLICT队列满 8 条报QUEUE_FULLsession.queueList列出某会话或全部队列按投递顺序返回session.queueRemove删除一条删除会话时级联清空session.queuePrioritize立即发送提升到优先级块末尾单向提升重复提升报ALREADY_PRIORITIZEDsession.queueReorder普通队列内上下移一位只能交换相邻的未提升条目其中每会话上限 8 条MAX_QUEUED_TURNS_PER_SESSION是 RACP 限额表给出的初始目标防止无界排队。一键立即发送按点击顺序排队的优先级块Send now立即发送是队列上最好玩的特性规则由 ADR 0265 定稿docs/adr/0265-turn-queue-priority-block-and-row-actions.md投递顺序 优先级块在前按点击先后普通队列在后按入队先后。SQL 层一行排序搞定ORDER BY (priority IS NULL) ASC, priority ASC, position ASC见 crates/host-core/src/turn_queue.rs。提升是单向的。一条被提升过的条目再次点击立即发送会得到冲突错误而不是被悄悄挪位——因为 Host 已经承诺要启动它了提升不能半生效。被提升的行被锁定界面上禁用上移、下移、编辑、删除按钮显示为已决定状态并保留 tooltip 解释为什么锁住。优先级块作为同一轮的连续消息投递第一条启动该轮后续条目通过 Composer 的 steering 通道注入同一轮于是对话记录呈现用户: 第一条、用户: 第二条、模型回答一次而不是割裂成多个 turn。也就是说连续两次立即发送不会后一次点击覆盖前一次而是第一次点的先跑——这修复了旧版last click wins的恼人行为。排空规则Host 何时才真正开工队列的存SQLite 表和用准入与排空分属两个模块这是整个设计里最优雅的分工Rust host-core只管存储store never decides execution——它永远不会自己启动任何任务无头 Agent Host 模块TypeScript负责准入与排空核心实现在 packages/agent-host/src/turn-queue.ts。排空有两条铁律只在当前 turn 的终结事件之后才取出一条执行。运行中的 turn 绝不被插队打断启动栅栏startup fence永不重放工作重启后恢复出来的队列一律处于held挂起状态必须等控制器controller挂接、调用resume后才会继续排空。重启不会让 AI无人看管地自动开工。还有一个容易被忽视的修复turn 的所有者finishTurn上报的结算才是轮次结束的唯一权威。运行时发出的终结事件如果指向一个已不再拥有的 turnisStaleTerminalEvent会被丢弃这就避免了先立即发送、再停止把某条排队条目永久卡死的问题。重启之后队列如何复活完整生命周期可以概括为五步渲染进程不再维护内存队列输入框通过agent/queue/push推给 Host前端状态见 apps/desktop/src/stores/slices/queue-slice.ts 与 apps/desktop/src/lib/queued-prompts.tshost-core 幂等写入turn_queue表Host 把agent/event/queueChanged事件广播给所有客户端界面实时镜像同一份队列会话被删除时外键级联让队列条目随之消失应用重启时Agent Host 从 store 按投递顺序恢复全部条目挂起等待控制器挂接。带来的直接收益重启不再丢失排队提示词——它们会以挂起状态重新出现在快照的queuedTurns里并且所有连接同一 Host 的客户端看到的是同一条队列桌面端、远程控制台完全一致。核心源码地图想动手细读建议按这个顺序决策背景docs/adr/0213-persist-host-owned-turn-queue.md、docs/adr/0265-turn-queue-priority-block-and-row-actions.md存储层Rustcrates/host-core/src/turn_queue.rs排空与提升TypeScriptpackages/agent-host/src/turn-queue.ts数据契约docs/spec/03-runtime/04-data-storage.md行为测试packages/agent-host/src/turn-queue.test.ts一句话总结PI-Desktop 的持久化轮次队列 Rust 管存、Host 管放、事件驱动排空、重启挂起等待人。这套存储与执行彻底分离 幂等写入 单向提升的组合正是它能在重启、多客户端、长任务等边缘场景下都不丢提示词的原因也很值得其他 AI 桌面应用借鉴。【免费下载链接】PI-DesktopLocal-first AI coding agent desktop: Electron Rust host core pi Agent Harness user-installable plugins项目地址: https://gitcode.com/GitHub_Trending/pid/PI-Desktop创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考