@co0ontty/wand 4.89.4 → 4.89.5-beta.343.1.gb264adf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +17 -4
  2. package/dist/ai-team-employee-binding.js +2 -1
  3. package/dist/ai-team-runner.d.ts +2 -1
  4. package/dist/ai-team-runner.js +38 -2
  5. package/dist/ai-team-types.js +3 -2
  6. package/dist/ai-text-runner.d.ts +61 -0
  7. package/dist/ai-text-runner.js +653 -0
  8. package/dist/archive-policy.d.ts +17 -0
  9. package/dist/archive-policy.js +8 -0
  10. package/dist/bounded-process-output.d.ts +5 -0
  11. package/dist/bounded-process-output.js +9 -0
  12. package/dist/build-info.json +4 -4
  13. package/dist/command-error.d.ts +6 -0
  14. package/dist/command-error.js +8 -0
  15. package/dist/config.js +11 -42
  16. package/dist/conversation-service.d.ts +7 -1
  17. package/dist/conversation-service.js +35 -10
  18. package/dist/conversation-session-preview.d.ts +2 -0
  19. package/dist/conversation-session-preview.js +4 -0
  20. package/dist/decision-client.js +22 -6
  21. package/dist/decision-expert-employee.js +2 -2
  22. package/dist/decision-expert-identity.d.ts +1 -1
  23. package/dist/decision-expert-identity.js +1 -1
  24. package/dist/decision-expert-service.d.ts +1 -0
  25. package/dist/decision-expert-service.js +82 -76
  26. package/dist/decision-hardware.js +4 -3
  27. package/dist/decision-types.d.ts +4 -0
  28. package/dist/decision-types.js +4 -0
  29. package/dist/deployment-lock.d.ts +13 -0
  30. package/dist/deployment-lock.js +189 -0
  31. package/dist/employee-text.js +1 -1
  32. package/dist/fixed-employee-avatar.d.ts +6 -0
  33. package/dist/fixed-employee-avatar.js +4 -0
  34. package/dist/git-quick-commit.d.ts +5 -40
  35. package/dist/git-quick-commit.js +7 -635
  36. package/dist/hr-employee-identity.d.ts +5 -0
  37. package/dist/hr-employee-identity.js +5 -0
  38. package/dist/hr-employee.d.ts +5 -0
  39. package/dist/hr-employee.js +21 -0
  40. package/dist/middleware/path-safety.js +1 -1
  41. package/dist/milestone-scope.js +1 -1
  42. package/dist/model-auto-assign.d.ts +1 -1
  43. package/dist/model-auto-assign.js +1 -1
  44. package/dist/models.d.ts +4 -0
  45. package/dist/models.js +21 -1
  46. package/dist/npm-update-utils.js +18 -55
  47. package/dist/pi-auto-resources.js +6 -3
  48. package/dist/plush-avatar.d.ts +12 -2
  49. package/dist/plush-avatar.js +16 -2
  50. package/dist/plush-cat-appearance.d.ts +97 -0
  51. package/dist/plush-cat-appearance.js +118 -0
  52. package/dist/plush-cat-whiskers.d.ts +6 -0
  53. package/dist/plush-cat-whiskers.js +42 -0
  54. package/dist/process-manager.d.ts +22 -21
  55. package/dist/process-manager.js +49 -83
  56. package/dist/prompt-optimizer.d.ts +1 -1
  57. package/dist/prompt-optimizer.js +1 -1
  58. package/dist/render-host.js +1 -19
  59. package/dist/retention.js +8 -10
  60. package/dist/scheduled-task-service.d.ts +41 -0
  61. package/dist/scheduled-task-service.js +320 -0
  62. package/dist/scheduled-task-state.d.ts +6 -0
  63. package/dist/scheduled-task-state.js +28 -0
  64. package/dist/scheduled-task-time.d.ts +4 -0
  65. package/dist/scheduled-task-time.js +82 -0
  66. package/dist/scheduled-task-types.d.ts +71 -0
  67. package/dist/scheduled-task-types.js +1 -0
  68. package/dist/server-employee-routes.d.ts +3 -0
  69. package/dist/server-employee-routes.js +28 -18
  70. package/dist/server-file-routes.js +44 -1
  71. package/dist/server-pi-recommendation-routes.js +13 -4
  72. package/dist/server-resume-routes.js +1 -1
  73. package/dist/server-scheduled-task-routes.d.ts +4 -0
  74. package/dist/server-scheduled-task-routes.js +34 -0
  75. package/dist/server-session-routes.d.ts +2 -10
  76. package/dist/server-session-routes.js +40 -69
  77. package/dist/server-task-routes.d.ts +2 -17
  78. package/dist/server-task-routes.js +23 -109
  79. package/dist/server-team-dispatch-routes.js +12 -2
  80. package/dist/server-update-routes.js +12 -3
  81. package/dist/server-workspace-routes.d.ts +1 -1
  82. package/dist/server-workspace-routes.js +40 -74
  83. package/dist/server.js +56 -17
  84. package/dist/session-registry.d.ts +4 -0
  85. package/dist/session-registry.js +27 -11
  86. package/dist/session-request.d.ts +9 -0
  87. package/dist/session-request.js +27 -0
  88. package/dist/session-topic.d.ts +1 -1
  89. package/dist/session-topic.js +1 -1
  90. package/dist/silicon-employee-draft.d.ts +2 -2
  91. package/dist/silicon-employee-draft.js +3 -3
  92. package/dist/socket-probe.d.ts +2 -0
  93. package/dist/socket-probe.js +20 -0
  94. package/dist/storage-schedules.d.ts +20 -0
  95. package/dist/storage-schedules.js +78 -0
  96. package/dist/storage-schema.d.ts +3 -0
  97. package/dist/storage-schema.js +702 -0
  98. package/dist/storage.d.ts +29 -2
  99. package/dist/storage.js +148 -698
  100. package/dist/structured-exec-pump.js +79 -38
  101. package/dist/structured-session-manager.d.ts +8 -17
  102. package/dist/structured-session-manager.js +85 -501
  103. package/dist/system-employee.d.ts +1 -1
  104. package/dist/system-employee.js +1 -1
  105. package/dist/task-archive-policy.d.ts +4 -0
  106. package/dist/task-archive-policy.js +16 -0
  107. package/dist/task-read-model.d.ts +27 -0
  108. package/dist/task-read-model.js +47 -0
  109. package/dist/task-retention.d.ts +1 -1
  110. package/dist/task-retention.js +1 -1
  111. package/dist/task-title-service.d.ts +30 -0
  112. package/dist/task-title-service.js +122 -0
  113. package/dist/task-title.d.ts +1 -1
  114. package/dist/task-title.js +1 -1
  115. package/dist/terminal-daemon-client.js +1 -18
  116. package/dist/tui/commands.d.ts +1 -1
  117. package/dist/tui/commands.js +6 -3
  118. package/dist/user-memory.js +1 -1
  119. package/dist/web-ui/asset-runtime.d.ts +12 -0
  120. package/dist/web-ui/asset-runtime.js +6 -0
  121. package/dist/web-ui/chat-message-meta.d.ts +3 -1
  122. package/dist/web-ui/chat-message-meta.js +21 -1
  123. package/dist/web-ui/composer-avatar-activity.d.ts +6 -0
  124. package/dist/web-ui/composer-avatar-activity.js +29 -0
  125. package/dist/web-ui/content/ai-teams.js +13 -13
  126. package/dist/web-ui/content/module-manifest.json +1 -0
  127. package/dist/web-ui/content/modules/206dd6fe9480feed/chat-render-5WZGIRQ7.js +24 -0
  128. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-26NLYQW5.js +111 -0
  129. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-34NMKHUN.js +1 -0
  130. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-57XAPHNS.js +36 -0
  131. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-5J3EQSWV.js +1 -0
  132. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-5MIXEH7P.js +1 -0
  133. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-A7N5KYZL.js +1 -0
  134. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-BPXSNT4W.js +1 -0
  135. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-D2WG3LJN.js +20 -0
  136. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-NURCNMRU.js +1 -0
  137. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-SJC4ZXP3.js +1 -0
  138. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-XXSPOSVD.js +1 -0
  139. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-YOXXNXOX.js +2 -0
  140. package/dist/web-ui/content/modules/206dd6fe9480feed/chunk-YX475LXO.js +1 -0
  141. package/dist/web-ui/content/modules/206dd6fe9480feed/employee-card-KB44OFX5.js +1 -0
  142. package/dist/web-ui/content/modules/206dd6fe9480feed/host-2X6ZCKPS.js +1 -0
  143. package/dist/web-ui/content/modules/206dd6fe9480feed/host-5QOHKHNC.js +1 -0
  144. package/dist/web-ui/content/modules/206dd6fe9480feed/host-AI64RHEZ.js +1 -0
  145. package/dist/web-ui/content/modules/206dd6fe9480feed/host-DU3XW44J.js +1 -0
  146. package/dist/web-ui/content/modules/206dd6fe9480feed/host-FWZVWOP6.js +1 -0
  147. package/dist/web-ui/content/modules/206dd6fe9480feed/host-GF5KKLZR.js +4 -0
  148. package/dist/web-ui/content/modules/206dd6fe9480feed/host-IIXD7IZL.js +1 -0
  149. package/dist/web-ui/content/modules/206dd6fe9480feed/host-LPXYTXLQ.js +69 -0
  150. package/dist/web-ui/content/modules/206dd6fe9480feed/host-MR5EGBX4.js +1 -0
  151. package/dist/web-ui/content/modules/206dd6fe9480feed/host-PBHWQEOX.js +2 -0
  152. package/dist/web-ui/content/modules/206dd6fe9480feed/host-QWMGB6DH.js +5 -0
  153. package/dist/web-ui/content/modules/206dd6fe9480feed/host-TQRIXUV5.js +3 -0
  154. package/dist/web-ui/content/modules/206dd6fe9480feed/host-ZGYIE4IZ.js +1 -0
  155. package/dist/web-ui/content/modules/206dd6fe9480feed/host-ZH5TRUMM.js +1 -0
  156. package/dist/web-ui/content/modules/206dd6fe9480feed/host-bridge-P7IE7JK6.js +1 -0
  157. package/dist/web-ui/content/modules/206dd6fe9480feed/library-bridge-UEPAUWAR.js +1 -0
  158. package/dist/web-ui/content/modules/206dd6fe9480feed/page-AHCH35BI.js +3 -0
  159. package/dist/web-ui/content/modules/206dd6fe9480feed/panel-7774KQSY.js +1 -0
  160. package/dist/web-ui/content/modules/206dd6fe9480feed/runtime.js +851 -0
  161. package/dist/web-ui/content/modules/206dd6fe9480feed/sha256-ANXV72UC.js +1 -0
  162. package/dist/web-ui/content/modules/206dd6fe9480feed/task-board-host-7UP2CXSK.js +2 -0
  163. package/dist/web-ui/content/modules/206dd6fe9480feed/workspace-agent-picker-JFFDXA3L.js +1 -0
  164. package/dist/web-ui/content/modules/206dd6fe9480feed/workspace-window-N4AZ2TM5.js +1 -0
  165. package/dist/web-ui/content/plush-avatar.js +177 -177
  166. package/dist/web-ui/content/scripts.js +1 -1090
  167. package/dist/web-ui/content/styles.css +1 -1
  168. package/dist/web-ui/content/tailwind.css +1 -1
  169. package/dist/web-ui/embedded-assets.d.ts +32 -0
  170. package/dist/web-ui/embedded-assets.js +10 -8
  171. package/dist/web-ui/markdown.d.ts +3 -2
  172. package/dist/web-ui/markdown.js +61 -46
  173. package/dist/web-ui/message-file-target.d.ts +13 -0
  174. package/dist/web-ui/message-file-target.js +85 -0
  175. package/dist/web-ui/react/local-preview/controller.d.ts +2 -0
  176. package/dist/web-ui/react/local-preview/controller.js +12 -0
  177. package/dist/web-ui/scripts.d.ts +10 -0
  178. package/dist/web-ui/scripts.js +42 -5
  179. package/package.json +6 -3
  180. package/browser-extension/icons/wand-128.png +0 -0
  181. package/browser-extension/icons/wand-16.png +0 -0
  182. package/browser-extension/icons/wand-32.png +0 -0
  183. package/browser-extension/icons/wand-48.png +0 -0
  184. package/dist/commit-task-archive.d.ts +0 -8
  185. package/dist/commit-task-archive.js +0 -65
