@dsh-workbench/core 0.3.11 → 1.0.0-beta.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 (224) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -117
  3. package/bin/dsh-workbench +130 -29
  4. package/bin/dsh-workbench.cmd +5 -0
  5. package/bin/opencli-isolated +3 -2
  6. package/bin/opencli-isolated.mjs +44 -0
  7. package/bin/opencli-node-mode.cjs +1 -0
  8. package/bin/seed-workshop-windows.mjs +307 -0
  9. package/client.js +4632 -2002
  10. package/cordis.patch.yml +3 -3
  11. package/dist/client/client.body.js +4632 -2002
  12. package/dist/client/index.js +5306 -2676
  13. package/dist/host/index.js +6990 -5879
  14. package/dist/types/app/client.d.ts +1 -0
  15. package/dist/types/app/host.d.ts +2 -1
  16. package/dist/types/app/layouts/approval-detail.d.ts +3 -0
  17. package/dist/types/app/layouts/env-gate/boot-gate.d.ts +1 -12
  18. package/dist/types/app/layouts/env-gate/gate-text.d.ts +2 -1
  19. package/dist/types/app/layouts/market/DiscoverPanel.d.ts +8 -0
  20. package/dist/types/app/layouts/market/add-module-text.d.ts +1 -1
  21. package/dist/types/app/layouts/market/discover-categories.d.ts +8 -0
  22. package/dist/types/app/layouts/market/discover-confirm.d.ts +14 -0
  23. package/dist/types/app/layouts/market/discover-detail.d.ts +12 -0
  24. package/dist/types/app/layouts/market/discover-dialogs.d.ts +7 -0
  25. package/dist/types/app/layouts/market/discover-doc.d.ts +18 -0
  26. package/dist/types/app/layouts/market/discover-init-dialog.d.ts +10 -0
  27. package/dist/types/app/layouts/market/discover-rows.d.ts +24 -0
  28. package/dist/types/app/layouts/market/discover-sources-dialog.d.ts +17 -0
  29. package/dist/types/app/layouts/market/discover-states.d.ts +22 -0
  30. package/dist/types/app/layouts/market/discover-toolbar.d.ts +23 -0
  31. package/dist/types/app/layouts/market/discover-versions.d.ts +9 -0
  32. package/dist/types/app/layouts/market/discover-view.d.ts +38 -0
  33. package/dist/types/app/layouts/market/market-header.d.ts +13 -0
  34. package/dist/types/app/layouts/market/panel.d.ts +1 -1
  35. package/dist/types/app/layouts/market/use-add-module.d.ts +1 -1
  36. package/dist/types/app/layouts/market/use-discover.d.ts +73 -0
  37. package/dist/types/app/layouts/market/use-module-versions.d.ts +1 -8
  38. package/dist/types/app/layouts/rightbar/MarketView.d.ts +1 -1
  39. package/dist/types/app/layouts/rightbar/Rightbar.d.ts +1 -1
  40. package/dist/types/app/layouts/rightbar/board-shape.d.ts +1 -14
  41. package/dist/types/app/layouts/rightbar/market-busy.d.ts +0 -22
  42. package/dist/types/app/layouts/rightbar/market-change.d.ts +1 -1
  43. package/dist/types/app/layouts/rightbar/market-hint.d.ts +1 -7
  44. package/dist/types/app/layouts/rightbar/market-plugin-rows.d.ts +0 -7
  45. package/dist/types/app/layouts/rightbar/market-row-icon.d.ts +1 -1
  46. package/dist/types/app/layouts/rightbar/market-row-types.d.ts +2 -2
  47. package/dist/types/app/layouts/rightbar/market-rows.d.ts +1 -1
  48. package/dist/types/app/layouts/rightbar/market-section-icon.d.ts +1 -1
  49. package/dist/types/app/layouts/rightbar/market-settle-hold.d.ts +1 -1
  50. package/dist/types/app/layouts/rightbar/market-settle.d.ts +4 -7
  51. package/dist/types/app/layouts/rightbar/market-shared-rows.d.ts +1 -1
  52. package/dist/types/app/layouts/rightbar/market-update-verdict.d.ts +1 -11
  53. package/dist/types/app/layouts/rightbar/market-view-text.d.ts +5 -1
  54. package/dist/types/app/layouts/rightbar/market-workbench-row.d.ts +1 -1
  55. package/dist/types/app/layouts/rightbar/store.d.ts +0 -12
  56. package/dist/types/app/layouts/sidebar/LongTaskDot.d.ts +0 -6
  57. package/dist/types/app/layouts/sidebar/LongTaskHover.d.ts +0 -6
  58. package/dist/types/app/layouts/sidebar/edition-boot.d.ts +1 -19
  59. package/dist/types/app/layouts/sidebar/edition.d.ts +1 -18
  60. package/dist/types/app/layouts/sidebar/use-attention.d.ts +0 -4
  61. package/dist/types/app/layouts/sidebar/workshop-preset.d.ts +2 -0
  62. package/dist/types/app/layouts/workbench-settings/AdapterSetItem.d.ts +5 -0
  63. package/dist/types/app/layouts/workbench-settings/ConfigSyncRows.d.ts +11 -0
  64. package/dist/types/app/layouts/workbench-settings/NewWorkbenchItem.d.ts +5 -0
  65. package/dist/types/app/layouts/workbench-settings/SettingsItem.d.ts +0 -9
  66. package/dist/types/app/layouts/workbench-settings/SidebarEditionItem.d.ts +0 -6
  67. package/dist/types/app/layouts/workbench-settings/WorkbenchSettingsSection.d.ts +0 -6
  68. package/dist/types/app/units/manifests.d.ts +1 -1
  69. package/dist/types/{app/units → kernel/client}/registry.d.ts +1 -1
  70. package/dist/types/kernel/contract/bundle-install.d.ts +2 -0
  71. package/dist/types/kernel/contract/config-sync.d.ts +2 -0
  72. package/dist/types/kernel/contract/diy.d.ts +1 -0
  73. package/dist/types/kernel/contract/dsh-plugins.d.ts +2 -0
  74. package/dist/types/kernel/contract/index.d.ts +5 -0
  75. package/dist/types/kernel/contract/long-tasks.d.ts +2 -0
  76. package/dist/types/kernel/contract/market-index.d.ts +2 -0
  77. package/dist/types/kernel/contract/platform.d.ts +1 -0
  78. package/dist/types/kernel/contract/preflight-wake.d.ts +2 -0
  79. package/dist/types/kernel/contract/profile-create.d.ts +2 -0
  80. package/dist/types/kernel/contract/sidebar-edition.d.ts +2 -0
  81. package/dist/types/kernel/contract/unit-manifests.d.ts +2 -0
  82. package/dist/types/{shared/api → kernel}/host/mount-units.d.ts +5 -1
  83. package/dist/types/modules/panels/client.d.ts +1 -1
  84. package/dist/types/modules/panels/model/approval.d.ts +3 -15
  85. package/dist/types/modules/panels/model/diy-changelog.d.ts +2 -0
  86. package/dist/types/modules/panels/model/diy-context.d.ts +1 -16
  87. package/dist/types/modules/panels/model/diy-page.d.ts +1 -0
  88. package/dist/types/modules/panels/model/diy-record-open.d.ts +0 -15
  89. package/dist/types/modules/panels/model/diy-record-text.d.ts +0 -2
  90. package/dist/types/modules/panels/model/diy-record.d.ts +0 -30
  91. package/dist/types/modules/panels/model/diy-tools.d.ts +1 -0
  92. package/dist/types/modules/panels/model/long-task-tools.d.ts +0 -11
  93. package/dist/types/modules/panels/model/market-dependency-update.d.ts +1 -7
  94. package/dist/types/modules/panels/model/market-dependency.d.ts +15 -10
  95. package/dist/types/modules/panels/model/market-discover-routes.d.ts +3 -0
  96. package/dist/types/modules/panels/model/market-discover.d.ts +33 -0
  97. package/dist/types/modules/panels/model/market-dispatch.d.ts +3 -3
  98. package/dist/types/modules/panels/model/market-env.d.ts +2 -3
  99. package/dist/types/modules/panels/model/market-registry.d.ts +3 -3
  100. package/dist/types/modules/panels/model/market-restart.d.ts +1 -1
  101. package/dist/types/modules/panels/model/market-route.d.ts +5 -3
  102. package/dist/types/modules/panels/model/market-sources-act.d.ts +9 -0
  103. package/dist/types/modules/panels/model/market-types.d.ts +6 -13
  104. package/dist/types/modules/panels/model/market-update-bundle.d.ts +3 -9
  105. package/dist/types/modules/panels/model/market-verify.d.ts +3 -19
  106. package/dist/types/modules/panels/model/market-workbench-update.d.ts +3 -2
  107. package/dist/types/modules/panels/model/market.d.ts +6 -5
  108. package/dist/types/modules/panels/model/plugin-actions.d.ts +2 -1
  109. package/dist/types/modules/panels/model/plugin-section.d.ts +3 -1
  110. package/dist/types/modules/panels/model/publish-preview-routes.d.ts +2 -0
  111. package/dist/types/modules/panels/unit.d.ts +7 -3
  112. package/dist/types/modules/sessions/model/attention.d.ts +0 -11
  113. package/dist/types/modules/sessions/model/session-node.d.ts +0 -10
  114. package/dist/types/shared/api/diy.d.ts +6 -4
  115. package/dist/types/shared/api/host/approval-call.d.ts +0 -9
  116. package/dist/types/shared/api/host/approval-gate.d.ts +0 -13
  117. package/dist/types/shared/api/host/bundle-routes.d.ts +1 -1
  118. package/dist/types/shared/api/host/diy-artifacts.d.ts +0 -11
  119. package/dist/types/shared/api/host/diy-changelog.d.ts +13 -0
  120. package/dist/types/shared/api/host/diy-components.d.ts +2 -3
  121. package/dist/types/shared/api/host/diy-modules.d.ts +0 -16
  122. package/dist/types/shared/api/host/diy-publish-preview.d.ts +4 -0
  123. package/dist/types/shared/api/host/diy-recon-fs.d.ts +2 -2
  124. package/dist/types/shared/api/host/diy-tokens.d.ts +8 -0
  125. package/dist/types/shared/api/host/host-routes.d.ts +3 -6
  126. package/dist/types/shared/api/host/long-task-notice.d.ts +0 -20
  127. package/dist/types/shared/api/host/long-tasks.d.ts +1 -8
  128. package/dist/types/shared/api/host/market-doc.d.ts +21 -0
  129. package/dist/types/shared/api/host/market-index-fetch.d.ts +37 -0
  130. package/dist/types/shared/api/host/market-source-init.d.ts +22 -0
  131. package/dist/types/shared/api/host/market-sources-store.d.ts +15 -0
  132. package/dist/types/shared/api/host/permission-mode.d.ts +0 -5
  133. package/dist/types/shared/api/host/post-channels.d.ts +1 -1
  134. package/dist/types/shared/api/host/sidebar-edition.d.ts +1 -33
  135. package/dist/types/shared/api/host/unit-roster-facts.d.ts +1 -1
  136. package/dist/types/shared/api/host/workspace-root.d.ts +0 -7
  137. package/dist/types/shared/api/platform/client.d.ts +10 -0
  138. package/dist/types/shared/api/unit-board.d.ts +0 -16
  139. package/dist/types/shared/api/write-outcome.d.ts +0 -12
  140. package/dist/types/shared/components/IconModules.d.ts +0 -6
  141. package/dist/types/shared/components/PanelFoot.d.ts +0 -9
  142. package/dist/types/shared/components/blocker-action.d.ts +0 -13
  143. package/dist/types/shared/dev-surface/index.d.ts +5 -0
  144. package/dist/types/shared/dev-surface/types.d.ts +79 -0
  145. package/dist/types/shared/hooks/bundle-queries.d.ts +1 -13
  146. package/dist/types/shared/hooks/fact-transport.d.ts +4 -0
  147. package/dist/types/shared/hooks/fact-transports.d.ts +0 -4
  148. package/dist/types/shared/hooks/market-queries.d.ts +11 -0
  149. package/dist/types/shared/hooks/panel-state-report.d.ts +0 -12
  150. package/dist/types/shared/hooks/sidebar-edition.d.ts +1 -6
  151. package/dist/types/shared/hooks/use-blocker-actions.d.ts +0 -8
  152. package/dist/types/shared/hooks/use-capabilities.d.ts +0 -59
  153. package/dist/types/shared/hooks/use-diy-debug.d.ts +0 -13
  154. package/dist/types/shared/hooks/use-diy-record.d.ts +0 -13
  155. package/dist/types/shared/hooks/use-shell-long-tasks.d.ts +1 -7
  156. package/icon.svg +17 -28
  157. package/package.json +33 -13
  158. package/preset/diy.patch.yml +1 -1
  159. package/profile/isolation.patch.yml +8 -8
  160. package/profile/sandbox.patch.yml +2 -2
  161. package/scripts/clone-profile.mjs +268 -0
  162. package/scripts/create-workbench.mjs +166 -0
  163. package/scripts/seed-profile.sh +22 -10
  164. package/scripts/seed-workshop.sh +17 -19
  165. package/skills/workbench-module-diy/BUILD.md +4 -11
  166. package/skills/workbench-module-diy/COPY.md +1 -1
  167. package/skills/workbench-module-diy/DATASOURCE.md +107 -22
  168. package/skills/workbench-module-diy/DESIGN.md +2 -1
  169. package/skills/workbench-module-diy/FAMILY.md +48 -68
  170. package/skills/workbench-module-diy/KIT.md +6 -3
  171. package/skills/workbench-module-diy/LINKAGE.md +1 -1
  172. package/skills/workbench-module-diy/PANEL.md +5 -3
  173. package/skills/workbench-module-diy/REVIEW.md +7 -7
  174. package/skills/workbench-module-diy/SKILL.md +20 -11
  175. package/skills/workbench-module-diy/STEPS.md +1 -1
  176. package/skills/workbench-module-diy/TOOLS.md +33 -9
  177. package/skills/workbench-module-diy/WIRING.md +18 -6
  178. package/skills/workbench-module-diy/WRITES.md +30 -4
  179. package/dist/types/shared/api/bundle-install.d.ts +0 -136
  180. package/dist/types/shared/api/config-sync.d.ts +0 -35
  181. package/dist/types/shared/api/dsh-plugins.d.ts +0 -11
  182. package/dist/types/shared/api/host/bundle-manager.d.ts +0 -11
  183. package/dist/types/shared/api/host/config-sync.d.ts +0 -46
  184. package/dist/types/shared/api/host/diy-preset-health.d.ts +0 -35
  185. package/dist/types/shared/api/host/dsh-plugins.d.ts +0 -5
  186. package/dist/types/shared/api/host/installed-module.d.ts +0 -54
  187. package/dist/types/shared/api/host/installed-module.test.d.ts +0 -1
  188. package/dist/types/shared/api/host/opencli-command.d.ts +0 -10
  189. package/dist/types/shared/api/host/opencli-command.test.d.ts +0 -1
  190. package/dist/types/shared/api/host/opencli.test.d.ts +0 -1
  191. package/dist/types/shared/api/host/package-content.d.ts +0 -6
  192. package/dist/types/shared/api/host/package-content.test.d.ts +0 -1
  193. package/dist/types/shared/api/host/package-kind.d.ts +0 -21
  194. package/dist/types/shared/api/host/package-kind.test.d.ts +0 -1
  195. package/dist/types/shared/api/host/package-route.d.ts +0 -23
  196. package/dist/types/shared/api/host/package-route.test.d.ts +0 -1
  197. package/dist/types/shared/api/host/plugin-catalog.d.ts +0 -65
  198. package/dist/types/shared/api/host/plugin-login-hint.d.ts +0 -2
  199. package/dist/types/shared/api/host/plugin-tools.d.ts +0 -14
  200. package/dist/types/shared/api/host/plugin-units.d.ts +0 -48
  201. package/dist/types/shared/api/host/preflight-route.d.ts +0 -15
  202. package/dist/types/shared/api/host/preflight.d.ts +0 -75
  203. package/dist/types/shared/api/host/probe-cache.d.ts +0 -6
  204. package/dist/types/shared/api/host/probe-libs.d.ts +0 -11
  205. package/dist/types/shared/api/host/probe-units.d.ts +0 -17
  206. package/dist/types/shared/api/host/probe-verdict.d.ts +0 -7
  207. package/dist/types/shared/api/host/profile-registries.d.ts +0 -21
  208. package/dist/types/shared/api/host/registry-declaration.d.ts +0 -23
  209. package/dist/types/shared/api/host/release.d.ts +0 -24
  210. package/dist/types/shared/api/host/runtime-seed.d.ts +0 -40
  211. package/dist/types/shared/api/host/self-update.d.ts +0 -52
  212. package/dist/types/shared/api/host/version-range.d.ts +0 -2
  213. package/dist/types/shared/api/long-tasks.d.ts +0 -19
  214. package/dist/types/shared/api/sidebar-edition.d.ts +0 -14
  215. package/dist/types/shared/api/unit-manifests.d.ts +0 -6
  216. package/docs/HANDOFF.md +0 -333
  217. package/docs/OPERATIONS.md +0 -240
  218. package/skills/workbench-module-diy/TOOLING.md +0 -38
  219. /package/dist/types/{app/layouts/rightbar/registry.d.ts → kernel/client/board-registry.d.ts} +0 -0
  220. /package/dist/types/{app/layouts/rightbar/registry.test.d.ts → kernel/contract/contracts.test.d.ts} +0 -0
  221. /package/dist/types/{shared/api/host/bundle-manager.test.d.ts → kernel/contract/index.test.d.ts} +0 -0
  222. /package/dist/types/{shared/api → kernel}/host/unit-readiness.d.ts +0 -0
  223. /package/dist/types/{shared/api → kernel}/host/unit-registry.d.ts +0 -0
  224. /package/dist/types/shared/{api/host/dsh-plugins.test.d.ts → dev-surface/install.d.ts} +0 -0
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process';
3
+ import { existsSync, mkdirSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const dshHome = process.env.DSH_HOME?.trim() || join(homedir(), '.dsh');
9
+ const workbenchHome = process.env.DSH_WORKBENCH_HOME?.trim() || join(dshHome, 'workbench');
10
+ const root = join(workbenchHome, 'opencli');
11
+ const isolatedHome = join(root, 'home');
12
+ const main = join(root, 'toolchain', 'node_modules', '@jackwener', 'opencli', 'dist', 'src', 'main.js');
13
+ const realHome = process.env.HOME || process.env.USERPROFILE || homedir();
14
+ const preload = join(dirname(fileURLToPath(import.meta.url)), 'opencli-node-mode.cjs');
15
+
16
+ mkdirSync(isolatedHome, { recursive: true });
17
+ if (!existsSync(main)) {
18
+ process.stderr.write(`dsh-workbench: opencli 的隔离运行时还没装好(${join(root, 'toolchain')})。\n`);
19
+ process.stderr.write(' 打开工作台:启动体检会给出一条能直接照做的安装命令。\n');
20
+ process.exit(127);
21
+ }
22
+
23
+ const env = {
24
+ ...process.env,
25
+ HOME: isolatedHome,
26
+ npm_config_cache: join(root, 'npm-cache'),
27
+ };
28
+ const userConfig = join(realHome, '.npmrc');
29
+ if (existsSync(userConfig)) env.NPM_CONFIG_USERCONFIG = userConfig;
30
+ if (process.versions.electron !== undefined) env.ELECTRON_RUN_AS_NODE = '1';
31
+
32
+ const child = spawn(process.execPath, ['--require', preload, main, ...process.argv.slice(2)], {
33
+ stdio: 'inherit',
34
+ env,
35
+ windowsHide: true,
36
+ });
37
+ child.on('error', (error) => {
38
+ process.stderr.write(`dsh-workbench: opencli 没跑起来:${String(error)}\n`);
39
+ process.exit(1);
40
+ });
41
+ child.on('exit', (code, signal) => {
42
+ if (signal !== null) process.kill(process.pid, signal);
43
+ else process.exit(code ?? 1);
44
+ });
@@ -0,0 +1 @@
1
+ process.defaultApp = true;
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process';
3
+ import {
4
+ existsSync,
5
+ lstatSync,
6
+ mkdirSync,
7
+ readFileSync,
8
+ readlinkSync,
9
+ rmSync,
10
+ symlinkSync,
11
+ writeFileSync,
12
+ } from 'node:fs';
13
+ import { homedir } from 'node:os';
14
+ import { dirname, join, resolve } from 'node:path';
15
+ import which from 'which';
16
+ import writeFileAtomic from 'write-file-atomic';
17
+
18
+ const mode = process.argv[2] === 'full' ? 'full' : process.argv[2] === 'sync' ? 'sync' : 'entry';
19
+ const shellRoot = process.env.DSH_WB_SHELL_ROOT ?? '';
20
+ const home = process.env.DSH_HOME?.trim() || join(homedir(), '.dsh');
21
+ const diy = join(home, 'workbench', 'diy');
22
+ const manifest = join(diy, 'package.json');
23
+ const syncState = join(diy, '.sync.json');
24
+ const syncLock = join(diy, '.sync.lock');
25
+ const pnpmPin = 'pnpm@10.32.1';
26
+ const pnpm = which.sync('pnpm', { nothrow: true }) ?? 'pnpm';
27
+
28
+ function say(message) {
29
+ process.stdout.write(`[dsh-workbench] ${message}\n`);
30
+ }
31
+
32
+ function versionOf(file) {
33
+ try {
34
+ const read = JSON.parse(readFileSync(file, 'utf8'));
35
+ return typeof read.version === 'string' ? read.version : '';
36
+ } catch {
37
+ return '';
38
+ }
39
+ }
40
+
41
+ function shellVersion() {
42
+ if (shellRoot === '') return '';
43
+ const version = versionOf(join(shellRoot, 'package.json'));
44
+ if (version !== '') return version;
45
+ say('读不到工作台版本(DSH_WB_SHELL_ROOT),工坊骨架先不建。');
46
+ return '';
47
+ }
48
+
49
+ function primitivesVersion() {
50
+ if (shellRoot === '') return '';
51
+ try {
52
+ const read = JSON.parse(readFileSync(join(shellRoot, 'package.json'), 'utf8'));
53
+ const version = read.devDependencies?.['@deepseek-ai/dsh-client-ui-primitives'];
54
+ return typeof version === 'string' ? version : '';
55
+ } catch {
56
+ return '';
57
+ }
58
+ }
59
+
60
+ function repoRoot() {
61
+ const parent = dirname(shellRoot);
62
+ return existsSync(join(parent, 'module-tools')) && existsSync(join(parent, 'shared')) ? parent : '';
63
+ }
64
+
65
+ function specs(version) {
66
+ const root = repoRoot();
67
+ if (root !== '') {
68
+ return {
69
+ core: `link:${resolve(shellRoot)}`,
70
+ tools: `link:${resolve(join(root, 'module-tools'))}`,
71
+ shared: `link:${resolve(join(root, 'shared'))}`,
72
+ };
73
+ }
74
+ return {
75
+ core: `^${version}`,
76
+ tools: `^${version}`,
77
+ shared: `^${version}`,
78
+ };
79
+ }
80
+
81
+ function ensureSkills() {
82
+ const source = join(shellRoot, 'skills', 'workbench-module-diy');
83
+ if (!existsSync(source)) return;
84
+ const link = join(diy, '.agents', 'skills', 'workbench-module-diy');
85
+ try {
86
+ const stat = lstatSync(link);
87
+ if (!stat.isSymbolicLink()) return;
88
+ if (resolve(readlinkSync(link)) === resolve(source)) return;
89
+ rmSync(link, { force: true });
90
+ } catch {
91
+
92
+ }
93
+ mkdirSync(dirname(link), { recursive: true });
94
+ try {
95
+ symlinkSync(resolve(source), link, process.platform === 'win32' ? 'junction' : 'dir');
96
+ say(`工坊指引已链上:${link}`);
97
+ } catch (error) {
98
+ say(`DIY 指引没挂上(${String(error)})—— 不影响启动。`);
99
+ }
100
+ }
101
+
102
+ function writeSkeleton(version) {
103
+ mkdirSync(join(diy, 'packages'), { recursive: true });
104
+ const target = specs(version);
105
+ const devDependencies = {
106
+ '@dsh-workbench/core': target.core,
107
+ '@dsh-workbench/module-tools': target.tools,
108
+ '@dsh-workbench/shared': target.shared,
109
+ '@types/node': '^24.19.0',
110
+ '@types/react': '^19.3.0',
111
+ esbuild: '^0.28.2',
112
+ react: '^19.3.0',
113
+ typescript: '5.9',
114
+ vitest: '^5.0.2',
115
+ };
116
+ const primitives = primitivesVersion();
117
+ if (primitives !== '') devDependencies['@deepseek-ai/dsh-client-ui-primitives'] = primitives;
118
+ const packageJson = {
119
+ name: 'dsh-workbench-diy',
120
+ version: '0.0.0',
121
+ private: true,
122
+ description: 'DIY 工坊:工作台模块在这里造。这个目录由 dsh-workbench 生成。',
123
+ packageManager: pnpmPin,
124
+ devDependencies,
125
+ pnpm: {
126
+ overrides: {
127
+ '@dsh-workbench/core': target.core,
128
+ '@dsh-workbench/module-tools': target.tools,
129
+ '@dsh-workbench/shared': target.shared,
130
+ },
131
+ },
132
+ };
133
+ writeFileSync(manifest, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
134
+ writeFileSync(
135
+ join(diy, 'pnpm-workspace.yaml'),
136
+ 'packages:\n - "packages/*"\n\nonlyBuiltDependencies:\n - esbuild\n',
137
+ 'utf8',
138
+ );
139
+ const store = join(diy, '.pnpm-store').replaceAll('\\', '/');
140
+ const cache = join(diy, '.npm-cache').replaceAll('\\', '/');
141
+ writeFileSync(join(diy, '.npmrc'), `store-dir=${store}\ncache-dir=${cache}\n`, 'utf8');
142
+ writeFileSync(
143
+ join(diy, 'README.md'),
144
+ [
145
+ '# DIY 工坊',
146
+ '',
147
+ '工作台模块在这里造。一个模块一个目录,都住在 `packages/` 下。',
148
+ '',
149
+ '- 造一个新模块:`dsh-wb-module init <名字> --dir packages/module-<名字>`',
150
+ '- 每个模块:`pnpm build` / `pnpm typecheck` / `pnpm test` / `pnpm selfcheck`',
151
+ '',
152
+ ].join('\n'),
153
+ 'utf8',
154
+ );
155
+ say(`建 DIY 工坊 ${diy}`);
156
+ }
157
+
158
+ function installedCoreVersion() {
159
+ return versionOf(join(diy, 'node_modules', '@dsh-workbench', 'core', 'package.json'));
160
+ }
161
+
162
+ function syncVersions(version) {
163
+ const target = specs(version);
164
+ const manifestValue = JSON.parse(readFileSync(manifest, 'utf8'));
165
+ manifestValue.devDependencies = {
166
+ ...manifestValue.devDependencies,
167
+ '@dsh-workbench/core': target.core,
168
+ '@dsh-workbench/module-tools': target.tools,
169
+ '@dsh-workbench/shared': target.shared,
170
+ };
171
+ manifestValue.pnpm = {
172
+ ...manifestValue.pnpm,
173
+ overrides: {
174
+ '@dsh-workbench/core': target.core,
175
+ '@dsh-workbench/module-tools': target.tools,
176
+ '@dsh-workbench/shared': target.shared,
177
+ },
178
+ };
179
+ writeFileSync(manifest, `${JSON.stringify(manifestValue, null, 2)}\n`, 'utf8');
180
+ say(`工坊工具链对齐到 ${version}`);
181
+ }
182
+
183
+ function writeState(state, version, reason = '') {
184
+ const payload = { state, version, at: new Date().toISOString() };
185
+ if (reason !== '') payload.reason = reason;
186
+ try {
187
+ writeFileAtomic.sync(syncState, `${JSON.stringify(payload)}\n`, 'utf8');
188
+ } catch {
189
+
190
+ }
191
+ }
192
+
193
+ function sleep(ms) {
194
+ if (ms <= 0) return;
195
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
196
+ }
197
+
198
+ function lockAlive() {
199
+ if (!existsSync(syncLock)) return false;
200
+ try {
201
+ const read = JSON.parse(readFileSync(syncLock, 'utf8'));
202
+ if (typeof read.pid !== 'number') return false;
203
+ process.kill(read.pid, 0);
204
+ return true;
205
+ } catch {
206
+ return false;
207
+ }
208
+ }
209
+
210
+ function acquireLock() {
211
+ const waitMs = Number(process.env.DSH_WB_SYNC_WAIT_MS ?? '5000');
212
+ const deadline = Date.now() + (Number.isFinite(waitMs) && waitMs > 0 ? waitMs : 0);
213
+ for (;;) {
214
+ if (!lockAlive()) {
215
+ try {
216
+ rmSync(syncLock, { force: true });
217
+ writeFileSync(syncLock, JSON.stringify({ pid: process.pid, at: new Date().toISOString() }), {
218
+ flag: 'wx',
219
+ });
220
+ return true;
221
+ } catch {
222
+ say('工坊自愈锁没抢到,这一轮跳过。');
223
+ return false;
224
+ }
225
+ }
226
+ if (Date.now() >= deadline) {
227
+ say('另一个工坊自愈正持锁,等过一轮仍没抢到,这一轮跳过。');
228
+ return false;
229
+ }
230
+ sleep(Math.min(250, Math.max(0, deadline - Date.now())));
231
+ }
232
+ }
233
+
234
+ function releaseLock() {
235
+ try {
236
+ rmSync(syncLock, { force: true });
237
+ } catch {
238
+
239
+ }
240
+ }
241
+
242
+ function manifestCoreSpec() {
243
+ try {
244
+ const read = JSON.parse(readFileSync(manifest, 'utf8'));
245
+ return read.devDependencies?.['@dsh-workbench/core'] ?? '';
246
+ } catch {
247
+ return '';
248
+ }
249
+ }
250
+
251
+ function install() {
252
+ say('装工坊依赖(第一次会下载 react / typescript / vitest)...');
253
+ return new Promise((resolve) => {
254
+ const child = spawn(`"${pnpm}" install`, {
255
+ cwd: diy,
256
+ stdio: 'inherit',
257
+ shell: true,
258
+ env: process.env,
259
+ windowsHide: true,
260
+ });
261
+ child.on('error', (error) => {
262
+ say(`pnpm 没跑起来:${String(error)}`);
263
+ resolve(1);
264
+ });
265
+ child.on('close', (code) => resolve(code ?? 1));
266
+ });
267
+ }
268
+
269
+ const version = shellVersion();
270
+
271
+ if (!existsSync(manifest)) {
272
+ if (mode === 'entry') {
273
+ say('工坊骨架还没建,等 full 那一趟。');
274
+ process.exit(0);
275
+ }
276
+ if (version === '') process.exit(0);
277
+ writeSkeleton(version);
278
+ }
279
+
280
+ ensureSkills();
281
+
282
+ const depsMissing = !existsSync(join(diy, 'node_modules'));
283
+ if (depsMissing && mode === 'entry') process.exit(0);
284
+ if (version === '') process.exit(0);
285
+
286
+ const installed = installedCoreVersion();
287
+ const target = specs(version);
288
+ const outdated = manifestCoreSpec() !== target.core || installed !== version;
289
+ if (!depsMissing && !outdated) {
290
+ writeState('ok', version);
291
+ process.exit(0);
292
+ }
293
+
294
+ if (!acquireLock()) process.exit(0);
295
+ let heartbeat = null;
296
+ try {
297
+ writeState('syncing', version);
298
+ heartbeat = globalThis.setInterval(() => writeState('syncing', version), 1000);
299
+ if (outdated) syncVersions(version);
300
+ const code = await install();
301
+ globalThis.clearInterval(heartbeat);
302
+ writeState(code === 0 ? 'ok' : 'failed', version, code === 0 ? '' : 'pnpm install 失败');
303
+ process.exit(code);
304
+ } finally {
305
+ if (heartbeat !== null) globalThis.clearInterval(heartbeat);
306
+ releaseLock();
307
+ }