@tt-a1i/hive 1.4.4 → 1.6.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 +47 -0
- package/README.en.md +21 -0
- package/README.md +16 -0
- package/assets/qq-group.jpg +0 -0
- package/dist/bin/team.cmd +1 -0
- package/dist/src/cli/hive-update.d.ts +45 -17
- package/dist/src/cli/hive-update.js +63 -25
- package/dist/src/cli/hive.d.ts +25 -0
- package/dist/src/cli/hive.js +41 -3
- package/dist/src/cli/team.d.ts +1 -0
- package/dist/src/cli/team.js +216 -3
- package/dist/src/server/agent-command-resolver.js +3 -19
- package/dist/src/server/agent-manager-support.d.ts +2 -2
- package/dist/src/server/agent-manager-support.js +98 -24
- package/dist/src/server/agent-run-starter.d.ts +6 -1
- package/dist/src/server/agent-run-starter.js +9 -2
- package/dist/src/server/agent-run-store.d.ts +1 -1
- package/dist/src/server/agent-runtime-close.d.ts +1 -0
- package/dist/src/server/agent-runtime-close.js +25 -1
- package/dist/src/server/agent-runtime-contract.d.ts +12 -1
- 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 +14 -3
- package/dist/src/server/agent-startup-instructions.d.ts +7 -1
- package/dist/src/server/agent-startup-instructions.js +17 -9
- package/dist/src/server/agent-stdin-dispatcher.d.ts +25 -5
- package/dist/src/server/agent-stdin-dispatcher.js +141 -40
- package/dist/src/server/cron-util.d.ts +7 -0
- package/dist/src/server/cron-util.js +19 -0
- package/dist/src/server/dispatch-ledger-store.d.ts +22 -0
- package/dist/src/server/dispatch-ledger-store.js +51 -3
- package/dist/src/server/env-sync-message.js +9 -9
- package/dist/src/server/feature-flags.d.ts +42 -0
- package/dist/src/server/feature-flags.js +24 -0
- package/dist/src/server/fs-pick-folder.js +4 -0
- package/dist/src/server/fs-sandbox.js +36 -7
- package/dist/src/server/hive-team-guidance.d.ts +12 -6
- package/dist/src/server/hive-team-guidance.js +253 -71
- package/dist/src/server/live-run-registry.d.ts +1 -0
- package/dist/src/server/live-run-registry.js +1 -1
- package/dist/src/server/open-target-commands.js +5 -6
- package/dist/src/server/orchestrator-autostart.d.ts +12 -0
- package/dist/src/server/orchestrator-autostart.js +15 -13
- package/dist/src/server/path-canonicalization.d.ts +3 -0
- package/dist/src/server/path-canonicalization.js +29 -0
- package/dist/src/server/platform-path.d.ts +3 -0
- package/dist/src/server/platform-path.js +13 -0
- package/dist/src/server/post-start-input-writer.d.ts +1 -1
- package/dist/src/server/post-start-input-writer.js +110 -13
- package/dist/src/server/preset-launch-support.d.ts +1 -1
- package/dist/src/server/preset-launch-support.js +33 -2
- package/dist/src/server/recovery-summary.d.ts +5 -1
- package/dist/src/server/recovery-summary.js +18 -17
- 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 +5 -1
- package/dist/src/server/restart-policy-support.js +9 -1
- package/dist/src/server/restart-policy.d.ts +6 -2
- package/dist/src/server/restart-policy.js +51 -31
- package/dist/src/server/role-template-store.d.ts +1 -0
- package/dist/src/server/role-template-store.js +11 -1
- package/dist/src/server/route-types.d.ts +43 -0
- package/dist/src/server/routes-runtime.js +2 -1
- package/dist/src/server/routes-settings.js +76 -0
- package/dist/src/server/routes-tasks.js +23 -0
- package/dist/src/server/routes-team.js +211 -1
- package/dist/src/server/routes-workflow-schedules.d.ts +2 -0
- package/dist/src/server/routes-workflow-schedules.js +58 -0
- package/dist/src/server/routes-workflows.d.ts +2 -0
- package/dist/src/server/routes-workflows.js +83 -0
- package/dist/src/server/routes-workspaces.js +5 -0
- package/dist/src/server/routes.js +4 -0
- package/dist/src/server/runtime-restart-policy.d.ts +3 -1
- package/dist/src/server/runtime-restart-policy.js +2 -1
- package/dist/src/server/runtime-store-contract.d.ts +125 -0
- package/dist/src/server/runtime-store-contract.js +1 -0
- package/dist/src/server/runtime-store-helpers.d.ts +11 -0
- package/dist/src/server/runtime-store-helpers.js +106 -2
- package/dist/src/server/runtime-store-workflows.d.ts +6 -0
- package/dist/src/server/runtime-store-workflows.js +108 -0
- package/dist/src/server/runtime-store.d.ts +3 -72
- package/dist/src/server/runtime-store.js +71 -4
- package/dist/src/server/session-capture-codex.d.ts +3 -3
- package/dist/src/server/session-capture-codex.js +9 -7
- package/dist/src/server/session-capture-gemini.d.ts +1 -1
- package/dist/src/server/session-capture-gemini.js +6 -3
- package/dist/src/server/settings-store.d.ts +3 -0
- package/dist/src/server/settings-store.js +1 -0
- package/dist/src/server/sqlite-schema-v19.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v19.js +17 -0
- package/dist/src/server/sqlite-schema-v20.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v20.js +20 -0
- package/dist/src/server/sqlite-schema-v21.d.ts +2 -0
- package/dist/src/server/sqlite-schema-v21.js +20 -0
- package/dist/src/server/sqlite-schema.d.ts +1 -1
- package/dist/src/server/sqlite-schema.js +110 -1
- package/dist/src/server/system-message.d.ts +7 -0
- package/dist/src/server/system-message.js +8 -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 +12 -1
- package/dist/src/server/tasks-file-watcher.js +128 -23
- package/dist/src/server/tasks-file.d.ts +3 -1
- package/dist/src/server/tasks-file.js +33 -9
- package/dist/src/server/tasks-websocket-server.js +13 -14
- package/dist/src/server/team-authz.d.ts +1 -1
- package/dist/src/server/team-authz.js +10 -1
- package/dist/src/server/team-autostaff.d.ts +16 -0
- package/dist/src/server/team-autostaff.js +16 -0
- package/dist/src/server/team-list-serializer.d.ts +1 -1
- package/dist/src/server/team-list-serializer.js +3 -1
- package/dist/src/server/team-operations.d.ts +21 -1
- package/dist/src/server/team-operations.js +183 -16
- package/dist/src/server/terminal-protocol.js +9 -3
- package/dist/src/server/terminal-stream-hub.js +16 -10
- package/dist/src/server/terminal-ws-server.js +10 -8
- package/dist/src/server/webhook-notifier.d.ts +34 -0
- package/dist/src/server/webhook-notifier.js +47 -0
- package/dist/src/server/websocket-upgrade-safety.d.ts +10 -0
- package/dist/src/server/websocket-upgrade-safety.js +35 -0
- package/dist/src/server/windows-command-line.d.ts +3 -0
- package/dist/src/server/windows-command-line.js +9 -0
- package/dist/src/server/windows-filename.d.ts +2 -0
- package/dist/src/server/windows-filename.js +33 -0
- package/dist/src/server/workflow-cli-policy.d.ts +60 -0
- package/dist/src/server/workflow-cli-policy.js +110 -0
- package/dist/src/server/workflow-dispatch-awaiter.d.ts +12 -0
- package/dist/src/server/workflow-dispatch-awaiter.js +80 -0
- package/dist/src/server/workflow-feature.d.ts +15 -0
- package/dist/src/server/workflow-feature.js +15 -0
- package/dist/src/server/workflow-http-serializers.d.ts +64 -0
- package/dist/src/server/workflow-http-serializers.js +58 -0
- 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-run-log-store.d.ts +19 -0
- package/dist/src/server/workflow-run-log-store.js +45 -0
- package/dist/src/server/workflow-run-store.d.ts +50 -0
- package/dist/src/server/workflow-run-store.js +103 -0
- package/dist/src/server/workflow-runner.d.ts +147 -0
- package/dist/src/server/workflow-runner.js +411 -0
- package/dist/src/server/workflow-schedule-create.d.ts +14 -0
- package/dist/src/server/workflow-schedule-create.js +41 -0
- package/dist/src/server/workflow-schedule-store.d.ts +43 -0
- package/dist/src/server/workflow-schedule-store.js +112 -0
- package/dist/src/server/workflow-scheduler.d.ts +36 -0
- package/dist/src/server/workflow-scheduler.js +97 -0
- package/dist/src/server/workflow-script-loader.d.ts +34 -0
- package/dist/src/server/workflow-script-loader.js +106 -0
- package/dist/src/server/workspace-path-validation.js +16 -4
- package/dist/src/server/workspace-shell-runtime.d.ts +5 -0
- package/dist/src/server/workspace-shell-runtime.js +24 -2
- package/dist/src/server/workspace-store-contract.d.ts +4 -1
- package/dist/src/server/workspace-store-hydration.js +23 -7
- package/dist/src/server/workspace-store-mutations.js +2 -5
- package/dist/src/server/workspace-store-support.d.ts +4 -0
- package/dist/src/server/workspace-store-support.js +13 -1
- package/dist/src/server/workspace-store.js +38 -4
- package/dist/src/shared/types.d.ts +16 -1
- package/package.json +4 -2
- package/web/dist/assets/{AddWorkerDialog-DeZhTQLi.js → AddWorkerDialog-CGbaxu0T.js} +2 -2
- package/web/dist/assets/AddWorkspaceDialog-CNgExu6b.js +1 -0
- package/web/dist/assets/{FirstRunWizard-B5wLcat5.js → FirstRunWizard-DxGApUNc.js} +1 -1
- package/web/dist/assets/{MarketplaceDrawer-BC0eBOEW.js → MarketplaceDrawer-Bk6cpukn.js} +1 -1
- package/web/dist/assets/WhatsNewDialog-CSGzk-2U.js +1 -0
- package/web/dist/assets/WorkerModal-i2F3n3nZ.js +1 -0
- package/web/dist/assets/WorkspaceTaskDrawer-C_Ta_K13.js +1 -0
- package/web/dist/assets/WorkspaceTerminalPanels-VdDxtrQF.js +1 -0
- package/web/dist/assets/index-5zh61jMg.css +1 -0
- package/web/dist/assets/index-CAgGM6nb.js +75 -0
- package/web/dist/assets/path-join-7MR1s7b1.js +1 -0
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +1 -1
- package/web/dist/assets/AddWorkspaceDialog-DDpXNEKf.js +0 -1
- package/web/dist/assets/WorkerModal-BwMHq-Bi.js +0 -1
- package/web/dist/assets/WorkspaceTaskDrawer-CxvT4nqs.js +0 -1
- package/web/dist/assets/WorkspaceTerminalPanels-CvibsPSd.js +0 -1
- package/web/dist/assets/index-BEsTmfrO.css +0 -1
- package/web/dist/assets/index-Ddb7bDN5.js +0 -75
- package/web/dist/assets/path-join-S7qkXQtP.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
All notable user-facing changes will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 1.6.0 - 2026-06-02
|
|
6
|
+
|
|
7
|
+
Orchestrator controls, worker visibility, and protocol-trust fixes.
|
|
8
|
+
|
|
9
|
+
- Adds a Stop control to the running Orchestrator pane so a runaway Orchestrator
|
|
10
|
+
can be halted from the UI (the default is auto-approve, so this is the only
|
|
11
|
+
in-UI kill switch).
|
|
12
|
+
- Surfaces per-worker queue depth and a latest-activity line on worker cards,
|
|
13
|
+
with a legend on the working badge clarifying that Hive does not auto-detect
|
|
14
|
+
stalls — the terminal is the source of truth.
|
|
15
|
+
- Redelivers worker reports the Orchestrator missed: a report is no longer
|
|
16
|
+
silently lost when the Orchestrator is down or restarting; it is queued and
|
|
17
|
+
redelivered on the next report or `team list`.
|
|
18
|
+
- Stops injecting the crash-recovery handover after a deliberate Stop and
|
|
19
|
+
Restart, so the Orchestrator is not handed stale open tasks it was meant to
|
|
20
|
+
drop.
|
|
21
|
+
- Adds an outbound completion webhook setting: Hive POSTs a small JSON payload
|
|
22
|
+
to a URL you choose when a worker reports or a workflow finishes — wire it to
|
|
23
|
+
Slack, ntfy, Feishu, and the like.
|
|
24
|
+
- Adds opt-in structured output to workflow `agent()` via `outputSchema`, so
|
|
25
|
+
fan-out/verify scripts receive a parsed object instead of parsing free text.
|
|
26
|
+
- Adds `team next`: tasks in `.hive/tasks.md` can carry an optional
|
|
27
|
+
`[needs: #2]` dependency, and `team next` returns the tasks that are unblocked
|
|
28
|
+
now.
|
|
29
|
+
|
|
30
|
+
## 1.5.0 - 2026-05-31
|
|
31
|
+
|
|
32
|
+
Workflow runtime, experimental team automation, and Codex reliability.
|
|
33
|
+
|
|
34
|
+
- Adds the experimental Hive workflow runtime: Orchestrators can author
|
|
35
|
+
multi-agent workflow scripts that fan out across real Hive PTY workers, show
|
|
36
|
+
runs in the Workflows drawer, stop runs, inspect run details, schedule
|
|
37
|
+
recurring workflows, and route workflow reports back into the Orchestrator.
|
|
38
|
+
- Adds workflow agent CLI policy settings so users can choose which CLI
|
|
39
|
+
workflow-created agents use by default and which CLIs are allowed.
|
|
40
|
+
- Adds the experimental auto-staff setting, letting the Orchestrator size the
|
|
41
|
+
worker roster to the task and prefer task-scoped ephemeral workers when it
|
|
42
|
+
needs temporary coders, testers, or reviewers.
|
|
43
|
+
- Adds an in-app What's New dialog so future upgrades can surface curated
|
|
44
|
+
release highlights without requiring users to read the changelog manually.
|
|
45
|
+
- Improves Codex reliability by waiting for pasted-content acknowledgements on
|
|
46
|
+
long dispatches while submitting short report/status injections quickly,
|
|
47
|
+
avoiding the several-second delay before reports reach the Orchestrator.
|
|
48
|
+
- Hardens Windows and runtime edge cases, including malformed WebSocket frames,
|
|
49
|
+
stale nvm4w Codex node entrypoints, workflow worker exits, and additional
|
|
50
|
+
workflow/runtime cleanup paths.
|
|
51
|
+
|
|
5
52
|
## 1.4.4 - 2026-05-29
|
|
6
53
|
|
|
7
54
|
Windows portability and team protocol hardening.
|
package/README.en.md
CHANGED
|
@@ -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
|
|
@@ -175,8 +187,17 @@ same shell environment you use to start Hive.
|
|
|
175
187
|
- Orchestrator and worker terminals backed by real PTYs.
|
|
176
188
|
- Add Worker flow with role presets for coder, reviewer, tester, and fully
|
|
177
189
|
custom prompts and commands — wire any CLI agent into the role you need.
|
|
190
|
+
- Auto-staff (experimental, on by default): the Orchestrator can create
|
|
191
|
+
temporary coders, testers, and reviewers based on the task, and Hive cleans
|
|
192
|
+
them up after their dispatch reports back.
|
|
193
|
+
- Workflows (experimental, off by default): the Orchestrator can run
|
|
194
|
+
multi-stage, multi-agent workflows while Hive shows runs, logs, results,
|
|
195
|
+
schedules, and stop controls in the Workflows panel.
|
|
196
|
+
- Workflow CLI policy: choose the default CLI for workflow-created agents and
|
|
197
|
+
restrict which CLIs workflow scripts may launch.
|
|
178
198
|
- `.hive/tasks.md` editor with external-file conflict handling.
|
|
179
199
|
- Background PTY preservation and best-effort native session resume.
|
|
200
|
+
- A What's New dialog after upgrades with curated release highlights.
|
|
180
201
|
- Local SQLite metadata under `~/.config/hive` by default, or `$HIVE_DATA_DIR`
|
|
181
202
|
when set.
|
|
182
203
|
|
package/README.md
CHANGED
|
@@ -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
|
|
@@ -131,8 +135,12 @@ Hive 不替你安装这些 CLI。请在启动 Hive 的同一个 shell 环境里
|
|
|
131
135
|
- Workspace 侧边栏,方便在多个本机项目之间切换。
|
|
132
136
|
- Orchestrator 和 Worker 终端都是真实 PTY 支撑的。
|
|
133
137
|
- Add Worker 预置 coder / reviewer / tester 等角色模板,也支持完全自定义 prompt 与命令——把任何 CLI agent 编排成你需要的角色。
|
|
138
|
+
- 自动组队(实验性,默认开启):Orchestrator 可以根据任务动态创建临时 coder / tester / reviewer,完成后自动回收。
|
|
139
|
+
- Workflows(实验性,默认关闭):Orchestrator 可以运行多阶段、多 agent 的 workflow,Hive 在 Workflows 面板里展示运行、日志、结果、定时任务和停止控制。
|
|
140
|
+
- Workflow CLI 策略:为 workflow 创建的 agent 选择默认 CLI,并限制允许使用的 CLI,避免脚本误启未配置的 agent。
|
|
134
141
|
- `.hive/tasks.md` 编辑器,带外部文件冲突处理。
|
|
135
142
|
- PTY 后台保留 + 尽力使用各 CLI 原生 session 恢复。
|
|
143
|
+
- 升级后的 What's New 弹窗,用简短 release highlights 告诉你新版改了什么。
|
|
136
144
|
- 元数据存在本机 SQLite,默认在 `~/.config/hive`,或者通过 `$HIVE_DATA_DIR` 指定。
|
|
137
145
|
|
|
138
146
|
Hive **不**提供 sandbox 隔离、多用户认证、云端托管,也不自带任何 agent 模型。它只负责调度你已经在用的本机 CLI。
|
|
@@ -241,6 +249,14 @@ pnpm release:dry
|
|
|
241
249
|
|
|
242
250
|
Hive 目前处于 alpha 阶段,核心流程已可用。当前重点是继续打磨多 Agent 协作体验、Windows 支持和更清晰的调度可观测性。欢迎试用、提 issue——反馈会直接影响后续节奏。
|
|
243
251
|
|
|
252
|
+
## 交流群
|
|
253
|
+
|
|
254
|
+
有问题、想反馈,或者就想聊聊 Agent 协作,欢迎进 QQ 群:**Ai Native 交流群**(群号 `1098836554`)。
|
|
255
|
+
|
|
256
|
+
<p align="center">
|
|
257
|
+
<img src="./assets/qq-group.jpg" width="240" alt="Ai Native 交流群 QQ 群二维码,群号 1098836554" />
|
|
258
|
+
</p>
|
|
259
|
+
|
|
244
260
|
## 在路上:跨 Agent 的长时记忆
|
|
245
261
|
|
|
246
262
|
<p align="center">
|
|
Binary file
|
package/dist/bin/team.cmd
CHANGED
|
@@ -4,26 +4,36 @@ export interface RunUpdateResult {
|
|
|
4
4
|
spawnError?: Error;
|
|
5
5
|
}
|
|
6
6
|
export type RunUpdate = (command: string, args: readonly string[]) => Promise<RunUpdateResult>;
|
|
7
|
+
export interface SpawnInvocationPlan {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
options: {
|
|
11
|
+
stdio: 'inherit';
|
|
12
|
+
windowsHide?: boolean;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
7
15
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
16
|
+
* Plan how `defaultRunUpdate` should hand the npm invocation to
|
|
17
|
+
* `child_process.spawn`. Two non-obvious cases collapse here.
|
|
18
|
+
*
|
|
19
|
+
* 1. Node 22+ refuses to spawn `.cmd` / `.bat` files directly after
|
|
20
|
+
* CVE-2024-27980 unless `shell: true` is passed. We do not want
|
|
21
|
+
* `shell: true` though — its arg-stringification path joins argv
|
|
22
|
+
* without quoting, so an install prefix containing spaces (the
|
|
23
|
+
* common Windows case `C:\Program Files\nodejs`) gets word-split
|
|
24
|
+
* by cmd.exe and `--prefix` only sees the first token, so npm
|
|
25
|
+
* silently installs hive to the wrong directory.
|
|
26
|
+
* 2. Wrapping with `cmd.exe /d /s /c <npm.cmd> <args>` solves both:
|
|
27
|
+
* spawning `cmd.exe` (a native exe) avoids the .cmd refusal, and
|
|
28
|
+
* Node's own argv-quoting builds an lpCommandLine where each
|
|
29
|
+
* space-containing arg is wrapped in double quotes that cmd.exe
|
|
30
|
+
* then re-parses correctly. `/d` skips AutoRun, `/s` keeps the
|
|
31
|
+
* quote-handling consistent with `/c`.
|
|
15
32
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `C:\Program Files\nodejs`) will be tokenized incorrectly. The common
|
|
19
|
-
* Windows prefix `%APPDATA%\npm` does not have this problem; fixing the
|
|
20
|
-
* spaces case requires a verbatim `cmd.exe /d /s /c call npm.cmd …`
|
|
21
|
-
* wrapper similar to `agent-command-resolver` and is tracked separately.
|
|
33
|
+
* Detect by filename suffix instead of `process.platform` so unit
|
|
34
|
+
* tests can inject `platform: 'win32'` and exercise the wrap.
|
|
22
35
|
*/
|
|
23
|
-
export declare const
|
|
24
|
-
shell: boolean;
|
|
25
|
-
stdio: "inherit";
|
|
26
|
-
};
|
|
36
|
+
export declare const planSpawnInvocation: (command: string, args: readonly string[], platform?: NodeJS.Platform) => SpawnInvocationPlan;
|
|
27
37
|
/**
|
|
28
38
|
* Signals the upgrade child should receive when the parent runtime is
|
|
29
39
|
* interrupted. Beyond the POSIX-only SIGTERM/SIGINT, SIGHUP is what
|
|
@@ -33,6 +43,24 @@ export declare const buildSpawnOptionsForCommand: (command: string) => {
|
|
|
33
43
|
* Windows exit paths.
|
|
34
44
|
*/
|
|
35
45
|
export declare const FORWARDED_UPDATE_SIGNALS: readonly NodeJS.Signals[];
|
|
46
|
+
/**
|
|
47
|
+
* Forward a parent-process signal to the spawned npm child. On POSIX
|
|
48
|
+
* we hand the signal straight to the child; on Windows there are no
|
|
49
|
+
* real signals, so `child.kill(SIGTERM)` resolves to TerminateProcess
|
|
50
|
+
* against cmd.exe (our wrapper) only — npm itself, plus any install
|
|
51
|
+
* scripts it spawned, become orphans. `taskkill /pid <pid> /t /f`
|
|
52
|
+
* walks the wrapper's process tree so the whole branch dies together.
|
|
53
|
+
* If taskkill is unavailable (restricted PATH, locked-down policy)
|
|
54
|
+
* we fall back to `child.kill` so the wrapper at least exits.
|
|
55
|
+
*
|
|
56
|
+
* Exported so the win32 path can be unit-tested by injecting a stub
|
|
57
|
+
* `killTree` runner — the real `taskkillProcessTree` shells out, and
|
|
58
|
+
* we don't want that running during the test suite.
|
|
59
|
+
*/
|
|
60
|
+
export declare const killUpdateChild: (child: {
|
|
61
|
+
pid?: number | undefined;
|
|
62
|
+
kill: (signal: NodeJS.Signals) => boolean;
|
|
63
|
+
}, signal: NodeJS.Signals, platform?: NodeJS.Platform, killTree?: (pid: number, onFailure?: () => void) => boolean) => void;
|
|
36
64
|
export declare const defaultRunUpdate: RunUpdate;
|
|
37
65
|
export declare const resolveHiveUpdateInstallArgs: (moduleUrl?: string) => string[];
|
|
38
66
|
interface RunHiveUpdateOptions {
|
|
@@ -2,7 +2,9 @@ import { spawn } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { basename, dirname, join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { taskkillProcessTree } from '../server/agent-manager-support.js';
|
|
5
6
|
import { getNpmCommand, INSTALL_COMMAND_ARGS, INSTALL_COMMAND_DISPLAY, PACKAGE_NAME, } from '../server/package-version.js';
|
|
7
|
+
import { buildCmdCallCommand } from '../server/windows-command-line.js';
|
|
6
8
|
export const HIVE_UPDATE_USAGE = [
|
|
7
9
|
'Usage:',
|
|
8
10
|
' hive update',
|
|
@@ -20,25 +22,36 @@ export const HIVE_UPDATE_USAGE = [
|
|
|
20
22
|
' -h, --help Print this help.',
|
|
21
23
|
].join('\n');
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* spawn `.cmd` / `.bat` files without `shell: true` after CVE-2024-27980.
|
|
26
|
-
* Detect by file extension rather than by `process.platform` so the same
|
|
27
|
-
* code path works for both real Windows runs and our cross-platform unit
|
|
28
|
-
* tests (which inject `platform: 'win32'` so that `getNpmCommand` returns
|
|
29
|
-
* `npm.cmd`).
|
|
25
|
+
* Plan how `defaultRunUpdate` should hand the npm invocation to
|
|
26
|
+
* `child_process.spawn`. Two non-obvious cases collapse here.
|
|
30
27
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
28
|
+
* 1. Node 22+ refuses to spawn `.cmd` / `.bat` files directly after
|
|
29
|
+
* CVE-2024-27980 unless `shell: true` is passed. We do not want
|
|
30
|
+
* `shell: true` though — its arg-stringification path joins argv
|
|
31
|
+
* without quoting, so an install prefix containing spaces (the
|
|
32
|
+
* common Windows case `C:\Program Files\nodejs`) gets word-split
|
|
33
|
+
* by cmd.exe and `--prefix` only sees the first token, so npm
|
|
34
|
+
* silently installs hive to the wrong directory.
|
|
35
|
+
* 2. Wrapping with `cmd.exe /d /s /c <npm.cmd> <args>` solves both:
|
|
36
|
+
* spawning `cmd.exe` (a native exe) avoids the .cmd refusal, and
|
|
37
|
+
* Node's own argv-quoting builds an lpCommandLine where each
|
|
38
|
+
* space-containing arg is wrapped in double quotes that cmd.exe
|
|
39
|
+
* then re-parses correctly. `/d` skips AutoRun, `/s` keeps the
|
|
40
|
+
* quote-handling consistent with `/c`.
|
|
41
|
+
*
|
|
42
|
+
* Detect by filename suffix instead of `process.platform` so unit
|
|
43
|
+
* tests can inject `platform: 'win32'` and exercise the wrap.
|
|
37
44
|
*/
|
|
38
|
-
export const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
export const planSpawnInvocation = (command, args, platform = process.platform) => {
|
|
46
|
+
if (platform === 'win32' && /\.(cmd|bat)$/i.test(command)) {
|
|
47
|
+
return {
|
|
48
|
+
command: 'cmd.exe',
|
|
49
|
+
args: ['/d', '/s', '/c', buildCmdCallCommand(command, args)],
|
|
50
|
+
options: { stdio: 'inherit', windowsHide: false },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { command, args: [...args], options: { stdio: 'inherit' } };
|
|
54
|
+
};
|
|
42
55
|
/**
|
|
43
56
|
* Signals the upgrade child should receive when the parent runtime is
|
|
44
57
|
* interrupted. Beyond the POSIX-only SIGTERM/SIGINT, SIGHUP is what
|
|
@@ -53,21 +66,46 @@ export const FORWARDED_UPDATE_SIGNALS = [
|
|
|
53
66
|
'SIGHUP',
|
|
54
67
|
'SIGBREAK',
|
|
55
68
|
];
|
|
69
|
+
/**
|
|
70
|
+
* Forward a parent-process signal to the spawned npm child. On POSIX
|
|
71
|
+
* we hand the signal straight to the child; on Windows there are no
|
|
72
|
+
* real signals, so `child.kill(SIGTERM)` resolves to TerminateProcess
|
|
73
|
+
* against cmd.exe (our wrapper) only — npm itself, plus any install
|
|
74
|
+
* scripts it spawned, become orphans. `taskkill /pid <pid> /t /f`
|
|
75
|
+
* walks the wrapper's process tree so the whole branch dies together.
|
|
76
|
+
* If taskkill is unavailable (restricted PATH, locked-down policy)
|
|
77
|
+
* we fall back to `child.kill` so the wrapper at least exits.
|
|
78
|
+
*
|
|
79
|
+
* Exported so the win32 path can be unit-tested by injecting a stub
|
|
80
|
+
* `killTree` runner — the real `taskkillProcessTree` shells out, and
|
|
81
|
+
* we don't want that running during the test suite.
|
|
82
|
+
*/
|
|
83
|
+
export const killUpdateChild = (child, signal, platform = process.platform, killTree = (pid, onFailure) => taskkillProcessTree(pid, platform, undefined, onFailure)) => {
|
|
84
|
+
const fallback = () => {
|
|
85
|
+
try {
|
|
86
|
+
child.kill(signal);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// child.kill on Windows throws if the signal name isn't
|
|
90
|
+
// implemented; we forward what we can and ignore the rest.
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
if (platform === 'win32' && typeof child.pid === 'number' && child.pid > 0) {
|
|
94
|
+
if (killTree(child.pid, fallback))
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
fallback();
|
|
98
|
+
};
|
|
56
99
|
export const defaultRunUpdate = (command, args) => new Promise((resolve) => {
|
|
57
|
-
const
|
|
100
|
+
const plan = planSpawnInvocation(command, args);
|
|
101
|
+
const child = spawn(plan.command, plan.args, plan.options);
|
|
58
102
|
let resolved = false;
|
|
59
103
|
// Handlers are registered with `once` so they don't accumulate
|
|
60
104
|
// across invocations and explicitly removed at finalize().
|
|
61
105
|
const handlers = new Map();
|
|
62
106
|
for (const signal of FORWARDED_UPDATE_SIGNALS) {
|
|
63
107
|
const handler = () => {
|
|
64
|
-
|
|
65
|
-
child.kill(signal);
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
// child.kill on Windows throws if the signal name isn't
|
|
69
|
-
// implemented; we forward what we can and ignore the rest.
|
|
70
|
-
}
|
|
108
|
+
killUpdateChild(child, signal);
|
|
71
109
|
};
|
|
72
110
|
handlers.set(signal, handler);
|
|
73
111
|
process.once(signal, handler);
|
package/dist/src/cli/hive.d.ts
CHANGED
|
@@ -33,6 +33,31 @@ type RunHiveCommandOptions = {
|
|
|
33
33
|
export declare const SHUTDOWN_SIGNALS: readonly ["SIGINT", "SIGTERM", "SIGHUP", "SIGBREAK"];
|
|
34
34
|
export declare const HIVE_USAGE: string;
|
|
35
35
|
export declare const handleHiveInfoCommand: (argv: string[]) => boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the directory where Hive persists its SQLite DB and supporting
|
|
38
|
+
* state. Platform-aware because `~/.config/hive` is a hidden dot-directory
|
|
39
|
+
* convention that Windows Explorer treats as second-class — Windows users
|
|
40
|
+
* can't navigate there from the address bar without typing the full path,
|
|
41
|
+
* and the standard roaming-profile location is `%APPDATA%\<app>` instead.
|
|
42
|
+
*
|
|
43
|
+
* Resolution order:
|
|
44
|
+
* 1. HIVE_DATA_DIR override (any platform, for tests / opinionated users).
|
|
45
|
+
* 2. Windows: %APPDATA%\hive — roaming user state, follows the user
|
|
46
|
+
* across machines on a domain profile. APPDATA, not LOCALAPPDATA,
|
|
47
|
+
* because Hive's DB is user data, not a machine-local cache.
|
|
48
|
+
* Falls back to homedir()\AppData\Roaming\hive when APPDATA is
|
|
49
|
+
* stripped from the env (some Windows Task Scheduler configs do this).
|
|
50
|
+
* 3. POSIX: $XDG_CONFIG_HOME/hive, falling back to ~/.config/hive.
|
|
51
|
+
*
|
|
52
|
+
* Migration: pre-fix Windows installs wrote to ~/.config/hive. When that
|
|
53
|
+
* legacy directory exists but the new %APPDATA%\hive does not, prefer the
|
|
54
|
+
* legacy path so an upgrade does not surface as an empty workspace list.
|
|
55
|
+
* This is a one-way ratchet — once the new location is populated, it wins.
|
|
56
|
+
*
|
|
57
|
+
* Exported so the resolution rules are unit-testable without touching env
|
|
58
|
+
* or the real filesystem.
|
|
59
|
+
*/
|
|
60
|
+
export declare const resolveDataDir: (platform?: NodeJS.Platform, env?: NodeJS.ProcessEnv, pathExists?: (path: string) => boolean) => string;
|
|
36
61
|
/**
|
|
37
62
|
* Recovery hint formatter for the "port already in use" error. Platform-aware
|
|
38
63
|
* because the lsof / xargs / kill pipeline is POSIX-only; on Windows a user
|
package/dist/src/cli/hive.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { once } from 'node:events';
|
|
3
|
-
import {
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { createAgentManager } from '../server/agent-manager.js';
|
|
8
8
|
import { createApp } from '../server/app.js';
|
|
9
9
|
import { readPackageVersion } from '../server/package-version.js';
|
|
10
|
+
import { sameFilesystemPath } from '../server/path-canonicalization.js';
|
|
10
11
|
import { createRuntimeStore } from '../server/runtime-store.js';
|
|
11
12
|
import { createVersionService } from '../server/version-service.js';
|
|
12
13
|
import { runHiveUpdateCommand } from './hive-update.js';
|
|
@@ -80,7 +81,44 @@ const parsePort = (argv) => {
|
|
|
80
81
|
}
|
|
81
82
|
return parsedPort ?? 3000;
|
|
82
83
|
};
|
|
83
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Resolve the directory where Hive persists its SQLite DB and supporting
|
|
86
|
+
* state. Platform-aware because `~/.config/hive` is a hidden dot-directory
|
|
87
|
+
* convention that Windows Explorer treats as second-class — Windows users
|
|
88
|
+
* can't navigate there from the address bar without typing the full path,
|
|
89
|
+
* and the standard roaming-profile location is `%APPDATA%\<app>` instead.
|
|
90
|
+
*
|
|
91
|
+
* Resolution order:
|
|
92
|
+
* 1. HIVE_DATA_DIR override (any platform, for tests / opinionated users).
|
|
93
|
+
* 2. Windows: %APPDATA%\hive — roaming user state, follows the user
|
|
94
|
+
* across machines on a domain profile. APPDATA, not LOCALAPPDATA,
|
|
95
|
+
* because Hive's DB is user data, not a machine-local cache.
|
|
96
|
+
* Falls back to homedir()\AppData\Roaming\hive when APPDATA is
|
|
97
|
+
* stripped from the env (some Windows Task Scheduler configs do this).
|
|
98
|
+
* 3. POSIX: $XDG_CONFIG_HOME/hive, falling back to ~/.config/hive.
|
|
99
|
+
*
|
|
100
|
+
* Migration: pre-fix Windows installs wrote to ~/.config/hive. When that
|
|
101
|
+
* legacy directory exists but the new %APPDATA%\hive does not, prefer the
|
|
102
|
+
* legacy path so an upgrade does not surface as an empty workspace list.
|
|
103
|
+
* This is a one-way ratchet — once the new location is populated, it wins.
|
|
104
|
+
*
|
|
105
|
+
* Exported so the resolution rules are unit-testable without touching env
|
|
106
|
+
* or the real filesystem.
|
|
107
|
+
*/
|
|
108
|
+
export const resolveDataDir = (platform = process.platform, env = process.env, pathExists = existsSync) => {
|
|
109
|
+
const override = env.HIVE_DATA_DIR;
|
|
110
|
+
if (override)
|
|
111
|
+
return override;
|
|
112
|
+
if (platform === 'win32') {
|
|
113
|
+
const appData = env.APPDATA ?? join(homedir(), 'AppData', 'Roaming');
|
|
114
|
+
const target = join(appData, 'hive');
|
|
115
|
+
const legacy = join(homedir(), '.config', 'hive');
|
|
116
|
+
if (!pathExists(target) && pathExists(legacy))
|
|
117
|
+
return legacy;
|
|
118
|
+
return target;
|
|
119
|
+
}
|
|
120
|
+
return join(env.XDG_CONFIG_HOME ?? join(homedir(), '.config'), 'hive');
|
|
121
|
+
};
|
|
84
122
|
const maybePrintUpdateHint = async (versionService) => {
|
|
85
123
|
const info = await versionService.getVersionInfo();
|
|
86
124
|
if (!info.update_available)
|
|
@@ -210,7 +248,7 @@ export const runHiveCommand = async (argv, options = {}) => {
|
|
|
210
248
|
};
|
|
211
249
|
};
|
|
212
250
|
const isMainModule = process.argv[1]
|
|
213
|
-
? fileURLToPath(import.meta.url)
|
|
251
|
+
? sameFilesystemPath(fileURLToPath(import.meta.url), process.argv[1])
|
|
214
252
|
: false;
|
|
215
253
|
if (isMainModule) {
|
|
216
254
|
const argv = process.argv.slice(2);
|
package/dist/src/cli/team.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export interface ParsedReportArgs {
|
|
|
10
10
|
}
|
|
11
11
|
export declare const parseReportArgs: (args: string[], command?: string) => ParsedReportArgs;
|
|
12
12
|
export declare const parseCancelArgs: (args: string[]) => ParsedCancelArgs;
|
|
13
|
+
export declare const decodeStdinBuffer: (buffer: Buffer) => string;
|
|
13
14
|
export declare const readStdinToString: (command?: string) => Promise<string>;
|
|
14
15
|
export declare const runTeamCommand: (argv: string[]) => Promise<void>;
|
|
15
16
|
export {};
|