package/README.md CHANGED
@@ -59,6 +59,7 @@ wand config:password
59
59
  - **Message queueing** — keep typing while the AI is working; messages are queued automatically
60
60
  - **File browser** — built-in path browsing and search
61
61
  - **Quick commits** — review Git changes and generate a commit message from the web UI
62
+ - **Scheduled tasks** — choose an employee, workspace directory and prompt, run once or repeat daily/weekly, and review execution history. See [scheduling behavior](docs/scheduled-tasks.md).
62
63
 
63
64
  #### Deployment
64
65
 
@@ -135,7 +136,7 @@ npm run check # TypeScript type check
135
136
  npm run build # Compile and copy static assets to dist/
136
137
  ```
137
138
 
138
- On this configured development machine, use `~/start.sh` to build/install the working tree and restart, `~/start.sh --restart` to restart without rebuilding, or `~/start.sh --status` to check status. This user-home helper enters the project and handles sudo locally; do not prefix it with `sudo`. It is not included in a fresh clone, and credentials stay outside the repository. Restart safety rules remain in [AGENTS.md](AGENTS.md).
139
+ On this configured development machine, use `~/start.sh` to build/install the working tree and restart, `~/start.sh --restart` to restart without rebuilding, or `~/start.sh --status` to check status. This user-home helper enters the project and handles sudo locally; do not prefix it with `sudo`. It is not included in a fresh clone, and credentials stay outside the repository. Restart safety rules remain in [AGENTS.md](AGENTS.md). Build/check commands share a project lock; local deployment and npm updates share the global installation lock. A busy lock fails before package or service changes. Local Beta versions are written only to build metadata and a private package snapshot, never to the working tree's package manifests. The `build:body` / `check:body` scripts are internal steps for the locked entry points.
139
140
 
140
141
  Use an isolated config for testing:
141
142
 
@@ -233,18 +234,30 @@ npm install -g @google/gemini-cli@latest
233
234
 
234
235
  #### 交互体验
235
236
 
236
- - **结构化对话** — 代码块语法高亮、工具调用折叠/展开、多问题分组渲染、Token 用量按轮累计
237
+ - **结构化对话** — 代码块语法高亮、工具调用折叠/展开、多问题分组渲染、输入区展示最近一轮 Token 用量与费用
237
238
  - **个性化角色** — 像素风猫咪头像(赛博虎妞 / 勤劳初二),支持自定义对话角色名称
238
239
  - **消息排队** — 在 AI 思考时可继续输入,消息自动排队发送
239
240
  - **文件浏览器** — 内置路径浏览和搜索功能
240
241
  - **本地预览** — 消息和终端里的本机链接可点击预览;顶栏也可手动打开本机 HTTP 端口或 HTML 目录
241
242
  - **快捷提交** — Git 变动快速提交入口,一键生成 commit message
243
+ - **定时任务** — 选择员工、工作区目录和提示词,单次或每天/每周自动执行,并查看执行记录;详见 [使用说明](docs/scheduled-tasks.md)。
242
244
 
243
245
  #### 部署与访问
244
246
 
245
247
  - **多平台客户端** — Android / iOS / macOS 原生客户端,支持加密连接码分发、自动更新检查
246
248
  - **HTTPS** — 可选自签证书,适合远程或移动端访问
247
249
  - **版本管理** — 内置更新检查与升级提示,支持 stable/beta 双通道
250
+
251
+ Web 设置中的「Beta 通道」决定服务端 npm 更新来源:关闭时仅检查
252
+ `@co0ontty/wand@latest`,开启时检查 `@co0ontty/wand@beta`;「自动更新 Web 服务」
253
+ 独立决定是否自动安装。检查后安装锁定具体版本,避免 dist-tag 在安装期间移动。
254
+ 关闭 Beta 不会自动降级;需要立即返回较旧正式版时,点击「更新或重新安装」。
255
+
256
+ 正式 npm 发布由 `vX.Y.Z` Git tag 触发,只写入 `latest`,拒绝预发布版本。
257
+ master 的 Beta 发布只写入 `beta`,版本为下一补丁号加
258
+ `-beta.<构建序号>.<重试序号>.g<提交>`,例如 `4.89.5-beta.100.1.gabcdef0`。
259
+ 版本基数同时检查正式 Git tags 和 npm latest,兼容未推送 Git 的本地正式发布。
260
+ Beta 尚未发布、通道版本无效或 npm 暂不可达时,不自动安装其他通道。
248
261
  - **CLI 更新** — 在服务端设置中检查并快速更新 Claude Code、Codex、OpenCode、Qoder CLI、Pi 和 Gemini CLI,也可开启自动更新
249
262
 
250
263
  ### 配置
@@ -271,7 +284,7 @@ wand config:set port 9443
271
284
 
272
285
  ### 语音识别
273
286
 
274
- Web、Android、iOS 可在语音输入设置中选择「服务端识别」或「客户端本地识别」。服务端使用按需安装的 whisper.cpp 多语言模型,支持无 GPU CPU 服务器、Mac mini Metal 与可选 CUDA;模型不随普通构建下载。部署、模型大小、鉴权和隐私边界见 [服务端语音识别](docs/server-speech.md)。设置内下载/初始化 LAYA 与语音模型,以及「决策专家」的本机性能检查和默认本地/免费调用链,见 [本地模型管理](docs/local-model-setup.md)。
287
+ Web、Android、iOS 可在语音输入设置中选择「服务端识别」或「客户端本地识别」。服务端使用按需安装的 whisper.cpp 多语言模型,支持无 GPU CPU 服务器、Mac mini Metal 与可选 CUDA;模型不随普通构建下载。部署、模型大小、鉴权和隐私边界见 [服务端语音识别](docs/server-speech.md)。设置内下载/初始化 LAYA 与语音模型,以及「石一」(决策专家)的本机性能检查和默认本地/免费调用链,见 [本地模型管理](docs/local-model-setup.md)。
275
288
 
276
289
  ### 可选本地决策(实验性)
277
290
 
@@ -322,7 +335,7 @@ npm run check # TypeScript 类型检查
322
335
  npm run build # 编译 + 复制静态资源到 dist/
323
336
  ```
