dsh-env-manager-plugin 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +273 -3
- package/client.js +2581 -0
- package/cordis.patch.yml +4 -0
- package/docs/00-project/current-state.md +272 -0
- package/docs/00-project/glossary.md +215 -0
- package/docs/00-project/project-brief.md +114 -0
- package/docs/00-project/roadmap.md +89 -0
- package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -0
- package/docs/01-architecture/api-verification.md +416 -0
- package/docs/01-architecture/architecture-overview.md +222 -0
- package/docs/01-architecture/data-model.md +930 -0
- package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -0
- package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -0
- package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -0
- package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -0
- package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -0
- package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -0
- package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -0
- package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -0
- package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -0
- package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -0
- package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -0
- package/docs/01-architecture/design.md +666 -0
- package/docs/01-architecture/detailed-design.md +961 -0
- package/docs/01-architecture/implementation-plan.md +323 -0
- package/docs/01-architecture/module-boundaries.md +306 -0
- package/docs/01-architecture/security-model.md +227 -0
- package/docs/01-architecture/storage-contract.md +224 -0
- package/docs/01-architecture/tool-contract.md +438 -0
- package/docs/01-architecture/ui-design.md +587 -0
- package/docs/02-harness/agent-behavior.md +36 -0
- package/docs/02-harness/change-snapshot-policy.md +29 -0
- package/docs/02-harness/client-ui-integration.md +110 -0
- package/docs/02-harness/context-policy.md +43 -0
- package/docs/02-harness/harness-standard.md +91 -0
- package/docs/02-harness/task-execution-policy.md +26 -0
- package/docs/02-harness/verification-policy.md +97 -0
- package/docs/03-openspec/archive-rule.md +25 -0
- package/docs/03-openspec/bugfix-rule.md +30 -0
- package/docs/03-openspec/design-rule.md +33 -0
- package/docs/03-openspec/openspec-usage-guide.md +31 -0
- package/docs/03-openspec/proposal-rule.md +70 -0
- package/docs/03-openspec/spec-rule.md +33 -0
- package/docs/03-openspec/tasks-rule.md +31 -0
- package/docs/04-development/coding-style.md +67 -0
- package/docs/04-development/dependency-policy.md +43 -0
- package/docs/04-development/development-guide.md +85 -0
- package/docs/04-development/directory-convention.md +105 -0
- package/docs/04-development/local-run-guide.md +61 -0
- package/docs/04-development/testing-guide.md +102 -0
- package/docs/05-domain/deployment-template.md +76 -0
- package/docs/05-domain/environment-template.md +165 -0
- package/docs/05-domain/operation-binding-template.md +55 -0
- package/docs/05-domain/operation-record-template.md +55 -0
- package/docs/05-domain/prompt-template.md +90 -0
- package/docs/05-domain/rule-template.md +73 -0
- package/docs/05-domain/service-template.md +39 -0
- package/docs/06-operations/deployment-guide.md +54 -0
- package/docs/06-operations/release.md +198 -0
- package/docs/06-operations/security-policy.md +53 -0
- package/docs/06-operations/troubleshooting.md +141 -0
- package/docs/07-templates/adr-template.md +21 -0
- package/docs/07-templates/bugfix-template.md +11 -0
- package/docs/07-templates/case-template.md +15 -0
- package/docs/07-templates/design-template.md +29 -0
- package/docs/07-templates/proposal-template.md +19 -0
- package/docs/07-templates/spec-template.md +15 -0
- package/docs/07-templates/tasks-template.md +12 -0
- package/docs/99-archive/README.md +13 -0
- package/docs/README.md +142 -0
- package/icon.svg +4 -0
- package/index.js +31 -0
- package/lib/app/app.d.ts +67 -0
- package/lib/app/app.js +494 -0
- package/lib/app/app.js.map +1 -0
- package/lib/config.d.ts +55 -0
- package/lib/config.js +42 -0
- package/lib/config.js.map +1 -0
- package/lib/domain/constants.d.ts +21 -0
- package/lib/domain/constants.js +59 -0
- package/lib/domain/constants.js.map +1 -0
- package/lib/domain/errors.d.ts +20 -0
- package/lib/domain/errors.js +22 -0
- package/lib/domain/errors.js.map +1 -0
- package/lib/domain/schemas.d.ts +28 -0
- package/lib/domain/schemas.js +445 -0
- package/lib/domain/schemas.js.map +1 -0
- package/lib/domain/types.d.ts +412 -0
- package/lib/domain/types.js +2 -0
- package/lib/domain/types.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +89 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +8 -0
- package/lib/logger.js +13 -0
- package/lib/logger.js.map +1 -0
- package/lib/memory/bridge.d.ts +18 -0
- package/lib/memory/bridge.js +13 -0
- package/lib/memory/bridge.js.map +1 -0
- package/lib/registry/integrity.d.ts +10 -0
- package/lib/registry/integrity.js +204 -0
- package/lib/registry/integrity.js.map +1 -0
- package/lib/registry/registry.d.ts +14 -0
- package/lib/registry/registry.js +182 -0
- package/lib/registry/registry.js.map +1 -0
- package/lib/resolver/merge.d.ts +23 -0
- package/lib/resolver/merge.js +90 -0
- package/lib/resolver/merge.js.map +1 -0
- package/lib/resolver/resolve.d.ts +18 -0
- package/lib/resolver/resolve.js +288 -0
- package/lib/resolver/resolve.js.map +1 -0
- package/lib/resolver/template.d.ts +10 -0
- package/lib/resolver/template.js +42 -0
- package/lib/resolver/template.js.map +1 -0
- package/lib/router/params.d.ts +3 -0
- package/lib/router/params.js +83 -0
- package/lib/router/params.js.map +1 -0
- package/lib/router/router.d.ts +11 -0
- package/lib/router/router.js +204 -0
- package/lib/router/router.js.map +1 -0
- package/lib/session/session.d.ts +16 -0
- package/lib/session/session.js +64 -0
- package/lib/session/session.js.map +1 -0
- package/lib/skill.d.ts +17 -0
- package/lib/skill.js +56 -0
- package/lib/skill.js.map +1 -0
- package/lib/storage/atomic.d.ts +10 -0
- package/lib/storage/atomic.js +107 -0
- package/lib/storage/atomic.js.map +1 -0
- package/lib/storage/paths.d.ts +10 -0
- package/lib/storage/paths.js +50 -0
- package/lib/storage/paths.js.map +1 -0
- package/lib/storage/records.d.ts +16 -0
- package/lib/storage/records.js +112 -0
- package/lib/storage/records.js.map +1 -0
- package/lib/storage/sessions.d.ts +17 -0
- package/lib/storage/sessions.js +65 -0
- package/lib/storage/sessions.js.map +1 -0
- package/lib/tools/tools.d.ts +14 -0
- package/lib/tools/tools.js +472 -0
- package/lib/tools/tools.js.map +1 -0
- package/lib/transport/http.d.ts +3 -0
- package/lib/transport/http.js +217 -0
- package/lib/transport/http.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +101 -6
- package/scripts/repair-profile.mjs +141 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { EnvManagerError } from '../domain/errors.js';
|
|
2
|
+
import { isRecordKind } from '../domain/constants.js';
|
|
3
|
+
const MAX_BODY = 2 * 1024 * 1024;
|
|
4
|
+
function statusFor(code) {
|
|
5
|
+
switch (code) {
|
|
6
|
+
case 'FORBIDDEN':
|
|
7
|
+
return 403;
|
|
8
|
+
case 'ENV_NOT_FOUND':
|
|
9
|
+
case 'SERVICE_NOT_FOUND':
|
|
10
|
+
case 'DEPLOYMENT_NOT_FOUND':
|
|
11
|
+
case 'RULE_PROFILE_NOT_FOUND':
|
|
12
|
+
case 'BINDING_NOT_FOUND':
|
|
13
|
+
case 'HOST_NOT_FOUND':
|
|
14
|
+
case 'CLUSTER_NOT_FOUND':
|
|
15
|
+
return 404;
|
|
16
|
+
case 'RECORD_IN_USE':
|
|
17
|
+
case 'BINDING_CONFLICT':
|
|
18
|
+
case 'DEPLOYMENT_AMBIGUOUS':
|
|
19
|
+
case 'DUPLICATE_ID':
|
|
20
|
+
return 409;
|
|
21
|
+
case 'RECORD_TOO_LARGE':
|
|
22
|
+
return 413;
|
|
23
|
+
case 'POLICY_DENIED':
|
|
24
|
+
return 403;
|
|
25
|
+
case 'CREDENTIAL_UNAVAILABLE':
|
|
26
|
+
return 503;
|
|
27
|
+
case 'INVALID_ARGUMENT':
|
|
28
|
+
case 'RECORD_INVALID':
|
|
29
|
+
case 'RULE_TEMPLATE_INVALID':
|
|
30
|
+
case 'RULE_UNDEFINED_VARIABLE':
|
|
31
|
+
case 'RULE_CYCLE':
|
|
32
|
+
case 'RULE_PATH_TRAVERSAL':
|
|
33
|
+
case 'PARAMETER_RESOLUTION_FAILED':
|
|
34
|
+
case 'SKILL_UNAVAILABLE':
|
|
35
|
+
return 400;
|
|
36
|
+
case 'INTERNAL_ERROR':
|
|
37
|
+
case 'STORAGE_UNWRITABLE':
|
|
38
|
+
return 500;
|
|
39
|
+
default:
|
|
40
|
+
return 500;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function readBody(req) {
|
|
44
|
+
return await new Promise((resolve, reject) => {
|
|
45
|
+
let size = 0;
|
|
46
|
+
const chunks = [];
|
|
47
|
+
req.on('data', (chunk) => {
|
|
48
|
+
size += chunk.length;
|
|
49
|
+
if (size > MAX_BODY) {
|
|
50
|
+
reject(new EnvManagerError('RECORD_TOO_LARGE', 'Request body exceeds 2 MiB'));
|
|
51
|
+
req.destroy();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
chunks.push(chunk);
|
|
55
|
+
});
|
|
56
|
+
req.on('end', () => {
|
|
57
|
+
try {
|
|
58
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
59
|
+
resolve(text ? JSON.parse(text) : {});
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
reject(new EnvManagerError('INVALID_ARGUMENT', 'Request body must be valid JSON'));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
req.on('error', reject);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function send(res, status, value) {
|
|
69
|
+
const body = JSON.stringify(value);
|
|
70
|
+
res.writeHead(status, {
|
|
71
|
+
'content-type': 'application/json; charset=utf-8',
|
|
72
|
+
'content-length': Buffer.byteLength(body),
|
|
73
|
+
'cache-control': 'no-store',
|
|
74
|
+
'x-content-type-options': 'nosniff',
|
|
75
|
+
});
|
|
76
|
+
res.end(body);
|
|
77
|
+
}
|
|
78
|
+
export function registerHttpTransport(ctx, app, logger) {
|
|
79
|
+
const webServer = ctx.get('webServer');
|
|
80
|
+
if (!webServer) {
|
|
81
|
+
logger.warn('webServer is unavailable; the panel transport is disabled');
|
|
82
|
+
return () => undefined;
|
|
83
|
+
}
|
|
84
|
+
const disposer = webServer.register({
|
|
85
|
+
kind: 'prefix',
|
|
86
|
+
path: '/env-manager/api',
|
|
87
|
+
handler: async (req, res) => {
|
|
88
|
+
try {
|
|
89
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
90
|
+
if (url.pathname !== '/env-manager/api') {
|
|
91
|
+
send(res, 404, { ok: false, error: { code: 'NOT_FOUND', message: 'Unknown endpoint' } });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (req.method !== 'POST') {
|
|
95
|
+
res.setHeader('allow', 'POST');
|
|
96
|
+
send(res, 405, { ok: false, error: { code: 'METHOD_NOT_ALLOWED', message: 'Use POST' } });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const contentType = req.headers['content-type'] ?? '';
|
|
100
|
+
if (!String(contentType).toLowerCase().includes('application/json')) {
|
|
101
|
+
send(res, 415, {
|
|
102
|
+
ok: false,
|
|
103
|
+
error: { code: 'UNSUPPORTED_MEDIA_TYPE', message: 'Content-Type must be application/json' },
|
|
104
|
+
});
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (req.headers['x-env-manager-request'] !== '1') {
|
|
108
|
+
send(res, 403, {
|
|
109
|
+
ok: false,
|
|
110
|
+
error: { code: 'FORBIDDEN', message: 'Missing x-env-manager-request header' },
|
|
111
|
+
});
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const origin = req.headers.origin;
|
|
115
|
+
if (origin) {
|
|
116
|
+
let sameOrigin = false;
|
|
117
|
+
try {
|
|
118
|
+
sameOrigin = new URL(origin).host === req.headers.host;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
sameOrigin = false;
|
|
122
|
+
}
|
|
123
|
+
if (!sameOrigin) {
|
|
124
|
+
send(res, 403, { ok: false, error: { code: 'FORBIDDEN', message: 'Cross-origin request rejected' } });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const body = (await readBody(req));
|
|
129
|
+
if (typeof body.op !== 'string') {
|
|
130
|
+
throw new EnvManagerError('INVALID_ARGUMENT', 'Body must contain a string op');
|
|
131
|
+
}
|
|
132
|
+
const payload = (body.payload ?? {});
|
|
133
|
+
const data = await dispatch(body.op, payload);
|
|
134
|
+
send(res, 200, { ok: true, data });
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
const envError = error instanceof EnvManagerError
|
|
138
|
+
? error
|
|
139
|
+
: new EnvManagerError('INTERNAL_ERROR', error instanceof Error ? error.message : String(error));
|
|
140
|
+
logger.warn(`HTTP ${envError.code}: ${envError.message}`);
|
|
141
|
+
send(res, statusFor(envError.code), {
|
|
142
|
+
ok: false,
|
|
143
|
+
error: {
|
|
144
|
+
code: envError.code,
|
|
145
|
+
message: envError.message,
|
|
146
|
+
details: envError.details,
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
async function dispatch(op, payload) {
|
|
153
|
+
switch (op) {
|
|
154
|
+
case 'meta':
|
|
155
|
+
return app.meta();
|
|
156
|
+
case 'list': {
|
|
157
|
+
if (!isRecordKind(payload.kind)) {
|
|
158
|
+
throw new EnvManagerError('INVALID_ARGUMENT', `Unknown record kind "${payload.kind}"`);
|
|
159
|
+
}
|
|
160
|
+
return app.list(payload.kind);
|
|
161
|
+
}
|
|
162
|
+
case 'get':
|
|
163
|
+
if (!isRecordKind(payload.kind)) {
|
|
164
|
+
throw new EnvManagerError('INVALID_ARGUMENT', `Unknown record kind "${payload.kind}"`);
|
|
165
|
+
}
|
|
166
|
+
return app.get(payload.kind, String(payload.id ?? ''));
|
|
167
|
+
case 'find':
|
|
168
|
+
return app.find(String(payload.query ?? ''));
|
|
169
|
+
case 'save': {
|
|
170
|
+
if (!isRecordKind(payload.kind)) {
|
|
171
|
+
throw new EnvManagerError('INVALID_ARGUMENT', `Unknown record kind "${payload.kind}"`);
|
|
172
|
+
}
|
|
173
|
+
if (typeof payload.yaml === 'string') {
|
|
174
|
+
return app.saveYaml(payload.kind, payload.yaml, {
|
|
175
|
+
dryRun: Boolean(payload.dryRun),
|
|
176
|
+
actor: 'ui',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return app.save(payload.kind, payload.record, {
|
|
180
|
+
dryRun: Boolean(payload.dryRun),
|
|
181
|
+
actor: 'ui',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
case 'remove':
|
|
185
|
+
if (!isRecordKind(payload.kind)) {
|
|
186
|
+
throw new EnvManagerError('INVALID_ARGUMENT', `Unknown record kind "${payload.kind}"`);
|
|
187
|
+
}
|
|
188
|
+
return app.remove(payload.kind, String(payload.id ?? ''), 'ui', {
|
|
189
|
+
dryRun: Boolean(payload.dryRun),
|
|
190
|
+
});
|
|
191
|
+
case 'validate':
|
|
192
|
+
case 'diagnostics':
|
|
193
|
+
return app.validate();
|
|
194
|
+
case 'credential':
|
|
195
|
+
return app.setCredential(String(payload.ref ?? ''), typeof payload.value === 'string' ? payload.value : '');
|
|
196
|
+
case 'credentialUnset':
|
|
197
|
+
return app.unsetCredential(String(payload.ref ?? ''));
|
|
198
|
+
case 'resolve':
|
|
199
|
+
return app.resolve({
|
|
200
|
+
environmentId: String(payload.environmentId ?? ''),
|
|
201
|
+
serviceId: String(payload.serviceId ?? ''),
|
|
202
|
+
deploymentId: payload.deploymentId ? String(payload.deploymentId) : undefined,
|
|
203
|
+
});
|
|
204
|
+
case 'route':
|
|
205
|
+
return app.route({
|
|
206
|
+
operation: String(payload.operation ?? ''),
|
|
207
|
+
environmentId: String(payload.environmentId ?? ''),
|
|
208
|
+
serviceId: payload.serviceId ? String(payload.serviceId) : undefined,
|
|
209
|
+
deploymentId: payload.deploymentId ? String(payload.deploymentId) : undefined,
|
|
210
|
+
});
|
|
211
|
+
default:
|
|
212
|
+
throw new EnvManagerError('INVALID_ARGUMENT', `Unknown operation "${op}"`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return disposer;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"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"}
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,101 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-env-manager-plugin",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-env-manager-plugin",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Environment registry, service catalog and operation-to-Skill routing for DSH.",
|
|
6
|
+
"author": "zhiwuli0228",
|
|
7
|
+
"homepage": "https://github.com/zhiwuli0228/dsh-env-manager#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/zhiwuli0228/dsh-env-manager.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/zhiwuli0228/dsh-env-manager/issues"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": "./index.js",
|
|
17
|
+
"./client": "./client.js",
|
|
18
|
+
"./locale/*.json": "./locale/*.json",
|
|
19
|
+
"./icon": "./icon.svg",
|
|
20
|
+
"./package.json": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"client.js",
|
|
25
|
+
"cordis.patch.yml",
|
|
26
|
+
"lib/",
|
|
27
|
+
"locale/*.json",
|
|
28
|
+
"icon.svg",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"docs/",
|
|
32
|
+
"scripts/repair-profile.mjs"
|
|
33
|
+
],
|
|
34
|
+
"keywords": [
|
|
35
|
+
"dsh",
|
|
36
|
+
"dsh-plugin",
|
|
37
|
+
"environment",
|
|
38
|
+
"service-registry",
|
|
39
|
+
"ops"
|
|
40
|
+
],
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20",
|
|
44
|
+
"dsh": ">=0.2.1-rc.5"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"dsh": {
|
|
50
|
+
"bundle": {
|
|
51
|
+
"patch": "./cordis.patch.yml"
|
|
52
|
+
},
|
|
53
|
+
"client": {
|
|
54
|
+
"platform": "web",
|
|
55
|
+
"immediately": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@deepseek-ai/schemastery": "^3.18.5",
|
|
60
|
+
"yaml": "^2.9.1",
|
|
61
|
+
"zod": "^4.6.7"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@deepseek-ai/cordis": "~4.0.5",
|
|
65
|
+
"@deepseek-ai/dsh-agent": "0.2.1-rc.5",
|
|
66
|
+
"@deepseek-ai/dsh-llm": "0.2.1-rc.5",
|
|
67
|
+
"@deepseek-ai/dsh-ptc-runtime": "0.2.1-rc.5",
|
|
68
|
+
"@deepseek-ai/dsh-sandbox": "0.2.1-rc.5",
|
|
69
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.1-rc.5",
|
|
70
|
+
"@deepseek-ai/dsh-scope": "0.2.1-rc.5",
|
|
71
|
+
"@deepseek-ai/dsh-session": "0.2.1-rc.5",
|
|
72
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-rc.5",
|
|
73
|
+
"@deepseek-ai/dsh-tools": "0.2.1-rc.5",
|
|
74
|
+
"@deepseek-ai/dsh-user-approval": "0.2.1-rc.5",
|
|
75
|
+
"@deepseek-ai/dsh-util-values": "0.2.1-rc.5",
|
|
76
|
+
"@deepseek-ai/dsh-working-directory": "0.2.1-rc.5",
|
|
77
|
+
"@types/node": "^24.19.2",
|
|
78
|
+
"typescript": "^5.9.3",
|
|
79
|
+
"vitest": "^3.2.7"
|
|
80
|
+
},
|
|
81
|
+
"scripts": {
|
|
82
|
+
"build": "tsc -p tsconfig.json",
|
|
83
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
84
|
+
"test": "vitest run",
|
|
85
|
+
"test:watch": "vitest",
|
|
86
|
+
"check": "npm run typecheck && npm run build && npm test && node --check client.js && node --check index.js",
|
|
87
|
+
"repair:profile": "node scripts/repair-profile.mjs",
|
|
88
|
+
"prepack": "npm run build"
|
|
89
|
+
},
|
|
90
|
+
"main": "index.js",
|
|
91
|
+
"peerDependencies": {
|
|
92
|
+
"@deepseek-ai/cordis": "~4.0.5",
|
|
93
|
+
"@deepseek-ai/dsh-llm": "0.2.1-rc.5",
|
|
94
|
+
"@deepseek-ai/dsh-tools": "0.2.1-rc.5"
|
|
95
|
+
},
|
|
96
|
+
"peerDependenciesMeta": {
|
|
97
|
+
"@deepseek-ai/cordis": {
|
|
98
|
+
"optional": "true"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Repair a DSH profile that has a duplicated or half-removed environment-manager
|
|
4
|
+
* bundle. This script only edits the profile's package.json; it never installs
|
|
5
|
+
* packages and never touches registry data under `data/`.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node scripts/repair-profile.mjs [--profile <name>] [--fix]
|
|
9
|
+
*
|
|
10
|
+
* Without --fix it reports problems and exits nonzero. With --fix it rewrites the
|
|
11
|
+
* package.json atomically after creating a timestamped backup.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs'
|
|
15
|
+
import os from 'node:os'
|
|
16
|
+
import path from 'node:path'
|
|
17
|
+
|
|
18
|
+
const PLUGIN = 'dsh-env-manager-plugin'
|
|
19
|
+
const LEGACY = 'dsh-env-manager'
|
|
20
|
+
|
|
21
|
+
function pathEntryExists(candidate) {
|
|
22
|
+
try {
|
|
23
|
+
fs.lstatSync(candidate)
|
|
24
|
+
return true
|
|
25
|
+
} catch {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const argv = process.argv.slice(2)
|
|
31
|
+
const fix = argv.includes('--fix')
|
|
32
|
+
const profileIndex = argv.indexOf('--profile')
|
|
33
|
+
const profile =
|
|
34
|
+
profileIndex >= 0 && argv[profileIndex + 1]
|
|
35
|
+
? argv[profileIndex + 1]
|
|
36
|
+
: process.env.DSH_PROFILE
|
|
37
|
+
|
|
38
|
+
if (!profile) {
|
|
39
|
+
console.error('Missing profile. Pass --profile <name> or set DSH_PROFILE.')
|
|
40
|
+
process.exit(2)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const dshHome = process.env.DSH_HOME || path.join(os.homedir(), '.dsh')
|
|
44
|
+
const profileDir = path.join(dshHome, 'profiles', profile)
|
|
45
|
+
const packagePath = path.join(profileDir, 'package.json')
|
|
46
|
+
|
|
47
|
+
if (!fs.existsSync(packagePath)) {
|
|
48
|
+
console.error(`Profile package.json not found: ${packagePath}`)
|
|
49
|
+
process.exit(2)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let pkg
|
|
53
|
+
try {
|
|
54
|
+
pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'))
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error(`Cannot parse ${packagePath}: ${error.message}`)
|
|
57
|
+
process.exit(2)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const dependencies = pkg.dependencies && typeof pkg.dependencies === 'object' ? pkg.dependencies : {}
|
|
61
|
+
const profileConfig = pkg.dsh?.profile
|
|
62
|
+
const bundles = Array.isArray(profileConfig?.bundles) ? profileConfig.bundles : []
|
|
63
|
+
const pluginEntries = bundles.filter((entry) => entry === PLUGIN).length
|
|
64
|
+
const legacyEntries = bundles.filter((entry) => entry === LEGACY).length
|
|
65
|
+
const dependencyEntries = Object.prototype.hasOwnProperty.call(dependencies, PLUGIN)
|
|
66
|
+
const legacyDependency = Object.prototype.hasOwnProperty.call(dependencies, LEGACY)
|
|
67
|
+
const pluginLib = path.join(profileDir, 'node_modules', PLUGIN, 'lib', 'index.js')
|
|
68
|
+
const legacyLink = path.join(profileDir, 'node_modules', LEGACY)
|
|
69
|
+
|
|
70
|
+
const problems = []
|
|
71
|
+
if (pluginEntries > 1) {
|
|
72
|
+
problems.push(`${PLUGIN} appears ${pluginEntries} times in dsh.profile.bundles`)
|
|
73
|
+
}
|
|
74
|
+
if (legacyEntries > 0) {
|
|
75
|
+
problems.push(`legacy ${LEGACY} still appears in dsh.profile.bundles`)
|
|
76
|
+
}
|
|
77
|
+
if (legacyDependency) {
|
|
78
|
+
problems.push(`legacy ${LEGACY} is still a dependency`)
|
|
79
|
+
}
|
|
80
|
+
if (dependencyEntries && pluginEntries === 0) {
|
|
81
|
+
problems.push(`${PLUGIN} is a dependency but missing from dsh.profile.bundles`)
|
|
82
|
+
}
|
|
83
|
+
if (dependencyEntries && !fs.existsSync(pluginLib)) {
|
|
84
|
+
problems.push(`installed package is missing ${pluginLib}`)
|
|
85
|
+
}
|
|
86
|
+
if (legacyLink && pathEntryExists(legacyLink)) {
|
|
87
|
+
problems.push(`stale legacy node_modules entry exists: ${legacyLink}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(`profile: ${profileDir}`)
|
|
91
|
+
console.log(`package: ${packagePath}`)
|
|
92
|
+
if (problems.length === 0) {
|
|
93
|
+
console.log('OK: one plugin dependency and one bundle entry; build output present.')
|
|
94
|
+
process.exit(0)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
console.log('Problems:')
|
|
98
|
+
for (const problem of problems) console.log(`- ${problem}`)
|
|
99
|
+
|
|
100
|
+
if (!fix) {
|
|
101
|
+
console.log('Run again with --fix to repair package.json (registry data is untouched).')
|
|
102
|
+
process.exit(1)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
|
|
106
|
+
const backupPath = `${packagePath}.bak-repair-${timestamp}`
|
|
107
|
+
fs.copyFileSync(packagePath, backupPath)
|
|
108
|
+
|
|
109
|
+
const nextBundles = []
|
|
110
|
+
let seenPlugin = false
|
|
111
|
+
for (const entry of bundles) {
|
|
112
|
+
if (entry === LEGACY) continue
|
|
113
|
+
if (entry === PLUGIN) {
|
|
114
|
+
if (seenPlugin) continue
|
|
115
|
+
seenPlugin = true
|
|
116
|
+
}
|
|
117
|
+
nextBundles.push(entry)
|
|
118
|
+
}
|
|
119
|
+
if (dependencyEntries && !seenPlugin) nextBundles.push(PLUGIN)
|
|
120
|
+
|
|
121
|
+
const nextDependencies = { ...dependencies }
|
|
122
|
+
delete nextDependencies[LEGACY]
|
|
123
|
+
pkg.dependencies = nextDependencies
|
|
124
|
+
pkg.dsh = pkg.dsh || {}
|
|
125
|
+
pkg.dsh.profile = pkg.dsh.profile || {}
|
|
126
|
+
pkg.dsh.profile.bundles = nextBundles
|
|
127
|
+
|
|
128
|
+
const temporary = `${packagePath}.tmp-repair-${process.pid}`
|
|
129
|
+
fs.writeFileSync(temporary, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
|
|
130
|
+
fs.renameSync(temporary, packagePath)
|
|
131
|
+
|
|
132
|
+
console.log(`Backup: ${backupPath}`)
|
|
133
|
+
console.log('Repaired package.json. Restart DSH, then reinstall with plugin_manager if needed.')
|
|
134
|
+
if (legacyLink && pathEntryExists(legacyLink)) {
|
|
135
|
+
console.log(`Warning: remove the stale link manually after verifying it: ${legacyLink}`)
|
|
136
|
+
}
|
|
137
|
+
if (dependencyEntries && !fs.existsSync(pluginLib)) {
|
|
138
|
+
console.error(`Still missing after repair: ${pluginLib}`)
|
|
139
|
+
console.error('Reinstall the bundle with plugin_manager; do not copy files by hand.')
|
|
140
|
+
process.exit(1)
|
|
141
|
+
}
|