@ran-sh/dsh-crew 1.0.3 → 1.1.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/codex/AGENTS.md +101 -92
- package/docs/ui-surfaces.md +48 -21
- package/lib/client.js +68 -44
- package/official-web-bridge/lib/client.js +368 -4709
- package/official-web-bridge/package.json +1 -2
- package/package.json +130 -67
- package/scripts/build-client.mjs +30 -15
- package/scripts/remove-legacy-official-bridge.ps1 +89 -0
- package/scripts/setup.mjs +152 -140
- package/scripts/verify-npm-install.mjs +311 -310
- package/scripts/verify-official-bridge-e2e.mjs +12 -1
- package/src/client/host-readiness.mjs +62 -59
- package/src/client/index.tsx +35 -30
- package/src/client/quick-entry.tsx +10 -0
- package/src/client/quick-panel.tsx +295 -0
- package/src/client/surface-detection.mjs +43 -30
- package/src/dsh-cli-runtime.mjs +500 -40
- package/src/dsh-cohort.mjs +20 -0
- package/src/hub/index.mjs +1602 -1485
- package/src/install/npx-lifecycle.mjs +1568 -111
- package/src/install/official-web.mjs +36 -73
- package/src/jobs.mjs +20 -24
- package/src/official-web-bridge.mjs +329 -249
- package/src/runtime-identity.mjs +23 -1
- package/src/supervisor/restart-request.mjs +202 -0
- package/windows/start-dsh-crew.ps1 +783 -370
- package/worker.cordis.yml +32 -46
- package/zcode/AGENTS.md +35 -26
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
},
|
|
16
16
|
"client": {
|
|
17
17
|
"inject": [
|
|
18
|
-
"@deepseek-ai/dsh-client-
|
|
18
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
19
19
|
"@deepseek-ai/dsh-client-locale",
|
|
20
|
-
"@deepseek-ai/dsh-client-ui-slots",
|
|
21
20
|
"@deepseek-ai/dsh-client-ui-settings"
|
|
22
21
|
],
|
|
23
22
|
"platform": "web"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ran-sh/dsh-crew",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/hub/entry.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -13,9 +13,8 @@
|
|
|
13
13
|
},
|
|
14
14
|
"client": {
|
|
15
15
|
"inject": [
|
|
16
|
-
"@deepseek-ai/dsh-client-
|
|
16
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
17
17
|
"@deepseek-ai/dsh-client-locale",
|
|
18
|
-
"@deepseek-ai/dsh-client-ui-slots",
|
|
19
18
|
"@deepseek-ai/dsh-client-ui-settings"
|
|
20
19
|
],
|
|
21
20
|
"platform": "web"
|
|
@@ -23,10 +22,10 @@
|
|
|
23
22
|
},
|
|
24
23
|
"scripts": {
|
|
25
24
|
"mcp": "node src/server.mjs",
|
|
26
|
-
"build:client": "tsdown src/client/entry.tsx --format cjs --platform browser --target es2022 --tsconfig tsconfig.client.json --deps.never-bundle react --deps.never-bundle react/jsx-runtime --deps.never-bundle react-dom --deps.never-bundle react-dom/client --out-dir .client-build --clean --logLevel warn && node scripts/build-client.mjs",
|
|
25
|
+
"build:client": "tsdown src/client/entry.tsx src/client/quick-entry.tsx --format cjs --platform browser --target es2022 --tsconfig tsconfig.client.json --deps.never-bundle react --deps.never-bundle react/jsx-runtime --deps.never-bundle react-dom --deps.never-bundle react-dom/client --out-dir .client-build --clean --logLevel warn && node scripts/build-client.mjs",
|
|
27
26
|
"verify:npm-install": "node scripts/verify-npm-install.mjs",
|
|
28
27
|
"verify:npm-install:official": "node scripts/verify-npm-install.mjs --with-official-dsh",
|
|
29
|
-
"verify:official-bridge": "node scripts/verify-official-bridge-e2e.mjs"
|
|
28
|
+
"verify:official-bridge": "node scripts/verify-official-bridge-e2e.mjs --diagnostic-only"
|
|
30
29
|
},
|
|
31
30
|
"dependencies": {
|
|
32
31
|
"@modelcontextprotocol/sdk": "^1.25.4",
|
|
@@ -38,74 +37,138 @@
|
|
|
38
37
|
"./package.json": "./package.json"
|
|
39
38
|
},
|
|
40
39
|
"peerDependencies": {
|
|
41
|
-
"@deepseek-ai/dsh
|
|
42
|
-
"@deepseek-ai/dsh-agent
|
|
43
|
-
"@deepseek-ai/dsh-agent-
|
|
44
|
-
"@deepseek-ai/dsh-
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/dsh-
|
|
47
|
-
"@deepseek-ai/dsh-
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
40
|
+
"@deepseek-ai/dsh": "0.1.2-rc.1",
|
|
41
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
42
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.2-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-agent-presets": "0.1.2-rc.1",
|
|
44
|
+
"@deepseek-ai/dsh-bash-local": "0.1.2-rc.1",
|
|
45
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
47
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
|
|
48
|
+
"@deepseek-ai/dsh-compaction-basic": "0.1.2-rc.1",
|
|
49
|
+
"@deepseek-ai/dsh-fs-local": "0.1.2-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-fs-observation-policy": "0.1.2-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.1.2-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-sandbox-local": "0.1.2-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-sdk-client": "0.1.2-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.2-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-sdk-minimal": "0.1.2-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.2-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.2-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-token-meter": "0.1.2-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-tool-fs": "0.1.2-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-tool-todo": "0.1.2-rc.1",
|
|
61
64
|
"react": "^18.0.0",
|
|
62
65
|
"react-dom": "^18.0.0"
|
|
63
66
|
},
|
|
64
67
|
"peerDependenciesMeta": {
|
|
65
|
-
"@deepseek-ai/dsh
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"@deepseek-ai/dsh-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
"@deepseek-ai/dsh-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"@deepseek-ai/dsh-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"@deepseek-ai/dsh-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"
|
|
68
|
+
"@deepseek-ai/dsh": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"@deepseek-ai/dsh-agent": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"@deepseek-ai/dsh-agent-loop": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"@deepseek-ai/dsh-agent-presets": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"@deepseek-ai/dsh-bash-local": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-renderer": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-settings": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@deepseek-ai/dsh-compaction-basic": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@deepseek-ai/dsh-fs-local": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@deepseek-ai/dsh-fs-observation-policy": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@deepseek-ai/dsh-llm": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"@deepseek-ai/dsh-llm-deepseek": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"@deepseek-ai/dsh-sandbox-local": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"@deepseek-ai/dsh-sandbox-policy": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
113
|
+
"@deepseek-ai/dsh-sdk-client": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": {
|
|
117
|
+
"optional": true
|
|
118
|
+
},
|
|
119
|
+
"@deepseek-ai/dsh-sdk-minimal": {
|
|
120
|
+
"optional": true
|
|
121
|
+
},
|
|
122
|
+
"@deepseek-ai/dsh-session": {
|
|
123
|
+
"optional": true
|
|
124
|
+
},
|
|
125
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": {
|
|
126
|
+
"optional": true
|
|
127
|
+
},
|
|
128
|
+
"@deepseek-ai/dsh-subprocess-local": {
|
|
129
|
+
"optional": true
|
|
130
|
+
},
|
|
131
|
+
"@deepseek-ai/dsh-token-meter": {
|
|
132
|
+
"optional": true
|
|
133
|
+
},
|
|
134
|
+
"@deepseek-ai/dsh-tool-fs": {
|
|
135
|
+
"optional": true
|
|
136
|
+
},
|
|
137
|
+
"@deepseek-ai/dsh-tool-todo": {
|
|
138
|
+
"optional": true
|
|
139
|
+
},
|
|
140
|
+
"react": {
|
|
141
|
+
"optional": true
|
|
142
|
+
},
|
|
143
|
+
"react-dom": {
|
|
144
|
+
"optional": true
|
|
145
|
+
}
|
|
87
146
|
},
|
|
88
147
|
"devDependencies": {
|
|
89
|
-
"@deepseek-ai/dsh
|
|
90
|
-
"@deepseek-ai/dsh-agent
|
|
91
|
-
"@deepseek-ai/dsh-agent-
|
|
92
|
-
"@deepseek-ai/dsh-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
94
|
-
"@deepseek-ai/dsh-
|
|
95
|
-
"@deepseek-ai/dsh-
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/dsh-
|
|
100
|
-
"@deepseek-ai/dsh-
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
103
|
-
"@deepseek-ai/dsh-
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/dsh-
|
|
106
|
-
"@deepseek-ai/dsh-
|
|
107
|
-
"@deepseek-ai/dsh-
|
|
108
|
-
"@deepseek-ai/dsh-
|
|
148
|
+
"@deepseek-ai/dsh": "0.1.2-rc.1",
|
|
149
|
+
"@deepseek-ai/dsh-agent": "0.1.2-rc.1",
|
|
150
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.2-rc.1",
|
|
151
|
+
"@deepseek-ai/dsh-agent-presets": "0.1.2-rc.1",
|
|
152
|
+
"@deepseek-ai/dsh-bash-local": "0.1.2-rc.1",
|
|
153
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
154
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
155
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1",
|
|
156
|
+
"@deepseek-ai/dsh-compaction-basic": "0.1.2-rc.1",
|
|
157
|
+
"@deepseek-ai/dsh-fs-local": "0.1.2-rc.1",
|
|
158
|
+
"@deepseek-ai/dsh-fs-observation-policy": "0.1.2-rc.1",
|
|
159
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
160
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.1.2-rc.1",
|
|
161
|
+
"@deepseek-ai/dsh-sandbox-local": "0.1.2-rc.1",
|
|
162
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
|
|
163
|
+
"@deepseek-ai/dsh-sdk-client": "0.1.2-rc.1",
|
|
164
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.2-rc.1",
|
|
165
|
+
"@deepseek-ai/dsh-sdk-minimal": "0.1.2-rc.1",
|
|
166
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
167
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.2-rc.1",
|
|
168
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.2-rc.1",
|
|
169
|
+
"@deepseek-ai/dsh-token-meter": "0.1.2-rc.1",
|
|
170
|
+
"@deepseek-ai/dsh-tool-fs": "0.1.2-rc.1",
|
|
171
|
+
"@deepseek-ai/dsh-tool-todo": "0.1.2-rc.1",
|
|
109
172
|
"@types/react": "^18.3.0",
|
|
110
173
|
"react": "^18.3.1",
|
|
111
174
|
"react-dom": "^18.3.1",
|
package/scripts/build-client.mjs
CHANGED
|
@@ -10,23 +10,38 @@ const root = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
|
10
10
|
const manifest = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
|
|
11
11
|
const pluginId = manifest.name;
|
|
12
12
|
const buildDir = join(root, '.client-build');
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
// Dual entry: the full 3210 control plane (entry.cjs) and the narrow 3080
|
|
15
|
+
// quick panel (quick-entry.cjs). They are wrapped under DIFFERENT module
|
|
16
|
+
// ids so the official surface never receives full control-plane code.
|
|
17
|
+
const fullEntry = 'entry.cjs';
|
|
18
|
+
const quickEntry = 'quick-entry.cjs';
|
|
19
|
+
const built = (await readdir(buildDir)).filter((name) => name.endsWith('.cjs'));
|
|
20
|
+
for (const expected of [fullEntry, quickEntry]) {
|
|
21
|
+
if (!built.includes(expected)) {
|
|
22
|
+
throw new Error(`missing compiled client entry ${expected} in .client-build (found: ${built.join(', ')})`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function wrap(source, id) {
|
|
27
|
+
return [
|
|
28
|
+
`window.__ModuleLoader__.load({ id: ${JSON.stringify(id)}, factory: (require) => {`,
|
|
29
|
+
'var module = { exports: {} }; var exports = module.exports;',
|
|
30
|
+
source.replace(/\n?\/\/# sourceMappingURL=.*$/u, ''),
|
|
31
|
+
'return module.exports; } });',
|
|
32
|
+
'',
|
|
33
|
+
].join('\n');
|
|
16
34
|
}
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
'var module = { exports: {} }; var exports = module.exports;',
|
|
21
|
-
source.replace(/\n?\/\/# sourceMappingURL=.*$/u, ''),
|
|
22
|
-
'return module.exports; } });',
|
|
23
|
-
'',
|
|
24
|
-
].join('\n');
|
|
35
|
+
|
|
36
|
+
const fullSource = await readFile(join(buildDir, fullEntry), 'utf8');
|
|
37
|
+
const fullWrapped = wrap(fullSource, pluginId);
|
|
25
38
|
await mkdir(join(root, 'lib'), { recursive: true });
|
|
26
|
-
await writeFile(join(root, 'lib', 'client.js'),
|
|
39
|
+
await writeFile(join(root, 'lib', 'client.js'), fullWrapped);
|
|
40
|
+
|
|
27
41
|
const bridgeManifest = JSON.parse(await readFile(join(root, 'official-web-bridge', 'package.json'), 'utf8'));
|
|
28
|
-
const
|
|
42
|
+
const quickSource = await readFile(join(buildDir, quickEntry), 'utf8');
|
|
43
|
+
const quickWrapped = wrap(quickSource, bridgeManifest.name);
|
|
29
44
|
await mkdir(join(root, 'official-web-bridge', 'lib'), { recursive: true });
|
|
30
|
-
await writeFile(join(root, 'official-web-bridge', 'lib', 'client.js'),
|
|
45
|
+
await writeFile(join(root, 'official-web-bridge', 'lib', 'client.js'), quickWrapped);
|
|
31
46
|
await rm(buildDir, { recursive: true, force: true });
|
|
32
|
-
console.log(`built lib/client.js and official-web-bridge/lib/client.js (${
|
|
47
|
+
console.log(`built lib/client.js (${fullWrapped.length} bytes) and official-web-bridge/lib/client.js (${quickWrapped.length} bytes) from ${fullEntry} + ${quickEntry}`);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# One-shot operator maintenance: remove the legacy official-web bridge state
|
|
2
|
+
# left behind BEFORE the read-only policy. This script is NEVER invoked by
|
|
3
|
+
# the dsh-crew installer; the product code never writes to ~/.dsh.
|
|
4
|
+
#
|
|
5
|
+
# Preconditions (fail closed unless ALL hold):
|
|
6
|
+
# 1. Official 3080 is stopped and no longer listening.
|
|
7
|
+
# 2. ~/.dsh/profiles/web/package.json dependencies["@ran-sh/dsh-crew-web-bridge"] exists.
|
|
8
|
+
# 3. dsh.profile.bundles contains "@ran-sh/dsh-crew-web-bridge".
|
|
9
|
+
# 4. node_modules/@ran-sh/dsh-crew-web-bridge is a symlink/junction whose
|
|
10
|
+
# target is an old Crew release official-web-bridge dir.
|
|
11
|
+
# Usage:
|
|
12
|
+
# powershell -NoProfile -ExecutionPolicy Bypass -File scripts/remove-legacy-official-bridge.ps1 [-WhatIf]
|
|
13
|
+
|
|
14
|
+
[CmdletBinding(SupportsShouldProcess = $true)]
|
|
15
|
+
param()
|
|
16
|
+
|
|
17
|
+
Set-StrictMode -Version Latest
|
|
18
|
+
$ErrorActionPreference = 'Stop'
|
|
19
|
+
|
|
20
|
+
$BridgePackage = '@ran-sh/dsh-crew-web-bridge'
|
|
21
|
+
$officialManifest = Join-Path $env:USERPROFILE '.dsh\profiles\web\package.json'
|
|
22
|
+
$bridgeLink = Join-Path $env:USERPROFILE '.dsh\profiles\web\node_modules\@ran-sh\dsh-crew-web-bridge'
|
|
23
|
+
$crewState = Join-Path $env:USERPROFILE '.config\dsh-crew\official-web.json'
|
|
24
|
+
|
|
25
|
+
function Fail($message) {
|
|
26
|
+
Write-Host "FAIL-CLOSED: $message" -ForegroundColor Red
|
|
27
|
+
exit 2
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# 1. Official 3080 must be stopped.
|
|
31
|
+
try {
|
|
32
|
+
$listeners = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties().GetActiveTcpListeners()
|
|
33
|
+
if (@($listeners | Where-Object Port -eq 3080).Count -gt 0) {
|
|
34
|
+
Fail 'official 3080 is still listening; stop it before cleanup.'
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
Fail "could not enumerate TCP listeners: $($_.Exception.Message)"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# 2. Read + back up the official manifest (backup goes OUTSIDE .dsh).
|
|
41
|
+
if (-not (Test-Path -LiteralPath $officialManifest -PathType Leaf)) {
|
|
42
|
+
Fail "official manifest not found: $officialManifest"
|
|
43
|
+
}
|
|
44
|
+
$backup = Join-Path ([System.IO.Path]::GetTempPath()) 'dsh-web-package.pre-crew-bridge-removal.json'
|
|
45
|
+
if ($PSCmdlet.ShouldProcess($officialManifest, "backup to $backup")) {
|
|
46
|
+
Copy-Item -LiteralPath $officialManifest -Destination $backup -Force
|
|
47
|
+
Write-Host "Backup: $backup"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$manifest = Get-Content -LiteralPath $officialManifest -Raw | ConvertFrom-Json -ErrorAction Stop
|
|
51
|
+
if (-not $manifest.dependencies.$BridgePackage) {
|
|
52
|
+
Fail 'bridge dependency key absent; nothing to clean.'
|
|
53
|
+
}
|
|
54
|
+
if (-not ($manifest.dsh.profile.bundles -contains $BridgePackage)) {
|
|
55
|
+
Fail 'bridge bundle entry absent; nothing to clean.'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# 3. The link must be a symlink/junction pointing at an old Crew release bridge.
|
|
59
|
+
$link = Get-Item -LiteralPath $bridgeLink -ErrorAction SilentlyContinue
|
|
60
|
+
if (-not $link -or $link.LinkType -notin @('SymbolicLink', 'Junction')) {
|
|
61
|
+
Fail 'bridge link is not a symlink/junction; refusing to touch unknown state.'
|
|
62
|
+
}
|
|
63
|
+
$target = $link.Target
|
|
64
|
+
if (-not $target) {
|
|
65
|
+
$target = (Get-Item -LiteralPath $bridgeLink).FullName
|
|
66
|
+
}
|
|
67
|
+
if ($target -notmatch 'dsh-crew.*official-web-bridge') {
|
|
68
|
+
Fail "bridge link target does not look like a Crew release bridge: $target"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# 4. Remove ONLY the dependency key, the bundle entry, and the link.
|
|
72
|
+
if ($PSCmdlet.ShouldProcess($officialManifest, 'remove legacy bridge entries')) {
|
|
73
|
+
$raw = Get-Content -LiteralPath $officialManifest -Raw | ConvertFrom-Json
|
|
74
|
+
$raw.dependencies.PSObject.Properties.Remove($BridgePackage)
|
|
75
|
+
$raw.dsh.profile.bundles = @($raw.dsh.profile.bundles | Where-Object { $_ -ne $BridgePackage })
|
|
76
|
+
$raw | ConvertTo-Json -Depth 20 | Set-Content -LiteralPath $officialManifest -Encoding UTF8
|
|
77
|
+
Remove-Item -LiteralPath $bridgeLink -Force
|
|
78
|
+
Write-Host 'Removed bridge dependency key, bundle entry, and link.'
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# 5. Remove Crew-owned legacy intent/state (Crew-owned path, safe to delete).
|
|
82
|
+
if ($PSCmdlet.ShouldProcess($crewState, 'remove legacy Crew bridge state')) {
|
|
83
|
+
Remove-Item -LiteralPath $crewState -Force -ErrorAction SilentlyContinue
|
|
84
|
+
Write-Host 'Removed Crew-owned legacy bridge state (if present).'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Write-Host 'Done. Restart official 3080 natively; verify:'
|
|
88
|
+
Write-Host ' - 3080 / is 2xx/3xx and /_dsh/dsh-crew/{ping,bridge-status,supervisor/restart} are gone'
|
|
89
|
+
Write-Host ' - 3210 /_dsh/dsh-crew/extension identity is correct (Crew launcher owns 3210 directly)'
|