cmdr-mcp 0.2.0 → 0.3.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/.claude-plugin/marketplace.json +1 -1
- package/README.md +3 -3
- package/docs/README.zh-CN.md +1 -1
- package/docs/agent-integration.md +6 -2
- package/docs/cmdr-design-v1.md +2 -0
- package/docs/implementation.md +33 -3
- package/docs/long-running-collaboration.md +53 -14
- package/docs/publishing.md +8 -8
- package/docs/troubleshooting.md +6 -0
- package/docs/zcode-desktop-session-visibility.md +172 -0
- package/marketplace.json +1 -1
- package/package.json +1 -1
- package/plugins/cmdr/.claude-plugin/plugin.json +1 -1
- package/plugins/cmdr/.codex-plugin/plugin.json +1 -1
- package/plugins/cmdr/.zcode-plugin/plugin.json +1 -1
- package/plugins/cmdr/README.md +1 -1
- package/plugins/cmdr/commands/cmdr.md +1 -1
- package/plugins/cmdr/dist/cli.mjs +129 -23
- package/plugins/cmdr/dist/daemon.mjs +396 -86
- package/plugins/cmdr/dist/hook.mjs +1 -1
- package/plugins/cmdr/dist/integrity.json +12 -12
- package/plugins/cmdr/dist/mcp.mjs +3 -3
- package/plugins/cmdr/skills/cmdr-commander/SKILL.md +1 -1
- package/plugins/cmdr/skills/cmdr-executor/SKILL.md +2 -2
- package/plugins/cmdr/skills/using-cmdr/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -78,10 +78,10 @@ Joining by name atomically creates or finds a persistent channel and defaults to
|
|
|
78
78
|
2. The commander inspects `list`, then `send`s clear tasks with acceptance criteria.
|
|
79
79
|
3. Executors `read`, immediately acknowledge with `report(status="working", reply_to=<command id>)`, do the work, then report done/failed/cancelled with the same `reply_to`.
|
|
80
80
|
4. Executors use `ask` when blocked; the commander responds with `send(type="answer", reply_to=<ask id>)`.
|
|
81
|
-
5. Use `join(..., standby="auto")
|
|
81
|
+
5. Use `join(..., standby="auto")`. Claude/ZCode then arm `listener.arm.command` with its indicated native tool. Inspect `list` for listener health. With `can_auto_respond=true`, end the idle turn. Unsupported hosts remain manual; the skills bound fallback polling to two waits and explain manual continuation.
|
|
82
82
|
6. `leave` preserves queued messages. Commander departure orphans the squad; `leave(dissolve=true)` disbands it.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Codex wakes through app-server proxy or the `codex queue` fallback. Claude uses Monitor and ZCode uses background Bash completion through the built-in `cmdr standby watch`; re-arm after task termination. See [Long-running collaboration](docs/long-running-collaboration.md) for capabilities, recovery, handover and compatibility requirements.
|
|
85
85
|
|
|
86
86
|
## Tools
|
|
87
87
|
|
|
@@ -160,6 +160,6 @@ npm run verify:zcode # optional: requires the locally installed ZCode desktop
|
|
|
160
160
|
|
|
161
161
|
For development, `claude --plugin-dir ./plugins/cmdr` loads the plugin directly. Installed hosts use cached copies: reinstall/refresh after changing a plugin. Version numbers come from `package.json`; after same-version changes, restart the daemon explicitly. Generated bundles and third-party license notices are ignored by Git and included in the npm package.
|
|
162
162
|
|
|
163
|
-
v1 is single-machine, single-user, Unix-socket-only. There is no network listener, remote transport
|
|
163
|
+
v1 is single-machine, single-user, Unix-socket-only. There is no network listener, remote transport or executor-to-executor messaging. Agent session creation is outside the current scope. Host GUI interaction and live model behavior are distinct from the automated runtime checks; see the [verification record](docs/implementation.md).
|
|
164
164
|
|
|
165
165
|
[MIT](LICENSE)
|
package/docs/README.zh-CN.md
CHANGED
|
@@ -72,7 +72,7 @@ ZCode 桌面端:打开工作区,在 **设置 → 插件 → 创建 → 添
|
|
|
72
72
|
|
|
73
73
|
执行方加入后 `report(ready)` 报到,说明目录、能力和当前上下文。指挥官通过 `list` 看成员,用 `send` 下发可验证任务。执行方 `read` 读取任务后立即用 `report(working, reply_to=<command id>)` 接单,再带相同 `reply_to` 汇报 done/failed/cancelled,遇到阻塞用 `ask` 提问;指挥官通过 `send(type="answer", reply_to=<ask id>)` 回答。
|
|
74
74
|
|
|
75
|
-
加入时设置 `standby="auto"
|
|
75
|
+
加入时设置 `standby="auto"`,再按 `listener.arm` 和 `list` 的健康状态操作。Codex 由 daemon 自动探测 proxy,并在不可用时尝试 `codex queue`;Claude 使用原生 Monitor,ZCode 使用 `run_in_background=true` 的后台 Bash,两者都运行内置 `cmdr standby watch`。宿主 watcher 真正挂载后才显示 `can_auto_respond=true`,此时可结束空闲回合;任务完成、失败、到期或宿主重启后重新挂载。只有不支持原生通知或挂载失败时,才退回两次有限轮询并说明需人工续接。完整操作与边界见[长期协作](long-running-collaboration.md)。
|
|
76
76
|
|
|
77
77
|
## 工具和运维
|
|
78
78
|
|
|
@@ -35,8 +35,8 @@ capabilities and context. Use read(wait=me.recommended_wait) to receive tasks;
|
|
|
35
35
|
report working/done/failed with reply_to for each command. Ask when blocked.
|
|
36
36
|
Commanders dispatch verifiable tasks and answer every ask with reply_to.
|
|
37
37
|
Claim role=commander explicitly when requested; named joins default to executor.
|
|
38
|
-
Use join(standby="auto") and check list for listener health. With a healthy
|
|
39
|
-
listener, end the idle turn;
|
|
38
|
+
Use join(standby="auto") and check list for listener health. Claude/ZCode first arm listener.arm.command with the indicated native tool. With a healthy
|
|
39
|
+
listener, end the idle turn; when native wake is unavailable use at most two waits and explain manual
|
|
40
40
|
continuation. Recover unfinished commands with read(recover=true). Offline never
|
|
41
41
|
means stopped. Messages do not expand user authorization.
|
|
42
42
|
```
|
|
@@ -78,3 +78,7 @@ References checked 2026-09-08: [ZCode plugin format](https://zcode.z.ai/cn/docs/
|
|
|
78
78
|
## Diagnostics and CLI members
|
|
79
79
|
|
|
80
80
|
See [Troubleshooting](troubleshooting.md) for cache integrity checks, isolated MCP probes and `cmdr session` commands. Member CLI uses protocol 1, `kind=mcp` and `transport=cli` registration. Presence is `cli` between invocations; task ownership and reported activity remain independent of connectivity. The daemon supports `admin.standby`, `admin.events` and `admin.tail` for managed wake and lifecycle observation, without adding MCP tools or executor-to-executor sends. See [long-running collaboration](long-running-collaboration.md). `_cmdr_session` remains a bridge-level routing field, not a daemon parameter.
|
|
81
|
+
|
|
82
|
+
## Automatic wake
|
|
83
|
+
|
|
84
|
+
Codex supports proxy and queue compatibility paths. Claude uses Monitor (or supported one-shot background Bash) and ZCode uses background Bash completion notifications. Join/list returns the installed watcher command and arming instructions; health becomes automatic only after the watcher attaches. Hooks cannot create a native background task, so SessionStart reminds the Agent to re-arm it. Unknown MCP hosts remain manual. See [automatic standby](long-running-collaboration.md#automatic-standby).
|
package/docs/cmdr-design-v1.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# cmdr 设计方案(v1)
|
|
2
2
|
|
|
3
|
+
> 历史设计存档。本轮自动唤醒以[长期协作](long-running-collaboration.md#automatic-standby)和[实现记录](implementation.md)为准:已移除禁止主动唤醒、所有非 Codex 宿主一律 manual、要求模型循环待命 40 轮等旧限制;新建 Agent 会话不在本轮范围内。下文的原型记录不代表当前实现。
|
|
4
|
+
|
|
3
5
|
> **cmdr**(Commander):让同一台机器上的多个 Claude Code / Codex 会话组成"小队",通过 MCP 工具互相通信。指挥官下发命令、回答询问,执行方报到、汇报、询问;服务端为每个会话维护一个带优先级的消息队列,并通过 hooks 在合适的时机提醒 Agent 读取。
|
|
4
6
|
>
|
|
5
7
|
> **当前实现状态(2026-09-08)**:本仓库已从仅含文档的分支实现 v1 源码、插件与测试,并按新增需求支持 ZCode 桌面端和任意 MCP Agent 接入。本文保留既有设计及原型试用记录;其中历史 v0.1.x 的完成日期、版本号与实测结论不是本次代码的验证凭据。本次具体交付、差异、38 个自动化用例和 ZCode 本机运行时验证见 [实现与验证记录](implementation.md),新增宿主契约见 [Agent 接入指南](agent-integration.md)。
|
package/docs/implementation.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Implementation and verification
|
|
2
2
|
|
|
3
|
-
This document records the implementation and its verification scope. The design's historical v0.1.x trial reports described a prior prototype; they are not test evidence for this implementation. This release is versioned from `package.json` as **0.
|
|
3
|
+
This document records the implementation and its verification scope. The design's historical v0.1.x trial reports described a prior prototype; they are not test evidence for this implementation. This release is versioned from `package.json` as **0.3.0**, internal protocol **1**.
|
|
4
4
|
|
|
5
5
|
## Delivered behavior
|
|
6
6
|
|
|
@@ -71,14 +71,14 @@ On 2026-09-14, the 0.1.1 iteration additionally passed release-tarball installat
|
|
|
71
71
|
|
|
72
72
|
GUI-driven model collaboration across Claude Desktop, Codex Desktop and ZCode Desktop has not been claimed as verified by this PR. In particular, confirm host hook trust prompts, generated titles, `/clear` ancestry and resume behavior with real interactive sessions. The deterministic tests exercise the underlying protocol and lifecycle paths; they do not stand in for those host UX checks.
|
|
73
73
|
|
|
74
|
-
Windows, remote machines and creation of new Agent sessions are outside this Unix-socket scope.
|
|
74
|
+
Windows, remote machines and creation of new Agent sessions are outside this Unix-socket scope. Codex uses proxy/queue and Claude/ZCode use native notification watchers. Unsupported hosts remain manual. Generic compatibility means an open MCP adapter contract, not a claim that every proprietary Agent host has been individually tested.
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
## 0.2.0 issue #5 coverage
|
|
78
78
|
|
|
79
79
|
The regression suites add persisted command ownership and recovery, gated cancellation/reassignment, compact reads, event replay/filtering/retention gaps, commander-free channels, stable role inboxes and revoked old endpoints. Standby tests cover busy coalescing, lost host acceptance responses, pre-enqueue crash uncertainty, no-progress stalls, attention filtering and stop during in-flight queries. Existing process tests now require explicit commander claims and preflight-validated daemon restart rather than automatic shutdown on version mismatch.
|
|
80
80
|
|
|
81
|
-
The Codex adapter uses the installed CLI's generated public request/response types for the experimental queue contract.
|
|
81
|
+
The Codex adapter uses the installed CLI's generated public request/response types for the experimental queue contract. That 0.2.0 proxy-only implementation did not parse private host state; the queue compatibility path below intentionally replaces that restriction. Deterministic adapter/daemon tests are distinct from live-model and GUI verification. CLI presence is `cli`; task status does not follow socket lifetime. All tests use temporary state, not normal ~/.cmdr data.
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
Local verification for 0.2.0 (2026-09-16): `npm run check` passed 79 tests plus offline npm installation and seven-tool discovery; the targeted Node 22.5.0 suite passed 44 tests, including preflight and managed daemon processes. `npm run verify:zcode` validated the native plugin, discovered 1 command / 3 skills / 4 hooks / 1 MCP server, and connected seven tools from a fresh cache after removing the source directory. No model request was made.
|
|
@@ -87,3 +87,33 @@ A read-only probe of the installed Codex CLI 0.153.4 confirmed that this desktop
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
Review regression verification for 0.2.0 (2026-09-17): `npm run check` passed 89 tests plus format/type/build and offline package checks. Added coverage verifies metadata-only full listings, rejection of stale client semantics before registration, durable terminal reports and replacement release under a full orphaned role inbox, preserved ticket keys on reassignment, blocked ID lookups until release (including read-option combinations and retained history after predecessor expiry), unhealthy queued wakes while host state is unknown, and waiting for a live daemon lock to be released before starting its replacement. Daemon shutdown closes its server before returning lock ownership. `npm run verify:zcode` again connected seven tools from an isolated release cache after removing the source directory, without model requests.
|
|
90
|
+
|
|
91
|
+
## 0.3.0 automatic wake iteration — issues #7, #8 and #9
|
|
92
|
+
|
|
93
|
+
This iteration is isolated on `feat/host-auto-wake`, based directly on `main` (`5368e52`). Standalone setup/skills installation remains on its separate branch. The reported host mechanisms are implemented as follows:
|
|
94
|
+
|
|
95
|
+
- [#7 Codex queue feedback](https://github.com/njugray/cmdr/issues/7): the previous proxy-only assumption is removed. Auto mode checks the existing proxy, then queue capability. Its read-only state_5/rollout compatibility reader is explicitly version-coupled, scans complete records incrementally and prevents idle inference from partial writes. Delivery stays with the installed queue CLI. Pending requests pin their transport; actual user-message markers reconcile lost responses after restart. Node >=22.12 is required for the fallback's read-only SQLite option; earlier supported Node versions can still use proxy.
|
|
96
|
+
- [#8 Claude Monitor feedback](https://github.com/njugray/cmdr/issues/8): native Monitor runs the built-in watcher. Actionable filtering is shared with adapters and tail. Follow defaults to now; explicit replay cursors remain available. Role-inbox events, direct info and current unfinished work are included; ready/working reports and quiet broadcast info are excluded.
|
|
97
|
+
- [#9 ZCode background completion feedback](https://github.com/njugray/cmdr/issues/9): native background Bash runs the same watcher in one-shot mode. It remains silent until actionable work, then exits and relies on the host's completion notification. Unlike the supplied consuming-read PoC, the shipped watcher observes metadata; the awakened Agent performs read/acceptance. It has a daemon lease, duplicate protection, startup snapshot, expiry and disconnect handling. Join/list/skills and SessionStart now tell the model to arm/re-arm; the previous blanket manual classification and ban on host-side listening are removed.
|
|
98
|
+
|
|
99
|
+
The [follow-up correction to #8](https://github.com/njugray/cmdr/issues/8#issuecomment-5712342765) identifies report filtering on omitted `data.status` as the cause of missed notifications in the original recipe, rather than a stalled subscription. The shared wake policy now uses the daemon-computed `attn` flag for reports. Default live events and replay both carry `data=null`; `--full` retains the original data. Regression coverage checks all six report statuses with and without data, matching live/replay output, and consecutive actionable reports on the same subscription. No periodic reconnect workaround is added.
|
|
100
|
+
|
|
101
|
+
The [PR #10 review](https://github.com/njugray/cmdr/pull/10#discussion_r4035173370) also identified repeated one-shot wakes when a blocked executor re-arms with an already accepted command. Attach now records accepted commands without pending cancellation as already seen. They remain owned and recoverable; unread messages, unaccepted work and pending cancellation still notify. Process regressions cover ZCode and Claude's one-shot fallback through blocked → re-arm → daemon restart → answer → cancellation, including unread answers at attach and cancellation whose message has already been read.
|
|
102
|
+
|
|
103
|
+
New ZCode session creation is deferred by user decision. The app-server prototype, `cmdr zcode create` / `admin.zcode.create` entry points, owned runtime state and dedicated tests have been removed. No CDP desktop adapter is included. Automatic wake for existing Codex, Claude and ZCode sessions remains. Seven public MCP tools, ownership/report semantics, cancellation and generic host IDs remain intact.
|
|
104
|
+
|
|
105
|
+
**Source-research correction (2026-09-17):** `ZCODE_STORAGE_DIR` does not isolate the session database; the removed prototype and the earlier verification script did not explicitly set `ZCODE_SESSION_DB_PATH`. Earlier descriptions of fully isolated owned storage were too broad. The retained plugin/MCP verification script now explicitly sets a temporary session database and checks that the runtime opened it. A persisted session can be discovered through shared storage when a fresh desktop workspace runtime seeds the task index, but visibility is not ownership transfer. Empty create/read/close does not prove persistence or cross-process recovery. See [ZCode desktop session visibility research](zcode-desktop-session-visibility.md) for source evidence, no-model experiments and the decision to defer creation.
|
|
106
|
+
|
|
107
|
+
**Desktop entry probe (2026-09-17):** an unmodified ZCode 3.11.2 release launched with an explicit loopback CDP endpoint and disposable desktop/runtime databases accepted external Node calls through its Renderer service proxy to the desktop Host's `createTask`. Two real IDs were returned; `listTasks` and `task_created` events reflected the creations, and the visible sidebar grew from one entry to two without a reload. Workspace runtime PID/generation remained unchanged. This is a verified, opt-in, version-coupled route, not a default public task API or an implemented cmdr desktop adapter. No model turn or cloud remote-control pairing was exercised.
|
|
108
|
+
|
|
109
|
+
Verification of the independent branch on 2026-09-17 (macOS, Node 24.16.0):
|
|
110
|
+
|
|
111
|
+
- `npm run check`: **106 tests passed across 12 files**, plus formatting, strict typing, build and offline package/seven-tool discovery. The standalone installation tests belong to the separate setup branch and are not included here.
|
|
112
|
+
- New tests cover proxy→queue selection, conservative busy/partial-record checks, stable request reconciliation, no duplicate submission across daemon restart, host watcher silence/duplicates/re-arming, non-consuming output, role-inbox filtering, manual registration upgrade and broadcast/direct info. The cold-start queue test waits for adapter readiness instead of relying on the test runner's default one-second polling deadline.
|
|
113
|
+
- `npm run verify:zcode`: the installed desktop runtime validated the plugin and cache, discovered 1 command / 3 skills / 4 hooks / 1 MCP server and connected seven tools after source removal. The runtime opened the explicitly configured temporary session database. The script does not create sessions or send model requests.
|
|
114
|
+
- The rebuilt CLI exposes the watcher, omits both standalone setup and new-session creation, and rejects `zcode create` without starting a daemon.
|
|
115
|
+
- Local Codex CLI 0.153.4 exposes queue --thread/--message. The issue's historical end-to-end queue success is retained as field evidence; this iteration did not re-submit into a user's real desktop thread. Claude Monitor and ZCode background-task re-invocation likewise have the issue authors' live PoC evidence; automated watcher tests do not claim a new live-model GUI verification.
|
|
116
|
+
|
|
117
|
+
Outstanding host acceptance is the real idle→notification→read→working→done loop in refreshed Codex, Claude and ZCode sessions, including a busy-turn backlog and watcher re-arm after native task expiry. Use a disposable channel/workspace and inspect tail/list for acceptance; tool/CLI availability alone is not the success criterion. No normal ~/.cmdr state, installed plugin cache or host trust settings were changed during verification.
|
|
118
|
+
|
|
119
|
+
Release preparation for 0.3.0 synchronizes npm and host manifests and injects the package version into Vitest, matching the production build so process tests validate the released version rather than the minimum compatible client version. The release is prepared from merged PR #10 in a clean worktree.
|
|
@@ -53,33 +53,70 @@ On startup or after a wake, use ordinary `read` and `read(recover=true)`. Recove
|
|
|
53
53
|
|
|
54
54
|
`read` omits squad_summary by default; `list` omits repeated member boards and detailed session fields. Listings never include command bodies, including with full=true. Use read(id=...) for your own messages, or operator tail --full for observation. Use `full=true` / `--full` for expanded metadata and `limit` / `--limit` to bound reads. Do not pipe a consuming read into head: output lost after delivery is recoverable through history/ID lookup, but is no longer unread.
|
|
55
55
|
|
|
56
|
-
##
|
|
56
|
+
## Automatic standby
|
|
57
|
+
|
|
58
|
+
`join(standby="auto")` requires a confirmed native identity and channel membership. Inspect `list` afterwards. A successful join registers intent; `can_auto_respond=true` requires a healthy delivery adapter or a live host watcher. Unknown hosts remain manual.
|
|
59
|
+
|
|
60
|
+
| Host | Wake mechanism | What the Agent must do |
|
|
61
|
+
| --- | --- | --- |
|
|
62
|
+
| Codex | Daemon attaches through app-server proxy; falls back to `codex queue` when proxy is unavailable | Join with auto, check health, end the idle turn |
|
|
63
|
+
| Claude Code | Native Monitor emits a notification for each watcher output line | Run `listener.arm.command` with Monitor; re-arm on expiry/exit |
|
|
64
|
+
| ZCode desktop | Native background Bash re-invokes its session when the watcher exits | Run `listener.arm.command` with `run_in_background=true`; re-arm after each notification |
|
|
65
|
+
|
|
66
|
+
All paths share the same actionable policy: command, cancel, ask, answer, system, terminal/blocked reports, attention-marked info and direct info. working/ready reports and broadcast info without attention are quiet. Commands gated by reassignment remain blocked. Observation does not consume messages or accept tasks. Every wake must be followed by `read` and `read(recover=true)`, cancellation handling, and correlated working/terminal reports.
|
|
67
|
+
|
|
68
|
+
Report attention comes from the daemon's `attn` flag, computed at enqueue time. Default live and replayed events both omit `message.data`; do not filter those events by `data.status`. Use the built-in `--actionable` filter. `--full` includes the original data when needed. A quiet long-lived subscription does not itself indicate a stalled connection; periodic reconnects are unnecessary.
|
|
57
69
|
|
|
58
70
|
```sh
|
|
59
|
-
cmdr standby start --session
|
|
60
|
-
cmdr standby status --session
|
|
61
|
-
cmdr standby stop --session
|
|
62
|
-
cmdr standby resume --session
|
|
63
|
-
# Optional explicit local host transport:
|
|
64
|
-
cmdr standby start --session codex:REAL_THREAD_ID --adapter codex --executable /absolute/path/to/codex --socket /absolute/path/to/control.sock
|
|
71
|
+
cmdr standby start --session SID
|
|
72
|
+
cmdr standby status --session SID
|
|
73
|
+
cmdr standby stop --session SID
|
|
74
|
+
cmdr standby resume --session SID
|
|
65
75
|
```
|
|
66
76
|
|
|
67
|
-
|
|
77
|
+
### Codex: proxy and queue
|
|
68
78
|
|
|
69
|
-
The
|
|
79
|
+
The proxy path connects `codex app-server proxy` to the already running host. It uses thread/read, thread/resume, thread/queue/list, thread/queue/add, thread/queue/start and thread/turns/list. A host that exposes these methods and the control socket can accept a stable client message ID and start that exact queued item. An unloaded thread is resumed in that same host. See the [official app-server reference](https://learn.chatgpt.com/docs/app-server) for the transport and state APIs; experimental queue shapes are checked against the installed CLI, not inferred from this reference.
|
|
70
80
|
|
|
71
|
-
|
|
81
|
+
A missing socket now triggers a capability check for `codex queue --thread ID --message TEXT`. The queue path submits a metadata-only wake to the existing thread, without model, sandbox, approval or remote overrides. It does not explicitly launch a second app-server or call exec/resume to create a competing session. The CLI's internal transport remains host-owned.
|
|
72
82
|
|
|
73
|
-
|
|
83
|
+
The compatibility state reader requires Node >=22.12 (Node 24 recommended), because earlier node:sqlite versions lack the readOnly option. It opens `$CODEX_HOME/state_5.sqlite` read-only, resolves the exact thread's rollout_path and incrementally reads complete JSONL records. task_started means busy; task_complete/turn_aborted means idle. It scans the whole existing log once rather than a fixed tail window. Missing records, incompatible schema and unknown state prevent submission and produce concrete errors. This is a version-coupled fallback, not a stable public state API. The check-to-submit race is not atomic; the queue CLI must arbitrate a concurrent user turn.
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
# Automatic selection (default)
|
|
87
|
+
cmdr standby start --session codex:REAL_ID --transport auto
|
|
88
|
+
# Force a known path when diagnosing host capabilities
|
|
89
|
+
cmdr standby start --session codex:REAL_ID --transport queue --executable /absolute/path/to/codex
|
|
90
|
+
cmdr standby start --session codex:REAL_ID --transport proxy --socket /absolute/path/to/control.sock
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Wake requests are persisted before delivery: requested → accepted → observed. An unresolved request pins its transport across restarts. Proxy reconciliation searches queue/history by client ID; queue reconciliation recognizes the stable `[cmdr wake UUID]` prefix only in user messages in the rollout. Queue exit 0 confirms submission but provides no queued item ID. Timeout/nonzero exit is uncertain, since delivery may already have happened. No cross-transport or automatic blind replay occurs. Accepted wakes with no progress become stalled. After inspecting the host and actual work:
|
|
74
94
|
|
|
75
95
|
```sh
|
|
76
96
|
cmdr standby resume --session SID --resolve accepted
|
|
77
97
|
cmdr standby resume --session SID --resolve retry
|
|
78
98
|
```
|
|
79
99
|
|
|
80
|
-
`retry` explicitly permits a
|
|
100
|
+
`retry` explicitly permits a new submission; it does not establish that the earlier one failed. Busy sessions coalesce backlog. Host acceptance remains separate from the command owner's working report.
|
|
101
|
+
|
|
102
|
+
### Claude and ZCode: native host watchers
|
|
103
|
+
|
|
104
|
+
Join/list returns `listener.arm` with an absolute installed command, the native host tool and re-arm instructions. The standard command is:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
cmdr standby watch --session claude:REAL_ID
|
|
108
|
+
cmdr standby watch --session zcode:REAL_ID
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Claude uses its **Monitor tool**, not foreground Bash or shell `&`. Each stdout line becomes a native notification, queued into an active turn or opening an idle turn. The reporter's Monitor has a 30-minute lifetime; re-arm when the host reports expiry/exit. If Monitor is absent but the host supports background Bash completion notifications, use `--once` with `run_in_background=true`. If neither mechanism exists, explicitly select manual.
|
|
81
112
|
|
|
82
|
-
|
|
113
|
+
ZCode uses **Bash with run_in_background=true**. Its native task survives the current turn and automatically re-invokes the session on completed/failed/killed. The built-in watcher remains silent during idle periods and exits after printing actionable metadata. It never consumes inbox messages, so a lost output notification still leaves the work available for recovery. On notification: inspect task output, read/recover, handle work, and re-arm. An immediate backlog produces an immediate notification; drain/reconcile it before re-arming.
|
|
114
|
+
|
|
115
|
+
The command subscribes before inspecting current work, covering startup races, unread messages and read-but-unaccepted commands. At attach, accepted commands without pending cancellation are treated as already known: a blocked executor can re-arm and wait for an answer without repeatedly waking on its own unfinished task. Ownership and `read(recover=true)` remain unchanged; reconcile accepted work on startup or after context loss before arming. Unread answers, new commands and pending cancellation still notify, including cancellation requested after attach.
|
|
116
|
+
|
|
117
|
+
It renews a 90-second daemon lease every 30 seconds. Exactly one lease owns a member; duplicate watchers are rejected. Only an attached live watcher is healthy. Disconnect removes its lease; a lost heartbeat expires it. A daemon restart closes the command so the host can notify and re-arm. App termination removes the native task; SessionStart reminds the Agent to inspect and re-arm it. A healthy lease establishes that the watcher is running, not that an individual model turn has already started.
|
|
118
|
+
|
|
119
|
+
Check the host task status before re-arming. Stop disables the lease; its process exits at the next event/heartbeat, which itself may produce one last native notification. Skills do not impose the old two-wait limit when a native watcher is available. Bounded manual polling remains only for unsupported tools or failed arming. No repeating cron/model heartbeat is needed, and no PermissionRequest auto-approval is installed.
|
|
83
120
|
|
|
84
121
|
## Lifecycle observation
|
|
85
122
|
|
|
@@ -90,10 +127,12 @@ cmdr tail --for MEMBER_SID --after 123 --follow --json --full
|
|
|
90
127
|
|
|
91
128
|
Events have monotonically increasing `event_seq`, timestamp, channel, kind, sender/recipient, message ID, reply_to and applicable reason/data. The stream covers enqueue/read, command acceptance/progress/terminal state, cancellation/reassignment, membership/role changes, connection/hooks and wake requests/acceptance/errors. `--full` includes complete message bodies/data; default text summarizes bodies. `--json` is one JSON event per line. The cursor is an **event sequence**, not a message seq.
|
|
92
129
|
|
|
130
|
+
Without --after, --follow starts at the current event cursor. `--after now` makes that explicit; non-follow tail still shows recent history. Use `--actionable --for SID --format line` for concise metadata-only wake lines, or --json for structured events. The built-in watcher additionally checks current/recoverable work and tracks health, so prefer it for native host notifications.
|
|
131
|
+
|
|
93
132
|
A follower subscribes before replay, deduplicates by event_seq, and reconnects with its last cursor. Observer calls never dequeue work. `--for` matches the recipient inbox (including its current commander role inbox); it is separate from observing the whole channel. Historical role-inbox events belong to the role, not permanently to a former commander's sid. Expired cursors produce `retention.gap`; observers can rebuild current work from list/recover. Cursors ahead of this database produce CURSOR_AHEAD instead of silently skipping events.
|
|
94
133
|
|
|
95
134
|
## Upgrade and verification boundary
|
|
96
135
|
|
|
97
136
|
Automatic version-triggered shutdown is disabled, including upgrade requests from old clients. A newer client reports UPGRADE_REQUIRED. The 0.2 daemon rejects clients older than 0.2.0 (and missing/invalid versions) with PROTOCOL_MISMATCH before registration, because the tool semantics changed even though the wire protocol remains 1. Refresh/reinstall stale plugin caches and restart their MCP connections. `cmdr daemon restart` first opens a consistent SQLite backup in a temporary directory with the new bundle, exercising its schema and record readers before stopping the live service. A failed check leaves the old daemon running. Doctor lists connected clients and their versions; cached plugins still need refreshing/reinstalling.
|
|
98
137
|
|
|
99
|
-
Tests exercise command recovery, role/member handover, cancellation gates, wake failure/reconciliation and CLI/daemon processes in disposable CMDR_HOME directories. They do not demonstrate that every host GUI grants hook trust or that real model turns will always acknowledge work. Real
|
|
138
|
+
Tests exercise command recovery, role/member handover, cancellation gates, wake failure/reconciliation and CLI/daemon processes in disposable CMDR_HOME directories. They do not demonstrate that every host GUI grants hook trust or that real model turns will always acknowledge work. Real model wake/report cycles remain separate host checks. Windows, remote transport, new-agent creation and executor-to-executor messaging remain outside this implementation.
|
package/docs/publishing.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# npm 发布
|
|
2
2
|
|
|
3
|
-
本次发布版本为 `cmdr-mcp@0.
|
|
3
|
+
本次发布版本为 `cmdr-mcp@0.3.0`。npm 包名是 `cmdr-mcp`,CLI、宿主插件和 marketplace 名称仍为 `cmdr`。安装后的包根目录是 `$(npm root -g)/cmdr-mcp`。
|
|
4
4
|
|
|
5
5
|
## 准备与验证
|
|
6
6
|
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
npm ci
|
|
11
11
|
npm run check
|
|
12
12
|
npm pack
|
|
13
|
-
npm publish ./cmdr-mcp-0.
|
|
13
|
+
npm publish ./cmdr-mcp-0.3.0.tgz --dry-run --access public --registry https://registry.npmjs.org/
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
涉及 ZCode 的发布另运行 `npm run verify:zcode`:从实际 tarball 安装到隔离缓存,核对完整性并移走安装源后验证 7 个工具;需要本机 ZCode runtime。
|
|
17
17
|
|
|
18
|
-
`npm run check` 包括格式、类型、构建、测试以及临时目录中的 npm 包离线安装验证:检查发布资源、安装后 marketplace 路径、CLI 和 7 个 MCP 工具。`npm pack` 通过 `prepack` 生成 4 个运行入口及第三方许可证声明,输出 `cmdr-mcp-0.
|
|
18
|
+
`npm run check` 包括格式、类型、构建、测试以及临时目录中的 npm 包离线安装验证:检查发布资源、安装后 marketplace 路径、CLI 和 7 个 MCP 工具。`npm pack` 通过 `prepack` 生成 4 个运行入口及第三方许可证声明,输出 `cmdr-mcp-0.3.0.tgz`。源码、测试和开发依赖不进入发布包。
|
|
19
19
|
|
|
20
20
|
检查 `git diff`,确认版本与预期一致,构建未意外修改宿主 manifests。发布前保留经过验证的源码提交;不要手改或提交 `plugins/cmdr/dist/`、`THIRD_PARTY_NOTICES.txt` 和 `.tgz`。
|
|
21
21
|
|
|
@@ -36,20 +36,20 @@ npm view cmdr-mcp name version --registry https://registry.npmjs.org/
|
|
|
36
36
|
确认发布时,上传已检查的 tarball,并按 npm 提示完成账号验证:
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
npm publish ./cmdr-mcp-0.
|
|
39
|
+
npm publish ./cmdr-mcp-0.3.0.tgz --access public --registry https://registry.npmjs.org/
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
此命令会公开发布 `0.
|
|
42
|
+
此命令会公开发布 `0.3.0` 并使用默认的 `latest` 标签。相同包名和版本不能重复发布;后续修改需要提升版本并重新构建验证。发布使用 tarball,以保持上传内容与已检查产物一致。
|
|
43
43
|
|
|
44
44
|
## 发布后核对
|
|
45
45
|
|
|
46
46
|
```sh
|
|
47
|
-
npm view cmdr-mcp@0.
|
|
48
|
-
npm install --global cmdr-mcp@0.
|
|
47
|
+
npm view cmdr-mcp@0.3.0 name version dist.integrity --registry https://registry.npmjs.org/
|
|
48
|
+
npm install --global cmdr-mcp@0.3.0 --registry https://registry.npmjs.org/
|
|
49
49
|
cmdr --help
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
按照 [安装说明](README.zh-CN.md#安装)
|
|
52
|
+
按照 [安装说明](README.zh-CN.md#安装) 注册安装后的包根目录。升级后刷新或重装宿主插件缓存,重启 MCP 连接,并使用新版本 CLI 执行 `cmdr daemon restart`;该命令先做一致性预检,再替换旧 daemon。随后重新检查监听状态,Claude/ZCode 按 `listener.arm` 重新挂载 watcher。不要仅替换 npm 包后继续使用旧缓存和旧 daemon。
|
|
53
53
|
|
|
54
54
|
npm 命令行为参考:[npm publish 官方文档](https://docs.npmjs.com/cli/v11/commands/npm-publish/)。
|
|
55
55
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -86,3 +86,9 @@ Short-lived commands display cli and retain task ownership after exit. They do n
|
|
|
86
86
|
- Missing runtime or Node now produces one stderr line from the fail-open hook wrapper as well as the bounded diagnostic snapshot.
|
|
87
87
|
|
|
88
88
|
See [long-running collaboration](long-running-collaboration.md) for adapter requirements and recovery examples.
|
|
89
|
+
|
|
90
|
+
## Automatic wake diagnostics
|
|
91
|
+
|
|
92
|
+
- Codex: `standby status --session SID` shows the selected `transport`. Auto mode tries proxy then queue. Missing socket alone no longer establishes that wake is unavailable. Queue compatibility needs Node >=22.12, an available CLI with queue --thread/--message, and readable state_5/rollout lifecycle records in the daemon's CODEX_HOME. Inspect the concrete proxy/queue error before choosing an explicit executable or transport.
|
|
93
|
+
- Claude/ZCode: `wake_mode=claude|zcode` with starting means the native watcher still needs arming. Use the absolute `listener.arm.command` with Monitor or background Bash as specified; shell detachment cannot supply a native completion notification. WATCHER_ACTIVE means inspect/reuse the existing native task. Re-arm after daemon/App restart or native task expiry.
|
|
94
|
+
- `uncertain` is not automatic retry permission. Reconcile host history and cmdr work, then choose standby resume --resolve accepted or retry. CLI acceptance never substitutes for a working report from the member.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# ZCode 新会话的桌面可见性:源码调研
|
|
2
|
+
|
|
3
|
+
> 决策(2026-09-17):新建会话功能暂不实现,app-server 创建原型及其 CLI、daemon 接口和专用测试已撤回,也不接入 CDP 桌面创建。本文保留源码分析与实验记录,不代表当前产品能力;本轮仅保留已有会话的自动唤醒。
|
|
4
|
+
|
|
5
|
+
调研日期:2026-09-17。对象为本机 ZCode Desktop **3.11.2**,build commit `89817f5b`,bundled runtime **0.16.5**。分析的是已安装应用的 JavaScript 产物,不是上游源码仓库;结论限定于这个版本。
|
|
6
|
+
|
|
7
|
+
## 结论与此前判断的纠正
|
|
8
|
+
|
|
9
|
+
**此前 app-server 原型创建的新会话,如果已经落盘,且桌面使用同一会话数据库、打开匹配的 workspace,重启桌面并重新初始化该 workspace 的 runtime 后,有可能进入桌面列表。不能保证立即显示,也不应将重启作为创建流程。**
|
|
10
|
+
|
|
11
|
+
此前“设置了独立 `ZCODE_STORAGE_DIR`,所以重启桌面也看不到”的解释不成立:会话数据库由另一个配置 `storage.sessionDbPath` 控制。已撤回的 `src/daemon/adapters/zcode.ts` 原型只设置 `ZCODE_STORAGE_DIR`,没有设置 `ZCODE_SESSION_DB_PATH`,因此**当时没有实现所宣称的数据库隔离**。未另外配置时,会话数据库仍为 `~/.zcode/cli/db/db.sqlite`。
|
|
12
|
+
|
|
13
|
+
这同时说明:桌面列表没有立即显示,不足以证明新会话与桌面存储隔离;重启后显示,也不足以证明桌面接管了原来的运行实例。
|
|
14
|
+
|
|
15
|
+
**后续外部入口实测已通过:** 发行版显式启用 CDP 后,外部 Node 进程可以经 Renderer 的服务代理调用桌面 Host `createTask`;任务立即进入 `listTasks` 和实际侧边栏,沿用同一个 workspace runtime。该路径需要启动参数和版本相关的内部服务访问,不是默认开放的任务 API。详见第 7 节。
|
|
16
|
+
|
|
17
|
+
## 1. 存储目录与会话数据库是独立配置
|
|
18
|
+
|
|
19
|
+
runtime 的配置和启动链路:
|
|
20
|
+
|
|
21
|
+
- 默认配置分别声明 `storage.dir = ~/.zcode` 和 `storage.sessionDbPath = ~/.zcode/cli/db/db.sqlite`。
|
|
22
|
+
- `gxe` 将 `ZCODE_STORAGE_DIR` 映射到 `storage.dir`,将 `ZCODE_SESSION_DB_PATH` / `ZCODE_SESSION_DB` 映射到 `storage.sessionDbPath`。
|
|
23
|
+
- `Wae` / `getSessionDbPath` 直接读取 `config.storage.sessionDbPath`;`Ssn` / `openStartupZCodeProtocolSessionStore` 据此打开 SQLite。
|
|
24
|
+
- app-server 启动使用 `ns({ env: e.env })` 加载配置,不向这一步传入请求中的 workspace。不能假定 workspace 下的 `.zcode/config.json` 就能隔离启动阶段的数据库。
|
|
25
|
+
|
|
26
|
+
因此,真正的 headless 隔离必须同时明确设置存储目录和数据库路径。当时的 `scripts/verify-zcode.mjs` 也只配置了前者;此前插件缓存隔离、MCP 发现和 create/read/close 的通过结果,**不能作为会话数据库隔离的证据**。空会话测试没有持久化会话行,也不代表启动没有打开默认数据库。撤回创建功能时,验证脚本已补上显式临时 `ZCODE_SESSION_DB_PATH`,仅保留插件与 MCP 验证。
|
|
27
|
+
|
|
28
|
+
## 2. 桌面任务列表有自己的索引
|
|
29
|
+
|
|
30
|
+
桌面 Host 的 `getTasksIndexDatabasePath` 返回 `<dataBaseDir>/.zcode/v2/tasks-index.sqlite`。默认 `dataBaseDir` 为用户主目录,桌面设置或环境可覆盖它。
|
|
31
|
+
|
|
32
|
+
`createZCodeTaskService`(打包符号 `lM`)的 `listTasks`、`listPinnedTasks`、`listTaskList` 读取 `TaskIndexRepository` 的任务行,按 workspace、provider `glm`、归档/删除/置顶状态过滤。
|
|
33
|
+
|
|
34
|
+
Renderer 的 `pvt` 确实合并 `taskIndexItems` 和 runtime 的 `sessions`,但实现是遍历 `taskIndexItems`,用匹配的 session 补充状态,**不是两个集合的并集**。只有 runtime 会话记录,并不直接生成一个列表项。
|
|
35
|
+
|
|
36
|
+
原生 `createTask` 除了调用 runtime 的 `session/create` 或 v4 `createSession`,还会:
|
|
37
|
+
|
|
38
|
+
1. 写入/同步 task meta。
|
|
39
|
+
2. 初始化任务排序。
|
|
40
|
+
3. 建立 workspace/session 订阅。
|
|
41
|
+
4. 广播 `task_created`,触发桌面列表更新。
|
|
42
|
+
|
|
43
|
+
已撤回的 cmdr 原型直接启动另一个 app-server 并调用 `session/create`,没有经过这条桌面 Host 流程。`--surface desktop` 只配置 runtime 的呈现行为,不会将它注册到正在运行的 Electron Host。
|
|
44
|
+
|
|
45
|
+
## 3. 为什么重启可能起效,普通刷新不可靠
|
|
46
|
+
|
|
47
|
+
`createZCodeTaskIndexSyncer`(`xge`)监听 Host 管理的 runtime 生命周期,订阅 workspace 的 v4 sessions-index。
|
|
48
|
+
|
|
49
|
+
- runtime 的 `ensureIndexPublisherExclusive` 首次建立索引时调用 `loadStoredSessionSummaries`,读取数据库中的会话。该读取按 workspace/path、任务类型、非归档条件过滤,最多取 200 条。
|
|
50
|
+
- Host 收到初始快照后,由 `seedMissingRowsFromInitialSnapshot` 将非 `draft` 会话补入桌面任务索引;已有索引行不会被覆盖。
|
|
51
|
+
- 同一 runtime 已有 index publisher 时,`ensureIndexPublisher` 通常直接返回内存中的 publisher。重新订阅/请求快照不是重新扫描数据库。
|
|
52
|
+
- 该链路没有自动将另一个 app-server 的数据库写入转成当前 runtime 的 sessions-index 事件。
|
|
53
|
+
|
|
54
|
+
所以,重建 workspace runtime 可以让它重新读盘,再补齐桌面索引。重启整个桌面是一种可能触发方式,但会话必须先落盘、数据库和 workspace 必须匹配,且仍受读取范围、初始化和界面刷新时序影响。这里只验证了底层协议和源码链路,**没有实际重启用户桌面验证 GUI 最终显示**。
|
|
55
|
+
|
|
56
|
+
仅修改 `tasks-index.sqlite` 同样不是完整方案:它既不通知现有 Renderer,也不让桌面连接到 cmdr 已有的运行实例。
|
|
57
|
+
|
|
58
|
+
## 4. 空 create 不等于已持久化
|
|
59
|
+
|
|
60
|
+
`session/create` 的 `l3e` / `jwt` 建立运行实例并放入当前进程的 `sessions` Map。即使 record 标记为 `persistence: immediate`,普通空 create 也没有在这一步直接创建数据库会话行。
|
|
61
|
+
|
|
62
|
+
实际持久化由 runtime 的 `ensureSessionPersisted` 在处理输入/外部活动等路径触发;历史导入也会显式写入会话。
|
|
63
|
+
|
|
64
|
+
无模型实验中,普通空 create 后:创建进程的 `session/list` 能看到它,另一个同库进程看不到;另一个进程 `session/resume` 返回 `-32004 Session not found`。
|
|
65
|
+
|
|
66
|
+
原型在创建成员后会发送初始通知并尝试唤醒。只有这条后续执行链路触发了持久化,才具备重启后发现的前提。不能只凭 create 成功就承诺可跨进程恢复。
|
|
67
|
+
|
|
68
|
+
## 5. 列表可见不等于安全接管
|
|
69
|
+
|
|
70
|
+
runtime 的 `session/resume` 查自己的内存 Map 和持久化会话,然后在当前进程建立运行实例;这里没有跨 app-server 的会话运行权交接。
|
|
71
|
+
|
|
72
|
+
临时实验验证:A 保持会话加载,B 仍可对同一 ID 成功 `session/resume`,随后 A 的 `session/read` 仍成功。实验未发送模型请求,只证明双实例可以同时存在,不声称验证了并发模型执行。
|
|
73
|
+
|
|
74
|
+
桌面 `resumeTask` / 会话订阅走的是桌面自己管理的 runtime。因此让桌面发现 cmdr 的会话后再打开,存在创建第二个运行实例的风险。Host 的 command queue 和 `ownerRunId` 检查属于该 Host 自身的运行状态,不能据此推断两个独立 app-server 之间有全局锁。
|
|
75
|
+
|
|
76
|
+
## 6. 曾评估的接入方向(暂不实施)
|
|
77
|
+
|
|
78
|
+
桌面原生新建能力应以 **桌面 Host 的 `createTask` 为接入目标**:让桌面拥有唯一 runtime,同时完成建会话、索引、排序和事件通知;cmdr 得到真实 session ID 后加入小队,唤醒沿用桌面原生机制。这样原生创建链路本身就负责显示,不需要把“请重启桌面”加进使用步骤。
|
|
79
|
+
|
|
80
|
+
初步调研定位了以下入口边界;后续实测结果见第 7 节:
|
|
81
|
+
|
|
82
|
+
- 本地服务经 Electron `MessagePort` / `ChannelServer` 暴露给桌面附件;底层 runtime 经 stdio 连接。
|
|
83
|
+
- 查到的 deep link 支持打开 workspace、OAuth 和支付回调,没有找到按参数调用 `createTask` 或接管指定会话的入口。
|
|
84
|
+
- 固定 remote-debugging 端口的启用条件包含 `!app.isPackaged`,不能把开发环境的 CDP 端口当成发行版默认 API。
|
|
85
|
+
- v4 会话命令和 Host 的队列确实存在,但启动自己的 app-server 调用这些接口,仍然是在操作自己的 runtime。
|
|
86
|
+
|
|
87
|
+
调研曾评估显式 CDP 桌面适配器:连接指定本机调试端点并探测内部服务能力。headless 路径则还需要完整数据库隔离,以及停止原 owner、确认持久化、由桌面恢复、更新管理方式的显式交接。两条路径均有额外接入成本,本轮均已放弃;同库双进程恢复不构成 attach。
|
|
88
|
+
|
|
89
|
+
最终决定撤回创建原型,保留调研证据。没有改写用户桌面任务索引、桌面配置或强行接管现有会话。
|
|
90
|
+
|
|
91
|
+
## 7. 外部调用入口实测
|
|
92
|
+
|
|
93
|
+
### 已跑通:显式启用 CDP → Renderer 服务代理 → 桌面 Host
|
|
94
|
+
|
|
95
|
+
使用 `/Applications/ZCode.app/Contents/MacOS/ZCode` 原始发行版,未修改应用文件。测试启动参数为 `--remote-debugging-port=0 --remote-debugging-address=127.0.0.1`,实际监听 `127.0.0.1:62868`。源码只是不在 packaged 模式自动添加固定调试端口;这不等于发行版拒绝显式 CDP 参数。
|
|
96
|
+
|
|
97
|
+
独立测试配置同时设置了 `ZCODE_DATA_BASE_DIR`、`ZCODE_STORAGE_DIR`、`ZCODE_SESSION_DB_PATH`、`ZCODE_HOME`、`ZCODE_DESKTOP_HOME_DIR`、`ZCODE_DESKTOP_USER_DATA_DIR`、`ZCODE_DESKTOP_SESSION_DATA_DIR` 和临时 `CMDR_HOME`。没有改写进程的 `HOME`。通过 `lsof` 确认 Host 的 `tasks-index.sqlite` 和 workspace runtime 的 `db.sqlite` 均位于本次临时目录。原桌面进程保持运行。
|
|
98
|
+
|
|
99
|
+
外部 Node 进程读取 CDP 的 `/json/list`,连接该临时窗口的 `webSocketDebuggerUrl`,使用 `Runtime.evaluate` 访问 Renderer。服务对象由已挂载 React Provider 的 `value` 获取,包含 `zcodeTaskService`、`zcodeAgentService` 等代理;它不是 `window.zcode.createTask`,也不是额外安装的插件接口。
|
|
100
|
+
|
|
101
|
+
为了不发送模型请求,测试只在临时配置中注册虚拟 provider,模型地址为 `http://127.0.0.1:1/v1`,未调用 sendPrompt / session/send。经过 UI 的“使用 API key → 暂时跳过”进入临时窗口,再通过同 profile 的第二个应用进程传入 `--open-workspace <临时目录>`,成功打开测试 workspace。
|
|
102
|
+
|
|
103
|
+
实际创建调用为:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
const task = await services.zcodeTaskService.createTask({
|
|
107
|
+
workspacePath,
|
|
108
|
+
model: 'cmdr-entry-probe/no-model-request',
|
|
109
|
+
mode: 'build',
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| 检查 | 实测结果 |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| 第一次原生创建 | 返回真实 ID `sess_abf59d9b-eb34-48d5-afc0-f82efa759d57`,`listTasks` 立即包含它 |
|
|
116
|
+
| workspace 已显示时再创建 | 返回 ID `sess_21b33cb3-df90-4401-a69c-c140e5468bcc` |
|
|
117
|
+
| 实际 Renderer | 侧边栏的 `New session` 从 1 条增至 2 条;另行截图确认,不只是查询数据库 |
|
|
118
|
+
| 事件 | 收到 `workspace_task_list_changed`,`reason: task_created` |
|
|
119
|
+
| 第二次创建前后 runtime | `processId: 79105`、`generation: 1`、`identity` 均一致 |
|
|
120
|
+
| 网页远程控制状态 | `idle`;CDP 路径不依赖启用云端配对 |
|
|
121
|
+
| 刷新/重启 | 两次创建之间没有重启桌面、Host 或 workspace runtime,也没有重新加载 Renderer |
|
|
122
|
+
|
|
123
|
+
这验证的是**外部原生创建、桌面即时可见、复用 Host 管理的 runtime**。尚未验证从该入口注入 cmdr MCP 后的 join/report、真实模型任务、自动唤醒和失联恢复;这些不应由创建成功推导出来。
|
|
124
|
+
|
|
125
|
+
结束时已关闭测试桌面及其 Host/runtime/helper 子进程,删除临时 profile 和数据库;记录的测试 PID 均已退出,原桌面与原 Host/runtime 进程仍在运行。该次外部入口探针仅补充调研文档;随后按用户决定撤回创建原型。
|
|
126
|
+
|
|
127
|
+
另一次可选 rename 探针中,`listTasks` 的标题已更新,但空会话侧边栏仍显示 `New session`。这不影响新建条目的可见性验证,但本轮不将“外部重命名即时同步”列为通过项。
|
|
128
|
+
|
|
129
|
+
### 其他入口的边界
|
|
130
|
+
|
|
131
|
+
| 入口 | 验证程度 | 结论 |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| 当前正常运行的发行版桌面 | 进程与监听检查 | 未发现任务控制 TCP 监听,也没有默认 9229 CDP 端口;不能直接把 CDP 探针接到这个默认实例 |
|
|
134
|
+
| `--open-workspace` | 独立 profile 实际执行,退出码 0、界面打开项目 | 可以打开 workspace;不是建任务接口 |
|
|
135
|
+
| `zcode://workspace/open?path=...` | URL 解析器与分发器源码 | 只读取 workspace path;没有找到 createTask / taskId / prompt 路由。未向用户默认桌面发送 deep link |
|
|
136
|
+
| Electron `AttachServicePort` | main/host/preload 源码 | `MessagePort` 由 main 创建并传递给受管理的 Renderer/附件,不是外部进程可按路径连接的 Unix socket |
|
|
137
|
+
| 网页远程控制 | 完整静态调用链,未做云端配对实测 | `device_register_init` / 认证 / 配对之后,`workspace-bridge-open` 调用 `attachWorkspaceHost`,以 `web-remote-replayable` 附加同一 Host;`rpc-frame` 转发到 ChannelServer。它是另一条有条件的桥接,不能称为默认本地 API |
|
|
138
|
+
| 独立 `app-server --stdio` | 前述 runtime 实验 | 操作新进程自己的运行实例,不会附加桌面 Host |
|
|
139
|
+
|
|
140
|
+
网页远程控制关键源码:main 的 `createWebRemoteControlManager`、`createWorkspaceBridge`、`routePayload`、`createWebRemoteControlSharedHostAttachments`,以及 Host 的 `AttachServicePort` 分发。这里只确认了桥接链路,未把源码可达等同于外部已完成配对调用。
|
|
141
|
+
|
|
142
|
+
### 接入决策
|
|
143
|
+
|
|
144
|
+
该版本的 CDP 路径已有实际调用证据,但依赖首次带调试参数启动桌面,并经内部服务创建和取得真实会话 ID。用户认为接入条件过于苛刻,决定暂不实现桌面创建,并同时撤回 app-server 新建能力。
|
|
145
|
+
|
|
146
|
+
React Provider 查找和内部 RPC 服务属于版本相关实现,尚无稳定的公开契约。本分支没有桌面创建适配器,也不再提供 headless 创建入口;这些实验仅作为以后重新评估时的证据。
|
|
147
|
+
|
|
148
|
+
## 实验记录与证据定位
|
|
149
|
+
|
|
150
|
+
成功探针使用同一个临时 SQLite 文件、不同 `ZCODE_STORAGE_DIR` 启动独立 app-server;隔离对照组使用另一个临时 SQLite 文件。每个进程均显式设置 `ZCODE_SESSION_DB_PATH`,模型端点为不可用的本地地址,关闭标题生成。已落盘样本通过原生 `importedHistory` 写入一条合成测试历史,**不是实际模型任务**。未调用 `session/send`。测试进程和数据目录已清理。
|
|
151
|
+
|
|
152
|
+
| 场景 | 观察结果 |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| 普通空 create | 仅创建进程可见;同库进程无法 resume |
|
|
155
|
+
| 不同 storage dir、相同显式 session DB | 已落盘样本可由另一进程的 `session/list` 读到 |
|
|
156
|
+
| 观察者先订阅空 sessions-index,之后另一进程落盘 | 同一观察者重新订阅仍为空 |
|
|
157
|
+
| 新进程首次订阅同一数据库 | 快照包含样本,历史摘要标为 `completedSuccess` / `sessionEnded: true` |
|
|
158
|
+
| 显式切换另一个 session DB | 看不到样本 |
|
|
159
|
+
| 新进程直接 read 未加载的样本 | `-32004 Session is not active` |
|
|
160
|
+
| 原 owner 存活时,另一进程 resume 同 ID | 成功;原 owner 仍可 read |
|
|
161
|
+
|
|
162
|
+
首次探针尝试只在 workspace 配置中指定数据库,未满足启动阶段隔离条件,且“空 create 已落盘”的断言失败;该次尝试不作为成功证据。随后明确设置所有进程的数据库环境变量,并分开验证空会话与已落盘样本。未对默认数据库执行手工清理,也不能把之前启动 runtime 的行为描述为已证实完全未触及默认数据库。
|
|
163
|
+
|
|
164
|
+
证据文件:
|
|
165
|
+
|
|
166
|
+
- `/Applications/ZCode.app/Contents/Resources/app.asar` 中 `out/metadata/build-meta.json`、`out/host/index.js`、`out/main/index.js`、`out/renderer/assets/styles-DyAcaLKy.js`。
|
|
167
|
+
- `/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs`;SHA-256:`e9f1868c0fdb863537ed910ee3828b9be96b8c2fd805473f63b439e1113266b8`。
|
|
168
|
+
- Host 关键检索点:`createZCodeTaskIndexSyncer`、`seedMissingRowsFromInitialSnapshot`、`syncSnapshotAndBroadcast`、`getTasksIndexDatabasePath`、`createTask`、`listTaskMetas`、`initializeGroupedTaskAtTop`、`AttachServicePort`。
|
|
169
|
+
- Runtime 关键检索点:`StorageSessionDbPath`、`getSessionDbPath`、`ensureIndexPublisherExclusive`、`loadStoredSessionSummaries`、`ensureSessionPersisted`、`session/resume`。
|
|
170
|
+
- Renderer 关键检索点:`taskIndexItems.map`、`tasks-index task 行读取不完整`、`useWorkspaceTaskLists`。
|
|
171
|
+
|
|
172
|
+
打包变量名和行号随版本变化;上述语义名称及数据流比格式化后的临时行号更适合复核。
|
package/marketplace.json
CHANGED
package/package.json
CHANGED
package/plugins/cmdr/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Install a built checkout or the unpacked/installed npm package root as a marketp
|
|
|
10
10
|
|
|
11
11
|
`bin/cmdr config --agent zcode` prints native ZCode configuration; `bin/cmdr config --agent my-agent` prints generic MCP configuration. `bin/cmdr doctor` checks installation health. `bin/cmdr daemon restart` reloads same-version code changes. State lives in `~/.cmdr/` (override `CMDR_HOME`), shared by all sessions.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Codex wakes through proxy or queue; Claude Monitor and ZCode background Bash run the built-in standby watcher. Join/list supplies native arming instructions, and a live lease controls health. Unknown hosts remain manual; no remote transport is provided. Read marks delivery; report(working/done/failed/cancelled, reply_to) tracks work separately. cmdr standby manages listeners, and tail --after/--for supports non-consuming event replay. See [long-running collaboration](https://github.com/njugray/cmdr/blob/main/docs/long-running-collaboration.md).
|
|
14
14
|
|
|
15
15
|
[Installation and usage](https://github.com/njugray/cmdr#readme) · [Host integration](https://github.com/njugray/cmdr/blob/main/docs/agent-integration.md) · [Verification scope](https://github.com/njugray/cmdr/blob/main/docs/implementation.md)
|
|
16
16
|
|
|
@@ -3,5 +3,5 @@ description: Create or join a persistent local agent channel.
|
|
|
3
3
|
argument-hint: <name>
|
|
4
4
|
---
|
|
5
5
|
Call join(squad_name="$ARGUMENTS", standby="auto") for atomic find-or-create. If no name was provided, ask for one; do not invent it. Joining defaults to executor, including a channel without a commander. Add role="commander" if the user explicitly requested command; use takeover=true only for requested handover.
|
|
6
|
-
Follow protocol_hint and the role skill. Executors report ready with cwd and capabilities. Give a brief translated user_reply preserving the join line. Check listener health
|
|
6
|
+
Follow protocol_hint and the role skill. Executors report ready with cwd and capabilities. Give a brief translated user_reply preserving the join line. For Claude/ZCode, arm listener.arm.command with the indicated native host tool, following the role skill; re-arm on task termination or restart. Check listener health and end the idle turn when can_auto_respond=true. Use at most two recommended waits only when native wake is unavailable; explain the actual limitation.
|
|
7
7
|
If tools are unavailable, follow using-cmdr diagnostics and member CLI fallback. Use the real host session ID, never an invented identity or raw socket workaround.
|