dsh-plugin-local-infer 0.1.3 → 0.1.4

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 (250) hide show
  1. package/README.md +22 -4
  2. package/cordis.patch.yml +7 -0
  3. package/docs/zh/README.md +14 -2
  4. package/dsh/client.js +4195 -4522
  5. package/package.json +28 -11
  6. package/packages/core/lib/adapter.d.ts +133 -9
  7. package/packages/core/lib/adapter.js +74 -1
  8. package/packages/core/lib/config.d.ts +1 -1
  9. package/packages/core/lib/config.js +1 -1
  10. package/packages/core/lib/debug.d.ts +1 -1
  11. package/packages/core/lib/debug.js +1 -1
  12. package/packages/core/lib/defaults.d.ts +1 -1
  13. package/packages/core/lib/defaults.js +1 -1
  14. package/packages/core/lib/deps.d.ts +44 -17
  15. package/packages/core/lib/deps.js +24 -8
  16. package/packages/core/lib/estimator.d.ts +1 -1
  17. package/packages/core/lib/estimator.js +1 -1
  18. package/packages/core/lib/guideline.d.ts +1 -1
  19. package/packages/core/lib/guideline.js +1 -1
  20. package/packages/core/lib/hardware.d.ts +1 -1
  21. package/packages/core/lib/hardware.js +1 -1
  22. package/packages/core/lib/hf-cache.d.ts +70 -0
  23. package/packages/core/lib/hf-cache.js +83 -0
  24. package/packages/core/lib/index.d.ts +16 -9
  25. package/packages/core/lib/index.js +10 -6
  26. package/packages/core/lib/infer-cache.d.ts +39 -0
  27. package/packages/core/lib/infer-cache.js +53 -0
  28. package/packages/core/lib/launch-command.d.ts +8 -4
  29. package/packages/core/lib/launch-command.js +13 -6
  30. package/packages/core/lib/launch-record.d.ts +1 -1
  31. package/packages/core/lib/launch-record.js +1 -1
  32. package/packages/core/lib/logs.d.ts +8 -1
  33. package/packages/core/lib/logs.js +12 -4
  34. package/packages/core/lib/models.d.ts +120 -14
  35. package/packages/core/lib/models.js +209 -17
  36. package/packages/core/lib/parameter.d.ts +31 -3
  37. package/packages/core/lib/parameter.js +1 -1
  38. package/packages/core/lib/progress.d.ts +54 -0
  39. package/packages/core/lib/progress.js +120 -0
  40. package/packages/core/lib/registrar.d.ts +20 -9
  41. package/packages/core/lib/registrar.js +27 -7
  42. package/packages/core/lib/reserve.d.ts +11 -3
  43. package/packages/core/lib/reserve.js +6 -4
  44. package/packages/core/lib/status.d.ts +12 -6
  45. package/packages/core/lib/status.js +21 -10
  46. package/packages/core/lib/sudo.d.ts +80 -0
  47. package/packages/core/lib/sudo.js +78 -0
  48. package/packages/core/package.json +1 -1
  49. package/packages/orchestrator/lib/config.d.ts +63 -0
  50. package/packages/orchestrator/lib/config.js +111 -0
  51. package/packages/orchestrator/lib/index.d.ts +51 -0
  52. package/packages/orchestrator/lib/index.js +73 -0
  53. package/packages/orchestrator/lib/route.d.ts +60 -0
  54. package/packages/orchestrator/lib/route.js +159 -0
  55. package/packages/orchestrator/locale/en.json +6 -0
  56. package/packages/orchestrator/package.json +39 -0
  57. package/packages/orchestrator/prompt.md +87 -0
  58. package/packages/providers/lib/acquire.d.ts +92 -14
  59. package/packages/providers/lib/acquire.js +215 -37
  60. package/packages/providers/lib/adapters.d.ts +136 -12
  61. package/packages/providers/lib/adapters.js +597 -70
  62. package/packages/providers/lib/debug.d.ts +1 -1
  63. package/packages/providers/lib/debug.js +1 -1
  64. package/packages/providers/lib/deps.d.ts +27 -230
  65. package/packages/providers/lib/deps.js +61 -214
  66. package/packages/providers/lib/engines/basalt/basalt.d.ts +130 -0
  67. package/packages/providers/lib/engines/basalt/basalt.js +304 -0
  68. package/packages/providers/lib/engines/basalt/basaltAdapter.d.ts +85 -0
  69. package/packages/providers/lib/engines/basalt/basaltAdapter.js +439 -0
  70. package/packages/providers/lib/engines/basalt/basaltLinux.d.ts +23 -0
  71. package/packages/providers/lib/engines/basalt/basaltLinux.js +47 -0
  72. package/packages/providers/lib/engines/basalt/basaltMacOS.d.ts +17 -0
  73. package/packages/providers/lib/engines/basalt/basaltMacOS.js +19 -0
  74. package/packages/providers/lib/engines/basalt/basaltWindows.d.ts +24 -0
  75. package/packages/providers/lib/engines/basalt/basaltWindows.js +49 -0
  76. package/packages/providers/lib/engines/engineOs.d.ts +24 -0
  77. package/packages/providers/lib/engines/engineOs.js +17 -0
  78. package/packages/providers/lib/engines/{hyperqwen.d.ts → hyperqwen/hyperqwen.d.ts} +2 -2
  79. package/packages/providers/lib/engines/{hyperqwen.js → hyperqwen/hyperqwen.js} +14 -2
  80. package/packages/providers/lib/engines/{hyperqwenAdapter.d.ts → hyperqwen/hyperqwenAdapter.d.ts} +6 -6
  81. package/packages/providers/lib/engines/{hyperqwenAdapter.js → hyperqwen/hyperqwenAdapter.js} +24 -14
  82. package/packages/providers/lib/engines/hyperqwen/hyperqwenArch.d.ts +9 -0
  83. package/packages/providers/lib/engines/hyperqwen/hyperqwenArch.js +9 -0
  84. package/packages/providers/lib/engines/hyperqwen/hyperqwenDebian.d.ts +9 -0
  85. package/packages/providers/lib/engines/hyperqwen/hyperqwenDebian.js +9 -0
  86. package/packages/providers/lib/engines/hyperqwen/hyperqwenFedora.d.ts +9 -0
  87. package/packages/providers/lib/engines/hyperqwen/hyperqwenFedora.js +9 -0
  88. package/packages/providers/lib/engines/hyperqwen/hyperqwenLinux.d.ts +10 -0
  89. package/packages/providers/lib/engines/hyperqwen/hyperqwenLinux.js +14 -0
  90. package/packages/providers/lib/engines/hyperqwen/hyperqwenMacOS.d.ts +9 -0
  91. package/packages/providers/lib/engines/hyperqwen/hyperqwenMacOS.js +9 -0
  92. package/packages/providers/lib/engines/hyperqwen/hyperqwenWindows.d.ts +9 -0
  93. package/packages/providers/lib/engines/hyperqwen/hyperqwenWindows.js +9 -0
  94. package/packages/providers/lib/engines/{infernix.d.ts → infernix/infernix.d.ts} +7 -4
  95. package/packages/providers/lib/engines/{infernix.js → infernix/infernix.js} +52 -7
  96. package/packages/providers/lib/engines/{infernixAdapter.d.ts → infernix/infernixAdapter.d.ts} +5 -6
  97. package/packages/providers/lib/engines/{infernixAdapter.js → infernix/infernixAdapter.js} +75 -42
  98. package/packages/providers/lib/engines/infernix/infernixArch.d.ts +9 -0
  99. package/packages/providers/lib/engines/infernix/infernixArch.js +9 -0
  100. package/packages/providers/lib/engines/infernix/infernixDebian.d.ts +9 -0
  101. package/packages/providers/lib/engines/infernix/infernixDebian.js +9 -0
  102. package/packages/providers/lib/engines/infernix/infernixFedora.d.ts +9 -0
  103. package/packages/providers/lib/engines/infernix/infernixFedora.js +9 -0
  104. package/packages/providers/lib/engines/infernix/infernixLinux.d.ts +17 -0
  105. package/packages/providers/lib/engines/infernix/infernixLinux.js +35 -0
  106. package/packages/providers/lib/engines/infernix/infernixMacOS.d.ts +16 -0
  107. package/packages/providers/lib/engines/infernix/infernixMacOS.js +18 -0
  108. package/packages/providers/lib/engines/infernix/infernixWindows.d.ts +16 -0
  109. package/packages/providers/lib/engines/infernix/infernixWindows.js +34 -0
  110. package/packages/providers/lib/engines/{llamacpp.d.ts → llamacpp/llamacpp.d.ts} +2 -2
  111. package/packages/providers/lib/engines/{llamacpp.js → llamacpp/llamacpp.js} +12 -2
  112. package/packages/providers/lib/engines/{llamacppAdapter.d.ts → llamacpp/llamacppAdapter.d.ts} +5 -6
  113. package/packages/providers/lib/engines/{llamacppAdapter.js → llamacpp/llamacppAdapter.js} +87 -45
  114. package/packages/providers/lib/engines/llamacpp/llamacppArch.d.ts +9 -0
  115. package/packages/providers/lib/engines/llamacpp/llamacppArch.js +9 -0
  116. package/packages/providers/lib/engines/llamacpp/llamacppDebian.d.ts +9 -0
  117. package/packages/providers/lib/engines/llamacpp/llamacppDebian.js +9 -0
  118. package/packages/providers/lib/engines/llamacpp/llamacppFedora.d.ts +9 -0
  119. package/packages/providers/lib/engines/llamacpp/llamacppFedora.js +9 -0
  120. package/packages/providers/lib/engines/llamacpp/llamacppLinux.d.ts +17 -0
  121. package/packages/providers/lib/engines/llamacpp/llamacppLinux.js +28 -0
  122. package/packages/providers/lib/engines/llamacpp/llamacppMacOS.d.ts +15 -0
  123. package/packages/providers/lib/engines/llamacpp/llamacppMacOS.js +17 -0
  124. package/packages/providers/lib/engines/llamacpp/llamacppWindows.d.ts +15 -0
  125. package/packages/providers/lib/engines/llamacpp/llamacppWindows.js +26 -0
  126. package/packages/providers/lib/engines/{ninfer.d.ts → ninfer/ninfer.d.ts} +2 -2
  127. package/packages/providers/lib/engines/{ninfer.js → ninfer/ninfer.js} +24 -2
  128. package/packages/providers/lib/engines/{ninferAdapter.d.ts → ninfer/ninferAdapter.d.ts} +5 -6
  129. package/packages/providers/lib/engines/{ninferAdapter.js → ninfer/ninferAdapter.js} +123 -55
  130. package/packages/providers/lib/engines/ninfer/ninferArch.d.ts +9 -0
  131. package/packages/providers/lib/engines/ninfer/ninferArch.js +9 -0
  132. package/packages/providers/lib/engines/ninfer/ninferDebian.d.ts +9 -0
  133. package/packages/providers/lib/engines/ninfer/ninferDebian.js +9 -0
  134. package/packages/providers/lib/engines/ninfer/ninferFedora.d.ts +9 -0
  135. package/packages/providers/lib/engines/ninfer/ninferFedora.js +9 -0
  136. package/packages/providers/lib/engines/ninfer/ninferLinux.d.ts +17 -0
  137. package/packages/providers/lib/engines/ninfer/ninferLinux.js +37 -0
  138. package/packages/providers/lib/engines/ninfer/ninferMacOS.d.ts +15 -0
  139. package/packages/providers/lib/engines/ninfer/ninferMacOS.js +17 -0
  140. package/packages/providers/lib/engines/ninfer/ninferWindows.d.ts +29 -0
  141. package/packages/providers/lib/engines/ninfer/ninferWindows.js +59 -0
  142. package/packages/providers/lib/engines/strata/strata.d.ts +1 -0
  143. package/packages/providers/lib/engines/{strata.js → strata/strata.js} +70 -3
  144. package/packages/providers/lib/engines/{strataAdapter.d.ts → strata/strataAdapter.d.ts} +5 -6
  145. package/packages/providers/lib/engines/{strataAdapter.js → strata/strataAdapter.js} +147 -111
  146. package/packages/providers/lib/engines/strata/strataArch.d.ts +9 -0
  147. package/packages/providers/lib/engines/strata/strataArch.js +9 -0
  148. package/packages/providers/lib/engines/strata/strataDebian.d.ts +9 -0
  149. package/packages/providers/lib/engines/strata/strataDebian.js +9 -0
  150. package/packages/providers/lib/engines/strata/strataFedora.d.ts +9 -0
  151. package/packages/providers/lib/engines/strata/strataFedora.js +9 -0
  152. package/packages/providers/lib/engines/strata/strataLinux.d.ts +21 -0
  153. package/packages/providers/lib/engines/strata/strataLinux.js +30 -0
  154. package/packages/providers/lib/engines/strata/strataMacOS.d.ts +16 -0
  155. package/packages/providers/lib/engines/strata/strataMacOS.js +17 -0
  156. package/packages/providers/lib/engines/strata/strataWindows.d.ts +27 -0
  157. package/packages/providers/lib/engines/strata/strataWindows.js +37 -0
  158. package/packages/providers/lib/engines.d.ts +7 -5
  159. package/packages/providers/lib/engines.js +21 -10
  160. package/packages/providers/lib/guidelines.d.ts +5 -4
  161. package/packages/providers/lib/guidelines.js +18 -5
  162. package/packages/providers/lib/index.d.ts +33 -29
  163. package/packages/providers/lib/index.js +45 -33
  164. package/packages/providers/lib/model-defaults.d.ts +5 -1
  165. package/packages/providers/lib/model-defaults.js +25 -1
  166. package/packages/providers/lib/platform.d.ts +8 -5
  167. package/packages/providers/lib/platform.js +23 -9
  168. package/packages/providers/lib/presets.d.ts +6 -4
  169. package/packages/providers/lib/presets.js +53 -5
  170. package/packages/providers/lib/systemDeps.d.ts +313 -0
  171. package/packages/providers/lib/systemDeps.js +284 -0
  172. package/packages/providers/lib/vram.d.ts +34 -8
  173. package/packages/providers/lib/vram.js +81 -8
  174. package/packages/providers/package.json +2 -2
  175. package/packages/service/lib/index.d.ts +176 -21
  176. package/packages/service/lib/index.js +589 -86
  177. package/packages/service/lib/launch-target.d.ts +19 -0
  178. package/packages/service/lib/launch-target.js +28 -0
  179. package/packages/service/lib/run-logs.d.ts +72 -0
  180. package/packages/service/lib/run-logs.js +125 -0
  181. package/packages/service/lib/types.d.ts +163 -6
  182. package/packages/service/lib/types.js +1 -1
  183. package/packages/service/package.json +2 -2
  184. package/packages/tool/lib/index.d.ts +1 -1
  185. package/packages/tool/lib/index.js +1 -1
  186. package/packages/tool/package.json +2 -2
  187. package/packages/ui/lib/config.d.ts +12 -2
  188. package/packages/ui/lib/config.js +18 -2
  189. package/packages/ui/lib/deps.d.ts +1 -1
  190. package/packages/ui/lib/deps.js +1 -1
  191. package/packages/ui/lib/form.d.ts +1 -1
  192. package/packages/ui/lib/form.js +1 -1
  193. package/packages/ui/lib/index.d.ts +7 -1
  194. package/packages/ui/lib/index.js +12 -2
  195. package/packages/ui/lib/meter.d.ts +1 -1
  196. package/packages/ui/lib/meter.js +1 -1
  197. package/packages/ui/lib/ops/engine.d.ts +142 -34
  198. package/packages/ui/lib/ops/engine.js +469 -265
  199. package/packages/ui/lib/ops/get-steps.d.ts +98 -0
  200. package/packages/ui/lib/ops/get-steps.js +359 -0
  201. package/packages/ui/lib/ops/hf.d.ts +26 -11
  202. package/packages/ui/lib/ops/hf.js +115 -25
  203. package/packages/ui/lib/ops/logs.d.ts +70 -15
  204. package/packages/ui/lib/ops/logs.js +96 -35
  205. package/packages/ui/lib/ops/model.d.ts +2 -10
  206. package/packages/ui/lib/ops/model.js +9 -16
  207. package/packages/ui/lib/request.d.ts +1 -1
  208. package/packages/ui/lib/request.js +1 -1
  209. package/packages/ui/lib/route.d.ts +22 -6
  210. package/packages/ui/lib/route.js +32 -9
  211. package/packages/ui/lib/routes/chat-template.d.ts +1 -14
  212. package/packages/ui/lib/routes/chat-template.js +1 -37
  213. package/packages/ui/lib/routes/deps.d.ts +1 -16
  214. package/packages/ui/lib/routes/deps.js +1 -27
  215. package/packages/ui/lib/routes/download.d.ts +1 -16
  216. package/packages/ui/lib/routes/download.js +1 -48
  217. package/packages/ui/lib/routes/get.d.ts +1 -18
  218. package/packages/ui/lib/routes/get.js +66 -17
  219. package/packages/ui/lib/routes/install.d.ts +1 -1
  220. package/packages/ui/lib/routes/install.js +1 -1
  221. package/packages/ui/lib/routes/launch.d.ts +13 -7
  222. package/packages/ui/lib/routes/launch.js +33 -9
  223. package/packages/ui/lib/routes/logs.d.ts +57 -0
  224. package/packages/ui/lib/routes/logs.js +117 -0
  225. package/packages/ui/lib/routes/provider-delete.d.ts +1 -1
  226. package/packages/ui/lib/routes/provider-delete.js +1 -1
  227. package/packages/ui/lib/routes/register.d.ts +1 -1
  228. package/packages/ui/lib/routes/register.js +1 -1
  229. package/packages/ui/lib/routes/save.d.ts +1 -1
  230. package/packages/ui/lib/routes/save.js +22 -2
  231. package/packages/ui/lib/routes/stop.d.ts +7 -4
  232. package/packages/ui/lib/routes/stop.js +7 -4
  233. package/packages/ui/lib/routes/stream.d.ts +40 -0
  234. package/packages/ui/lib/routes/stream.js +68 -0
  235. package/packages/ui/lib/routes/summary.d.ts +1 -1
  236. package/packages/ui/lib/routes/summary.js +1 -1
  237. package/packages/ui/lib/routes/unregister.d.ts +1 -1
  238. package/packages/ui/lib/routes/unregister.js +1 -1
  239. package/packages/ui/lib/viewmodels/deps.d.ts +1 -31
  240. package/packages/ui/lib/viewmodels/deps.js +1 -89
  241. package/packages/ui/lib/viewmodels/depsHelpers.d.ts +1 -28
  242. package/packages/ui/lib/viewmodels/depsHelpers.js +72 -11
  243. package/packages/ui/lib/viewmodels/summary.d.ts +7 -2
  244. package/packages/ui/lib/viewmodels/summary.js +55 -35
  245. package/packages/ui/lib/viewmodels/summaryHelpers.d.ts +1 -1
  246. package/packages/ui/lib/viewmodels/summaryHelpers.js +1 -1
  247. package/packages/ui/lib/warnings.d.ts +1 -1
  248. package/packages/ui/lib/warnings.js +1 -1
  249. package/packages/ui/package.json +4 -4
  250. package/packages/providers/lib/engines/strata.d.ts +0 -53
