@tt-a1i/hive 1.4.4 → 1.5.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 (164) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +8 -0
  3. package/assets/qq-group.jpg +0 -0
  4. package/dist/bin/team.cmd +1 -0
  5. package/dist/src/cli/hive-update.d.ts +45 -17
  6. package/dist/src/cli/hive-update.js +63 -25
  7. package/dist/src/cli/hive.d.ts +25 -0
  8. package/dist/src/cli/hive.js +41 -3
  9. package/dist/src/cli/team.d.ts +1 -0
  10. package/dist/src/cli/team.js +199 -3
  11. package/dist/src/server/agent-command-resolver.js +3 -19
  12. package/dist/src/server/agent-manager-support.d.ts +2 -2
  13. package/dist/src/server/agent-manager-support.js +98 -24
  14. package/dist/src/server/agent-run-starter.d.ts +7 -1
  15. package/dist/src/server/agent-run-starter.js +9 -2
  16. package/dist/src/server/agent-run-store.d.ts +1 -1
  17. package/dist/src/server/agent-runtime-close.d.ts +1 -0
  18. package/dist/src/server/agent-runtime-close.js +25 -1
  19. package/dist/src/server/agent-runtime-contract.d.ts +2 -1
  20. package/dist/src/server/agent-runtime.d.ts +1 -1
  21. package/dist/src/server/agent-runtime.js +8 -2
  22. package/dist/src/server/agent-startup-instructions.d.ts +8 -1
  23. package/dist/src/server/agent-startup-instructions.js +15 -9
  24. package/dist/src/server/agent-stdin-dispatcher.d.ts +12 -5
  25. package/dist/src/server/agent-stdin-dispatcher.js +129 -40
  26. package/dist/src/server/cron-util.d.ts +7 -0
  27. package/dist/src/server/cron-util.js +19 -0
  28. package/dist/src/server/dispatch-ledger-store.d.ts +22 -0
  29. package/dist/src/server/dispatch-ledger-store.js +51 -3
  30. package/dist/src/server/env-sync-message.js +9 -9
  31. package/dist/src/server/fs-pick-folder.js +4 -0
  32. package/dist/src/server/fs-sandbox.js +36 -7
  33. package/dist/src/server/hive-team-guidance.d.ts +11 -6
  34. package/dist/src/server/hive-team-guidance.js +252 -71
  35. package/dist/src/server/live-run-registry.d.ts +1 -0
  36. package/dist/src/server/live-run-registry.js +1 -1
  37. package/dist/src/server/open-target-commands.js +5 -6
  38. package/dist/src/server/orchestrator-autostart.d.ts +12 -0
  39. package/dist/src/server/orchestrator-autostart.js +15 -13
  40. package/dist/src/server/path-canonicalization.d.ts +3 -0
  41. package/dist/src/server/path-canonicalization.js +29 -0
  42. package/dist/src/server/platform-path.d.ts +3 -0
  43. package/dist/src/server/platform-path.js +13 -0
  44. package/dist/src/server/post-start-input-writer.d.ts +1 -1
  45. package/dist/src/server/post-start-input-writer.js +110 -13
  46. package/dist/src/server/preset-launch-support.d.ts +1 -1
  47. package/dist/src/server/preset-launch-support.js +33 -2
  48. package/dist/src/server/recovery-summary.d.ts +6 -1
  49. package/dist/src/server/recovery-summary.js +17 -17
  50. package/dist/src/server/restart-policy-support.d.ts +6 -1
  51. package/dist/src/server/restart-policy-support.js +9 -1
  52. package/dist/src/server/restart-policy.d.ts +2 -2
  53. package/dist/src/server/restart-policy.js +3 -1
  54. package/dist/src/server/role-template-store.d.ts +1 -0
  55. package/dist/src/server/role-template-store.js +11 -1
  56. package/dist/src/server/route-types.d.ts +43 -0
  57. package/dist/src/server/routes-runtime.js +2 -1
  58. package/dist/src/server/routes-settings.js +76 -0
  59. package/dist/src/server/routes-team.js +211 -1
  60. package/dist/src/server/routes-workflow-schedules.d.ts +2 -0
  61. package/dist/src/server/routes-workflow-schedules.js +58 -0
  62. package/dist/src/server/routes-workflows.d.ts +2 -0
  63. package/dist/src/server/routes-workflows.js +83 -0
  64. package/dist/src/server/routes.js +4 -0
  65. package/dist/src/server/runtime-restart-policy.d.ts +3 -1
  66. package/dist/src/server/runtime-restart-policy.js +3 -1
  67. package/dist/src/server/runtime-store-contract.d.ts +122 -0
  68. package/dist/src/server/runtime-store-contract.js +1 -0
  69. package/dist/src/server/runtime-store-helpers.d.ts +9 -0
  70. package/dist/src/server/runtime-store-helpers.js +101 -2
  71. package/dist/src/server/runtime-store-workflows.d.ts +6 -0
  72. package/dist/src/server/runtime-store-workflows.js +100 -0
  73. package/dist/src/server/runtime-store.d.ts +3 -72
  74. package/dist/src/server/runtime-store.js +70 -4
  75. package/dist/src/server/session-capture-codex.d.ts +3 -3
  76. package/dist/src/server/session-capture-codex.js +9 -7
  77. package/dist/src/server/session-capture-gemini.d.ts +1 -1
  78. package/dist/src/server/session-capture-gemini.js +6 -3
  79. package/dist/src/server/settings-store.d.ts +3 -0
  80. package/dist/src/server/settings-store.js +1 -0
  81. package/dist/src/server/sqlite-schema-v19.d.ts +2 -0
  82. package/dist/src/server/sqlite-schema-v19.js +17 -0
  83. package/dist/src/server/sqlite-schema-v20.d.ts +2 -0
  84. package/dist/src/server/sqlite-schema-v20.js +20 -0
  85. package/dist/src/server/sqlite-schema-v21.d.ts +2 -0
  86. package/dist/src/server/sqlite-schema-v21.js +20 -0
  87. package/dist/src/server/sqlite-schema.d.ts +1 -1
  88. package/dist/src/server/sqlite-schema.js +97 -1
  89. package/dist/src/server/system-message.d.ts +7 -0
  90. package/dist/src/server/system-message.js +8 -1
  91. package/dist/src/server/tasks-file-watcher.d.ts +13 -1
  92. package/dist/src/server/tasks-file-watcher.js +127 -23
  93. package/dist/src/server/tasks-file.d.ts +2 -1
  94. package/dist/src/server/tasks-file.js +32 -9
  95. package/dist/src/server/tasks-websocket-server.js +13 -14
  96. package/dist/src/server/team-authz.d.ts +1 -1
  97. package/dist/src/server/team-authz.js +9 -1
  98. package/dist/src/server/team-autostaff.d.ts +16 -0
  99. package/dist/src/server/team-autostaff.js +16 -0
  100. package/dist/src/server/team-list-serializer.d.ts +1 -1
  101. package/dist/src/server/team-list-serializer.js +3 -1
  102. package/dist/src/server/team-operations.d.ts +15 -1
  103. package/dist/src/server/team-operations.js +116 -11
  104. package/dist/src/server/terminal-protocol.js +9 -3
  105. package/dist/src/server/terminal-stream-hub.js +16 -10
  106. package/dist/src/server/terminal-ws-server.js +10 -8
  107. package/dist/src/server/websocket-upgrade-safety.d.ts +10 -0
  108. package/dist/src/server/websocket-upgrade-safety.js +35 -0
  109. package/dist/src/server/windows-command-line.d.ts +3 -0
  110. package/dist/src/server/windows-command-line.js +9 -0
  111. package/dist/src/server/windows-filename.d.ts +2 -0
  112. package/dist/src/server/windows-filename.js +33 -0
  113. package/dist/src/server/workflow-cli-policy.d.ts +60 -0
  114. package/dist/src/server/workflow-cli-policy.js +110 -0
  115. package/dist/src/server/workflow-dispatch-awaiter.d.ts +12 -0
  116. package/dist/src/server/workflow-dispatch-awaiter.js +80 -0
  117. package/dist/src/server/workflow-feature.d.ts +15 -0
  118. package/dist/src/server/workflow-feature.js +15 -0
  119. package/dist/src/server/workflow-http-serializers.d.ts +64 -0
  120. package/dist/src/server/workflow-http-serializers.js +58 -0
  121. package/dist/src/server/workflow-run-log-store.d.ts +19 -0
  122. package/dist/src/server/workflow-run-log-store.js +45 -0
  123. package/dist/src/server/workflow-run-store.d.ts +50 -0
  124. package/dist/src/server/workflow-run-store.js +103 -0
  125. package/dist/src/server/workflow-runner.d.ts +147 -0
  126. package/dist/src/server/workflow-runner.js +401 -0
  127. package/dist/src/server/workflow-schedule-create.d.ts +14 -0
  128. package/dist/src/server/workflow-schedule-create.js +41 -0
  129. package/dist/src/server/workflow-schedule-store.d.ts +43 -0
  130. package/dist/src/server/workflow-schedule-store.js +112 -0
  131. package/dist/src/server/workflow-scheduler.d.ts +36 -0
  132. package/dist/src/server/workflow-scheduler.js +97 -0
  133. package/dist/src/server/workflow-script-loader.d.ts +34 -0
  134. package/dist/src/server/workflow-script-loader.js +106 -0
  135. package/dist/src/server/workspace-path-validation.js +16 -4
  136. package/dist/src/server/workspace-shell-runtime.d.ts +5 -0
  137. package/dist/src/server/workspace-shell-runtime.js +24 -2
  138. package/dist/src/server/workspace-store-contract.d.ts +4 -1
  139. package/dist/src/server/workspace-store-hydration.js +23 -7
  140. package/dist/src/server/workspace-store-mutations.js +2 -5
  141. package/dist/src/server/workspace-store-support.d.ts +4 -0
  142. package/dist/src/server/workspace-store-support.js +13 -1
  143. package/dist/src/server/workspace-store.js +38 -4
  144. package/dist/src/shared/types.d.ts +16 -1
  145. package/package.json +4 -2
  146. package/web/dist/assets/{AddWorkerDialog-DeZhTQLi.js → AddWorkerDialog-CcC-7kgG.js} +2 -2
  147. package/web/dist/assets/AddWorkspaceDialog-BDpOTfmt.js +1 -0
  148. package/web/dist/assets/{FirstRunWizard-B5wLcat5.js → FirstRunWizard-BYX_ocQn.js} +1 -1
  149. package/web/dist/assets/{MarketplaceDrawer-BC0eBOEW.js → MarketplaceDrawer-DUxSk7db.js} +1 -1
  150. package/web/dist/assets/WhatsNewDialog-B_RlCXcV.js +1 -0
  151. package/web/dist/assets/WorkerModal-D9-7YfZZ.js +1 -0
  152. package/web/dist/assets/WorkspaceTaskDrawer-BCKoF7qc.js +1 -0
  153. package/web/dist/assets/{WorkspaceTerminalPanels-CvibsPSd.js → WorkspaceTerminalPanels-Dq8y91t2.js} +1 -1
  154. package/web/dist/assets/index-BiOvKIVw.css +1 -0
  155. package/web/dist/assets/index-DMRUklT3.js +73 -0
  156. package/web/dist/assets/path-join-7MR1s7b1.js +1 -0
  157. package/web/dist/index.html +2 -2
  158. package/web/dist/sw.js +1 -1
  159. package/web/dist/assets/AddWorkspaceDialog-DDpXNEKf.js +0 -1
  160. package/web/dist/assets/WorkerModal-BwMHq-Bi.js +0 -1
  161. package/web/dist/assets/WorkspaceTaskDrawer-CxvT4nqs.js +0 -1
  162. package/web/dist/assets/index-BEsTmfrO.css +0 -1
  163. package/web/dist/assets/index-Ddb7bDN5.js +0 -75
  164. package/web/dist/assets/path-join-S7qkXQtP.js +0 -1
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_WORKFLOW_CLI_POLICY } from './workflow-cli-policy.js';
1
2
  /**
2
3
  * Tail reminder appended to every message that flows INTO the orchestrator
3
4
  * (worker reports, worker status updates, user chat input). Re-anchors the
@@ -10,12 +11,25 @@
10
11
  * banner noise after a few occurrences, but `<...-system-reminder>` tags
11
12
  * mirror the out-of-band envelope LLMs are trained to attend to; placement
12
13
  * at the tail (right before the agent's reply turn) maximizes recency
13
- * weighting; phrasing as a two-option action menu is more actionable than
14
- * abstract identity restatement.
14
+ * weighting; phrasing as a short action menu is more actionable than abstract
15
+ * identity restatement. Kept deliberately SHORT — the full command syntax and
16
+ * the workflow DSL live in `.hive/PROTOCOL.md`, which agents re-read on demand.
17
+ * A long banner on every turn is itself the noise this envelope exists to beat.
15
18
  */
