@ran-sh/dsh-crew 1.6.2 → 1.7.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.
- package/.claude-plugin/plugin.json +1 -1
- package/package.json +233 -232
- package/skills/dsh-crew/SKILL.md +118 -0
- package/src/install/crew-skill.mjs +91 -0
- package/src/install/install-legacy.mjs +20 -30
- package/src/install/zcode.mjs +29 -35
- package/src/runtime-identity.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,232 +1,233 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ran-sh/dsh-crew",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"main": "./src/hub/entry.mjs",
|
|
6
|
-
"bin": {
|
|
7
|
-
"dsh-crew": "bin/dsh-crew.mjs"
|
|
8
|
-
},
|
|
9
|
-
"description": "DeepSeek Harness plugin: dispatch work to DSH agents from Claude Code / Codex, as native subagents with live progress",
|
|
10
|
-
"dshCrew": {
|
|
11
|
-
"payloadSchema": 2,
|
|
12
|
-
"windowsSupervisorHandoff": 1
|
|
13
|
-
},
|
|
14
|
-
"dsh": {
|
|
15
|
-
"bundle": {
|
|
16
|
-
"patch": "./cordis.patch.yml"
|
|
17
|
-
},
|
|
18
|
-
"client": {
|
|
19
|
-
"inject": [
|
|
20
|
-
"@deepseek-ai/dsh-client-ui-renderer",
|
|
21
|
-
"@deepseek-ai/dsh-client-locale",
|
|
22
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
23
|
-
],
|
|
24
|
-
"platform": "web"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"scripts": {
|
|
28
|
-
"mcp": "node src/server.mjs",
|
|
29
|
-
"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 && tsdown 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 --no-clean --logLevel warn && node scripts/build-client.mjs",
|
|
30
|
-
"verify:npm-install": "node scripts/verify-npm-install.mjs",
|
|
31
|
-
"verify:npm-install:official": "node scripts/verify-npm-install.mjs --with-official-dsh",
|
|
32
|
-
"verify:official-bridge": "node scripts/verify-official-bridge-e2e.mjs --diagnostic-only"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@modelcontextprotocol/sdk": "^1.25.4",
|
|
36
|
-
"zod": "^3.24.0"
|
|
37
|
-
},
|
|
38
|
-
"exports": {
|
|
39
|
-
".": "./src/hub/entry.mjs",
|
|
40
|
-
"./client": "./lib/client.js",
|
|
41
|
-
"./package.json": "./package.json"
|
|
42
|
-
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"@deepseek-ai/dsh": "0.1.5-rc.2",
|
|
45
|
-
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
|
|
46
|
-
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
|
|
47
|
-
"@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
|
|
48
|
-
"@deepseek-ai/dsh-bash-local": "0.1.5-rc.2",
|
|
49
|
-
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
|
|
50
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
|
|
51
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
52
|
-
"@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.2",
|
|
53
|
-
"@deepseek-ai/dsh-fs-local": "0.1.5-rc.2",
|
|
54
|
-
"@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.2",
|
|
55
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
56
|
-
"@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.2",
|
|
57
|
-
"@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.2",
|
|
58
|
-
"@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
|
|
59
|
-
"@deepseek-ai/dsh-sdk-client": "0.1.5-rc.2",
|
|
60
|
-
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.5-rc.2",
|
|
61
|
-
"@deepseek-ai/dsh-sdk-minimal": "0.1.5-rc.2",
|
|
62
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
63
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.2",
|
|
64
|
-
"@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.2",
|
|
65
|
-
"@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
|
|
66
|
-
"@deepseek-ai/dsh-tool-fs": "0.1.5-rc.2",
|
|
67
|
-
"@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
|
|
68
|
-
"react": "^18.0.0",
|
|
69
|
-
"react-dom": "^18.0.0"
|
|
70
|
-
},
|
|
71
|
-
"peerDependenciesMeta": {
|
|
72
|
-
"@deepseek-ai/dsh": {
|
|
73
|
-
"optional": true
|
|
74
|
-
},
|
|
75
|
-
"@deepseek-ai/dsh-agent": {
|
|
76
|
-
"optional": true
|
|
77
|
-
},
|
|
78
|
-
"@deepseek-ai/dsh-agent-loop": {
|
|
79
|
-
"optional": true
|
|
80
|
-
},
|
|
81
|
-
"@deepseek-ai/dsh-agent-presets": {
|
|
82
|
-
"optional": true
|
|
83
|
-
},
|
|
84
|
-
"@deepseek-ai/dsh-bash-local": {
|
|
85
|
-
"optional": true
|
|
86
|
-
},
|
|
87
|
-
"@deepseek-ai/dsh-client-locale": {
|
|
88
|
-
"optional": true
|
|
89
|
-
},
|
|
90
|
-
"@deepseek-ai/dsh-client-ui-renderer": {
|
|
91
|
-
"optional": true
|
|
92
|
-
},
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-settings": {
|
|
94
|
-
"optional": true
|
|
95
|
-
},
|
|
96
|
-
"@deepseek-ai/dsh-compaction-basic": {
|
|
97
|
-
"optional": true
|
|
98
|
-
},
|
|
99
|
-
"@deepseek-ai/dsh-fs-local": {
|
|
100
|
-
"optional": true
|
|
101
|
-
},
|
|
102
|
-
"@deepseek-ai/dsh-fs-observation-policy": {
|
|
103
|
-
"optional": true
|
|
104
|
-
},
|
|
105
|
-
"@deepseek-ai/dsh-llm": {
|
|
106
|
-
"optional": true
|
|
107
|
-
},
|
|
108
|
-
"@deepseek-ai/dsh-llm-deepseek": {
|
|
109
|
-
"optional": true
|
|
110
|
-
},
|
|
111
|
-
"@deepseek-ai/dsh-sandbox-local": {
|
|
112
|
-
"optional": true
|
|
113
|
-
},
|
|
114
|
-
"@deepseek-ai/dsh-sandbox-policy": {
|
|
115
|
-
"optional": true
|
|
116
|
-
},
|
|
117
|
-
"@deepseek-ai/dsh-sdk-client": {
|
|
118
|
-
"optional": true
|
|
119
|
-
},
|
|
120
|
-
"@deepseek-ai/dsh-sdk-jsonrpc-server": {
|
|
121
|
-
"optional": true
|
|
122
|
-
},
|
|
123
|
-
"@deepseek-ai/dsh-sdk-minimal": {
|
|
124
|
-
"optional": true
|
|
125
|
-
},
|
|
126
|
-
"@deepseek-ai/dsh-session": {
|
|
127
|
-
"optional": true
|
|
128
|
-
},
|
|
129
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": {
|
|
130
|
-
"optional": true
|
|
131
|
-
},
|
|
132
|
-
"@deepseek-ai/dsh-subprocess-local": {
|
|
133
|
-
"optional": true
|
|
134
|
-
},
|
|
135
|
-
"@deepseek-ai/dsh-token-meter": {
|
|
136
|
-
"optional": true
|
|
137
|
-
},
|
|
138
|
-
"@deepseek-ai/dsh-tool-fs": {
|
|
139
|
-
"optional": true
|
|
140
|
-
},
|
|
141
|
-
"@deepseek-ai/dsh-tool-todo": {
|
|
142
|
-
"optional": true
|
|
143
|
-
},
|
|
144
|
-
"react": {
|
|
145
|
-
"optional": true
|
|
146
|
-
},
|
|
147
|
-
"react-dom": {
|
|
148
|
-
"optional": true
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
"devDependencies": {
|
|
152
|
-
"@deepseek-ai/dsh": "0.1.5-rc.2",
|
|
153
|
-
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
|
|
154
|
-
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
|
|
155
|
-
"@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
|
|
156
|
-
"@deepseek-ai/dsh-bash-local": "0.1.5-rc.2",
|
|
157
|
-
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
|
|
158
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
|
|
159
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
160
|
-
"@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.2",
|
|
161
|
-
"@deepseek-ai/dsh-fs-local": "0.1.5-rc.2",
|
|
162
|
-
"@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.2",
|
|
163
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
164
|
-
"@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.2",
|
|
165
|
-
"@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.2",
|
|
166
|
-
"@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
|
|
167
|
-
"@deepseek-ai/dsh-sdk-client": "0.1.5-rc.2",
|
|
168
|
-
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.5-rc.2",
|
|
169
|
-
"@deepseek-ai/dsh-sdk-minimal": "0.1.5-rc.2",
|
|
170
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
171
|
-
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.2",
|
|
172
|
-
"@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.2",
|
|
173
|
-
"@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
|
|
174
|
-
"@deepseek-ai/dsh-tool-fs": "0.1.5-rc.2",
|
|
175
|
-
"@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
|
|
176
|
-
"@types/react": "^18.3.0",
|
|
177
|
-
"react": "^18.3.1",
|
|
178
|
-
"react-dom": "^18.3.1",
|
|
179
|
-
"tsdown": "0.22.14",
|
|
180
|
-
"typescript": "^5.6.0"
|
|
181
|
-
},
|
|
182
|
-
"license": "MIT",
|
|
183
|
-
"repository": {
|
|
184
|
-
"type": "git",
|
|
185
|
-
"url": "git+https://github.com/Ran-sh/dsh-crew.git"
|
|
186
|
-
},
|
|
187
|
-
"homepage": "https://github.com/Ran-sh/dsh-crew",
|
|
188
|
-
"bugs": {
|
|
189
|
-
"url": "https://github.com/Ran-sh/dsh-crew/issues"
|
|
190
|
-
},
|
|
191
|
-
"keywords": [
|
|
192
|
-
"dsh",
|
|
193
|
-
"deepseek",
|
|
194
|
-
"claude-code",
|
|
195
|
-
"codex",
|
|
196
|
-
"zcode",
|
|
197
|
-
"windows",
|
|
198
|
-
"subagent",
|
|
199
|
-
"worker",
|
|
200
|
-
"multimodal",
|
|
201
|
-
"plugin",
|
|
202
|
-
"agent"
|
|
203
|
-
],
|
|
204
|
-
"files": [
|
|
205
|
-
"bin",
|
|
206
|
-
"lib",
|
|
207
|
-
"src",
|
|
208
|
-
"scripts",
|
|
209
|
-
"agents",
|
|
210
|
-
"commands",
|
|
211
|
-
"codex",
|
|
212
|
-
"zcode",
|
|
213
|
-
"
|
|
214
|
-
"
|
|
215
|
-
"
|
|
216
|
-
"
|
|
217
|
-
"
|
|
218
|
-
".
|
|
219
|
-
"
|
|
220
|
-
"README
|
|
221
|
-
"
|
|
222
|
-
"docs/
|
|
223
|
-
"docs/
|
|
224
|
-
"docs/
|
|
225
|
-
"docs/
|
|
226
|
-
"docs/
|
|
227
|
-
"docs/images/dsh-crew-
|
|
228
|
-
"docs/images/dsh-crew-
|
|
229
|
-
"docs/images/dsh-crew-
|
|
230
|
-
"
|
|
231
|
-
|
|
232
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@ran-sh/dsh-crew",
|
|
3
|
+
"version": "1.7.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/hub/entry.mjs",
|
|
6
|
+
"bin": {
|
|
7
|
+
"dsh-crew": "bin/dsh-crew.mjs"
|
|
8
|
+
},
|
|
9
|
+
"description": "DeepSeek Harness plugin: dispatch work to DSH agents from Claude Code / Codex, as native subagents with live progress",
|
|
10
|
+
"dshCrew": {
|
|
11
|
+
"payloadSchema": 2,
|
|
12
|
+
"windowsSupervisorHandoff": 1
|
|
13
|
+
},
|
|
14
|
+
"dsh": {
|
|
15
|
+
"bundle": {
|
|
16
|
+
"patch": "./cordis.patch.yml"
|
|
17
|
+
},
|
|
18
|
+
"client": {
|
|
19
|
+
"inject": [
|
|
20
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
21
|
+
"@deepseek-ai/dsh-client-locale",
|
|
22
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
23
|
+
],
|
|
24
|
+
"platform": "web"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"mcp": "node src/server.mjs",
|
|
29
|
+
"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 && tsdown 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 --no-clean --logLevel warn && node scripts/build-client.mjs",
|
|
30
|
+
"verify:npm-install": "node scripts/verify-npm-install.mjs",
|
|
31
|
+
"verify:npm-install:official": "node scripts/verify-npm-install.mjs --with-official-dsh",
|
|
32
|
+
"verify:official-bridge": "node scripts/verify-official-bridge-e2e.mjs --diagnostic-only"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.25.4",
|
|
36
|
+
"zod": "^3.24.0"
|
|
37
|
+
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": "./src/hub/entry.mjs",
|
|
40
|
+
"./client": "./lib/client.js",
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@deepseek-ai/dsh": "0.1.5-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-bash-local": "0.1.5-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-fs-local": "0.1.5-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-sdk-client": "0.1.5-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.5-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-sdk-minimal": "0.1.5-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-tool-fs": "0.1.5-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
|
|
68
|
+
"react": "^18.0.0",
|
|
69
|
+
"react-dom": "^18.0.0"
|
|
70
|
+
},
|
|
71
|
+
"peerDependenciesMeta": {
|
|
72
|
+
"@deepseek-ai/dsh": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@deepseek-ai/dsh-agent": {
|
|
76
|
+
"optional": true
|
|
77
|
+
},
|
|
78
|
+
"@deepseek-ai/dsh-agent-loop": {
|
|
79
|
+
"optional": true
|
|
80
|
+
},
|
|
81
|
+
"@deepseek-ai/dsh-agent-presets": {
|
|
82
|
+
"optional": true
|
|
83
|
+
},
|
|
84
|
+
"@deepseek-ai/dsh-bash-local": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"@deepseek-ai/dsh-client-locale": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-renderer": {
|
|
91
|
+
"optional": true
|
|
92
|
+
},
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-settings": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"@deepseek-ai/dsh-compaction-basic": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"@deepseek-ai/dsh-fs-local": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"@deepseek-ai/dsh-fs-observation-policy": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"@deepseek-ai/dsh-llm": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"@deepseek-ai/dsh-llm-deepseek": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
111
|
+
"@deepseek-ai/dsh-sandbox-local": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"@deepseek-ai/dsh-sandbox-policy": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
117
|
+
"@deepseek-ai/dsh-sdk-client": {
|
|
118
|
+
"optional": true
|
|
119
|
+
},
|
|
120
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": {
|
|
121
|
+
"optional": true
|
|
122
|
+
},
|
|
123
|
+
"@deepseek-ai/dsh-sdk-minimal": {
|
|
124
|
+
"optional": true
|
|
125
|
+
},
|
|
126
|
+
"@deepseek-ai/dsh-session": {
|
|
127
|
+
"optional": true
|
|
128
|
+
},
|
|
129
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": {
|
|
130
|
+
"optional": true
|
|
131
|
+
},
|
|
132
|
+
"@deepseek-ai/dsh-subprocess-local": {
|
|
133
|
+
"optional": true
|
|
134
|
+
},
|
|
135
|
+
"@deepseek-ai/dsh-token-meter": {
|
|
136
|
+
"optional": true
|
|
137
|
+
},
|
|
138
|
+
"@deepseek-ai/dsh-tool-fs": {
|
|
139
|
+
"optional": true
|
|
140
|
+
},
|
|
141
|
+
"@deepseek-ai/dsh-tool-todo": {
|
|
142
|
+
"optional": true
|
|
143
|
+
},
|
|
144
|
+
"react": {
|
|
145
|
+
"optional": true
|
|
146
|
+
},
|
|
147
|
+
"react-dom": {
|
|
148
|
+
"optional": true
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"devDependencies": {
|
|
152
|
+
"@deepseek-ai/dsh": "0.1.5-rc.2",
|
|
153
|
+
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
|
|
154
|
+
"@deepseek-ai/dsh-agent-loop": "0.1.5-rc.2",
|
|
155
|
+
"@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
|
|
156
|
+
"@deepseek-ai/dsh-bash-local": "0.1.5-rc.2",
|
|
157
|
+
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
|
|
158
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
|
|
159
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
160
|
+
"@deepseek-ai/dsh-compaction-basic": "0.1.5-rc.2",
|
|
161
|
+
"@deepseek-ai/dsh-fs-local": "0.1.5-rc.2",
|
|
162
|
+
"@deepseek-ai/dsh-fs-observation-policy": "0.1.5-rc.2",
|
|
163
|
+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
164
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.1.5-rc.2",
|
|
165
|
+
"@deepseek-ai/dsh-sandbox-local": "0.1.5-rc.2",
|
|
166
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
|
|
167
|
+
"@deepseek-ai/dsh-sdk-client": "0.1.5-rc.2",
|
|
168
|
+
"@deepseek-ai/dsh-sdk-jsonrpc-server": "0.1.5-rc.2",
|
|
169
|
+
"@deepseek-ai/dsh-sdk-minimal": "0.1.5-rc.2",
|
|
170
|
+
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
171
|
+
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.5-rc.2",
|
|
172
|
+
"@deepseek-ai/dsh-subprocess-local": "0.1.5-rc.2",
|
|
173
|
+
"@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
|
|
174
|
+
"@deepseek-ai/dsh-tool-fs": "0.1.5-rc.2",
|
|
175
|
+
"@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
|
|
176
|
+
"@types/react": "^18.3.0",
|
|
177
|
+
"react": "^18.3.1",
|
|
178
|
+
"react-dom": "^18.3.1",
|
|
179
|
+
"tsdown": "0.22.14",
|
|
180
|
+
"typescript": "^5.6.0"
|
|
181
|
+
},
|
|
182
|
+
"license": "MIT",
|
|
183
|
+
"repository": {
|
|
184
|
+
"type": "git",
|
|
185
|
+
"url": "git+https://github.com/Ran-sh/dsh-crew.git"
|
|
186
|
+
},
|
|
187
|
+
"homepage": "https://github.com/Ran-sh/dsh-crew",
|
|
188
|
+
"bugs": {
|
|
189
|
+
"url": "https://github.com/Ran-sh/dsh-crew/issues"
|
|
190
|
+
},
|
|
191
|
+
"keywords": [
|
|
192
|
+
"dsh",
|
|
193
|
+
"deepseek",
|
|
194
|
+
"claude-code",
|
|
195
|
+
"codex",
|
|
196
|
+
"zcode",
|
|
197
|
+
"windows",
|
|
198
|
+
"subagent",
|
|
199
|
+
"worker",
|
|
200
|
+
"multimodal",
|
|
201
|
+
"plugin",
|
|
202
|
+
"agent"
|
|
203
|
+
],
|
|
204
|
+
"files": [
|
|
205
|
+
"bin",
|
|
206
|
+
"lib",
|
|
207
|
+
"src",
|
|
208
|
+
"scripts",
|
|
209
|
+
"agents",
|
|
210
|
+
"commands",
|
|
211
|
+
"codex",
|
|
212
|
+
"zcode",
|
|
213
|
+
"skills",
|
|
214
|
+
"statusline",
|
|
215
|
+
"official-web-bridge",
|
|
216
|
+
"windows",
|
|
217
|
+
"cordis.patch.yml",
|
|
218
|
+
"worker.cordis.yml",
|
|
219
|
+
".claude-plugin",
|
|
220
|
+
"README.md",
|
|
221
|
+
"README.*.md",
|
|
222
|
+
"docs/job-contracts.md",
|
|
223
|
+
"docs/readiness-matrix.md",
|
|
224
|
+
"docs/gpt-relay-extension.md",
|
|
225
|
+
"docs/ui-surfaces.md",
|
|
226
|
+
"docs/installation.md",
|
|
227
|
+
"docs/images/dsh-crew-logo.png",
|
|
228
|
+
"docs/images/dsh-crew-overview.png",
|
|
229
|
+
"docs/images/dsh-crew-host.png",
|
|
230
|
+
"docs/images/dsh-crew-jobs.png",
|
|
231
|
+
"LICENSE"
|
|
232
|
+
]
|
|
233
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dsh-crew
|
|
3
|
+
description: "DSH Crew worker/reviewer dispatch (dsh-crew MCP tools): dispatch coding work, configure models and review gates, and maintain session history. Load only when the operator asks to use dsh-crew."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DSH Crew
|
|
7
|
+
|
|
8
|
+
**On demand only.** Do not dispatch Crew work because it might help — dispatch
|
|
9
|
+
because the operator asked for it in this turn ("use dsh-crew", "call dsh-crew",
|
|
10
|
+
"派给 crew", and the like). Crew is a capability the operator chooses, not a
|
|
11
|
+
standing policy, so nothing here should shape how you work until it is invoked.
|
|
12
|
+
That is the whole point of it living in a skill rather than in a global
|
|
13
|
+
instruction file: the host's own way of working stays untouched.
|
|
14
|
+
|
|
15
|
+
Once invoked, this is the operating guide.
|
|
16
|
+
|
|
17
|
+
## What it is
|
|
18
|
+
|
|
19
|
+
A plugin on the official DeepSeek Harness. A hub on 3210 dispatches jobs to
|
|
20
|
+
worker/reviewer models, optionally in an isolated git worktree, and returns a
|
|
21
|
+
compact structured result. Codex, ZCode and Claude Code all reach it through the
|
|
22
|
+
same `dsh-crew` MCP server, so the behaviour below is identical from any host.
|
|
23
|
+
|
|
24
|
+
## Tools
|
|
25
|
+
|
|
26
|
+
| Tool | Use |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `dsh_run_worker` | dispatch one unit and wait for the result |
|
|
29
|
+
| `dsh_spawn_worker` | dispatch and return a workflow id immediately |
|
|
30
|
+
| `dsh_worker_status` | list workflows with phase, role, model, tokens |
|
|
31
|
+
| `dsh_worker_result` | fetch or wait for one workflow (`wait_seconds`) |
|
|
32
|
+
| `dsh_worker_cancel` | cancel a workflow |
|
|
33
|
+
| `dsh_worker_config` | read/update session settings: enable dispatch, tier, effort, timeout, presets, policy |
|
|
34
|
+
|
|
35
|
+
`dsh_worker_config` with no arguments is the cheapest way to answer "what is
|
|
36
|
+
Crew set to right now". Its settings last for the session only; persisted
|
|
37
|
+
changes belong in the 3210 panel.
|
|
38
|
+
|
|
39
|
+
## Choosing what to dispatch
|
|
40
|
+
|
|
41
|
+
Delegate a bounded, independently verifiable unit when isolation,
|
|
42
|
+
specialization, parallel work or independent review earns its cost. Give each
|
|
43
|
+
unit its objective, owned files, workspace, constraints and acceptance
|
|
44
|
+
evidence. Keep ambiguity, integration, external effects and final communication
|
|
45
|
+
yourself. Trivial work stays local.
|
|
46
|
+
|
|
47
|
+
Continue authorized work after a successful subtask; a returned workflow is a
|
|
48
|
+
checkpoint, not the end of the task. If a worker's result is incomplete or its
|
|
49
|
+
review asks for changes, that is a task result to act on — not approval.
|
|
50
|
+
|
|
51
|
+
## Configuration
|
|
52
|
+
|
|
53
|
+
Two surfaces, and they are not equivalent:
|
|
54
|
+
|
|
55
|
+
- **3210** — the full control plane: workflow, model priority, routing, provider
|
|
56
|
+
lifecycle, history, and the peak/off-peak schedule.
|
|
57
|
+
- **3080** — the quick surface (sub-agent switch, model priority order). It
|
|
58
|
+
writes through the same config via a restricted key allowlist.
|
|
59
|
+
|
|
60
|
+
Everything lands in `~/.config/dsh-crew/config.json`. Prefer the panel over hand
|
|
61
|
+
editing: the write path validates, and a hand edit can be silently dropped by
|
|
62
|
+
the loader.
|
|
63
|
+
|
|
64
|
+
## Model routing
|
|
65
|
+
|
|
66
|
+
Worker and reviewer each walk an ordered `{provider, model}` priority list and
|
|
67
|
+
take the first admissible candidate; an empty list falls through to Harness
|
|
68
|
+
Default. Candidates are skipped when the provider is unhealthy, tombstoned, or
|
|
69
|
+
inside a peak window it is blocked for. A `warn` rule keeps the model selectable
|
|
70
|
+
and records the advisory in the selection trace.
|
|
71
|
+
|
|
72
|
+
The **peak/off-peak schedule** (panel → 波峰波谷调度) restricts chosen models by
|
|
73
|
+
local wall clock: `block` skips the model during peak so the next candidate
|
|
74
|
+
serves the job, `warn` uses it and flags the choice, and an unlisted model is
|
|
75
|
+
unrestricted. Defaults mirror DeepSeek's published peak hours.
|
|
76
|
+
|
|
77
|
+
## Work
|
|
78
|
+
|
|
79
|
+
`isolation: worktree` is the default: a coding worker runs in a per-job git
|
|
80
|
+
worktree and the primary tree is untouched. Non-git workspaces fail with
|
|
81
|
+
`NOT_GIT_REPOSITORY` rather than silently sharing the tree; use `shared`
|
|
82
|
+
explicitly if that is what you want. Concurrent jobs are capped by
|
|
83
|
+
`max_parallel`.
|
|
84
|
+
|
|
85
|
+
The reviewer gate is `required` by default: an unreviewed change fails. Review
|
|
86
|
+
findings and failing tests are results to address, never a reason to bypass the
|
|
87
|
+
gate.
|
|
88
|
+
|
|
89
|
+
## History
|
|
90
|
+
|
|
91
|
+
Session storage is shared between 3080 and 3210 — clearing one clears both.
|
|
92
|
+
Cleanup is scoped by provenance, and the default scope is **Crew-created only**,
|
|
93
|
+
so the operator's own conversations survive. `all` removes theirs too; use it
|
|
94
|
+
deliberately. Archived batches are restorable from the panel.
|
|
95
|
+
|
|
96
|
+
## When Crew is unavailable
|
|
97
|
+
|
|
98
|
+
If a capability needed by a work unit you already dispatched becomes unavailable
|
|
99
|
+
or non-callable, **stop and ask**. Do not implement further on that unit, do not
|
|
100
|
+
repair or reconfigure Crew, do not silently fall back to doing it yourself.
|
|
101
|
+
Perform bounded read-only diagnosis, report the evidence and what already
|
|
102
|
+
completed, and wait for the operator to choose: repair Crew and continue through
|
|
103
|
+
it, or leave Crew alone and continue with the host agent.
|
|
104
|
+
|
|
105
|
+
A nonterminal wait is not an outage — keep polling the same workflow rather than
|
|
106
|
+
dispatching a duplicate. This gate applies only once Crew has been selected for
|
|
107
|
+
a work unit; it does not apply when planning chose local work.
|
|
108
|
+
|
|
109
|
+
## Host boundaries
|
|
110
|
+
|
|
111
|
+
- Never install, update, register, unlink, repair or mutate anything under
|
|
112
|
+
`~/.dsh`. Crew's runtime lives in its own `DSH_HOME`.
|
|
113
|
+
- Runtime upgrades go through the Crew-owned installer (`dsh-crew update`), never
|
|
114
|
+
through direct pnpm/npm/dsh plugin operations.
|
|
115
|
+
- Preparing an upgrade must not restart 3080 or 3210.
|
|
116
|
+
- The legacy 3080 bridge must never be used for 3210 lifecycle or rollback.
|
|
117
|
+
- Delegation grants no new authority: pushing, publishing, messaging, changing
|
|
118
|
+
credentials or deleting data still need their own authorization.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// On-demand Crew guidance, installed as a user skill.
|
|
2
|
+
//
|
|
3
|
+
// Crew used to inject a "capability-aware delegation policy" block into the
|
|
4
|
+
// host's global instruction file. That made every host session — Codex, ZCode —
|
|
5
|
+
// carry Crew's delegation rules whether or not the operator wanted Crew that
|
|
6
|
+
// turn, which shapes how the host does its own work.
|
|
7
|
+
//
|
|
8
|
+
// The guidance now lives in a skill instead, loaded only when the operator asks
|
|
9
|
+
// for Crew. Nothing about the host's default behaviour changes; the knowledge is
|
|
10
|
+
// there the moment it is wanted.
|
|
11
|
+
//
|
|
12
|
+
// Each host reads its own skill directory, so the skill is copied to all of them
|
|
13
|
+
// — the same layout the Oracle skill uses, plus the shared `~/.agents/skills`
|
|
14
|
+
// that ZCode reads. Installing a skill replaces writing a policy block, so the
|
|
15
|
+
// host installers also *remove* any block a previous release left behind.
|
|
16
|
+
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
19
|
+
import { dirname, join, resolve } from 'node:path';
|
|
20
|
+
|
|
21
|
+
export const CREW_SKILL_NAME = 'dsh-crew';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Skill roots, in the order they are installed. `.agents/skills` is the shared
|
|
25
|
+
* directory ZCode reads; the other two are what Codex and Claude Code read. The
|
|
26
|
+
* Codex one is resolved through `CODEX_HOME` because Codex may point elsewhere —
|
|
27
|
+
// writing only to `~/.codex` would put the skill where Codex never looks.
|
|
28
|
+
*/
|
|
29
|
+
export function crewSkillRoots({ home = homedir(), env = process.env } = {}) {
|
|
30
|
+
const codexHome = typeof env?.CODEX_HOME === 'string' && env.CODEX_HOME.trim()
|
|
31
|
+
? resolve(env.CODEX_HOME.trim())
|
|
32
|
+
: join(home, '.codex');
|
|
33
|
+
return [
|
|
34
|
+
join(home, '.agents', 'skills'),
|
|
35
|
+
join(codexHome, 'skills'),
|
|
36
|
+
join(home, '.claude', 'skills'),
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function crewSkillFiles({ home = homedir(), env = process.env } = {}) {
|
|
41
|
+
return crewSkillRoots({ home, env }).map((root) => join(root, CREW_SKILL_NAME, 'SKILL.md'));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The skill template shipped in the payload. */
|
|
45
|
+
export function crewSkillSource({ root }) {
|
|
46
|
+
return join(root, 'skills', CREW_SKILL_NAME, 'SKILL.md');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function readCrewSkill({ root }) {
|
|
50
|
+
const file = crewSkillSource({ root });
|
|
51
|
+
return existsSync(file) ? readFileSync(file, 'utf8') : null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Copy the skill template into every host skill directory. Idempotent: a file
|
|
56
|
+
* that already matches is left alone, so a repeat install stays quiet.
|
|
57
|
+
*/
|
|
58
|
+
export function installCrewSkill({ home = homedir(), root, env = process.env } = {}) {
|
|
59
|
+
if (!root) return { ok: false, code: 'CREW_SKILL_SOURCE_REQUIRED' };
|
|
60
|
+
const content = readCrewSkill({ root });
|
|
61
|
+
if (content === null) return { ok: false, code: 'CREW_SKILL_TEMPLATE_MISSING', source: crewSkillSource({ root }) };
|
|
62
|
+
const written = [];
|
|
63
|
+
const files = crewSkillFiles({ home, env });
|
|
64
|
+
for (const file of files) {
|
|
65
|
+
let current = null;
|
|
66
|
+
try { current = readFileSync(file, 'utf8'); } catch { /* absent or unreadable */ }
|
|
67
|
+
if (current === content) continue;
|
|
68
|
+
try {
|
|
69
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
70
|
+
writeFileSync(file, content);
|
|
71
|
+
written.push(file);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
return { ok: false, code: 'CREW_SKILL_WRITE_FAILED', file, error: String(error?.message ?? error) };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { ok: true, changed: written.length > 0, written, files, file: files[0] };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Remove the installed skill from every host directory. Only Crew's own skill
|
|
81
|
+
* folder is touched, so a user's other skills are never affected.
|
|
82
|
+
*/
|
|
83
|
+
export function removeCrewSkill({ home = homedir(), env = process.env } = {}) {
|
|
84
|
+
const removed = [];
|
|
85
|
+
for (const dir of crewSkillRoots({ home, env }).map((root) => join(root, CREW_SKILL_NAME))) {
|
|
86
|
+
if (!existsSync(dir)) continue;
|
|
87
|
+
try { rmSync(dir, { recursive: true, force: true }); removed.push(dir); }
|
|
88
|
+
catch { /* best effort: a locked file is not worth failing an uninstall */ }
|
|
89
|
+
}
|
|
90
|
+
return { ok: true, changed: removed.length > 0, removed, file: removed[0] ?? null };
|
|
91
|
+
}
|
|
@@ -7,7 +7,8 @@ import { createHash } from 'node:crypto';
|
|
|
7
7
|
import { dirname, join, resolve, relative } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { homedir } from 'node:os';
|
|
10
|
-
import { normalizeModelPriority } from '../model-routing.mjs';
|
|
10
|
+
import { normalizeModelPriority } from '../model-routing.mjs';
|
|
11
|
+
import { crewSkillFiles, installCrewSkill, readCrewSkill, removeCrewSkill } from './crew-skill.mjs';
|
|
11
12
|
import { zcodeStatus } from './zcode.mjs';
|
|
12
13
|
|
|
13
14
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
@@ -94,32 +95,13 @@ export function stripKnownLegacyCodexPolicy(text, { knownHashes = CODEX_LEGACY_P
|
|
|
94
95
|
return `${keptPrefix}${match[0]}${keptSuffix}`;
|
|
95
96
|
}
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const managed = new RegExp(`${POLICY_START.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[\\s\\S]*?${POLICY_END.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`, 'm');
|
|
104
|
-
const template = readText(join(root, 'codex', 'AGENTS.md'))?.trim() ?? '';
|
|
105
|
-
let next;
|
|
106
|
-
if (managed.test(current)) next = current.replace(managed, block);
|
|
107
|
-
else if (current.trim() === template) next = `${block}\n`;
|
|
108
|
-
else next = `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${block}\n`;
|
|
109
|
-
next = stripKnownLegacyCodexPolicy(next);
|
|
110
|
-
if (next !== current) {
|
|
111
|
-
backup(file);
|
|
112
|
-
writeFileSync(file, next);
|
|
113
|
-
}
|
|
114
|
-
return { ok: true, action: `global policy: ${file}` };
|
|
98
|
+
/** The installed skill is present and still matches the payload template. */
|
|
99
|
+
function crewSkillInstalled({ home, root, env = process.env }) {
|
|
100
|
+
const expected = readCrewSkill({ root });
|
|
101
|
+
if (expected === null) return false;
|
|
102
|
+
// Every host directory must hold the current template, not just the first.
|
|
103
|
+
return crewSkillFiles({ home, env }).every((file) => readText(file) === expected);
|
|
115
104
|
}
|
|
116
|
-
|
|
117
|
-
function globalCodexPolicyReady({ home, root = ROOT, env = process.env }) {
|
|
118
|
-
const block = managedPolicyBlock(root);
|
|
119
|
-
const text = readText(join(codexHomeDir(home, env), 'AGENTS.md'));
|
|
120
|
-
return !!block && typeof text === 'string' && text.includes(block);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
105
|
function uninstallGlobalCodexPolicy({ home, env = process.env }) {
|
|
124
106
|
const file = join(codexHomeDir(home, env), 'AGENTS.md');
|
|
125
107
|
const current = readText(file);
|
|
@@ -432,7 +414,7 @@ export function installStatus({ home = homedir(), root = ROOT, env = process.env
|
|
|
432
414
|
status_prompt: expectedStatusPrompt !== null && readText(join(codexRoot, 'prompts', 'dsh-status.md')) === expectedStatusPrompt,
|
|
433
415
|
mcp: !!expectedTarget && mcpTarget === expectedTarget,
|
|
434
416
|
target_alignment: !!expectedTarget && workerTarget === expectedTarget && reviewerTarget === expectedTarget && mcpTarget === expectedTarget,
|
|
435
|
-
|
|
417
|
+
skill: crewSkillInstalled({ home, root, env }),
|
|
436
418
|
};
|
|
437
419
|
const codexInstalled = Object.values(components).some(Boolean)
|
|
438
420
|
|| existsSync(join(codexRoot, 'agents', 'ds-flash.toml'))
|
|
@@ -466,6 +448,8 @@ export function uninstallCodex({ home = homedir(), env = process.env } = {}) {
|
|
|
466
448
|
}
|
|
467
449
|
const policyAction = uninstallGlobalCodexPolicy({ home, env });
|
|
468
450
|
if (policyAction) actions.push(policyAction);
|
|
451
|
+
const skillAction = removeCrewSkill({ home, env });
|
|
452
|
+
if (skillAction.changed) actions.push(...skillAction.removed.map((dir) => `removed: ${dir}`));
|
|
469
453
|
// Remove only the dsh-crew entry from [mcp_servers], keeping any other
|
|
470
454
|
// MCP servers the user configured.
|
|
471
455
|
const configFile = join(codexHomeDir(home, env), 'config.toml');
|
|
@@ -622,9 +606,15 @@ export function installCodex({ home = homedir(), scope, root = ROOT, env = proce
|
|
|
622
606
|
if (scope !== 'project') {
|
|
623
607
|
const act = writeGlobalCodexMcpServer(home, renderedPath, env);
|
|
624
608
|
actions.push(...act);
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
609
|
+
// Crew guidance is a skill now, loaded only when the operator asks for it.
|
|
610
|
+
// Removing the policy block here cleans up what an earlier release put in
|
|
611
|
+
// the host instruction file; ignoring the result keeps the first install on
|
|
612
|
+
// a machine that never had one quiet.
|
|
613
|
+
const droppedPolicy = uninstallGlobalCodexPolicy({ home, env });
|
|
614
|
+
if (droppedPolicy) actions.push(`removed delegating policy block: ${join(codexHomeDir(home, env), 'AGENTS.md')}`);
|
|
615
|
+
const skill = installCrewSkill({ home, root, env });
|
|
616
|
+
if (!skill.ok) return { ok: false, actions: [...actions, `crew skill: ${skill.code}`] };
|
|
617
|
+
actions.push(...skill.written.map((file) => `skill: ${file}`));
|
|
628
618
|
}
|
|
629
619
|
return { ok: true, actions };
|
|
630
620
|
}
|
package/src/install/zcode.mjs
CHANGED
|
@@ -9,6 +9,8 @@ import { dirname, join, resolve } from 'node:path';
|
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
import { homedir } from 'node:os';
|
|
11
11
|
|
|
12
|
+
import { crewSkillFiles, installCrewSkill, readCrewSkill, removeCrewSkill } from './crew-skill.mjs';
|
|
13
|
+
|
|
12
14
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
13
15
|
const HOST = 'zcode';
|
|
14
16
|
const SERVER = 'dsh-crew';
|
|
@@ -103,27 +105,6 @@ function expectedTarget({ root = ROOT } = {}) {
|
|
|
103
105
|
return resolve(join(root, 'src', 'server.mjs'));
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
function managedPolicyBlock(root) {
|
|
107
|
-
const template = readText(join(root, 'zcode', 'AGENTS.md'))?.trim();
|
|
108
|
-
return template ? `${POLICY_START}\n${template}\n${POLICY_END}` : null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function installPolicy({ home, root }) {
|
|
112
|
-
const file = join(home, '.zcode', 'AGENTS.md');
|
|
113
|
-
const block = managedPolicyBlock(root);
|
|
114
|
-
if (!block) return { ok: false, code: 'ZCODE_POLICY_TEMPLATE_MISSING' };
|
|
115
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
116
|
-
const current = readText(file) ?? '';
|
|
117
|
-
const escapedStart = POLICY_START.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
118
|
-
const escapedEnd = POLICY_END.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
119
|
-
const managed = new RegExp(`${escapedStart}[\\s\\S]*?${escapedEnd}`, 'm');
|
|
120
|
-
const next = managed.test(current)
|
|
121
|
-
? current.replace(managed, block)
|
|
122
|
-
: `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${block}\n`;
|
|
123
|
-
if (next !== current) { backup(file); writeFileSync(file, next); }
|
|
124
|
-
return { ok: true, file };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
108
|
function removePolicy({ home }) {
|
|
128
109
|
const file = join(home, '.zcode', 'AGENTS.md');
|
|
129
110
|
const current = readText(file);
|
|
@@ -277,7 +258,8 @@ function updateMcp({ home, root }) {
|
|
|
277
258
|
return { ok: true, changed, config_file: source.file, config_kind: source.kind, target };
|
|
278
259
|
}
|
|
279
260
|
|
|
280
|
-
export function installZCode({ home = homedir(), root = ROOT } = {}) {
|
|
261
|
+
export function installZCode({ home = homedir(), root = ROOT, env = process.env } = {}) {
|
|
262
|
+
const actions = [];
|
|
281
263
|
const templates = templateFiles({ home, root });
|
|
282
264
|
const missing = templates.find(({ source }) => !existsSync(source));
|
|
283
265
|
if (missing) return { ok: false, code: 'ZCODE_TEMPLATE_MISSING', source: missing.source };
|
|
@@ -287,8 +269,14 @@ export function installZCode({ home = homedir(), root = ROOT } = {}) {
|
|
|
287
269
|
// failed install is transaction-like and leaves user files untouched.
|
|
288
270
|
const mcp = updateMcp({ home, root });
|
|
289
271
|
if (!mcp.ok) return mcp;
|
|
290
|
-
|
|
291
|
-
|
|
272
|
+
// Crew guidance is a skill now, loaded only when the operator asks for it.
|
|
273
|
+
// The removal cleans up the policy block an earlier release wrote into the
|
|
274
|
+
// host instruction file; ignoring its result keeps a first install quiet.
|
|
275
|
+
const droppedPolicy = removePolicy({ home });
|
|
276
|
+
if (droppedPolicy) actions.push('policy: removed managed ZCode block');
|
|
277
|
+
const skill = installCrewSkill({ home, root, env });
|
|
278
|
+
if (!skill.ok) return { ok: false, code: skill.code, source: skill.source };
|
|
279
|
+
actions.push(...skill.written.map((file) => `skill: ${file}`));
|
|
292
280
|
const installed = installTemplates({ home, root, priorFiles });
|
|
293
281
|
if (!installed.ok) return installed;
|
|
294
282
|
cleanupPriorMcpSources({ owned: previousOwnership, exceptFile: mcp.config_file });
|
|
@@ -303,16 +291,20 @@ export function installZCode({ home = homedir(), root = ROOT } = {}) {
|
|
|
303
291
|
files: installed.records,
|
|
304
292
|
configFiles: [currentSourceRecord, ...priorSourceRecords],
|
|
305
293
|
});
|
|
306
|
-
return { ok: true, ...mcp,
|
|
294
|
+
return { ok: true, ...mcp, skill_files: skill.written, files: installed.actions };
|
|
307
295
|
}
|
|
308
296
|
|
|
309
|
-
function zcodeComponents({ home = homedir(), root = ROOT } = {}) {
|
|
297
|
+
function zcodeComponents({ home = homedir(), root = ROOT, env = process.env } = {}) {
|
|
310
298
|
const expected = normalizePath(expectedTarget({ root }));
|
|
311
299
|
const source = configSource({ home });
|
|
312
300
|
const configured = serverTarget(source.servers[SERVER]);
|
|
313
301
|
const owned = ownership({ home });
|
|
314
|
-
|
|
315
|
-
|
|
302
|
+
// The guidance is a skill now; a policy block in the host instruction file is
|
|
303
|
+
// no longer written and no longer part of readiness.
|
|
304
|
+
const expectedSkill = readCrewSkill({ root });
|
|
305
|
+
// A block written by an earlier release still counts as an installed
|
|
306
|
+
// footprint, so uninstall knows there is something of ours to clean up.
|
|
307
|
+
const legacyPolicyText = readText(join(home, '.zcode', 'AGENTS.md'));
|
|
316
308
|
const templates = templateFiles({ home, root });
|
|
317
309
|
const templateReady = (entry) => {
|
|
318
310
|
if (!entry) return false;
|
|
@@ -335,7 +327,7 @@ function zcodeComponents({ home = homedir(), root = ROOT } = {}) {
|
|
|
335
327
|
});
|
|
336
328
|
const components = {
|
|
337
329
|
mcp: configured === expected,
|
|
338
|
-
|
|
330
|
+
skill: expectedSkill !== null && readText(crewSkillFiles({ home, env })[0]) === expectedSkill,
|
|
339
331
|
worker_agent: templateReady(templateBySuffix(join('agents', 'ds-worker.md'))),
|
|
340
332
|
reviewer_agent: templateReady(templateBySuffix(join('agents', 'ds-reviewer.md'))),
|
|
341
333
|
config_prompt: templateReady(templateBySuffix(join('commands', 'dsh-config.md'))),
|
|
@@ -345,9 +337,9 @@ function zcodeComponents({ home = homedir(), root = ROOT } = {}) {
|
|
|
345
337
|
&& normalizePath(owned.target) === expected
|
|
346
338
|
&& ownershipFilesReady,
|
|
347
339
|
};
|
|
348
|
-
const policyFootprint = typeof
|
|
349
|
-
&&
|
|
350
|
-
&&
|
|
340
|
+
const policyFootprint = typeof legacyPolicyText === 'string'
|
|
341
|
+
&& legacyPolicyText.includes(POLICY_START)
|
|
342
|
+
&& legacyPolicyText.includes(POLICY_END);
|
|
351
343
|
const installed = Object.hasOwn(source.servers, SERVER)
|
|
352
344
|
|| !!owned
|
|
353
345
|
|| policyFootprint
|
|
@@ -355,8 +347,8 @@ function zcodeComponents({ home = homedir(), root = ROOT } = {}) {
|
|
|
355
347
|
return { components, source, expected, configured, owned, installed };
|
|
356
348
|
}
|
|
357
349
|
|
|
358
|
-
export function zcodeStatus({ home = homedir(), root = ROOT } = {}) {
|
|
359
|
-
const { components, source, expected, configured, installed } = zcodeComponents({ home, root });
|
|
350
|
+
export function zcodeStatus({ home = homedir(), root = ROOT, env = process.env } = {}) {
|
|
351
|
+
const { components, source, expected, configured, installed } = zcodeComponents({ home, root, env });
|
|
360
352
|
const missing = Object.entries(components).filter(([, value]) => !value).map(([key]) => key);
|
|
361
353
|
return {
|
|
362
354
|
installed,
|
|
@@ -369,7 +361,7 @@ export function zcodeStatus({ home = homedir(), root = ROOT } = {}) {
|
|
|
369
361
|
};
|
|
370
362
|
}
|
|
371
363
|
|
|
372
|
-
export function uninstallZCode({ home = homedir() } = {}) {
|
|
364
|
+
export function uninstallZCode({ home = homedir(), env = process.env } = {}) {
|
|
373
365
|
const actions = [];
|
|
374
366
|
const owned = ownership({ home });
|
|
375
367
|
if (owned) {
|
|
@@ -381,6 +373,8 @@ export function uninstallZCode({ home = homedir() } = {}) {
|
|
|
381
373
|
rmSync(OWNERSHIP_FILE({ home }), { force: true });
|
|
382
374
|
}
|
|
383
375
|
if (removePolicy({ home })) actions.push('policy: removed managed ZCode block');
|
|
376
|
+
const skillAction = removeCrewSkill({ home, env });
|
|
377
|
+
if (skillAction.changed) actions.push(...skillAction.removed.map((dir) => `removed: ${dir}`));
|
|
384
378
|
const managedFiles = Array.isArray(owned?.files) && owned.files.length
|
|
385
379
|
? owned.files
|
|
386
380
|
: ['agents/ds-worker.md', 'agents/ds-reviewer.md', 'commands/dsh-config.md', 'commands/dsh-status.md']
|
package/src/runtime-identity.mjs
CHANGED
|
@@ -36,7 +36,7 @@ export {
|
|
|
36
36
|
// included in the identity contract.
|
|
37
37
|
const RUNTIME_ID = randomUUID();
|
|
38
38
|
|
|
39
|
-
export const RUNTIME_VERSION = '1.
|
|
39
|
+
export const RUNTIME_VERSION = '1.7.1';
|
|
40
40
|
export const HUB_PROTOCOL_VERSION = 1;
|
|
41
41
|
|
|
42
42
|
export const HUB_CAPABILITIES = Object.freeze([
|