@ran-sh/dsh-crew 1.9.0 → 1.9.1

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.
Files changed (151) hide show
  1. package/.claude-plugin/marketplace.json +16 -16
  2. package/.claude-plugin/plugin.json +14 -14
  3. package/LICENSE +21 -21
  4. package/README.de.md +359 -359
  5. package/README.es.md +359 -359
  6. package/README.fr.md +359 -359
  7. package/README.hi.md +359 -359
  8. package/README.id.md +359 -359
  9. package/README.ja.md +359 -359
  10. package/README.ko.md +359 -359
  11. package/README.md +126 -126
  12. package/README.pt.md +359 -359
  13. package/README.ru.md +359 -359
  14. package/README.th.md +359 -359
  15. package/README.tr.md +359 -359
  16. package/README.vi.md +359 -359
  17. package/README.zh-TW.md +359 -359
  18. package/README.zh.md +116 -116
  19. package/agents/ds-flash.md +24 -24
  20. package/agents/ds-pro.md +24 -24
  21. package/agents/ds-reviewer.md +23 -23
  22. package/agents/ds-worker.md +23 -23
  23. package/bin/dsh-crew.mjs +16 -16
  24. package/codex/agents/ds-flash.toml +34 -34
  25. package/codex/agents/ds-pro.toml +34 -34
  26. package/codex/agents/ds-reviewer.toml +32 -32
  27. package/codex/agents/ds-worker.toml +32 -32
  28. package/codex/prompts/dsh-config.md +19 -19
  29. package/codex/prompts/dsh-status.md +5 -5
  30. package/commands/config.md +23 -23
  31. package/commands/off.md +5 -5
  32. package/commands/on.md +5 -5
  33. package/commands/status.md +9 -9
  34. package/cordis.patch.yml +4 -4
  35. package/docs/gpt-relay-extension.md +103 -103
  36. package/docs/installation.md +138 -138
  37. package/docs/job-contracts.md +103 -103
  38. package/docs/readiness-matrix.md +85 -85
  39. package/docs/ui-surfaces.md +107 -107
  40. package/official-web-bridge/cordis.patch.yml +4 -4
  41. package/official-web-bridge/entry.mjs +1 -1
  42. package/official-web-bridge/overlay-entry.mjs +59 -59
  43. package/official-web-bridge/package.json +25 -25
  44. package/package.json +1 -1
  45. package/scripts/build-client.mjs +49 -49
  46. package/scripts/live-crew-smoke.mjs +39 -39
  47. package/scripts/live-policy-matrix.mjs +177 -177
  48. package/scripts/policy-probe.mjs +101 -101
  49. package/scripts/remove-legacy-official-bridge.ps1 +89 -89
  50. package/scripts/setup.mjs +393 -393
  51. package/scripts/smoke-real.mjs +110 -110
  52. package/scripts/smoke.mjs +78 -78
  53. package/scripts/verify-crew-ui-polish.mjs +145 -145
  54. package/scripts/verify-history-ui.mjs +97 -97
  55. package/scripts/verify-installer-fix.mjs +26 -26
  56. package/scripts/verify-npm-install.mjs +311 -311
  57. package/scripts/verify-official-bridge-e2e.mjs +192 -192
  58. package/src/adaptive-routing.mjs +260 -260
  59. package/src/client/activation-summary.tsx +64 -64
  60. package/src/client/collapsible-sections.mjs +55 -55
  61. package/src/client/history-panel.tsx +108 -108
  62. package/src/client/host-readiness.mjs +71 -71
  63. package/src/client/index.tsx +1711 -1711
  64. package/src/client/model-callability-view.mjs +17 -17
  65. package/src/client/panel-chrome.tsx +40 -40
  66. package/src/client/quick-entry.tsx +10 -10
  67. package/src/client/quick-panel.tsx +275 -275
  68. package/src/client/readiness-envelope.mjs +34 -34
  69. package/src/client/surface-detection.mjs +43 -43
  70. package/src/config-readiness.mjs +226 -226
  71. package/src/credential-reference.mjs +38 -38
  72. package/src/delivery.mjs +205 -205
  73. package/src/dsh-cli-runtime.mjs +1021 -1021
  74. package/src/dsh-cohort.mjs +20 -20
  75. package/src/extension-contract.mjs +104 -104
  76. package/src/failure-classification.mjs +201 -201
  77. package/src/history/admission-gate.mjs +67 -67
  78. package/src/history/archive-store.mjs +272 -272
  79. package/src/history/cleanup-plan.mjs +89 -89
  80. package/src/history/http.mjs +32 -32
  81. package/src/history/operation.mjs +86 -86
  82. package/src/history/runner-detach.mjs +34 -34
  83. package/src/history/runner.mjs +52 -52
  84. package/src/history/runtime.mjs +36 -36
  85. package/src/history/service.mjs +177 -177
  86. package/src/history/state.mjs +27 -27
  87. package/src/hub/entry.mjs +104 -104
  88. package/src/hub/index.mjs +2694 -2694
  89. package/src/hub-client.mjs +154 -154
  90. package/src/hub-compatibility.mjs +42 -42
  91. package/src/i18n.mjs +19 -19
  92. package/src/information-flow.mjs +67 -67
  93. package/src/install/cli.mjs +28 -28
  94. package/src/install/install-legacy.mjs +711 -711
  95. package/src/install/install.mjs +483 -483
  96. package/src/install/npx-lifecycle.mjs +3456 -3456
  97. package/src/install/official-frontend-assets.mjs +78 -78
  98. package/src/install/official-web.mjs +95 -95
  99. package/src/install/payload-content.mjs +88 -88
  100. package/src/install/windows-startup.mjs +236 -236
  101. package/src/install/windows-supervisor-adapter.mjs +443 -443
  102. package/src/install/windows-supervisor-lifecycle.mjs +782 -782
  103. package/src/install/zcode.mjs +397 -397
  104. package/src/job-contracts.mjs +255 -255
  105. package/src/local-request-guard.mjs +60 -60
  106. package/src/mcp-runtime.mjs +340 -340
  107. package/src/model-callability-contract.mjs +79 -79
  108. package/src/model-catalog.mjs +180 -180
  109. package/src/model-routing.mjs +586 -586
  110. package/src/model-schedule.mjs +207 -207
  111. package/src/official-web-bridge.mjs +447 -447
  112. package/src/policy.mjs +235 -235
  113. package/src/provider-delete-adapters.mjs +1934 -1934
  114. package/src/provider-health.mjs +130 -130
  115. package/src/provider-inventory.mjs +182 -182
  116. package/src/provider-layer-migration-adapters.mjs +759 -759
  117. package/src/provider-layer-migration.mjs +198 -198
  118. package/src/provider-lifecycle-state.mjs +103 -103
  119. package/src/provider-lifecycle.mjs +252 -252
  120. package/src/provider-profile-store.mjs +390 -390
  121. package/src/provider-settings-store.mjs +633 -633
  122. package/src/provider-store-lock.mjs +67 -67
  123. package/src/readiness-matrix.mjs +181 -181
  124. package/src/removable-waiter.mjs +29 -29
  125. package/src/role-profiles.mjs +107 -107
  126. package/src/runtime-controls.mjs +84 -84
  127. package/src/runtime-identity-contract.mjs +34 -34
  128. package/src/runtime-identity.mjs +235 -235
  129. package/src/runtime-readiness-snapshot.mjs +285 -285
  130. package/src/server.mjs +581 -581
  131. package/src/session-origins.mjs +60 -60
  132. package/src/standalone-sdk.mjs +23 -23
  133. package/src/status-shard.mjs +63 -63
  134. package/src/structured-error-code.mjs +38 -38
  135. package/src/supervisor/restart-request.mjs +256 -256
  136. package/src/workflow-runtime.mjs +739 -739
  137. package/src/workflow.mjs +155 -155
  138. package/src/workspace-audit.mjs +231 -231
  139. package/src/workspace-context.mjs +146 -146
  140. package/src/workspace-isolation.mjs +455 -455
  141. package/src/workspace-readiness.mjs +32 -32
  142. package/statusline/statusline.sh +14 -14
  143. package/statusline/worker-segment.sh +35 -35
  144. package/windows/start-dsh-crew.cmd +57 -57
  145. package/windows/start-dsh-crew.ps1 +1302 -1302
  146. package/windows/supervisor-control.ps1 +467 -467
  147. package/worker.cordis.yml +67 -67
  148. package/zcode/agents/ds-reviewer.md +31 -31
  149. package/zcode/agents/ds-worker.md +31 -31
  150. package/zcode/commands/dsh-config.md +17 -17
  151. package/zcode/commands/dsh-status.md +5 -5
