@tt-a1i/hive 1.5.0 → 1.7.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.
- package/CHANGELOG.md +39 -0
- package/README.en.md +23 -1
- package/README.md +10 -1
- package/dist/src/cli/team.js +19 -2
- package/dist/src/server/agent-run-bootstrap.d.ts +6 -1
- package/dist/src/server/agent-run-bootstrap.js +5 -2
- package/dist/src/server/agent-run-starter.d.ts +6 -7
- package/dist/src/server/agent-run-starter.js +18 -4
- package/dist/src/server/agent-runtime-contract.d.ts +10 -0
- package/dist/src/server/agent-runtime-stop-run.d.ts +1 -1
- package/dist/src/server/agent-runtime-stop-run.js +4 -1
- package/dist/src/server/agent-runtime.d.ts +2 -1
- package/dist/src/server/agent-runtime.js +10 -5
- package/dist/src/server/agent-startup-instructions.d.ts +7 -8
- package/dist/src/server/agent-startup-instructions.js +6 -4
- package/dist/src/server/agent-stdin-dispatcher.d.ts +20 -7
- package/dist/src/server/agent-stdin-dispatcher.js +22 -10
- package/dist/src/server/command-preset-defaults.js +12 -0
- package/dist/src/server/feature-flags.d.ts +42 -0
- package/dist/src/server/feature-flags.js +24 -0
- package/dist/src/server/hive-team-guidance.d.ts +4 -3
- package/dist/src/server/hive-team-guidance.js +17 -16
- package/dist/src/server/post-start-input-writer.js +2 -2
- package/dist/src/server/preset-launch-support.js +2 -1
- package/dist/src/server/recovery-summary.d.ts +5 -6
- package/dist/src/server/recovery-summary.js +3 -2
- package/dist/src/server/report-outbox-store.d.ts +36 -0
- package/dist/src/server/report-outbox-store.js +33 -0
- package/dist/src/server/restart-policy-support.d.ts +4 -5
- package/dist/src/server/restart-policy.d.ts +5 -1
- package/dist/src/server/restart-policy.js +51 -33
- package/dist/src/server/routes-settings.js +3 -3
- package/dist/src/server/routes-tasks.js +23 -0
- package/dist/src/server/routes-workspaces.js +5 -0
- package/dist/src/server/runtime-restart-policy.d.ts +3 -3
- package/dist/src/server/runtime-restart-policy.js +2 -3
- package/dist/src/server/runtime-store-contract.d.ts +3 -0
- package/dist/src/server/runtime-store-helpers.d.ts +2 -0
- package/dist/src/server/runtime-store-helpers.js +14 -9
- package/dist/src/server/runtime-store-workflows.js +8 -0
- package/dist/src/server/runtime-store.js +1 -0
- package/dist/src/server/session-capture.d.ts +6 -0
- package/dist/src/server/session-capture.js +32 -0
- package/dist/src/server/sqlite-schema-v22.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v22.js +27 -0
- package/dist/src/server/sqlite-schema.d.ts +1 -1
- package/dist/src/server/sqlite-schema.js +19 -1
- package/dist/src/server/task-deps.d.ts +32 -0
- package/dist/src/server/task-deps.js +40 -0
- package/dist/src/server/tasks-file-watcher.d.ts +6 -7
- package/dist/src/server/tasks-file-watcher.js +3 -2
- package/dist/src/server/tasks-file.d.ts +2 -1
- package/dist/src/server/tasks-file.js +3 -2
- package/dist/src/server/team-authz.d.ts +1 -1
- package/dist/src/server/team-authz.js +1 -0
- package/dist/src/server/team-operations.d.ts +7 -1
- package/dist/src/server/team-operations.js +81 -19
- package/dist/src/server/webhook-notifier.d.ts +34 -0
- package/dist/src/server/webhook-notifier.js +47 -0
- package/dist/src/server/workflow-cli-policy.d.ts +1 -1
- package/dist/src/server/workflow-cli-policy.js +1 -1
- package/dist/src/server/workflow-output-schema.d.ts +18 -0
- package/dist/src/server/workflow-output-schema.js +41 -0
- package/dist/src/server/workflow-runner.js +12 -2
- package/dist/src/shared/types.d.ts +2 -2
- package/package.json +1 -1
- package/web/dist/assets/{AddWorkerDialog-CcC-7kgG.js → AddWorkerDialog-BRUxpa3f.js} +2 -2
- package/web/dist/assets/{AddWorkspaceDialog-BDpOTfmt.js → AddWorkspaceDialog-D56x5JCb.js} +1 -1
- package/web/dist/assets/{FirstRunWizard-BYX_ocQn.js → FirstRunWizard-BFVaMIsE.js} +1 -1
- package/web/dist/assets/{MarketplaceDrawer-DUxSk7db.js → MarketplaceDrawer-DeEZ35dN.js} +1 -1
- package/web/dist/assets/{WhatsNewDialog-B_RlCXcV.js → WhatsNewDialog-CHkZeINH.js} +1 -1
- package/web/dist/assets/{WorkerModal-D9-7YfZZ.js → WorkerModal-BBCuMLIa.js} +1 -1
- package/web/dist/assets/{WorkspaceTaskDrawer-BCKoF7qc.js → WorkspaceTaskDrawer-CpZHAcj1.js} +1 -1
- package/web/dist/assets/WorkspaceTerminalPanels-7If2mDyp.js +1 -0
- package/web/dist/assets/index-5zh61jMg.css +1 -0
- package/web/dist/assets/index-CxNL0O-C.js +73 -0
- package/web/dist/cli-icons/hermes.png +0 -0
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +1 -1
- package/web/dist/assets/WorkspaceTerminalPanels-Dq8y91t2.js +0 -1
- package/web/dist/assets/index-BiOvKIVw.css +0 -1
- package/web/dist/assets/index-DMRUklT3.js +0 -73
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 1.7.0 - 2026-06-05
|
|
6
|
+
|
|
7
|
+
Hermes joins the roster.
|
|
8
|
+
|
|
9
|
+
- Adds Hermes as a fifth built-in CLI agent preset alongside Claude Code,
|
|
10
|
+
Codex, OpenCode, and Gemini: available as an Orchestrator or Worker, in
|
|
11
|
+
`team spawn --cli hermes`, and in the workflow CLI allowlist.
|
|
12
|
+
- Hermes runs YOLO via `--yolo` and resumes sessions via
|
|
13
|
+
`--resume <session_id>`; crash recovery (Layer A) captures its session id
|
|
14
|
+
from the CLI's own startup output through a new stdout-based capture
|
|
15
|
+
source.
|
|
16
|
+
- Existing installs pick the preset up automatically via a database
|
|
17
|
+
migration — no manual setup beyond having `hermes` on your PATH.
|
|
18
|
+
|
|
19
|
+
## 1.6.0 - 2026-06-02
|
|
20
|
+
|
|
21
|
+
Orchestrator controls, worker visibility, and protocol-trust fixes.
|
|
22
|
+
|
|
23
|
+
- Adds a Stop control to the running Orchestrator pane so a runaway Orchestrator
|
|
24
|
+
can be halted from the UI (the default is auto-approve, so this is the only
|
|
25
|
+
in-UI kill switch).
|
|
26
|
+
- Surfaces per-worker queue depth and a latest-activity line on worker cards,
|
|
27
|
+
with a legend on the working badge clarifying that Hive does not auto-detect
|
|
28
|
+
stalls — the terminal is the source of truth.
|
|
29
|
+
- Redelivers worker reports the Orchestrator missed: a report is no longer
|
|
30
|
+
silently lost when the Orchestrator is down or restarting; it is queued and
|
|
31
|
+
redelivered on the next report or `team list`.
|
|
32
|
+
- Stops injecting the crash-recovery handover after a deliberate Stop and
|
|
33
|
+
Restart, so the Orchestrator is not handed stale open tasks it was meant to
|
|
34
|
+
drop.
|
|
35
|
+
- Adds an outbound completion webhook setting: Hive POSTs a small JSON payload
|
|
36
|
+
to a URL you choose when a worker reports or a workflow finishes — wire it to
|
|
37
|
+
Slack, ntfy, Feishu, and the like.
|
|
38
|
+
- Adds opt-in structured output to workflow `agent()` via `outputSchema`, so
|
|
39
|
+
fan-out/verify scripts receive a parsed object instead of parsing free text.
|
|
40
|
+
- Adds `team next`: tasks in `.hive/tasks.md` can carry an optional
|
|
41
|
+
`[needs: #2]` dependency, and `team next` returns the tasks that are unblocked
|
|
42
|
+
now.
|
|
43
|
+
|
|
5
44
|
## 1.5.0 - 2026-05-31
|
|
6
45
|
|
|
7
46
|
Workflow runtime, experimental team automation, and Codex reliability.
|
package/README.en.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
**Hive is a browser-native workbench where a team of agents works together — one orchestrates, the rest execute, all on your laptop.** The orchestrator
|
|
12
|
-
is a real `claude` / `codex` / `opencode` / `gemini` process — not you, and
|
|
12
|
+
is a real `claude` / `codex` / `opencode` / `gemini` / `hermes` process — not you, and
|
|
13
13
|
not a script — and so are the workers it dispatches to. Every agent runs as
|
|
14
14
|
a real PTY on your machine, talks through a small `team` protocol that Hive
|
|
15
15
|
injects into each agent's shell, and shares a markdown task graph at
|
|
@@ -123,6 +123,18 @@ First-run flow:
|
|
|
123
123
|
5. Ask the Orchestrator to delegate work. It sends tasks with
|
|
124
124
|
`team send <worker-name> "<task>"`; workers report back with `team report`.
|
|
125
125
|
|
|
126
|
+
If you want the Orchestrator to size the team itself, leave **Auto-staff**
|
|
127
|
+
enabled (it is on by default). It can `team spawn` the right temporary mix of
|
|
128
|
+
coders, testers, and reviewers for the task, then Hive dismisses those
|
|
129
|
+
temporary workers when their work is done.
|
|
130
|
+
|
|
131
|
+
For stronger automation, enable the experimental **Workflows** toggle in
|
|
132
|
+
settings. The Orchestrator can then author and run multi-agent workflows that
|
|
133
|
+
fan out across implementation, review, testing, or other stages. The topbar
|
|
134
|
+
**Workflows** panel shows runs, phase results, logs, schedules, and stop
|
|
135
|
+
controls. The same panel also lets you choose which CLI workflow-created
|
|
136
|
+
agents use by default and which CLIs they are allowed to use.
|
|
137
|
+
|
|
126
138
|
## How It Works
|
|
127
139
|
|
|
128
140
|
```text
|
|
@@ -164,6 +176,7 @@ Three details matter:
|
|
|
164
176
|
| Codex | `codex` | `--dangerously-bypass-approvals-and-sandbox` | `resume <session_id>` |
|
|
165
177
|
| OpenCode | `opencode` | Config-driven in `~/.config/opencode/opencode.json` | `--session <session_id>` |
|
|
166
178
|
| Gemini | `gemini` | `--yolo` | `--resume <session_id>` |
|
|
179
|
+
| Hermes | `hermes` | `--yolo` | `--resume <session_id>` |
|
|
167
180
|
| Custom | Any executable | User configured | User configured |
|
|
168
181
|
|
|
169
182
|
Hive does not install these CLIs for you. Install and authenticate them in the
|
|
@@ -175,8 +188,17 @@ same shell environment you use to start Hive.
|
|
|
175
188
|
- Orchestrator and worker terminals backed by real PTYs.
|
|
176
189
|
- Add Worker flow with role presets for coder, reviewer, tester, and fully
|
|
177
190
|
custom prompts and commands — wire any CLI agent into the role you need.
|
|
191
|
+
- Auto-staff (experimental, on by default): the Orchestrator can create
|
|
192
|
+
temporary coders, testers, and reviewers based on the task, and Hive cleans
|
|
193
|
+
them up after their dispatch reports back.
|
|
194
|
+
- Workflows (experimental, off by default): the Orchestrator can run
|
|
195
|
+
multi-stage, multi-agent workflows while Hive shows runs, logs, results,
|
|
196
|
+
schedules, and stop controls in the Workflows panel.
|
|
197
|
+
- Workflow CLI policy: choose the default CLI for workflow-created agents and
|
|
198
|
+
restrict which CLIs workflow scripts may launch.
|
|
178
199
|
- `.hive/tasks.md` editor with external-file conflict handling.
|
|
179
200
|
- Background PTY preservation and best-effort native session resume.
|
|
201
|
+
- A What's New dialog after upgrades with curated release highlights.
|
|
180
202
|
- Local SQLite metadata under `~/.config/hive` by default, or `$HIVE_DATA_DIR`
|
|
181
203
|
when set.
|
|
182
204
|
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<img src="./assets/hive-hero.png" alt="Hive 本机多 agent 协作工作台" />
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
-
**Hive 是浏览器里的 Agent 协作工作台——一群 Agent 在你本机各自开工,一个当 Orchestrator 派活、归总进展,其余各司其职。** Orchestrator 本身就是一个真实的 `claude` / `codex` / `opencode` / `gemini` 进程——不是你、也不是脚本——它派单的 Worker 同样是真 CLI agent。所有 agent 都是本机真实的 PTY 进程,通过 Hive 注入到 shell 里的小型 `team` 协议互相通信,共享 `<workspace>/.hive/tasks.md` 这份 markdown 任务图。
|
|
11
|
+
**Hive 是浏览器里的 Agent 协作工作台——一群 Agent 在你本机各自开工,一个当 Orchestrator 派活、归总进展,其余各司其职。** Orchestrator 本身就是一个真实的 `claude` / `codex` / `opencode` / `gemini` / `hermes` 进程——不是你、也不是脚本——它派单的 Worker 同样是真 CLI agent。所有 agent 都是本机真实的 PTY 进程,通过 Hive 注入到 shell 里的小型 `team` 协议互相通信,共享 `<workspace>/.hive/tasks.md` 这份 markdown 任务图。
|
|
12
12
|
|
|
13
13
|
写代码、做调研、起草文档、做翻译——凡是能拆给一群人协作的脑力活,都可以让一群 Agent 合伙干。
|
|
14
14
|
|
|
@@ -84,6 +84,10 @@ PWA 只是 UI 壳,Hive 后端仍需要在终端里跑着。如果启动 PWA
|
|
|
84
84
|
4. 在 Team Members 面板里添加 Worker。
|
|
85
85
|
5. 跟 Orchestrator 说一声让它派活,它会用 `team send <worker-name> "<task>"` 发任务,Worker 完事后用 `team report` 回报。
|
|
86
86
|
|
|
87
|
+
想让 Orchestrator 自己决定团队规模,可以保留 **自动组队** 开关开启(默认开启):它会按任务需要临时 `team spawn` 合适数量的 coder / tester / reviewer,任务结束后自动收回临时成员。
|
|
88
|
+
|
|
89
|
+
想试更强的自动化,可以在右上角设置里开启实验性的 **Workflow** 开关。开启后,Orchestrator 可以编写并运行多 agent workflow,把一个目标拆成 fan-out / review / test 等阶段;顶部的 **Workflows** 面板会显示运行记录、阶段结果、定时任务和停止按钮。Workflow 创建的新 agent 默认使用哪种 CLI、允许使用哪些 CLI,也可以在 Workflows 面板里配置。
|
|
90
|
+
|
|
87
91
|
## 工作方式
|
|
88
92
|
|
|
89
93
|
```text
|
|
@@ -122,6 +126,7 @@ Workspace 任务图:
|
|
|
122
126
|
| Codex | `codex` | `--dangerously-bypass-approvals-and-sandbox` | `resume <session_id>` |
|
|
123
127
|
| OpenCode | `opencode` | 由 `~/.config/opencode/opencode.json` 配置 | `--session <session_id>` |
|
|
124
128
|
| Gemini | `gemini` | `--yolo` | `--resume <session_id>` |
|
|
129
|
+
| Hermes | `hermes` | `--yolo` | `--resume <session_id>` |
|
|
125
130
|
| 自定义 | 任意可执行文件 | 自己配 | 自己配 |
|
|
126
131
|
|
|
127
132
|
Hive 不替你安装这些 CLI。请在启动 Hive 的同一个 shell 环境里先装好、登录好。
|
|
@@ -131,8 +136,12 @@ Hive 不替你安装这些 CLI。请在启动 Hive 的同一个 shell 环境里
|
|
|
131
136
|
- Workspace 侧边栏,方便在多个本机项目之间切换。
|
|
132
137
|
- Orchestrator 和 Worker 终端都是真实 PTY 支撑的。
|
|
133
138
|
- Add Worker 预置 coder / reviewer / tester 等角色模板,也支持完全自定义 prompt 与命令——把任何 CLI agent 编排成你需要的角色。
|
|
139
|
+
- 自动组队(实验性,默认开启):Orchestrator 可以根据任务动态创建临时 coder / tester / reviewer,完成后自动回收。
|
|
140
|
+
- Workflows(实验性,默认关闭):Orchestrator 可以运行多阶段、多 agent 的 workflow,Hive 在 Workflows 面板里展示运行、日志、结果、定时任务和停止控制。
|
|
141
|
+
- Workflow CLI 策略:为 workflow 创建的 agent 选择默认 CLI,并限制允许使用的 CLI,避免脚本误启未配置的 agent。
|
|
134
142
|
- `.hive/tasks.md` 编辑器,带外部文件冲突处理。
|
|
135
143
|
- PTY 后台保留 + 尽力使用各 CLI 原生 session 恢复。
|
|
144
|
+
- 升级后的 What's New 弹窗,用简短 release highlights 告诉你新版改了什么。
|
|
136
145
|
- 元数据存在本机 SQLite,默认在 `~/.config/hive`,或者通过 `$HIVE_DATA_DIR` 指定。
|
|
137
146
|
|
|
138
147
|
Hive **不**提供 sandbox 隔离、多用户认证、云端托管,也不自带任何 agent 模型。它只负责调度你已经在用的本机 CLI。
|
package/dist/src/cli/team.js
CHANGED
|
@@ -9,8 +9,9 @@ const REQUIRED_ENV_KEYS = [
|
|
|
9
9
|
const TEAM_USAGE = [
|
|
10
10
|
'Usage:',
|
|
11
11
|
' team list',
|
|
12
|
+
' team next (tasks in .hive/tasks.md that are unblocked now — those whose [needs: #n] deps are all done)',
|
|
12
13
|
' team send <worker-name> "<task>"',
|
|
13
|
-
' team spawn <role> [--name <name>] [--cli <claude|codex|opencode|gemini>] [--ephemeral]',
|
|
14
|
+
' team spawn <role> [--name <name>] [--cli <claude|codex|opencode|gemini|hermes>] [--ephemeral]',
|
|
14
15
|
' team dismiss <worker-name>',
|
|
15
16
|
" team workflow run --stdin [--args '<JSON>'] (script from stdin — for multi-line scripts)",
|
|
16
17
|
' team workflow run --inline "<source>" [--args \'<JSON>\']',
|
|
@@ -243,6 +244,22 @@ export const runTeamCommand = async (argv) => {
|
|
|
243
244
|
console.log(JSON.stringify(await response.json()));
|
|
244
245
|
return;
|
|
245
246
|
}
|
|
247
|
+
if (command === 'next') {
|
|
248
|
+
const env = getHiveEnv();
|
|
249
|
+
const baseUrl = getBaseUrl(env);
|
|
250
|
+
const response = await fetchRuntime(baseUrl, `/api/workspaces/${env.HIVE_PROJECT_ID}/tasks/next`, {
|
|
251
|
+
method: 'GET',
|
|
252
|
+
headers: {
|
|
253
|
+
'x-hive-agent-id': env.HIVE_AGENT_ID,
|
|
254
|
+
'x-hive-agent-token': env.HIVE_AGENT_TOKEN,
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
if (!response.ok) {
|
|
258
|
+
await throwHttpError(response);
|
|
259
|
+
}
|
|
260
|
+
console.log(JSON.stringify(await response.json()));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
246
263
|
if (command === 'send') {
|
|
247
264
|
const [workerName, ...taskParts] = args;
|
|
248
265
|
const task = taskParts.join(' ').trim();
|
|
@@ -274,7 +291,7 @@ export const runTeamCommand = async (argv) => {
|
|
|
274
291
|
if (command === 'spawn') {
|
|
275
292
|
const role = args[0];
|
|
276
293
|
if (!role || role.startsWith('--')) {
|
|
277
|
-
throw new Error('Usage: team spawn <role> [--name <name>] [--cli <claude|codex|opencode|gemini>] [--ephemeral]\n' +
|
|
294
|
+
throw new Error('Usage: team spawn <role> [--name <name>] [--cli <claude|codex|opencode|gemini|hermes>] [--ephemeral]\n' +
|
|
278
295
|
' Default: persistent member (lives until you `team dismiss` it).\n' +
|
|
279
296
|
' --ephemeral: auto-dismiss after the next dispatch report (one-shot worker).');
|
|
280
297
|
}
|
|
@@ -60,6 +60,10 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
|
|
|
60
60
|
};
|
|
61
61
|
knownSessionIds: Set<string>;
|
|
62
62
|
root: string;
|
|
63
|
+
} | {
|
|
64
|
+
knownSessionIds: Set<string>;
|
|
65
|
+
env?: never;
|
|
66
|
+
root?: never;
|
|
63
67
|
} | undefined;
|
|
64
68
|
startConfig: AgentLaunchConfigInput;
|
|
65
69
|
startEnv: {
|
|
@@ -69,8 +73,9 @@ export declare const buildAgentRunBootstrap: (workspace: WorkspaceSummary, agent
|
|
|
69
73
|
HIVE_AGENT_TOKEN: string;
|
|
70
74
|
};
|
|
71
75
|
};
|
|
72
|
-
export declare const startAgentRunCapture: ({ agentId, sessionCaptureSnapshot, sessionStore, startConfig, workspace, }: {
|
|
76
|
+
export declare const startAgentRunCapture: ({ agentId, getRunOutput, sessionCaptureSnapshot, sessionStore, startConfig, workspace, }: {
|
|
73
77
|
agentId: string;
|
|
78
|
+
getRunOutput?: () => string | null;
|
|
74
79
|
sessionCaptureSnapshot: SessionCaptureSnapshot | undefined;
|
|
75
80
|
sessionStore: AgentSessionStorePort;
|
|
76
81
|
startConfig: AgentLaunchConfigInput;
|
|
@@ -84,10 +84,13 @@ export const buildAgentRunBootstrap = (workspace, agentId, config, sessionStore,
|
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
|
-
export const startAgentRunCapture = ({ agentId, sessionCaptureSnapshot, sessionStore, startConfig, workspace, }) => {
|
|
87
|
+
export const startAgentRunCapture = ({ agentId, getRunOutput, sessionCaptureSnapshot, sessionStore, startConfig, workspace, }) => {
|
|
88
88
|
if (!sessionCaptureSnapshot || !startConfig.sessionIdCapture)
|
|
89
89
|
return;
|
|
90
|
-
|
|
90
|
+
const captureSnapshot = startConfig.sessionIdCapture.source === 'stdout_regex' && getRunOutput
|
|
91
|
+
? { ...sessionCaptureSnapshot, getOutput: getRunOutput }
|
|
92
|
+
: sessionCaptureSnapshot;
|
|
93
|
+
void captureSessionIdForCapture(workspace.path, startConfig.sessionIdCapture, captureSnapshot, (sessionId) => {
|
|
91
94
|
sessionStore.setLastSessionId(workspace.id, agentId, sessionId);
|
|
92
95
|
}, SESSION_CAPTURE_TIMEOUT_MS);
|
|
93
96
|
};
|
|
@@ -6,6 +6,7 @@ import type { AgentSessionStorePort } from './agent-runtime-ports.js';
|
|
|
6
6
|
import type { LiveAgentRun } from './agent-runtime-types.js';
|
|
7
7
|
import type { AgentTokenRegistry } from './agent-tokens.js';
|
|
8
8
|
import type { CommandPresetRecord } from './command-preset-store.js';
|
|
9
|
+
import { type FeatureFlags } from './feature-flags.js';
|
|
9
10
|
import type { LiveRunRegistry } from './live-run-registry.js';
|
|
10
11
|
import type { RestartPolicy } from './restart-policy.js';
|
|
11
12
|
interface AgentRunStarterInput {
|
|
@@ -18,12 +19,10 @@ interface AgentRunStarterInput {
|
|
|
18
19
|
getCommandPreset: (id: string) => CommandPresetRecord | undefined;
|
|
19
20
|
getAgent: ((workspaceId: string, agentId: string) => AgentSummary | undefined) | undefined;
|
|
20
21
|
restartPolicy: RestartPolicy;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* in the orchestrator's startup prompt. */
|
|
26
|
-
getAutostaffEnabled?: () => boolean;
|
|
22
|
+
/** Resolves the live experimental flags for the orchestrator's startup
|
|
23
|
+
* prompt (`workflowsEnabled` gates the `team workflow` line + authoring
|
|
24
|
+
* rule; `autostaffEnabled` gates the team-sizing rule). */
|
|
25
|
+
getFlags?: () => FeatureFlags;
|
|
27
26
|
}
|
|
28
|
-
export declare const createAgentRunStarter: ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy,
|
|
27
|
+
export declare const createAgentRunStarter: ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, }: AgentRunStarterInput) => (workspace: WorkspaceSummary, agentId: string, config: AgentLaunchConfigInput, hivePort: string) => Promise<LiveAgentRun>;
|
|
29
28
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { buildAgentRunBootstrap, startAgentRunCapture } from './agent-run-bootstrap.js';
|
|
2
2
|
import { handleAgentRunExit } from './agent-run-exit-handler.js';
|
|
3
3
|
import { buildAgentStartupInstructions } from './agent-startup-instructions.js';
|
|
4
|
+
import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
|
|
4
5
|
import { createPostStartInputWriter, isInteractiveAgentCommand } from './post-start-input-writer.js';
|
|
5
|
-
export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy,
|
|
6
|
+
export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, store, sessionStore, tokenRegistry, getCommandPreset, getAgent, restartPolicy, getFlags, }) => async (workspace, agentId, config, hivePort) => {
|
|
6
7
|
if (!agentManager)
|
|
7
8
|
throw new Error('Agent manager is required to start agents');
|
|
8
9
|
const agent = getAgent?.(workspace.id, agentId);
|
|
@@ -84,7 +85,21 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
|
|
|
84
85
|
registry.clearPendingExitCode(run.runId);
|
|
85
86
|
return liveRun;
|
|
86
87
|
}
|
|
87
|
-
startAgentRunCapture({
|
|
88
|
+
startAgentRunCapture({
|
|
89
|
+
agentId,
|
|
90
|
+
getRunOutput: () => {
|
|
91
|
+
try {
|
|
92
|
+
return agentManager.getRun(run.runId).output;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
sessionCaptureSnapshot,
|
|
99
|
+
sessionStore,
|
|
100
|
+
startConfig,
|
|
101
|
+
workspace,
|
|
102
|
+
});
|
|
88
103
|
const postStartWriter = createPostStartInputWriter(agentManager, startConfig.interactiveCommand ?? startConfig.command);
|
|
89
104
|
queueMicrotask(() => {
|
|
90
105
|
try {
|
|
@@ -102,8 +117,7 @@ export const createAgentRunStarter = ({ agentManager, registry, onAgentExit, sto
|
|
|
102
117
|
void postStartWriter(run.runId, buildAgentStartupInstructions({
|
|
103
118
|
agent,
|
|
104
119
|
workspace,
|
|
105
|
-
|
|
106
|
-
autostaffEnabled: getAutostaffEnabled?.() ?? false,
|
|
120
|
+
flags: getFlags?.() ?? FEATURE_FLAGS_ALL_OFF,
|
|
107
121
|
})).catch(() => {
|
|
108
122
|
// The agent may have exited before post-start guidance could be written.
|
|
109
123
|
});
|
|
@@ -34,5 +34,15 @@ export interface AgentRuntime {
|
|
|
34
34
|
}) => void;
|
|
35
35
|
writeUserInputPrompt: (workspaceId: string, text: string) => void;
|
|
36
36
|
writeSystemMessageToAgent: (workspaceId: string, agentId: string, text: string) => void;
|
|
37
|
+
/** Awaitable report delivery — rejects if the orchestrator PTY write fails,
|
|
38
|
+
* so the caller can persist the report to the redelivery outbox. */
|
|
39
|
+
deliverReportToOrchestrator: (workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
40
|
+
requireActiveRun?: boolean;
|
|
41
|
+
}) => Promise<void>;
|
|
42
|
+
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
43
|
+
* is marked delivered only after the PTY write resolves. */
|
|
44
|
+
deliverSystemMessageToAgent: (workspaceId: string, agentId: string, text: string, input?: {
|
|
45
|
+
requireActiveRun?: boolean;
|
|
46
|
+
}) => Promise<void>;
|
|
37
47
|
}
|
|
38
48
|
export type { StartAgentOptions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { AgentManager } from './agent-manager.js';
|
|
2
2
|
import type { LiveAgentRun } from './agent-runtime-types.js';
|
|
3
3
|
import type { LiveRunRegistry } from './live-run-registry.js';
|
|
4
|
-
export declare const stopLiveRun: (agentManager: AgentManager | undefined, registry: LiveRunRegistry, syncRun: (run: LiveAgentRun) => LiveAgentRun, runId: string) => void;
|
|
4
|
+
export declare const stopLiveRun: (agentManager: AgentManager | undefined, registry: LiveRunRegistry, syncRun: (run: LiveAgentRun) => LiveAgentRun, runId: string, onUserStop?: (runId: string) => void) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const stopLiveRun = (agentManager, registry, syncRun, runId) => {
|
|
1
|
+
export const stopLiveRun = (agentManager, registry, syncRun, runId, onUserStop) => {
|
|
2
2
|
if (!agentManager) {
|
|
3
3
|
throw new Error('Agent manager is required to stop agents');
|
|
4
4
|
}
|
|
@@ -12,5 +12,8 @@ export const stopLiveRun = (agentManager, registry, syncRun, runId) => {
|
|
|
12
12
|
else if (['error', 'exited'].includes(agentManager.getRun(runId).status)) {
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
|
+
// Reaching here means the run was genuinely live and we are about to kill it
|
|
16
|
+
// at the user's request — distinct from a crash that already ended the run.
|
|
17
|
+
onUserStop?.(runId);
|
|
15
18
|
agentManager.stopRun(runId);
|
|
16
19
|
};
|
|
@@ -3,6 +3,7 @@ import type { AgentManager } from './agent-manager.js';
|
|
|
3
3
|
import type { AgentRuntime } from './agent-runtime-contract.js';
|
|
4
4
|
import type { AgentRunStorePort, AgentSessionStorePort } from './agent-runtime-ports.js';
|
|
5
5
|
import type { CommandPresetRecord } from './command-preset-store.js';
|
|
6
|
+
import type { FeatureFlags } from './feature-flags.js';
|
|
6
7
|
import { type RestartPolicy } from './restart-policy.js';
|
|
7
|
-
export declare const createAgentRuntime: (agentManager: AgentManager | undefined, agentRunStore: AgentRunStorePort, sessionStore: AgentSessionStorePort, getCommandPreset: (id: string) => CommandPresetRecord | undefined, onAgentExit: (workspaceId: string, agentId: string) => void, restartPolicy?: RestartPolicy, getAgent?: (workspaceId: string, agentId: string) => AgentSummary | undefined,
|
|
8
|
+
export declare const createAgentRuntime: (agentManager: AgentManager | undefined, agentRunStore: AgentRunStorePort, sessionStore: AgentSessionStorePort, getCommandPreset: (id: string) => CommandPresetRecord | undefined, onAgentExit: (workspaceId: string, agentId: string) => void, restartPolicy?: RestartPolicy, getAgent?: (workspaceId: string, agentId: string) => AgentSummary | undefined, getFlags?: () => FeatureFlags) => AgentRuntime;
|
|
8
9
|
export type { AgentRuntime };
|
|
@@ -10,7 +10,7 @@ import { createAgentStdinDispatcher } from './agent-stdin-dispatcher.js';
|
|
|
10
10
|
import { createAgentTokenRegistry } from './agent-tokens.js';
|
|
11
11
|
import { createLiveRunRegistry } from './live-run-registry.js';
|
|
12
12
|
import { createNoopRestartPolicy } from './restart-policy.js';
|
|
13
|
-
export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, getCommandPreset, onAgentExit, restartPolicy = createNoopRestartPolicy(), getAgent,
|
|
13
|
+
export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, getCommandPreset, onAgentExit, restartPolicy = createNoopRestartPolicy(), getAgent, getFlags) => {
|
|
14
14
|
const registry = createLiveRunRegistry();
|
|
15
15
|
const launchCache = createAgentLaunchCache(agentRunStore);
|
|
16
16
|
const tokenRegistry = createAgentTokenRegistry();
|
|
@@ -29,7 +29,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
29
29
|
getWorkspaceId: launchCache.getWorkspaceId,
|
|
30
30
|
registry,
|
|
31
31
|
syncRun,
|
|
32
|
-
...(
|
|
32
|
+
...(getFlags ? { getFlags } : {}),
|
|
33
33
|
});
|
|
34
34
|
const startLiveRun = createAgentRunStarter({
|
|
35
35
|
agentManager,
|
|
@@ -41,8 +41,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
41
41
|
getCommandPreset,
|
|
42
42
|
getAgent,
|
|
43
43
|
restartPolicy,
|
|
44
|
-
...(
|
|
45
|
-
...(getAutostaffEnabled ? { getAutostaffEnabled } : {}),
|
|
44
|
+
...(getFlags ? { getFlags } : {}),
|
|
46
45
|
});
|
|
47
46
|
return {
|
|
48
47
|
async close() {
|
|
@@ -106,7 +105,7 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
106
105
|
return startPromise;
|
|
107
106
|
},
|
|
108
107
|
stopAgentRun(runId) {
|
|
109
|
-
stopLiveRun(agentManager, registry, syncRun, runId);
|
|
108
|
+
stopLiveRun(agentManager, registry, syncRun, runId, (stoppedRunId) => restartPolicy.markUserStopped(stoppedRunId));
|
|
110
109
|
},
|
|
111
110
|
validateAgentToken: tokenRegistry.validate,
|
|
112
111
|
writeReportPrompt(workspaceId, workerName, _workerId, text, artifacts, input = {}) {
|
|
@@ -127,5 +126,11 @@ export const createAgentRuntime = (agentManager, agentRunStore, sessionStore, ge
|
|
|
127
126
|
writeSystemMessageToAgent(workspaceId, agentId, text) {
|
|
128
127
|
stdinDispatcher.writeSystemMessageToAgent(workspaceId, agentId, text);
|
|
129
128
|
},
|
|
129
|
+
deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input = {}) {
|
|
130
|
+
return stdinDispatcher.deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input);
|
|
131
|
+
},
|
|
132
|
+
deliverSystemMessageToAgent(workspaceId, agentId, text, input = {}) {
|
|
133
|
+
return stdinDispatcher.deliverSystemMessageToAgent(workspaceId, agentId, text, input);
|
|
134
|
+
},
|
|
130
135
|
};
|
|
131
136
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentSummary, WorkspaceSummary } from '../shared/types.js';
|
|
2
|
+
import { type FeatureFlags } from './feature-flags.js';
|
|
2
3
|
export declare const buildAgentSessionBindingMarker: ({ agent, workspace, }: {
|
|
3
4
|
agent: AgentSummary;
|
|
4
5
|
workspace: WorkspaceSummary;
|
|
@@ -7,14 +8,12 @@ export declare const buildAgentLegacyIdentityMarker: ({ agent, workspace, }: {
|
|
|
7
8
|
agent: AgentSummary;
|
|
8
9
|
workspace: WorkspaceSummary;
|
|
9
10
|
}) => string;
|
|
10
|
-
export declare const buildAgentStartupInstructions: ({ agent, workspace,
|
|
11
|
+
export declare const buildAgentStartupInstructions: ({ agent, workspace, flags, }: {
|
|
11
12
|
agent: AgentSummary;
|
|
12
13
|
workspace: WorkspaceSummary;
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
* told it may size the team to the task up front. */
|
|
19
|
-
autostaffEnabled?: boolean;
|
|
14
|
+
/** Live experimental flags. `workflowsEnabled` gates the `team workflow`
|
|
15
|
+
* command line + the workflow-authoring rule (so a fresh orchestrator isn't
|
|
16
|
+
* told to run a command the runtime rejects); `autostaffEnabled` gates the
|
|
17
|
+
* team-sizing rule. Omitted → all off. */
|
|
18
|
+
flags?: FeatureFlags;
|
|
20
19
|
}) => string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
|
|
1
2
|
import { getHiveTeamRules } from './hive-team-guidance.js';
|
|
2
3
|
import { TASKS_RELATIVE_PATH } from './tasks-file.js';
|
|
3
4
|
export const buildAgentSessionBindingMarker = ({ agent, workspace, }) => `Hive session binding: workspace_id=${workspace.id}; agent_id=${agent.id}`;
|
|
4
5
|
export const buildAgentLegacyIdentityMarker = ({ agent, workspace, }) => `You are ${agent.name} (${agent.role}) in workspace ${workspace.name}.`;
|
|
5
|
-
export const buildAgentStartupInstructions = ({ agent, workspace,
|
|
6
|
+
export const buildAgentStartupInstructions = ({ agent, workspace, flags = FEATURE_FLAGS_ALL_OFF, }) => {
|
|
7
|
+
const { workflowsEnabled } = flags;
|
|
6
8
|
const lines = [
|
|
7
9
|
'<hive-message kind="startup">',
|
|
8
10
|
'',
|
|
@@ -17,14 +19,14 @@ export const buildAgentStartupInstructions = ({ agent, workspace, workflowsEnabl
|
|
|
17
19
|
'',
|
|
18
20
|
];
|
|
19
21
|
if (agent.role === 'orchestrator') {
|
|
20
|
-
lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH}`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team send "<worker-name>" "<task>"', '- team spawn <role> [--name <n>] [--cli claude|codex|opencode|gemini] [--ephemeral]', '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
|
|
22
|
+
lines.push('Your responsibilities:', '- Respond to the user directly; clarify the goal and break it into dispatchable tasks', `- Maintain ${TASKS_RELATIVE_PATH}`, '- Dispatch by worker name and drive the next step from each report', '', 'Available team commands:', '- team list', '- team send "<worker-name>" "<task>"', '- team spawn <role> [--name <n>] [--cli claude|codex|opencode|gemini|hermes] [--ephemeral]', '- team cancel --dispatch <id> "<reason>"', ...(workflowsEnabled
|
|
21
23
|
? [
|
|
22
24
|
'- team workflow run --stdin (fan-out / staged work — see .hive/PROTOCOL.md for the DSL)',
|
|
23
25
|
]
|
|
24
|
-
: []), '', 'Always dispatch by worker name, never by worker id.', 'Always cancel an open dispatch by its dispatch id.', '', 'Hive worker dispatch rules:', ...getHiveTeamRules(agent,
|
|
26
|
+
: []), '', 'Always dispatch by worker name, never by worker id.', 'Always cancel an open dispatch by its dispatch id.', '', 'Hive worker dispatch rules:', ...getHiveTeamRules(agent, flags));
|
|
25
27
|
}
|
|
26
28
|
else {
|
|
27
|
-
lines.push('Available team commands:', '- team report "<result>" [--dispatch <id>] [--artifact <path>] report done / failed / blocked', '- team report --stdin [--dispatch <id>] [--artifact <path>] same, body read from stdin (multi-line / quotes / special chars)', '- team status "<state>" [--artifact <path>] mid-task progress / standby / connected status', '- team status --stdin [--artifact <path>] same, body read from stdin', '- team list list the workspace workers (with status)', '- team --help command syntax only; NOT a way to report', '', 'Syntax notes:', '- The body is the first positional argument; flag order is free: `team report "result" --dispatch X` and `team report --dispatch X "result"` are both valid.', "- Long bodies (multi-line / quotes / shell metacharacters) always go through `--stdin`, piped in via your shell (POSIX: a quoted heredoc `<<'EOF' … EOF` to stop $var / backtick expansion; Windows cmd: `type body.txt |` or `< body.txt`). `--stdin` only reads from stdin and relies on no shell syntax of its own.", '- On error the CLI also prints USAGE — fix the arguments against it.', '', 'When a task is done you MUST run `team report "<result>"`.', 'Failure, blocked, or partial completion are also reported with `team report "<current state and reason>"`.', 'When no task is in progress, report connection / standby / blocked state with `team status "<state>"`.', 'Do not call team send; workers cannot dispatch to each other.', '', 'Hive worker boundaries:', ...getHiveTeamRules(agent,
|
|
29
|
+
lines.push('Available team commands:', '- team report "<result>" [--dispatch <id>] [--artifact <path>] report done / failed / blocked', '- team report --stdin [--dispatch <id>] [--artifact <path>] same, body read from stdin (multi-line / quotes / special chars)', '- team status "<state>" [--artifact <path>] mid-task progress / standby / connected status', '- team status --stdin [--artifact <path>] same, body read from stdin', '- team list list the workspace workers (with status)', '- team --help command syntax only; NOT a way to report', '', 'Syntax notes:', '- The body is the first positional argument; flag order is free: `team report "result" --dispatch X` and `team report --dispatch X "result"` are both valid.', "- Long bodies (multi-line / quotes / shell metacharacters) always go through `--stdin`, piped in via your shell (POSIX: a quoted heredoc `<<'EOF' … EOF` to stop $var / backtick expansion; Windows cmd: `type body.txt |` or `< body.txt`). `--stdin` only reads from stdin and relies on no shell syntax of its own.", '- On error the CLI also prints USAGE — fix the arguments against it.', '', 'When a task is done you MUST run `team report "<result>"`.', 'Failure, blocked, or partial completion are also reported with `team report "<current state and reason>"`.', 'When no task is in progress, report connection / standby / blocked state with `team status "<state>"`.', 'Do not call team send; workers cannot dispatch to each other.', '', 'Hive worker boundaries:', ...getHiveTeamRules(agent, flags));
|
|
28
30
|
}
|
|
29
31
|
lines.push('', '</hive-message>', '');
|
|
30
32
|
return lines.join('\n');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentManager } from './agent-manager.js';
|
|
2
2
|
import type { AgentLaunchConfigInput } from './agent-run-store.js';
|
|
3
3
|
import type { LiveAgentRun } from './agent-runtime-types.js';
|
|
4
|
+
import { type FeatureFlags } from './feature-flags.js';
|
|
4
5
|
import type { LiveRunRegistry } from './live-run-registry.js';
|
|
5
6
|
interface AgentStdinDispatcherInput {
|
|
6
7
|
agentManager: AgentManager | undefined;
|
|
@@ -8,16 +9,17 @@ interface AgentStdinDispatcherInput {
|
|
|
8
9
|
getWorkspaceId: (agentId: string) => string | undefined;
|
|
9
10
|
registry: LiveRunRegistry;
|
|
10
11
|
syncRun: (run: LiveAgentRun) => LiveAgentRun;
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
|
|
12
|
+
/** Resolves the live experimental flags. The orchestrator reminder tail
|
|
13
|
+
* appended to every injected message reads `workflowsEnabled` from it.
|
|
14
|
+
* Optional; omitted → all flags off. */
|
|
15
|
+
getFlags?: () => FeatureFlags;
|
|
14
16
|
}
|
|
15
|
-
export declare const buildOrchestratorReportPayload: (workerName: string, text: string, artifacts: string[],
|
|
16
|
-
export declare const buildOrchestratorStatusPayload: (workerName: string, text: string, artifacts: string[],
|
|
17
|
-
export declare const buildOrchestratorUserInputPayload: (text: string,
|
|
17
|
+
export declare const buildOrchestratorReportPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
|
|
18
|
+
export declare const buildOrchestratorStatusPayload: (workerName: string, text: string, artifacts: string[], flags?: FeatureFlags) => string;
|
|
19
|
+
export declare const buildOrchestratorUserInputPayload: (text: string, flags?: FeatureFlags) => string;
|
|
18
20
|
export declare const buildWorkerDispatchPayload: (fromAgentName: string, workerDescription: string, dispatchId: string, text: string) => string;
|
|
19
21
|
export declare const buildWorkerCancelPayload: (dispatchId: string, reason: string) => string;
|
|
20
|
-
export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun,
|
|
22
|
+
export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, getFlags, }: AgentStdinDispatcherInput) => {
|
|
21
23
|
writeReportPrompt(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
22
24
|
requireActiveRun?: boolean;
|
|
23
25
|
}): void;
|
|
@@ -33,5 +35,16 @@ export declare const createAgentStdinDispatcher: ({ agentManager, getLaunchConfi
|
|
|
33
35
|
* Used by the workflow runner to notify the triggering orchestrator
|
|
34
36
|
* when a run finishes (mirrors Claude Code's <task-notification>). */
|
|
35
37
|
writeSystemMessageToAgent(workspaceId: string, agentId: string, text: string): void;
|
|
38
|
+
/** Awaitable report delivery — same payload as writeReportPrompt but the
|
|
39
|
+
* promise is returned so the caller can persist the report to the
|
|
40
|
+
* redelivery outbox if the orchestrator PTY write rejects. */
|
|
41
|
+
deliverReportToOrchestrator(workspaceId: string, workerName: string, text: string, artifacts: string[], input?: {
|
|
42
|
+
requireActiveRun?: boolean;
|
|
43
|
+
}): Promise<void>;
|
|
44
|
+
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
45
|
+
* is marked delivered only after the PTY write actually resolves. */
|
|
46
|
+
deliverSystemMessageToAgent(workspaceId: string, agentId: string, text: string, input?: {
|
|
47
|
+
requireActiveRun?: boolean;
|
|
48
|
+
}): Promise<void>;
|
|
36
49
|
};
|
|
37
50
|
export {};
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
+
import { FEATURE_FLAGS_ALL_OFF } from './feature-flags.js';
|
|
1
2
|
import { buildOrchestratorReminderTail, buildWorkerReminderTail } from './hive-team-guidance.js';
|
|
2
3
|
import { PtyInactiveError } from './http-errors.js';
|
|
3
4
|
import { createPostStartInputWriter } from './post-start-input-writer.js';
|
|
4
|
-
export const buildOrchestratorReportPayload = (workerName, text, artifacts,
|
|
5
|
+
export const buildOrchestratorReportPayload = (workerName, text, artifacts, flags = FEATURE_FLAGS_ALL_OFF) => {
|
|
5
6
|
const lines = [`<hive-message kind="report" from="@${workerName}">`, text];
|
|
6
7
|
for (const artifact of artifacts)
|
|
7
8
|
lines.push(`artifact: ${artifact}`);
|
|
8
|
-
lines.push('</hive-message>', '', buildOrchestratorReminderTail(
|
|
9
|
+
lines.push('</hive-message>', '', buildOrchestratorReminderTail(flags), '');
|
|
9
10
|
return lines.join('\n');
|
|
10
11
|
};
|
|
11
|
-
export const buildOrchestratorStatusPayload = (workerName, text, artifacts,
|
|
12
|
+
export const buildOrchestratorStatusPayload = (workerName, text, artifacts, flags = FEATURE_FLAGS_ALL_OFF) => {
|
|
12
13
|
const lines = [`<hive-message kind="status" from="@${workerName}">`, text];
|
|
13
14
|
for (const artifact of artifacts)
|
|
14
15
|
lines.push(`artifact: ${artifact}`);
|
|
15
|
-
lines.push('</hive-message>', '', buildOrchestratorReminderTail(
|
|
16
|
+
lines.push('</hive-message>', '', buildOrchestratorReminderTail(flags), '');
|
|
16
17
|
return lines.join('\n');
|
|
17
18
|
};
|
|
18
|
-
export const buildOrchestratorUserInputPayload = (text,
|
|
19
|
+
export const buildOrchestratorUserInputPayload = (text, flags = FEATURE_FLAGS_ALL_OFF) => [text, '', buildOrchestratorReminderTail(flags), ''].join('\n');
|
|
19
20
|
export const buildWorkerDispatchPayload = (fromAgentName, workerDescription, dispatchId, text) => [
|
|
20
21
|
`<hive-message kind="dispatch" from="@${fromAgentName}">`,
|
|
21
22
|
'',
|
|
@@ -44,8 +45,8 @@ export const buildWorkerCancelPayload = (dispatchId, reason) => [
|
|
|
44
45
|
'</hive-message>',
|
|
45
46
|
'',
|
|
46
47
|
].join('\n');
|
|
47
|
-
export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun,
|
|
48
|
-
const
|
|
48
|
+
export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getWorkspaceId, registry, syncRun, getFlags, }) => {
|
|
49
|
+
const flags = () => getFlags?.() ?? FEATURE_FLAGS_ALL_OFF;
|
|
49
50
|
const chains = new Map();
|
|
50
51
|
const getChain = (agentId) => {
|
|
51
52
|
let chain = chains.get(agentId);
|
|
@@ -156,10 +157,10 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
156
157
|
};
|
|
157
158
|
return {
|
|
158
159
|
writeReportPrompt(workspaceId, workerName, text, artifacts, input = {}) {
|
|
159
|
-
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorReportPayload(workerName, text, artifacts,
|
|
160
|
+
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorReportPayload(workerName, text, artifacts, flags()), input));
|
|
160
161
|
},
|
|
161
162
|
writeStatusPrompt(workspaceId, workerName, text, artifacts, input = {}) {
|
|
162
|
-
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorStatusPayload(workerName, text, artifacts,
|
|
163
|
+
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorStatusPayload(workerName, text, artifacts, flags()), input));
|
|
163
164
|
},
|
|
164
165
|
writeSendPrompt(workspaceId, workerId, dispatchId, fromAgentName, workerDescription, text) {
|
|
165
166
|
return writeToActiveAgentRun(workspaceId, workerId, buildWorkerDispatchPayload(fromAgentName, workerDescription, dispatchId, text), { requireActiveRun: true });
|
|
@@ -168,7 +169,7 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
168
169
|
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, workerId, buildWorkerCancelPayload(dispatchId, reason), input));
|
|
169
170
|
},
|
|
170
171
|
writeUserInputPrompt(workspaceId, text) {
|
|
171
|
-
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorUserInputPayload(text,
|
|
172
|
+
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorUserInputPayload(text, flags())));
|
|
172
173
|
},
|
|
173
174
|
/** Generic: deliver an opaque text block to a specific agent's PTY.
|
|
174
175
|
* Used by the workflow runner to notify the triggering orchestrator
|
|
@@ -176,5 +177,16 @@ export const createAgentStdinDispatcher = ({ agentManager, getLaunchConfig, getW
|
|
|
176
177
|
writeSystemMessageToAgent(workspaceId, agentId, text) {
|
|
177
178
|
swallowQueuedFailure(writeToActiveAgentRun(workspaceId, agentId, text));
|
|
178
179
|
},
|
|
180
|
+
/** Awaitable report delivery — same payload as writeReportPrompt but the
|
|
181
|
+
* promise is returned so the caller can persist the report to the
|
|
182
|
+
* redelivery outbox if the orchestrator PTY write rejects. */
|
|
183
|
+
deliverReportToOrchestrator(workspaceId, workerName, text, artifacts, input = {}) {
|
|
184
|
+
return writeToActiveAgentRun(workspaceId, `${workspaceId}:orchestrator`, buildOrchestratorReportPayload(workerName, text, artifacts, flags()), input);
|
|
185
|
+
},
|
|
186
|
+
/** Awaitable opaque delivery — used to drain the report outbox so an entry
|
|
187
|
+
* is marked delivered only after the PTY write actually resolves. */
|
|
188
|
+
deliverSystemMessageToAgent(workspaceId, agentId, text, input = {}) {
|
|
189
|
+
return writeToActiveAgentRun(workspaceId, agentId, text, input);
|
|
190
|
+
},
|
|
179
191
|
};
|
|
180
192
|
};
|
|
@@ -2,6 +2,7 @@ import { CLAUDE_DEFAULT_YOLO_ARGS } from './claude-command-defaults.js';
|
|
|
2
2
|
const CODEX_DEFAULT_YOLO_ARGS = ['--dangerously-bypass-approvals-and-sandbox'];
|
|
3
3
|
const OPENCODE_DEFAULT_YOLO_ARGS = [];
|
|
4
4
|
const GEMINI_DEFAULT_YOLO_ARGS = ['--yolo'];
|
|
5
|
+
const HERMES_DEFAULT_YOLO_ARGS = ['--yolo'];
|
|
5
6
|
export const BUILTIN_COMMAND_PRESETS = [
|
|
6
7
|
{
|
|
7
8
|
command: 'claude',
|
|
@@ -47,5 +48,16 @@ export const BUILTIN_COMMAND_PRESETS = [
|
|
|
47
48
|
},
|
|
48
49
|
yoloArgsTemplate: GEMINI_DEFAULT_YOLO_ARGS,
|
|
49
50
|
},
|
|
51
|
+
{
|
|
52
|
+
command: 'hermes',
|
|
53
|
+
displayName: 'Hermes',
|
|
54
|
+
id: 'hermes',
|
|
55
|
+
resumeArgsTemplate: '--resume {session_id}',
|
|
56
|
+
sessionIdCapture: {
|
|
57
|
+
pattern: String.raw `Session:\s*([A-Za-z0-9_-]+)`,
|
|
58
|
+
source: 'stdout_regex',
|
|
59
|
+
},
|
|
60
|
+
yoloArgsTemplate: HERMES_DEFAULT_YOLO_ARGS,
|
|
61
|
+
},
|
|
50
62
|
];
|
|
51
63
|
export const getBuiltinCommandPreset = (id) => BUILTIN_COMMAND_PRESETS.find((preset) => preset.id === id);
|