@ran-sh/dsh-crew 1.9.0 → 1.10.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 +16 -16
- package/.claude-plugin/plugin.json +14 -14
- package/LICENSE +21 -21
- package/README.de.md +359 -359
- package/README.es.md +359 -359
- package/README.fr.md +359 -359
- package/README.hi.md +359 -359
- package/README.id.md +359 -359
- package/README.ja.md +359 -359
- package/README.ko.md +359 -359
- package/README.md +126 -126
- package/README.pt.md +359 -359
- package/README.ru.md +359 -359
- package/README.th.md +359 -359
- package/README.tr.md +359 -359
- package/README.vi.md +359 -359
- package/README.zh-TW.md +359 -359
- package/README.zh.md +116 -116
- package/agents/ds-flash.md +24 -24
- package/agents/ds-pro.md +24 -24
- package/agents/ds-reviewer.md +23 -23
- package/agents/ds-worker.md +23 -23
- package/bin/dsh-crew.mjs +16 -16
- package/codex/agents/ds-flash.toml +34 -34
- package/codex/agents/ds-pro.toml +34 -34
- package/codex/agents/ds-reviewer.toml +32 -32
- package/codex/agents/ds-worker.toml +32 -32
- package/codex/prompts/dsh-config.md +19 -19
- package/codex/prompts/dsh-status.md +5 -5
- package/commands/config.md +23 -23
- package/commands/off.md +5 -5
- package/commands/on.md +5 -5
- package/commands/status.md +9 -9
- package/cordis.patch.yml +4 -4
- package/docs/gpt-relay-extension.md +103 -103
- package/docs/installation.md +138 -138
- package/docs/job-contracts.md +103 -103
- package/docs/readiness-matrix.md +85 -85
- package/docs/ui-surfaces.md +107 -107
- package/official-web-bridge/cordis.patch.yml +4 -4
- package/official-web-bridge/entry.mjs +1 -1
- package/official-web-bridge/overlay-entry.mjs +59 -59
- package/official-web-bridge/package.json +25 -25
- package/package.json +3 -2
- package/scripts/build-client.mjs +49 -49
- package/scripts/live-crew-smoke.mjs +39 -39
- package/scripts/live-policy-matrix.mjs +177 -177
- package/scripts/policy-probe.mjs +101 -101
- package/scripts/remove-legacy-official-bridge.ps1 +89 -89
- package/scripts/setup.mjs +393 -393
- package/scripts/smoke-real.mjs +110 -110
- package/scripts/smoke.mjs +78 -78
- package/scripts/verify-crew-ui-polish.mjs +145 -145
- package/scripts/verify-history-ui.mjs +97 -97
- package/scripts/verify-installer-fix.mjs +26 -26
- package/scripts/verify-npm-install.mjs +311 -311
- package/scripts/verify-official-bridge-e2e.mjs +192 -192
- package/src/adaptive-routing.mjs +260 -260
- package/src/client/activation-summary.tsx +64 -64
- package/src/client/collapsible-sections.mjs +55 -55
- package/src/client/history-panel.tsx +108 -108
- package/src/client/host-readiness.mjs +71 -71
- package/src/client/index.tsx +1711 -1711
- package/src/client/model-callability-view.mjs +17 -17
- package/src/client/panel-chrome.tsx +40 -40
- package/src/client/quick-entry.tsx +10 -10
- package/src/client/quick-panel.tsx +275 -275
- package/src/client/readiness-envelope.mjs +34 -34
- package/src/client/surface-detection.mjs +43 -43
- package/src/config-readiness.mjs +226 -226
- package/src/credential-reference.mjs +38 -38
- package/src/delivery.mjs +205 -205
- package/src/dsh-cli-runtime.mjs +1021 -1021
- package/src/dsh-cohort.mjs +20 -20
- package/src/extension-contract.mjs +104 -104
- package/src/failure-classification.mjs +201 -201
- package/src/history/admission-gate.mjs +67 -67
- package/src/history/archive-store.mjs +272 -272
- package/src/history/cleanup-plan.mjs +89 -89
- package/src/history/http.mjs +32 -32
- package/src/history/operation.mjs +86 -86
- package/src/history/runner-detach.mjs +34 -34
- package/src/history/runner.mjs +52 -52
- package/src/history/runtime.mjs +36 -36
- package/src/history/service.mjs +177 -177
- package/src/history/state.mjs +27 -27
- package/src/hub/entry.mjs +104 -104
- package/src/hub/index.mjs +2694 -2694
- package/src/hub-client.mjs +154 -154
- package/src/hub-compatibility.mjs +42 -42
- package/src/i18n.mjs +19 -19
- package/src/information-flow.mjs +67 -67
- package/src/install/cli.mjs +28 -28
- package/src/install/install-legacy.mjs +711 -711
- package/src/install/install.mjs +483 -483
- package/src/install/npx-lifecycle.mjs +3456 -3456
- package/src/install/official-frontend-assets.mjs +78 -78
- package/src/install/official-web.mjs +95 -95
- package/src/install/payload-content.mjs +88 -88
- package/src/install/windows-startup.mjs +236 -236
- package/src/install/windows-supervisor-adapter.mjs +443 -443
- package/src/install/windows-supervisor-lifecycle.mjs +782 -782
- package/src/install/zcode.mjs +397 -397
- package/src/job-contracts.mjs +255 -255
- package/src/local-request-guard.mjs +60 -60
- package/src/mcp-runtime.mjs +340 -340
- package/src/model-callability-contract.mjs +79 -79
- package/src/model-catalog.mjs +180 -180
- package/src/model-routing.mjs +586 -586
- package/src/model-schedule.mjs +207 -207
- package/src/official-web-bridge.mjs +447 -447
- package/src/policy.mjs +235 -235
- package/src/provider-delete-adapters.mjs +1934 -1934
- package/src/provider-health.mjs +130 -130
- package/src/provider-inventory.mjs +182 -182
- package/src/provider-layer-migration-adapters.mjs +759 -759
- package/src/provider-layer-migration.mjs +198 -198
- package/src/provider-lifecycle-state.mjs +103 -103
- package/src/provider-lifecycle.mjs +252 -252
- package/src/provider-profile-store.mjs +390 -390
- package/src/provider-settings-store.mjs +633 -633
- package/src/provider-store-lock.mjs +67 -67
- package/src/readiness-matrix.mjs +181 -181
- package/src/removable-waiter.mjs +29 -29
- package/src/role-profiles.mjs +107 -107
- package/src/runtime-controls.mjs +84 -84
- package/src/runtime-identity-contract.mjs +34 -34
- package/src/runtime-identity.mjs +235 -235
- package/src/runtime-readiness-snapshot.mjs +285 -285
- package/src/server.mjs +581 -581
- package/src/session-origins.mjs +60 -60
- package/src/standalone-sdk.mjs +23 -23
- package/src/status-shard.mjs +63 -63
- package/src/structured-error-code.mjs +38 -38
- package/src/supervisor/restart-request.mjs +256 -256
- package/src/workflow-runtime.mjs +739 -739
- package/src/workflow.mjs +155 -155
- package/src/workspace-audit.mjs +231 -231
- package/src/workspace-context.mjs +146 -146
- package/src/workspace-isolation.mjs +463 -455
- package/src/workspace-readiness.mjs +32 -32
- package/statusline/statusline.sh +14 -14
- package/statusline/worker-segment.sh +35 -35
- package/windows/start-dsh-crew.cmd +57 -57
- package/windows/start-dsh-crew.ps1 +1302 -1302
- package/windows/supervisor-control.ps1 +467 -467
- package/worker.cordis.yml +67 -67
- package/zcode/agents/ds-reviewer.md +31 -31
- package/zcode/agents/ds-worker.md +31 -31
- package/zcode/commands/dsh-config.md +17 -17
- package/zcode/commands/dsh-status.md +5 -5
package/src/runtime-identity.mjs
CHANGED
|
@@ -1,235 +1,235 @@
|
|
|
1
|
-
// Shared runtime identity and Hub compatibility contract.
|
|
2
|
-
//
|
|
3
|
-
// Package/release semver and the wire protocol are intentionally separate:
|
|
4
|
-
// - RUNTIME_VERSION identifies the source/runtime generation for diagnostics.
|
|
5
|
-
// - HUB_PROTOCOL_VERSION changes only when Hub <-> MCP wire semantics become
|
|
6
|
-
// incompatible.
|
|
7
|
-
//
|
|
8
|
-
// The Harness/DSH cohort version (e.g. 0.1.5-rc.2) is a THIRD, independent
|
|
9
|
-
// domain: it identifies the installed @deepseek-ai/dsh package generation,
|
|
10
|
-
// never the Crew release. Verifiers must compare the cohort against
|
|
11
|
-
// dsh_version, never against runtime_version.
|
|
12
|
-
//
|
|
13
|
-
// Keep this module dependency-light so Hub, MCP and tests all use the exact
|
|
14
|
-
// same compatibility rules.
|
|
15
|
-
|
|
16
|
-
import { randomUUID } from 'node:crypto';
|
|
17
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
18
|
-
import { homedir } from 'node:os';
|
|
19
|
-
import { dirname, extname, join, resolve } from 'node:path';
|
|
20
|
-
import {
|
|
21
|
-
PRODUCTION_EXECUTION_PLANE,
|
|
22
|
-
PRODUCTION_PROFILE,
|
|
23
|
-
PRODUCTION_LISTEN_PORT,
|
|
24
|
-
} from './runtime-identity-contract.mjs';
|
|
25
|
-
export {
|
|
26
|
-
PRODUCTION_EXECUTION_PLANE,
|
|
27
|
-
PRODUCTION_PROFILE,
|
|
28
|
-
PRODUCTION_LISTEN_PORT,
|
|
29
|
-
isCompleteRuntimeIdentity,
|
|
30
|
-
sameCompleteRuntimeIdentity,
|
|
31
|
-
isExactNativeCrewIdentity,
|
|
32
|
-
} from './runtime-identity-contract.mjs';
|
|
33
|
-
|
|
34
|
-
// Production Crew execution is intentionally bound to the isolated 3210 Hub.
|
|
35
|
-
// These fields are public provenance only; no credential or session secret is
|
|
36
|
-
// included in the identity contract.
|
|
37
|
-
const RUNTIME_ID = randomUUID();
|
|
38
|
-
|
|
39
|
-
export const RUNTIME_VERSION = '1.
|
|
40
|
-
export const HUB_PROTOCOL_VERSION = 1;
|
|
41
|
-
|
|
42
|
-
export const HUB_CAPABILITIES = Object.freeze([
|
|
43
|
-
'jobs',
|
|
44
|
-
'jobs-wait',
|
|
45
|
-
'jobs-cancel',
|
|
46
|
-
'roles',
|
|
47
|
-
'attempt-index',
|
|
48
|
-
'model-policy',
|
|
49
|
-
'model-catalog',
|
|
50
|
-
'presets',
|
|
51
|
-
'config',
|
|
52
|
-
'canonical-events',
|
|
53
|
-
'evidence',
|
|
54
|
-
'profiles',
|
|
55
|
-
'workspace-context',
|
|
56
|
-
'extension-contract',
|
|
57
|
-
'provider-inventory',
|
|
58
|
-
'provider-layer-migration-v1',
|
|
59
|
-
'provider-lifecycle-v1',
|
|
60
|
-
'provider-health-v1',
|
|
61
|
-
'provider-probe-stream-v1',
|
|
62
|
-
'credential-reference-inventory-v1',
|
|
63
|
-
'credential-purge-v1',
|
|
64
|
-
'runtime-provenance-v1',
|
|
65
|
-
]);
|
|
66
|
-
|
|
67
|
-
// Capabilities the current MCP workflow depends on for full Hub execution.
|
|
68
|
-
// Additional capabilities may be advertised without breaking compatibility.
|
|
69
|
-
export const REQUIRED_HUB_CAPABILITIES = Object.freeze([
|
|
70
|
-
'jobs',
|
|
71
|
-
'jobs-wait',
|
|
72
|
-
'jobs-cancel',
|
|
73
|
-
'roles',
|
|
74
|
-
'attempt-index',
|
|
75
|
-
'model-policy',
|
|
76
|
-
]);
|
|
77
|
-
|
|
78
|
-
export const HUB_COMPATIBILITY_CODES = Object.freeze({
|
|
79
|
-
UNREACHABLE: 'HUB_UNREACHABLE',
|
|
80
|
-
HTTP_ERROR: 'HUB_HTTP_ERROR',
|
|
81
|
-
SERVICE_MISMATCH: 'HUB_SERVICE_MISMATCH',
|
|
82
|
-
PROTOCOL_MISSING: 'HUB_PROTOCOL_MISSING',
|
|
83
|
-
PROTOCOL_MISMATCH: 'HUB_PROTOCOL_MISMATCH',
|
|
84
|
-
CAPABILITY_MISSING: 'HUB_CAPABILITY_MISSING',
|
|
85
|
-
PROVENANCE_MISSING: 'HUB_PROVENANCE_MISSING',
|
|
86
|
-
EXECUTION_PLANE_MISMATCH: 'HUB_EXECUTION_PLANE_MISMATCH',
|
|
87
|
-
LISTEN_PORT_MISMATCH: 'HUB_LISTEN_PORT_MISMATCH',
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
function normalizedCapabilities(value) {
|
|
91
|
-
if (!Array.isArray(value)) return [];
|
|
92
|
-
return [...new Set(value.filter((item) => typeof item === 'string' && item.trim()).map((item) => item.trim()))];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function readVersionManifest(file) {
|
|
96
|
-
try {
|
|
97
|
-
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
98
|
-
if (parsed?.name !== '@deepseek-ai/dsh') return null;
|
|
99
|
-
return typeof parsed.version === 'string' && parsed.version.trim() ? parsed.version.trim() : null;
|
|
100
|
-
} catch { return null; }
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Resolve the @deepseek-ai/dsh manifest belonging to an explicit CLI entry.
|
|
105
|
-
*
|
|
106
|
-
* This intentionally accepts only a package manifest whose name is the
|
|
107
|
-
* official Harness package. It lets a Crew-owned source checkout (for example
|
|
108
|
-
* the GitHub-only dsh-v0.1.3-alpha.1 tag) report its real cohort without ever
|
|
109
|
-
* reading the official ~/.dsh profile or trusting an arbitrary package.json.
|
|
110
|
-
*/
|
|
111
|
-
function readExplicitCliVersion(entry) {
|
|
112
|
-
if (typeof entry !== 'string' || !entry.trim()) return null;
|
|
113
|
-
let cursor;
|
|
114
|
-
try { cursor = resolve(entry); } catch { return null; }
|
|
115
|
-
if (extname(cursor).toLowerCase() !== '.js') {
|
|
116
|
-
// A Windows shim normally lives at <root>/node_modules/.bin/dsh.cmd.
|
|
117
|
-
// Starting at its parent still finds the sibling @deepseek-ai/dsh tree.
|
|
118
|
-
cursor = dirname(cursor);
|
|
119
|
-
}
|
|
120
|
-
for (let depth = 0; depth < 12; depth += 1) {
|
|
121
|
-
const direct = readVersionManifest(join(cursor, 'package.json'));
|
|
122
|
-
if (direct) return direct;
|
|
123
|
-
const nested = readVersionManifest(join(cursor, 'node_modules', '@deepseek-ai', 'dsh', 'package.json'));
|
|
124
|
-
if (nested) return nested;
|
|
125
|
-
const parent = dirname(cursor);
|
|
126
|
-
if (parent === cursor) break;
|
|
127
|
-
cursor = parent;
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function getHubRuntimeIdentity() {
|
|
133
|
-
return {
|
|
134
|
-
service: 'dsh-crew-hub',
|
|
135
|
-
surface: 'native-crew-harness',
|
|
136
|
-
ui_role: 'runtime',
|
|
137
|
-
runtime_version: RUNTIME_VERSION,
|
|
138
|
-
dsh_version: readCrewDshVersion(),
|
|
139
|
-
protocol_version: HUB_PROTOCOL_VERSION,
|
|
140
|
-
execution_plane: PRODUCTION_EXECUTION_PLANE,
|
|
141
|
-
profile: PRODUCTION_PROFILE,
|
|
142
|
-
listen_port: PRODUCTION_LISTEN_PORT,
|
|
143
|
-
runtime_id: RUNTIME_ID,
|
|
144
|
-
capabilities: [...HUB_CAPABILITIES],
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Installed Harness cohort version (the @deepseek-ai/dsh package under the
|
|
149
|
-
// Crew-owned DSH home, or an explicit Crew-owned CLI source checkout). Null
|
|
150
|
-
// when unreadable: callers treat null as "unknown cohort", never as a match.
|
|
151
|
-
// This is the ONLY field cohort verifiers may compare against TARGET_DSH_VERSION.
|
|
152
|
-
export function readCrewDshVersion({ home = homedir(), env = process.env } = {}) {
|
|
153
|
-
// Only the Crew-scoped override is trusted here. A generic DSH_CLI may
|
|
154
|
-
// point at the official web profile and must never become Crew provenance.
|
|
155
|
-
const explicit = env?.DSH_CREW_DSH_CLI;
|
|
156
|
-
const explicitVersion = readExplicitCliVersion(explicit);
|
|
157
|
-
if (explicitVersion) return explicitVersion;
|
|
158
|
-
try {
|
|
159
|
-
const file = join(home, '.config', 'dsh-crew', 'harness', 'runtime', 'node_modules', '@deepseek-ai', 'dsh', 'package.json');
|
|
160
|
-
if (!existsSync(file)) return null;
|
|
161
|
-
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
162
|
-
return typeof parsed?.version === 'string' && parsed.version.length > 0 ? parsed.version : null;
|
|
163
|
-
} catch { return null; }
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Evaluate an already-received Hub ping body.
|
|
168
|
-
*
|
|
169
|
-
* This function does no I/O. `reachable` means an HTTP response was received;
|
|
170
|
-
* `compatible` means the response is from dsh-crew and satisfies the current
|
|
171
|
-
* protocol + required capability contract.
|
|
172
|
-
*/
|
|
173
|
-
export function evaluateHubHandshake(body, { requiredCapabilities = REQUIRED_HUB_CAPABILITIES, strictProduction = false } = {}) {
|
|
174
|
-
const capabilities = normalizedCapabilities(body?.capabilities);
|
|
175
|
-
const base = {
|
|
176
|
-
reachable: true,
|
|
177
|
-
compatible: false,
|
|
178
|
-
service: typeof body?.service === 'string' ? body.service : null,
|
|
179
|
-
runtime_version: typeof body?.runtime_version === 'string' ? body.runtime_version : null,
|
|
180
|
-
protocol_version: Number.isInteger(body?.protocol_version) ? body.protocol_version : null,
|
|
181
|
-
execution_plane: typeof body?.execution_plane === 'string' ? body.execution_plane : null,
|
|
182
|
-
profile: typeof body?.profile === 'string' ? body.profile : null,
|
|
183
|
-
listen_port: Number.isInteger(body?.listen_port) ? body.listen_port : null,
|
|
184
|
-
runtime_id: typeof body?.runtime_id === 'string' ? body.runtime_id : null,
|
|
185
|
-
capabilities,
|
|
186
|
-
missing_capabilities: [],
|
|
187
|
-
code: null,
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
if (body?.service !== 'dsh-crew-hub') {
|
|
191
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.SERVICE_MISMATCH };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// An explicit execution identity that is not the isolated 3210 Crew plane
|
|
195
|
-
// must never be accepted as the production Hub. Missing legacy fields remain
|
|
196
|
-
// compatible with the older protocol contract and are handled below.
|
|
197
|
-
if (body?.execution_plane !== undefined && body.execution_plane !== PRODUCTION_EXECUTION_PLANE) {
|
|
198
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.EXECUTION_PLANE_MISMATCH };
|
|
199
|
-
}
|
|
200
|
-
if (body?.listen_port !== undefined && body.listen_port !== PRODUCTION_LISTEN_PORT) {
|
|
201
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.LISTEN_PORT_MISMATCH };
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (!Number.isInteger(body?.protocol_version)) {
|
|
205
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISSING };
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (body.protocol_version !== HUB_PROTOCOL_VERSION) {
|
|
209
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISMATCH };
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (strictProduction && !(body?.execution_plane === PRODUCTION_EXECUTION_PLANE
|
|
213
|
-
&& body?.profile === PRODUCTION_PROFILE
|
|
214
|
-
&& Number.isInteger(body?.listen_port) && body.listen_port === PRODUCTION_LISTEN_PORT
|
|
215
|
-
&& typeof body?.runtime_id === 'string' && body.runtime_id.trim().length > 0)) {
|
|
216
|
-
return { ...base, code: HUB_COMPATIBILITY_CODES.PROVENANCE_MISSING };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const required = normalizedCapabilities(requiredCapabilities);
|
|
220
|
-
const advertised = new Set(capabilities);
|
|
221
|
-
const missing = required.filter((capability) => !advertised.has(capability));
|
|
222
|
-
if (missing.length > 0) {
|
|
223
|
-
return {
|
|
224
|
-
...base,
|
|
225
|
-
missing_capabilities: missing,
|
|
226
|
-
code: HUB_COMPATIBILITY_CODES.CAPABILITY_MISSING,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
...base,
|
|
232
|
-
compatible: true,
|
|
233
|
-
code: null,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
1
|
+
// Shared runtime identity and Hub compatibility contract.
|
|
2
|
+
//
|
|
3
|
+
// Package/release semver and the wire protocol are intentionally separate:
|
|
4
|
+
// - RUNTIME_VERSION identifies the source/runtime generation for diagnostics.
|
|
5
|
+
// - HUB_PROTOCOL_VERSION changes only when Hub <-> MCP wire semantics become
|
|
6
|
+
// incompatible.
|
|
7
|
+
//
|
|
8
|
+
// The Harness/DSH cohort version (e.g. 0.1.5-rc.2) is a THIRD, independent
|
|
9
|
+
// domain: it identifies the installed @deepseek-ai/dsh package generation,
|
|
10
|
+
// never the Crew release. Verifiers must compare the cohort against
|
|
11
|
+
// dsh_version, never against runtime_version.
|
|
12
|
+
//
|
|
13
|
+
// Keep this module dependency-light so Hub, MCP and tests all use the exact
|
|
14
|
+
// same compatibility rules.
|
|
15
|
+
|
|
16
|
+
import { randomUUID } from 'node:crypto';
|
|
17
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
19
|
+
import { dirname, extname, join, resolve } from 'node:path';
|
|
20
|
+
import {
|
|
21
|
+
PRODUCTION_EXECUTION_PLANE,
|
|
22
|
+
PRODUCTION_PROFILE,
|
|
23
|
+
PRODUCTION_LISTEN_PORT,
|
|
24
|
+
} from './runtime-identity-contract.mjs';
|
|
25
|
+
export {
|
|
26
|
+
PRODUCTION_EXECUTION_PLANE,
|
|
27
|
+
PRODUCTION_PROFILE,
|
|
28
|
+
PRODUCTION_LISTEN_PORT,
|
|
29
|
+
isCompleteRuntimeIdentity,
|
|
30
|
+
sameCompleteRuntimeIdentity,
|
|
31
|
+
isExactNativeCrewIdentity,
|
|
32
|
+
} from './runtime-identity-contract.mjs';
|
|
33
|
+
|
|
34
|
+
// Production Crew execution is intentionally bound to the isolated 3210 Hub.
|
|
35
|
+
// These fields are public provenance only; no credential or session secret is
|
|
36
|
+
// included in the identity contract.
|
|
37
|
+
const RUNTIME_ID = randomUUID();
|
|
38
|
+
|
|
39
|
+
export const RUNTIME_VERSION = '1.10.0';
|
|
40
|
+
export const HUB_PROTOCOL_VERSION = 1;
|
|
41
|
+
|
|
42
|
+
export const HUB_CAPABILITIES = Object.freeze([
|
|
43
|
+
'jobs',
|
|
44
|
+
'jobs-wait',
|
|
45
|
+
'jobs-cancel',
|
|
46
|
+
'roles',
|
|
47
|
+
'attempt-index',
|
|
48
|
+
'model-policy',
|
|
49
|
+
'model-catalog',
|
|
50
|
+
'presets',
|
|
51
|
+
'config',
|
|
52
|
+
'canonical-events',
|
|
53
|
+
'evidence',
|
|
54
|
+
'profiles',
|
|
55
|
+
'workspace-context',
|
|
56
|
+
'extension-contract',
|
|
57
|
+
'provider-inventory',
|
|
58
|
+
'provider-layer-migration-v1',
|
|
59
|
+
'provider-lifecycle-v1',
|
|
60
|
+
'provider-health-v1',
|
|
61
|
+
'provider-probe-stream-v1',
|
|
62
|
+
'credential-reference-inventory-v1',
|
|
63
|
+
'credential-purge-v1',
|
|
64
|
+
'runtime-provenance-v1',
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
// Capabilities the current MCP workflow depends on for full Hub execution.
|
|
68
|
+
// Additional capabilities may be advertised without breaking compatibility.
|
|
69
|
+
export const REQUIRED_HUB_CAPABILITIES = Object.freeze([
|
|
70
|
+
'jobs',
|
|
71
|
+
'jobs-wait',
|
|
72
|
+
'jobs-cancel',
|
|
73
|
+
'roles',
|
|
74
|
+
'attempt-index',
|
|
75
|
+
'model-policy',
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
export const HUB_COMPATIBILITY_CODES = Object.freeze({
|
|
79
|
+
UNREACHABLE: 'HUB_UNREACHABLE',
|
|
80
|
+
HTTP_ERROR: 'HUB_HTTP_ERROR',
|
|
81
|
+
SERVICE_MISMATCH: 'HUB_SERVICE_MISMATCH',
|
|
82
|
+
PROTOCOL_MISSING: 'HUB_PROTOCOL_MISSING',
|
|
83
|
+
PROTOCOL_MISMATCH: 'HUB_PROTOCOL_MISMATCH',
|
|
84
|
+
CAPABILITY_MISSING: 'HUB_CAPABILITY_MISSING',
|
|
85
|
+
PROVENANCE_MISSING: 'HUB_PROVENANCE_MISSING',
|
|
86
|
+
EXECUTION_PLANE_MISMATCH: 'HUB_EXECUTION_PLANE_MISMATCH',
|
|
87
|
+
LISTEN_PORT_MISMATCH: 'HUB_LISTEN_PORT_MISMATCH',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
function normalizedCapabilities(value) {
|
|
91
|
+
if (!Array.isArray(value)) return [];
|
|
92
|
+
return [...new Set(value.filter((item) => typeof item === 'string' && item.trim()).map((item) => item.trim()))];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function readVersionManifest(file) {
|
|
96
|
+
try {
|
|
97
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
98
|
+
if (parsed?.name !== '@deepseek-ai/dsh') return null;
|
|
99
|
+
return typeof parsed.version === 'string' && parsed.version.trim() ? parsed.version.trim() : null;
|
|
100
|
+
} catch { return null; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Resolve the @deepseek-ai/dsh manifest belonging to an explicit CLI entry.
|
|
105
|
+
*
|
|
106
|
+
* This intentionally accepts only a package manifest whose name is the
|
|
107
|
+
* official Harness package. It lets a Crew-owned source checkout (for example
|
|
108
|
+
* the GitHub-only dsh-v0.1.3-alpha.1 tag) report its real cohort without ever
|
|
109
|
+
* reading the official ~/.dsh profile or trusting an arbitrary package.json.
|
|
110
|
+
*/
|
|
111
|
+
function readExplicitCliVersion(entry) {
|
|
112
|
+
if (typeof entry !== 'string' || !entry.trim()) return null;
|
|
113
|
+
let cursor;
|
|
114
|
+
try { cursor = resolve(entry); } catch { return null; }
|
|
115
|
+
if (extname(cursor).toLowerCase() !== '.js') {
|
|
116
|
+
// A Windows shim normally lives at <root>/node_modules/.bin/dsh.cmd.
|
|
117
|
+
// Starting at its parent still finds the sibling @deepseek-ai/dsh tree.
|
|
118
|
+
cursor = dirname(cursor);
|
|
119
|
+
}
|
|
120
|
+
for (let depth = 0; depth < 12; depth += 1) {
|
|
121
|
+
const direct = readVersionManifest(join(cursor, 'package.json'));
|
|
122
|
+
if (direct) return direct;
|
|
123
|
+
const nested = readVersionManifest(join(cursor, 'node_modules', '@deepseek-ai', 'dsh', 'package.json'));
|
|
124
|
+
if (nested) return nested;
|
|
125
|
+
const parent = dirname(cursor);
|
|
126
|
+
if (parent === cursor) break;
|
|
127
|
+
cursor = parent;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function getHubRuntimeIdentity() {
|
|
133
|
+
return {
|
|
134
|
+
service: 'dsh-crew-hub',
|
|
135
|
+
surface: 'native-crew-harness',
|
|
136
|
+
ui_role: 'runtime',
|
|
137
|
+
runtime_version: RUNTIME_VERSION,
|
|
138
|
+
dsh_version: readCrewDshVersion(),
|
|
139
|
+
protocol_version: HUB_PROTOCOL_VERSION,
|
|
140
|
+
execution_plane: PRODUCTION_EXECUTION_PLANE,
|
|
141
|
+
profile: PRODUCTION_PROFILE,
|
|
142
|
+
listen_port: PRODUCTION_LISTEN_PORT,
|
|
143
|
+
runtime_id: RUNTIME_ID,
|
|
144
|
+
capabilities: [...HUB_CAPABILITIES],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Installed Harness cohort version (the @deepseek-ai/dsh package under the
|
|
149
|
+
// Crew-owned DSH home, or an explicit Crew-owned CLI source checkout). Null
|
|
150
|
+
// when unreadable: callers treat null as "unknown cohort", never as a match.
|
|
151
|
+
// This is the ONLY field cohort verifiers may compare against TARGET_DSH_VERSION.
|
|
152
|
+
export function readCrewDshVersion({ home = homedir(), env = process.env } = {}) {
|
|
153
|
+
// Only the Crew-scoped override is trusted here. A generic DSH_CLI may
|
|
154
|
+
// point at the official web profile and must never become Crew provenance.
|
|
155
|
+
const explicit = env?.DSH_CREW_DSH_CLI;
|
|
156
|
+
const explicitVersion = readExplicitCliVersion(explicit);
|
|
157
|
+
if (explicitVersion) return explicitVersion;
|
|
158
|
+
try {
|
|
159
|
+
const file = join(home, '.config', 'dsh-crew', 'harness', 'runtime', 'node_modules', '@deepseek-ai', 'dsh', 'package.json');
|
|
160
|
+
if (!existsSync(file)) return null;
|
|
161
|
+
const parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
162
|
+
return typeof parsed?.version === 'string' && parsed.version.length > 0 ? parsed.version : null;
|
|
163
|
+
} catch { return null; }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Evaluate an already-received Hub ping body.
|
|
168
|
+
*
|
|
169
|
+
* This function does no I/O. `reachable` means an HTTP response was received;
|
|
170
|
+
* `compatible` means the response is from dsh-crew and satisfies the current
|
|
171
|
+
* protocol + required capability contract.
|
|
172
|
+
*/
|
|
173
|
+
export function evaluateHubHandshake(body, { requiredCapabilities = REQUIRED_HUB_CAPABILITIES, strictProduction = false } = {}) {
|
|
174
|
+
const capabilities = normalizedCapabilities(body?.capabilities);
|
|
175
|
+
const base = {
|
|
176
|
+
reachable: true,
|
|
177
|
+
compatible: false,
|
|
178
|
+
service: typeof body?.service === 'string' ? body.service : null,
|
|
179
|
+
runtime_version: typeof body?.runtime_version === 'string' ? body.runtime_version : null,
|
|
180
|
+
protocol_version: Number.isInteger(body?.protocol_version) ? body.protocol_version : null,
|
|
181
|
+
execution_plane: typeof body?.execution_plane === 'string' ? body.execution_plane : null,
|
|
182
|
+
profile: typeof body?.profile === 'string' ? body.profile : null,
|
|
183
|
+
listen_port: Number.isInteger(body?.listen_port) ? body.listen_port : null,
|
|
184
|
+
runtime_id: typeof body?.runtime_id === 'string' ? body.runtime_id : null,
|
|
185
|
+
capabilities,
|
|
186
|
+
missing_capabilities: [],
|
|
187
|
+
code: null,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
if (body?.service !== 'dsh-crew-hub') {
|
|
191
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.SERVICE_MISMATCH };
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// An explicit execution identity that is not the isolated 3210 Crew plane
|
|
195
|
+
// must never be accepted as the production Hub. Missing legacy fields remain
|
|
196
|
+
// compatible with the older protocol contract and are handled below.
|
|
197
|
+
if (body?.execution_plane !== undefined && body.execution_plane !== PRODUCTION_EXECUTION_PLANE) {
|
|
198
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.EXECUTION_PLANE_MISMATCH };
|
|
199
|
+
}
|
|
200
|
+
if (body?.listen_port !== undefined && body.listen_port !== PRODUCTION_LISTEN_PORT) {
|
|
201
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.LISTEN_PORT_MISMATCH };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (!Number.isInteger(body?.protocol_version)) {
|
|
205
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISSING };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (body.protocol_version !== HUB_PROTOCOL_VERSION) {
|
|
209
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.PROTOCOL_MISMATCH };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (strictProduction && !(body?.execution_plane === PRODUCTION_EXECUTION_PLANE
|
|
213
|
+
&& body?.profile === PRODUCTION_PROFILE
|
|
214
|
+
&& Number.isInteger(body?.listen_port) && body.listen_port === PRODUCTION_LISTEN_PORT
|
|
215
|
+
&& typeof body?.runtime_id === 'string' && body.runtime_id.trim().length > 0)) {
|
|
216
|
+
return { ...base, code: HUB_COMPATIBILITY_CODES.PROVENANCE_MISSING };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const required = normalizedCapabilities(requiredCapabilities);
|
|
220
|
+
const advertised = new Set(capabilities);
|
|
221
|
+
const missing = required.filter((capability) => !advertised.has(capability));
|
|
222
|
+
if (missing.length > 0) {
|
|
223
|
+
return {
|
|
224
|
+
...base,
|
|
225
|
+
missing_capabilities: missing,
|
|
226
|
+
code: HUB_COMPATIBILITY_CODES.CAPABILITY_MISSING,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
...base,
|
|
232
|
+
compatible: true,
|
|
233
|
+
code: null,
|
|
234
|
+
};
|
|
235
|
+
}
|