@@ -1,154 +1,154 @@
1
- // Client for the in-host workers-hub jobs API. When a DSH web instance with the
2
- // dsh-crew bundle is running, jobs run inside it (sessions visible in the
3
- // Web UI); otherwise the MCP server falls back to standalone runtimes.
4
-
5
- import { readGlobalConfig } from './install/install.mjs';
6
- import { evaluateHubHandshake, HUB_COMPATIBILITY_CODES } from './runtime-identity.mjs';
7
- import { buildReadinessMatrix } from './readiness-matrix.mjs';
8
- import { isBoundedMachineCode } from './structured-error-code.mjs';
9
-
10
- const BASE = (process.env.DSH_CREW_HUB ?? readGlobalConfig().hub_url).replace(/\/$/, '');
11
- const API = `${BASE}/_dsh/dsh-crew`;
12
-
13
- export const HUB_REQUEST_FAILED = 'HUB_REQUEST_FAILED';
14
-
15
- const EMPTY_STATUS = Object.freeze({
16
- reachable: false,
17
- compatible: false,
18
- service: null,
19
- runtime_version: null,
20
- protocol_version: null,
21
- capabilities: [],
22
- missing_capabilities: [],
23
- code: HUB_COMPATIBILITY_CODES.UNREACHABLE,
24
- });
25
-
26
- let lastProbe = { at: 0, base: null, status: EMPTY_STATUS };
27
-
28
- function withReadiness(status) {
29
- return {
30
- ...status,
31
- readiness_matrix: buildReadinessMatrix({ hubCompatibility: status }),
32
- };
33
- }
34
-
35
- function cacheStatus(status, base) {
36
- const observed = withReadiness(status);
37
- lastProbe = { at: Date.now(), base, status: observed };
38
- return observed;
39
- }
40
-
41
- async function fetchJson(path, base = BASE) {
42
- const api = `${String(base).replace(/\/$/, '')}/_dsh/dsh-crew`;
43
- const res = await fetch(`${api}${path}`, { signal: AbortSignal.timeout(800) });
44
- let body;
45
- try { body = await res.json(); } catch { body = null; }
46
- return { res, body };
47
- }
48
-
49
- /**
50
- * Probe reachability and compatibility as separate contracts.
51
- *
52
- * /ping is intentionally legacy-compatible and proves only that a dsh-crew Hub
53
- * is alive. /runtime is the v0.3 compatibility handshake. A legacy Hub that
54
- * lacks /runtime is therefore reachable-but-incompatible instead of looking
55
- * offline or being silently treated as current.
56
- */
57
- export async function hubStatus({ force = false, base = BASE } = {}) {
58
- const normalizedBase = String(base).replace(/\/$/, '');
59
- if (!force && lastProbe.base === normalizedBase && Date.now() - lastProbe.at < 10_000) return lastProbe.status;
60
- try {
61
- const ping = await fetchJson('/ping', normalizedBase);
62
- if (!ping.res.ok) {
63
- return cacheStatus({
64
- ...EMPTY_STATUS,
65
- reachable: true,
66
- code: HUB_COMPATIBILITY_CODES.HTTP_ERROR,
67
- http_status: ping.res.status,
68
- endpoint: 'ping',
69
- }, normalizedBase);
70
- }
71
- if (ping.body?.service !== 'dsh-crew-hub') {
72
- return cacheStatus(evaluateHubHandshake(ping.body), normalizedBase);
73
- }
74
-
75
- const runtime = await fetchJson('/runtime', normalizedBase);
76
- if (runtime.res.status === 404) {
77
- return cacheStatus({
78
- ...EMPTY_STATUS,
79
- reachable: true,
80
- service: 'dsh-crew-hub',
81
- code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISSING,
82
- endpoint: 'runtime',
83
- }, normalizedBase);
84
- }
85
- if (!runtime.res.ok) {
86
- return cacheStatus({
87
- ...EMPTY_STATUS,
88
- reachable: true,
89
- service: 'dsh-crew-hub',
90
- code: HUB_COMPATIBILITY_CODES.HTTP_ERROR,
91
- http_status: runtime.res.status,
92
- endpoint: 'runtime',
93
- }, normalizedBase);
94
- }
95
- return cacheStatus(evaluateHubHandshake(runtime.body, { strictProduction: true }), normalizedBase);
96
- } catch {
97
- return cacheStatus(EMPTY_STATUS, normalizedBase);
98
- }
99
- }
100
-
101
- export async function hubAvailable() {
102
- return (await hubStatus()).compatible;
103
- }
104
-
105
- function structuredCode(body) {
106
- if (isBoundedMachineCode(body?.code)) return body.code;
107
- if (isBoundedMachineCode(body?.policyCode)) return body.policyCode;
108
- return null;
109
- }
110
-
111
- /** Build a bounded Hub request error without copying arbitrary response fields. */
112
- export function hubRequestError(body, status) {
113
- const err = new Error(body?.error ?? `hub request failed (${status})`);
114
- err.code = structuredCode(body) ?? HUB_REQUEST_FAILED;
115
- return err;
116
- }
117
-
118
- // Transport deadlines: every Hub call is bounded so a wedged local HTTP
119
- // exchange can never outlive the workflow timeout contract. Long polls get
120
- // their requested wait plus grace; spawn gets a wider bound because worktree
121
- // creation can clone sizeable repositories. The env override exists for
122
- // deterministic deadline tests; production defaults stay at 10s.
123
- const ENV_TIMEOUT_MS = Number(process.env.DSH_CREW_HUB_TIMEOUT_MS);
124
- const DEFAULT_TIMEOUT_MS = Number.isInteger(ENV_TIMEOUT_MS) && ENV_TIMEOUT_MS > 0 ? ENV_TIMEOUT_MS : 10_000;
125
- const SPAWN_TIMEOUT_MS = Math.max(DEFAULT_TIMEOUT_MS, 60_000);
126
- const LONG_POLL_GRACE_MS = 5_000;
127
-
128
- async function call(path, init, { timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
129
- let res;
130
- try {
131
- res = await fetch(`${API}${path}`, { ...init, signal: AbortSignal.timeout(timeoutMs) });
132
- } catch (err) {
133
- if (err?.name === 'TimeoutError' || err?.name === 'AbortError') {
134
- throw hubRequestError({ error: `hub request timed out after ${timeoutMs}ms` }, 0);
135
- }
136
- throw err;
137
- }
138
- const body = await res.json();
139
- if (!res.ok || body.ok === false) throw hubRequestError(body, res.status);
140
- return body;
141
- }
142
-
143
- export const hub = {
144
- spawn: (spec) => call('/jobs', {
145
- method: 'POST',
146
- headers: { 'content-type': 'application/json' },
147
- body: JSON.stringify(spec),
148
- }, { timeoutMs: SPAWN_TIMEOUT_MS }).then((b) => b.job),
149
- list: () => call('/jobs').then((b) => b.jobs),
150
- get: (id, waitSeconds = 0) => call(`/jobs/${id}?wait=${waitSeconds}`, undefined, {
151
- timeoutMs: waitSeconds > 0 ? (waitSeconds * 1000) + LONG_POLL_GRACE_MS : DEFAULT_TIMEOUT_MS,
152
- }).then((b) => b.job),
153
- cancel: (id) => call(`/jobs/${id}/cancel`, { method: 'POST' }).then((b) => b.job),
154
- };
1
+ // Client for the in-host workers-hub jobs API. When a DSH web instance with the
2
+ // dsh-crew bundle is running, jobs run inside it (sessions visible in the
3
+ // Web UI); otherwise the MCP server falls back to standalone runtimes.
4
+
5
+ import { readGlobalConfig } from './install/install.mjs';
6
+ import { evaluateHubHandshake, HUB_COMPATIBILITY_CODES } from './runtime-identity.mjs';
7
+ import { buildReadinessMatrix } from './readiness-matrix.mjs';
8
+ import { isBoundedMachineCode } from './structured-error-code.mjs';
9
+
10
+ const BASE = (process.env.DSH_CREW_HUB ?? readGlobalConfig().hub_url).replace(/\/$/, '');
11
+ const API = `${BASE}/_dsh/dsh-crew`;
12
+
13
+ export const HUB_REQUEST_FAILED = 'HUB_REQUEST_FAILED';
14
+
15
+ const EMPTY_STATUS = Object.freeze({
16
+ reachable: false,
17
+ compatible: false,
18
+ service: null,
19
+ runtime_version: null,
20
+ protocol_version: null,
21
+ capabilities: [],
22
+ missing_capabilities: [],
23
+ code: HUB_COMPATIBILITY_CODES.UNREACHABLE,
24
+ });
25
+
26
+ let lastProbe = { at: 0, base: null, status: EMPTY_STATUS };
27
+
28
+ function withReadiness(status) {
29
+ return {
30
+ ...status,
31
+ readiness_matrix: buildReadinessMatrix({ hubCompatibility: status }),
32
+ };
33
+ }
34
+
35
+ function cacheStatus(status, base) {
36
+ const observed = withReadiness(status);
37
+ lastProbe = { at: Date.now(), base, status: observed };
38
+ return observed;
39
+ }
40
+
41
+ async function fetchJson(path, base = BASE) {
42
+ const api = `${String(base).replace(/\/$/, '')}/_dsh/dsh-crew`;
43
+ const res = await fetch(`${api}${path}`, { signal: AbortSignal.timeout(800) });
44
+ let body;
45
+ try { body = await res.json(); } catch { body = null; }
46
+ return { res, body };
47
+ }
48
+
49
+ /**
50
+ * Probe reachability and compatibility as separate contracts.
51
+ *
52
+ * /ping is intentionally legacy-compatible and proves only that a dsh-crew Hub
53
+ * is alive. /runtime is the v0.3 compatibility handshake. A legacy Hub that
54
+ * lacks /runtime is therefore reachable-but-incompatible instead of looking
55
+ * offline or being silently treated as current.
56
+ */
57
+ export async function hubStatus({ force = false, base = BASE } = {}) {
58
+ const normalizedBase = String(base).replace(/\/$/, '');
59
+ if (!force && lastProbe.base === normalizedBase && Date.now() - lastProbe.at < 10_000) return lastProbe.status;
60
+ try {
61
+ const ping = await fetchJson('/ping', normalizedBase);
62
+ if (!ping.res.ok) {
63
+ return cacheStatus({
64
+ ...EMPTY_STATUS,
65
+ reachable: true,
66
+ code: HUB_COMPATIBILITY_CODES.HTTP_ERROR,
67
+ http_status: ping.res.status,
68
+ endpoint: 'ping',
69
+ }, normalizedBase);
70
+ }
71
+ if (ping.body?.service !== 'dsh-crew-hub') {
72
+ return cacheStatus(evaluateHubHandshake(ping.body), normalizedBase);
73
+ }
74
+
75
+ const runtime = await fetchJson('/runtime', normalizedBase);
76
+ if (runtime.res.status === 404) {
77
+ return cacheStatus({
78
+ ...EMPTY_STATUS,
79
+ reachable: true,
80
+ service: 'dsh-crew-hub',
81
+ code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISSING,
82
+ endpoint: 'runtime',
83
+ }, normalizedBase);
84
+ }
85
+ if (!runtime.res.ok) {
86
+ return cacheStatus({
87
+ ...EMPTY_STATUS,
88
+ reachable: true,
89
+ service: 'dsh-crew-hub',
90
+ code: HUB_COMPATIBILITY_CODES.HTTP_ERROR,
91
+ http_status: runtime.res.status,
92
+ endpoint: 'runtime',
93
+ }, normalizedBase);
94
+ }
95
+ return cacheStatus(evaluateHubHandshake(runtime.body, { strictProduction: true }), normalizedBase);
96
+ } catch {
97
+ return cacheStatus(EMPTY_STATUS, normalizedBase);
98
+ }
99
+ }
100
+
101
+ export async function hubAvailable() {
102
+ return (await hubStatus()).compatible;
103
+ }
104
+
105
+ function structuredCode(body) {
106
+ if (isBoundedMachineCode(body?.code)) return body.code;
107
+ if (isBoundedMachineCode(body?.policyCode)) return body.policyCode;
108
+ return null;
109
+ }
110
+
111
+ /** Build a bounded Hub request error without copying arbitrary response fields. */
112
+ export function hubRequestError(body, status) {
113
+ const err = new Error(body?.error ?? `hub request failed (${status})`);
114
+ err.code = structuredCode(body) ?? HUB_REQUEST_FAILED;
115
+ return err;
116
+ }
117
+
118
+ // Transport deadlines: every Hub call is bounded so a wedged local HTTP
119
+ // exchange can never outlive the workflow timeout contract. Long polls get
120
+ // their requested wait plus grace; spawn gets a wider bound because worktree
121
+ // creation can clone sizeable repositories. The env override exists for
122
+ // deterministic deadline tests; production defaults stay at 10s.
123
+ const ENV_TIMEOUT_MS = Number(process.env.DSH_CREW_HUB_TIMEOUT_MS);
124
+ const DEFAULT_TIMEOUT_MS = Number.isInteger(ENV_TIMEOUT_MS) && ENV_TIMEOUT_MS > 0 ? ENV_TIMEOUT_MS : 10_000;
125
+ const SPAWN_TIMEOUT_MS = Math.max(DEFAULT_TIMEOUT_MS, 60_000);
126
+ const LONG_POLL_GRACE_MS = 5_000;
127
+
128
+ async function call(path, init, { timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
129
+ let res;
130
+ try {
131
+ res = await fetch(`${API}${path}`, { ...init, signal: AbortSignal.timeout(timeoutMs) });
132
+ } catch (err) {
133
+ if (err?.name === 'TimeoutError' || err?.name === 'AbortError') {
134
+ throw hubRequestError({ error: `hub request timed out after ${timeoutMs}ms` }, 0);
135
+ }
136
+ throw err;
137
+ }
138
+ const body = await res.json();
139
+ if (!res.ok || body.ok === false) throw hubRequestError(body, res.status);
140
+ return body;
141
+ }
142
+
143
+ export const hub = {
144
+ spawn: (spec) => call('/jobs', {
145
+ method: 'POST',
146
+ headers: { 'content-type': 'application/json' },
147
+ body: JSON.stringify(spec),
148
+ }, { timeoutMs: SPAWN_TIMEOUT_MS }).then((b) => b.job),
149
+ list: () => call('/jobs').then((b) => b.jobs),
150
+ get: (id, waitSeconds = 0) => call(`/jobs/${id}?wait=${waitSeconds}`, undefined, {
151
+ timeoutMs: waitSeconds > 0 ? (waitSeconds * 1000) + LONG_POLL_GRACE_MS : DEFAULT_TIMEOUT_MS,
152
+ }).then((b) => b.job),
153
+ cancel: (id) => call(`/jobs/${id}/cancel`, { method: 'POST' }).then((b) => b.job),
154
+ };
@@ -1,18 +1,18 @@
1
- // Pure execution-mode decision for the Hub compatibility contract.
2
- // Transport probing lives in hub-client.mjs; this module only decides whether
3
- // a session may use Hub, intentionally fall back, or must fail closed.
4
-
5
- import { HUB_COMPATIBILITY_CODES } from './runtime-identity.mjs';
6
-
7
- export function hubCompatibilityMessage(status = {}) {
8
- const code = status.code ?? 'HUB_INCOMPATIBLE';
9
- if (!status.reachable) return `DSH workers hub is not reachable (${code}).`;
10
- const detail = status.missing_capabilities?.length
11
- ? `; missing capabilities: ${status.missing_capabilities.join(', ')}`
12
- : '';
13
- return `DSH workers hub is reachable but incompatible (${code}${detail}). Update/restart the Hub plugin before using Hub execution.`;
14
- }
15
-
1
+ // Pure execution-mode decision for the Hub compatibility contract.
2
+ // Transport probing lives in hub-client.mjs; this module only decides whether
3
+ // a session may use Hub, intentionally fall back, or must fail closed.
4
+
5
+ import { HUB_COMPATIBILITY_CODES } from './runtime-identity.mjs';
6
+
7
+ export function hubCompatibilityMessage(status = {}) {
8
+ const code = status.code ?? 'HUB_INCOMPATIBLE';
9
+ if (!status.reachable) return `DSH workers hub is not reachable (${code}).`;
10
+ const detail = status.missing_capabilities?.length
11
+ ? `; missing capabilities: ${status.missing_capabilities.join(', ')}`
12
+ : '';
13
+ return `DSH workers hub is reachable but incompatible (${code}${detail}). Update/restart the Hub plugin before using Hub execution.`;
14
+ }
15
+
16
16
  export function resolveHubExecutionMode(requestedMode = 'auto', status = {}, { productionOnly = false } = {}) {
17
17
  if (requestedMode === 'standalone') {
18
18
  if (productionOnly) {
@@ -23,28 +23,28 @@ export function resolveHubExecutionMode(requestedMode = 'auto', status = {}, { p
23
23
  };
24
24
  }
25
25
  return { ok: true, mode: 'standalone', reason: 'explicit-standalone' };
26
- }
27
-
28
- if (status.compatible === true) {
29
- return { ok: true, mode: 'hub', reason: 'compatible-hub' };
30
- }
31
-
32
- if (status.reachable === true) {
33
- return {
34
- ok: false,
35
- code: status.code ?? 'HUB_INCOMPATIBLE',
36
- error: hubCompatibilityMessage(status),
37
- hub: status,
38
- };
39
- }
40
-
26
+ }
27
+
28
+ if (status.compatible === true) {
29
+ return { ok: true, mode: 'hub', reason: 'compatible-hub' };
30
+ }
31
+
32
+ if (status.reachable === true) {
33
+ return {
34
+ ok: false,
35
+ code: status.code ?? 'HUB_INCOMPATIBLE',
36
+ error: hubCompatibilityMessage(status),
37
+ hub: status,
38
+ };
39
+ }
40
+
41
41
  if (requestedMode === 'hub') {
42
- return {
43
- ok: false,
44
- code: status.code ?? HUB_COMPATIBILITY_CODES.UNREACHABLE,
45
- error: 'Session mode is "hub" but the DSH workers hub is not reachable.',
46
- hub: status,
47
- };
42
+ return {
43
+ ok: false,
44
+ code: status.code ?? HUB_COMPATIBILITY_CODES.UNREACHABLE,
45
+ error: 'Session mode is "hub" but the DSH workers hub is not reachable.',
46
+ hub: status,
47
+ };
48
48
  }
49
49
 
50
50
  if (productionOnly) {
@@ -57,9 +57,9 @@ export function resolveHubExecutionMode(requestedMode = 'auto', status = {}, { p
57
57
  }
58
58
 
59
59
  return {
60
- ok: true,
61
- mode: 'standalone',
62
- reason: 'hub-unreachable-fallback',
63
- hub: status,
64
- };
65
- }
60
+ ok: true,
61
+ mode: 'standalone',
62
+ reason: 'hub-unreachable-fallback',
63
+ hub: status,
64
+ };
65
+ }
package/src/i18n.mjs CHANGED
@@ -1,19 +1,19 @@
1
- // Server-side locale for strings that reach the user: connectivity-test
2
- // reports, model-list labels and error messages.
3
- //
4
- // The panel owns the authoritative locale (DSH's setting may be absent, in
5
- // which case the browser decides), so it passes `lang` with every request and
6
- // the hub calls setLang(). The host's durable setting seeds the initial value
7
- // for paths with no request behind them, such as the pasted-image pre-step.
8
-
9
- let LANG = 'en';
10
-
11
- export function setLang(lang) {
12
- if (lang === 'zh' || lang === 'en') LANG = lang;
13
- return LANG;
14
- }
15
-
16
- export function getLang() { return LANG; }
17
-
18
- /** Pick the string for the active locale. Both branches are cheap literals. */
19
- export function tr(zh, en) { return LANG === 'zh' ? zh : en; }
1
+ // Server-side locale for strings that reach the user: connectivity-test
2
+ // reports, model-list labels and error messages.
3
+ //
4
+ // The panel owns the authoritative locale (DSH's setting may be absent, in
5
+ // which case the browser decides), so it passes `lang` with every request and
6
+ // the hub calls setLang(). The host's durable setting seeds the initial value
7
+ // for paths with no request behind them, such as the pasted-image pre-step.
8
+
9
+ let LANG = 'en';
10
+
11
+ export function setLang(lang) {
12
+ if (lang === 'zh' || lang === 'en') LANG = lang;
13
+ return LANG;
14
+ }
15
+
16
+ export function getLang() { return LANG; }
17
+
18
+ /** Pick the string for the active locale. Both branches are cheap literals. */
19
+ export function tr(zh, en) { return LANG === 'zh' ? zh : en; }
@@ -1,67 +1,67 @@
1
- // Bounded context builders for agent-to-agent hand-offs.
2
- //
3
- // Workers still receive the user's complete delegated task. Once a worker has
4
- // run, downstream agents receive only an objective plus structured evidence
5
- // and artifact references. They inspect the isolated workspace directly when
6
- // more detail is required; raw prose and whole patches are never re-embedded.
7
-
8
- function clip(value, limit) {
9
- const text = String(value ?? '').trim();
10
- if (text.length <= limit) return text;
11
- return `${text.slice(0, limit)}\n[truncated: ${text.length - limit} characters omitted]`;
12
- }
13
-
14
- function list(values, { count = 40, itemLimit = 300 } = {}) {
15
- if (!Array.isArray(values) || values.length === 0) return ['(none)'];
16
- const selected = values.slice(0, count).map((value) => `- ${clip(value, itemLimit)}`);
17
- if (values.length > count) selected.push(`- [truncated: ${values.length - count} additional items omitted]`);
18
- return selected;
19
- }
20
-
21
- function tests(values) {
22
- if (!Array.isArray(values) || values.length === 0) return ['(none reported)'];
23
- return list(values.map((entry) => [entry?.status, entry?.command, entry?.summary].filter(Boolean).join(' — ')), {
24
- count: 30,
25
- itemLimit: 500,
26
- });
27
- }
28
-
29
- /** Build the automatic-review context capsule. */
30
- export function buildReviewTask(task, view = {}, { strictness = 'standard' } = {}) {
31
- const outcome = view?.outcome ?? {};
32
- const candidate = view?.candidate ?? {};
33
- const changedFiles = Array.isArray(candidate.changed_files) ? candidate.changed_files : [];
34
- const parts = [
35
- 'You are the automatic reviewer of a completed worker implementation.',
36
- 'REVIEW ONLY: inspect the candidate and report findings. Do not modify files.',
37
- ...(strictness === 'strict' ? [
38
- 'STRICT REVIEW: fail closed. Approve only when direct code and test evidence supports every material claim; treat missing evidence as needs changes.',
39
- ] : []),
40
- '',
41
- 'Objective:',
42
- clip(task, 4000),
43
- '',
44
- 'Worker outcome:',
45
- `task_status=${outcome.task_status ?? 'unknown'} tests_status=${outcome.tests_status ?? 'unknown'} delivery=${outcome.delivery?.complete ? 'complete' : 'incomplete'}`,
46
- '',
47
- 'Reported changes:',
48
- ...list(outcome.changes),
49
- '',
50
- 'Reported tests:',
51
- ...tests(outcome.tests),
52
- '',
53
- 'Reported risks:',
54
- ...list(outcome.risks),
55
- '',
56
- 'Candidate artifact:',
57
- `base_revision=${candidate.base_revision ?? 'unknown'}`,
58
- `fingerprint=${candidate.fingerprint ?? 'unknown'}`,
59
- 'changed_files:',
60
- ...list(changedFiles, { count: 80, itemLimit: 500 }),
61
- '',
62
- 'Inspect the candidate directly in the current isolated workspace. Use git diff against the base revision and open only the files needed for review. The worker\'s raw prose and full patch are intentionally not embedded in this hand-off.',
63
- '',
64
- 'Report: 1) whether the implementation satisfies the objective, 2) concrete bugs/style/security risks, 3) suggested fixes. End with ## Review Findings / ## Evidence / ## Risks / ## Verdict (approved | needs changes | rejected).',
65
- ];
66
- return parts.join('\n');
67
- }
1
+ // Bounded context builders for agent-to-agent hand-offs.
2
+ //
3
+ // Workers still receive the user's complete delegated task. Once a worker has
4
+ // run, downstream agents receive only an objective plus structured evidence
5
+ // and artifact references. They inspect the isolated workspace directly when
6
+ // more detail is required; raw prose and whole patches are never re-embedded.
7
+
8
+ function clip(value, limit) {
9
+ const text = String(value ?? '').trim();
10
+ if (text.length <= limit) return text;
11
+ return `${text.slice(0, limit)}\n[truncated: ${text.length - limit} characters omitted]`;
12
+ }
13
+
14
+ function list(values, { count = 40, itemLimit = 300 } = {}) {
15
+ if (!Array.isArray(values) || values.length === 0) return ['(none)'];
16
+ const selected = values.slice(0, count).map((value) => `- ${clip(value, itemLimit)}`);
17
+ if (values.length > count) selected.push(`- [truncated: ${values.length - count} additional items omitted]`);
18
+ return selected;
19
+ }
20
+
21
+ function tests(values) {
22
+ if (!Array.isArray(values) || values.length === 0) return ['(none reported)'];
23
+ return list(values.map((entry) => [entry?.status, entry?.command, entry?.summary].filter(Boolean).join(' — ')), {
24
+ count: 30,
25
+ itemLimit: 500,
26
+ });
27
+ }
28
+
29
+ /** Build the automatic-review context capsule. */
30
+ export function buildReviewTask(task, view = {}, { strictness = 'standard' } = {}) {
31
+ const outcome = view?.outcome ?? {};
32
+ const candidate = view?.candidate ?? {};
33
+ const changedFiles = Array.isArray(candidate.changed_files) ? candidate.changed_files : [];
34
+ const parts = [
35
+ 'You are the automatic reviewer of a completed worker implementation.',
36
+ 'REVIEW ONLY: inspect the candidate and report findings. Do not modify files.',
37
+ ...(strictness === 'strict' ? [
38
+ 'STRICT REVIEW: fail closed. Approve only when direct code and test evidence supports every material claim; treat missing evidence as needs changes.',
39
+ ] : []),
40
+ '',
41
+ 'Objective:',
42
+ clip(task, 4000),
43
+ '',
44
+ 'Worker outcome:',
45
+ `task_status=${outcome.task_status ?? 'unknown'} tests_status=${outcome.tests_status ?? 'unknown'} delivery=${outcome.delivery?.complete ? 'complete' : 'incomplete'}`,
46
+ '',
47
+ 'Reported changes:',
48
+ ...list(outcome.changes),
49
+ '',
50
+ 'Reported tests:',
51
+ ...tests(outcome.tests),
52
+ '',
53
+ 'Reported risks:',
54
+ ...list(outcome.risks),
55
+ '',
56
+ 'Candidate artifact:',
57
+ `base_revision=${candidate.base_revision ?? 'unknown'}`,
58
+ `fingerprint=${candidate.fingerprint ?? 'unknown'}`,
59
+ 'changed_files:',
60
+ ...list(changedFiles, { count: 80, itemLimit: 500 }),
61
+ '',
62
+ 'Inspect the candidate directly in the current isolated workspace. Use git diff against the base revision and open only the files needed for review. The worker\'s raw prose and full patch are intentionally not embedded in this hand-off.',
63
+ '',
64
+ 'Report: 1) whether the implementation satisfies the objective, 2) concrete bugs/style/security risks, 3) suggested fixes. End with ## Review Findings / ## Evidence / ## Risks / ## Verdict (approved | needs changes | rejected).',
65
+ ];
66
+ return parts.join('\n');
67
+ }
@@ -1,28 +1,28 @@
1
- #!/usr/bin/env node
2
- // Usage: node src/install/cli.mjs <claude|codex|all|hud|uninstall-claude|uninstall-codex|uninstall-all> [--statusline] [--project]
3
-
4
- import { installClaudeCode, installCodex, uninstallClaudeCode, uninstallCodex, installHudSegment } from './install.mjs';
5
-
6
- const cmd = process.argv[2];
7
- const flags = new Set(process.argv.slice(3));
8
- const opts = { statusline: flags.has('--statusline'), scope: flags.has('--project') ? 'project' : 'user' };
9
-
10
- const run = {
11
- claude: () => [installClaudeCode(opts)],
12
- codex: () => [installCodex(opts)],
13
- all: () => [installClaudeCode(opts), installHudSegment(opts), installCodex(opts)],
14
- 'uninstall-claude': () => [uninstallClaudeCode(opts)],
15
- 'uninstall-codex': () => [uninstallCodex(opts)],
16
- 'uninstall-all': () => [uninstallClaudeCode(opts), uninstallCodex(opts)],
17
- hud: () => [installHudSegment(opts)],
18
- }[cmd];
19
-
20
- if (!run) {
21
- console.error('usage: cli.mjs <claude|codex|all|hud|uninstall-claude|uninstall-codex|uninstall-all> [--statusline] [--project]');
22
- process.exit(1);
23
- }
24
- for (const p of run()) {
25
- const r = await p;
26
- for (const a of r.actions) console.log('•', a);
27
- }
28
- console.log('done.');
1
+ #!/usr/bin/env node
2
+ // Usage: node src/install/cli.mjs <claude|codex|all|hud|uninstall-claude|uninstall-codex|uninstall-all> [--statusline] [--project]
3
+
4
+ import { installClaudeCode, installCodex, uninstallClaudeCode, uninstallCodex, installHudSegment } from './install.mjs';
5
+
6
+ const cmd = process.argv[2];
7
+ const flags = new Set(process.argv.slice(3));
8
+ const opts = { statusline: flags.has('--statusline'), scope: flags.has('--project') ? 'project' : 'user' };
9
+
10
+ const run = {
11
+ claude: () => [installClaudeCode(opts)],
12
+ codex: () => [installCodex(opts)],
13
+ all: () => [installClaudeCode(opts), installHudSegment(opts), installCodex(opts)],
14
+ 'uninstall-claude': () => [uninstallClaudeCode(opts)],
15
+ 'uninstall-codex': () => [uninstallCodex(opts)],
16
+ 'uninstall-all': () => [uninstallClaudeCode(opts), uninstallCodex(opts)],
17
+ hud: () => [installHudSegment(opts)],
18
+ }[cmd];
19
+
20
+ if (!run) {
21
+ console.error('usage: cli.mjs <claude|codex|all|hud|uninstall-claude|uninstall-codex|uninstall-all> [--statusline] [--project]');
22
+ process.exit(1);
23
+ }
24
+ for (const p of run()) {
25
+ const r = await p;
26
+ for (const a of r.actions) console.log('•', a);
27
+ }
28
+ console.log('done.');