@openvulcan/dsh-vulcancode 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -2
  3. package/assets/openvulcan-icon.svg +33 -0
  4. package/cordis.patch.yml +17 -0
  5. package/node_modules/@openvulcan/dsh-decision-guard/LICENSE +21 -0
  6. package/node_modules/@openvulcan/dsh-decision-guard/README.md +14 -0
  7. package/node_modules/@openvulcan/dsh-decision-guard/assets/decision-guard-icon.png +0 -0
  8. package/node_modules/@openvulcan/dsh-decision-guard/lib/calls.d.ts +40 -0
  9. package/node_modules/@openvulcan/dsh-decision-guard/lib/calls.js +150 -0
  10. package/node_modules/@openvulcan/dsh-decision-guard/lib/client.js +2193 -0
  11. package/node_modules/@openvulcan/dsh-decision-guard/lib/decide.d.ts +90 -0
  12. package/node_modules/@openvulcan/dsh-decision-guard/lib/decide.js +108 -0
  13. package/node_modules/@openvulcan/dsh-decision-guard/lib/index.d.ts +129 -0
  14. package/node_modules/@openvulcan/dsh-decision-guard/lib/index.js +572 -0
  15. package/node_modules/@openvulcan/dsh-decision-guard/lib/intent.d.ts +22 -0
  16. package/node_modules/@openvulcan/dsh-decision-guard/lib/intent.js +77 -0
  17. package/node_modules/@openvulcan/dsh-decision-guard/lib/panel.d.ts +158 -0
  18. package/node_modules/@openvulcan/dsh-decision-guard/lib/panel.js +340 -0
  19. package/node_modules/@openvulcan/dsh-decision-guard/lib/records.d.ts +133 -0
  20. package/node_modules/@openvulcan/dsh-decision-guard/lib/records.js +186 -0
  21. package/node_modules/@openvulcan/dsh-decision-guard/lib/review.d.ts +55 -0
  22. package/node_modules/@openvulcan/dsh-decision-guard/lib/review.js +202 -0
  23. package/node_modules/@openvulcan/dsh-decision-guard/lib/session-state.d.ts +62 -0
  24. package/node_modules/@openvulcan/dsh-decision-guard/lib/session-state.js +155 -0
  25. package/node_modules/@openvulcan/dsh-decision-guard/lib/version.d.ts +2 -0
  26. package/node_modules/@openvulcan/dsh-decision-guard/lib/version.js +4 -0
  27. package/node_modules/@openvulcan/dsh-decision-guard/package.json +68 -0
  28. package/node_modules/@openvulcan/dsh-vulcan-account/LICENSE +21 -0
  29. package/node_modules/@openvulcan/dsh-vulcan-account/assets/account-icon.png +0 -0
  30. package/node_modules/@openvulcan/dsh-vulcan-account/lib/client.js +565 -0
  31. package/node_modules/@openvulcan/dsh-vulcan-account/lib/index.d.ts +92 -0
  32. package/node_modules/@openvulcan/dsh-vulcan-account/lib/index.js +194 -0
  33. package/node_modules/@openvulcan/dsh-vulcan-account/package.json +57 -0
  34. package/node_modules/@openvulcan/dsh-vulcan-answers/LICENSE +21 -0
  35. package/node_modules/@openvulcan/dsh-vulcan-answers/assets/answers-icon.png +0 -0
  36. package/node_modules/@openvulcan/dsh-vulcan-answers/assets/prompts/answer-mode-interactive.md +79 -0
  37. package/node_modules/@openvulcan/dsh-vulcan-answers/assets/prompts/answer-mode-standard.md +1 -0
  38. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/answer-model.d.ts +258 -0
  39. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/answer-model.js +698 -0
  40. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/client.js +671 -0
  41. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/fences.d.ts +29 -0
  42. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/fences.js +70 -0
  43. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/index.d.ts +19 -0
  44. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/index.js +52 -0
  45. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/limits.d.ts +9 -0
  46. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/limits.js +9 -0
  47. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/prompt.d.ts +22 -0
  48. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/prompt.js +39 -0
  49. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/reply-format.d.ts +20 -0
  50. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/reply-format.js +17 -0
  51. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/session-state.d.ts +66 -0
  52. package/node_modules/@openvulcan/dsh-vulcan-answers/lib/session-state.js +118 -0
  53. package/node_modules/@openvulcan/dsh-vulcan-answers/package.json +59 -0
  54. package/node_modules/@openvulcan/dsh-vulcan-luaskills/LICENSE +21 -0
  55. package/node_modules/@openvulcan/dsh-vulcan-luaskills/assets/luaskills-icon.svg +1 -0
  56. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/client.js +940 -0
  57. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/constants.d.ts +46 -0
  58. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/constants.js +51 -0
  59. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/engine.d.ts +55 -0
  60. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/engine.js +149 -0
  61. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/hub.d.ts +49 -0
  62. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/hub.js +116 -0
  63. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/index.d.ts +26 -0
  64. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/index.js +276 -0
  65. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/protocol.d.ts +65 -0
  66. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/protocol.js +2 -0
  67. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/runtime.d.ts +111 -0
  68. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/runtime.js +281 -0
  69. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/sdk-install.d.ts +26 -0
  70. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/sdk-install.js +87 -0
  71. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/settings.d.ts +79 -0
  72. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/settings.js +165 -0
  73. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/skills.d.ts +34 -0
  74. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/skills.js +61 -0
  75. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/tools.d.ts +59 -0
  76. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/tools.js +107 -0
  77. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/worker.d.ts +10 -0
  78. package/node_modules/@openvulcan/dsh-vulcan-luaskills/lib/worker.js +140 -0
  79. package/node_modules/@openvulcan/dsh-vulcan-luaskills/package.json +57 -0
  80. package/node_modules/@openvulcan/dsh-vulcan-memory/LICENSE +21 -0
  81. package/node_modules/@openvulcan/dsh-vulcan-memory/assets/markdown-memory-guide.md +21 -0
  82. package/node_modules/@openvulcan/dsh-vulcan-memory/assets/memory-curator/SKILL.md +31 -0
  83. package/node_modules/@openvulcan/dsh-vulcan-memory/assets/memory-icon.png +0 -0
  84. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/client.js +1090 -0
  85. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/index.d.ts +30 -0
  86. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/index.js +240 -0
  87. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/inject.d.ts +30 -0
  88. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/inject.js +46 -0
  89. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/constants.d.ts +23 -0
  90. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/constants.js +25 -0
  91. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/document.d.ts +108 -0
  92. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/document.js +373 -0
  93. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/errors.d.ts +14 -0
  94. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/errors.js +31 -0
  95. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/index.d.ts +196 -0
  96. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/index.js +204 -0
  97. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/operations.d.ts +92 -0
  98. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/operations.js +472 -0
  99. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/package.d.ts +126 -0
  100. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/package.js +553 -0
  101. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/registry.d.ts +56 -0
  102. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/registry.js +182 -0
  103. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/scope.d.ts +13 -0
  104. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/scope.js +24 -0
  105. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/search.d.ts +65 -0
  106. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/search.js +227 -0
  107. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/snapshot.d.ts +34 -0
  108. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/snapshot.js +171 -0
  109. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/store.d.ts +72 -0
  110. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/store.js +250 -0
  111. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/timestamp.d.ts +6 -0
  112. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/timestamp.js +12 -0
  113. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/tokens.d.ts +8 -0
  114. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/markdown/tokens.js +38 -0
  115. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/page.d.ts +132 -0
  116. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/page.js +235 -0
  117. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/project.d.ts +14 -0
  118. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/project.js +27 -0
  119. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/settings.d.ts +29 -0
  120. package/node_modules/@openvulcan/dsh-vulcan-memory/lib/settings.js +62 -0
  121. package/node_modules/@openvulcan/dsh-vulcan-memory/package.json +63 -0
  122. package/node_modules/@openvulcan/dsh-vulcan-style/LICENSE +21 -0
  123. package/node_modules/@openvulcan/dsh-vulcan-style/assets/style-icon.png +0 -0
  124. package/node_modules/@openvulcan/dsh-vulcan-style/lib/client.js +1061 -0
  125. package/node_modules/@openvulcan/dsh-vulcan-style/lib/index.d.ts +34 -0
  126. package/node_modules/@openvulcan/dsh-vulcan-style/lib/index.js +42 -0
  127. package/node_modules/@openvulcan/dsh-vulcan-style/package.json +51 -0
  128. package/node_modules/@openvulcan/openvulcan-account/LICENSE +21 -0
  129. package/node_modules/@openvulcan/openvulcan-account/lib/account.d.ts +140 -0
  130. package/node_modules/@openvulcan/openvulcan-account/lib/account.js +347 -0
  131. package/node_modules/@openvulcan/openvulcan-account/lib/index.d.ts +1 -0
  132. package/node_modules/@openvulcan/openvulcan-account/lib/index.js +1 -0
  133. package/node_modules/@openvulcan/openvulcan-account/package.json +29 -0
  134. package/node_modules/@openvulcan/vulcan-decision/LICENSE +21 -0
  135. package/node_modules/@openvulcan/vulcan-decision/README.md +23 -0
  136. package/node_modules/@openvulcan/vulcan-decision/bin/vulcan-decision.js +4 -0
  137. package/node_modules/@openvulcan/vulcan-decision/lib/cli.d.ts +5 -0
  138. package/node_modules/@openvulcan/vulcan-decision/lib/cli.js +267 -0
  139. package/node_modules/@openvulcan/vulcan-decision/lib/cloud/edge.d.ts +211 -0
  140. package/node_modules/@openvulcan/vulcan-decision/lib/cloud/edge.js +594 -0
  141. package/node_modules/@openvulcan/vulcan-decision/lib/download.d.ts +36 -0
  142. package/node_modules/@openvulcan/vulcan-decision/lib/download.js +99 -0
  143. package/node_modules/@openvulcan/vulcan-decision/lib/engine.d.ts +37 -0
  144. package/node_modules/@openvulcan/vulcan-decision/lib/engine.js +39 -0
  145. package/node_modules/@openvulcan/vulcan-decision/lib/hardware.d.ts +105 -0
  146. package/node_modules/@openvulcan/vulcan-decision/lib/hardware.js +207 -0
  147. package/node_modules/@openvulcan/vulcan-decision/lib/home.d.ts +26 -0
  148. package/node_modules/@openvulcan/vulcan-decision/lib/home.js +54 -0
  149. package/node_modules/@openvulcan/vulcan-decision/lib/index.d.ts +17 -0
  150. package/node_modules/@openvulcan/vulcan-decision/lib/index.js +17 -0
  151. package/node_modules/@openvulcan/vulcan-decision/lib/local/engine.d.ts +54 -0
  152. package/node_modules/@openvulcan/vulcan-decision/lib/local/engine.js +157 -0
  153. package/node_modules/@openvulcan/vulcan-decision/lib/local/models.d.ts +126 -0
  154. package/node_modules/@openvulcan/vulcan-decision/lib/local/models.js +261 -0
  155. package/node_modules/@openvulcan/vulcan-decision/lib/local/packs.d.ts +102 -0
  156. package/node_modules/@openvulcan/vulcan-decision/lib/local/packs.js +195 -0
  157. package/node_modules/@openvulcan/vulcan-decision/lib/local/worker.d.ts +61 -0
  158. package/node_modules/@openvulcan/vulcan-decision/lib/local/worker.js +123 -0
  159. package/node_modules/@openvulcan/vulcan-decision/lib/protocol.d.ts +74 -0
  160. package/node_modules/@openvulcan/vulcan-decision/lib/protocol.js +31 -0
  161. package/node_modules/@openvulcan/vulcan-decision/lib/render.d.ts +15 -0
  162. package/node_modules/@openvulcan/vulcan-decision/lib/render.js +33 -0
  163. package/node_modules/@openvulcan/vulcan-decision/lib/version.d.ts +2 -0
  164. package/node_modules/@openvulcan/vulcan-decision/lib/version.js +4 -0
  165. package/node_modules/@openvulcan/vulcan-decision/package.json +40 -0
  166. package/node_modules/@openvulcan/vulcan-decision/python/vulcan_decision_worker.py +363 -0
  167. package/node_modules/@openvulcan/vulcan-decision/runtime-packs/onnx-cpu.json +627 -0
  168. package/node_modules/@openvulcan/vulcan-decision/runtime-packs/onnx-cuda.json +423 -0
  169. package/node_modules/@openvulcan/vulcan-decision/runtime-packs/torch-cpu.json +1047 -0
  170. package/node_modules/@openvulcan/vulcan-decision/runtime-packs/torch-cu128.json +647 -0
  171. package/package.json +53 -4
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The exact LuaSkills artifacts this plugin installs. Each fact is defined here once; the
3
+ * installer, the engine and the pages read it from this module.
4
+ */
5
+ /** One npm package installed into the runtime's own `node_modules`, checked by its lockfile integrity. */
6
+ export interface PinnedPackage {
7
+ readonly name: string;
8
+ readonly version: string;
9
+ readonly tarball: string;
10
+ /** Subresource integrity (`sha512-…`) published by the npm registry. */
11
+ readonly integrity: string;
12
+ }
13
+ /** The Node SDK and its one dependency. Koffi ships prebuilt binaries, so no install script runs. */
14
+ export declare const SDK_PACKAGES: readonly PinnedPackage[];
15
+ /** The SDK package the engine imports. */
16
+ export declare const SDK_PACKAGE: PinnedPackage;
17
+ /** LuaSkills core (JSON FFI) release; also the SDK 0.6.7 default. */
18
+ export declare const LUASKILLS_VERSION = "v0.7.2";
19
+ /**
20
+ * Lua runtime packages release. Pinned, because the SDK otherwise asks the GitHub API for the
21
+ * newest release of the series on every install.
22
+ */
23
+ export declare const LUA_RUNTIME_VERSION = "v0.1.8";
24
+ /** Roughly what the runtime takes on disk once installed, for the install prompt. */
25
+ export declare const RUNTIME_SIZE_MB = 190;
26
+ /** The default skill, installed into the ROOT layer with the runtime; it can be disabled, not removed. */
27
+ export declare const DEFAULT_SKILL: {
28
+ readonly skillId: "vulcan-codekit";
29
+ readonly source: "LuaSkills/vulcan-codekit";
30
+ readonly sourceType: "github";
31
+ };
32
+ /**
33
+ * Codekit entries that only read. Every other LuaSkills entry may change files and follows the
34
+ * session's sandbox mode.
35
+ */
36
+ export declare const READ_ONLY_ENTRIES: ReadonlySet<string>;
37
+ /** The two LuaSkills Hub sites; the China site is a read-only mirror. */
38
+ export declare const HUB_SITES: readonly [{
39
+ readonly site: "global";
40
+ readonly url: "https://hub.luaskills.com";
41
+ }, {
42
+ readonly site: "cn";
43
+ readonly url: "https://hub.luaskills.cn";
44
+ }];
45
+ /** Budget every skill call is given; matches VulcanCode's inline tool result limit. */
46
+ export declare const RESULT_BUDGET_BYTES = 200000;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The exact LuaSkills artifacts this plugin installs. Each fact is defined here once; the
3
+ * installer, the engine and the pages read it from this module.
4
+ */
5
+ /** The Node SDK and its one dependency. Koffi ships prebuilt binaries, so no install script runs. */
6
+ export const SDK_PACKAGES = [
7
+ {
8
+ name: '@luaskills/sdk',
9
+ version: '0.6.7',
10
+ tarball: 'https://registry.npmjs.org/@luaskills/sdk/-/sdk-0.6.7.tgz',
11
+ integrity: 'sha512-1yEvpMiPiEDDZK3/z1Deq3Hq7fb/SBaznObFjareUyBWoWCurT5jSHpzgex3ioyHnB3i6mXkrfvpukcEoN866Q==',
12
+ },
13
+ {
14
+ name: 'koffi',
15
+ version: '2.16.3',
16
+ tarball: 'https://registry.npmjs.org/koffi/-/koffi-2.16.3.tgz',
17
+ integrity: 'sha512-E9y1AsgYGlaxMhcZzHr8y96QF2U5XzA12GGVAfbWqIubTwPNMXQarfBzePNXHe0xtIEtNd6ifAv3GAKYGUeBAQ==',
18
+ },
19
+ ];
20
+ /** The SDK package the engine imports. */
21
+ export const SDK_PACKAGE = SDK_PACKAGES[0];
22
+ /** LuaSkills core (JSON FFI) release; also the SDK 0.6.7 default. */
23
+ export const LUASKILLS_VERSION = 'v0.7.2';
24
+ /**
25
+ * Lua runtime packages release. Pinned, because the SDK otherwise asks the GitHub API for the
26
+ * newest release of the series on every install.
27
+ */
28
+ export const LUA_RUNTIME_VERSION = 'v0.1.8';
29
+ /** Roughly what the runtime takes on disk once installed, for the install prompt. */
30
+ export const RUNTIME_SIZE_MB = 190;
31
+ /** The default skill, installed into the ROOT layer with the runtime; it can be disabled, not removed. */
32
+ export const DEFAULT_SKILL = { skillId: 'vulcan-codekit', source: 'LuaSkills/vulcan-codekit', sourceType: 'github' };
33
+ /**
34
+ * Codekit entries that only read. Every other LuaSkills entry may change files and follows the
35
+ * session's sandbox mode.
36
+ */
37
+ export const READ_ONLY_ENTRIES = new Set([
38
+ 'vulcan-codekit-repo-map',
39
+ 'vulcan-codekit-ast-detail',
40
+ 'vulcan-codekit-ast-tree',
41
+ 'vulcan-codekit-rg',
42
+ 'vulcan-codekit-markdown-menu',
43
+ 'vulcan-codekit-node-source',
44
+ ]);
45
+ /** The two LuaSkills Hub sites; the China site is a read-only mirror. */
46
+ export const HUB_SITES = [
47
+ { site: 'global', url: 'https://hub.luaskills.com' },
48
+ { site: 'cn', url: 'https://hub.luaskills.cn' },
49
+ ];
50
+ /** Budget every skill call is given; matches VulcanCode's inline tool result limit. */
51
+ export const RESULT_BUDGET_BYTES = 200_000;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The Host side of the LuaSkills worker: one request at a time per call site, answered by id.
3
+ * The worker owns every SDK call; when it exits, every pending request fails with the reason.
4
+ *
5
+ * The worker is a child process, not a thread: the LuaSkills core library it loads stays mapped
6
+ * until its process ends, and Windows refuses to delete a mapped library, so only a process lets
7
+ * the runtime be removed or reinstalled while dsh runs. A native crash also stays in the child.
8
+ */
9
+ import type { ApplyResult, EntryDescriptor, HelpDetail, InvocationResult, SkillHelp } from './protocol.js';
10
+ export type DownloadListener = (role: string, received: number, total: number | null) => void;
11
+ export declare class LuaSkillsWorker {
12
+ private readonly onExit;
13
+ private readonly worker;
14
+ private readonly pending;
15
+ private next;
16
+ private exitError;
17
+ /** Set once the Host asked the worker to stop; its exit is then not a crash. */
18
+ private stopping;
19
+ private readonly started;
20
+ /** Settles once the worker process has ended and released the core library. */
21
+ private readonly exited;
22
+ /** Set while a runtime install reports its downloads. */
23
+ onDownload: DownloadListener | undefined;
24
+ /**
25
+ * @param sdkEntry - absolute path of the SDK's entry module.
26
+ * @param onExit - called once if the worker stops without being asked to.
27
+ */
28
+ constructor(sdkEntry: string, onExit: (error: Error) => void);
29
+ private fail;
30
+ private request;
31
+ installRuntime(params: {
32
+ runtimeRoot: string;
33
+ luaskillsVersion: string;
34
+ luaRuntimeVersion: string;
35
+ }): Promise<void>;
36
+ start(params: {
37
+ runtimeRoot: string;
38
+ poolConfig: object;
39
+ hostOptions: object;
40
+ }): Promise<void>;
41
+ entries(): Promise<EntryDescriptor[]>;
42
+ help(): Promise<SkillHelp[]>;
43
+ helpDetail(skillId: string, flow?: string): Promise<HelpDetail | null>;
44
+ call(name: string, args: unknown, context: unknown): Promise<InvocationResult>;
45
+ install(root: string, request: object): Promise<ApplyResult>;
46
+ update(root: string, request: object): Promise<ApplyResult>;
47
+ uninstall(root: string, skillId: string): Promise<ApplyResult>;
48
+ setEnabled(skillId: string, enabled: boolean): Promise<unknown>;
49
+ /** The worker's process id; the SDK names its scratch folders after it. */
50
+ get pid(): number | undefined;
51
+ /** Close the engine, then the process; nothing is reported as a crash. */
52
+ stop(): Promise<void>;
53
+ /** Stop at once, abandoning whatever the worker is doing; resolves once the process is gone. */
54
+ kill(): Promise<void>;
55
+ }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The Host side of the LuaSkills worker: one request at a time per call site, answered by id.
3
+ * The worker owns every SDK call; when it exits, every pending request fails with the reason.
4
+ *
5
+ * The worker is a child process, not a thread: the LuaSkills core library it loads stays mapped
6
+ * until its process ends, and Windows refuses to delete a mapped library, so only a process lets
7
+ * the runtime be removed or reinstalled while dsh runs. A native crash also stays in the child.
8
+ */
9
+ import { fork } from 'node:child_process';
10
+ import { fileURLToPath, pathToFileURL } from 'node:url';
11
+ export class LuaSkillsWorker {
12
+ onExit;
13
+ worker;
14
+ pending = new Map();
15
+ next = 0;
16
+ exitError;
17
+ /** Set once the Host asked the worker to stop; its exit is then not a crash. */
18
+ stopping = false;
19
+ started;
20
+ /** Settles once the worker process has ended and released the core library. */
21
+ exited;
22
+ /** Set while a runtime install reports its downloads. */
23
+ onDownload;
24
+ /**
25
+ * @param sdkEntry - absolute path of the SDK's entry module.
26
+ * @param onExit - called once if the worker stops without being asked to.
27
+ */
28
+ constructor(sdkEntry, onExit) {
29
+ this.onExit = onExit;
30
+ this.worker = fork(fileURLToPath(new URL('./worker.js', import.meta.url)), [pathToFileURL(sdkEntry).href], {
31
+ // Inspector or loader flags of dsh's own process do not apply to the worker; under Electron
32
+ // the executable runs as plain Node.js.
33
+ execArgv: [],
34
+ env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' },
35
+ serialization: 'advanced',
36
+ stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
37
+ });
38
+ let ready;
39
+ let failed;
40
+ this.started = new Promise((resolve, reject) => { ready = resolve; failed = reject; });
41
+ this.started.catch(() => { });
42
+ this.exited = new Promise((resolve) => {
43
+ this.worker.once('exit', () => { resolve(); });
44
+ // A process that never started has no exit to wait for.
45
+ this.worker.once('error', () => { if (this.worker.pid === undefined)
46
+ resolve(); });
47
+ });
48
+ this.worker.on('message', (message) => {
49
+ if ('event' in message) {
50
+ if (message.event === 'ready')
51
+ ready();
52
+ else
53
+ this.onDownload?.(message.role, message.received, message.total);
54
+ return;
55
+ }
56
+ const waiter = this.pending.get(message.id);
57
+ if (waiter === undefined)
58
+ return;
59
+ this.pending.delete(message.id);
60
+ if (message.ok)
61
+ waiter.resolve(message.value);
62
+ else
63
+ waiter.reject(new Error(message.error));
64
+ });
65
+ // A failed SDK import surfaces as `error` or `exit` before `ready`; settling `started` twice is a no-op.
66
+ this.worker.on('error', (error) => {
67
+ failed(error);
68
+ this.fail(error);
69
+ });
70
+ this.worker.on('exit', (code, signal) => {
71
+ const error = new Error(`the LuaSkills worker stopped (${signal === null ? `exit code ${code}` : signal})`);
72
+ failed(error);
73
+ this.fail(error);
74
+ });
75
+ }
76
+ fail(error) {
77
+ if (this.exitError !== undefined)
78
+ return;
79
+ this.exitError = this.stopping ? new Error('the LuaSkills worker was stopped') : error;
80
+ for (const waiter of this.pending.values())
81
+ waiter.reject(this.exitError);
82
+ this.pending.clear();
83
+ if (!this.stopping)
84
+ this.onExit(error);
85
+ }
86
+ async request(method, params = null, internal = false) {
87
+ await this.started;
88
+ if (this.exitError !== undefined)
89
+ throw this.exitError;
90
+ if (this.stopping && !internal)
91
+ throw new Error('the LuaSkills worker is stopping');
92
+ const id = ++this.next;
93
+ return await new Promise((resolve, reject) => {
94
+ this.pending.set(id, { resolve: resolve, reject });
95
+ this.worker.send({ id, method, params });
96
+ });
97
+ }
98
+ installRuntime(params) {
99
+ return this.request('installRuntime', params);
100
+ }
101
+ start(params) {
102
+ return this.request('start', params);
103
+ }
104
+ entries() {
105
+ return this.request('entries');
106
+ }
107
+ help() {
108
+ return this.request('help');
109
+ }
110
+ helpDetail(skillId, flow) {
111
+ return this.request('helpDetail', { skillId, ...flow === undefined ? {} : { flow } });
112
+ }
113
+ call(name, args, context) {
114
+ return this.request('call', { name, args, context });
115
+ }
116
+ install(root, request) {
117
+ return this.request('install', { root, request });
118
+ }
119
+ update(root, request) {
120
+ return this.request('update', { root, request });
121
+ }
122
+ uninstall(root, skillId) {
123
+ return this.request('uninstall', { root, skillId });
124
+ }
125
+ setEnabled(skillId, enabled) {
126
+ return this.request('setEnabled', { skillId, enabled });
127
+ }
128
+ /** The worker's process id; the SDK names its scratch folders after it. */
129
+ get pid() {
130
+ return this.worker.pid;
131
+ }
132
+ /** Close the engine, then the process; nothing is reported as a crash. */
133
+ async stop() {
134
+ this.stopping = true;
135
+ // A call still running holds the engine; it gets a few seconds before the process is ended.
136
+ await Promise.race([
137
+ this.request('stop', null, true),
138
+ new Promise(resolve => setTimeout(resolve, 5000)),
139
+ ]).catch(() => { });
140
+ await this.kill();
141
+ }
142
+ /** Stop at once, abandoning whatever the worker is doing; resolves once the process is gone. */
143
+ async kill() {
144
+ this.stopping = true;
145
+ if (this.worker.exitCode === null && this.worker.signalCode === null)
146
+ this.worker.kill();
147
+ await this.exited;
148
+ }
149
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Read-only LuaSkills Hub catalog, fetched by the Host for the LuaSkills page. Installing stays
3
+ * inside LuaSkills through the `official_hub` source, against the same Hub base URL the engine
4
+ * uses. Limits follow VulcanCode's Hub client.
5
+ */
6
+ export declare class HubError extends Error {
7
+ readonly code: string;
8
+ constructor(message: string, code?: string);
9
+ }
10
+ export interface HubContent {
11
+ readonly requested_locale?: string;
12
+ readonly locale?: string;
13
+ /** `original`, `translation`, or `original_fallback` while no translation exists. */
14
+ readonly kind?: string;
15
+ readonly summary?: string;
16
+ readonly intro?: string;
17
+ readonly features?: readonly string[];
18
+ readonly readme?: string | null;
19
+ }
20
+ export interface HubSkill {
21
+ readonly skill_id: string;
22
+ readonly publisher?: string;
23
+ readonly display_name?: string;
24
+ readonly summary?: string;
25
+ readonly repository_url?: string;
26
+ readonly homepage_url?: string;
27
+ readonly license?: string;
28
+ readonly tags?: readonly string[];
29
+ readonly latest_version?: string;
30
+ readonly updated_at?: string;
31
+ readonly content?: HubContent | null;
32
+ }
33
+ export interface HubPage {
34
+ readonly hub: string;
35
+ readonly items: readonly HubSkill[];
36
+ readonly nextCursor: string | null;
37
+ }
38
+ export interface HubDetail {
39
+ readonly hub: string;
40
+ readonly skill: HubSkill;
41
+ readonly original: HubContent | null;
42
+ readonly latest: {
43
+ readonly version: string;
44
+ readonly readme?: string;
45
+ readonly published_at?: string;
46
+ };
47
+ }
48
+ export declare function searchHub(base: string, query: string, cursor: string | null, locale: string | null): Promise<HubPage>;
49
+ export declare function hubSkill(base: string, skillId: string, locale: string | null): Promise<HubDetail>;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Read-only LuaSkills Hub catalog, fetched by the Host for the LuaSkills page. Installing stays
3
+ * inside LuaSkills through the `official_hub` source, against the same Hub base URL the engine
4
+ * uses. Limits follow VulcanCode's Hub client.
5
+ */
6
+ const PAGE_SIZE = 24;
7
+ const MAX_QUERY_CHARS = 100;
8
+ const MAX_CURSOR_CHARS = 12;
9
+ const MAX_SKILL_ID_CHARS = 64;
10
+ const MAX_LOCALE_CHARS = 35;
11
+ const SEARCH_MAX_BYTES = 1024 * 1024;
12
+ /** A translated README can exceed the original. */
13
+ const DETAIL_MAX_BYTES = 2 * 1024 * 1024;
14
+ const REQUEST_TIMEOUT_MS = 30_000;
15
+ export class HubError extends Error {
16
+ code;
17
+ constructor(message, code = 'hub_failed') {
18
+ super(message);
19
+ this.code = code;
20
+ }
21
+ }
22
+ function apiUrl(base, segments) {
23
+ let url;
24
+ try {
25
+ url = new URL(base.endsWith('/') ? base : `${base}/`);
26
+ }
27
+ catch {
28
+ throw new HubError(`the LuaSkills Hub address ${base} is not a URL`, 'invalid_request');
29
+ }
30
+ url.pathname = `${url.pathname.replace(/\/+$/, '')}/api/v1/${segments.map(encodeURIComponent).join('/')}`;
31
+ return url;
32
+ }
33
+ function setLocale(url, locale) {
34
+ if (locale === null || locale === '')
35
+ return;
36
+ if (locale.length > MAX_LOCALE_CHARS)
37
+ throw new HubError('the language code is too long', 'invalid_request');
38
+ url.searchParams.set('lang', locale);
39
+ }
40
+ async function fetchJson(url, maxBytes, what) {
41
+ const response = await fetch(url, { signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), headers: { accept: 'application/json' } });
42
+ const text = await readCapped(response, maxBytes, what);
43
+ if (!response.ok) {
44
+ let message = text.slice(0, 200);
45
+ try {
46
+ const body = JSON.parse(text);
47
+ message = body.error?.message ?? message;
48
+ }
49
+ catch {
50
+ // Not JSON; the start of the text is the message.
51
+ }
52
+ throw new HubError(`LuaSkills Hub ${what} failed: HTTP ${response.status} ${message}`.trim());
53
+ }
54
+ try {
55
+ return JSON.parse(text);
56
+ }
57
+ catch {
58
+ throw new HubError(`LuaSkills Hub returned an invalid ${what} response`);
59
+ }
60
+ }
61
+ async function readCapped(response, maxBytes, what) {
62
+ if (response.body === null)
63
+ return '';
64
+ const chunks = [];
65
+ let size = 0;
66
+ for await (const chunk of response.body) {
67
+ size += chunk.byteLength;
68
+ if (size > maxBytes)
69
+ throw new HubError(`LuaSkills Hub ${what} response is larger than ${maxBytes} bytes`);
70
+ chunks.push(chunk);
71
+ }
72
+ return Buffer.concat(chunks).toString('utf8');
73
+ }
74
+ export async function searchHub(base, query, cursor, locale) {
75
+ const text = query.trim();
76
+ if ([...text].length > MAX_QUERY_CHARS)
77
+ throw new HubError(`the search text is longer than ${MAX_QUERY_CHARS} characters`, 'invalid_request');
78
+ if (cursor !== null && cursor.length > MAX_CURSOR_CHARS)
79
+ throw new HubError('the page cursor is not valid', 'invalid_request');
80
+ const url = apiUrl(base, ['skills', 'search']);
81
+ url.searchParams.set('limit', String(PAGE_SIZE));
82
+ if (text !== '')
83
+ url.searchParams.set('q', text);
84
+ if (cursor !== null && cursor !== '')
85
+ url.searchParams.set('cursor', cursor);
86
+ setLocale(url, locale);
87
+ const body = await fetchJson(url, SEARCH_MAX_BYTES, 'search');
88
+ if (!Array.isArray(body.items) || !body.items.every(isSkill))
89
+ throw new HubError('LuaSkills Hub returned an invalid search response');
90
+ return {
91
+ hub: base.replace(/\/+$/, ''),
92
+ items: body.items,
93
+ nextCursor: typeof body.next_cursor === 'string' && body.next_cursor !== '' ? body.next_cursor : null,
94
+ };
95
+ }
96
+ export async function hubSkill(base, skillId, locale) {
97
+ const id = skillId.trim();
98
+ if (id === '' || [...id].length > MAX_SKILL_ID_CHARS) {
99
+ throw new HubError(`the skill id must be 1 to ${MAX_SKILL_ID_CHARS} characters`, 'invalid_request');
100
+ }
101
+ const url = apiUrl(base, ['skills', id]);
102
+ setLocale(url, locale);
103
+ const body = await fetchJson(url, DETAIL_MAX_BYTES, 'skill detail');
104
+ const latest = body.latest;
105
+ if (!isSkill(body.skill) || typeof latest?.version !== 'string')
106
+ throw new HubError('LuaSkills Hub returned an invalid skill detail response');
107
+ return {
108
+ hub: base.replace(/\/+$/, ''),
109
+ skill: body.skill,
110
+ original: typeof body.original === 'object' && body.original !== null ? body.original : null,
111
+ latest,
112
+ };
113
+ }
114
+ function isSkill(value) {
115
+ return typeof value === 'object' && value !== null && typeof value.skill_id === 'string';
116
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * LuaSkills in dsh. The runtime is not part of this package: the user installs it from the
3
+ * LuaSkills settings page, and from then on every enabled skill entry is a dsh tool, every
4
+ * loaded skill is in dsh's skill catalog, and the page manages installed skills and the Hub.
5
+ * The pages talk to the exact `/api/vulcan-luaskills/*` routes inside dsh's authenticated
6
+ * connection.
7
+ */
8
+ import type { Context } from '@deepseek-ai/cordis';
9
+ import { type InstalledSkill } from './skills.js';
10
+ export type { RuntimeState, RuntimeView } from './runtime.js';
11
+ export type { LuaSkillsSettings } from './settings.js';
12
+ export type { InstalledSkill } from './skills.js';
13
+ export declare const name = "vulcan-luaskills";
14
+ export declare const inject: string[];
15
+ /** Prefix of every page route, below dsh's `/api`. Also restated in `client/shared.ts`. */
16
+ export declare const ROUTE_PREFIX = "/api/vulcan-luaskills/";
17
+ /** An installed skill with whether the engine loaded it. */
18
+ export interface SkillRow extends InstalledSkill {
19
+ readonly loaded: boolean;
20
+ readonly tools: readonly string[];
21
+ }
22
+ export declare function apply(ctx: Context): void;
23
+ /** Fetch-shaped handler of one page route. */
24
+ type Handler = (request: Request, url: URL) => Promise<unknown>;
25
+ /** Answer one page request; failures carry their code, never a stack. */
26
+ export declare function handle(handler: Handler, request: Request): Promise<Response>;