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.
Files changed (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +273 -3
  3. package/client.js +2581 -0
  4. package/cordis.patch.yml +4 -0
  5. package/docs/00-project/current-state.md +272 -0
  6. package/docs/00-project/glossary.md +215 -0
  7. package/docs/00-project/project-brief.md +114 -0
  8. package/docs/00-project/roadmap.md +89 -0
  9. package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -0
  10. package/docs/01-architecture/api-verification.md +416 -0
  11. package/docs/01-architecture/architecture-overview.md +222 -0
  12. package/docs/01-architecture/data-model.md +930 -0
  13. package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -0
  14. package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -0
  15. package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -0
  16. package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -0
  17. package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -0
  18. package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -0
  19. package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -0
  20. package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -0
  21. package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -0
  22. package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -0
  23. package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -0
  24. package/docs/01-architecture/design.md +666 -0
  25. package/docs/01-architecture/detailed-design.md +961 -0
  26. package/docs/01-architecture/implementation-plan.md +323 -0
  27. package/docs/01-architecture/module-boundaries.md +306 -0
  28. package/docs/01-architecture/security-model.md +227 -0
  29. package/docs/01-architecture/storage-contract.md +224 -0
  30. package/docs/01-architecture/tool-contract.md +438 -0
  31. package/docs/01-architecture/ui-design.md +587 -0
  32. package/docs/02-harness/agent-behavior.md +36 -0
  33. package/docs/02-harness/change-snapshot-policy.md +29 -0
  34. package/docs/02-harness/client-ui-integration.md +110 -0
  35. package/docs/02-harness/context-policy.md +43 -0
  36. package/docs/02-harness/harness-standard.md +91 -0
  37. package/docs/02-harness/task-execution-policy.md +26 -0
  38. package/docs/02-harness/verification-policy.md +97 -0
  39. package/docs/03-openspec/archive-rule.md +25 -0
  40. package/docs/03-openspec/bugfix-rule.md +30 -0
  41. package/docs/03-openspec/design-rule.md +33 -0
  42. package/docs/03-openspec/openspec-usage-guide.md +31 -0
  43. package/docs/03-openspec/proposal-rule.md +70 -0
  44. package/docs/03-openspec/spec-rule.md +33 -0
  45. package/docs/03-openspec/tasks-rule.md +31 -0
  46. package/docs/04-development/coding-style.md +67 -0
  47. package/docs/04-development/dependency-policy.md +43 -0
  48. package/docs/04-development/development-guide.md +85 -0
  49. package/docs/04-development/directory-convention.md +105 -0
  50. package/docs/04-development/local-run-guide.md +61 -0
  51. package/docs/04-development/testing-guide.md +102 -0
  52. package/docs/05-domain/deployment-template.md +76 -0
  53. package/docs/05-domain/environment-template.md +165 -0
  54. package/docs/05-domain/operation-binding-template.md +55 -0
  55. package/docs/05-domain/operation-record-template.md +55 -0
  56. package/docs/05-domain/prompt-template.md +90 -0
  57. package/docs/05-domain/rule-template.md +73 -0
  58. package/docs/05-domain/service-template.md +39 -0
  59. package/docs/06-operations/deployment-guide.md +54 -0
  60. package/docs/06-operations/release.md +198 -0
  61. package/docs/06-operations/security-policy.md +53 -0
  62. package/docs/06-operations/troubleshooting.md +141 -0
  63. package/docs/07-templates/adr-template.md +21 -0
  64. package/docs/07-templates/bugfix-template.md +11 -0
  65. package/docs/07-templates/case-template.md +15 -0
  66. package/docs/07-templates/design-template.md +29 -0
  67. package/docs/07-templates/proposal-template.md +19 -0
  68. package/docs/07-templates/spec-template.md +15 -0
  69. package/docs/07-templates/tasks-template.md +12 -0
  70. package/docs/99-archive/README.md +13 -0
  71. package/docs/README.md +142 -0
  72. package/icon.svg +4 -0
  73. package/index.js +31 -0
  74. package/lib/app/app.d.ts +67 -0
  75. package/lib/app/app.js +494 -0
  76. package/lib/app/app.js.map +1 -0
  77. package/lib/config.d.ts +55 -0
  78. package/lib/config.js +42 -0
  79. package/lib/config.js.map +1 -0
  80. package/lib/domain/constants.d.ts +21 -0
  81. package/lib/domain/constants.js +59 -0
  82. package/lib/domain/constants.js.map +1 -0
  83. package/lib/domain/errors.d.ts +20 -0
  84. package/lib/domain/errors.js +22 -0
  85. package/lib/domain/errors.js.map +1 -0
  86. package/lib/domain/schemas.d.ts +28 -0
  87. package/lib/domain/schemas.js +445 -0
  88. package/lib/domain/schemas.js.map +1 -0
  89. package/lib/domain/types.d.ts +412 -0
  90. package/lib/domain/types.js +2 -0
  91. package/lib/domain/types.js.map +1 -0
  92. package/lib/index.d.ts +18 -0
  93. package/lib/index.js +89 -0
  94. package/lib/index.js.map +1 -0
  95. package/lib/logger.d.ts +8 -0
  96. package/lib/logger.js +13 -0
  97. package/lib/logger.js.map +1 -0
  98. package/lib/memory/bridge.d.ts +18 -0
  99. package/lib/memory/bridge.js +13 -0
  100. package/lib/memory/bridge.js.map +1 -0
  101. package/lib/registry/integrity.d.ts +10 -0
  102. package/lib/registry/integrity.js +204 -0
  103. package/lib/registry/integrity.js.map +1 -0
  104. package/lib/registry/registry.d.ts +14 -0
  105. package/lib/registry/registry.js +182 -0
  106. package/lib/registry/registry.js.map +1 -0
  107. package/lib/resolver/merge.d.ts +23 -0
  108. package/lib/resolver/merge.js +90 -0
  109. package/lib/resolver/merge.js.map +1 -0
  110. package/lib/resolver/resolve.d.ts +18 -0
  111. package/lib/resolver/resolve.js +288 -0
  112. package/lib/resolver/resolve.js.map +1 -0
  113. package/lib/resolver/template.d.ts +10 -0
  114. package/lib/resolver/template.js +42 -0
  115. package/lib/resolver/template.js.map +1 -0
  116. package/lib/router/params.d.ts +3 -0
  117. package/lib/router/params.js +83 -0
  118. package/lib/router/params.js.map +1 -0
  119. package/lib/router/router.d.ts +11 -0
  120. package/lib/router/router.js +204 -0
  121. package/lib/router/router.js.map +1 -0
  122. package/lib/session/session.d.ts +16 -0
  123. package/lib/session/session.js +64 -0
  124. package/lib/session/session.js.map +1 -0
  125. package/lib/skill.d.ts +17 -0
  126. package/lib/skill.js +56 -0
  127. package/lib/skill.js.map +1 -0
  128. package/lib/storage/atomic.d.ts +10 -0
  129. package/lib/storage/atomic.js +107 -0
  130. package/lib/storage/atomic.js.map +1 -0
  131. package/lib/storage/paths.d.ts +10 -0
  132. package/lib/storage/paths.js +50 -0
  133. package/lib/storage/paths.js.map +1 -0
  134. package/lib/storage/records.d.ts +16 -0
  135. package/lib/storage/records.js +112 -0
  136. package/lib/storage/records.js.map +1 -0
  137. package/lib/storage/sessions.d.ts +17 -0
  138. package/lib/storage/sessions.js +65 -0
  139. package/lib/storage/sessions.js.map +1 -0
  140. package/lib/tools/tools.d.ts +14 -0
  141. package/lib/tools/tools.js +472 -0
  142. package/lib/tools/tools.js.map +1 -0
  143. package/lib/transport/http.d.ts +3 -0
  144. package/lib/transport/http.js +217 -0
  145. package/lib/transport/http.js.map +1 -0
  146. package/locale/en.json +6 -0
  147. package/locale/zh.json +6 -0
  148. package/package.json +101 -6
  149. 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
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "DSH Environment Manager",
4
+ "description": "Manages enterprise environments, services, deployments and operation-skill bindings for DSH sessions."
5
+ }
6
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "DSH 环境管理器",
4
+ "description": "为 DSH 会话管理企业环境、服务、部署实例以及操作与 Skill 的绑定关系。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,6 +1,101 @@
1
- {
2
- "name": "dsh-env-manager-plugin",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
+ }