16
- export const ORCHESTRATOR_REMINDER_TAIL = '<hive-system-reminder>\n' +
17
- 'You are the Hive Orchestrator. Reply by either: (a) `team send "<worker-name>" "<task>"` to dispatch follow-up work to a Hive worker — run `team list` first when the roster may have changed since your last view (Hive does not push membership changes; stale names fail dispatch), (b) `team cancel --dispatch <id> "<reason>"` to cancel an obsolete dispatch, or (c) plain text to the user. Never call your CLI\'s built-in subagent tools (Task / Explore / etc.) — they bypass Hive and will not appear in the UI.\n' +
18
- '</hive-system-reminder>';
19
+ export const buildOrchestratorReminderTail = (workflowsEnabled) => {
20
+ const body = 'You are the Hive Orchestrator. Reply with one of: ' +
21
+ '(a) `team send "<worker-name>" "<task>"` to dispatch — run `team list` first if the roster may have changed since your last view (Hive does not push membership changes; stale names fail). ' +
22
+ 'If no worker fits or the roster is empty, `team spawn <role> [--cli claude|codex|opencode|gemini]` to create one (add `--ephemeral` for a one-shot), then dispatch; do not ask the user to add workers. ' +
23
+ '(b) `team cancel --dispatch <id> "<reason>"` to close an obsolete dispatch. ' +
24
+ (workflowsEnabled
25
+ ? '(c) `team workflow run --stdin` to fan out across 3+ workers or run a staged review→fix — never a loop of `team send` (no barrier, no UI group, no stop button). (d) plain text to the user. '
26
+ : '(c) plain text to the user. ') +
27
+ `Do not use your CLI's own subagent${workflowsEnabled ? ' / workflow' : ''} tools — they run inside your CLI, bypass Hive, and never reach the UI or \`team list\`. ` +
28
+ (workflowsEnabled
29
+ ? 'Full command syntax and the workflow DSL: re-read `.hive/PROTOCOL.md`.'
30
+ : 'Full command syntax: re-read `.hive/PROTOCOL.md`.');
31
+ return `<hive-system-reminder>\n${body}\n</hive-system-reminder>`;
32
+ };
19
33
  /**
20
34
  * Tail reminder appended to dispatches sent TO a worker. Reinforces the
21
35
  * worker identity (so the agent does not regress into its normal CLI
@@ -23,80 +37,247 @@ export const ORCHESTRATOR_REMINDER_TAIL = '<hive-system-reminder>\n' +
23
37
  * with dispatch_id pre-bound.
24
38
  */
