@co0ontty/wand 4.83.1-beta.g97d7ae9 → 4.84.0

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 (188) hide show
  1. package/README.md +4 -0
  2. package/dist/agent-dispatch.js +5 -1
  3. package/dist/ai-team-availability.d.ts +1 -1
  4. package/dist/ai-team-prompts.js +13 -4
  5. package/dist/ai-team-runner.d.ts +80 -5
  6. package/dist/ai-team-runner.js +332 -55
  7. package/dist/ai-team-types.d.ts +92 -5
  8. package/dist/ai-team-types.js +9 -2
  9. package/dist/build-info.json +4 -4
  10. package/dist/cli-api.d.ts +1 -0
  11. package/dist/cli-api.js +3 -0
  12. package/dist/cli.js +18 -1
  13. package/dist/commit-task-archive.d.ts +3 -1
  14. package/dist/commit-task-archive.js +21 -10
  15. package/dist/config.d.ts +1 -1
  16. package/dist/config.js +73 -0
  17. package/dist/conversation-mentions.d.ts +16 -0
  18. package/dist/conversation-mentions.js +32 -0
  19. package/dist/conversation-service.d.ts +90 -0
  20. package/dist/conversation-service.js +759 -0
  21. package/dist/conversation-session-preview.d.ts +9 -0
  22. package/dist/conversation-session-preview.js +47 -0
  23. package/dist/conversation-task-preview.d.ts +5 -0
  24. package/dist/conversation-task-preview.js +8 -0
  25. package/dist/conversation-types.d.ts +80 -0
  26. package/dist/conversation-types.js +7 -0
  27. package/dist/core-extension-host.d.ts +27 -0
  28. package/dist/core-extension-host.js +138 -0
  29. package/dist/core-runner.d.ts +86 -0
  30. package/dist/core-runner.js +757 -0
  31. package/dist/core-status-cli.d.ts +9 -0
  32. package/dist/core-status-cli.js +280 -0
  33. package/dist/core-turn-tracker.d.ts +12 -0
  34. package/dist/core-turn-tracker.js +36 -0
  35. package/dist/decision-runner.d.ts +6 -0
  36. package/dist/decision-runner.js +3 -1
  37. package/dist/decision-tool.d.ts +2 -0
  38. package/dist/decision-tool.js +49 -22
  39. package/dist/env-utils.d.ts +7 -3
  40. package/dist/env-utils.js +30 -5
  41. package/dist/git-quick-commit.d.ts +5 -0
  42. package/dist/git-quick-commit.js +9 -3
  43. package/dist/git-utils.js +2 -1
  44. package/dist/harness-engine.d.ts +110 -0
  45. package/dist/harness-engine.js +331 -0
  46. package/dist/mission-diff.js +2 -1
  47. package/dist/model-auto-assign.d.ts +50 -0
  48. package/dist/model-auto-assign.js +163 -0
  49. package/dist/model-group-runner.d.ts +4 -0
  50. package/dist/model-group-runner.js +72 -0
  51. package/dist/model-groups.d.ts +38 -0
  52. package/dist/model-groups.js +138 -0
  53. package/dist/models.d.ts +12 -0
  54. package/dist/models.js +102 -8
  55. package/dist/npm-update-utils.js +2 -1
  56. package/dist/openrouter-free-cli.d.ts +25 -0
  57. package/dist/openrouter-free-cli.js +109 -0
  58. package/dist/openrouter-free-models.d.ts +85 -0
  59. package/dist/openrouter-free-models.js +458 -0
  60. package/dist/openrouter-free-selection.d.ts +5 -0
  61. package/dist/openrouter-free-selection.js +7 -0
  62. package/dist/path-repair.d.ts +10 -0
  63. package/dist/path-repair.js +50 -5
  64. package/dist/pi-auto-resources.d.ts +12 -0
  65. package/dist/pi-auto-resources.js +151 -0
  66. package/dist/pi-execution-types.d.ts +48 -0
  67. package/dist/pi-execution-types.js +1 -0
  68. package/dist/pi-execution.d.ts +9 -0
  69. package/dist/pi-execution.js +187 -0
  70. package/dist/pi-extension-resources.d.ts +13 -0
  71. package/dist/pi-extension-resources.js +71 -0
  72. package/dist/pi-openrouter-free-bridge.d.ts +2 -0
  73. package/dist/pi-openrouter-free-bridge.js +80 -0
  74. package/dist/pi-resource-bridge.d.ts +2 -0
  75. package/dist/pi-resource-bridge.js +73 -0
  76. package/dist/pi-resource-catalog.d.ts +18 -0
  77. package/dist/pi-resource-catalog.js +82 -0
  78. package/dist/pi-resource-recommendation.d.ts +29 -0
  79. package/dist/pi-resource-recommendation.js +169 -0
  80. package/dist/pi-resource-run.d.ts +8 -0
  81. package/dist/pi-resource-run.js +28 -0
  82. package/dist/pi-session-settings.d.ts +157 -0
  83. package/dist/pi-session-settings.js +166 -0
  84. package/dist/platform-action-catalog.d.ts +24 -0
  85. package/dist/platform-action-catalog.js +141 -0
  86. package/dist/platform-action-service.d.ts +37 -0
  87. package/dist/platform-action-service.js +138 -0
  88. package/dist/platform-action-types.d.ts +125 -0
  89. package/dist/platform-action-types.js +7 -0
  90. package/dist/process-manager.d.ts +21 -1
  91. package/dist/process-manager.js +168 -15
  92. package/dist/provider-catalog.js +1 -1
  93. package/dist/provider-cli-updater.js +29 -8
  94. package/dist/provider-history-scanner.d.ts +9 -0
  95. package/dist/provider-history-scanner.js +107 -1
  96. package/dist/retention.d.ts +19 -7
  97. package/dist/retention.js +171 -28
  98. package/dist/server-ai-team-routes.js +6 -2
  99. package/dist/server-conversation-routes.d.ts +5 -0
  100. package/dist/server-conversation-routes.js +91 -0
  101. package/dist/server-employee-routes.d.ts +2 -0
  102. package/dist/server-employee-routes.js +85 -11
  103. package/dist/server-pi-recommendation-routes.d.ts +13 -0
  104. package/dist/server-pi-recommendation-routes.js +67 -0
  105. package/dist/server-resume-routes.js +1 -1
  106. package/dist/server-session-routes.d.ts +4 -3
  107. package/dist/server-session-routes.js +182 -37
  108. package/dist/server-settings-routes.d.ts +5 -0
  109. package/dist/server-settings-routes.js +46 -0
  110. package/dist/server-task-routes.js +49 -4
  111. package/dist/server-team-dispatch-routes.d.ts +19 -0
  112. package/dist/server-team-dispatch-routes.js +71 -0
  113. package/dist/server-update-routes.d.ts +1 -1
  114. package/dist/server-update-routes.js +10 -5
  115. package/dist/server-workspace-routes.js +44 -24
  116. package/dist/server.d.ts +1 -0
  117. package/dist/server.js +148 -30
  118. package/dist/session-ai-context.d.ts +5 -1
  119. package/dist/session-ai-context.js +9 -4
  120. package/dist/session-registry.d.ts +4 -0
  121. package/dist/session-registry.js +47 -13
  122. package/dist/session-transport.js +8 -1
  123. package/dist/settings-web-access.d.ts +15 -0
  124. package/dist/settings-web-access.js +37 -0
  125. package/dist/silicon-employee-defaults.d.ts +29 -0
  126. package/dist/silicon-employee-defaults.js +41 -0
  127. package/dist/silicon-employee-dispatch.d.ts +5 -1
  128. package/dist/silicon-employee-dispatch.js +10 -4
  129. package/dist/silicon-employee-draft.d.ts +21 -4
  130. package/dist/silicon-employee-draft.js +103 -16
  131. package/dist/storage.d.ts +73 -2
  132. package/dist/storage.js +362 -26
  133. package/dist/structured-claude-protocol.js +1 -1
  134. package/dist/structured-client-protocol.js +11 -33
  135. package/dist/structured-content.d.ts +23 -0
  136. package/dist/structured-content.js +72 -0
  137. package/dist/structured-failure.d.ts +16 -0
  138. package/dist/structured-failure.js +36 -0
  139. package/dist/structured-pi-adapter.d.ts +8 -3
  140. package/dist/structured-pi-adapter.js +131 -30
  141. package/dist/structured-provider-common.d.ts +6 -0
  142. package/dist/structured-provider-common.js +23 -1
  143. package/dist/structured-runner.d.ts +45 -0
  144. package/dist/structured-session-manager.d.ts +78 -4
  145. package/dist/structured-session-manager.js +513 -129
  146. package/dist/structured-thinking.d.ts +15 -0
  147. package/dist/structured-thinking.js +46 -0
  148. package/dist/subagent-dispatch.d.ts +56 -0
  149. package/dist/subagent-dispatch.js +102 -0
  150. package/dist/system-employee.d.ts +4 -3
  151. package/dist/system-employee.js +7 -4
  152. package/dist/task-retention.d.ts +23 -0
  153. package/dist/task-retention.js +69 -0
  154. package/dist/task-types.d.ts +4 -0
  155. package/dist/task-types.js +3 -0
  156. package/dist/team-dispatch.d.ts +101 -0
  157. package/dist/team-dispatch.js +269 -0
  158. package/dist/tool-preview.js +7 -1
  159. package/dist/tui/commands.js +50 -1
  160. package/dist/tui/ipc-protocol.d.ts +1 -1
  161. package/dist/tui/ipc-server.d.ts +4 -0
  162. package/dist/tui/ipc-server.js +23 -0
  163. package/dist/turn-heartbeat.d.ts +35 -0
  164. package/dist/turn-heartbeat.js +64 -0
  165. package/dist/types.d.ts +147 -1
  166. package/dist/user-profile.d.ts +33 -0
  167. package/dist/user-profile.js +70 -0
  168. package/dist/web-ui/chat-message-meta.d.ts +11 -0
  169. package/dist/web-ui/chat-message-meta.js +47 -0
  170. package/dist/web-ui/content/ai-teams.js +13 -13
  171. package/dist/web-ui/content/scripts.js +795 -95
  172. package/dist/web-ui/content/styles.css +1 -1
  173. package/dist/web-ui/content/tailwind.css +1 -6808
  174. package/dist/web-ui/content/vendor/qrcode/qrcode.bundle.js +1 -1
  175. package/dist/web-ui/embedded-assets.d.ts +1 -1
  176. package/dist/web-ui/embedded-assets.js +5 -5
  177. package/dist/web-ui/index.d.ts +1 -1
  178. package/dist/web-ui/index.js +3 -3
  179. package/dist/web-ui/markdown.d.ts +2 -0
  180. package/dist/web-ui/markdown.js +111 -0
  181. package/dist/web-ui/page.d.ts +4 -0
  182. package/dist/web-ui/page.js +8 -0
  183. package/dist/web-ui/react/local-preview/controller.d.ts +30 -0
  184. package/dist/web-ui/react/local-preview/controller.js +159 -0
  185. package/dist/web-ui/running-activity.d.ts +63 -0
  186. package/dist/web-ui/running-activity.js +134 -0
  187. package/dist/web-ui/styles.js +2 -11
  188. package/package.json +7 -2
