@logicseek/hello-cc 1.1.0-rc.1 → 1.1.0-rc.3
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 +190 -108
- package/README.md +1 -10
- package/README.zh-CN.md +1 -8
- package/docs/codex-account.zh-CN.md +38 -0
- package/docs/codex-protocol.md +59 -0
- package/docs/commands.md +13 -28
- package/docs/commands.zh-CN.md +11 -20
- package/docs/dsh.md +5 -3
- package/docs/dsh.zh-CN.md +6 -4
- package/docs/macos-process-identity.md +15 -0
- package/docs/native.md +95 -4
- package/docs/native.zh-CN.md +70 -1
- package/docs/web-handoff.zh-CN.md +107 -5
- package/lib/cli/app.mjs +9 -6
- package/lib/cli/commands/coordination.mjs +7 -2
- package/lib/cli/commands/gc.mjs +14 -12
- package/lib/cli/commands/hook.mjs +16 -3
- package/lib/cli/commands/install.mjs +37 -9
- package/lib/cli/commands/lock.mjs +3 -1
- package/lib/cli/commands/misc.mjs +105 -13
- package/lib/cli/commands/native.mjs +3 -44
- package/lib/cli/commands/peer.mjs +3 -0
- package/lib/cli/commands/run.mjs +13 -6
- package/lib/cli/commands/tmux.mjs +1 -2
- package/lib/cli-runtime.mjs +19 -2
- package/lib/core/coordination/gc-plan.mjs +5 -0
- package/lib/core/coordination/locks.mjs +3 -1
- package/lib/core/peers/evidence.mjs +21 -1
- package/lib/core/peers/tmux-safety.mjs +4 -0
- package/lib/core/sessions/hook-root-identity.mjs +47 -0
- package/lib/core/sessions/launch.mjs +7 -1
- package/lib/db/connection.mjs +67 -21
- package/lib/diagnostics/codex-protocol.mjs +105 -0
- package/lib/guidance.mjs +20 -36
- package/lib/integrations/codex-account.mjs +143 -0
- package/lib/integrations/dsh-collaboration.mjs +3 -4
- package/lib/integrations/dsh.mjs +4 -2
- package/lib/integrations/native/claude.mjs +24 -6
- package/lib/integrations/native/codex.mjs +38 -7
- package/lib/integrations/native/dsh-acp.mjs +67 -24
- package/lib/integrations/native/index.mjs +4 -1
- package/lib/integrations/native/jsonrpc.mjs +37 -5
- package/lib/integrations/native/telemetry.mjs +30 -0
- package/lib/process/identity.mjs +67 -28
- package/lib/process/pinned-cwd.mjs +302 -0
- package/lib/process/pinned-guidance.mjs +138 -0
- package/lib/process/pinned-project-state.mjs +105 -0
- package/lib/process/selected-cwd-identity.mjs +95 -0
- package/lib/runtime/buffer-evidence.mjs +7 -1
- package/lib/runtime/client.mjs +18 -1
- package/lib/runtime/native/client.mjs +4 -1
- package/lib/runtime/native/history.mjs +140 -0
- package/lib/runtime/native/launcher.mjs +106 -0
- package/lib/runtime/native/service.mjs +160 -27
- package/lib/runtime/native/store.mjs +51 -21
- package/lib/runtime/project-path.mjs +24 -5
- package/lib/runtime/projects.mjs +3 -0
- package/lib/runtime/state.mjs +61 -26
- package/lib/shared/file-lock.mjs +62 -17
- package/lib/shared/redact.mjs +2 -1
- package/lib/shared/socket-lock-worker.mjs +15 -6
- package/lib/web/agent-defaults.mjs +110 -0
- package/lib/web/auto-attach.mjs +3 -2
- package/lib/web/browser/contracts.d.ts +10 -0
- package/lib/web/browser/core.mjs +1997 -0
- package/lib/web/browser/project-data.mjs +158 -0
- package/lib/web/browser/session-sync.mjs +82 -0
- package/lib/web/browser-assets.mjs +19 -0
- package/lib/web/buffer-gc-runtime.mjs +2 -2
- package/lib/web/codex-app-server.mjs +104 -33
- package/lib/web/codex-sessions.mjs +60 -11
- package/lib/web/context-files.mjs +82 -0
- package/lib/web/cookie-auth.mjs +51 -3
- package/lib/web/external-sessions.mjs +22 -4
- package/lib/web/http-routes.mjs +236 -23
- package/lib/web/http.mjs +50 -4
- package/lib/web/liveness-reaper.mjs +2 -2
- package/lib/web/native-sessions.mjs +322 -13
- package/lib/web/project-contexts.mjs +235 -42
- package/lib/web/project-file-write.mjs +249 -0
- package/lib/web/project-files.mjs +268 -0
- package/lib/web/pty-sessions.mjs +11 -3
- package/lib/web/runtime-main.mjs +134 -82
- package/lib/web/session-serialize.mjs +87 -8
- package/lib/web/session-state-sync.mjs +98 -0
- package/lib/web/shutdown-diagnostics.mjs +38 -0
- package/lib/web/shutdown-response.mjs +21 -0
- package/lib/web/shutdown-state.mjs +91 -0
- package/lib/web/startup.mjs +76 -27
- package/lib/web/tmux-client-snapshot.mjs +85 -0
- package/lib/web/tmux-sessions.mjs +71 -7
- package/lib/web/tmux-stream.mjs +36 -8
- package/lib/web/ui-agent-defaults.mjs +149 -0
- package/lib/web/ui-agent-start.mjs +330 -0
- package/lib/web/ui-codex-account.mjs +81 -0
- package/lib/web/ui-codex.mjs +81 -73
- package/lib/web/ui-command-palette.mjs +21 -5
- package/lib/web/ui-file-writes.mjs +220 -0
- package/lib/web/ui-files.mjs +231 -0
- package/lib/web/ui-handoff.mjs +10 -2
- package/lib/web/ui-history.mjs +175 -105
- package/lib/web/ui-i18n.mjs +280 -8
- package/lib/web/ui-interactions.mjs +6 -4
- package/lib/web/ui-native-timeline.mjs +326 -0
- package/lib/web/ui-native.mjs +93 -49
- package/lib/web/ui-review.mjs +5 -3
- package/lib/web/ui-safe-markdown.mjs +79 -0
- package/lib/web/ui-session-tools.mjs +224 -0
- package/lib/web/ui-template.mjs +27 -1967
- package/lib/web/ui-terminal-find.mjs +5 -3
- package/lib/web/ui-workbench.mjs +5 -3
- package/lib/web/ui-workspace.mjs +3 -0
- package/package.json +8 -2
- package/scripts/benchmark-session-sync.mjs +53 -0
- package/scripts/codex-protocol.mjs +88 -0
- package/scripts/dsh-approval-layers-acceptance.mjs +172 -0
- package/scripts/dsh-package-provenance.mjs +118 -0
- package/scripts/native-bounded-live-acceptance.mjs +193 -0
- package/scripts/native-fixture-root.mjs +49 -0
- package/scripts/native-installed-acceptance.mjs +204 -6
- package/scripts/native-stability-checks.mjs +40 -0
- package/scripts/regression-cookie-expiry.mjs +70 -0
- package/scripts/regression-http-transport.mjs +9 -0
- package/scripts/regression-terminal-marker.mjs +95 -0
- package/scripts/regression.mjs +637 -186
- package/scripts/shim-reentry-probe.mjs +105 -0
- package/scripts/web-acceptance-diagnostics.mjs +90 -0
- package/scripts/web-codex-account-acceptance.mjs +178 -0
- package/scripts/web-file-preview-checks.mjs +302 -0
- package/scripts/web-mcp-form-acceptance.mjs +22 -7
- package/scripts/web-mcp-form-live-acceptance.mjs +1 -1
- package/scripts/web-native-handoff-checks.mjs +128 -0
- package/scripts/web-native-interaction-acceptance.mjs +152 -18
- package/scripts/web-native-interaction-diagnostics.mjs +80 -0
- package/scripts/web-native-model-acceptance.mjs +22 -7
- package/scripts/web-session-tools-checks.mjs +112 -0
- package/scripts/web-workbench-acceptance.mjs +435 -0
- package/scripts/web-workbench-installed-acceptance.mjs +122 -0
package/docs/dsh.zh-CN.md
CHANGED
|
@@ -8,7 +8,7 @@ DeepSeek Harness(`dsh`)可以与 Claude Code、Codex 共用 hello-cc 的项
|
|
|
8
8
|
|
|
9
9
|
支持 Linux 和 macOS;Windows 使用 WSL,不支持原生 Windows shell。容器验证与实际设备验收分别记录。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
此接入自 hello-cc 1.0.2 起提供,沿用 npm 的 latest 标签。在 Node.js 24+ 环境执行 `npm install -g @logicseek/hello-cc` 安装。验证源码时,用本仓库的 CLI:
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
node /absolute/path/to/hello-cc/bin/hcc.mjs --root /path/to/project dsh setup --mode cordis
|
|
@@ -18,6 +18,8 @@ node /absolute/path/to/hello-cc/bin/hcc.mjs --root /path/to/project dsh web -- -
|
|
|
18
18
|
|
|
19
19
|
下文 `hcc` 指包含这些代码的 CLI。已有的全局 `hcc` 未必包含此接入。
|
|
20
20
|
|
|
21
|
+
macOS 从 1.0.5 起使用稳定的启动周期标记。升级时按[进程身份迁移说明](macos-process-identity.md)正常重启所管理的运行时,保留身份无法比较的旧进程。
|
|
22
|
+
|
|
21
23
|
## 选择入口
|
|
22
24
|
|
|
23
25
|
| 入口 | 适用场景 | 会话由谁持有 |
|
|
@@ -115,7 +117,7 @@ hcc native start --peer dsh-reviewer --provider dsh --binary /absolute/path/to/d
|
|
|
115
117
|
|
|
116
118
|
```bash
|
|
117
119
|
npm pack --ignore-scripts
|
|
118
|
-
dsh plugin --profile web add /absolute/path/to/logicseek-hello-cc-1.0.
|
|
120
|
+
dsh plugin --profile web add /absolute/path/to/logicseek-hello-cc-1.0.5.tgz
|
|
119
121
|
```
|
|
120
122
|
|
|
121
123
|
Harness 的 pnpm 策略要求明确允许原生依赖构建。若首次 add 返回 `ERR_PNPM_IGNORED_BUILDS`,在所选 profile 的 `pnpm-workspace.yaml` 中合并以下配置,然后重跑同一 add 命令;默认位置是 `~/.dsh/profiles/web/pnpm-workspace.yaml`,自定义 DSH_HOME 时以该目录为准。保留文件中已有设置,只批准候选包使用的固定版本:
|
|
@@ -125,9 +127,9 @@ allowBuilds:
|
|
|
125
127
|
node-pty@1.2.0-beta.15: true
|
|
126
128
|
```
|
|
127
129
|
|
|
128
|
-
安装后由 Harness profile 的 `dsh.profile.bundles` 选择包;不要再同时加载项目 Cordis/hooks overlay。bundle 已通过实际 npm 安装、官方 add/重复 add/remove、隔离 profile 加载和真实模型工具调用。2026-10-02 已安装到本机真实 desktop profile 并热加载,配套 ACP 使用既有 DeepSeek 路由完成真实工具调用;初次桌面 sub2api 模型返回账户仅允许 Codex 官方客户端的 403;随后桌面默认模型已变为官方 DeepSeek,沿用当时配置的新建会话完成 hcc_state、hcc_message_send 和真实 completed 回合。原 sub2api
|
|
130
|
+
安装后由 Harness profile 的 `dsh.profile.bundles` 选择包;不要再同时加载项目 Cordis/hooks overlay。bundle 已通过实际 npm 安装、官方 add/重复 add/remove、隔离 profile 加载和真实模型工具调用。2026-10-02 已安装到本机真实 desktop profile 并热加载,配套 ACP 使用既有 DeepSeek 路由完成真实工具调用;初次桌面 sub2api 模型返回账户仅允许 Codex 官方客户端的 403;随后桌面默认模型已变为官方 DeepSeek,沿用当时配置的新建会话完成 hcc_state、hcc_message_send 和真实 completed 回合。原 sub2api 路由限制仍存在。后续维护版本沿用 npm latest 标签发布。profile 插件安装/移除由 Harness 管理,项目 overlay 则使用 `setup --mode off` 关闭。
|
|
129
131
|
|
|
130
|
-
验证记录见 Cordis/native 验收 (源码目录: `docs/verification/2026-10-02-dsh-cordis-native.md`)、兼容桥记录 (源码目录: `docs/verification/2026-10-02-dsh-official-bridge.md`) 和详细接入计划 (源码目录: `docs/plans/2026-10-02-dsh-integration.md`)。真实模型验收在临时项目和自有进程中完成;既有会话与模型凭据保留;本机实际安装记录见 Mac 接入验收 (源码目录: `docs/verification/2026-10-02-dsh-device-install.md`)
|
|
132
|
+
验证记录见 Cordis/native 验收 (源码目录: `docs/verification/2026-10-02-dsh-cordis-native.md`)、兼容桥记录 (源码目录: `docs/verification/2026-10-02-dsh-official-bridge.md`) 和详细接入计划 (源码目录: `docs/plans/2026-10-02-dsh-integration.md`)。真实模型验收在临时项目和自有进程中完成;既有会话与模型凭据保留;本机实际安装记录见 Mac 接入验收 (源码目录: `docs/verification/2026-10-02-dsh-device-install.md`)。Linux 容器已验证,实际 WSL/员工设备和真实业务签收尚未完成;隔离订单样例已完成报告、证据、交接、解锁与任务结束验证。
|
|
131
133
|
|
|
132
134
|
可用下面的安装验收脚本重现 npm 安装、官方 `plugin add` / 重复 add / remove,以及安装后的公共 CLI。`--run-live` 会沿用已有 DeepSeek 认证,验证 ACP 权限拒绝和一个隔离订单汇总任务;没有该参数时不调用真实模型。脚本只使用本次创建的 HOME、DSH_HOME、项目和进程。
|
|
133
135
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# macOS 进程身份与升级
|
|
2
|
+
|
|
3
|
+
macOS 的 `kern.boottime` 是墙上时钟时间,同一次开机期间也可能因时钟校正改变。以它的秒、微秒字段识别进程,会把仍在运行的进程误判为新实例。
|
|
4
|
+
|
|
5
|
+
Darwin 身份改为 `darwin:<kern.bootsessionuuid>:<UTC/C ps lstart>`。开机 UUID 严格验证并统一小写;缺失、查询失败或格式错误时返回 `unknown`,不会退回 `kern.boottime`。进程开始时间仍前后读取两次,状态中的 zombie 仍视为已退出。PID、进程开始时间和命令摘要的所有权校验没有放宽。
|
|
6
|
+
|
|
7
|
+
旧版本保存的 `<boot 秒>:<boot 微秒>:<ps lstart>` 无法可靠转换成新标记。对同一存活 PID,旧、新格式之间返回 `unknown`,既不授予所有权,也不证明旧进程已经退出。其 runtime 指针不因超过普通未知状态宽限期而被回收;Cordis 恢复和 native 启动也必须保留仍存活的旧 owner。与真实进程退出或同格式 PID 复用有关的判定保持原有规则。
|
|
8
|
+
|
|
9
|
+
这种专用 `unknown` 同样保留 peer/binding、过期锁和缓冲文件,阻止过期任务被接管;它不会赋予 `live` 身份、续租或写权限。普通未知状态的超时策略不变。
|
|
10
|
+
|
|
11
|
+
早期 Web 工作台候选使用过 `mac:<boot UUID>:<ps lstart>` 前缀。它与正式的 `darwin:` 格式交叉比较时同样保留为 `unknown`,不因前缀变化回收仍存活的候选进程;需要由原版本正常关闭后再启动新版本。
|
|
12
|
+
|
|
13
|
+
升级前,先用原版本正常关闭所属 native worker/runtime,正常退出 Harness Desktop,再安装并启动新版本,使运行中的 owner 重新建立身份。保留账号配置、会话与协作数据库;不要手工改写旧身份、删除仍存活 runtime 的指针,或仅凭 PID 强行接管。若旧进程已经退出,OS 的死亡证据仍允许正常恢复。没有完整身份的其他未知状态继续使用原有策略。
|
|
14
|
+
|
|
15
|
+
回归覆盖同一次开机期间 `kern.boottime` 漂移、不同 boot UUID、错误和缺失 UUID、PATH 缺失时的固定系统路径、语言环境、PID 复用、exec、真实自有 zombie,以及跨格式 runtime 指针、native 启动和 Cordis 恢复边界。
|
package/docs/native.md
CHANGED
|
@@ -54,6 +54,49 @@ real Web approval receipt (source checkout: `docs/verification/2026-10-02-native
|
|
|
54
54
|
exercises this default project lookup without injecting a query function. It
|
|
55
55
|
does not verify a published package or an employee installation.
|
|
56
56
|
|
|
57
|
+
## Start from Web
|
|
58
|
+
|
|
59
|
+
Run `hcc web`, select the project, and choose **New Agent**. Codex, Claude and
|
|
60
|
+
DeepSeek Harness default to **Background Agent**, which creates a native worker
|
|
61
|
+
and starts or reuses the project's independent native runtime. You do not need
|
|
62
|
+
to run `hcc native start` first; the provider requirements above still apply.
|
|
63
|
+
|
|
64
|
+
**Settings** can save the project default provider plus a model and an in-project
|
|
65
|
+
working directory for each provider. **New Agent** prefills these values; when no
|
|
66
|
+
directory is configured it uses the project root. The worker continues to share the selected
|
|
67
|
+
project's HCC task and message bus. Select or add another project to work outside
|
|
68
|
+
that root. **Model (optional)** can stay empty to use the provider's configured
|
|
69
|
+
default; any supplied value must be supported by that provider. **Name (optional)**
|
|
70
|
+
can stay empty for a generated peer name.
|
|
71
|
+
|
|
72
|
+
These defaults live in the selected HCC project database and apply only to future
|
|
73
|
+
Web native creations. They do not change running workers, history resume, CLI
|
|
74
|
+
launches or provider account files. Concurrent saves use revision checks; reload
|
|
75
|
+
and review the latest values after a conflict. Clearing the model in the creation
|
|
76
|
+
form explicitly chooses the provider's own default for that one worker.
|
|
77
|
+
|
|
78
|
+
**New Agent** creates a new native session. **History → HCC retained history**
|
|
79
|
+
browses saved native workers and explicitly resumes workers recorded as closed.
|
|
80
|
+
Resume keeps the peer and provider session ID, rechecks ownership, and starts a
|
|
81
|
+
new executor. CLI resume remains available. **Advanced options** keeps the terminal
|
|
82
|
+
CLI and Codex App Server paths, including their existing history controls. Shell
|
|
83
|
+
uses a terminal; DeepSeek Harness uses a background worker.
|
|
84
|
+
|
|
85
|
+
After creation, send prompts and inspect receipts or approvals in the same Web
|
|
86
|
+
session. Creating a worker does not by itself complete a model task. Closing
|
|
87
|
+
the page or stopping Web preserves the independent native runtime and worker;
|
|
88
|
+
explicitly close the worker when it is no longer needed. The dated acceptance
|
|
89
|
+
records below do not establish real-model or release acceptance of this new
|
|
90
|
+
creation or history/resume entries. See the [Web guide](web-handoff.zh-CN.md).
|
|
91
|
+
|
|
92
|
+
The **Files** entry browses saved project files and artifacts without creating a
|
|
93
|
+
worker or sending file contents to a model. It provides bounded text, Markdown,
|
|
94
|
+
image, PDF and static HTML previews. Explicit uploads create new project files
|
|
95
|
+
without replacing existing names (up to 10 MiB); complete UTF-8 text files can be
|
|
96
|
+
edited and saved with a revision check (up to 1 MiB). Conflicts and uncertain write
|
|
97
|
+
results keep the draft for inspection. These actions do not attach files to a model
|
|
98
|
+
conversation. See the [project file guide](web-handoff.zh-CN.md#上传与编辑项目文件).
|
|
99
|
+
|
|
57
100
|
## CLI
|
|
58
101
|
|
|
59
102
|
Run commands from the project you want the workers to share, or select it with
|
|
@@ -153,6 +196,13 @@ it does not attach to an existing live TUI or desktop instance. HCC cannot prove
|
|
|
153
196
|
that an external application has independently opened the same saved session,
|
|
154
197
|
so do not open the same conversation concurrently outside the owned runtime.
|
|
155
198
|
|
|
199
|
+
New saved workers also retain the filesystem identity of their working
|
|
200
|
+
directory. Resume requires that identity to still match, even if the path
|
|
201
|
+
spelling is unchanged. Older workers without that evidence remain readable in
|
|
202
|
+
HCC history but are not automatically resumable; manual review and association
|
|
203
|
+
are not yet implemented. Web history marks these records as unavailable before
|
|
204
|
+
the native service rechecks at admission.
|
|
205
|
+
|
|
156
206
|
Native workers receive a worker-specific `HCC_ROOT`, `HCC_DB`, `HCC_PEER`, and
|
|
157
207
|
`HCC_NATIVE_OWNER`. A provider hook must match the peer's native transport owner.
|
|
158
208
|
Its native hook path only heartbeats that owner and renews its locks. It does
|
|
@@ -224,10 +274,14 @@ explicitly. Truncated requests can only be declined or cancelled. Nested schemas
|
|
|
224
274
|
|
|
225
275
|
- Existing Codex/Claude/dsh terminal sessions remain on their original transport;
|
|
226
276
|
attaching to or taking over an existing TUI/Desktop session is not implemented.
|
|
227
|
-
- Web
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
277
|
+
- Web can create Codex, Claude and dsh native workers, and discovers existing
|
|
278
|
+
workers in the same project. It exposes messages, delivery receipts,
|
|
279
|
+
interruption, and explicit closure. History reads retained project events and
|
|
280
|
+
explicitly resumes closed workers; it is not the provider's complete transcript.
|
|
281
|
+
Active workers and workers without confirmed closure cannot resume from this
|
|
282
|
+
entry. Closing the page or Web runtime
|
|
283
|
+
preserves the independent native worker. Human responses are bound to the
|
|
284
|
+
current executor and turn. See the [Web handoff guide](web-handoff.zh-CN.md).
|
|
231
285
|
- Codex, Claude and dsh native workers receive project- and peer-scoped HCC MCP
|
|
232
286
|
configuration. Writes still require provider permission and HCC ownership checks.
|
|
233
287
|
- Provider-internal `SendMessage`, subagent/team discovery, and Codex delegation
|
|
@@ -367,3 +421,40 @@ Legacy deliveries retain peer origin during migration. This distinction does
|
|
|
367
421
|
not grant tool permissions: writes and other gated tools still require approval.
|
|
368
422
|
For delegated file work, first authorize the receiving agent's bounded task,
|
|
369
423
|
then send the peer handoff.
|
|
424
|
+
|
|
425
|
+
## Bounded stability acceptance
|
|
426
|
+
|
|
427
|
+
Add `--stability` to installed-package acceptance to run sustained work after
|
|
428
|
+
its lifecycle and cross-provider checks:
|
|
429
|
+
|
|
430
|
+
```sh
|
|
431
|
+
node /absolute/path/to/acceptance-prefix/node_modules/@logicseek/hello-cc/scripts/native-installed-acceptance.mjs \
|
|
432
|
+
--run-live --codex-bin /absolute/path/to/codex --dsh-bin /absolute/path/to/dsh \
|
|
433
|
+
--archive /absolute/path/to/hello-cc.tgz --stability \
|
|
434
|
+
--stability-cycles 6 --stability-burst 2 --stability-idle-ms 30000 \
|
|
435
|
+
--stability-resume-every 2 --output /absolute/path/to/stability-receipt.json
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
All three providers work concurrently. Each worker receives its whole burst
|
|
439
|
+
before the driver waits. Each reply must recall the original random marker
|
|
440
|
+
and the previous ticket from history, checking FIFO execution and retained
|
|
441
|
+
context. Duplicate submission IDs must yield exactly one reply and ACK.
|
|
442
|
+
Periodic worker close/resume and one normal owned-daemon restart preserve the
|
|
443
|
+
original sessions. Idle observation checks the control endpoint, pending
|
|
444
|
+
requests and identity. The final audit checks persisted deliveries, database
|
|
445
|
+
integrity, bounded event retention and absence of reply loops. Receipts retain
|
|
446
|
+
actual replies, failure state and owned-process memory samples. Failed work is
|
|
447
|
+
not replayed automatically or reclassified as successful after a retry.
|
|
448
|
+
|
|
449
|
+
Defaults are six cycles, two queued messages per worker per cycle, 30 seconds
|
|
450
|
+
of idle observation per cycle, and worker resume every two cycles. Limits are
|
|
451
|
+
1–24 cycles, 1–4 messages, 0–300000 idle milliseconds and a 1–24 cycle resume
|
|
452
|
+
interval. These options require `--stability`. This is bounded authenticated
|
|
453
|
+
work, not a 24-hour soak, capacity benchmark or proof of no memory leak. A
|
|
454
|
+
successful DSH resume alone does not explain earlier context fluctuations.
|
|
455
|
+
|
|
456
|
+
`--stability-only` requires `--stability`. It bootstraps three real sessions and
|
|
457
|
+
runs stability work while skipping the baseline interruption, command approval
|
|
458
|
+
and model MCP communication scenarios. The receipt records this scope; skipped
|
|
459
|
+
scenarios require separate evidence. On any failure, the driver captures current
|
|
460
|
+
session snapshots, recent deliveries and events before closing owned workers.
|
package/docs/native.zh-CN.md
CHANGED
|
@@ -48,6 +48,38 @@ npm install --no-save --package-lock=false @anthropic-ai/claude-agent-sdk@0.3.28
|
|
|
48
48
|
已有独立回执 (源码目录: `docs/verification/2026-10-02-native-web-claude-default-sdk.json`),不代表
|
|
49
49
|
发布包或员工设备已完成安装验收。
|
|
50
50
|
|
|
51
|
+
## 从 Web 新建
|
|
52
|
+
|
|
53
|
+
运行 `hcc web`,选择项目,再点击“新建 Agent”。Codex、Claude 和 DeepSeek Harness
|
|
54
|
+
默认使用“后台 Agent”,创建 native worker 并按需启动或复用该项目的独立 native
|
|
55
|
+
runtime。无需先运行 `hcc native start`;上述 provider 安装和认证要求仍然适用。
|
|
56
|
+
|
|
57
|
+
顶部“设置”可保存项目默认 provider,以及各 provider 的默认模型和项目内工作目录。
|
|
58
|
+
新建表单会预填这些值;未设置工作目录时使用项目根目录。worker 继续共享所选项目的
|
|
59
|
+
HCC 任务和消息总线。要在根目录之外工作,先选择或添加相应项目。“模型(可选)”
|
|
60
|
+
留空时使用 provider 当前配置,填写时需使用该 provider 支持的模型值;“名称(可选)”
|
|
61
|
+
留空时自动生成 peer 名称。
|
|
62
|
+
|
|
63
|
+
这些默认值只用于后续 Web 新建 native worker,不改变既有 worker、恢复或 CLI 启动。
|
|
64
|
+
配置由项目数据库保存,跨浏览器读取;并发保存发生冲突时需重新载入核对。详情见
|
|
65
|
+
[项目启动默认值](web-handoff.zh-CN.md#项目-agent-启动默认值)。
|
|
66
|
+
|
|
67
|
+
“新建 Agent”创建新 native 会话;项目栏“历史”中的“HCC 保留历史”可查看已保存的
|
|
68
|
+
worker,并显式恢复已关闭的 worker。恢复保留原 peer 和 provider 会话 ID,重新核对
|
|
69
|
+
所有权后启动新执行器。CLI resume 继续可用。“高级选项”保留终端 CLI、Codex App
|
|
70
|
+
Server 及各自原有的历史恢复操作。Shell 使用终端,DeepSeek Harness 使用后台 worker。
|
|
71
|
+
|
|
72
|
+
创建后在同一 Web 会话内发送提示、查看投递回执或处理审批。创建 worker 不代表模型
|
|
73
|
+
任务已经完成。关闭页面或停止 Web 都保留独立 native runtime 和 worker;不再需要时
|
|
74
|
+
明确关闭 worker。下方带日期的既有验收记录不代表这个新建入口已通过真实模型或发布
|
|
75
|
+
验收。详细操作见 [Web 指南](web-handoff.zh-CN.md)。
|
|
76
|
+
|
|
77
|
+
顶部“文件”可浏览项目文件与生成产物,也可显式上传新文件(最大 10 MiB)或编辑完整
|
|
78
|
+
UTF-8 文本(最大 1 MiB),无需创建 worker。同名上传不覆盖,文本保存会检查版本;
|
|
79
|
+
冲突或回执不确定时保留草稿。这些操作不会把文件发送给模型。详情见
|
|
80
|
+
[文件与产物预览](web-handoff.zh-CN.md#浏览文件与产物)及
|
|
81
|
+
[上传与编辑](web-handoff.zh-CN.md#上传与编辑项目文件)。
|
|
82
|
+
|
|
51
83
|
## CLI 使用
|
|
52
84
|
|
|
53
85
|
在需要共享状态的项目目录中运行,或使用已有全局 `--root`、`--db` 指定项目和数据库。
|
|
@@ -135,6 +167,11 @@ hcc native start --peer codex-reviewer --provider codex --resume last
|
|
|
135
167
|
的连接恢复会话历史,不是附着已有的活动 TUI 或桌面实例。HCC 无法证明外部应用
|
|
136
168
|
没有独立打开同一个保存会话,因此不要同时在 owned runtime 外写入该会话。
|
|
137
169
|
|
|
170
|
+
新保存的 worker 还记录工作目录的文件系统身份;即使路径文字未变,恢复前也必须
|
|
171
|
+
重新匹配该身份。缺少此证据的旧 worker 仍可在 HCC 历史中读取,但不能自动恢复;
|
|
172
|
+
人工核验与关联流程尚未实现。Web 历史会先标为不可恢复,native 服务在实际接纳时
|
|
173
|
+
再次校验。
|
|
174
|
+
|
|
138
175
|
worker 获得明确的 `HCC_ROOT`、`HCC_DB`、`HCC_PEER`、`HCC_NATIVE_OWNER`。provider hook
|
|
139
176
|
必须匹配该 peer 的 native transport owner。native hook 路径只刷新 owner 心跳和续
|
|
140
177
|
期其锁,不覆盖 provider binding 或进程身份、不再次注入 inbox、不 ACK 消息,也
|
|
@@ -213,7 +250,9 @@ Web 刷新执行状态时在页面内存中保留填写内容;提交、请求
|
|
|
213
250
|
|
|
214
251
|
- 尚未实现接管或 attach 已有 Codex/Claude/dsh TUI、桌面会话;这些会话继续使用原
|
|
215
252
|
transport。
|
|
216
|
-
- Web
|
|
253
|
+
- Web 可新建 Codex、Claude、dsh native worker,也可发现并控制同一项目的现有 worker,
|
|
254
|
+
提供消息、回执、中断和明确关闭。“历史”提供 HCC 保留事件与已关闭 worker 的显式恢复;
|
|
255
|
+
记录不是 provider 完整历史,活跃或停止未确认的 worker 不可从此入口恢复。
|
|
217
256
|
关闭页面或 Web runtime 保留独立 native worker;支持与当前执行器、turn 绑定的人工应答。
|
|
218
257
|
使用方式见 [Web 继续本地任务](web-handoff.zh-CN.md#本地-native-worker-接手)。
|
|
219
258
|
- Codex、Claude 和 dsh native worker 自动获得项目与 peer 受限的 HCC MCP;
|
|
@@ -312,3 +351,33 @@ provider 版本、源码摘要、浏览器证据和清理结果;脚本不会
|
|
|
312
351
|
消息总线送达的内容保持 peer 消息身份,即使发送方自称 `web` 或 `shell`。旧回执
|
|
313
352
|
迁移后仍按 peer 消息处理。来源区分不授予工具权限,写入等受控操作仍需审批。
|
|
314
353
|
委派文件任务时,先由用户明确授权接收 agent 的限定任务,再发送 peer 交接。
|
|
354
|
+
|
|
355
|
+
## 有界稳定性验收
|
|
356
|
+
|
|
357
|
+
安装包验收可加 `--stability`,在基础生命周期和跨 provider 通信之后运行持续负载:
|
|
358
|
+
|
|
359
|
+
```sh
|
|
360
|
+
node /absolute/path/to/acceptance-prefix/node_modules/@logicseek/hello-cc/scripts/native-installed-acceptance.mjs \
|
|
361
|
+
--run-live --codex-bin /absolute/path/to/codex --dsh-bin /absolute/path/to/dsh \
|
|
362
|
+
--archive /absolute/path/to/hello-cc.tgz --stability \
|
|
363
|
+
--stability-cycles 6 --stability-burst 2 --stability-idle-ms 30000 \
|
|
364
|
+
--stability-resume-every 2 --output /absolute/path/to/stability-receipt.json
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
三个 provider 同时工作,每轮先向各 worker 排队投递整组消息。每条要求模型从
|
|
368
|
+
历史中回忆原始随机标记和上一条消息的票据,验证串行处理顺序与上下文保留。
|
|
369
|
+
每轮还重复提交同一提交 ID,核对只产生一条回复与一个 ACK;定期关闭并恢复
|
|
370
|
+
worker,在中点正常重启自有 daemon,再验证原 session 和历史。空闲窗口继续
|
|
371
|
+
检查控制接口、pending 请求与会话身份。结束时核对持久投递、数据库完整性、
|
|
372
|
+
事件保留上限与无回复循环。回执保留每条实际回复、失败状态和自有进程内存
|
|
373
|
+
采样,不自动重放失败任务,也不把同轮重新尝试改写为成功。
|
|
374
|
+
|
|
375
|
+
默认 6 轮、每 worker 每轮 2 条、每轮空闲观察 30 秒、每 2 轮恢复。参数限制为
|
|
376
|
+
1–24 轮、1–4 条、0–300000 毫秒和 1–24 轮恢复间隔;这些选项必须与
|
|
377
|
+
`--stability` 一起使用。这是有界真实模型负载验收,不能代替 24 小时 soak、
|
|
378
|
+
并发容量测量或内存泄漏证明。DSH 单次恢复成功也不能单独解释历史恢复波动。
|
|
379
|
+
|
|
380
|
+
`--stability-only` 与 `--stability` 一起使用时,只建立三个真实会话并运行稳定性
|
|
381
|
+
负载,跳过基础中断、命令审批和模型 MCP 通信场景;回执明确标记该范围。
|
|
382
|
+
适合已有独立生命周期/交互回执时单独补做持续负载,不能把跳过项算作通过。
|
|
383
|
+
发生任一错误时,脚本在关闭自有 worker 前保存会话快照、最近投递和事件。
|
|
@@ -1,6 +1,92 @@
|
|
|
1
|
-
# Web
|
|
1
|
+
# Web 新建 Agent、项目文件与继续本地任务
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Web 可以直接新建 Codex、Claude 或 DeepSeek Harness 后台 Agent,也可以继续同一项目中已有的 native worker 或受管终端。
|
|
4
|
+
|
|
5
|
+
## 浏览文件与产物
|
|
6
|
+
|
|
7
|
+
选择项目后,点击顶部“文件”,即可浏览项目目录并打开已保存的文件,无需先创建 Agent。
|
|
8
|
+
支持逐层进入目录、返回上级、输入项目相对目录和刷新。会话中“引用与执行器能力”的文件
|
|
9
|
+
检索结果也可以直接打开预览;“引用文件”仍然只在消息草稿里加入路径标记。
|
|
10
|
+
|
|
11
|
+
| 文件类型 | 预览方式 |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| 文本、源代码 | 显示转义后的原文 |
|
|
14
|
+
| Markdown | 显示基本排版与代码块,可切回源码 |
|
|
15
|
+
| HTML | 隔离的静态预览,可切回源码;脚本、表单、导航和外部资源不运行 |
|
|
16
|
+
| PNG、JPEG、GIF、WebP | 图片预览 |
|
|
17
|
+
| PDF | 浏览器内置查看器;未支持内嵌显示时可下载查看 |
|
|
18
|
+
| SVG | 仅显示源码 |
|
|
19
|
+
| 其他二进制文件 | 提示暂不支持预览,不尝试按文本显示 |
|
|
20
|
+
|
|
21
|
+
预览只读取当前项目内的普通文件,不修改文件,也不会把内容上传给模型。
|
|
22
|
+
`dist`、`build` 等产物目录可以浏览;运行状态、依赖缓存及已知凭据路径不提供预览,
|
|
23
|
+
符号链接和硬链接也不读取。目录每次最多显示 500 项,并提示未完整列出的情况;
|
|
24
|
+
文本超过 1 MiB 时只显示前部并标记截断,截断 HTML 只显示源码。图片和 PDF 最大为
|
|
25
|
+
10 MiB,超过限制会明确提示。文件在读取期间变化时,请刷新后重试。
|
|
26
|
+
|
|
27
|
+
切换文件、切换项目或关闭预览会使旧请求失效。手机可在目录与预览之间返回切换;
|
|
28
|
+
分屏辅助窗口的文件入口会在同一项目的主窗口中打开。静态预览不会启动生成网页所需的
|
|
29
|
+
开发服务器。
|
|
30
|
+
|
|
31
|
+
## 上传与编辑项目文件
|
|
32
|
+
|
|
33
|
+
在“文件”中进入目标目录,选择一个本机文件并核对目标文件名,再点击上传。文件会保存到
|
|
34
|
+
运行 HCC 的机器上当前项目的这个目录,单文件最大 10 MiB;不自动创建目录,不覆盖同名
|
|
35
|
+
文件。上传不是聊天附件发送,不会自动让 Agent 读取文件。要在任务中引用文件,仍需在
|
|
36
|
+
消息中明确引用项目路径。
|
|
37
|
+
|
|
38
|
+
完整的 UTF-8 文本、源码、Markdown 和 HTML 可以切换到编辑模式,修改后显式保存。
|
|
39
|
+
编辑上限为 1 MiB,截断预览和二进制文件不能在线编辑。UTF-8 BOM 与原有 CRLF 换行会
|
|
40
|
+
保留;混合换行文件会提示保存时统一为 LF。没有编辑过的文本不能重复保存。
|
|
41
|
+
保存前核对读取时的文件版本;
|
|
42
|
+
另一窗口或本地程序已修改文件时,保留草稿并显示冲突,核对磁盘内容后再决定如何处理。
|
|
43
|
+
HCC 的同文件写入会串行化;本地编辑器等其他程序不共享这个锁,因此这不是对任意外部
|
|
44
|
+
写入的系统级原子版本交换。保存通过同目录临时文件替换,避免向读者暴露半写的文本。
|
|
45
|
+
|
|
46
|
+
切换文件、项目或关闭文件窗口会保留当前页面内的编辑草稿;刷新或关闭整个页面仍可能
|
|
47
|
+
丢失未保存内容。“返回预览”保留草稿,“放弃草稿并重载”会先确认再丢弃。
|
|
48
|
+
遇到断线或写入回执不确定时,使用“读取已保存文件”核对文本,或“核对目标文件”比较
|
|
49
|
+
上传文件的大小和内容哈希;不会自动重发保存或上传。上传回执恢复只在浏览器保存项目
|
|
50
|
+
身份、路径、大小和哈希,不保存上传文件内容。
|
|
51
|
+
|
|
52
|
+
上传、编辑与预览沿用相同的项目路径限制,不允许修改运行状态、依赖缓存、已知凭据路径、
|
|
53
|
+
符号链接或硬链接。写入固定到经验证的目标父目录身份,不会跟随被替换的项目路径去写
|
|
54
|
+
另一个目录;如果原目录在写入中被移动,需重新选择当前位置并核对写入结果。
|
|
55
|
+
|
|
56
|
+
## 项目 Agent 启动默认值
|
|
57
|
+
|
|
58
|
+
顶部“设置”中可保存当前项目的默认 Agent,以及 Codex、Claude、DeepSeek Harness
|
|
59
|
+
各自的默认模型和工作目录。它们保存在所选项目的 HCC 数据库中,可供其他浏览器读取;
|
|
60
|
+
语言、主题、密度和字号仍是当前浏览器的显示偏好。
|
|
61
|
+
|
|
62
|
+
模型留空表示使用 provider 自身的当前配置;HCC 不会推测该配置中的模型,也不在保存时
|
|
63
|
+
调用模型验证名称。工作目录保存为项目相对路径,`.` 表示项目根目录,其他值必须指向
|
|
64
|
+
现有的项目内目录。新建时会再次检查目录,已经删除或移到项目外的目录不能用来启动。
|
|
65
|
+
|
|
66
|
+
保存后,“新建 Agent”会预填相应 provider 的模型和目录,本次创建仍可修改。取消后再打开
|
|
67
|
+
会保留尚未提交的草稿;默认值读取或重试不会覆盖已编辑的字段。成功创建后,下一次新建
|
|
68
|
+
重新读取项目默认值。清空模型表示本次使用 provider 默认配置,可以覆盖已保存的项目模型。
|
|
69
|
+
新值只用于后续 Web 新建 native worker;既有 worker、历史恢复、CLI 启动及高级终端/
|
|
70
|
+
App Server 流程各自沿用原有配置。此处不管理 provider 登录、API key、端点、环境变量
|
|
71
|
+
或全局配置文件。
|
|
72
|
+
|
|
73
|
+
保存使用版本校验。其他窗口先保存后,当前窗口会显示冲突并保留输入,需重新载入并
|
|
74
|
+
核对最新值;不会静默覆盖其他窗口的修改。“恢复初始值”先重置表单,保存后才生效。
|
|
75
|
+
如果保存响应因断线而不确定,先重新读取配置核对结果。
|
|
76
|
+
|
|
77
|
+
## 新建后台 Agent
|
|
78
|
+
|
|
79
|
+
运行 `hcc web`,选择项目,再点击“新建 Agent”。选择 Codex、Claude 或 DeepSeek Harness 后,默认使用“后台 Agent”;无需预先运行 `hcc native start`。对应 CLI 或 Claude SDK 仍需已安装,身份认证沿用运行 hello-cc 的环境,Web 不代为安装或登录。
|
|
80
|
+
|
|
81
|
+
工作目录使用该项目为此 provider 保存的默认值,未设置时为项目根目录,可改为项目内的子目录;worker 仍共享所选项目的任务、消息、锁和交接。需要在另一个项目工作时,先切换或添加该项目。模型预填项目中保存的默认值,也可在本次创建时修改或清空;留空使用 provider 当前配置,填写时应使用该 provider 支持的模型值。名称可留空自动生成。
|
|
82
|
+
|
|
83
|
+
“新建 Agent”用于创建新的 native worker;恢复已关闭的 worker,请使用项目栏“历史”中的“HCC 保留历史”。既有 `hcc native start` 和 `--resume last` CLI 继续可用。创建后在同一 Web 会话内发送提示、查看回执和处理审批;创建成功不代表已经运行模型任务。关闭页面或停止 Web runtime 都不会停止独立的 native runtime/worker,需要明确执行关闭操作。
|
|
84
|
+
|
|
85
|
+
“高级选项”保留终端 CLI、Codex 的结构化 App Server 及它们原有的恢复流程。Shell 使用终端,DeepSeek Harness 使用后台 Agent。以下交接说明分别适用于这些执行方式。
|
|
86
|
+
|
|
87
|
+
## 继续已有终端
|
|
88
|
+
|
|
89
|
+
CLI/tmux 适合继续已经托管的本地 Codex/Claude/shell:Web 打开同一个 pane,不另起执行器。
|
|
4
90
|
|
|
5
91
|
运行 `hcc web` 后选择已有会话。选中项和未发送草稿按项目保存于当前浏览器;刷新会恢复原位置。第一个 Web 连接取得控制,其他窗口可观察,点击“接管浏览器控制”后才可写入。服务端检查控制 epoch,旧窗口不能继续输入、改变终端尺寸、修改该 peer 或处理审批。本地 tmux client 仍可直接输入,Web 会显示其连接状态。
|
|
6
92
|
|
|
@@ -10,10 +96,12 @@
|
|
|
10
96
|
|
|
11
97
|
## Codex 结构化界面
|
|
12
98
|
|
|
13
|
-
|
|
99
|
+
在“新建 Agent”中选择 Codex,展开“高级选项”并选择结构化 App Server。需要本地已安装且支持 App Server 的 `codex`,登录和模型环境来自启动 hello-cc 的进程。hello-cc 不自动登录、不更改信任配置、不探测未公开的 TUI 内部 endpoint。
|
|
14
100
|
|
|
15
101
|
可先运行 `hcc doctor --codex --json` 查看只读诊断。它分别报告已安装版本、CLI help 声明的 App Server 启动参数、hooks 配置与项目中的 hook 调用记录;这些事实不等于完整 RPC 能力、hooks 已受信任、stdout 投递成功或模型已接收。版本/help 探测使用独立临时 HOME/CODEX_HOME 并清理,防止 Codex 启动文件触碰用户目录;hooks 配置仍从原路径只读检查。没有充分回执的状态显示 `unknown`,不会自动触发 hook 或修改 trust。普通 `hcc doctor` 仍只检查数据库。
|
|
16
102
|
|
|
103
|
+
升级 Codex 前可运行 `npm run codex:protocol -- --codex-bin /absolute/path/to/codex --out /tmp/hcc-protocol-new`。输出目录必须不存在;工具使用隔离 HOME/CODEX_HOME 生成官方 TypeScript 和 JSON Schema,记录版本/文件指纹并检查交接所依赖的协议子集。不兼容时返回非零退出码,未接入请求单独列出;生成成功不代表真实模型或外部授权验收。安装包内也可直接运行 `node /absolute/path/to/hello-cc/scripts/codex-protocol.mjs`。详见 `docs/codex-protocol.md`。
|
|
104
|
+
|
|
17
105
|
结构化界面提供消息、当前 turn 状态、追加指令、轮次中断、计划、差异和人工交互。命令/文件审批以及空表单 MCP 工具确认由当前控制窗口明确批准本次或拒绝。文件与网络权限可逐项勾选,并明确选择本轮或会话有效期;只能授予原请求的子集。问题支持选项、其他/自由输入和敏感答案,需逐题明确填写。接管控制本身不会批准工具。
|
|
18
106
|
|
|
19
107
|
表单输入与焦点会跨状态刷新保留,直接答案不写入 HCC 状态、事件、回执或浏览器存储。原 turn 完成、中断成功、provider 解决请求或执行器关闭后,请求卡片失效;旧控制窗口不能用过期 epoch 应答。参数被截断时只能拒绝或取消。MCP 支持下述标准表单和带原 thread/turn 标识的 URL 请求;嵌套对象、任意数组等复杂结构、动态工具及账号 token 刷新尚未接入。
|
|
@@ -36,7 +124,7 @@ MCP 标准表单可以直接在 Web 填写文本、数值、是/否和单选/多
|
|
|
36
124
|
|
|
37
125
|
## 本地 native worker 接手
|
|
38
126
|
|
|
39
|
-
|
|
127
|
+
已有 worker 可以继续从 CLI 启动,例如 `hcc native start --peer codex-worker --provider codex`,再打开 Web 的同一项目;也可直接使用上方的新建入口。Web 自动发现实际仍由 native runtime 持有的 worker,显示其原 peer/session、事件和投递回执;接手已有 worker 后的发送、中断和明确关闭都通过原 runtime 执行,不另建 provider 子进程。Claude/dsh worker 也走这条路径,按实际能力显示中断操作。
|
|
40
128
|
|
|
41
129
|
发送成功先显示队列回执;执行器接收、运行和完成分别使用实际投递状态。断线或不确定结果保留 submission ID,刷新不会重放消息。native runtime 重启或 worker 被替换时,旧 Web 视图及其控制凭证失效,重新发现当前 worker 后才能操作。
|
|
42
130
|
|
|
@@ -46,14 +134,28 @@ MCP 标准表单可以直接在 Web 填写文本、数值、是/否和单选/多
|
|
|
46
134
|
|
|
47
135
|
## 历史、协作工具与结果审阅
|
|
48
136
|
|
|
49
|
-
|
|
137
|
+
项目栏“历史”默认打开“HCC 保留历史”,可按 Codex、Claude、DeepSeek Harness 筛选当前项目的 native worker,查看已保留的 provider 事件与投递回执。native runtime 离线时仍可读取已保存记录;浏览历史不会启动 provider 或模型 turn。
|
|
138
|
+
|
|
139
|
+
worker 列表最多显示最近 100 项,超过时提示截断。事件每页 100 条,可以前后翻页;投递回执显示该 worker 最新 100 条。当前存储只保留整个项目最近约 2,000 条 provider 事件;这不是 provider 的完整对话档案。历史中可能没有最初输入、早期已裁剪事件或尚未被 HCC 记录的输出。DSH ACP 恢复本身也不代表原始对话重放。
|
|
140
|
+
|
|
141
|
+
恢复前先明确关闭原 worker,再选中历史项并确认。后端只接受已记录为 `closed`、原 peer/provider/session 与 owner 仍一致的记录;运行中、断连、失败或退出未确认的记录不能从此入口恢复。恢复沿用原 peer、provider 会话和工作目录,创建新的 native 执行器;不会重放已处理或投递状态不明的消息,尚未执行的队列消息会按现有 native 队列规则继续。provider 安装和账号要求仍然适用,DSH 还需实际 ACP runtime 声明 resume 能力。
|
|
142
|
+
|
|
143
|
+
恢复请求只提交一次。断线或响应丢失后,页面保留原恢复记录,通过刷新查找同一 peer 的新执行器;不会自动重新恢复。浏览器刷新后也可继续检查结果。恢复成功仅表示执行器已接入,Claude SDK 的会话初始化仍可能等到第一条新提示后才确认。
|
|
144
|
+
|
|
145
|
+
选择“Codex 已保存会话”,可分页浏览当前项目已保存的 thread,读取上下文,再显式恢复或分叉。恢复仍要求旧执行器已确认停止;分叉生成新的 thread/peer,原任务 owner 不变。有正在托管的源会话时,分叉也必须取得该会话的浏览器控制。历史读取不会启动模型 turn。
|
|
50
146
|
|
|
51
147
|
Web 专用 Codex App Server,以及由 HCC 托管的 Codex/Claude/dsh native worker,自动接入 [项目与 peer 受限的 MCP 协作工具](mcp.zh-CN.md)。配置只传给对应执行器或 worker,不写全局 provider 配置;关闭 worker 前撤销其临时权限。模型可查询任务与 inbox、领取任务、发送消息、写 handoff、获取/释放自己的资源锁和记录本地证据;不替用户执行发布或业务验收。
|
|
52
148
|
|
|
53
149
|
会话栏“结果审阅”汇总结构化 command 的执行状态与退出码、是否有 turn 差异、模型通过 MCP 明确提交的本地证据,以及人工添加的验收记录。自动结果仅在实时观察到新 turn 开始后归属当前任务;缺失该事件时,不会从历史快照补认任务证据。自动结果在项目数据库 events 中只保存中性标题、状态、退出码和来源 ID,不保存命令、输出或差异正文;正文仍可在可用的执行器会话或 provider 历史中查看。命令退出成功仅说明该命令成功;人工填写“通过”必须附证据引用。界面分别展示本地验证、发布部署、业务验收,并注明记录来源。turn 完成、测试记录或人工验收均不自动改变 hcc task 状态。`gc --history` 保留结果审计记录和最小提交去重凭据。
|
|
54
150
|
|
|
151
|
+
## Codex 账号与限额
|
|
152
|
+
|
|
153
|
+
Web 专用 Codex 和原生 Codex worker 新增只读“账号与限额”面板,观察窗口也可刷新。它显示本执行器的登录/供应商认证状态、可获取的订阅窗口、重置时间和读取时间;缺失或不支持的配额保持未知,账号切换与执行器替换拒绝旧查询结果。此操作不新建任务或 turn,也不提供登录、退出或 token 管理。未登录时需在运行任务的电脑完成本地 Codex 登录。使用方式、接口身份和真实/模拟验收边界见 [账号与限额说明](codex-account.zh-CN.md)。
|
|
154
|
+
|
|
55
155
|
## 验收边界
|
|
56
156
|
|
|
157
|
+
以下既有记录分别对应当时的执行器、交接和交互流程,不代表新增的统一“新建 Agent”、项目启动默认值、文件上传编辑、HCC 历史或 Web native 恢复入口已完成真实模型或发布验收。
|
|
158
|
+
|
|
57
159
|
本地验证包含真实 SQLite/HTTP、模拟交互请求、隔离 tmux 与桌面/手机浏览器。安装版 Codex 0.144.6 的协议验收另行覆盖 initialize、thread/start/list、10 个 MCP 工具发现和实际 `hcc_state` 读回;此协议检查不调用模型,可用 `node scripts/web-handoff-installed-acceptance.mjs` 重现。
|
|
58
160
|
|
|
59
161
|
真实模型验收已在隔离项目和 Codex home 中完成“本地 → Web → 本地”三段文件任务,全程保持原 Codex 进程和 thread;关闭 Web runtime 后仍可继续。可用 `scripts/web-native-model-acceptance.mjs` 在明确需要真实模型调用时重现。三种 provider 的真实生命周期、模型 MCP 发信、回复/ACK 和无回复循环另有独立回执。交互表单另有 11 项模拟 provider 浏览器检查。真实 Codex 已经完成“提问 → Web 答复 → 指定文件权限 → 本轮授权 → 写入所选答案 → 后续请求拒绝 → 本地继续”的验收;默认加载的 Claude SDK 已完成真实 Write 工具批准、拒绝和本地续接。dsh 已完成真实 ACP 写入的 Web 批准、拒绝和原 session 本地续接,审批卡片另通过桌面与 390px 手机检查;仅在隔离 profile 中对指定验收文件设置公开审批策略。完整结果与运行条件见 本地验收记录 (源码目录: `docs/verification/2026-10-02-web-local-task-handoff.md`)。
|
package/lib/cli/app.mjs
CHANGED
|
@@ -54,7 +54,8 @@ import { readPackageMeta } from '../package-meta.mjs';
|
|
|
54
54
|
import { removeGuidanceBlocks as removeGuidanceBlocksForRoot, writeGuidance as writeGuidanceForRoot } from '../guidance.mjs';
|
|
55
55
|
import { globalRuntimePath, runtimePath } from '../runtime/paths.mjs';
|
|
56
56
|
import { readRuntime, reclaimRuntimePointerFiles } from '../runtime/state.mjs';
|
|
57
|
-
import { waitForProcessIdentityExit } from '../process/identity.mjs';
|
|
57
|
+
import { waitForProcessIdentityExit, inspectProcessIdentity, compareProcessIdentity } from '../process/identity.mjs';
|
|
58
|
+
import { withFileLock } from '../shared/file-lock.mjs';
|
|
58
59
|
|
|
59
60
|
import { runtimeRequest } from '../runtime/client.mjs';
|
|
60
61
|
|
|
@@ -322,7 +323,7 @@ const { cmdDown, cmdFindRoot, cmdWhichReal } = createMiscCommands({
|
|
|
322
323
|
path, fs, process, CliError, parseOpts, printResult,
|
|
323
324
|
readRuntime, runtimeRequest, runtimePath, globalRuntimePath,
|
|
324
325
|
reclaimRuntimePointerFiles, helpDown, loadSetup,
|
|
325
|
-
waitForProcessIdentityExit,
|
|
326
|
+
waitForProcessIdentityExit, inspectProcessIdentity, compareProcessIdentity, withFileLock,
|
|
326
327
|
PRODUCT_NAME
|
|
327
328
|
});
|
|
328
329
|
|
|
@@ -507,8 +508,9 @@ function webErrorStatus(err) {
|
|
|
507
508
|
if (!(err instanceof CliError)) return 500;
|
|
508
509
|
if (err.code === 'REGISTRY_BUSY') return 503;
|
|
509
510
|
if (err.code === 'CODEX_START_FAILED') return 503;
|
|
511
|
+
if (err.code === 'PROJECT_PATH_CHANGED') return 409;
|
|
510
512
|
if (err.code.startsWith('CODEX_') || ['STALE_CONTROL_EPOCH', 'UNKNOWN_CONTROL_CLIENT'].includes(err.code)) return 409;
|
|
511
|
-
if (['BAD_ARGS', 'BAD_REQUEST', 'PEER_IDENTITY_REQUIRED', 'REQUEST_TOO_LARGE'].includes(err.code)) return 400;
|
|
513
|
+
if (['BAD_ARGS', 'BAD_REQUEST', 'PEER_IDENTITY_REQUIRED', 'REQUEST_TOO_LARGE', 'INTERACTION_RESPONSE_INVALID'].includes(err.code)) return 400;
|
|
512
514
|
if (['PEER_IDENTITY_MISMATCH', 'TASK_OWNED', 'TASK_OWNER_MISMATCH', 'LOCK_OWNED', 'PROJECT_NOT_REGISTERED', 'PROJECT_PATH_FORBIDDEN', 'RUNTIME_ADMIN_REQUIRED'].includes(err.code)) return 403;
|
|
513
515
|
if (err.code.startsWith('NATIVE_')) return err.code === 'NATIVE_RUNTIME_OFFLINE' ? 503 : 409;
|
|
514
516
|
if (['NOT_FOUND'].includes(err.code)) return 404;
|
|
@@ -576,11 +578,12 @@ function formatHookEventName(hookType) {
|
|
|
576
578
|
}
|
|
577
579
|
|
|
578
580
|
function writeGuidance(ctx) {
|
|
579
|
-
return writeGuidanceForRoot(ctx.root);
|
|
581
|
+
return writeGuidanceForRoot(ctx.root, { expectedSnapshot: ctx.initialRootIdentity });
|
|
580
582
|
}
|
|
581
583
|
|
|
582
|
-
function removeGuidanceBlocks(ctx) {
|
|
583
|
-
return removeGuidanceBlocksForRoot(ctx.root
|
|
584
|
+
function removeGuidanceBlocks(ctx, options = {}) {
|
|
585
|
+
return removeGuidanceBlocksForRoot(ctx.root,
|
|
586
|
+
{ expectedSnapshot: ctx.initialRootIdentity, ...options });
|
|
584
587
|
}
|
|
585
588
|
|
|
586
589
|
function cmdMigrateState(ctx, args) {
|
|
@@ -163,8 +163,13 @@ export function createCoordinationCommands(deps) {
|
|
|
163
163
|
const kind = opts.kind || 'ask';
|
|
164
164
|
const runtime = opts.inject ? readRuntime(ctx) : null;
|
|
165
165
|
const db = connect(ctx);
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
let id;
|
|
167
|
+
try {
|
|
168
|
+
touchCurrentPeer(db, ctx, identity, null, 'shell');
|
|
169
|
+
id = sendMessage(db, sender, recipient, taskId, kind, body);
|
|
170
|
+
} finally {
|
|
171
|
+
db.close();
|
|
172
|
+
}
|
|
168
173
|
let injected = false;
|
|
169
174
|
if (opts.inject) {
|
|
170
175
|
await injectPeer(ctx, recipient, body, !opts['no-enter'], runtime, sender);
|
package/lib/cli/commands/gc.mjs
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
} from '../../core/coordination/gc-plan.mjs';
|
|
26
26
|
import { runOptimisticEvidenceMutation } from '../../core/coordination/optimistic-evidence.mjs';
|
|
27
27
|
import { peerEvidenceAllowsReap } from '../../core/peers/evidence.mjs';
|
|
28
|
-
import {
|
|
28
|
+
import { globalRuntimePath } from '../../runtime/paths.mjs';
|
|
29
29
|
import { resolveProjectDatabase } from '../../runtime/project-path.mjs';
|
|
30
30
|
import { readRuntime, reclaimRuntimePointerFiles } from '../../runtime/state.mjs';
|
|
31
31
|
import { runtimeRequest, runtimeBufferGcUnavailable } from '../../runtime/client.mjs';
|
|
@@ -58,6 +58,10 @@ export function createGcCommands(deps) {
|
|
|
58
58
|
// stale bufs) so automatic background gc bounds DB growth without deleting
|
|
59
59
|
// user-meaningful history.
|
|
60
60
|
// `db` is used open; the caller owns its lifecycle.
|
|
61
|
+
function bufferDirectory(ctx) {
|
|
62
|
+
return path.join(resolveProjectDatabase({ root: ctx.root, createStateDir: false }).stateDir, BUFS_DIR_NAME);
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
function captureGcClockSubject(db, {
|
|
62
66
|
bufferGcCutoffs,
|
|
63
67
|
olderThanDays,
|
|
@@ -628,10 +632,6 @@ function runGcWithHistorySnapshot(ctx, db, {
|
|
|
628
632
|
return results;
|
|
629
633
|
}
|
|
630
634
|
|
|
631
|
-
function bufferDirectory(ctx) {
|
|
632
|
-
return path.join(resolveProjectDatabase({ root: ctx.root, createStateDir: false }).stateDir, BUFS_DIR_NAME);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
635
|
function bufferDirectoryPaths(directory) {
|
|
636
636
|
try {
|
|
637
637
|
return fs.readdirSync(directory).map((name) => path.resolve(directory, name));
|
|
@@ -659,16 +659,16 @@ function localBufferEvidence(ctx, db, directory, unknownTracker = null, candidat
|
|
|
659
659
|
});
|
|
660
660
|
}
|
|
661
661
|
|
|
662
|
-
function runtimePointerPresent(
|
|
662
|
+
function runtimePointerPresent(localPointer) {
|
|
663
663
|
return Boolean(process.env.HCC_RUNTIME_URL ||
|
|
664
|
-
fs.existsSync(
|
|
664
|
+
fs.existsSync(localPointer) ||
|
|
665
665
|
fs.existsSync(globalRuntimePath()));
|
|
666
666
|
}
|
|
667
667
|
|
|
668
|
-
function reclaimUnavailableRuntimePointers(
|
|
668
|
+
function reclaimUnavailableRuntimePointers(localPointer, { dryRun = false } = {}) {
|
|
669
669
|
if (process.env.HCC_RUNTIME_URL) return { allowed: false, gcCutoffs: [] };
|
|
670
670
|
const gcCutoffs = [];
|
|
671
|
-
const result = reclaimRuntimePointerFiles([
|
|
671
|
+
const result = reclaimRuntimePointerFiles([localPointer, globalRuntimePath()], {
|
|
672
672
|
dryRun,
|
|
673
673
|
onReclaim: ({ gcCutoff }) => {
|
|
674
674
|
if (Number.isSafeInteger(gcCutoff)) gcCutoffs.push(gcCutoff);
|
|
@@ -718,15 +718,17 @@ function deferredPreparedBufferGc(prepared, graceActive = false) {
|
|
|
718
718
|
}
|
|
719
719
|
|
|
720
720
|
async function prepareManualBufferGc(ctx, db, { retentionSec, dryRun }) {
|
|
721
|
-
const
|
|
721
|
+
const stateDir = resolveProjectDatabase({ root: ctx.root, createStateDir: false }).stateDir;
|
|
722
|
+
const directory = path.join(stateDir, BUFS_DIR_NAME);
|
|
723
|
+
const localPointer = path.join(stateDir, 'runtime.json');
|
|
722
724
|
const unknownTracker = new Map();
|
|
723
725
|
const pointerGcCutoffs = [];
|
|
724
726
|
const recoverRuntimePointers = () => {
|
|
725
|
-
const recovery = reclaimUnavailableRuntimePointers(
|
|
727
|
+
const recovery = reclaimUnavailableRuntimePointers(localPointer, { dryRun });
|
|
726
728
|
pointerGcCutoffs.push(...recovery.gcCutoffs);
|
|
727
729
|
return recovery.allowed;
|
|
728
730
|
};
|
|
729
|
-
const pointerPresent = runtimePointerPresent(
|
|
731
|
+
const pointerPresent = runtimePointerPresent(localPointer);
|
|
730
732
|
let runtime = null;
|
|
731
733
|
try { runtime = readRuntime(ctx); } catch (error) {
|
|
732
734
|
if (pointerPresent && !recoverRuntimePointers()) {
|
|
@@ -5,6 +5,7 @@ import { parseOpts, validateOpts } from '../../cli-args.mjs';
|
|
|
5
5
|
import { tx } from '../../db/schema.mjs';
|
|
6
6
|
import { resolveProjectDatabase } from '../../runtime/project-path.mjs';
|
|
7
7
|
import { projectDbPath } from '../../runtime/paths.mjs';
|
|
8
|
+
import { HOOK_ROOT_IDENTITY_ENV, assertHookRootIdentity } from '../../core/sessions/hook-root-identity.mjs';
|
|
8
9
|
|
|
9
10
|
export function createHookCommand(deps) {
|
|
10
11
|
const {
|
|
@@ -86,11 +87,22 @@ async function cmdHook(ctx, args) {
|
|
|
86
87
|
const hccRoot = (nativeOwner || !isDsh) && process.env.HCC_ROOT
|
|
87
88
|
? path.resolve(process.env.HCC_ROOT)
|
|
88
89
|
: path.resolve(hookCwd);
|
|
90
|
+
// First-party launches carry the original directory inode. Reject a stale
|
|
91
|
+
// callback before database resolution or project activity can target a new
|
|
92
|
+
// directory installed at the old pathname. dsh service hooks are intentionally
|
|
93
|
+
// payload-scoped and do not inherit a service-wide project identity.
|
|
94
|
+
const launchRootIdentity = (!isDsh || nativeOwner)
|
|
95
|
+
? assertHookRootIdentity(hccRoot, process.env[HOOK_ROOT_IDENTITY_ENV]) : null;
|
|
89
96
|
|
|
90
97
|
const dshProject = isDsh && !nativeOwner ? resolveProjectDatabase({ root: hccRoot, createStateDir: false }) : null;
|
|
91
98
|
const nativeProject = nativeOwner ? resolveProjectDatabase({ root: hccRoot,
|
|
92
99
|
db: process.env.HCC_DB, createStateDir: false }) : null;
|
|
93
|
-
const
|
|
100
|
+
const sameHookRoot = () => {
|
|
101
|
+
if (!ctx.root) return false;
|
|
102
|
+
try { return fs.realpathSync(ctx.root) === fs.realpathSync(hccRoot); }
|
|
103
|
+
catch { return path.resolve(ctx.root) === hccRoot; }
|
|
104
|
+
};
|
|
105
|
+
const ordinaryDb = (sameHookRoot() ? ctx.dbPath : null) ||
|
|
94
106
|
process.env.HCC_DB;
|
|
95
107
|
if (nativeProject && !fs.existsSync(nativeProject.db)) {
|
|
96
108
|
throw new CliError('NATIVE_HOOK_OWNERSHIP_MISMATCH', 'Native hook database must already be owned by its runtime');
|
|
@@ -100,9 +112,9 @@ async function cmdHook(ctx, args) {
|
|
|
100
112
|
const hookCtx = {
|
|
101
113
|
...ctx,
|
|
102
114
|
root: nativeProject?.root || dshProject?.root || hccRoot,
|
|
103
|
-
dbPath: nativeProject?.db || dshProject?.db || ordinaryDefaultDb || path.resolve(ordinaryDb)
|
|
115
|
+
dbPath: nativeProject?.db || dshProject?.db || ordinaryDefaultDb || path.resolve(ordinaryDb),
|
|
116
|
+
...(launchRootIdentity ? { initialRootIdentity: launchRootIdentity } : {})
|
|
104
117
|
};
|
|
105
|
-
if (!nativeOwner) registerProjectActivity(hookCtx);
|
|
106
118
|
|
|
107
119
|
// dsh uses only its true session ID. Ordinary hooks retain environment,
|
|
108
120
|
// resume, session, and terminal identity precedence.
|
|
@@ -123,6 +135,7 @@ async function cmdHook(ctx, args) {
|
|
|
123
135
|
// Hook delivery must not migrate another workspace's registered database.
|
|
124
136
|
const db = isDsh || nativeOwner ? connect(hookCtx, { migrateRegistered: false }) : connect(hookCtx);
|
|
125
137
|
try {
|
|
138
|
+
if (!nativeOwner) registerProjectActivity(hookCtx);
|
|
126
139
|
if (nativeOwner) {
|
|
127
140
|
// Native delivery owns context injection and completion receipts. Hooks
|
|
128
141
|
// only renew its verified owner, never turn a native binding into a
|