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
@@ -31,6 +31,7 @@ import { downloadRoute } from "./routes/download.js";
31
31
  import { getRoute } from "./routes/get.js";
32
32
  import { installRoute } from "./routes/install.js";
33
33
  import { launchRoute } from "./routes/launch.js";
34
+ import { logsRoute } from "./routes/logs.js";
34
35
  import { providerDeleteRoute } from "./routes/provider-delete.js";
35
36
  import { registerRoute } from "./routes/register.js";
36
37
  import { saveRoute } from "./routes/save.js";
@@ -104,6 +105,15 @@ export class RouteResponder {
104
105
  this.res.write(chunk);
105
106
  }
106
107
  }
108
+ /**
109
+ * Watch the response's client disconnect (the node 'close' before the
110
+ * route ends): the listener fires once when the card's Cancel closes the
111
+ * stream, so the route aborts the in-flight run. A fake response without
112
+ * on() never fires it, and the run degrades to running to completion.
113
+ */
114
+ onClose(listener) {
115
+ this.res.on?.('close', listener);
116
+ }
107
117
  /** End the response, optionally with a final body chunk. */
108
118
  end(body) {
109
119
  this.res.end(body);
@@ -143,16 +153,18 @@ export function defineRoute(spec) {
143
153
  }
144
154
  /**
145
155
  * registerLocalInferRoute registers the summary, save, provider-delete, deps,
146
- * install, download, chat-template, get, launch, stop, register, and
156
+ * install, download, chat-template, get, launch, stop, logs, register, and
147
157
  * unregister routes on the web server and holds them by an effect, so a
148
158
  * bundle switch off removes them before the next switch on re-registers. The
149
159
  * scoped context carries the webServer; the localInfer service is passed in
150
160
  * because the scope only injects what it names. The optional getHost is the
151
- * lifecycle host the Get route's git and build steps run through; it
152
- * defaults to the node host, and a test injects a stub so the route never
153
- * clones a real repo in CI.
161
+ * lifecycle host the Get route's git and build steps run through, and the
162
+ * optional launchHost the launch route's Get steps run through; both default
163
+ * to the node host, and a test injects a stub so the routes never clone a
164
+ * real repo in CI.
154
165
  */
155
- export function registerLocalInferRoute(scope, localInfer, getHost) {
166
+ export function registerLocalInferRoute(scope, localInfer, getHost, launchHost) {
167
+ const logsStreamRoute = logsRoute(localInfer);
156
168
  const routes = [
157
169
  summaryRoute(localInfer),
158
170
  saveRoute(localInfer),
@@ -162,8 +174,9 @@ export function registerLocalInferRoute(scope, localInfer, getHost) {
162
174
  downloadRoute(localInfer),
163
175
  chatTemplateRoute(localInfer),
164
176
  getRoute(localInfer, getHost),
165
- launchRoute(localInfer),
177
+ launchRoute(localInfer, launchHost),
166
178
  stopRoute(localInfer),
179
+ logsStreamRoute,
167
180
  registerRoute(localInfer),
168
181
  unregisterRoute(localInfer),
169
182
  ];
@@ -175,8 +188,13 @@ export function registerLocalInferRoute(scope, localInfer, getHost) {
175
188
  // The engine death observer: a crash, a pkill, or the poll-detected exit
176
189
  // of an adopted process clears the provider entry's launch record and
177
190
  // notes the exit in the last-run logs the moment it happens, so the card
178
- // and a later restart read the provider stopped rather than stale.
179
- localInfer.setEngineDeathObserver(handleEngineDeath);
191
+ // and a later restart read the provider stopped rather than stale. The
192
+ // closure captures the service so the same note reaches the dead entry's
193
+ // live run-log buffer (handleEngineDeath closes a run its late append
194
+ // reopened, so the note never strands the key as running).
195
+ localInfer.setEngineDeathObserver((event) => {
196
+ handleEngineDeath(event, localInfer);
197
+ });
180
198
  // The mount re-link: re-adopt a surviving engine from a stored launch
181
199
  // record and start its liveness watcher without waiting for the card to
182
200
  // open the summary route, so a DSH that restarts re-attaches its engines
@@ -185,10 +203,15 @@ export function registerLocalInferRoute(scope, localInfer, getHost) {
185
203
  const disposers = routes.map((route) => scope.webServer.register(route));
186
204
  return () => {
187
205
  localInfer.setEngineDeathObserver(undefined);
206
+ // Browser panes still streaming hold hub subscriptions that
207
+ // unregistering the route does not touch: close every open stream
208
+ // first, so a bundle switch off leaves no listener forwarding into a
209
+ // response no route owns any more.
210
+ logsStreamRoute.closeOpenStreams();
188
211
  for (const dispose of disposers) {
189
212
  dispose();
190
213
  }
191
214
  };
192
215
  }, 'local-infer: settings routes');
193
216
  }
194
- //# sourceMappingURL=route.js.map
217
+ //# sourceMappingURL=route.js.map
@@ -1,14 +1 @@
1
- /**
2
- * The POST /local-infer/chat-template route: the card's auto-download (and
3
- * the System-dependencies fallback) pulls a selected template into the model
4
- * directory through this route, so a picked preset works out of the box.
5
- * @module dsh-plugin-local-infer/ui/routes/chat-template
6
- */
7
- import type { LocalInferService } from 'dsh-plugin-local-infer/service';
8
- import type { LocalInferRoute } from '../route.ts';
9
- /**
10
- * chatTemplateRoute builds the POST /local-infer/chat-template route
11
- * definition the register step holds by an effect.
12
- */
13
- export declare function chatTemplateRoute(localInfer: LocalInferService): LocalInferRoute;
14
- //# sourceMappingURL=chat-template.d.ts.map
1
+
@@ -1,37 +1 @@
1
- /**
2
- * The POST /local-infer/chat-template route: the card's auto-download (and
3
- * the System-dependencies fallback) pulls a selected template into the model
4
- * directory through this route, so a picked preset works out of the box.
5
- * @module dsh-plugin-local-infer/ui/routes/chat-template
6
- */
7
- import { defineRoute } from "../route.js";
8
- import { chatTemplateDownloadFor } from "../ops/hf.js";
9
- /**
10
- * chatTemplateRoute builds the POST /local-infer/chat-template route
11
- * definition the register step holds by an effect.
12
- */
13
- export function chatTemplateRoute(localInfer) {
14
- return defineRoute({
15
- name: 'local-infer-chat-template',
16
- path: '/local-infer/chat-template',
17
- method: 'POST',
18
- failStatus: 500,
19
- tooLargeMessage: 'chat template payload too large',
20
- run: async ({ body }, res) => {
21
- // exactOptionalPropertyTypes: build the request object with only the
22
- // keys that are present, so an absent value never writes `undefined`.
23
- const request = {};
24
- if (typeof body.engine === 'string') {
25
- request.engine = body.engine;
26
- }
27
- if (typeof body.template === 'string') {
28
- request.template = body.template;
29
- }
30
- if (typeof body.directory === 'string') {
31
- request.directory = body.directory;
32
- }
33
- res.json(200, await chatTemplateDownloadFor(localInfer, request));
34
- },
35
- });
36
- }
37
- //# sourceMappingURL=chat-template.js.map
1
+
@@ -1,16 +1 @@
1
- /**
2
- * The GET /local-infer/deps route: the deps panel read model. The handler
3
- * parses the engine and config query params (an absent engine or a broken
4
- * config falls back to the stored config) and answers with the dep plan, the
5
- * per-dep statuses, the copy/paste install string, and the Play/Run trust
6
- * gate.
7
- * @module dsh-plugin-local-infer/ui/routes/deps
8
- */
9
- import type { LocalInferService } from 'dsh-plugin-local-infer/service';
10
- import type { LocalInferRoute } from '../route.ts';
11
- /**
12
- * depsRoute builds the GET /local-infer/deps route definition the register
13
- * step holds by an effect.
14
- */
15
- export declare function depsRoute(localInfer: LocalInferService): LocalInferRoute;
16
- //# sourceMappingURL=deps.d.ts.map
1
+
@@ -1,27 +1 @@
1
- /**
2
- * The GET /local-infer/deps route: the deps panel read model. The handler
3
- * parses the engine and config query params (an absent engine or a broken
4
- * config falls back to the stored config) and answers with the dep plan, the
5
- * per-dep statuses, the copy/paste install string, and the Play/Run trust
6
- * gate.
7
- * @module dsh-plugin-local-infer/ui/routes/deps
8
- */
9
- import { defineRoute } from "../route.js";
10
- import { depsRequestFromUrl } from "../request.js";
11
- import { buildDeps } from "../viewmodels/deps.js";
12
- /**
13
- * depsRoute builds the GET /local-infer/deps route definition the register
14
- * step holds by an effect.
15
- */
16
- export function depsRoute(localInfer) {
17
- return defineRoute({
18
- name: 'local-infer-deps',
19
- path: '/local-infer/deps',
20
- method: 'GET',
21
- failStatus: 500,
22
- run: async ({ url }, res) => {
23
- res.json(200, await buildDeps(localInfer, depsRequestFromUrl(url)));
24
- },
25
- });
26
- }
27
- //# sourceMappingURL=deps.js.map
1
+
@@ -1,16 +1 @@
1
- /**
2
- * The POST /local-infer/download route: it runs the hf CLI download for the
3
- * request's default model, resolving the entry through the providers'
4
- * default list (a 404 when no entry names the pair) and the directory
5
- * against the request, the stored config, and the plugin's default model
6
- * directory in that order.
7
- * @module dsh-plugin-local-infer/ui/routes/download
8
- */
9
- import type { LocalInferService } from 'dsh-plugin-local-infer/service';
10
- import type { LocalInferRoute } from '../route.ts';
11
- /**
12
- * downloadRoute builds the POST /local-infer/download route definition the
13
- * register step holds by an effect.
14
- */
15
- export declare function downloadRoute(localInfer: LocalInferService): LocalInferRoute;
16
- //# sourceMappingURL=download.d.ts.map
1
+
@@ -1,48 +1 @@
1
- /**
2
- * The POST /local-infer/download route: it runs the hf CLI download for the
3
- * request's default model, resolving the entry through the providers'
4
- * default list (a 404 when no entry names the pair) and the directory
5
- * against the request, the stored config, and the plugin's default model
6
- * directory in that order.
7
- * @module dsh-plugin-local-infer/ui/routes/download
8
- */
9
- import { defineRoute } from "../route.js";
10
- import { downloadFor } from "../ops/hf.js";
11
- import { persistDownloadLog } from "../ops/logs.js";
12
- /**
13
- * downloadRoute builds the POST /local-infer/download route definition the
14
- * register step holds by an effect.
15
- */
16
- export function downloadRoute(localInfer) {
17
- return defineRoute({
18
- name: 'local-infer-download',
19
- path: '/local-infer/download',
20
- method: 'POST',
21
- failStatus: 500,
22
- tooLargeMessage: 'download payload too large',
23
- run: async ({ body }, res) => {
24
- // exactOptionalPropertyTypes: build the request object with only the
25
- // keys that are present, so an absent value never writes `undefined`.
26
- const request = {};
27
- if (typeof body.engine === 'string') {
28
- request.engine = body.engine;
29
- }
30
- if (typeof body.model === 'string') {
31
- request.model = body.model;
32
- }
33
- if (typeof body.directory === 'string') {
34
- request.directory = body.directory;
35
- }
36
- const result = await downloadFor(localInfer, request);
37
- // The "Downloading..." separator leads the persisted run, so the Logs
38
- // section and the log file read the download as a fresh process section,
39
- // the same line the card writes when the Download button is clicked.
40
- const line = result.ok
41
- ? 'download complete\n'
42
- : `!! download failed${result.detail !== undefined ? `: ${result.detail}` : ''}\n`;
43
- persistDownloadLog(`--- Downloading...\n${line}`);
44
- res.json(200, result);
45
- },
46
- });
47
- }
48
- //# sourceMappingURL=download.js.map
1
+
@@ -1,18 +1 @@
1
- /**
2
- * The POST /local-infer/get route: the Get step. Its answer streams as plain
3
- * text, so the card appends the git sync, the dependency run, and the build
4
- * output to its Logs section as it lands. The full run persists as the
5
- * last-run logs.
6
- * @module dsh-plugin-local-infer/ui/routes/get
7
- */
8
- import type { LifecycleHost } from 'dsh-plugin-local-infer/core';
9
- import type { LocalInferService } from 'dsh-plugin-local-infer/service';
10
- import type { LocalInferRoute } from '../route.ts';
11
- /**
12
- * getRoute builds the POST /local-infer/get route definition the register
13
- * step holds by an effect. The optional getHost is the lifecycle host the
14
- * git and build steps run through; it defaults to the node host, and a test
15
- * injects a stub so the route never clones a real repo in CI.
16
- */
17
- export declare function getRoute(localInfer: LocalInferService, getHost?: LifecycleHost): LocalInferRoute;
18
- //# sourceMappingURL=get.d.ts.map
1
+
@@ -1,14 +1,20 @@
1
1
  /**
2
- * The POST /local-infer/get route: the Get step. Its answer streams as plain
3
- * text, so the card appends the git sync, the dependency run, and the build
4
- * output to its Logs section as it lands. The full run persists as the
5
- * last-run logs.
2
+ * The POST /local-infer/get route: the Get step. Its answer streams as
3
+ * NDJSON progress events only (a structured download state folded from the
4
+ * hf download's tqdm stderr): the run's log text reaches the card through
5
+ * the per-provider run-log stream (the GET /local-infer/logs route fed by the
6
+ * hub), so one line never arrives twice. The full run still collects,
7
+ * persists as the last-run logs in plain text, and feeds the live hub, so
8
+ * the log file, the Logs section, and the streamed run read the run the same
9
+ * way.
6
10
  * @module dsh-plugin-local-infer/ui/routes/get
7
11
  */
12
+ import { runLogKey } from '../../../service/lib/index.js';
8
13
  import { parseStoredPlatformConfig } from "../config.js";
9
- import { getEngine } from "../ops/engine.js";
10
- import { persistGetLogs } from "../ops/logs.js";
14
+ import { CANCELED_LINE, GET_EVENT_PREFIX, getEngine, resolveStoredRequest } from "../ops/engine.js";
15
+ import { captureRunBaseline, finishRunSection, GET_RUN_SEED } from "../ops/logs.js";
11
16
  import { defineRoute } from "../route.js";
17
+ import { abortOnResponseClose, ndjsonLine, throttledProgressSink } from "./stream.js";
12
18
  /**
13
19
  * getRoute builds the POST /local-infer/get route definition the register
14
20
  * step holds by an effect. The optional getHost is the lifecycle host the
@@ -34,24 +40,67 @@ export function getRoute(localInfer, getHost) {
34
40
  if (platform !== undefined) {
35
41
  request.platform = platform;
36
42
  }
37
- res.textStream();
43
+ res.ndjsonStream();
44
+ // The run key the live hub buffers this Get under, the shared runLogKey
45
+ // rule (the request names no provider, so the stored entry matching the
46
+ // engine and model wins, and a draft falls back to the engine id).
47
+ const { stored, engineId, config } = resolveStoredRequest(request);
48
+ const runKey = runLogKey(stored.providers, engineId, undefined, config);
49
+ localInfer.beginRun(runKey, GET_RUN_SEED);
50
+ // The stored last-run logs as they stand before the run persists
51
+ // anything: the sudo observer persists its note while the run hangs on
52
+ // the prompt, and finishRunSection closes the run over the baseline so
53
+ // that provisional line and the collected run text persist once.
54
+ const baseline = captureRunBaseline();
38
55
  let collected = '';
56
+ // The log sink collects the plain-text run (the persisted log) and
57
+ // appends the same chunk to the live hub, whose run-log stream carries
58
+ // the text to the card's Logs pane (Q2: one streamed display path).
59
+ // The route's own answer no longer mirrors the text as log events, so
60
+ // a line never lands twice.
39
61
  const log = (text) => {
40
62
  collected += text;
41
- res.write(text);
63
+ localInfer.appendRunLog(runKey, text);
42
64
  };
65
+ // The hf download's raw stderr sink: the core chunk folder turns the
66
+ // tqdm lines into a structured state, and the sink emits a progress
67
+ // event when a fold yields one (throttled to the half-second cadence).
68
+ const onChunk = throttledProgressSink((progress) => ndjsonLine(res, { progress }));
69
+ // The card's provider-form Cancel aborts the fetch, which closes the
70
+ // response: the abort interrupts the in-flight hf child (SIGINT, then
71
+ // SIGTERM). Resume is within-invocation only; a killed run re-downloads
72
+ // from zero on the re-run (the orphaned .incomplete blob lingers until
73
+ // `hf cache prune`). A close after the run settled is the normal end,
74
+ // not a cancel.
75
+ const { signal, markFinished } = abortOnResponseClose(res);
43
76
  try {
44
- await getEngine(localInfer, request, log, getHost);
77
+ try {
78
+ await getEngine(localInfer, request, log, getHost, signal, onChunk);
79
+ }
80
+ catch (error) {
81
+ log(`${GET_EVENT_PREFIX}get failed: ${String(error?.message ?? error)}\n`);
82
+ }
83
+ // A cancel that closed the stream appends the "Canceled" line, so the
84
+ // persisted run (and the log file) read the run as canceled, the same
85
+ // line the card writes to its Logs buffer on the Cancel.
86
+ if (signal.aborted) {
87
+ log(`${CANCELED_LINE}`);
88
+ }
89
+ markFinished();
90
+ // The "Getting engine and model..." separator leads the persisted
91
+ // run and the live run's seed, so the Logs section, the log file, and
92
+ // the streamed run read the run as one fresh process section.
93
+ // finishRunSection closes the run over the baseline captured before
94
+ // it started, not a second append over its own provisional notes.
95
+ finishRunSection(baseline, `${GET_RUN_SEED}${collected}`);
96
+ res.end();
45
97
  }
46
- catch (error) {
47
- log(`!! get failed: ${String(error?.message ?? error)}\n`);
98
+ finally {
99
+ // The bracket closes on every settle path, cancel and failure
100
+ // included: the key's running flag clears after finishRunSection.
101
+ localInfer.endRun(runKey);
48
102
  }
49
- // The "Getting..." separator leads the persisted run, so the Logs
50
- // section and the log file read the run as a fresh process section, the
51
- // same line the card writes when the Get button is clicked.
52
- persistGetLogs(`--- Getting...\n${collected}`);
53
- res.end();
54
103
  },
55
104
  });
56
105
  }
57
- //# sourceMappingURL=get.js.map
106
+ //# sourceMappingURL=get.js.map
@@ -13,4 +13,4 @@ import type { LocalInferRoute } from '../route.ts';
13
13
  * register step holds by an effect.
14
14
  */
15
15
  export declare function installRoute(localInfer: LocalInferService): LocalInferRoute;
16
- //# sourceMappingURL=install.d.ts.map
16
+ //# sourceMappingURL=install.d.ts.map
@@ -33,4 +33,4 @@ export function installRoute(localInfer) {
33
33
  },
34
34
  });
35
35
  }