package/README.md CHANGED
@@ -135,6 +135,8 @@ npm run check # TypeScript type check
135
135
  npm run build # Compile and copy static assets to dist/
136
136
  ```
137
137
 
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
+
138
140
  Use an isolated config for testing:
139
141
 
140
142
  ```bash
@@ -316,6 +318,8 @@ npm run check # TypeScript 类型检查
316
318
  npm run build # 编译 + 复制静态资源到 dist/
317
319
  ```
318
320
 
321
+ 本机开发环境统一调用用户主目录入口:`~/start.sh` 构建/安装当前代码并重启,`~/start.sh --restart` 仅重启、不重新构建,`~/start.sh --status` 查状态。入口自动进入项目并在本地处理 sudo,外层不要再加 sudo;它是本机配置,不随新克隆提供,凭据不入仓库。重启安全约束仍以 [AGENTS.md](AGENTS.md) 为准。
322
+
319
323
  隔离测试环境(不影响生产实例):
320
324
 
321
325
  ```bash
@@ -1,4 +1,5 @@
1
1
  import { getDefaultModelForProvider } from "./config.js";
2
+ import { defaultModelGroupSelector } from "./model-groups.js";
2
3
  import { defaultRoleForCli } from "./default-employee.js";
3
4
  import { providerCliCommand } from "./session-provider.js";