@@ -29,14 +29,16 @@ export function parseNvidiaSmiGpuUsage(output) {
29
29
  * signature. The binary marker must appear in the command line (the image
30
30
  * name for a docker plan, the engine binary for a local one); a declared port
31
31
  * must appear as a standalone number (the `--port N` flag or the docker
32
- * `-p host:port:port` mapping); a declared env key must be set when the line
33
- * carries env data, and is neutral when it does not.
32
+ * `-p host:port:port` mapping) unless `portInArgv` is false, which means the
33
+ * engine binds its port from a file; a declared env key must be set when the
34
+ * line carries env data, and is neutral when it does not.
34
35
  */
35
36
  export function matchLaunchSignature(line, signature) {
36
37
  if (!line.command.includes(signature.binary))
37
38
  return false;
38
- if (signature.port !== undefined && !portAppears(line.command, signature.port))
39
+ if (signature.portInArgv !== false && signature.port !== undefined && !portAppears(line.command, signature.port)) {
39
40
  return false;
41
+ }
40
42
  if (signature.envKeys !== undefined && signature.envKeys.length > 0 && line.env !== undefined) {
41
43
  const hit = signature.envKeys.some(key => key in line.env);
42
44
  if (!hit)
@@ -90,4 +92,4 @@ export function resolveOsReserve(input) {
90
92
  }
91
93
  return { reserveMiB: DEFAULT_OS_RESERVE_MIB, source: 'default' };
92
94
  }
93
- //# sourceMappingURL=reserve.js.map
95
+ //# sourceMappingURL=reserve.js.map
@@ -10,8 +10,10 @@ export type ProviderStatus = 'running' | 'stopped' | 'unsure';
10
10
  /**
11
11
  * ProviderRef is the identity side of one saved provider config: the stable
12
12
  * id the card renders and the engine and model it serves. The model is
13
- * optional because a config that names no model cannot be confirmed against
14
- * a running engine, and reads as unsure rather than a guess. The config is
13
+ * optional: a config that names no model (an absent or empty value) confirms
14
+ * against a plugin-launched engine the detector tied to any model on its
15
+ * port, and reads as unsure only while no running engine carries a model tie.
16
+ * The config is
15
17
  * optional and lets the detector price the provider's own launch signature
16
18
  * (the engine binary the build mode runs, the port it binds) rather than the
17
19
  * adapter's default-port signature; the port is the resolved bind port the
@@ -60,9 +62,13 @@ export declare function isGpuBusy(usage?: GpuUsageProbe | null): boolean;
60
62
  * the detector's answer. The order is the plan's contract:
61
63
  * 1. A provider whose engine the process probe confirmed running is running
62
64
  * (green) when the detector tied that engine to the provider's exact model,
63
- * and unsure (yellow) when the engine serves an unidentified or a
64
- * different model. A running engine using its VRAM does not read as a busy
65
- * card, so the dot is green, not the unattributable yellow.
65
+ * or when the provider names no model and the detector tied the engine to
66
+ * any model: only this plugin's launches and re-links stamp a model tie, so
67
+ * a model-tied engine on the provider's port is that provider's own engine.
68
+ * A provider reads as unsure (yellow) when the engine serves an
69
+ * unidentified or a different model. A running engine using its VRAM does
70
+ * not read as a busy card, so the dot is green, not the unattributable
71
+ * yellow.
66
72
  * 2. A provider whose engine is not running falls back to the card state: a
67
73
  * busy card (a foreign engine holding the VRAM at 75% or more) reads as
68
74
  * unsure, because a full card cannot be attributed to a single model, and
@@ -70,4 +76,4 @@ export declare function isGpuBusy(usage?: GpuUsageProbe | null): boolean;
70
76
  * a saved config whose engine is down is stopped.
71
77
  */
72
78
  export declare function computeProviderStatuses(input: ProviderStatusInput): Record<string, ProviderStatus>;
73
- //# sourceMappingURL=status.d.ts.map
79
+ //# sourceMappingURL=status.d.ts.map
@@ -11,14 +11,26 @@ export function isGpuBusy(usage) {
11
11
  return false;
12
12
  return usage.usedMiB / usage.totalMiB >= GPU_USAGE_BUSY_THRESHOLD;
13
13
  }
14
+ /**
15
+ * namesNoModel reports whether one model field names no model: the absent
16
+ * value or the empty string. The provider side and the engine-ref side of the
17
+ * status tie both read it, so one rule decides both representations.
18
+ */
19
+ function namesNoModel(model) {
20
+ return model === undefined || model === '';
21
+ }
14
22
  /**
15
23
  * computeProviderStatuses resolves each saved provider's running-state from
16
24
  * the detector's answer. The order is the plan's contract:
17
25
  * 1. A provider whose engine the process probe confirmed running is running
18
26
  * (green) when the detector tied that engine to the provider's exact model,
19
- * and unsure (yellow) when the engine serves an unidentified or a
20
- * different model. A running engine using its VRAM does not read as a busy
21
- * card, so the dot is green, not the unattributable yellow.
27
+ * or when the provider names no model and the detector tied the engine to
28
+ * any model: only this plugin's launches and re-links stamp a model tie, so
29
+ * a model-tied engine on the provider's port is that provider's own engine.
30
+ * A provider reads as unsure (yellow) when the engine serves an
31
+ * unidentified or a different model. A running engine using its VRAM does
32
+ * not read as a busy card, so the dot is green, not the unattributable
33
+ * yellow.
22
34
  * 2. A provider whose engine is not running falls back to the card state: a
23
35
  * busy card (a foreign engine holding the VRAM at 75% or more) reads as
24
36
  * unsure, because a full card cannot be attributed to a single model, and
@@ -37,16 +49,15 @@ export function computeProviderStatuses(input) {
37
49
  if (matches.length > 0) {
38
50
  // The engine is running. The question is which model it serves: the
39
51
  // detector's identified model, if it tied one, else unknown.
40
- const identified = matches.find((ref) => ref.modelId !== undefined && ref.modelId !== '');
52
+ const identified = matches.find((ref) => !namesNoModel(ref.modelId));
41
53
  if (identified !== undefined &&
42
- provider.model !== undefined &&
43
- identified.modelId === provider.model) {
54
+ (namesNoModel(provider.model) || identified.modelId === provider.model)) {
44
55
  statuses[provider.id] = 'running';
45
56
  continue;
46
57
  }
47
- // The engine is running but the model is not identified, the provider
48
- // names no model, or the engine serves a different model: unsure, not
49
- // a guess.
58
+ // The engine is running but the detector could not tie it to a model, or
59
+ // it serves a different model than the provider names: unsure, not a
60
+ // guess.
50
61
  statuses[provider.id] = 'unsure';
51
62
  continue;
52
63
  }
@@ -56,4 +67,4 @@ export function computeProviderStatuses(input) {
56
67
  }
57
68
  return statuses;
58
69
  }
59
- //# sourceMappingURL=status.js.map
70
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The pure half of the sudo-prompt rule. A sudo command run by the plugin
3
+ * prompts on the terminal that launched the host, where the card user cannot
4
+ * see it, so the runners announce the prompt and cap how long it may wait.
5
+ * This module holds the constants and the injected-callback guard both
6
+ * runners drive; the child-process wiring stays in the service and the
7
+ * providers, so core never touches node.
8
+ * @module dsh-plugin-local-infer/core/sudo
9
+ */
10
+ /**
11
+ * SUDO_CLI_NOTE is the line the Logs section, the log file, and the streamed
12
+ * run show when a sudo command is waiting for the user to type the password
13
+ * on the CLI.
14
+ */
15
+ export declare const SUDO_CLI_NOTE = "Check your CLI for a sudo prompt";
16
+ /**
17
+ * SUDO_PASSWORD_TIMEOUT_MS caps how long a sudo command may wait for the user
18
+ * to type the password on the CLI before the run kills it and fails.
19
+ */
20
+ export declare const SUDO_PASSWORD_TIMEOUT_MS = 60000;
21
+ /**
22
+ * SUDO_PROBE_COMMAND is the non-interactive probe that answers whether sudo
23
+ * already holds cached credentials (exit 0) or is about to prompt on the
24
+ * terminal (non-zero). The runners execute it; core only declares it.
25
+ */
26
+ export declare const SUDO_PROBE_COMMAND: readonly string[];
27
+ /**
28
+ * sudoFailureDetail builds the CommandOutcome.detail text for a command the
29
+ * sudo deadline killed, naming the CLI note and the timeout seconds so the
30
+ * Logs section explains what the user missed.
31
+ */
32
+ export declare function sudoFailureDetail(command: string): string;
33
+ /**
34
+ * SudoTimer is the injectable set/clear pair a sudo guard arms and disarms.
35
+ * Tests drive the clock through a fake; the default is setTimeout and
36
+ * clearTimeout.
37
+ */
38
+ export interface SudoTimer {
39
+ set: (callback: () => void, ms: number) => unknown;
40
+ clear: (handle: unknown) => void;
41
+ }
42
+ /**
43
+ * SudoGuardOptions tunes one guarded command run. `needsSudo` is the caller's
44
+ * declaration (SystemDep.requiresSudo on the install path, RunOptions.needsSudo
45
+ * on the lifecycle path), never inferred from the command text. `probe`
46
+ * answers whether sudo already holds cached credentials, `notify` announces
47
+ * the coming prompt once, `kill` stops the command, `timeoutMs` overrides the
48
+ * deadline, and `timer` swaps the clock.
49
+ */
50
+ export interface SudoGuardOptions {
51
+ needsSudo?: boolean;
52
+ command: string;
53
+ probe: () => Promise<boolean>;
54
+ notify: (command: string) => void;
55
+ kill: () => void;
56
+ timeoutMs?: number;
57
+ timer?: SudoTimer;
58
+ }
59
+ /**
60
+ * SudoGuard is the guard's answer, read by the caller around the command run.
61
+ * `announced` says the prompt was announced and a deadline is armed;
62
+ * `disarm` clears the armed deadline once the command finishes; `timedOut`
63
+ * reads whether the deadline already fired, so a failed run can carry
64
+ * sudoFailureDetail instead of a bare exit.
65
+ */
66
+ export interface SudoGuard {
67
+ announced: boolean;
68
+ disarm(): void;
69
+ timedOut(): boolean;
70
+ }
71
+ /**
72
+ * guardSudoCommand applies the shared sudo-prompt rule for one command, so
73
+ * the service install runner and the providers lifecycle host drive one rule.
74
+ * A command the caller does not declare sudo runs through unguarded: no
75
+ * probe, no announcement, no timer. A declared command probes first; cached
76
+ * credentials (probe resolves true) run through the same way. Otherwise the
77
+ * guard calls notify once and arms the timeout whose fire calls kill.
78
+ */
79
+ export declare function guardSudoCommand(options: SudoGuardOptions): Promise<SudoGuard>;
80
+ //# sourceMappingURL=sudo.d.ts.map
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The pure half of the sudo-prompt rule. A sudo command run by the plugin
3
+ * prompts on the terminal that launched the host, where the card user cannot
4
+ * see it, so the runners announce the prompt and cap how long it may wait.
5
+ * This module holds the constants and the injected-callback guard both
6
+ * runners drive; the child-process wiring stays in the service and the
7
+ * providers, so core never touches node.
8
+ * @module dsh-plugin-local-infer/core/sudo
9
+ */
10
+ /**
11
+ * SUDO_CLI_NOTE is the line the Logs section, the log file, and the streamed
12
+ * run show when a sudo command is waiting for the user to type the password
13
+ * on the CLI.
14
+ */
15
+ export const SUDO_CLI_NOTE = 'Check your CLI for a sudo prompt';
16
+ /**
17
+ * SUDO_PASSWORD_TIMEOUT_MS caps how long a sudo command may wait for the user
18
+ * to type the password on the CLI before the run kills it and fails.
19
+ */
20
+ export const SUDO_PASSWORD_TIMEOUT_MS = 60_000;
21
+ /**
22
+ * SUDO_PROBE_COMMAND is the non-interactive probe that answers whether sudo
23
+ * already holds cached credentials (exit 0) or is about to prompt on the
24
+ * terminal (non-zero). The runners execute it; core only declares it.
25
+ */
26
+ export const SUDO_PROBE_COMMAND = ['sudo', '-n', 'true'];
27
+ /**
28
+ * sudoFailureDetail builds the CommandOutcome.detail text for a command the
29
+ * sudo deadline killed, naming the CLI note and the timeout seconds so the
30
+ * Logs section explains what the user missed.
31
+ */
32
+ export function sudoFailureDetail(command) {
33
+ return (`${command} was killed: no sudo password was entered within ` +
34
+ `${SUDO_PASSWORD_TIMEOUT_MS / 1000} seconds. ${SUDO_CLI_NOTE}`);
35
+ }
36
+ /** DEFAULT_SUDO_TIMER is the guard clock when the caller injects none. */
37
+ const DEFAULT_SUDO_TIMER = {
38
+ set: (callback, ms) => setTimeout(callback, ms),
39
+ clear: (handle) => clearTimeout(handle),
40
+ };
41
+ /**
42
+ * guardSudoCommand applies the shared sudo-prompt rule for one command, so
43
+ * the service install runner and the providers lifecycle host drive one rule.
44
+ * A command the caller does not declare sudo runs through unguarded: no
45
+ * probe, no announcement, no timer. A declared command probes first; cached
46
+ * credentials (probe resolves true) run through the same way. Otherwise the
47
+ * guard calls notify once and arms the timeout whose fire calls kill.
48
+ */
49
+ export async function guardSudoCommand(options) {
50
+ if (options.needsSudo !== true) {
51
+ return unguarded();
52
+ }
53
+ if (await options.probe()) {
54
+ return unguarded();
55
+ }
56
+ options.notify(options.command);
57
+ const timer = options.timer ?? DEFAULT_SUDO_TIMER;
58
+ const timeoutMs = options.timeoutMs ?? SUDO_PASSWORD_TIMEOUT_MS;
59
+ let timedOut = false;
60
+ const handle = timer.set(() => {
61
+ timedOut = true;
62
+ options.kill();
63
+ }, timeoutMs);
64
+ return {
65
+ announced: true,
66
+ disarm: () => timer.clear(handle),
67
+ timedOut: () => timedOut,
68
+ };
69
+ }
70
+ /** unguarded is the pass-through guard for a run nothing was armed for. */
71
+ function unguarded() {
72
+ return {
73
+ announced: false,
74
+ disarm: () => { },
75
+ timedOut: () => false,
76
+ };
77
+ }
78
+ //# sourceMappingURL=sudo.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-local-infer-core",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Pure, framework-free domain model for the dsh local-inference plugin: ParameterSpec, HardwareProfile, EngineAdapter, VramEstimator, GuidelineEngine, DefaultsResolver, DshModelRegistrar, and SystemDepProvisioner primitives shared by every engine and model",
5
5
  "keywords": [
6
6
  "dsh",
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The Orchestrator prompt store: the saved prompt file under
3
+ * ~/.dsh/local-infer/orchestrator.json, the shipped prompt.md default, and
4
+ * the in-memory holder the system-prompt section and the settings routes
5
+ * share. Every read sanitizes the file, so a by-hand edit never poisons the
6
+ * injected prompt. Mirrors the sanitize-on-read discipline of
7
+ * packages/ui/src/config.ts.
8
+ * @module dsh-plugin-local-infer/orchestrator/config
9
+ */
10
+ /**
11
+ * orchestratorConfigPath names the file this package owns. It sits in the
12
+ * shared local-infer dir beside the ui config so one place holds everything
13
+ * the plugin persists.
14
+ */
15
+ export declare function orchestratorConfigPath(): string;
16
+ /**
17
+ * StoredOrchestratorConfig is the whole persisted shape: the saved prompt,
18
+ * where an empty string carries "no saved prompt" so the holder falls back
19
+ * to the shipped default.
20
+ */
21
+ export interface StoredOrchestratorConfig {
22
+ prompt: string;
23
+ }
24
+ /**
25
+ * readOrchestratorConfig reads the saved prompt. A missing or broken file,
26
+ * or a prompt field that is not a string, reads as no saved prompt (empty),
27
+ * so a first open and a by-hand edit both land on the default instead of
28
+ * throwing.
29
+ */
30
+ export declare function readOrchestratorConfig(): StoredOrchestratorConfig;
31
+ /**
32
+ * writeOrchestratorConfig persists the prompt, creating the directory tree
33
+ * on first write the same way the ui config write does.
34
+ */
35
+ export declare function writeOrchestratorConfig(config: StoredOrchestratorConfig): void;
36
+ /**
37
+ * defaultOrchestratorPrompt returns the shipped prompt.md text read from the
38
+ * package root. The URL hop is relative to this module, so src/ and lib/
39
+ * depths both resolve one level up to the package root. The read is cached;
40
+ * an unreadable file yields '' without throwing.
41
+ */
42
+ export declare function defaultOrchestratorPrompt(): string;
43
+ /**
44
+ * getOrchestratorPrompt returns the effective prompt: the saved value when a
45
+ * non-empty one exists, otherwise the shipped default. The first call reads
46
+ * the file once and caches, so the system-prompt section pays no per-message
47
+ * disk read.
48
+ */
49
+ export declare function getOrchestratorPrompt(): string;
50
+ /**
51
+ * setOrchestratorPrompt persists the prompt and refreshes the holder, so the
52
+ * injected section picks the new text up without another file read. An empty
53
+ * save means "no saved prompt" and falls back to the default.
54
+ */
55
+ export declare function setOrchestratorPrompt(prompt: string): void;
56
+ /**
57
+ * hasSavedOrchestratorPrompt reports whether the file holds a saved prompt
58
+ * override. The empty string is the store's sentinel for "no saved prompt",
59
+ * so the settings routes read the flag through here instead of re-deriving
60
+ * the sentinel rule the holder already applies.
61
+ */
62
+ export declare function hasSavedOrchestratorPrompt(): boolean;
63
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The Orchestrator prompt store: the saved prompt file under
3
+ * ~/.dsh/local-infer/orchestrator.json, the shipped prompt.md default, and
4
+ * the in-memory holder the system-prompt section and the settings routes
5
+ * share. Every read sanitizes the file, so a by-hand edit never poisons the
6
+ * injected prompt. Mirrors the sanitize-on-read discipline of
7
+ * packages/ui/src/config.ts.
8
+ * @module dsh-plugin-local-infer/orchestrator/config
9
+ */
10
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
+ import { homedir } from 'node:os';
12
+ import { dirname, join } from 'node:path';
13
+ /**
14
+ * orchestratorConfigPath names the file this package owns. It sits in the
15
+ * shared local-infer dir beside the ui config so one place holds everything
16
+ * the plugin persists.
17
+ */
18
+ export function orchestratorConfigPath() {
19
+ return join(homedir(), '.dsh', 'local-infer', 'orchestrator.json');
20
+ }
21
+ /**
22
+ * readOrchestratorConfig reads the saved prompt. A missing or broken file,
23
+ * or a prompt field that is not a string, reads as no saved prompt (empty),
24
+ * so a first open and a by-hand edit both land on the default instead of
25
+ * throwing.
26
+ */
27
+ export function readOrchestratorConfig() {
28
+ const path = orchestratorConfigPath();
29
+ if (!existsSync(path)) {
30
+ return { prompt: '' };
31
+ }
32
+ try {
33
+ const parsed = JSON.parse(readFileSync(path, 'utf8'));
34
+ return { prompt: typeof parsed.prompt === 'string' ? parsed.prompt : '' };
35
+ }
36
+ catch {
37
+ return { prompt: '' };
38
+ }
39
+ }
40
+ /**
41
+ * writeOrchestratorConfig persists the prompt, creating the directory tree
42
+ * on first write the same way the ui config write does.
43
+ */
44
+ export function writeOrchestratorConfig(config) {
45
+ const path = orchestratorConfigPath();
46
+ mkdirSync(dirname(path), { recursive: true });
47
+ writeFileSync(path, JSON.stringify({ prompt: config.prompt }, null, 2));
48
+ }
49
+ // Cache of the shipped prompt.md text: the file never changes while the
50
+ // process runs, so only a successful read is kept and a failed read retries
51
+ // on the next call instead of locking in the empty fallback.
52
+ let defaultPromptCache;
53
+ /**
54
+ * defaultOrchestratorPrompt returns the shipped prompt.md text read from the
55
+ * package root. The URL hop is relative to this module, so src/ and lib/
56
+ * depths both resolve one level up to the package root. The read is cached;
57
+ * an unreadable file yields '' without throwing.
58
+ */
59
+ export function defaultOrchestratorPrompt() {
60
+ if (defaultPromptCache === undefined) {
61
+ try {
62
+ defaultPromptCache = readFileSync(new URL('../prompt.md', import.meta.url), 'utf8');
63
+ }
64
+ catch {
65
+ return '';
66
+ }
67
+ }
68
+ return defaultPromptCache;
69
+ }
70
+ // The effective prompt holder: null until the first read refreshes it from
71
+ // the file, then the saved value or the default until the setter persists a
72
+ // new one.
73
+ let effectivePrompt = null;
74
+ /**
75
+ * getOrchestratorPrompt returns the effective prompt: the saved value when a
76
+ * non-empty one exists, otherwise the shipped default. The first call reads
77
+ * the file once and caches, so the system-prompt section pays no per-message
78
+ * disk read.
79
+ */
80
+ export function getOrchestratorPrompt() {
81
+ if (effectivePrompt === null) {
82
+ effectivePrompt = toEffective(readOrchestratorConfig().prompt);
83
+ }
84
+ return effectivePrompt;
85
+ }
86
+ /**
87
+ * setOrchestratorPrompt persists the prompt and refreshes the holder, so the
88
+ * injected section picks the new text up without another file read. An empty
89
+ * save means "no saved prompt" and falls back to the default.
90
+ */
91
+ export function setOrchestratorPrompt(prompt) {
92
+ writeOrchestratorConfig({ prompt });
93
+ effectivePrompt = toEffective(prompt);
94
+ }
95
+ /**
96
+ * hasSavedOrchestratorPrompt reports whether the file holds a saved prompt
97
+ * override. The empty string is the store's sentinel for "no saved prompt",
98
+ * so the settings routes read the flag through here instead of re-deriving
99
+ * the sentinel rule the holder already applies.
100
+ */
101
+ export function hasSavedOrchestratorPrompt() {
102
+ return readOrchestratorConfig().prompt !== '';
103
+ }
104
+ /**
105
+ * toEffective resolves one saved value against the default: an empty saved
106
+ * prompt reads as no saved prompt.
107
+ */
108
+ function toEffective(saved) {
109
+ return saved === '' ? defaultOrchestratorPrompt() : saved;
110
+ }
111
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The Orchestrator capability: an editable "Orchestrator Prompt" persisted
3
+ * under `~/.dsh/local-infer`, defaulted from the shipped `prompt.md`, and
4
+ * injected into the system prompt while the component is enabled.
5
+ *
6
+ * The prompt store (saved file, shipped default, effective-prompt holder)
7
+ * lives in ./config.js and is re-exported here as the single source of truth
8
+ * the system-prompt seam (TASK-003) and the settings routes (TASK-004) pull
9
+ * from.
10
+ * @module dsh-plugin-local-infer/orchestrator
11
+ */
12
+ import type { Context } from '@deepseek-ai/cordis';
13
+ export { defaultOrchestratorPrompt, getOrchestratorPrompt, hasSavedOrchestratorPrompt, orchestratorConfigPath, readOrchestratorConfig, setOrchestratorPrompt, writeOrchestratorConfig, } from './config.js';
14
+ export type { StoredOrchestratorConfig } from './config.js';
15
+ export declare const name = "local-infer-orchestrator";
16
+ export declare const inject: string[];
17
+ /**
18
+ * SystemPromptService narrows the dsh-system-prompt service to the one
19
+ * member this package uses. That package augments the cordis Context with
20
+ * `systemPrompt` and is not a dependency here, so the scoped inject casts
21
+ * the scope locally (same shape as the ui's WebServerService narrowing).
22
+ */
23
+ export interface SystemPromptService {
24
+ /**
25
+ * Registers one ordered prompt section in the calling scope and returns
26
+ * the Cordis effect disposer. `text` may be a provider re-evaluated at
27
+ * each assembly.
28
+ */
29
+ section(section: {
30
+ name: string;
31
+ order: number;
32
+ text: string | (() => string);
33
+ interpolate?: boolean;
34
+ }): () => void;
35
+ }
36
+ /**
37
+ * Mount the Orchestrator prompt. The scoped `systemPrompt` inject registers
38
+ * the one global `orchestrator` section where the seam exists; the effect
39
+ * scope ties the registration to the plugin, so it unregisters with the
40
+ * plugin. The scoped `webServer` inject registers the /local-infer/
41
+ * orchestrator settings routes where that seam exists, so a headless profile
42
+ * keeps no routes.
43
+ */
44
+ export declare function apply(ctx: Context): void;
45
+ declare const plugin: {
46
+ name: string;
47
+ inject: string[];
48
+ apply: typeof apply;
49
+ };
50
+ export default plugin;
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The Orchestrator capability: an editable "Orchestrator Prompt" persisted
3
+ * under `~/.dsh/local-infer`, defaulted from the shipped `prompt.md`, and
4
+ * injected into the system prompt while the component is enabled.
5
+ *
6
+ * The prompt store (saved file, shipped default, effective-prompt holder)
7
+ * lives in ./config.js and is re-exported here as the single source of truth
8
+ * the system-prompt seam (TASK-003) and the settings routes (TASK-004) pull
9
+ * from.
10
+ * @module dsh-plugin-local-infer/orchestrator
11
+ */
12
+ import { getOrchestratorPrompt } from './config.js';
13
+ import { registerOrchestratorRoutes } from './route.js';
14
+ export { defaultOrchestratorPrompt, getOrchestratorPrompt, hasSavedOrchestratorPrompt, orchestratorConfigPath, readOrchestratorConfig, setOrchestratorPrompt, writeOrchestratorConfig, } from './config.js';
15
+ export const name = 'local-infer-orchestrator';
16
+ // No required top-level services: the `systemPrompt` and `webServer` seams
17
+ // are pulled with scoped injects in their own effects, so the component
18
+ // stays loadable in profiles that lack either service.
19
+ export const inject = [];
20
+ // The section placement: the deployment persona prefix sits at 0 and the
21
+ // first centrally allocated policy section (PLAN_POLICY) at 500, so 100
22
+ // puts the Orchestrator instructions just after the persona and ahead of
23
+ // first-party guidance. dsh-system-prompt allocates nothing between 0 and
24
+ // 500, and external contributions may pick any finite order.
25
+ const orchestratorSectionOrder = 100;
26
+ /**
27
+ * mountSeam pulls one optional service through a scoped inject and mounts
28
+ * the half that needs it. A profile without the seam never runs the
29
+ * callback, and a mount failure is logged and swallowed so the component
30
+ * still loads without that half. `skipped` names the half in the catch log.
31
+ */
32
+ function mountSeam(ctx, service, skipped, mount) {
33
+ ctx.inject([service], (scope) => {
34
+ try {
35
+ mount(scope);
36
+ }
37
+ catch (error) {
38
+ console.error(`[local-infer] orchestrator ${skipped}: ${error}`);
39
+ }
40
+ });
41
+ }
42
+ /**
43
+ * Mount the Orchestrator prompt. The scoped `systemPrompt` inject registers
44
+ * the one global `orchestrator` section where the seam exists; the effect
45
+ * scope ties the registration to the plugin, so it unregisters with the
46
+ * plugin. The scoped `webServer` inject registers the /local-infer/
47
+ * orchestrator settings routes where that seam exists, so a headless profile
48
+ * keeps no routes.
49
+ */
50
+ export function apply(ctx) {
51
+ if (typeof ctx.inject !== 'function') {
52
+ return;
53
+ }
54
+ mountSeam(ctx, 'systemPrompt', 'prompt section skipped', (scope) => {
55
+ const systemPrompt = scope.systemPrompt;
56
+ systemPrompt.section({
57
+ name: 'orchestrator',
58
+ order: orchestratorSectionOrder,
59
+ // The prompt is user-editable text: a stray {{var}} stays literal
60
+ // instead of failing every later prompt assembly.
61
+ interpolate: false,
62
+ // Provider form re-reads the holder per assembly, so a settings
63
+ // Save reaches the next assembly without a host restart.
64
+ text: () => getOrchestratorPrompt(),
65
+ });
66
+ });
67
+ mountSeam(ctx, 'webServer', 'settings routes skipped', (scope) => {
68
+ registerOrchestratorRoutes(scope);
69
+ });
70
+ }
71
+ const plugin = { name, inject, apply };
72
+ export default plugin;
73
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The Orchestrator settings routes the Web card talks to: GET
3
+ * /local-infer/orchestrator answers { prompt, defaultPrompt, saved } (the
4
+ * effective prompt, the shipped prompt.md default, and whether the effective
5
+ * prompt is a saved value), and POST /local-infer/orchestrator/save persists
6
+ * { prompt } through the config setter (an empty string clears the saved
7
+ * override back to the default) and answers with the same payload. The routes
8
+ * are held by an effect, so they go when the component does.
9
+ *
10
+ * The HTTP plumbing is a minimal local mirror of the ui package's defineRoute
11
+ * template (method guard 405, bounded body 413, JSON answer). The ui package
12
+ * does export its template, but this package deliberately keeps no dependency
13
+ * on ui: importing ui's route module would load its whole route graph (the
14
+ * service, providers, and core packages) into a component that ships disabled
15
+ * and must stay loadable headless, so the shared shape is copied rather than
16
+ * imported, and the two copies change together by hand. The stream helpers
17
+ * the ui template carries are dropped; these two routes only ever answer with
18
+ * one JSON body.
19
+ * @module dsh-plugin-local-infer/orchestrator/route
20
+ */
21
+ import type { Context } from '@deepseek-ai/cordis';
22
+ /**
23
+ * OrchestratorRoute is one webServer route definition the register step holds
24
+ * by an effect: the stable name, the exact-match path, and the handler the web
25
+ * server invokes per request.
26
+ */
27
+ export interface OrchestratorRoute {
28
+ name: string;
29
+ kind: 'exact';
30
+ path: string;
31
+ handler: (req: IncomingLike, res: OutgoingLike) => void | Promise<void>;
32
+ }
33
+ /**
34
+ * The webServer service is dsh-specific and absent from the cordis Context
35
+ * type, so the route narrows the scoped context to the one member it needs
36
+ * (same shape as the ui's WebServerService narrowing).
37
+ */
38
+ export interface WebServerService {
39
+ register(route: OrchestratorRoute): () => void;
40
+ }
41
+ interface IncomingLike extends AsyncIterable<Buffer> {
42
+ method: string;
43
+ url: string;
44
+ destroy(): void;
45
+ }
46
+ interface OutgoingLike {
47
+ writeHead(status: number, headers?: Record<string, string>): OutgoingLike;
48
+ end(body?: string): void;
49
+ }
50
+ /**
51
+ * registerOrchestratorRoutes registers the GET and save routes on the web
52
+ * server and holds them by an effect, so a component switch off removes them
53
+ * before the next switch on re-registers. The scoped context carries the
54
+ * webServer.
55
+ */
56
+ export declare function registerOrchestratorRoutes(scope: Context & {
57
+ webServer: WebServerService;
58
+ }): void;
59
+ export {};
60
+ //# sourceMappingURL=route.d.ts.map