324
337
 
325
- 本机开发环境统一调用用户主目录入口:`~/start.sh` 构建/安装当前代码并重启,`~/start.sh --restart` 仅重启、不重新构建,`~/start.sh --status` 查状态。入口自动进入项目并在本地处理 sudo,外层不要再加 sudo;它是本机配置,不随新克隆提供,凭据不入仓库。重启安全约束仍以 [AGENTS.md](AGENTS.md) 为准。
338
+ 本机开发环境统一调用用户主目录入口:`~/start.sh` 构建/安装当前代码并重启,`~/start.sh --restart` 仅重启、不重新构建,`~/start.sh --status` 查状态。入口自动进入项目并在本地处理 sudo,外层不要再加 sudo;它是本机配置,不随新克隆提供,凭据不入仓库。重启安全约束仍以 [AGENTS.md](AGENTS.md) 为准。构建/检查共用项目锁,本地部署与 npm 更新共用全局安装锁;锁忙时在包或服务修改前拒绝执行。本地 Beta 版本仅写入构建信息和私有打包快照,不改共享工作树的包版本文件。`build:body` / `check:body` 是加锁入口的内部步骤,不直接调用。
326
339
 
327
340
  隔离测试环境(不影响生产实例):
328
341
 
@@ -31,7 +31,8 @@ export function requireTeamEmployee(source, id) {
31
31
  }