36
- //# sourceMappingURL=install.js.map
36
+ //# sourceMappingURL=install.js.map
@@ -2,17 +2,23 @@
2
2
  * The POST /local-infer/launch route: it renders the plan the registered
3
3
  * adapter produces and runs the service's launch entry point (deploy, then
4
4
  * the health poll). The launch streams its progress as NDJSON: a step event
5
- * as each phase (prereqs, download, build, launch) begins, then a final
6
- * result event. The card's Launch control reads the step that is running and
7
- * times out only the launch (health-poll) step; the rebuild steps run as
8
- * long as they need to.
5
+ * as each phase (prereqs, download, build, launch) begins, a progress event
6
+ * when the Get-steps hf download's tqdm stderr folds into a structured
7
+ * state, a sudo event when a guarded command waits for the user's password
8
+ * on the launching CLI, then a final result event. The card's Launch control
9
+ * reads the step that is running and times out only the launch (health-poll)
10
+ * step; the rebuild steps run as long as they need to.
9
11
  * @module dsh-plugin-local-infer/ui/routes/launch
10
12
  */
13
+ import type { LifecycleHost } from 'dsh-plugin-local-infer/core';
11
14
  import type { LocalInferService } from 'dsh-plugin-local-infer/service';
12
15
  import type { LocalInferRoute } from '../route.ts';