4
5
  import { agentKey } from "./ai-team-types.js";
@@ -21,6 +22,9 @@ export function resolveTaskDispatchTarget(deps, task) {
21
22
  export async function dispatchAgentForTask(deps, input) {
22
23
  const { storage, config, structured, processes } = deps;
23
24
  const { agent } = input;
25
+ if (agent.engine === "sdk" && !input.employee) {
26
+ throw new Error("SDK 执行引擎只能通过员工候选启用。");
27
+ }
24
28
  if (input.employee) {
25
29
  if (agent.kind !== "structured")
26
30
  throw new Error("绑定员工只支持结构化会话。");
@@ -40,7 +44,7 @@ export async function dispatchAgentForTask(deps, input) {
40
44
  const cwd = group.cwd;
41
45
  const provider = agent.provider;
42
46
  const model = agent.model === "default" ? "" : agent.model;
43
- const resolvedModel = model || getDefaultModelForProvider(config, provider) || undefined;
47
+ const resolvedModel = model || defaultModelGroupSelector(config.modelGroups, provider, getDefaultModelForProvider(config, provider)) || getDefaultModelForProvider(config, provider) || undefined;
44
48
  const session = agent.kind === "pty"
45
49
  ? await processes.start(providerCliCommand(provider), cwd, agent.mode, input.prompt, {
46
50
  provider,
@@ -35,7 +35,7 @@ export interface StartupFailureProbe {
35
35
  */
36
36
  export declare function classifyStartupFailure(probe: StartupFailureProbe): CandidateFailureKind;
37
37
  export interface WorkFailureInput {
38
- /** 只有 work 步骤参与降级;leader 步骤走既有格式重试/waiting_user 路径。 */
38
+ /** 成员执行步骤的启动失败降级;负责人完整候选重试由 runner 管理。 */
39
39
  stepKind: "leader" | "work";
40
40
  /** PTY 候选一律不异步分类、不降级(§3.4 修正 B4)。 */
41
41
  agentKind: WandTaskAgentKind;
@@ -43,7 +43,8 @@ export function leaderOf(team) {
43
43
  return team.members.find((member) => member.isLeader) ?? team.members[0];
44
44
  }
45
45
  export function workersOf(team) {
46
- return team.members.filter((member) => !member.isLeader);
46
+ // A single employee or explicitly @-selected coordinator retains their own professional duty.
47
+ return team.members.length === 1 || team.allowLeaderWork ? team.members : team.members.filter((member) => !member.isLeader);
47
48
  }
48
49
  /** 每步的约定报告文件(相对 cwd)。所有 CLI 都能写文件,因此是通用的交接方式。 */
49
50
  export function aiTeamReportPath(runId, seq, kind, memberId) {
@@ -240,7 +241,8 @@ function leaderSystemPrompt(run, resolveModel) {
240
241
  return [
241
242
  ...(employeePrompt ? [employeePrompt] : []),
242
243
  `你是 AI 团队「${run.team.name}」的负责人(${leader.name})。`,
243
- `你的职责:${leader.duty.trim() || "拆分任务、派工、根据报告决定下一步。"}`,
244
+ `你的专业职责:${leader.duty.trim() || "拆分任务、派工、根据报告决定下一步。"}`,
245
+ ...(run.team.allowLeaderWork ? ["用户通过 @ 指定你为本轮负责人:协调职责是拆分任务、按群成员的专业职责派工、收集报告并汇总;不代表所有工作都由你执行。"] : []),
244
246
  "",
245
247
  "## 成员(只能把工作派给下列成员;id 必须原样使用)",
246
248
  "成员的名单行只列首选执行配置;执行配置由系统按候选顺序自动降级,你只按成员能力分派,不操心模型可用性。",
@@ -248,11 +250,18 @@ function leaderSystemPrompt(run, resolveModel) {
248
250
  ...teamInstructions(run.team),
249
251
  "",
250
252
  "## 工作方式",
251
- "- 你不直接改代码:你负责拆分任务、派工,并根据成员报告决定下一步。",
253
+ run.team.members.length === 1
254
+ ? "- 本群只有你一位员工:规划阶段只制定计划,work 步骤使用你的同一 member id。执行阶段会在独立的阶段会话里工作并交付。"
255
+ : run.team.allowLeaderWork
256
+ ? "- 规划阶段只负责拆分、派工和汇总。属于你专业职责的工作可派给自己的 member id,系统会用独立 work 会话执行;其余工作交给职责匹配的成员,不能包办,也不为了全员发言重复派工。"
257
+ : "- 你不直接改代码:你负责拆分任务、派工,并根据成员报告决定下一步。",
252
258
  `- 每次只安排接下来要做的几步(1–${AI_TEAM_MAX_ASSIGN_STEPS} 步)。互不依赖的工作派给不同成员可以并行;所有在跑的步骤结束后,我会把报告交回给你。`,
253
259
  "- 并行成员共用同一个工作目录,不要让两个人同时改同一批文件。",
254
- "- 实现与验收交给不同成员,不要让同一个成员验收自己的工作。",
260
+ run.team.members.length === 1
261
+ ? "- 可以自测,但不能声称独立交叉验收。任务需要另一人验收时,等待用户明确邀请/确认,不虚构成员。"
262
+ : "- 实现与验收交给不同成员,不要让同一个成员验收自己的工作。",
255
263
  "- 派工优先按角色:制定计划给 plan 成员,实现给 work 成员,验收给 verify 成员;没标角色的成员视为 any。",
264
+ "- 同时按成员的专业职责选人并遵守边界(例如设计成员只出设计,不改产品代码),不能因为某人是负责人就把所有工作交给他。",
256
265
  "- 同一成员同一时间只有一个步骤;互不相干的步骤并行派出,有先后关系的用 after 声明。",
257
266
  "- 需要用户拍板时就提问,不要猜。",
258
267
  `- ${OBJECTIVE_INTENT_NOTE}`,
@@ -1,11 +1,12 @@
1
1
  import type { SiliconEmployee } from "./ai-team-types.js";
2
2
  import { type AgentDispatchDeps } from "./agent-dispatch.js";
3
3
  import { type ModelCatalogView } from "./ai-team-availability.js";
4
- import { type AiTeam, type AiTeamLiveStep, type AiTeamLiveUpdate, type AiTeamRun, type AiTeamRunDetail, type AiTeamRunSummary, type AiTeamStep } from "./ai-team-types.js";
4
+ import { type AiTeam, type AiTeamLiveSnapshot, type AiTeamLiveStep, type AiTeamLiveUpdate, type AiTeamRun, type AiTeamRunDetail, type AiTeamRunSummary, type AiTeamStep } from "./ai-team-types.js";
5
5
  import type { SessionRegistry } from "./session-registry.js";
6
+ import type { StructuredFailure } from "./structured-failure.js";
6
7
  import type { WandStorage } from "./storage.js";
7
8
  import type { WandTask, WandTaskAgent } from "./task-types.js";
8
- import type { ConversationTurn, ProcessEvent, SessionSnapshot } from "./types.js";
9
+ import type { ConversationAuthor, ConversationTurn, ProcessEvent, SessionSnapshot } from "./types.js";
9
10
  /** 群聊会话的 automationId 前缀;后面接运行 id。 */
10
11
  export declare const AI_TEAM_CHAT_PREFIX = "ai-team-chat:";
11
12
  /** 用户可见的冲突错误(路由转 409)。 */
@@ -30,6 +31,7 @@ export interface AiTeamSessionOps {
30
31
  ownerOf(sessionId: string): "structured" | "pty" | "storage" | null;
31
32
  /** Server-private generation and one-shot, explicitly unaccepted startup fact. */
32
33
  consumeUnacceptedStartup?(sessionId: string, requestId: string): boolean;
34
+ consumeUnacceptedFailure?(sessionId: string, requestId: string): StructuredFailure | null;
33
35
  }
34
36
  /** 群聊:一次运行一个转发会话,团队的决定、派工和报告都以成员身份发在里面。 */
35
37
  export interface AiTeamChatOps {
@@ -43,6 +45,8 @@ export interface AiTeamChatOps {
43
45
  export interface AiTeamRunnerOptions {
44
46
  storage: WandStorage;
45
47
  chat?: AiTeamChatOps;
48
+ /** Instance projection includes ordinary group replies without copying private DMs. */
49
+ chatHistoryTurns?: (conversationId: string) => ConversationTurn[];
46
50
  /** 解析任务卡的执行目录;默认走 agent-dispatch 的规则。 */
47
51
  resolveCwd: (task: WandTask) => string;
48
52
  ops: AiTeamSessionOps;
@@ -50,6 +54,11 @@ export interface AiTeamRunnerOptions {
50
54
  /** 运行中步骤的 live 文本推送(§4.9):去抖后每 500ms 至多一次,stepId+text+omittedChars+state 全同不重复推。 */
51
55
  notifyLive?: (update: AiTeamLiveUpdate) => void;
52
56
  now?: () => number;
57
+ /**
58
+ * 静默心跳阈值(毫秒),默认 AI_TEAM_SILENCE_HEARTBEAT_MS。测试注入小值来验证静默期确实重推,
59
+ * 生产不设这一项;调用方不要拿它做无界轮询——每个 run 至多一个计时器,离开 running 即 cancel。
60
+ */
61
+ heartbeatMs?: number;
53
62
  /**
54
63
  * 某 provider 已发现的模型清单(§3.4 model-unknown 事前比对)。目录未就绪 / 清单为空时
55
64
  * 返回空值即可,判定方向是「拿不准就放行」。
@@ -60,6 +69,11 @@ export interface AiTeamRunnerOptions {
60
69
  * `default` 哨兵不是模型名,写真正会用的那个。
61
70
  */
62
71
  defaultModelOf?: (provider: WandTaskAgent["provider"]) => string;
72
+ /**
73
+ * 当前用户资料的署名投影。只在没有对话归属、只能回放 relay 快照的旧群聊里用;
74
+ * 有对话归属时由 ConversationService 统一投影,避免两处口径。
75
+ */
76
+ selfAuthor?: () => ConversationAuthor;
63
77
  }
64
78
  export declare function createAiTeamSessionOps(deps: AgentDispatchDeps & {
65
79
  sessions: SessionRegistry;
@@ -68,9 +82,11 @@ export declare function createAiTeamChatOps(deps: AgentDispatchDeps): AiTeamChat
68
82
  export declare function createAiTeamRunner(deps: AgentDispatchDeps & {
69
83
  sessions: SessionRegistry;
70
84
  notify?: (run: AiTeamRun) => void;
85
+ chatHistoryTurns?: (conversationId: string) => ConversationTurn[];
71
86
  notifyLive?: (update: AiTeamLiveUpdate) => void;
72
87
  models?: (provider: WandTaskAgent["provider"]) => ModelCatalogView;
73
88
  defaultModelOf?: (provider: WandTaskAgent["provider"]) => string;
89
+ selfAuthor?: () => ConversationAuthor;
74
90
  }): AiTeamRunner;
75
91
  /**
76
92
  * 群聊里的发言人。上传的头像是 data URL,每条消息都带一份太重,改用按 id 取的像素猫。
@@ -127,11 +143,13 @@ export declare class AiTeamRunner {
127
143
  private readonly storage;
128
144
  private readonly ops;
129
145
  private readonly chat?;
146
+ private readonly chatHistoryTurns?;
130
147
  private readonly resolveCwd;
131
148
  private readonly notifyListener?;
132
149
  private readonly notifyLiveListener?;
133
150
  private readonly modelsOf?;
134
151
  private readonly defaultModelOf?;
152
+ private readonly selfAuthorOf?;
135
153
  private readonly now;
136
154
  private readonly chains;
137
155
  private readonly outputTimers;
@@ -139,6 +157,22 @@ export declare class AiTeamRunner {
139
157
  private readonly liveTimers;
140
158
  /** 上次推出去的 live 列表指纹(§4.9):stepId + text + omittedChars + state 全同就不重复推。 */
141
159
  private readonly lastLiveKey;
160
+ /** 上次真正推出 live 列表的时刻(毫秒),静默心跳的起算点。 */
161
+ private readonly lastLivePushAt;
162
+ /** 上次 `ai-team-run` 通知发出的时刻(毫秒);心跳据此判断 run 通道是否也该重推。 */
163
+ private readonly lastRunNotifyAt;
164
+ /**
165
+ * 静默心跳计时器,按 runId 计:**每个 run 至多一个**,run 离开 running(终态 / 等批准 / 等回复)
166
+ * 或 dispose 时立即 cancel,不留悬挂计时器。
167
+ */
168
+ private readonly heartbeatTimers;
169
+ /**
170
+ * 每个运行中步骤最近一次「可观测活动」的签名与时刻(毫秒)。纯内存观测记录,不入库:
171
+ * 服务重启后退回步骤自己的 `startedAt` 重新起算,第一次观察不算活动。
172
+ * 步骤落地(done / failed / skipped)时在 `saveStep` 里删掉,容量随并发步数有界。
173
+ */
174
+ private readonly stepActivity;
175
+ private readonly heartbeatMs;
142
176
  private readonly recheckTimers;
143
177
  /** 已经确定「不降级、按既有路径记 failed」的步骤,防止 finishStep 再判一次形成回环。 */
144
178
  private readonly noDegrade;
@@ -156,10 +190,15 @@ export declare class AiTeamRunner {
156
190
  /** 先脱敏再头尾截断:截断会把中间的敏感串切出来,顺序不能反。 */
157
191
  private cleanError;
158
192
  start(input: {
159
- teamId: string;
193
+ teamId?: string;
194
+ team?: AiTeam;
160
195
  taskId: string;
161
196
  note?: string;
162
197
  chatSessionId?: string;
198
+ conversationId?: string;
199
+ memberVersion?: number;
200
+ runId?: string;
201
+ onAccepted?: (run: AiTeamRun) => void;
163
202
  }): Promise<AiTeamRunDetail>;
164
203
  approve(runId: string, options?: {
165
204
  echo?: boolean;
@@ -180,6 +219,8 @@ export declare class AiTeamRunner {
180
219
  * 成员干活时先记下,负责人下一轮一起看到;运行已结束则接着开一轮新的。
181
220
  */
182
221
  chatInput(sessionId: string, text: string): Promise<void>;
222
+ /** Explicit task target; ordinary group talk never implicitly approves/stops/starts a run. */
223
+ inputForRun(runId: string, text: string): Promise<AiTeamRunDetail>;
183
224
  detail(runId: string): AiTeamRunDetail;
184
225
  listForTask(taskId: string): AiTeamRun[];
185
226
  /**
@@ -187,12 +228,45 @@ export declare class AiTeamRunner {
187
228
  * 快照拿不到的步骤跳过而不抛。run 不存在时与 detail() 同口径抛错。
188
229
  */
189
230
  live(runId: string): AiTeamLiveStep[];
231
+ /**
232
+ * 轮询端(`GET /api/ai-team-runs/:id/live`)的完整投影:live 步骤 + run 级活动时间。
233
+ * 一次读数算出两者,移动端不必为了「还在跑吗」再拉一次 detail。run 不存在时与 detail() 同口径抛错。
234
+ */
235
+ liveSnapshot(runId: string): AiTeamLiveSnapshot;
236
+ /**
237
+ * run 级活动时间投影(派生、不入库)。`steps` 为该 run 的全部步骤,缺省时只在 run 还在跑
238
+ * 才去查表:终态 / 等批准 / 等用户时 `run.updatedAt` 就是最后一次状态写入,而逐步骤的内存观察
239
+ * 也已随步骤落地清掉,再查几十条历史记录没有意义。
240
+ */
241
+ private activityOf;
190
242
  private liveSteps;
191
243
  private liveStep;
244
+ /**
245
+ * 记一步「最近一次可观测活动」的时刻并返回。签名 = 活动状态 + live 文本长度 + 原始输出与回合
246
+ * 规模 + 是否在本轮里 + 待授权请求 id;任一项变了就算活动发生在此刻。
247
+ * 与 live 推送指纹刻意不同:指纹只管「要不要推」,这里的信号要能把「文本没变但输出仍在涨」
248
+ * (一条长命令、一段被 ANSI 包住的进度)也认成活动。首次观察不记成活动,以 `startedAt` 为基线,
249
+ * 免得服务重启后第一次读快照就谎报「刚刚有活动」。
250
+ */
251
+ private noteStepActivity;
192
252
  /** 挂一次 run 级 live 去抖:同一 run 每 500ms 至多算一遍、推一次,与 evaluate 的计时器互不干扰。 */
193
253
  private scheduleLivePush;
194
- /** 推一次 live 列表(§4.9);指纹(stepId + text + omittedChars + state)没变就不重复推,推送失败只忽略。 */
254
+ /**
255
+ * 推一次 live 列表(§4.9);指纹(stepId + text + omittedChars + state)没变就不重复推,
256
+ * 推送失败只忽略。例外是静默心跳:`heartbeat` 为 true 时按心跳计时器的裁决放行,内容可以逐字相同,
257
+ * 但新的 `activity.observedAt` 与 heartbeat 标记让前端知道「这个 run 还在被跟踪」。
258
+ * 放行不松开去抖:推完照样记指纹并重排心跳,所以静默期最多每 heartbeatMs 一次,不是无界重推。
259
+ */
195
260
  private pushLive;
261
+ /**
262
+ * 排一次静默心跳:距上次 live 推送或 run 通知还差多久到阈值,就多久后再看一次。
263
+ * 同一 run 至多一个计时器;run 不在 running、被删除或 dispose 时 cancel,不泄漏。
264
+ */
265
+ private scheduleHeartbeat;
266
+ /** 心跳到点:仍在跑且仍在静默就把 live 快照和 run 状态各重推一次,然后按新基线续排。 */
267
+ private beat;
268
+ /** run 离开 running(终态、等批准、等用户)、被删除或 dispose:取消心跳并清掉基线。 */
269
+ private cancelHeartbeat;
196
270
  /** 团队页的运行记录;teamId 为空时列出所有团队(侧边栏计数用)。 */
197
271
  listRuns(filter: {
198
272
  teamId?: string;
@@ -273,7 +347,7 @@ export declare class AiTeamRunner {
273
347
  * 只直接派出 A′,**不整轮 advance**(N1:advance 的 queued/byId/busyMembers 是进循环时的快照,
274
348
  * 整轮调整会在同一栈里对同一步二次派发)。`proceed` 原样透传给 A′ 的 dispatchStep。
275
349
  */
276
- private degradeWorkStep;
350
+ private degradeStep;
277
351
  /**
278
352
  * 会话「起来又倒下」的启动期归因(§3.4 触发点 2)。判定核在 ai-team-availability,
279
353
  * 这里只负责喂时钟、快照与报告产出;不满足降级条件返回 null,按既有路径记 failed。
@@ -330,4 +404,5 @@ export declare class AiTeamRunner {
330
404
  private saveStep;
331
405
  private notify;
332
406
  private iso;
407
+ private isoOf;
333
408
  }