@ran-sh/dsh-crew 0.5.1 → 0.5.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/README.md +93 -112
- package/README.zh.md +93 -111
- package/agents/ds-worker.md +5 -4
- package/codex/AGENTS.md +92 -0
- package/codex/agents/ds-worker.toml +1 -1
- package/docs/installation.md +63 -0
- package/docs/job-contracts.md +12 -4
- package/docs/readiness-matrix.md +6 -2
- package/docs/ui-surfaces.md +1 -2
- package/lib/client.js +41 -4
- package/official-web-bridge/lib/client.js +41 -4
- package/package.json +6 -1
- package/scripts/setup.mjs +127 -42
- package/src/client/host-readiness.mjs +2 -1
- package/src/client/index.tsx +29 -15
- package/src/config-readiness.mjs +50 -10
- package/src/hub/index.mjs +42 -15
- package/src/install/install-legacy.mjs +65 -11
- package/src/install/install.mjs +3 -1
- package/src/install/npx-lifecycle.mjs +55 -19
- package/src/install/windows-startup.mjs +115 -0
- package/src/install/zcode.mjs +316 -0
- package/src/orchestrator.mjs +53 -0
- package/src/readiness-matrix.mjs +4 -3
- package/src/runtime-identity.mjs +1 -1
- package/src/server.mjs +38 -34
- package/src/workflow-runtime.mjs +27 -27
- package/src/workflow.mjs +63 -5
- package/windows/start-dsh-crew.cmd +57 -0
- package/windows/start-dsh-crew.ps1 +326 -0
- package/windows/start-dsh-crew.vbs +9 -0
- package/zcode/AGENTS.md +26 -0
- package/zcode/agents/ds-reviewer.md +36 -0
- package/zcode/agents/ds-worker.md +39 -0
- package/zcode/commands/dsh-config.md +6 -0
- package/zcode/commands/dsh-status.md +4 -0
package/docs/ui-surfaces.md
CHANGED
|
@@ -12,7 +12,7 @@ management:
|
|
|
12
12
|
- Worker and Reviewer policy
|
|
13
13
|
- model priority, fallback, review, and adaptive routing
|
|
14
14
|
- runtime and activation-boundary information
|
|
15
|
-
- Codex and
|
|
15
|
+
- Codex, Claude, and ZCode installation actions and structured readiness
|
|
16
16
|
- task status and bounded model-invocation summaries
|
|
17
17
|
- the link to the underlying 3210 Crew Harness
|
|
18
18
|
|
|
@@ -44,4 +44,3 @@ the full control plane and never becomes `READY`.
|
|
|
44
44
|
|
|
45
45
|
The split changes presentation only. Crew state, credentials, routing policy,
|
|
46
46
|
and model execution remain isolated under the Crew-owned home and profile.
|
|
47
|
-
|
package/lib/client.js
CHANGED
|
@@ -192,6 +192,7 @@ function bridgeState(surface) {
|
|
|
192
192
|
function projectHostReadiness({ installStatus, runtime, surface } = {}) {
|
|
193
193
|
const codex = installStatus?.codex;
|
|
194
194
|
const claude = installStatus?.claude;
|
|
195
|
+
const zcode = installStatus?.zcode;
|
|
195
196
|
return [
|
|
196
197
|
{
|
|
197
198
|
id: "codex_mcp",
|
|
@@ -214,6 +215,18 @@ function projectHostReadiness({ installStatus, runtime, surface } = {}) {
|
|
|
214
215
|
"permissions"
|
|
215
216
|
])
|
|
216
217
|
},
|
|
218
|
+
{
|
|
219
|
+
id: "zcode_mcp",
|
|
220
|
+
state: componentState(zcode, [
|
|
221
|
+
"mcp",
|
|
222
|
+
"policy",
|
|
223
|
+
"worker_agent",
|
|
224
|
+
"reviewer_agent",
|
|
225
|
+
"config_prompt",
|
|
226
|
+
"status_prompt",
|
|
227
|
+
"ownership"
|
|
228
|
+
])
|
|
229
|
+
},
|
|
217
230
|
{
|
|
218
231
|
id: "crew_harness",
|
|
219
232
|
state: runtimeState(runtime),
|
|
@@ -354,7 +367,7 @@ const COPY = {
|
|
|
354
367
|
jobCount: (count) => `${count} 个任务`,
|
|
355
368
|
runningCount: (count) => `${count} 个运行中`,
|
|
356
369
|
sectionNames: {
|
|
357
|
-
integrations: "Codex / Claude 集成状态",
|
|
370
|
+
integrations: "Codex / Claude / ZCode 集成状态",
|
|
358
371
|
workflow: "Crew 工作流设置",
|
|
359
372
|
flash: "Worker / Flash",
|
|
360
373
|
pro: "Reviewer / Pro",
|
|
@@ -374,6 +387,7 @@ const COPY = {
|
|
|
374
387
|
ds_worker: "ds-worker",
|
|
375
388
|
ds_reviewer: "ds-reviewer",
|
|
376
389
|
claude_plugin: "Claude plugin",
|
|
390
|
+
zcode_mcp: "ZCode MCP",
|
|
377
391
|
crew_harness: "Crew Harness",
|
|
378
392
|
official_bridge: "Official bridge"
|
|
379
393
|
},
|
|
@@ -602,6 +616,11 @@ const COPY = {
|
|
|
602
616
|
install: "把 ds-flash / ds-pro 角色和 /dsh-config、/dsh-status 命令复制到 ~/.codex/(MCP 路径按本机自动渲染,含 approve 审批与超时配置)",
|
|
603
617
|
update: "重新渲染并覆盖角色文件与命令(插件路径或配置变更后用);原文件先备份",
|
|
604
618
|
restore: "删除 ~/.codex/ 下的 ds-flash / ds-pro 角色与 dsh 命令文件(角色文件先备份)"
|
|
619
|
+
},
|
|
620
|
+
zcode: {
|
|
621
|
+
install: "安装 ZCode 全局规则、ds-worker / ds-reviewer 角色、命令和按来源选择的 MCP 配置到 ~/.zcode/",
|
|
622
|
+
update: "重新渲染 ZCode 角色、命令和 MCP 条目;保留个人文件与其他 MCP 服务",
|
|
623
|
+
restore: "仅移除 dsh-crew 管理的 ZCode 文件和 MCP 条目(保留备份)"
|
|
605
624
|
}
|
|
606
625
|
}
|
|
607
626
|
},
|
|
@@ -627,7 +646,7 @@ const COPY = {
|
|
|
627
646
|
jobCount: (count) => `${count} jobs`,
|
|
628
647
|
runningCount: (count) => `${count} running`,
|
|
629
648
|
sectionNames: {
|
|
630
|
-
integrations: "Codex / Claude integration status",
|
|
649
|
+
integrations: "Codex / Claude / ZCode integration status",
|
|
631
650
|
workflow: "Crew workflow settings",
|
|
632
651
|
flash: "Worker / Flash",
|
|
633
652
|
pro: "Reviewer / Pro",
|
|
@@ -647,6 +666,7 @@ const COPY = {
|
|
|
647
666
|
ds_worker: "ds-worker",
|
|
648
667
|
ds_reviewer: "ds-reviewer",
|
|
649
668
|
claude_plugin: "Claude plugin",
|
|
669
|
+
zcode_mcp: "ZCode MCP",
|
|
650
670
|
crew_harness: "Crew Harness",
|
|
651
671
|
official_bridge: "Official bridge"
|
|
652
672
|
},
|
|
@@ -875,6 +895,11 @@ const COPY = {
|
|
|
875
895
|
install: "Copy ds-flash / ds-pro roles and /dsh-config, /dsh-status prompts into ~/.codex/ (MCP paths rendered for this machine, approve mode + timeout included)",
|
|
876
896
|
update: "Re-render and overwrite role files and prompts (after path/config changes); originals backed up",
|
|
877
897
|
restore: "Delete ds-flash / ds-pro roles and dsh prompts from ~/.codex/ (roles backed up first)"
|
|
898
|
+
},
|
|
899
|
+
zcode: {
|
|
900
|
+
install: "Install the ZCode global policy, ds-worker / ds-reviewer agents, commands and source-aware MCP config under ~/.zcode/",
|
|
901
|
+
update: "Re-render ZCode agents, commands and MCP entry; user files and unrelated MCP servers are preserved",
|
|
902
|
+
restore: "Remove only dsh-crew-owned ZCode files and MCP entry (backups kept)"
|
|
878
903
|
}
|
|
879
904
|
}
|
|
880
905
|
}
|
|
@@ -1879,6 +1904,10 @@ function WorkersPanel({ ctx }) {
|
|
|
1879
1904
|
style: S.chip(!!status?.claude?.ready),
|
|
1880
1905
|
children: ["Claude ", status?.claude?.ready ? "READY" : "CHECK"]
|
|
1881
1906
|
}),
|
|
1907
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1908
|
+
style: S.chip(!!status?.zcode?.ready),
|
|
1909
|
+
children: ["ZCode ", status?.zcode?.ready ? "READY" : "CHECK"]
|
|
1910
|
+
}),
|
|
1882
1911
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1883
1912
|
style: S.chip(jobs.some((job) => job.status === "running")),
|
|
1884
1913
|
children: [jobs.filter((job) => job.status === "running").length, " running"]
|
|
@@ -1954,7 +1983,7 @@ function WorkersPanel({ ctx }) {
|
|
|
1954
1983
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleSection, {
|
|
1955
1984
|
sectionId: "integrations",
|
|
1956
1985
|
title: copy.sectionNames.integrations,
|
|
1957
|
-
summary: sectionSummary(status?.claude?.ready ? "Claude READY" : "Claude CHECK", status?.codex?.ready ? "Codex READY" : "Codex CHECK"),
|
|
1986
|
+
summary: sectionSummary(status?.claude?.ready ? "Claude READY" : "Claude CHECK", `${status?.codex?.ready ? "Codex READY" : "Codex CHECK"} · ${status?.zcode?.ready ? "ZCode READY" : "ZCode CHECK"}`),
|
|
1958
1987
|
expanded: !!expandedSections.integrations,
|
|
1959
1988
|
onToggle: () => toggleSection("integrations"),
|
|
1960
1989
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -2023,7 +2052,15 @@ function WorkersPanel({ ctx }) {
|
|
|
2023
2052
|
opacity: .6
|
|
2024
2053
|
},
|
|
2025
2054
|
children: (status?.codex?.missing ?? []).join(" · ")
|
|
2026
|
-
}), "codex", "codex-uninstall", copy.tips.codex)
|
|
2055
|
+
}), "codex", "codex-uninstall", copy.tips.codex),
|
|
2056
|
+
integrationRow("ZCode", !!status?.zcode?.installed, !!status?.zcode?.ready, status?.zcode?.ready ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2057
|
+
title: (status?.zcode?.missing ?? []).join(", "),
|
|
2058
|
+
style: {
|
|
2059
|
+
fontSize: 11,
|
|
2060
|
+
opacity: .6
|
|
2061
|
+
},
|
|
2062
|
+
children: (status?.zcode?.missing ?? []).join(" · ")
|
|
2063
|
+
}), "zcode", "zcode-uninstall", copy.tips.zcode)
|
|
2027
2064
|
]
|
|
2028
2065
|
})
|
|
2029
2066
|
}),
|
|
@@ -192,6 +192,7 @@ function bridgeState(surface) {
|
|
|
192
192
|
function projectHostReadiness({ installStatus, runtime, surface } = {}) {
|
|
193
193
|
const codex = installStatus?.codex;
|
|
194
194
|
const claude = installStatus?.claude;
|
|
195
|
+
const zcode = installStatus?.zcode;
|
|
195
196
|
return [
|
|
196
197
|
{
|
|
197
198
|
id: "codex_mcp",
|
|
@@ -214,6 +215,18 @@ function projectHostReadiness({ installStatus, runtime, surface } = {}) {
|
|
|
214
215
|
"permissions"
|
|
215
216
|
])
|
|
216
217
|
},
|
|
218
|
+
{
|
|
219
|
+
id: "zcode_mcp",
|
|
220
|
+
state: componentState(zcode, [
|
|
221
|
+
"mcp",
|
|
222
|
+
"policy",
|
|
223
|
+
"worker_agent",
|
|
224
|
+
"reviewer_agent",
|
|
225
|
+
"config_prompt",
|
|
226
|
+
"status_prompt",
|
|
227
|
+
"ownership"
|
|
228
|
+
])
|
|
229
|
+
},
|
|
217
230
|
{
|
|
218
231
|
id: "crew_harness",
|
|
219
232
|
state: runtimeState(runtime),
|
|
@@ -354,7 +367,7 @@ const COPY = {
|
|
|
354
367
|
jobCount: (count) => `${count} 个任务`,
|
|
355
368
|
runningCount: (count) => `${count} 个运行中`,
|
|
356
369
|
sectionNames: {
|
|
357
|
-
integrations: "Codex / Claude 集成状态",
|
|
370
|
+
integrations: "Codex / Claude / ZCode 集成状态",
|
|
358
371
|
workflow: "Crew 工作流设置",
|
|
359
372
|
flash: "Worker / Flash",
|
|
360
373
|
pro: "Reviewer / Pro",
|
|
@@ -374,6 +387,7 @@ const COPY = {
|
|
|
374
387
|
ds_worker: "ds-worker",
|
|
375
388
|
ds_reviewer: "ds-reviewer",
|
|
376
389
|
claude_plugin: "Claude plugin",
|
|
390
|
+
zcode_mcp: "ZCode MCP",
|
|
377
391
|
crew_harness: "Crew Harness",
|
|
378
392
|
official_bridge: "Official bridge"
|
|
379
393
|
},
|
|
@@ -602,6 +616,11 @@ const COPY = {
|
|
|
602
616
|
install: "把 ds-flash / ds-pro 角色和 /dsh-config、/dsh-status 命令复制到 ~/.codex/(MCP 路径按本机自动渲染,含 approve 审批与超时配置)",
|
|
603
617
|
update: "重新渲染并覆盖角色文件与命令(插件路径或配置变更后用);原文件先备份",
|
|
604
618
|
restore: "删除 ~/.codex/ 下的 ds-flash / ds-pro 角色与 dsh 命令文件(角色文件先备份)"
|
|
619
|
+
},
|
|
620
|
+
zcode: {
|
|
621
|
+
install: "安装 ZCode 全局规则、ds-worker / ds-reviewer 角色、命令和按来源选择的 MCP 配置到 ~/.zcode/",
|
|
622
|
+
update: "重新渲染 ZCode 角色、命令和 MCP 条目;保留个人文件与其他 MCP 服务",
|
|
623
|
+
restore: "仅移除 dsh-crew 管理的 ZCode 文件和 MCP 条目(保留备份)"
|
|
605
624
|
}
|
|
606
625
|
}
|
|
607
626
|
},
|
|
@@ -627,7 +646,7 @@ const COPY = {
|
|
|
627
646
|
jobCount: (count) => `${count} jobs`,
|
|
628
647
|
runningCount: (count) => `${count} running`,
|
|
629
648
|
sectionNames: {
|
|
630
|
-
integrations: "Codex / Claude integration status",
|
|
649
|
+
integrations: "Codex / Claude / ZCode integration status",
|
|
631
650
|
workflow: "Crew workflow settings",
|
|
632
651
|
flash: "Worker / Flash",
|
|
633
652
|
pro: "Reviewer / Pro",
|
|
@@ -647,6 +666,7 @@ const COPY = {
|
|
|
647
666
|
ds_worker: "ds-worker",
|
|
648
667
|
ds_reviewer: "ds-reviewer",
|
|
649
668
|
claude_plugin: "Claude plugin",
|
|
669
|
+
zcode_mcp: "ZCode MCP",
|
|
650
670
|
crew_harness: "Crew Harness",
|
|
651
671
|
official_bridge: "Official bridge"
|
|
652
672
|
},
|
|
@@ -875,6 +895,11 @@ const COPY = {
|
|
|
875
895
|
install: "Copy ds-flash / ds-pro roles and /dsh-config, /dsh-status prompts into ~/.codex/ (MCP paths rendered for this machine, approve mode + timeout included)",
|
|
876
896
|
update: "Re-render and overwrite role files and prompts (after path/config changes); originals backed up",
|
|
877
897
|
restore: "Delete ds-flash / ds-pro roles and dsh prompts from ~/.codex/ (roles backed up first)"
|
|
898
|
+
},
|
|
899
|
+
zcode: {
|
|
900
|
+
install: "Install the ZCode global policy, ds-worker / ds-reviewer agents, commands and source-aware MCP config under ~/.zcode/",
|
|
901
|
+
update: "Re-render ZCode agents, commands and MCP entry; user files and unrelated MCP servers are preserved",
|
|
902
|
+
restore: "Remove only dsh-crew-owned ZCode files and MCP entry (backups kept)"
|
|
878
903
|
}
|
|
879
904
|
}
|
|
880
905
|
}
|
|
@@ -1879,6 +1904,10 @@ function WorkersPanel({ ctx }) {
|
|
|
1879
1904
|
style: S.chip(!!status?.claude?.ready),
|
|
1880
1905
|
children: ["Claude ", status?.claude?.ready ? "READY" : "CHECK"]
|
|
1881
1906
|
}),
|
|
1907
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1908
|
+
style: S.chip(!!status?.zcode?.ready),
|
|
1909
|
+
children: ["ZCode ", status?.zcode?.ready ? "READY" : "CHECK"]
|
|
1910
|
+
}),
|
|
1882
1911
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1883
1912
|
style: S.chip(jobs.some((job) => job.status === "running")),
|
|
1884
1913
|
children: [jobs.filter((job) => job.status === "running").length, " running"]
|
|
@@ -1954,7 +1983,7 @@ function WorkersPanel({ ctx }) {
|
|
|
1954
1983
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleSection, {
|
|
1955
1984
|
sectionId: "integrations",
|
|
1956
1985
|
title: copy.sectionNames.integrations,
|
|
1957
|
-
summary: sectionSummary(status?.claude?.ready ? "Claude READY" : "Claude CHECK", status?.codex?.ready ? "Codex READY" : "Codex CHECK"),
|
|
1986
|
+
summary: sectionSummary(status?.claude?.ready ? "Claude READY" : "Claude CHECK", `${status?.codex?.ready ? "Codex READY" : "Codex CHECK"} · ${status?.zcode?.ready ? "ZCode READY" : "ZCode CHECK"}`),
|
|
1958
1987
|
expanded: !!expandedSections.integrations,
|
|
1959
1988
|
onToggle: () => toggleSection("integrations"),
|
|
1960
1989
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -2023,7 +2052,15 @@ function WorkersPanel({ ctx }) {
|
|
|
2023
2052
|
opacity: .6
|
|
2024
2053
|
},
|
|
2025
2054
|
children: (status?.codex?.missing ?? []).join(" · ")
|
|
2026
|
-
}), "codex", "codex-uninstall", copy.tips.codex)
|
|
2055
|
+
}), "codex", "codex-uninstall", copy.tips.codex),
|
|
2056
|
+
integrationRow("ZCode", !!status?.zcode?.installed, !!status?.zcode?.ready, status?.zcode?.ready ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2057
|
+
title: (status?.zcode?.missing ?? []).join(", "),
|
|
2058
|
+
style: {
|
|
2059
|
+
fontSize: 11,
|
|
2060
|
+
opacity: .6
|
|
2061
|
+
},
|
|
2062
|
+
children: (status?.zcode?.missing ?? []).join(" · ")
|
|
2063
|
+
}), "zcode", "zcode-uninstall", copy.tips.zcode)
|
|
2027
2064
|
]
|
|
2028
2065
|
})
|
|
2029
2066
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ran-sh/dsh-crew",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/hub/entry.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -126,6 +126,8 @@
|
|
|
126
126
|
"deepseek",
|
|
127
127
|
"claude-code",
|
|
128
128
|
"codex",
|
|
129
|
+
"zcode",
|
|
130
|
+
"windows",
|
|
129
131
|
"subagent",
|
|
130
132
|
"worker",
|
|
131
133
|
"multimodal",
|
|
@@ -140,8 +142,10 @@
|
|
|
140
142
|
"agents",
|
|
141
143
|
"commands",
|
|
142
144
|
"codex",
|
|
145
|
+
"zcode",
|
|
143
146
|
"statusline",
|
|
144
147
|
"official-web-bridge",
|
|
148
|
+
"windows",
|
|
145
149
|
"cordis.patch.yml",
|
|
146
150
|
"worker.cordis.yml",
|
|
147
151
|
".claude-plugin",
|
|
@@ -152,6 +156,7 @@
|
|
|
152
156
|
"docs/readiness-matrix.md",
|
|
153
157
|
"docs/gpt-relay-extension.md",
|
|
154
158
|
"docs/ui-surfaces.md",
|
|
159
|
+
"docs/installation.md",
|
|
155
160
|
"docs/images/dsh-crew-logo.png",
|
|
156
161
|
"docs/images/dsh-crew-overview.png",
|
|
157
162
|
"docs/images/dsh-crew-host.png",
|
package/scripts/setup.mjs
CHANGED
|
@@ -23,20 +23,57 @@ import {
|
|
|
23
23
|
|
|
24
24
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
25
25
|
|
|
26
|
-
function commandExists(name) {
|
|
27
|
-
const r = spawnSync(/^win/.test(process.platform) ? 'where' : 'which', [name], {
|
|
26
|
+
function commandExists(name) {
|
|
27
|
+
const r = spawnSync(/^win/.test(process.platform) ? 'where' : 'which', [name], {
|
|
28
28
|
encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
|
|
29
29
|
});
|
|
30
|
-
return r.status === 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
return r.status === 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const PACKAGE_MANAGER_COMMAND = /^(?:npm|npx|pnpm|yarn|yarnpkg|bun|bunx)$/i;
|
|
34
|
+
|
|
35
|
+
export function spawnCommand(command, platform = process.platform) {
|
|
36
|
+
if (platform === 'win32' && PACKAGE_MANAGER_COMMAND.test(command)) {
|
|
37
|
+
return `${command}.cmd`;
|
|
38
|
+
}
|
|
39
|
+
return command;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function spawnNeedsShell(command, platform = process.platform) {
|
|
43
|
+
return platform === 'win32' && PACKAGE_MANAGER_COMMAND.test(command);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function spawnInvocation(command, args = [], platform = process.platform, environment = process.env) {
|
|
47
|
+
const executable = spawnCommand(command, platform);
|
|
48
|
+
if (!spawnNeedsShell(command, platform)) return { command: executable, args };
|
|
49
|
+
const unsafe = args.find((arg) => !/^[A-Za-z0-9@._:+/=\-]+$/.test(String(arg)));
|
|
50
|
+
if (unsafe !== undefined) throw new Error(`unsafe package-manager argument: ${unsafe}`);
|
|
51
|
+
return {
|
|
52
|
+
command: environment.ComSpec || 'cmd.exe',
|
|
53
|
+
args: ['/d', '/s', '/c', [executable, ...args].join(' ')],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function run(cmd, args, opts = {}) {
|
|
58
|
+
let invocation;
|
|
59
|
+
try {
|
|
60
|
+
invocation = spawnInvocation(cmd, args);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return { ok: false, status: -1, stdout: '', stderr: String(error?.message ?? error), error };
|
|
63
|
+
}
|
|
64
|
+
const r = spawnSync(invocation.command, invocation.args, {
|
|
65
|
+
encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], shell: opts.shell === true, cwd: opts.cwd ?? ROOT,
|
|
66
|
+
env: opts.env ?? process.env,
|
|
67
|
+
});
|
|
68
|
+
const processError = r.error ? `${r.error.name}: ${r.error.message}` : '';
|
|
69
|
+
return {
|
|
70
|
+
ok: r.status === 0,
|
|
71
|
+
status: r.status ?? -1,
|
|
72
|
+
stdout: r.stdout ?? '',
|
|
73
|
+
stderr: r.stderr || processError,
|
|
74
|
+
error: r.error ?? null,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
40
77
|
|
|
41
78
|
/**
|
|
42
79
|
* Detect the DSH CLI. `allowDownload` is intentionally opt-in: installation
|
|
@@ -106,18 +143,18 @@ export async function setupInstall({
|
|
|
106
143
|
installer = realInstaller,
|
|
107
144
|
depRunner = null,
|
|
108
145
|
} = {}) {
|
|
109
|
-
log('DSH Crew installer');
|
|
110
|
-
if (!checkRoot(root)) return { ok: false, error: `not a dsh-crew checkout: ${root}` };
|
|
111
|
-
|
|
112
|
-
|
|
146
|
+
log('DSH Crew installer');
|
|
147
|
+
if (!checkRoot(root)) return { ok: false, error: `not a dsh-crew checkout: ${root}` };
|
|
148
|
+
const pnpmOk = commandExists('pnpm');
|
|
149
|
+
|
|
150
|
+
if (depRunner) {
|
|
113
151
|
const r = depRunner(root);
|
|
114
152
|
if (!r.ok) { mark(log, false, r.text); return { ok: false, error: r.text }; }
|
|
115
153
|
mark(log, true, r.text);
|
|
116
|
-
} else if (!dryRun) {
|
|
117
|
-
const
|
|
118
|
-
const cmd = pnpmOk ? 'pnpm' : 'npx';
|
|
154
|
+
} else if (!dryRun) {
|
|
155
|
+
const cmd = pnpmOk ? 'pnpm' : 'npx';
|
|
119
156
|
const baseArgs = pnpmOk ? [] : ['-y', 'pnpm'];
|
|
120
|
-
const d = run(cmd, [...baseArgs, 'install', '--frozen-lockfile']);
|
|
157
|
+
const d = run(cmd, [...baseArgs, 'install', '--frozen-lockfile'], { cwd: root });
|
|
121
158
|
if (!d.ok) {
|
|
122
159
|
if (depsPresent(root)) mark(log, true, `dependencies (already present; install skipped — ${(d.stderr || d.stdout || '').trim().split('\n')[0]})`);
|
|
123
160
|
else {
|
|
@@ -126,9 +163,11 @@ export async function setupInstall({
|
|
|
126
163
|
}
|
|
127
164
|
} else mark(log, true, 'dependencies');
|
|
128
165
|
} else mark(log, true, 'dependencies (dry-run)');
|
|
129
|
-
|
|
130
|
-
if (!dryRun) {
|
|
131
|
-
const b =
|
|
166
|
+
|
|
167
|
+
if (!dryRun) {
|
|
168
|
+
const b = pnpmOk
|
|
169
|
+
? run('pnpm', ['run', 'build:client'], { cwd: root })
|
|
170
|
+
: run('npx', ['-y', 'pnpm', 'run', 'build:client'], { cwd: root });
|
|
132
171
|
if (!b.ok) {
|
|
133
172
|
log(`✗ client build failed:\n${(b.stderr || b.stdout || '').slice(0, 600)}`);
|
|
134
173
|
return { ok: false, error: 'client build failed' };
|
|
@@ -167,12 +206,36 @@ export async function setupInstall({
|
|
|
167
206
|
mark(log, true, `DSH crew profile linked offline (dedicated Crew DSH_HOME, profile dsh-crew; ${registration.changed ? 'updated' : 'already current'})`);
|
|
168
207
|
}
|
|
169
208
|
|
|
170
|
-
if (dryRun) mark(log, true, 'Codex Desktop integration (dry-run)');
|
|
171
|
-
else {
|
|
209
|
+
if (dryRun) mark(log, true, 'Codex Desktop integration (dry-run)');
|
|
210
|
+
else {
|
|
172
211
|
const r = installer.installCodex ? installer.installCodex({ home }) : realInstaller.installCodex({ home });
|
|
173
212
|
mark(log, r.ok !== false, r.ok === false ? `Codex Desktop integration failed: ${(r.actions ?? []).join('; ')}` : 'Codex Desktop integration');
|
|
174
|
-
if (r.ok === false) return { ok: false, error: 'Codex integration failed' };
|
|
175
|
-
}
|
|
213
|
+
if (r.ok === false) return { ok: false, error: 'Codex integration failed' };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (dryRun) mark(log, true, 'ZCode integration (dry-run)');
|
|
217
|
+
else {
|
|
218
|
+
const r = installer.installZCode
|
|
219
|
+
? installer.installZCode({ home, root })
|
|
220
|
+
: realInstaller.installZCode({ home, root });
|
|
221
|
+
if (r.ok === false) {
|
|
222
|
+
mark(log, false, `ZCode integration failed (${r.code ?? 'unknown'})`);
|
|
223
|
+
return { ok: false, error: 'ZCode integration failed' };
|
|
224
|
+
}
|
|
225
|
+
mark(log, true, 'ZCode integration');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (dryRun) mark(log, true, 'Windows login startup (dry-run)');
|
|
229
|
+
else {
|
|
230
|
+
const r = installer.installWindowsStartup
|
|
231
|
+
? installer.installWindowsStartup({ home, root })
|
|
232
|
+
: realInstaller.installWindowsStartup({ home, root });
|
|
233
|
+
if (r.ok === false) {
|
|
234
|
+
mark(log, false, `Windows login startup failed (${r.code ?? 'unknown'})`);
|
|
235
|
+
return { ok: false, error: 'Windows login startup failed' };
|
|
236
|
+
}
|
|
237
|
+
if (r.supported) mark(log, true, 'Windows login startup');
|
|
238
|
+
}
|
|
176
239
|
|
|
177
240
|
if (commandExists('claude')) {
|
|
178
241
|
if (dryRun) mark(log, true, 'Claude Code integration (dry-run)');
|
|
@@ -203,17 +266,31 @@ export async function setupUninstall({
|
|
|
203
266
|
const fail = (name, text) => { mark(log, false, text || `${name} failed`); failures.push(name); };
|
|
204
267
|
|
|
205
268
|
if (dryRun) {
|
|
206
|
-
mark(log, true, 'Codex Desktop integration would be removed');
|
|
207
|
-
mark(log, true, '
|
|
208
|
-
mark(log, true, '
|
|
269
|
+
mark(log, true, 'Codex Desktop integration would be removed');
|
|
270
|
+
mark(log, true, 'ZCode integration would be removed');
|
|
271
|
+
mark(log, true, 'Claude Code integration would be removed');
|
|
272
|
+
mark(log, true, 'Windows login startup would be removed');
|
|
273
|
+
mark(log, true, 'DSH crew profile would be removed');
|
|
209
274
|
} else {
|
|
210
275
|
const cx = installer.uninstallCodex ? installer.uninstallCodex({ home }) : realInstaller.uninstallCodex({ home });
|
|
211
|
-
if (cx.ok !== false) mark(log, true, 'Codex Desktop integration removed');
|
|
212
|
-
else fail('codex', 'Codex Desktop integration removal failed');
|
|
276
|
+
if (cx.ok !== false) mark(log, true, 'Codex Desktop integration removed');
|
|
277
|
+
else fail('codex', 'Codex Desktop integration removal failed');
|
|
278
|
+
|
|
279
|
+
const zc = installer.uninstallZCode
|
|
280
|
+
? installer.uninstallZCode({ home, root })
|
|
281
|
+
: realInstaller.uninstallZCode({ home, root });
|
|
282
|
+
if (zc.ok !== false) mark(log, true, 'ZCode integration removed');
|
|
283
|
+
else fail('zcode', 'ZCode integration removal failed');
|
|
213
284
|
|
|
214
|
-
const cl = installer.uninstallClaudeCode ? installer.uninstallClaudeCode({ home }) : realInstaller.uninstallClaudeCode({ home });
|
|
215
|
-
if (cl.ok !== false) mark(log, true, 'Claude Code integration removed');
|
|
216
|
-
else fail('claude', 'Claude Code integration removal failed');
|
|
285
|
+
const cl = installer.uninstallClaudeCode ? installer.uninstallClaudeCode({ home }) : realInstaller.uninstallClaudeCode({ home });
|
|
286
|
+
if (cl.ok !== false) mark(log, true, 'Claude Code integration removed');
|
|
287
|
+
else fail('claude', 'Claude Code integration removal failed');
|
|
288
|
+
|
|
289
|
+
const startup = installer.uninstallWindowsStartup
|
|
290
|
+
? installer.uninstallWindowsStartup({ home })
|
|
291
|
+
: realInstaller.uninstallWindowsStartup({ home });
|
|
292
|
+
if (startup.ok === false) fail('startup', 'Windows login startup removal failed');
|
|
293
|
+
else if (startup.supported) mark(log, true, 'Windows login startup removed');
|
|
217
294
|
|
|
218
295
|
const name = readPackageName(root);
|
|
219
296
|
if (!name) fail('dsh', 'DSH plugin removal failed: package name missing');
|
|
@@ -243,9 +320,15 @@ export async function setupUninstall({
|
|
|
243
320
|
}
|
|
244
321
|
|
|
245
322
|
export async function setupStatus({ log = console.log, root = ROOT, home = homedir(), installer = realInstaller } = {}) {
|
|
246
|
-
const st = installer.installStatus ? installer.installStatus({ home }) : realInstaller.installStatus({ home });
|
|
247
|
-
const claude = st?.claude?.installed ? 'installed' : 'not installed';
|
|
248
|
-
const codex = st?.codex?.installed ? 'installed' : 'not installed';
|
|
323
|
+
const st = installer.installStatus ? installer.installStatus({ home, root }) : realInstaller.installStatus({ home, root });
|
|
324
|
+
const claude = st?.claude?.installed ? 'installed' : 'not installed';
|
|
325
|
+
const codex = st?.codex?.installed ? 'installed' : 'not installed';
|
|
326
|
+
const zcode = st?.zcode?.installed ? 'installed' : 'not installed';
|
|
327
|
+
const startupState = installer.windowsStartupStatus
|
|
328
|
+
? installer.windowsStartupStatus({ home })
|
|
329
|
+
: realInstaller.windowsStartupStatus({ home });
|
|
330
|
+
const windowsStartup = !startupState.supported ? 'not supported'
|
|
331
|
+
: startupState.ready ? 'installed' : startupState.installed ? 'needs repair' : 'not installed';
|
|
249
332
|
// Crew status reads ONLY the dedicated Crew profile under the Crew DSH_HOME;
|
|
250
333
|
// the official web profile layout under the default DSH home is intentionally
|
|
251
334
|
// never inspected.
|
|
@@ -260,10 +343,12 @@ export async function setupStatus({ log = console.log, root = ROOT, home = homed
|
|
|
260
343
|
} catch { dshPlugin = 'unknown'; }
|
|
261
344
|
}
|
|
262
345
|
log(`DSH plugin: ${dshPlugin} (dedicated dsh-crew profile; official web profile ignored)`);
|
|
263
|
-
log(`Codex Desktop integration: ${codex}`);
|
|
264
|
-
log(`
|
|
265
|
-
|
|
266
|
-
}
|
|
346
|
+
log(`Codex Desktop integration: ${codex}`);
|
|
347
|
+
log(`ZCode integration: ${zcode}`);
|
|
348
|
+
log(`Claude Code integration: ${claude}`);
|
|
349
|
+
log(`Windows login startup: ${windowsStartup}`);
|
|
350
|
+
return { ok: true, dshPlugin, codex, zcode, claude, windowsStartup };
|
|
351
|
+
}
|
|
267
352
|
|
|
268
353
|
export async function runSetupCli({ argv = process.argv.slice(2), run: actions = {}, log = console.log } = {}) {
|
|
269
354
|
const action = argv[0];
|
|
@@ -33,13 +33,14 @@ function bridgeState(surface) {
|
|
|
33
33
|
export function projectHostReadiness({ installStatus, runtime, surface } = {}) {
|
|
34
34
|
const codex = installStatus?.codex;
|
|
35
35
|
const claude = installStatus?.claude;
|
|
36
|
+
const zcode = installStatus?.zcode;
|
|
36
37
|
return [
|
|
37
38
|
{ id: 'codex_mcp', state: componentState(codex, ['mcp'], { aligned: true }) },
|
|
38
39
|
{ id: 'ds_worker', state: componentState(codex, ['worker_role'], { aligned: true }) },
|
|
39
40
|
{ id: 'ds_reviewer', state: componentState(codex, ['reviewer_role'], { aligned: true }) },
|
|
40
41
|
{ id: 'claude_plugin', state: componentState(claude, ['enabled', 'marketplace', 'snapshot', 'permissions']) },
|
|
42
|
+
{ id: 'zcode_mcp', state: componentState(zcode, ['mcp', 'policy', 'worker_agent', 'reviewer_agent', 'config_prompt', 'status_prompt', 'ownership']) },
|
|
41
43
|
{ id: 'crew_harness', state: runtimeState(runtime), detail: runtime?.runtime_version ?? null },
|
|
42
44
|
{ id: 'official_bridge', state: bridgeState(surface) },
|
|
43
45
|
];
|
|
44
46
|
}
|
|
45
|
-
|
package/src/client/index.tsx
CHANGED
|
@@ -52,11 +52,11 @@ const COPY = {
|
|
|
52
52
|
expandAll: '全部展开', collapseAll: '全部折叠',
|
|
53
53
|
modelCount: (count: number) => `${count} 个模型`, providerCount: (count: number) => `${count} 个 Provider`,
|
|
54
54
|
jobCount: (count: number) => `${count} 个任务`, runningCount: (count: number) => `${count} 个运行中`,
|
|
55
|
-
sectionNames: { integrations: 'Codex / Claude 集成状态', workflow: 'Crew 工作流设置', flash: 'Worker / Flash', pro: 'Reviewer / Pro', dispatch: '模型优先级与派发', adaptive: '自适应路由', runtime: '运行 / 生效边界', multimodal: '视觉与生图', providers: '自定义 Provider', jobs: '任务状态' },
|
|
55
|
+
sectionNames: { integrations: 'Codex / Claude / ZCode 集成状态', workflow: 'Crew 工作流设置', flash: 'Worker / Flash', pro: 'Reviewer / Pro', dispatch: '模型优先级与派发', adaptive: '自适应路由', runtime: '运行 / 生效边界', multimodal: '视觉与生图', providers: '自定义 Provider', jobs: '任务状态' },
|
|
56
56
|
openHarness: '打开 3210 Crew Harness →',
|
|
57
57
|
harnessHint: '底层 Provider、Harness Models 与运行时配置',
|
|
58
58
|
hostReadiness: '宿主集成就绪度', hostReadinessHint: '只使用结构化安装与运行时证据;缺少证据不会显示 READY。',
|
|
59
|
-
readinessLabels: { codex_mcp: 'Codex MCP', ds_worker: 'ds-worker', ds_reviewer: 'ds-reviewer', claude_plugin: 'Claude plugin', crew_harness: 'Crew Harness', official_bridge: 'Official bridge' },
|
|
59
|
+
readinessLabels: { codex_mcp: 'Codex MCP', ds_worker: 'ds-worker', ds_reviewer: 'ds-reviewer', claude_plugin: 'Claude plugin', zcode_mcp: 'ZCode MCP', crew_harness: 'Crew Harness', official_bridge: 'Official bridge' },
|
|
60
60
|
readinessStates: { READY: 'READY', DEGRADED: 'DEGRADED', UNAVAILABLE: 'UNAVAILABLE', UNKNOWN: 'UNKNOWN' },
|
|
61
61
|
globalHint: '修改即时保存到 ~/.config/dsh-crew/config.json;CC / Codex 的新会话自动读取为默认值(会话内可用 /dsh-crew:config 临时覆盖)。',
|
|
62
62
|
orchestration: 'Agent 编排',
|
|
@@ -154,11 +154,16 @@ const COPY = {
|
|
|
154
154
|
update: '重跑安装流程:刷新注册与权限、迁移旧格式配置、更新 HUD 接线;幂等,可放心点',
|
|
155
155
|
restore: '从 Claude Code 移除集成:清除 marketplace 注册、插件启用项与权限规则(settings 先备份);不删除插件源码与已跑任务',
|
|
156
156
|
},
|
|
157
|
-
codex: {
|
|
158
|
-
install: '把 ds-flash / ds-pro 角色和 /dsh-config、/dsh-status 命令复制到 ~/.codex/(MCP 路径按本机自动渲染,含 approve 审批与超时配置)',
|
|
159
|
-
update: '重新渲染并覆盖角色文件与命令(插件路径或配置变更后用);原文件先备份',
|
|
160
|
-
restore: '删除 ~/.codex/ 下的 ds-flash / ds-pro 角色与 dsh 命令文件(角色文件先备份)',
|
|
161
|
-
},
|
|
157
|
+
codex: {
|
|
158
|
+
install: '把 ds-flash / ds-pro 角色和 /dsh-config、/dsh-status 命令复制到 ~/.codex/(MCP 路径按本机自动渲染,含 approve 审批与超时配置)',
|
|
159
|
+
update: '重新渲染并覆盖角色文件与命令(插件路径或配置变更后用);原文件先备份',
|
|
160
|
+
restore: '删除 ~/.codex/ 下的 ds-flash / ds-pro 角色与 dsh 命令文件(角色文件先备份)',
|
|
161
|
+
},
|
|
162
|
+
zcode: {
|
|
163
|
+
install: '安装 ZCode 全局规则、ds-worker / ds-reviewer 角色、命令和按来源选择的 MCP 配置到 ~/.zcode/',
|
|
164
|
+
update: '重新渲染 ZCode 角色、命令和 MCP 条目;保留个人文件与其他 MCP 服务',
|
|
165
|
+
restore: '仅移除 dsh-crew 管理的 ZCode 文件和 MCP 条目(保留备份)',
|
|
166
|
+
},
|
|
162
167
|
},
|
|
163
168
|
},
|
|
164
169
|
en: {
|
|
@@ -173,11 +178,11 @@ const COPY = {
|
|
|
173
178
|
expandAll: 'Expand all', collapseAll: 'Collapse all',
|
|
174
179
|
modelCount: (count: number) => `${count} models`, providerCount: (count: number) => `${count} providers`,
|
|
175
180
|
jobCount: (count: number) => `${count} jobs`, runningCount: (count: number) => `${count} running`,
|
|
176
|
-
sectionNames: { integrations: 'Codex / Claude integration status', workflow: 'Crew workflow settings', flash: 'Worker / Flash', pro: 'Reviewer / Pro', dispatch: 'Model priority & dispatch', adaptive: 'Adaptive routing', runtime: 'Runtime / activation boundaries', multimodal: 'Vision & image generation', providers: 'Custom providers', jobs: 'Task status' },
|
|
181
|
+
sectionNames: { integrations: 'Codex / Claude / ZCode integration status', workflow: 'Crew workflow settings', flash: 'Worker / Flash', pro: 'Reviewer / Pro', dispatch: 'Model priority & dispatch', adaptive: 'Adaptive routing', runtime: 'Runtime / activation boundaries', multimodal: 'Vision & image generation', providers: 'Custom providers', jobs: 'Task status' },
|
|
177
182
|
openHarness: 'Open 3210 Crew Harness →',
|
|
178
183
|
harnessHint: 'Low-level providers, Harness Models, and runtime configuration',
|
|
179
184
|
hostReadiness: 'Host integration readiness', hostReadinessHint: 'Uses structured installer and runtime evidence only; missing evidence is never READY.',
|
|
180
|
-
readinessLabels: { codex_mcp: 'Codex MCP', ds_worker: 'ds-worker', ds_reviewer: 'ds-reviewer', claude_plugin: 'Claude plugin', crew_harness: 'Crew Harness', official_bridge: 'Official bridge' },
|
|
185
|
+
readinessLabels: { codex_mcp: 'Codex MCP', ds_worker: 'ds-worker', ds_reviewer: 'ds-reviewer', claude_plugin: 'Claude plugin', zcode_mcp: 'ZCode MCP', crew_harness: 'Crew Harness', official_bridge: 'Official bridge' },
|
|
181
186
|
readinessStates: { READY: 'READY', DEGRADED: 'DEGRADED', UNAVAILABLE: 'UNAVAILABLE', UNKNOWN: 'UNKNOWN' },
|
|
182
187
|
globalHint: 'Changes save instantly to ~/.config/dsh-crew/config.json; new CC / Codex sessions pick them up as defaults (override per session with /dsh-crew:config).',
|
|
183
188
|
orchestration: 'Agent orchestration',
|
|
@@ -275,11 +280,16 @@ const COPY = {
|
|
|
275
280
|
update: 'Re-run the installer: refresh registration & permissions, migrate legacy config, update HUD wiring; idempotent',
|
|
276
281
|
restore: 'Remove the integration from Claude Code: marketplace registration, plugin enablement and permission rules (settings backed up); plugin source and past jobs untouched',
|
|
277
282
|
},
|
|
278
|
-
codex: {
|
|
279
|
-
install: 'Copy ds-flash / ds-pro roles and /dsh-config, /dsh-status prompts into ~/.codex/ (MCP paths rendered for this machine, approve mode + timeout included)',
|
|
280
|
-
update: 'Re-render and overwrite role files and prompts (after path/config changes); originals backed up',
|
|
281
|
-
restore: 'Delete ds-flash / ds-pro roles and dsh prompts from ~/.codex/ (roles backed up first)',
|
|
282
|
-
},
|
|
283
|
+
codex: {
|
|
284
|
+
install: 'Copy ds-flash / ds-pro roles and /dsh-config, /dsh-status prompts into ~/.codex/ (MCP paths rendered for this machine, approve mode + timeout included)',
|
|
285
|
+
update: 'Re-render and overwrite role files and prompts (after path/config changes); originals backed up',
|
|
286
|
+
restore: 'Delete ds-flash / ds-pro roles and dsh prompts from ~/.codex/ (roles backed up first)',
|
|
287
|
+
},
|
|
288
|
+
zcode: {
|
|
289
|
+
install: 'Install the ZCode global policy, ds-worker / ds-reviewer agents, commands and source-aware MCP config under ~/.zcode/',
|
|
290
|
+
update: 'Re-render ZCode agents, commands and MCP entry; user files and unrelated MCP servers are preserved',
|
|
291
|
+
restore: 'Remove only dsh-crew-owned ZCode files and MCP entry (backups kept)',
|
|
292
|
+
},
|
|
283
293
|
},
|
|
284
294
|
},
|
|
285
295
|
};
|
|
@@ -817,6 +827,7 @@ function WorkersPanel({ ctx }: { ctx: any }) {
|
|
|
817
827
|
<div style={{ display: 'flex', gap: 6, marginTop: 8, flexWrap: 'wrap' }}>
|
|
818
828
|
<span style={S.chip(!!status?.codex?.ready)}>Codex {status?.codex?.ready ? 'READY' : 'CHECK'}</span>
|
|
819
829
|
<span style={S.chip(!!status?.claude?.ready)}>Claude {status?.claude?.ready ? 'READY' : 'CHECK'}</span>
|
|
830
|
+
<span style={S.chip(!!status?.zcode?.ready)}>ZCode {status?.zcode?.ready ? 'READY' : 'CHECK'}</span>
|
|
820
831
|
<span style={S.chip(jobs.some((job) => job.status === 'running'))}>{jobs.filter((job) => job.status === 'running').length} running</span>
|
|
821
832
|
</div>
|
|
822
833
|
</div>
|
|
@@ -836,7 +847,7 @@ function WorkersPanel({ ctx }: { ctx: any }) {
|
|
|
836
847
|
</div>
|
|
837
848
|
|
|
838
849
|
<CollapsibleSection sectionId="integrations" title={copy.sectionNames.integrations}
|
|
839
|
-
summary={sectionSummary(status?.claude?.ready ? 'Claude READY' : 'Claude CHECK', status?.codex?.ready ? 'Codex READY' : 'Codex CHECK')}
|
|
850
|
+
summary={sectionSummary(status?.claude?.ready ? 'Claude READY' : 'Claude CHECK', `${status?.codex?.ready ? 'Codex READY' : 'Codex CHECK'} · ${status?.zcode?.ready ? 'ZCode READY' : 'ZCode CHECK'}`)}
|
|
840
851
|
expanded={!!expandedSections.integrations} onToggle={() => toggleSection('integrations')}>
|
|
841
852
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
842
853
|
<div style={S.block}>
|
|
@@ -860,6 +871,9 @@ function WorkersPanel({ ctx }: { ctx: any }) {
|
|
|
860
871
|
{integrationRow('Codex', !!status?.codex?.installed, !!status?.codex?.ready,
|
|
861
872
|
status?.codex?.ready ? null : <span title={(status?.codex?.missing ?? []).join(', ')} style={{ fontSize: 11, opacity: 0.6 }}>{(status?.codex?.missing ?? []).join(' · ')}</span>,
|
|
862
873
|
'codex', 'codex-uninstall', (copy as any).tips.codex)}
|
|
874
|
+
{integrationRow('ZCode', !!status?.zcode?.installed, !!status?.zcode?.ready,
|
|
875
|
+
status?.zcode?.ready ? null : <span title={(status?.zcode?.missing ?? []).join(', ')} style={{ fontSize: 11, opacity: 0.6 }}>{(status?.zcode?.missing ?? []).join(' · ')}</span>,
|
|
876
|
+
'zcode', 'zcode-uninstall', (copy as any).tips.zcode)}
|
|
863
877
|
</div>
|
|
864
878
|
</CollapsibleSection>
|
|
865
879
|
|