13
16
  /**
14
17
  * launchRoute builds the POST /local-infer/launch route definition the
15
- * register step holds by an effect.
18
+ * register step holds by an effect. The optional launchHost is the lifecycle
19
+ * host the launch's Get steps (git sync, build) run through; it defaults to
20
+ * the node host, and a test injects a stub so the route never clones a real
21
+ * repo in CI.
16
22
  */
17
- export declare function launchRoute(localInfer: LocalInferService): LocalInferRoute;
18
- //# sourceMappingURL=launch.d.ts.map
23
+ export declare function launchRoute(localInfer: LocalInferService, launchHost?: LifecycleHost): LocalInferRoute;
24
+ //# sourceMappingURL=launch.d.ts.map
@@ -2,20 +2,27 @@
2
2
  * The POST /local-infer/launch route: it renders the plan the registered
3
3
  * adapter produces and runs the service's launch entry point (deploy, then
4
4
  * the health poll). The launch streams its progress as NDJSON: a step event
5
- * as each phase (prereqs, download, build, launch) begins, then a final
6
- * result event. The card's Launch control reads the step that is running and
7
- * times out only the launch (health-poll) step; the rebuild steps run as
8
- * long as they need to.
5
+ * as each phase (prereqs, download, build, launch) begins, a progress event
6
+ * when the Get-steps hf download's tqdm stderr folds into a structured
7
+ * state, a sudo event when a guarded command waits for the user's password
8
+ * on the launching CLI, then a final result event. The card's Launch control
9
+ * reads the step that is running and times out only the launch (health-poll)
10
+ * step; the rebuild steps run as long as they need to.
9
11
  * @module dsh-plugin-local-infer/ui/routes/launch