32
32
  // The default partner's read projection includes short-term habits; they are not team snapshot data.
33
33
  return isDefaultSiliconEmployee(employee)
34
- ? defaultEmployeeDefinition(employee.agents, employee.updatedAt, source.getSiliconEmployeeDefinition?.(id) ?? employee, null)
34
+ ? { ...defaultEmployeeDefinition(employee.agents, employee.updatedAt, source.getSiliconEmployeeDefinition?.(id) ?? employee, null),
35
+ avatar: employee.avatar }
35
36
  : employee;
36
37
  }
37
38
  /** Resolve once per new run. Team duty/role/leadership remain local; no knowledge is read. */
@@ -178,6 +178,7 @@ export declare class AiTeamRunner {
178
178
  private readonly noDegrade;
179
179
  private readonly teamRequestIds;
180
180
  private sweepTimer;
181
+ private disposed;
181
182
  /** 脱敏参照目录只算一次:os.homedir() 读 env,configDir 随 storage 定,运行期不变。 */
182
183
  private redactionDirsValue;
183
184
  constructor(options: AiTeamRunnerOptions);
@@ -284,7 +285,7 @@ export declare class AiTeamRunner {
284
285
  * 没变就什么都不发。巡检间隔与 evaluate 行为都不动。
285
286
  */
286
287
  startSweep(): void;
287
- dispose(): void;
288
+ dispose(): Promise<void>;
288
289
  /** 等当前排队的所有操作跑完(测试用)。 */
289
290
  idle(): Promise<void>;
290
291
  private enqueue;
@@ -381,6 +381,7 @@ export class AiTeamRunner {
381
381
  noDegrade = new Set();
382
382
  teamRequestIds = new Map();
383
383
  sweepTimer = null;
384
+ disposed = false;
384
385
  /** 脱敏参照目录只算一次:os.homedir() 读 env,configDir 随 storage 定,运行期不变。 */
385
386
  redactionDirsValue = null;
386
387
  constructor(options) {
@@ -423,6 +424,8 @@ export class AiTeamRunner {
423
424
  }
424
425
  // ── 公开操作 ──
425
426
  async start(input) {
427
+ if (this.disposed)
428
+ throw new AiTeamConflictError("AiTeamRunner has been disposed.");
426
429
  const definition = input.team ?? this.storage.getAiTeam(input.teamId ?? "");
427
430
  if (!definition)
428
431
  throw new Error("团队不存在。");
@@ -791,6 +794,8 @@ export class AiTeamRunner {
791
794
  }
792
795
  /** 挂一次 run 级 live 去抖:同一 run 每 500ms 至多算一遍、推一次,与 evaluate 的计时器互不干扰。 */
793
796
  scheduleLivePush(runId) {
797
+ if (this.disposed)
798
+ return;
794
799
  if (!this.notifyLiveListener || this.liveTimers.has(runId))
795
800
  return;
796
801
  const timer = setTimeout(() => {
@@ -807,6 +812,8 @@ export class AiTeamRunner {
807
812
  * 放行不松开去抖:推完照样记指纹并重排心跳,所以静默期最多每 heartbeatMs 一次,不是无界重推。
808
813
  */
809
814
  pushLive(runId, heartbeat = false) {
815
+ if (this.disposed)
816
+ return;
810
817
  if (!this.notifyLiveListener)
811
818
  return;
812
819
  const run = this.storage.getAiTeamRun(runId);
@@ -858,6 +865,8 @@ export class AiTeamRunner {
858
865
  * 同一 run 至多一个计时器;run 不在 running、被删除或 dispose 时 cancel,不泄漏。
859
866
  */
860
867
  scheduleHeartbeat(runId) {
868
+ if (this.disposed)
869
+ return;
861
870
  if (this.heartbeatTimers.has(runId))
862
871
  return;
863
872
  if (!this.notifyLiveListener && !this.notifyListener)
@@ -921,6 +930,8 @@ export class AiTeamRunner {
921
930
  // ── 事件驱动 ──
922
931
  /** 与 missions.ingest 并列调用。绝大多数事件与团队无关,必须廉价返回。 */
923
932
  ingest(event) {
933
+ if (this.disposed)
934
+ return;
924
935
  if (!event.sessionId || event.sessionId === "__system__")
925
936
  return;
926
937
  if (event.type !== "status" && event.type !== "ended" && event.type !== "task" && event.type !== "output")
@@ -972,6 +983,8 @@ export class AiTeamRunner {
972
983
  * 没变就什么都不发。巡检间隔与 evaluate 行为都不动。
973
984
  */
974
985
  startSweep() {
986
+ if (this.disposed)
987
+ return;
975
988
  if (this.sweepTimer)
976
989
  return;
977
990
  this.sweepTimer = setInterval(() => {
@@ -984,7 +997,8 @@ export class AiTeamRunner {
984
997
  }, SWEEP_INTERVAL_MS);
985
998
  this.sweepTimer.unref?.();
986
999
  }
987
- dispose() {
1000
+ async dispose() {
1001
+ this.disposed = true;
988
1002
  if (this.sweepTimer)
989
1003
  clearInterval(this.sweepTimer);
990
1004
  this.sweepTimer = null;
@@ -1006,6 +1020,8 @@ export class AiTeamRunner {
1006
1020
  this.lastLiveKey.clear();
1007
1021
  this.noDegrade.clear();
1008
1022
  this.teamRequestIds.clear();
1023
+ // Settle accepted host handshakes before the server closes storage.
1024
+ await this.idle();
1009
1025
  }
1010
1026
  /** 等当前排队的所有操作跑完(测试用)。 */
1011
1027
  async idle() {
@@ -1016,7 +1032,11 @@ export class AiTeamRunner {
1016
1032
  // ── 内部:串行化 ──
1017
1033
  enqueue(runId, task) {
1018
1034
  const previous = this.chains.get(runId) ?? Promise.resolve();
1019
- const next = previous.catch(() => undefined).then(task);
1035
+ const next = previous.catch(() => undefined).then(() => {
1036
+ if (this.disposed)
1037
+ throw new AiTeamConflictError("AiTeamRunner has been disposed.");
1038
+ return task();
1039
+ });
1020
1040
  const tracked = next.catch((error) => {
1021
1041
  if (!(error instanceof AiTeamConflictError)) {
1022
1042
  console.error(`[AiTeam] run ${runId}:`, getErrorMessage(error));
@@ -1044,6 +1064,8 @@ export class AiTeamRunner {
1044
1064
  }
1045
1065
  // ── 内部:推进 ──
1046
1066
  async evaluate(runId) {
1067
+ if (this.disposed)
1068
+ return;
1047
1069
  const run = this.storage.getAiTeamRun(runId);
1048
1070
  if (!run || run.status !== "running")
1049
1071
  return;
@@ -1066,6 +1088,8 @@ export class AiTeamRunner {
1066
1088
  await this.advance(run);
1067
1089
  }
1068
1090
  scheduleRecheck(runId, delayMs) {
1091
+ if (this.disposed)
1092
+ return;
1069
1093
  if (this.recheckTimers.has(runId))
1070
1094
  return;
1071
1095
  const timer = setTimeout(() => {
@@ -1250,6 +1274,8 @@ export class AiTeamRunner {
1250
1274
  * 有成员失败、队列清空或依赖再也满足不了时,等在跑的都结束后交回 Leader。
1251
1275
  */
1252
1276
  async advance(run) {
1277
+ if (this.disposed)
1278
+ return;
1253
1279
  if (run.status !== "running")
1254
1280
  return;
1255
1281
  const steps = this.storage.listAiTeamSteps(run.id);
@@ -1294,6 +1320,8 @@ export class AiTeamRunner {
1294
1320
  }
1295
1321
  /** 开一轮 Leader:把上一轮 Leader 之后结束的成员报告交给他。 */
1296
1322
  async startLeaderRound(run, userNote) {
1323
+ if (this.disposed)
1324
+ return;
1297
1325
  if (!this.hasBudget(run))
1298
1326
  return;
1299
1327
  // 成员干活时用户在群里说的话,这一轮一起交给负责人。
@@ -1482,6 +1510,8 @@ export class AiTeamRunner {
1482
1510
  * 提示词分两段:`system`(角色与规则)只在新建会话时交给系统提示通道,`message` 是本轮用户消息。
1483
1511
  */
1484
1512
  async dispatchStep(run, step, buildPrompt, proceed = true) {
1513
+ if (this.disposed)
1514
+ return;
1485
1515
  const member = this.member(run.team, step.memberId);
1486
1516
  const candidates = member ? memberAgents(member) : [];
1487
1517
  const info = this.infoOf(step);
@@ -1550,6 +1580,8 @@ export class AiTeamRunner {
1550
1580
  }
1551
1581
  }
1552
1582
  catch (error) {
1583
+ if (this.disposed)
1584
+ return;
1553
1585
  const message = getErrorMessage(error);
1554
1586
  const rejected = error instanceof AgentDispatchPreflightError && error.failure.retryable;
1555
1587
  const kind = rejected ? "input-rejected" : classifyCandidateFailure(message);
@@ -1939,6 +1971,8 @@ export class AiTeamRunner {
1939
1971
  }
1940
1972
  }
1941
1973
  postTurn(run, turn) {
1974
+ if (this.disposed)
1975
+ return;
1942
1976
  if (!this.chat || !run.chatSessionId)
1943
1977
  return;
1944
1978
  try {
@@ -2046,6 +2080,8 @@ export class AiTeamRunner {
2046
2080
  this.storage.saveAiTeamStep(step);
2047
2081
  }
2048
2082
  notify(run) {
2083
+ if (this.disposed)
2084
+ return;
2049
2085
  // 记下 run 通道的活动基线并排上静默心跳:长任务只等一次状态写入是不够的,
2050
2086
  // 用户在十几分钟没有新消息时需要「仍在运行」的证据,见 beat()。
2051
2087
  this.lastRunNotifyAt.set(run.id, this.now());
@@ -1,5 +1,6 @@
1
1
  import { DECISION_EXPERT_KEY } from "./decision-expert-identity.js";
2
2
  import { SPEECH_POLISHER_KEY } from "./speech-polisher-identity.js";
3
+ import { HR_EMPLOYEE_KEY } from "./hr-employee-identity.js";
3
4
  export const AI_TEAM_MIN_MEMBERS = 2;
4
5
  export const AI_TEAM_MAX_MEMBERS = 8;
5
6
  export const AI_TEAM_DEFAULT_MAX_STEPS = 30;
@@ -53,13 +54,13 @@ export function isDecisionExpertSiliconEmployee(employee) {
53
54
  return employee?.systemKey === DECISION_EXPERT_KEY;
54
55
  }
55
56
  export function isBuiltinSiliconEmployee(employee) {
56
- return isSystemSiliconEmployee(employee) || isDefaultSiliconEmployee(employee) || isDecisionExpertSiliconEmployee(employee) || employee?.systemKey === SPEECH_POLISHER_KEY;
57
+ return isSystemSiliconEmployee(employee) || isDefaultSiliconEmployee(employee) || isDecisionExpertSiliconEmployee(employee) || employee?.systemKey === SPEECH_POLISHER_KEY || employee?.systemKey === HR_EMPLOYEE_KEY;
57
58
  }
58
59
  export const SILICON_EMPLOYEE_MAX_TAGS = 8;
59
60
  export const SILICON_EMPLOYEE_TAG_MAX_CHARS = 20;
60
61
  /** 内置标识只由真实员工身份投影,不能用自定义标签冒充。 */
61
62
  export function siliconEmployeeTags(employee) {
62
- if (isSystemSiliconEmployee(employee) || isDecisionExpertSiliconEmployee(employee) || employee.systemKey === SPEECH_POLISHER_KEY)
63
+ if (isSystemSiliconEmployee(employee) || isDecisionExpertSiliconEmployee(employee) || employee.systemKey === SPEECH_POLISHER_KEY || employee.systemKey === HR_EMPLOYEE_KEY)
63
64
  return [SYSTEM_EMPLOYEE_TAG];
64
65
  if (isDefaultSiliconEmployee(employee))
65
66
  return [DEFAULT_EMPLOYEE_TAG];
@@ -0,0 +1,61 @@
1
+ import { type EmployeeTextDeps } from "./employee-text.js";
2
+ import type { AiTextRequest, SessionProvider, SessionSnapshot } from "./types.js";
3
+ export { QuickCommitError } from "./command-error.js";
4
+ /** Neutral one-shot text execution. Tool-running Git fallback never uses the retry chain. */
5
+ export declare function defaultProvider(provider: SessionProvider | undefined): SessionProvider;
6
+ export interface QuickCommitAiOptions {
7
+ modelGroups?: import("./model-groups.js").ModelGroup[];
8
+ provider?: SessionProvider;
9
+ model?: string | null;
10
+ thinkingEffort?: SessionSnapshot["thinkingEffort"];
11
+ inheritEnv?: boolean;
12
+ /** 内置「系统运维」员工的角色设定:作为系统提示前缀注入。 */
13
+ opsPersona?: string;
14
+ /** 员工候选链(按顺序);未设置时只用 provider/model 这一次调用。 */
15
+ cliCandidates?: import("./types.js").AiCliCandidate[];
16
+ /** SDK 使用当前实例配置与现有免费分组服务,不创建其他执行渠道。 */
17
+ employeeText?: EmployeeTextDeps;
18
+ /** 系统应用必须经员工渠道;没有可用候选时直接失败,不退回默认 provider。 */
19
+ employeeChannelOnly?: boolean;
20
+ /** 整条候选链的时间上限;默认 CLI_CHAIN_BUDGET_MS。第一条消息里的调用要短得多。 */
21
+ budgetMs?: number;
22
+ signal?: AbortSignal;
23
+ }
24
+ type CliAiTextOptions = QuickCommitAiOptions & {
25
+ deadline?: number;
26
+ };
27
+ export declare function normalizeAiText(raw: string): string;
28
+ export declare function buildPiTextArgs(request: AiTextRequest, opts: QuickCommitAiOptions, allowTools?: boolean): string[];
29
+ export declare function buildGrokTextArgs(request: AiTextRequest, opts: QuickCommitAiOptions, allowTools?: boolean): string[];
30
+ /**
31
+ * Gemini CLI 没有 `--append-system-prompt`,规则走 `contentWithSystemPrompt` 并进内容;
32
+ * headless 下必须带 `--skip-trust`,否则未信任的工作目录会直接以 55 退出。
33
+ *
34
+ * `-p ""` 只把 CLI 钉在 headless 模式,真正的 prompt 走 stdin:commit diff 可能很大,
35
+ * 塞进 argv 会撞 ARG_MAX。Gemini 没有 Codex `--ephemeral` 那样的临时会话开关,
36
+ * 一次性调用会留在它自己的聊天记录里(Wand 不扫描 Gemini 历史,不会误当可恢复会话)。
37
+ */
38
+ export declare function buildGeminiTextArgs(opts: QuickCommitAiOptions, allowTools?: boolean): string[];
39
+ export declare function buildQoderTextArgs(request: AiTextRequest, opts: QuickCommitAiOptions, allowTools?: boolean): string[];
40
+ /** provider 自己的系统提示开关 + 规则文本;没有开关的 provider 返回空。 */
41
+ export declare function systemPromptArgsFrom(provider: SessionProvider, system: string): string[];
42
+ /** 没有系统提示开关的 provider(codex / opencode):规则只能并进内容前面。 */
43
+ export declare function contentWithSystemPrompt(provider: SessionProvider, request: AiTextRequest): string;
44
+ export declare function runCliText(command: string, args: string[], prompt: string, opts: {
45
+ cwd: string;
46
+ timeoutMs: number;
47
+ inheritEnv?: boolean;
48
+ signal?: AbortSignal;
49
+ env?: (base: NodeJS.ProcessEnv) => NodeJS.ProcessEnv;
50
+ }): Promise<string>;
51
+ export declare function assertGeminiTextCapability(): void;
52
+ export declare function callCliAiText(request: AiTextRequest, cwd: string, language: string, opts: CliAiTextOptions): Promise<string>;
53
+ /** 角色设定走系统提示前缀;任务自己的输出格式与约束必须排在后面。 */
54
+ export declare function withOpsPersona(request: AiTextRequest, persona?: string): AiTextRequest;
55
+ /**
56
+ * Run a lightweight AI request through the system employee's configured chain.
57
+ * provider 与引擎由候选决定;SDK 与 CLI 均保留各自适配和身份。
58
+ * parseOutput 在候选链内解析/校验结果;失败后继续下一条,而非提前宣布成功。
59
+ */
60
+ export declare function callConfiguredAiText(request: AiTextRequest, cwd: string, language: string, opts: QuickCommitAiOptions): Promise<string>;
61
+ export declare function callConfiguredAiText<T>(request: AiTextRequest, cwd: string, language: string, opts: QuickCommitAiOptions, parseOutput: (raw: string) => T): Promise<T>;