25
39
  export const buildWorkerReminderTail = (dispatchId) => '<hive-system-reminder>\n' +
26
- `You are a Hive Worker. Do not launch nested CLI subagents (Task / Explore / etc.) — finish the task yourself. When the task is done, blocked, or has failed, report with: \`team report "<result>" --dispatch ${dispatchId}\` (or \`team report --stdin --dispatch ${dispatchId}\` for long bodies).\n` +
40
+ `You are a Hive Worker. Do not launch nested CLI subagents — finish the task yourself. When the task is done, blocked, or has failed, report with: \`team report "<result>" --dispatch ${dispatchId}\` (or \`team report --stdin --dispatch ${dispatchId}\` for long bodies).\n` +
27
41
  '</hive-system-reminder>';
28
- const ORCHESTRATOR_RULES = [
29
- 'Hive worker 是右侧卡片里的真实 CLI agent,不是你所在 CLI 的内置 subagent / 子代理工具。',
30
- '派单前必须以最新 roster 为准:每次 `team send` 之前,如果距上一次 `team list` 之后发生过 user 回复或你自己的派单/取消,重新跑一次 `team list` 拿当前成员名单。Hive 不主动推送成员变更——别按对会话早期 roster 的记忆派单,否则容易派到已改名或已删除的 worker。',
31
- '普通、低风险、几分钟内能直接完成的小任务可以自己做;不要为了形式感派 worker。需要并行、长时间执行、独立 review/test、专门角色,或 user 明确要求 worker/成员处理时,再用 `team send`。',
32
- '如果只有一个可用 worker,直接用 `team send <worker-name> "<task>"` 派给它;不要把选择题丢回给 user。',
33
- '当 user 要你“让 worker ...”时,必须用 `team send <worker-name> "<task>"` 派给 Hive worker。',
34
- '派单时如果任务明显需要某种角色能力(例如代码评审、测试、安全审查),但 `team list` 中没有匹配 role 的成员,可以在回复 user 的自然语言部分(而非 `team send` 的任务正文)末尾用一句话建议添加该角色,例如:“如果这类任务后续会变多,可以考虑添加一个 reviewer”。仅在明显缺失时提;同一缺口在 user 未响应前不要重复建议。',
35
- '方向变更或 user 明确取消某个未完成派单时,使用 `team cancel --dispatch <id> "<reason>"` 显式关闭旧 dispatch;不要只用自然语言说“取消”。',
36
- '不要使用你所在 CLI 的内置 subagent / 子代理工具(如 Task / Explore 等)来代替 Hive worker;它们不会出现在 Hive UI,也不会更新 Hive 调度状态。',
37
- '`team list` 返回的 `last_pty_line` 是该 worker PTY 终端的最后一行原始输出(含任意 stdout / help / 控制序列噪声),**不是** worker 的正式汇报。正式汇报只来自 stdin 注入的 `[Hive 系统消息:来自 @<name> 的汇报]` `[Hive 系统消息:来自 @<name> 的状态更新]`——只把这两种来源当作 reply。',
42
+ /**
43
+ * Core, always-on orchestrator rules. Injected at startup, on crash recovery,
44
+ * and on restart env-sync. Deliberately free of multi-line code skeletons
45
+ * those are reference material that lives in `.hive/PROTOCOL.md` (see
46
+ * WORKFLOW_DSL_REFERENCE) so the recovery / env-sync paths re-anchor identity
47
+ * and dispatch discipline without re-injecting a wall of example JS.
48
+ */
49
+ const CORE_ORCHESTRATOR_RULES = [
50
+ 'A Hive worker is a real CLI agent shown as a card on the right NOT a subagent of your own CLI.',
51
+ 'Dispatch against the current roster: re-run `team list` before a `team send` whenever a user reply or one of your own dispatches/cancels has happened since your last list. Hive never pushes membership changes, so do not dispatch from a remembered roster — a renamed or removed worker fails.',
52
+ 'Small, low-risk tasks you can finish in a couple of minutes: do them yourself; do not dispatch for the sake of form. Reach for `team send` when the work needs parallelism, long execution, independent review/test, a dedicated role, or the user explicitly asked for a worker.',
53
+ 'If exactly one worker is available, dispatch to it directly with `team send <worker-name> "<task>"` — do not bounce the choice back to the user.',
54
+ 'When the user says "have a worker do X", dispatch it with `team send <worker-name> "<task>"`.',
55
+ 'If the roster is empty or lacks the role the task needs, build the team yourself: `team spawn <role> [--name <n>] [--cli claude|codex|opencode|gemini]`, then immediately dispatch. Do not stop to ask the user to add members — that call is yours.',
56
+ '`team spawn` is PERSISTENT by default (a normal member that stays in the workspace); add `--ephemeral` for a one-shot worker that auto-dismisses after its first `team report`. Rule of thumb: will you reuse this role in the next 10 minutes? Yes → persistent; no → `--ephemeral`.',
57
+ 'When the user cancels or changes direction on an open dispatch, close it explicitly with `team cancel --dispatch <id> "<reason>"` — do not just say "cancel" in prose.',
58
+ 'Each `team send` opens a SEPARATE dispatch with its own pending count and its own required report — it is not a way to tack context onto a dispatch already in flight. Send the same worker twice and it owes you TWO reports; one report closes only one dispatch (the one its `--dispatch <id>` names, or the oldest open one if the flag is omitted), so the other stays open and the worker is pinned on `working`. To change or extend an in-flight task, `team cancel --dispatch <id> "<reason>"` the stale dispatch and re-send the whole task, or wait for the worker to report and dispatch the follow-up after.',
59
+ "Never substitute your CLI's own subagent / workflow tools (e.g. Task / Explore / Workflow / Agent) for Hive workers or Hive workflows — they run inside your CLI process, bypass Hive's PTY fleet, never appear in the UI or `team list`, and the stop button cannot reach them.",
60
+ 'In `team list`, `last_pty_line` is raw terminal output (stdout / help / control-sequence noise), NOT a worker\'s report. A real report arrives only as an injected "report from @<name>" / "status from @<name>" system message — treat only those as replies.',
61
+ ];
62
+ /**
63
+ * Workflow-authoring rule — only injected when the experimental workflow
64
+ * feature is ENABLED. When workflows are off the orchestrator is never told
65
+ * to reach for `team workflow`, which keeps its always-on prompt lean and
66
+ * avoids it firing a command the runtime will reject.
67
+ */
68
+ const WORKFLOW_ORCHESTRATOR_RULES = [
69
+ 'Choosing to use a workflow is YOUR call, judged from the task\'s shape — the user describes what they want in plain language and will not (and need not) ask for a "workflow" by name. When a task fans out across 3+ workers, needs a staged review→fix, or loops until results converge, author the workflow script yourself from the task and fire it with ONE `team workflow run --stdin` — decide this on your own, do not wait to be told, and do not approximate it with a loop of `team send` (no barrier, no UI grouping, no stop button). The DSL and ready-made patterns are in `.hive/PROTOCOL.md`.',
70
+ ];
71
+ /**
72
+ * Auto-staff rule — only injected when the experimental auto-staff feature is
73
+ * ENABLED (ON by default). Grants + encourages the orchestrator to size the
74
+ * team to the task instead of adding workers one at a time. The shared-FS +
75
+ * ephemeral notes are operating instructions (Hive gives every worker the same
76
+ * workspace root with no per-worker isolation), not optional caution: without
77
+ * them parallel coders overwrite each other.
78
+ *
79
+ * The text adapts to whether workflows are ALSO on: there is no batch `team
80
+ * spawn` syntax (one command per member), so it says exactly that; and when
81
+ * workflows are available it defers one-shot batch fan-out to `team workflow
82
+ * run` so the two experiments don't give the orchestrator competing advice.
83
+ */
84
+ const buildAutostaffRule = (workflowsEnabled) => 'You may size the team to the task instead of adding workers one at a time: judge what mix of roles runs it fastest (e.g. a couple of coders plus a reviewer and a tester) and issue the individual `team spawn <role> --ephemeral` commands you need up front — one command per member (there is no batch form), this call is yours, do not ask the user. Match the count to the work: more agents is not faster once they would collide or sit idle. CRITICAL: all workers share the same workspace files with NO per-worker isolation, so split the work so no two agents touch the same files/modules. Use `--ephemeral` so this task-scoped staff auto-dismiss after reporting and do not pile up.' +
85
+ (workflowsEnabled
86
+ ? ' When the work is a one-shot fan-out across 3+ workers or a staged review→fix that runs to completion, prefer `team workflow run` (barrier, phase tree, stop button) over a batch of `team spawn`; reserve up-front staffing for a standing team you direct interactively across several turns.'
87
+ : '');
88
+ const orchestratorRules = (workflowsEnabled, autostaffEnabled) => [
89
+ ...CORE_ORCHESTRATOR_RULES,
90
+ ...(workflowsEnabled ? WORKFLOW_ORCHESTRATOR_RULES : []),
91
+ ...(autostaffEnabled ? [buildAutostaffRule(workflowsEnabled)] : []),
38
92
  ];
39
93
  const WORKER_RULES = [
40
- '你是 Hive 右侧卡片里的真实 CLI worker,不是你所在 CLI 的内置 subagent',
41
- '不要调用 team send,也不要再启动你所在 CLI 的内置 subagent / 子代理工具(如 Task / Explore 等)来替你完成派单。',
42
- '完成或阻塞已派发任务时必须用 `team report` 汇报给 Orchestrator',
43
- '如果当前没有明确派发任务,只是汇报待命、环境或状态,使用 `team status "<当前状态>"`。',
44
- '`team --help` 只用于查命令语法,**绝不是** 汇报手段;其输出不会进入 Orchestrator 视野,跑完后仍需正式调用 `team report` / `team status`。',
45
- '`team report` / `team status` 报错时会同时打印 USAGE,按 USAGE 修正参数后重试;不要把 `team --help` 当成"自我探查"的替身。',
94
+ 'You are a real CLI worker shown as a card on the right in Hive — not a subagent of your own CLI.',
95
+ "Do not call `team send`, and do not launch your own CLI's subagent tools to do the work for you — finish it yourself.",
96
+ 'When an assigned task is done, blocked, or has failed, you MUST report to the Orchestrator with `team report`.',
97
+ 'When you have no active dispatch and only want to report readiness, environment, or status, use `team status "<state>"`.',
98
+ '`team --help` only prints command syntax — it is NOT a way to report; its output never reaches the Orchestrator. You still owe a real `team report` / `team status` afterward.',
99
+ 'If `team report` / `team status` errors, it also prints USAGE — fix the arguments per USAGE and retry; do not use `team --help` as a stand-in for reporting.',
46
100
  ];
47
- export const getHiveTeamRules = (agent) => agent.role === 'orchestrator' ? ORCHESTRATOR_RULES : WORKER_RULES;
101
+ export const getHiveTeamRules = (agent, workflowsEnabled = false, autostaffEnabled = false) => agent.role === 'orchestrator'
102
+ ? orchestratorRules(workflowsEnabled, autostaffEnabled)
103
+ : WORKER_RULES;
48
104
  const renderRules = (rules) => rules.map((line) => `- ${line}`).join('\n');
105
+ /**
106
+ * The workflow DSL teaching: agent()/parallel()/pipeline() semantics, the
107
+ * agent() opts surface, runnable skeletons, and the canonical patterns. This
108
+ * is REFERENCE material — it lives only in `.hive/PROTOCOL.md`, never in the
109
+ * per-message reminder or the recovery/env-sync injections, so the always-on
110
+ * paths stay lean. The orchestrator is pointed here by the core rules and the
111
+ * reminder tail whenever it needs to author a `team workflow run`.
112
+ */
113
+ const WORKFLOW_DSL_REFERENCE = `## Workflow DSL (\`team workflow run --stdin\`)
114
+
115
+ Use a workflow when a task fans out beyond a single dispatch: 3+ parallel
116
+ workers, a staged review→fix, or a loop until results converge. The DSL mirrors
117
+ Claude Code's Workflow tool, but every \`agent()\` runs on Hive's PTY fleet — a
118
+ real CLI process — not an in-CLI API subagent. \`team workflow run\` is the only
119
+ entry into the Hive runtime; never use your CLI's own Workflow/Agent tool.
120
+
121
+ Host functions injected into the script: \`agent(prompt, opts)\`,
122
+ \`parallel(thunks)\`, \`pipeline(items, ...stages)\`, \`phase(title)\`,
123
+ \`log(msg)\`, plus the \`args\` global.
124
+
125
+ \`agent(prompt, opts)\` opts: \`{ agentType?: "coder"|"reviewer"|"tester"|"custom"|<custom-role-name>, cli?: "claude"|"codex"|"opencode"|"gemini", model?: string, label?: string, timeoutMs?: number }\` — other fields are silently ignored. \`agentType\` also accepts the name of a workspace custom role template (case-insensitive); a typo throws rather than silently falling back to coder. \`model\` is passed through to the worker launch config (\`--model <id>\`), so a 100-way fan-out can use a cheap model and the synthesizer a strong one. The worker auto-dismisses when its \`agent()\` call resolves — you never dismiss it.
126
+
127
+ \`parallel()\` takes an array of THUNKS (\`() => agent(...)\`), NOT already-started promises: \`parallel([agent(...), agent(...)])\` degrades to unordered concurrency counted as a single step (a no-op grouping), because the promises already started at construction time. \`pipeline(items, ...stages)\` stages are also functions, shape \`(prev, item, i) => agent(...)\`.
128
+
129
+ \`log("...")\` writes one narrator line — stored in the DB, shown when the run row is expanded in the Drawer, and its last 8 lines are spliced into the completion reminder sent back to you. Use it for a readable progress summary, e.g. \`log('Discovered 47 endpoints')\`.
130
+
131
+ Runtime limits: each run defaults to at most 1000 \`agent()\` calls and 60 minutes wall-clock; the concurrency cap is \`min(16, cores-2)\` and parallel/pipeline queue against it automatically. Override in \`meta\`, e.g. \`meta = { name, description, maxAgentCalls: 50, maxDurationMs }\`.
132
+
133
+ \`meta\` must be a pure literal (no variables). Scripts are JS, not TS (type annotations error). The body may use top-level \`await\` and a trailing \`return\`.
134
+
135
+ Minimal script (heredoc into \`--stdin\`):
136
+ \`\`\`
137
+ export const meta = { name: 'review-changes', description: 'review + tests' }
138
+ phase('Find')
139
+ const issues = await agent('Run \`git diff\` and list any potential bugs.', { agentType: 'reviewer', label: 'review' })
140
+ phase('Verify')
141
+ const tests = await agent(\`Write tests for: \${issues}\`, { agentType: 'tester', label: 'verify' })
142
+ return { issues, tests }
143
+ \`\`\`
144
+
145
+ Parallel fan-out + multi-vendor mix (Hive's signature — several CLIs in one run):
146
+ \`\`\`
147
+ export const meta = { name: 'parallel-audit', description: 'audit N files in parallel' }
148
+ const files = ['src/a.ts', 'src/b.ts', 'src/c.ts']
149
+ phase('Audit')
150
+ const reports = await parallel(files.map((f) => () => agent(\`Audit \${f} for security bugs.\`, { agentType: 'reviewer', cli: 'codex', label: \`audit:\${f}\` })))
151
+ phase('Synthesize')
152
+ return await agent(\`Synthesize: \${reports.filter(Boolean).join('\\n---\\n')}\`, { agentType: 'reviewer', cli: 'claude', label: 'synth' })
153
+ \`\`\`
154
+
155
+ Passing args (so a saved script is reusable instead of hard-coding values):
156
+ \`\`\`
157
+ team workflow run --stdin --args '["src/a.ts","src/b.ts"]' <<'EOF'
158
+ export const meta = { name: 'audit', description: 'd' }
159
+ phase('Audit')
160
+ return await parallel(args.map((f) => () => agent(\`Audit \${f}\`)))
161
+ EOF
162
+ \`\`\`
163
+ \`--args\` takes JSON (\`'{"q":1}'\`, \`'["a","b"]'\`, \`'"plain"'\`); omitted → \`args\` is \`undefined\`.
164
+
165
+ Patterns worth knowing:
166
+ - **loop-until-dry** — stop after K empty rounds; more robust than \`while (count < N)\`, which stalls on the hard-to-find tail:
167
+ \`\`\`
168
+ const seen = new Set(), confirmed = []
169
+ let dry = 0
170
+ while (dry < 2) {
171
+ const found = await agent('Find any potential bugs not in: ' + [...seen].join(', '))
172
+ const fresh = found.split('\\n').filter((b) => b.trim() && !seen.has(b))
173
+ if (!fresh.length) { dry++; continue }
174
+ dry = 0
175
+ fresh.forEach((b) => { seen.add(b); confirmed.push(b) })
176
+ }
177
+ return confirmed
178
+ \`\`\`
179
+ - **judge panel** — N independent verifiers per finding; majority confirms. Catches plausible-but-wrong findings:
180
+ \`\`\`
181
+ phase('Verify')
182
+ const votes = await parallel([
183
+ () => agent(\`Try to REFUTE: \${claim}. Default refuted=true if uncertain. Reply yes/no.\`),
184
+ () => agent(\`Independently judge: \${claim}. Reply yes/no.\`),
185
+ () => agent(\`Repro test: \${claim}. Did you confirm? yes/no.\`),
186
+ ])
187
+ const real = votes.filter((v) => v?.toLowerCase().startsWith('y')).length >= 2
188
+ \`\`\`
189
+ - **pipeline** — multi-item, multi-stage, no barrier between stages (item A can be in stage 3 while item B is in stage 1); wall-clock = slowest single item, not sum-of-slowest-per-stage. Each stage gets \`(prevResult, originalItem, index)\`; a stage that throws drops that item to null and skips its remaining stages.
190
+
191
+ On completion Hive injects \`<hive-system-reminder>Hive workflow ... finished: status=...</hive-system-reminder>\` carrying each step's short report; synthesize that back to the user. Full per-agent transcripts: \`team workflow show <run-id>\`.`;
49
192
  /**
50
193
  * Workspace-local protocol cheat sheet written to `.hive/PROTOCOL.md`. Agents
51
194
  * are explicitly trained to look at project root markdown when confused, so
52
195
  * keeping a single canonical doc next to `.hive/tasks.md` doubles as a
53
196
  * "cat-recover" path when both the startup prompt and the in-message
54
- * reminders fail to anchor.
197
+ * reminders fail to anchor. This is also the single home of the full command
198
+ * syntax and the workflow DSL reference — the always-on injections only carry
199
+ * the lean core rules and point here.
55
200
  */
56
- export const buildProtocolDoc = () => [
57
- '# Hive Team Protocol',
58
- '',
59
- 'This file is auto-generated by Hive on every workspace open. If you',
60
- '(the agent) lost context after `/compact` or an internal summarization,',
61
- 're-read `.hive/PROTOCOL.md` (POSIX: `cat`, Windows cmd: `type`, PowerShell:',
62
- '`Get-Content`) to re-anchor.',
63
- '',
64
- '## You are running inside Hive',
65
- '',
66
- 'Hive is a multi-CLI-agent workbench. Each agent in this workspace is a',
67
- 'real CLI process (Claude Code / Codex / OpenCode / Gemini). All',
68
- 'inter-agent communication goes through the `team` CLI binary on your',
69
- 'PATH.',
70
- '',
71
- '## Roles',
72
- '',
73
- '- **Orchestrator** — talks to the user, plans tasks, dispatches to workers',
74
- '- **Worker** (Coder / Reviewer / Tester / custom) — executes one assigned task and reports back',
75
- '',
76
- '## `team` CLI orchestrator',
77
- '',
78
- '- `team list` show workspace members and their status',
79
- '- `team send "<worker-name>" "<task>"` dispatch to a worker by name (never id)',
80
- '- `team cancel --dispatch <id> "<reason>"` — cancel an obsolete open dispatch',
81
- '',
82
- '## `team` CLI worker',
83
- '',
84
- '- `team report "<result>" --dispatch <id>` — report task outcome',
85
- '- `team report --stdin --dispatch <id>` — same, body from stdin (pipe content in via your shell — POSIX heredoc, `type file |`, or whatever your environment supports)',
86
- '- `team status "<state>"` — update orchestrator when no dispatch is active',
87
- '',
88
- '## Orchestrator rules',
89
- '',
90
- renderRules(ORCHESTRATOR_RULES),
91
- '',
92
- '## Worker rules',
93
- '',
94
- renderRules(WORKER_RULES),
95
- '',
96
- '## In-message reminders',
97
- '',
98
- 'Every message you receive in this workspace ends with a short',
99
- '`<hive-system-reminder>` block carrying the minimum syntax you need',
100
- 'right now. If something is missing from that block, re-read this file.',
101
- '',
102
- ].join('\n');
201
+ export const buildProtocolDoc = (cliPolicy = DEFAULT_WORKFLOW_CLI_POLICY, workflowsEnabled = false, autostaffEnabled = false) => {
202
+ // The `team workflow …` subcommands + the DSL reference + the per-workspace
203
+ // CLI-policy section only appear when the experimental workflow feature is
204
+ // ON. While off, the orchestrator's canonical reference never mentions
205
+ // workflows (leaner prompt) and never points at a command the runtime rejects.
206
+ const workflowCliCommands = workflowsEnabled
207
+ ? [
208
+ "- `team workflow run --stdin` — fire a multi-agent workflow; pass JS source via stdin. Add `--args '<JSON>'` to set the script's `args` global.",
209
+ '- `team workflow run --inline "<source>"` — same, single-arg form',
210
+ '- `team workflow stop <run-id>` — cancel a running workflow',
211
+ '- `team workflow show <run-id>` — full per-agent transcript (status, phase, label, prompt, full reportText) — use this when the truncated completion reminder is not enough',
212
+ '- `team workflow schedule --cron "<5-field cron>" --name <n> --stdin` — register a RECURRING run; pass the same JS source you would give `run`. The source is persisted so cron can fire it with no orchestrator present. The UI can pause / delete schedules but never create them — scheduling is your job.',
213
+ ]
214
+ : [];
215
+ const workflowSections = workflowsEnabled
216
+ ? [
217
+ WORKFLOW_DSL_REFERENCE,
218
+ '',
219
+ '## Workflow agent CLIs (this workspace)',
220
+ '',
221
+ 'When a workflow `agent()` omits `cli` it launches a worker on the default',
222
+ 'CLI below; an explicit `cli:` must be one of the allowed CLIs or the run',
223
+ 'fails with a clear error. (Custom role templates keep their own configured',
224
+ 'CLI and are exempt from the allowlist.)',
225
+ '',
226
+ `- Default CLI when \`cli\` is omitted: **${cliPolicy.default}**`,
227
+ `- Allowed CLIs for \`cli\`: ${cliPolicy.allowed.join(', ')}`,
228
+ '',
229
+ ]
230
+ : [];
231
+ return [
232
+ '# Hive Team Protocol',
233
+ '',
234
+ 'This file is auto-generated by Hive on every workspace open. If you',
235
+ '(the agent) lost context after `/compact` or an internal summarization,',
236
+ 're-read `.hive/PROTOCOL.md` (POSIX: `cat`, Windows cmd: `type`, PowerShell:',
237
+ '`Get-Content`) to re-anchor.',
238
+ '',
239
+ '## You are running inside Hive',
240
+ '',
241
+ 'Hive is a multi-CLI-agent workbench. Each agent in this workspace is a',
242
+ 'real CLI process (Claude Code / Codex / OpenCode / Gemini). All',
243
+ 'inter-agent communication goes through the `team` CLI binary on your',
244
+ 'PATH.',
245
+ '',
246
+ '## Roles',
247
+ '',
248
+ '- **Orchestrator** — talks to the user, plans tasks, dispatches to workers',
249
+ '- **Worker** (Coder / Reviewer / Tester / custom) — executes one assigned task and reports back',
250
+ '',
251
+ '## `team` CLI — orchestrator',
252
+ '',
253
+ '- `team list` — show workspace members and their status',
254
+ '- `team send "<worker-name>" "<task>"` — dispatch to a worker by name (never id)',
255
+ '- `team spawn <role> [--name <name>] [--cli claude|codex|opencode|gemini]` — create a PERSISTENT member when none fits (or when the roster is empty)',
256
+ '- `team spawn <role> --ephemeral [other-flags]` — create a one-shot worker that auto-dismisses after its first `team report`',
257
+ '- `team dismiss <worker-name>` — remove an ephemeral worker you spawned',
258
+ '- `team cancel --dispatch <id> "<reason>"` — cancel an obsolete open dispatch',
259
+ ...workflowCliCommands,
260
+ '',
261
+ '## `team` CLI — worker',
262
+ '',
263
+ '- `team report "<result>" --dispatch <id>` — report task outcome',
264
+ '- `team report --stdin --dispatch <id>` — same, body from stdin (pipe content in via your shell — POSIX heredoc, `type file |`, or whatever your environment supports)',
265
+ '- `team status "<state>"` — update orchestrator when no dispatch is active',
266
+ '',
267
+ '## Orchestrator rules',
268
+ '',
269
+ renderRules(orchestratorRules(workflowsEnabled, autostaffEnabled)),
270
+ '',
271
+ '## Worker rules',
272
+ '',
273
+ renderRules(WORKER_RULES),
274
+ '',
275
+ ...workflowSections,
276
+ '## In-message reminders',
277
+ '',
278
+ 'Every message you receive in this workspace ends with a short',
279
+ '`<hive-system-reminder>` block carrying the minimum syntax you need',
280
+ 'right now. If something is missing from that block, re-read this file.',
281
+ '',
282
+ ].join('\n');
283
+ };
@@ -2,6 +2,7 @@ import type { LiveAgentRun } from './agent-runtime-types.js';
2
2
  export interface RunExitEntry {
3
3
  promise: Promise<void>;
4
4
  resolve: () => void;
5
+ runId: string;
5
6
  }
6
7
  export interface LiveRunRegistry {
7
8
  add: (run: LiveAgentRun) => void;
@@ -11,7 +11,7 @@ export const createLiveRunRegistry = () => {
11
11
  const promise = new Promise((nextResolve) => {
12
12
  resolve = nextResolve;
13
13
  });
14
- runExitPromises.set(runId, { promise, resolve });
14
+ runExitPromises.set(runId, { promise, resolve, runId });
15
15
  },
16
16
  deleteExitEntry(runId) {
17
17
  runExitPromises.delete(runId);
@@ -1,5 +1,6 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { getDefaultOpenTargetIdForPlatform, getEffectiveOpenTargetId, isOpenTargetId, } from '../shared/open-targets.js';
3
+ import { buildCmdCallCommand } from './windows-command-line.js';
3
4
  export { getEffectiveOpenTargetId, isOpenTargetId, isOpenTargetSupported, OPEN_TARGET_IDS_BY_PLATFORM, } from '../shared/open-targets.js';
4
5
  export const resolveOpenTargetPlatform = (platform) => {
5
6
  if (platform === 'darwin')
@@ -50,15 +51,13 @@ const linuxAttempts = (targetId, path) => {
50
51
  * PATHEXT and cannot launch `.cmd` files directly, so a bare `code` argv
51
52
  * returns ENOENT even when VSCode is installed.
52
53
  *
53
- * `cmd.exe /d /s /c` parses the trailing command line. We pass the binary
54
- * name and path as separate argv elements; node's child_process quotes the
55
- * path when it contains whitespace, and cmd's `/s` quote-stripping does NOT
56
- * fire because the command line starts with the binary name (e.g. `code`),
57
- * not a `"`.
54
+ * `cmd.exe /d /s /c` parses the trailing command line. Build that command
55
+ * with cmd-aware escaping instead of separate argv entries so path metachars
56
+ * (`&`, `|`, `%`, etc.) remain data rather than syntax.
58
57
  */
59
58
  const cmdExeShimAttempt = (bin, path) => ({
60
59
  command: 'cmd.exe',
61
- args: ['/d', '/s', '/c', bin, path],
60
+ args: ['/d', '/s', '/c', buildCmdCallCommand(bin, [path])],
62
61
  });
63
62
  const windowsAttempts = (targetId, path) => {
64
63
  switch (targetId) {
@@ -18,6 +18,18 @@ export interface OrchestratorStartResult {
18
18
  error: string | null;
19
19
  run_id: string | null;
20
20
  }
21
+ /**
22
+ * Translate an early-exit terminal state to a human-friendly error string.
23
+ *
24
+ * Two cases land here:
25
+ * - exit 127 (POSIX) / 9009 (Windows cmd.exe): shell saying "command not
26
+ * found" — the most common real case when the configured CLI is missing,
27
+ * because node-pty does NOT throw sync ENOENT for missing binaries; it
28
+ * spawns successfully and the child dies via onExit.
29
+ * - any other non-zero exit: surface the raw code so we don't lie about the
30
+ * cause.
31
+ */
32
+ export declare const formatEarlyExitError: (command: string, exitCode: number | null) => string;
21
33
  /**
22
34
  * Wraps `store.startAgent` so spawn failures never bubble up: callers always
23
35
  * receive a structured result. The HTTP layer uses this to keep workspace
@@ -1,15 +1,17 @@
1
1
  import { getStartupCommandExecutable } from './startup-command-parser.js';
2
2
  // SETTLE_WAIT_MS: how long we wait before declaring autostart "ok". Must be
3
3
  // long enough to observe an early exit when the child shell prints
4
- // "command not found" then dies with exit 127 (typically <100ms in practice).
5
- // 800ms balances reliability vs the perceived workspace-create latency cost.
4
+ // "command not found" then dies with exit 127 (POSIX) or 9009 (Windows)
5
+ // — typically <100ms in practice. 800ms balances reliability vs the perceived
6
+ // workspace-create latency cost.
6
7
  const SETTLE_WAIT_MS = 800;
7
8
  const POLL_INTERVAL_MS = 25;
8
- // Shells emit exit code 127 when the requested command is not on PATH (POSIX).
9
- // node-pty does NOT raise a synchronous spawn error for that case — the PTY
10
- // just dies almost immediately via onExit. We translate that to the same UX
11
- // string as the sync-ENOENT path so the user gets one consistent message.
12
- const COMMAND_NOT_FOUND_EXIT_CODE = 127;
9
+ // Shells emit a "command not found" exit code when the requested binary is
10
+ // missing on PATH. node-pty does NOT raise a synchronous spawn error for that
11
+ // case — the PTY just dies almost immediately via onExit. We translate that to
12
+ // the same UX string as the sync-ENOENT path so the user gets one consistent
13
+ // message. POSIX shells use 127; Windows cmd.exe uses 9009.
14
+ const COMMAND_NOT_FOUND_EXIT_CODES = new Set([127, 9009]);
13
15
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
14
16
  const isErrnoException = (error) => error instanceof Error && typeof error.code === 'string';
15
17
  /**
@@ -28,15 +30,15 @@ const formatStartError = (error, command) => {
28
30
  * Translate an early-exit terminal state to a human-friendly error string.
29
31
  *
30
32
  * Two cases land here:
31
- * - exit 127: shell saying "command not found" (the most common real case
32
- * when the configured CLI is missing node-pty does NOT throw sync ENOENT
33
- * for missing binaries, it spawns successfully and the child dies via
34
- * onExit).
33
+ * - exit 127 (POSIX) / 9009 (Windows cmd.exe): shell saying "command not
34
+ * found" the most common real case when the configured CLI is missing,
35
+ * because node-pty does NOT throw sync ENOENT for missing binaries; it
36
+ * spawns successfully and the child dies via onExit.
35
37
  * - any other non-zero exit: surface the raw code so we don't lie about the
36
38
  * cause.
37
39
  */
38
- const formatEarlyExitError = (command, exitCode) => {
39
- if (exitCode === COMMAND_NOT_FOUND_EXIT_CODE) {
40
+ export const formatEarlyExitError = (command, exitCode) => {
41
+ if (exitCode !== null && COMMAND_NOT_FOUND_EXIT_CODES.has(exitCode)) {
40
42
  return `${command} CLI not found in PATH`;
41
43
  }
42
44
  return `${command} failed to start (exit ${exitCode ?? 'null'})`;
@@ -0,0 +1,3 @@
1
+ export declare const realpathNative: (path: string) => string;
2
+ export declare const normalizeFilesystemIdentity: (path: string, platform?: NodeJS.Platform) => string;
3
+ export declare const sameFilesystemPath: (left: string, right: string, platform?: NodeJS.Platform) => boolean;
@@ -0,0 +1,29 @@
1
+ import { realpathSync } from 'node:fs';
2
+ import { posix, resolve, win32 } from 'node:path';
3
+ export const realpathNative = (path) => {
4
+ try {
5
+ return realpathSync.native(path);
6
+ }
7
+ catch (error) {
8
+ if (error?.code === 'ENOSYS')
9
+ return realpathSync(path);
10
+ throw error;
11
+ }
12
+ };
13
+ export const normalizeFilesystemIdentity = (path, platform = process.platform) => {
14
+ const resolveForPlatform = platform === 'win32' ? win32.resolve : posix.resolve;
15
+ let resolved;
16
+ if (platform === process.platform) {
17
+ try {
18
+ resolved = realpathNative(path);
19
+ }
20
+ catch {
21
+ resolved = resolve(path);
22
+ }
23
+ }
24
+ else {
25
+ resolved = resolveForPlatform(path);
26
+ }
27
+ return platform === 'win32' ? resolved.toLowerCase() : resolved;
28
+ };
29
+ export const sameFilesystemPath = (left, right, platform = process.platform) => normalizeFilesystemIdentity(left, platform) === normalizeFilesystemIdentity(right, platform);
@@ -0,0 +1,3 @@
1
+ export declare const arePathsEqual: (left: string, right: string, platform?: NodeJS.Platform) => boolean;
2
+ export declare const containsPathMarker: (haystack: string, marker: string, platform?: NodeJS.Platform) => boolean;
3
+ export declare const indexOfPathMarker: (haystack: string, marker: string, platform?: NodeJS.Platform) => number;
@@ -0,0 +1,13 @@
1
+ const toForwardSlashes = (path) => path.replace(/\\/g, '/');
2
+ const normalizeForWin32 = (path) => toForwardSlashes(path).toLowerCase();
3
+ export const arePathsEqual = (left, right, platform = process.platform) => {
4
+ if (platform === 'win32')
5
+ return normalizeForWin32(left) === normalizeForWin32(right);
6
+ return left === right;
7
+ };
8
+ export const containsPathMarker = (haystack, marker, platform = process.platform) => indexOfPathMarker(haystack, marker, platform) !== -1;
9
+ export const indexOfPathMarker = (haystack, marker, platform = process.platform) => {
10
+ if (platform === 'win32')
11
+ return toForwardSlashes(haystack).indexOf(marker);
12
+ return haystack.indexOf(marker);
13
+ };
@@ -3,4 +3,4 @@ export declare const toBracketedPasteSubmission: (text: string) => string;
3
3
  export declare const isInteractiveAgentCommand: (command: string) => boolean;
4
4
  export declare const hasInteractivePromptReady: (output: string, command?: string) => boolean;
5
5
  export declare const hasBracketedPasteAcknowledgement: (output: string, baselineLength: number) => boolean;
6
- export declare const createPostStartInputWriter: (agentManager: AgentManager, command: string) => ((runId: string, text: string) => void);
6
+ export declare const createPostStartInputWriter: (agentManager: AgentManager, command: string) => ((runId: string, text: string) => Promise<void>);