10
12
  */
13
+ import { nodeLifecycleHost } from '../../../providers/lib/index.js';
11
14
  import { launchEngine } from "../ops/engine.js";
12
15
  import { defineRoute, RouteError } from "../route.js";
13
16
  import { launchRequestFromBody } from "../request.js";
17
+ import { abortOnResponseClose, ndjsonLine, throttledProgressSink } from "./stream.js";
14
18
  /**
15
19
  * launchRoute builds the POST /local-infer/launch route definition the
16
- * register step holds by an effect.
20
+ * register step holds by an effect. The optional launchHost is the lifecycle
21
+ * host the launch's Get steps (git sync, build) run through; it defaults to
22
+ * the node host, and a test injects a stub so the route never clones a real
23
+ * repo in CI.
17
24
  */
18
- export function launchRoute(localInfer) {
25
+ export function launchRoute(localInfer, launchHost = nodeLifecycleHost) {
19
26
  return defineRoute({
20
27
  name: 'local-infer-launch',
21
28
  path: '/local-infer/launch',
@@ -25,13 +32,29 @@ export function launchRoute(localInfer) {
25
32
  run: async ({ body }, res) => {
26
33
  res.ndjsonStream();
27
34
  const writeLine = (line) => {
28
- res.write(JSON.stringify(line) + '\n');
35
+ ndjsonLine(res, line);
29
36
  };
30
37
  const onProgress = (step) => {
31
38
  writeLine({ step });
32
39
  };
40
+ // The Get-steps hf download's raw stderr sink: the core chunk folder
41
+ // turns the tqdm lines into a structured state, and the sink emits a
42
+ // progress event when a fold yields one (throttled to the half-second
43
+ // cadence), between the step and result events.
44
+ const onChunk = throttledProgressSink((progress) => writeLine({ progress }));
45
+ // The run's sudo observer calls this when a guarded command waits for
46
+ // the password on the launching CLI (see launchEngine): the card reads
47
+ // the line as "Sudo needed" on its Launch control.
48
+ const onSudo = () => {
49
+ writeLine({ sudo: true });
50
+ };
51
+ // The card's provider-form Cancel aborts the fetch, which closes the
52
+ // response: the abort interrupts the in-flight Get-step hf child
53
+ // (SIGINT, then SIGTERM), and the persisted run carries the "Canceled"
54
+ // line. A close after the run settled is the normal end, not a cancel.
55
+ const { signal, markFinished } = abortOnResponseClose(res);
33
56
  try {
34
- const result = await launchEngine(localInfer, launchRequestFromBody(body), onProgress);
57
+ const result = await launchEngine(localInfer, launchRequestFromBody(body), onProgress, launchHost, signal, onChunk, onSudo);
35
58
  writeLine({ result });
36
59
  }
37
60
  catch (error) {
@@ -43,8 +66,9 @@ export function launchRoute(localInfer) {
43
66
  : String(error?.message ?? error);
44
67
  writeLine({ result: { healthy: false, detail } });
45
68
  }
69
+ markFinished();
46
70
  res.end();
47
71
  },
48
72
  });
49
73
  }
50
- //# sourceMappingURL=launch.js.map
74
+ //# sourceMappingURL=launch.js.map
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The GET /local-infer/logs route: the per-provider live run-log stream the
3
+ * card's Logs pane holds open (Q2: all live log display streams, nothing
4
+ * polls). The handler subscribes to the run-log hub before reading the
5
+ * catch-up snapshot, so an append that lands between the two is deduped by
6
+ * seq against the snapshot instead of doubling or being lost. One attached
7
+ * connection sees, in order: one `{ snapshot, seq, running }` catch-up line,
8
+ * then one `{ log, seq }` line per append, a `{ runBegin, seq }` line when a
9
+ * new run resets the buffer (the pane replaces, never appends), and a
10
+ * `{ runEnd, seq }` line when the run settles. The connection stays attached
11
+ * across runs. An unknown or blank provider key streams the empty snapshot
12
+ * and stays attached, so a client racing a run start never sees a 404; the
13
+ * client disconnect disposes the hub subscription.
14
+ * @module dsh-plugin-local-infer/ui/routes/logs
15
+ */
16
+ import type { LocalInferService } from 'dsh-plugin-local-infer/service';
17
+ import type { LocalInferRoute } from '../route.ts';
18
+ /**
19
+ * LogsStreamEvent is one NDJSON line the logs route streams: the catch-up
20
+ * snapshot (the bounded buffer text, the seq it reached, the running flag),
21
+ * one appended chunk, a run begin (the new run's seed line, seq back at 0,
22
+ * so the pane replaces its display), or the run end (the seq it settled at).
23
+ * Every line carries the seq the next append continues, so the card can drop
24
+ * any line whose seq the text it holds already covers.
25
+ */
26
+ export type LogsStreamEvent = {
27
+ snapshot: string;
28
+ seq: number;
29
+ running: boolean;
30
+ } | {
31
+ log: string;
32
+ seq: number;
33
+ } | {
34
+ runBegin: string;
35
+ seq: number;
36
+ } | {
37
+ runEnd: true;
38
+ seq: number;
39
+ };
40
+ /**
41
+ * LogsStreamRoute is the logs route's definition plus the open-stream
42
+ * registry the route effect's disposer drains. A bundle switch off
43
+ * unregisters the route, but browser panes that still hold a stream open
44
+ * leave their hub subscriptions behind unless something closes them; the
45
+ * effect disposer calls closeOpenStreams for that.
46
+ */
47
+ export interface LogsStreamRoute extends LocalInferRoute {
48
+ closeOpenStreams(): void;
49
+ }
50
+ /**
51
+ * logsRoute builds the GET /local-infer/logs?provider=<key> route definition
52
+ * the register step holds by an effect. The `provider` query is the run key
53
+ * every run path shares (the runLogKey rule the card's requests mirror); a
54
+ * missing or unknown key is a live stream of nothing until someone runs it.
55
+ */
56
+ export declare function logsRoute(localInfer: LocalInferService): LogsStreamRoute;
57
+ //# sourceMappingURL=logs.d.ts.map