输入、附件、引用与发送队列
从草稿到已接受输入
renderer 保存编辑状态和附件引用,通过 preload 提交 RunInput。主进程负责确认 session、校验文本/文件/附件、展开引用、保存用户输入事实,再启动模型。UI 点击发送与主进程成功接受是不同时间点;失败不能提前清掉不可恢复的草稿。
图片由主进程管理导入、所有权和持久化路径,IPC 传递受控 ID。文件引用可携带行号或评论;会话引用由宿主读取目标会话可用内容,不让 renderer 自己拼绝对数据路径。命令 shell 展开在实际执行阶段发生,入队校验不会执行 shell。
ChatComposer 的 @ 面板合并文件搜索结果与当前会话 suggestions 中的子智能体,和 / 共用宿主已过滤启用状态、作用域及重名覆盖的目录。机器人名称、描述沿用 ZCode 的前缀、子串和英文子序列排序,中文查询只匹配连续文字;空查询保留目录顺序。两组候选共用键盘索引和滚动容器,机器人选择复用文本插入与光标恢复,不写入 fileReferences。+ 添加面板继续只提供附件和文件。
每个会话独立串行
SessionInputQueue 为每个 session 建立 Promise 链,防止发送、删除、排序、立即发送同时修改队列。commit 顺序为 save → 内存状态 → publish;保存失败时不能先显示已成功。
排队项状态为 queued 或 dispatching(实际提交中),含文本、引用和已保留附件。附件不能同时属于两个队列项;retain 成功后才保存队列,保存失败就解除保留。移除项释放资源,取回编辑则把资源交回草稿;草稿保存和队列删除在同一 SQLite 事务提交,失败时均保留原状态。
派发与去重
派发前先把项改为 dispatching,再调用宿主 start。宿主接受后移出队列;若接受之后队列保存失败,内存中仍移除该项并暂停,避免同一输入再次执行。历史记录中的 accepted input IDs 在重启恢复时再次去重。
恢复的残余项统一回 queued,有剩余项就暂停自动发送并显示 restart 原因。正常完成可继续排队;错误或停止会暂停,等待用户决定。重启不是重新授权执行全部积压命令。
立即发送与归档
“立即”和 Command/Ctrl+Enter 对齐 ZCode 的 startNow:草稿先校验,队列项先持久化为 dispatching,再停止当前轮并等待模型请求、工具及子智能体结束,最后由宿主 start 启动新轮。停止当前轮期间抑制其队列 settled 回调,防止旧轮将保留队列暂停或抢先派发。内部 AgentSession.steer 与此入口分离,不用于用户的立即发送。
停止或启动失败时,未接受项恢复为 queued 并暂停,允许重试、编辑和移除。若宿主已经持久化接受记录,即使启动回执或后续队列保存失败,也必须移除该项,防止重发。队列投影发布失败不会撤销已接受回执。
兼容旧版 delivery=guide 队列:启动时仅针对这些残余 ID 扫描 durable userGuide 消息,与 accepted input IDs 合并去重;未消费项去掉 delivery 标记,恢复为普通暂停队列。已保存的 userGuide 正文、附件、导航和分支数据继续可读。内部 steering 在模型请求失败后的重试前消费待引导消息,避免重试沿用旧上下文。此处保证本地已接受输入的交付去重,不承诺外部模型请求的执行具有事务语义。
控制命令、自定义命令与子智能体命令保留下一轮准备路径。用户选择清空旧队列时也先确保新输入有效,防止一次无效发送删掉已接受消息。
归档在同一串行链中检查已停止,持久化归档后清空队列并回收附件。关闭应用时停止接收新操作,等已排队操作收尾,将剩余输入保存为暂停状态。