dsh-plugin-local-infer 0.1.2 → 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 (251) hide show
  1. package/README.md +32 -6
  2. package/cordis.patch.yml +7 -0
  3. package/docs/zh/README.md +24 -4
  4. package/dsh/client.js +4200 -4049
  5. package/package.json +33 -11
  6. package/packages/core/lib/adapter.d.ts +177 -11
  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 +48 -20
  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 +25 -14
  41. package/packages/core/lib/registrar.js +30 -10
  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 +95 -15
  59. package/packages/providers/lib/acquire.js +239 -40
  60. package/packages/providers/lib/adapters.d.ts +155 -221
  61. package/packages/providers/lib/adapters.js +589 -935
  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 +31 -212
  65. package/packages/providers/lib/deps.js +71 -205
  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/{hyperqwen.d.ts → engines/hyperqwen/hyperqwen.d.ts} +2 -2
  79. package/packages/providers/lib/{hyperqwen.js → engines/hyperqwen/hyperqwen.js} +14 -2
  80. package/packages/providers/lib/engines/hyperqwen/hyperqwenAdapter.d.ts +38 -0
  81. package/packages/providers/lib/engines/hyperqwen/hyperqwenAdapter.js +115 -0
  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/{infernix.d.ts → engines/infernix/infernix.d.ts} +7 -4
  95. package/packages/providers/lib/{infernix.js → engines/infernix/infernix.js} +53 -8
  96. package/packages/providers/lib/engines/infernix/infernixAdapter.d.ts +52 -0
  97. package/packages/providers/lib/engines/infernix/infernixAdapter.js +235 -0
  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/{llamacpp.d.ts → engines/llamacpp/llamacpp.d.ts} +2 -2
  111. package/packages/providers/lib/{llamacpp.js → engines/llamacpp/llamacpp.js} +12 -2
  112. package/packages/providers/lib/engines/llamacpp/llamacppAdapter.d.ts +50 -0
  113. package/packages/providers/lib/engines/llamacpp/llamacppAdapter.js +274 -0
  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/{ninfer.d.ts → engines/ninfer/ninfer.d.ts} +2 -2
  127. package/packages/providers/lib/{ninfer.js → engines/ninfer/ninfer.js} +25 -3
  128. package/packages/providers/lib/engines/ninfer/ninferAdapter.d.ts +81 -0
  129. package/packages/providers/lib/engines/ninfer/ninferAdapter.js +392 -0
  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/strata.js +264 -0
  144. package/packages/providers/lib/engines/strata/strataAdapter.d.ts +97 -0
  145. package/packages/providers/lib/engines/strata/strataAdapter.js +463 -0
  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 +8 -5
  159. package/packages/providers/lib/engines.js +22 -11
  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 -24
  163. package/packages/providers/lib/index.js +46 -24
  164. package/packages/providers/lib/model-defaults.d.ts +10 -5
  165. package/packages/providers/lib/model-defaults.js +47 -5
  166. package/packages/providers/lib/platform.d.ts +8 -5
  167. package/packages/providers/lib/platform.js +27 -7
  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 +187 -23
  176. package/packages/service/lib/index.js +667 -90
  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 +166 -8
  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 +89 -0
  188. package/packages/ui/lib/config.js +251 -0
  189. package/packages/ui/lib/deps.d.ts +4 -4
  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 +216 -0
  198. package/packages/ui/lib/ops/engine.js +697 -0
  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 +42 -0
  202. package/packages/ui/lib/ops/hf.js +150 -0
  203. package/packages/ui/lib/ops/logs.d.ts +78 -0
  204. package/packages/ui/lib/ops/logs.js +119 -0
  205. package/packages/ui/lib/ops/model.d.ts +71 -0
  206. package/packages/ui/lib/ops/model.js +123 -0
  207. package/packages/ui/lib/request.d.ts +106 -0
  208. package/packages/ui/lib/request.js +80 -0
  209. package/packages/ui/lib/route.d.ts +106 -422
  210. package/packages/ui/lib/route.js +136 -1845
  211. package/packages/ui/lib/routes/chat-template.d.ts +1 -0
  212. package/packages/ui/lib/routes/chat-template.js +1 -0
  213. package/packages/ui/lib/routes/deps.d.ts +1 -0
  214. package/packages/ui/lib/routes/deps.js +1 -0
  215. package/packages/ui/lib/routes/download.d.ts +1 -0
  216. package/packages/ui/lib/routes/download.js +1 -0
  217. package/packages/ui/lib/routes/get.d.ts +1 -0
  218. package/packages/ui/lib/routes/get.js +106 -0
  219. package/packages/ui/lib/routes/install.d.ts +16 -0
  220. package/packages/ui/lib/routes/install.js +36 -0
  221. package/packages/ui/lib/routes/launch.d.ts +24 -0
  222. package/packages/ui/lib/routes/launch.js +74 -0
  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 +15 -0
  226. package/packages/ui/lib/routes/provider-delete.js +37 -0
  227. package/packages/ui/lib/routes/register.d.ts +16 -0
  228. package/packages/ui/lib/routes/register.js +28 -0
  229. package/packages/ui/lib/routes/save.d.ts +18 -0
  230. package/packages/ui/lib/routes/save.js +159 -0
  231. package/packages/ui/lib/routes/stop.d.ts +19 -0
  232. package/packages/ui/lib/routes/stop.js +32 -0
  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 +15 -0
  236. package/packages/ui/lib/routes/summary.js +26 -0
  237. package/packages/ui/lib/routes/unregister.d.ts +14 -0
  238. package/packages/ui/lib/routes/unregister.js +26 -0
  239. package/packages/ui/lib/viewmodels/deps.d.ts +1 -0
  240. package/packages/ui/lib/viewmodels/deps.js +1 -0
  241. package/packages/ui/lib/viewmodels/depsHelpers.d.ts +1 -0
  242. package/packages/ui/lib/viewmodels/depsHelpers.js +94 -0
  243. package/packages/ui/lib/viewmodels/summary.d.ts +145 -0
  244. package/packages/ui/lib/viewmodels/summary.js +245 -0
  245. package/packages/ui/lib/viewmodels/summaryHelpers.d.ts +30 -0
  246. package/packages/ui/lib/viewmodels/summaryHelpers.js +42 -0
  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/strata.d.ts +0 -15
  251. package/packages/providers/lib/strata.js +0 -14
@@ -14,6 +14,14 @@ export interface DefaultModel {
14
14
  url: string;
15
15
  file?: string;
16
16
  }
17
+ /**
18
+ * ModelDownloadSource is the half of a DefaultModel the presence check, the
19
+ * hf CLI command, and the hub-cache lookup read: the Hugging Face repo URL
20
+ * and the optional artifact file. A full list entry satisfies it, and an
21
+ * adapter that only resolves the download pair composes just these fields
22
+ * instead of restating the entry's inert registry data.
23
+ */
24
+ export type ModelDownloadSource = Pick<DefaultModel, 'url' | 'file'>;
17
25
  /**
18
26
  * repoIdFromUrl turns a Hugging Face repo URL into the `owner/name` repo id
19
27
  * the hf CLI takes. A URL with no owner/name pair reads as an empty id, which
@@ -27,18 +35,57 @@ export declare function repoIdFromUrl(url: string): string;
27
35
  */
28
36
  export declare function repoNameFromUrl(url: string): string;
29
37
  /**
30
- * modelArtifactPath is the path the presence check looks for in the model
31
- * directory: the entry's artifact file when it names one, else the repo-name
32
- * directory a whole-repo download leaves behind.
38
+ * hubCacheModelDirectory is the per-model directory the hf CLI creates in the
39
+ * hub cache for one repo id: `models--{namespace}--{name}`. A repo id without
40
+ * an owner/name pair reads as an empty directory name, which the callers
41
+ * handle as an absent model.
42
+ */
43
+ export declare function hubCacheModelDirectory(repoId: string): string;
44
+ /**
45
+ * isModelDirectoryOverridden reports whether a model directory field (the
46
+ * config's or a download request's) names a path (a non-blank string), the
47
+ * one rule every download route and view model shares to decide the layout:
48
+ * a named directory targets that directory flat (`--local-dir`), an unnamed
49
+ * one takes the hub-cache layout (no `--local-dir`, the
50
+ * `models--{ns}--{name}` directories the hf CLI writes into the hub cache).
51
+ * The predicate form lets callers narrow the field to a string without
52
+ * restating the blank check.
53
+ */
54
+ export declare function isModelDirectoryOverridden(modelDirectory: unknown): modelDirectory is string;
55
+ /**
56
+ * modelArtifactPath is the path a model download's artifact lands at in the
57
+ * model directory: the entry's artifact file when it names one, else the
58
+ * repo-name directory a whole-repo download leaves behind. With the hub-cache
59
+ * layout (`useHubCache`), it resolves into the per-model cache directory's
60
+ * `blobs` folder, the content-addressed store the hf CLI writes without
61
+ * `--local-dir`; the `directory` is then the hub cache root, not the per-model
62
+ * folder. Every presence decision (the card-facing checks and the engines'
63
+ * deploy re-fetch gates) resolves the deterministic snapshot instead
64
+ * (modelArtifactPresent); the hub-cache form here stays the blobs-store path.
33
65
  */
34
- export declare function modelArtifactPath(entry: DefaultModel, directory: string): string;
66
+ export declare function modelArtifactPath(entry: ModelDownloadSource, directory: string, useHubCache?: boolean): string;
35
67
  /**
36
- * hfDownloadCommand renders the hf CLI download for one default model: the
37
- * repo, the artifact file when the entry names one, and the `--local-dir`
38
- * target. The string is the single source the download route runs and the
39
- * card shows beside its Download button.
68
+ * hfDownloadFileCommand renders the hf CLI download for one repo and file
69
+ * pair: the repo, the file (omitted when blank, a whole-repo download), the
70
+ * `--local-dir` target when the hub-cache layout does not apply, and the
71
+ * `--format human` flag. The flag overrides the non-TTY default (`auto` picks
72
+ * `agent`, which prints no progress) so the hf CLI prints tqdm progress
73
+ * lines to stderr, which the progress streaming tasks consume. The string is
74
+ * the single source every hf download command renders through: the model and
75
+ * chat-template builders below, and the Infernix extra-download commands the
76
+ * Get step streams.
40
77
  */
41
- export declare function hfDownloadCommand(entry: DefaultModel, directory: string): string;
78
+ export declare function hfDownloadFileCommand(repo: string, file: string, directory: string, useHubCache?: boolean): string;
79
+ /**
80
+ * hfDownloadCommand renders the hf CLI download for one model download
81
+ * source: the repo, the artifact file when the entry names one, and the
82
+ * `--local-dir` target. With the hub-cache layout (`useHubCache`), the `--local-dir` is
83
+ * dropped so the hf CLI writes into the hub cache's `models--{ns}--{name}`
84
+ * directory (the content-addressed `blobs/` plus the `snapshots/`). The
85
+ * string is the single source the download route runs and the card shows
86
+ * beside its Download button, rendered through hfDownloadFileCommand.
87
+ */
88
+ export declare function hfDownloadCommand(entry: ModelDownloadSource, directory: string, useHubCache?: boolean): string;
42
89
  /**
43
90
  * The chat template file the hf CLI pulls into the model directory. The
44
91
  * NInfer deploy step and the template download route both target this name, so
@@ -48,11 +95,50 @@ export declare const CHAT_TEMPLATE_FILE = "chat_template.jinja";
48
95
  /**
49
96
  * hfChatTemplateCommand renders the hf CLI download for one chat template repo
50
97
  * reference into the model directory: the repo, the template file, and the
51
- * `--local-dir` target. The string is the single source the template download
52
- * route runs and the card shows beside its Download button and in the System
53
- * dependencies box when the auto-download is unavailable.
98
+ * `--local-dir` target. With the hub-cache layout (`useHubCache`), the
99
+ * `--local-dir` is dropped so the template lands in the hub cache's
100
+ * `models--{ns}--{name}` directory. The string is the single source the
101
+ * template download route runs and the card shows beside its Download button
102
+ * and in the System dependencies box when the auto-download is unavailable,
103
+ * rendered through hfDownloadFileCommand.
54
104
  */
55
- export declare function hfChatTemplateCommand(repo: string, directory: string): string;
105
+ export declare function hfChatTemplateCommand(repo: string, directory: string, useHubCache?: boolean): string;
106
+ /**
107
+ * chatTemplateArtifactPath is the path the flat-layout chat-template presence
108
+ * check looks for: the template file joined onto the model directory. The
109
+ * hub-cache layout resolves through chatTemplatePresent instead (the
110
+ * deterministic snapshot pick), not through this join.
111
+ */
112
+ export declare function chatTemplateArtifactPath(directory: string): string;
113
+ /**
114
+ * modelArtifactPresent reports whether a model download source's artifact is
115
+ * on disk. With the hub-cache layout it resolves the deterministic hub-cache
116
+ * snapshot holding the file (the same pick the model-directory display uses),
117
+ * so a `blobs` folder left by any download never reads as present on its
118
+ * own; a blank `file` (a whole-repo download) reads the repo's snapshot
119
+ * directories. With the flat layout it checks the artifact path joined onto
120
+ * the base directory. `baseDir` is the hub cache root under the cache layout,
121
+ * the flat override otherwise.
122
+ */
123
+ export declare function modelArtifactPresent(entry: ModelDownloadSource, baseDir: string, useHubCache?: boolean): boolean;
124
+ /**
125
+ * chatTemplatePresent reports whether a chat template repo's template file is
126
+ * on disk: the deterministic hub-cache snapshot pick under the hub-cache
127
+ * layout (a per-repo `snapshots` folder alone never reads as present), the
128
+ * flat file join otherwise. `baseDir` follows the modelArtifactPresent rule.
129
+ */
130
+ export declare function chatTemplatePresent(repo: string, baseDir: string, useHubCache?: boolean): boolean;
131
+ /**
132
+ * hubCacheSnapshotFilePath resolves the concrete file path of one file in the
133
+ * hub cache's snapshots, matching what the hf CLI treats as the active
134
+ * revision: the commit recorded in `refs/main` wins when its directory under
135
+ * `models--{ns}--{name}/snapshots/` holds the file; otherwise the snapshot
136
+ * with the newest mtime wins, covering a repo with no ref and a ref naming a
137
+ * commit that lacks the file. Ties break on readdir order. Returns null when
138
+ * no snapshot holds the file (the file is not downloaded), which the caller
139
+ * reads as absent. The `hubCache` is the hub cache root.
140
+ */
141
+ export declare function hubCacheSnapshotFilePath(hubCache: string, repoId: string, file: string): string | null;
56
142
  /**
57
143
  * ModelDirectoryEntry is one top-level entry of a model directory listing:
58
144
  * the entry name, whether it is a directory, and for directories whether the
@@ -74,4 +160,24 @@ export interface ModelDirectoryEntry {
74
160
  * sorted, so the dropdown order is stable across summary fetches.
75
161
  */
76
162
  export declare function modelEntriesForEngine(entries: readonly ModelDirectoryEntry[], engineId: string): string[];
77
- //# sourceMappingURL=models.d.ts.map
163
+ /**
164
+ * ModelCacheEntry is one `models--*` directory in the hub cache: the repo id
165
+ * the directory names (the `{namespace}/{name}` decoded from the
166
+ * `models--{ns}--{name}` form) and the artifact file names the snapshots hold
167
+ * (the union across every commit), the data the per-engine cache scan filters.
168
+ */
169
+ export interface ModelCacheEntry {
170
+ repoId: string;
171
+ files: string[];
172
+ }
173
+ /**
174
+ * modelCacheEntriesForEngine filters the hub cache's `models--*` directories
175
+ * down to the models the engine's Model dropdown offers, by the artifact types
176
+ * each engine serves: Basalt `.basalt`, NInfer `.ninfer`, Infernix
177
+ * `.ninfer`/`.infernix`, llama.cpp `.gguf`, Hyper-Qwen a repo holding a
178
+ * `.safetensors` weight file, and Strata `.gguf`/`.safetensors`. An engine with
179
+ * no matching cached model lists none. The result is the repo ids the
180
+ * dropdown shows, sorted for a stable order across summary fetches.
181
+ */
182
+ export declare function modelCacheEntriesForEngine(entries: readonly ModelCacheEntry[], engineId: string): string[];
183
+ //# sourceMappingURL=models.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
1
2
  import { join } from 'node:path';
2
3
  /**
3
4
  * repoIdFromUrl turns a Hugging Face repo URL into the `owner/name` repo id
@@ -21,26 +22,81 @@ export function repoNameFromUrl(url) {
21
22
  return slash >= 0 ? repo.slice(slash + 1) : repo;
22
23
  }
23
24
  /**
24
- * modelArtifactPath is the path the presence check looks for in the model
25
- * directory: the entry's artifact file when it names one, else the repo-name
26
- * directory a whole-repo download leaves behind.
25
+ * hubCacheModelDirectory is the per-model directory the hf CLI creates in the
26
+ * hub cache for one repo id: `models--{namespace}--{name}`. A repo id without
27
+ * an owner/name pair reads as an empty directory name, which the callers
28
+ * handle as an absent model.
27
29
  */
28
- export function modelArtifactPath(entry, directory) {
30
+ export function hubCacheModelDirectory(repoId) {
31
+ const slash = repoId.lastIndexOf('/');
32
+ if (slash <= 0)
33
+ return '';
34
+ return `models--${repoId.slice(0, slash)}--${repoId.slice(slash + 1)}`;
35
+ }
36
+ /**
37
+ * isModelDirectoryOverridden reports whether a model directory field (the
38
+ * config's or a download request's) names a path (a non-blank string), the
39
+ * one rule every download route and view model shares to decide the layout:
40
+ * a named directory targets that directory flat (`--local-dir`), an unnamed
41
+ * one takes the hub-cache layout (no `--local-dir`, the
42
+ * `models--{ns}--{name}` directories the hf CLI writes into the hub cache).
43
+ * The predicate form lets callers narrow the field to a string without
44
+ * restating the blank check.
45
+ */
46
+ export function isModelDirectoryOverridden(modelDirectory) {
47
+ return typeof modelDirectory === 'string' && modelDirectory.trim() !== '';
48
+ }
49
+ /**
50
+ * modelArtifactPath is the path a model download's artifact lands at in the
51
+ * model directory: the entry's artifact file when it names one, else the
52
+ * repo-name directory a whole-repo download leaves behind. With the hub-cache
53
+ * layout (`useHubCache`), it resolves into the per-model cache directory's
54
+ * `blobs` folder, the content-addressed store the hf CLI writes without
55
+ * `--local-dir`; the `directory` is then the hub cache root, not the per-model
56
+ * folder. Every presence decision (the card-facing checks and the engines'
57
+ * deploy re-fetch gates) resolves the deterministic snapshot instead
58
+ * (modelArtifactPresent); the hub-cache form here stays the blobs-store path.
59
+ */
60
+ export function modelArtifactPath(entry, directory, useHubCache = false) {
61
+ if (useHubCache) {
62
+ const modelDir = hubCacheModelDirectory(repoIdFromUrl(entry.url));
63
+ if (modelDir !== '')
64
+ return join(directory, modelDir, 'blobs');
65
+ }
29
66
  if (entry.file !== undefined && entry.file !== '') {
30
67
  return join(directory, entry.file);
31
68
  }
32
69
  return join(directory, repoNameFromUrl(entry.url));
33
70
  }
34
71
  /**
35
- * hfDownloadCommand renders the hf CLI download for one default model: the
36
- * repo, the artifact file when the entry names one, and the `--local-dir`
37
- * target. The string is the single source the download route runs and the
38
- * card shows beside its Download button.
72
+ * hfDownloadFileCommand renders the hf CLI download for one repo and file
73
+ * pair: the repo, the file (omitted when blank, a whole-repo download), the
74
+ * `--local-dir` target when the hub-cache layout does not apply, and the
75
+ * `--format human` flag. The flag overrides the non-TTY default (`auto` picks
76
+ * `agent`, which prints no progress) so the hf CLI prints tqdm progress
77
+ * lines to stderr, which the progress streaming tasks consume. The string is
78
+ * the single source every hf download command renders through: the model and
79
+ * chat-template builders below, and the Infernix extra-download commands the
80
+ * Get step streams.
81
+ */
82
+ export function hfDownloadFileCommand(repo, file, directory, useHubCache = false) {
83
+ const filePart = file !== '' ? ` ${file}` : '';
84
+ const localDir = useHubCache ? '' : ` --local-dir ${directory}`;
85
+ return `hf download ${repo}${filePart}${localDir} --format human`;
86
+ }
87
+ /**
88
+ * hfDownloadCommand renders the hf CLI download for one model download
89
+ * source: the repo, the artifact file when the entry names one, and the
90
+ * `--local-dir` target. With the hub-cache layout (`useHubCache`), the `--local-dir` is
91
+ * dropped so the hf CLI writes into the hub cache's `models--{ns}--{name}`
92
+ * directory (the content-addressed `blobs/` plus the `snapshots/`). The
93
+ * string is the single source the download route runs and the card shows
94
+ * beside its Download button, rendered through hfDownloadFileCommand.
39
95
  */
40
- export function hfDownloadCommand(entry, directory) {
96
+ export function hfDownloadCommand(entry, directory, useHubCache = false) {
41
97
  const repo = repoIdFromUrl(entry.url);
42
- const file = entry.file !== undefined && entry.file !== '' ? ` ${entry.file}` : '';
43
- return `hf download ${repo}${file} --local-dir ${directory}`;
98
+ const file = entry.file !== undefined && entry.file !== '' ? entry.file : '';
99
+ return hfDownloadFileCommand(repo, file, directory, useHubCache);
44
100
  }
45
101
  /**
46
102
  * The chat template file the hf CLI pulls into the model directory. The
@@ -51,12 +107,115 @@ export const CHAT_TEMPLATE_FILE = 'chat_template.jinja';
51
107
  /**
52
108
  * hfChatTemplateCommand renders the hf CLI download for one chat template repo
53
109
  * reference into the model directory: the repo, the template file, and the
54
- * `--local-dir` target. The string is the single source the template download
55
- * route runs and the card shows beside its Download button and in the System
56
- * dependencies box when the auto-download is unavailable.
110
+ * `--local-dir` target. With the hub-cache layout (`useHubCache`), the
111
+ * `--local-dir` is dropped so the template lands in the hub cache's
112
+ * `models--{ns}--{name}` directory. The string is the single source the
113
+ * template download route runs and the card shows beside its Download button
114
+ * and in the System dependencies box when the auto-download is unavailable,
115
+ * rendered through hfDownloadFileCommand.
116
+ */
117
+ export function hfChatTemplateCommand(repo, directory, useHubCache = false) {
118
+ return hfDownloadFileCommand(repo, CHAT_TEMPLATE_FILE, directory, useHubCache);
119
+ }
120
+ /**
121
+ * chatTemplateArtifactPath is the path the flat-layout chat-template presence
122
+ * check looks for: the template file joined onto the model directory. The
123
+ * hub-cache layout resolves through chatTemplatePresent instead (the
124
+ * deterministic snapshot pick), not through this join.
125
+ */
126
+ export function chatTemplateArtifactPath(directory) {
127
+ return join(directory, CHAT_TEMPLATE_FILE);
128
+ }
129
+ /**
130
+ * modelArtifactPresent reports whether a model download source's artifact is
131
+ * on disk. With the hub-cache layout it resolves the deterministic hub-cache
132
+ * snapshot holding the file (the same pick the model-directory display uses),
133
+ * so a `blobs` folder left by any download never reads as present on its
134
+ * own; a blank `file` (a whole-repo download) reads the repo's snapshot
135
+ * directories. With the flat layout it checks the artifact path joined onto
136
+ * the base directory. `baseDir` is the hub cache root under the cache layout,
137
+ * the flat override otherwise.
138
+ */
139
+ export function modelArtifactPresent(entry, baseDir, useHubCache = false) {
140
+ if (useHubCache) {
141
+ return hubCacheSnapshotFilePath(baseDir, repoIdFromUrl(entry.url), entry.file ?? '') !== null;
142
+ }
143
+ return existsSync(modelArtifactPath(entry, baseDir));
144
+ }
145
+ /**
146
+ * chatTemplatePresent reports whether a chat template repo's template file is
147
+ * on disk: the deterministic hub-cache snapshot pick under the hub-cache
148
+ * layout (a per-repo `snapshots` folder alone never reads as present), the
149
+ * flat file join otherwise. `baseDir` follows the modelArtifactPresent rule.
57
150
  */
58
- export function hfChatTemplateCommand(repo, directory) {
59
- return `hf download ${repo} ${CHAT_TEMPLATE_FILE} --local-dir ${directory}`;
151
+ export function chatTemplatePresent(repo, baseDir, useHubCache = false) {
152
+ if (useHubCache) {
153
+ return hubCacheSnapshotFilePath(baseDir, repo, CHAT_TEMPLATE_FILE) !== null;
154
+ }
155
+ return existsSync(chatTemplateArtifactPath(baseDir));
156
+ }
157
+ /**
158
+ * hubCacheSnapshotFilePath resolves the concrete file path of one file in the
159
+ * hub cache's snapshots, matching what the hf CLI treats as the active
160
+ * revision: the commit recorded in `refs/main` wins when its directory under
161
+ * `models--{ns}--{name}/snapshots/` holds the file; otherwise the snapshot
162
+ * with the newest mtime wins, covering a repo with no ref and a ref naming a
163
+ * commit that lacks the file. Ties break on readdir order. Returns null when
164
+ * no snapshot holds the file (the file is not downloaded), which the caller
165
+ * reads as absent. The `hubCache` is the hub cache root.
166
+ */
167
+ export function hubCacheSnapshotFilePath(hubCache, repoId, file) {
168
+ const modelDir = hubCacheModelDirectory(repoId);
169
+ if (modelDir === '')
170
+ return null;
171
+ const modelRoot = join(hubCache, modelDir);
172
+ const snapshots = join(modelRoot, 'snapshots');
173
+ // The hf CLI writes the revision it last downloaded into refs/main; that
174
+ // commit is the cache's active one, so it outranks mtime.
175
+ const active = readHubCacheRef(join(modelRoot, 'refs', 'main'));
176
+ if (active !== '') {
177
+ const activePath = join(snapshots, active, file);
178
+ if (existsSync(activePath))
179
+ return activePath;
180
+ }
181
+ let commits;
182
+ try {
183
+ commits = readdirSync(snapshots);
184
+ }
185
+ catch {
186
+ return null;
187
+ }
188
+ let newestPath = null;
189
+ let newestMtime = -Infinity;
190
+ for (const commit of commits) {
191
+ const path = join(snapshots, commit, file);
192
+ if (!existsSync(path))
193
+ continue;
194
+ const snapshotDir = join(snapshots, commit);
195
+ let mtime;
196
+ try {
197
+ mtime = statSync(snapshotDir).mtimeMs;
198
+ }
199
+ catch {
200
+ // A directory that cannot be stat'ed mid-scan cannot win the pick.
201
+ continue;
202
+ }
203
+ if (mtime > newestMtime) {
204
+ newestMtime = mtime;
205
+ newestPath = path;
206
+ }
207
+ }
208
+ return newestPath;
209
+ }
210
+ // readHubCacheRef returns the commit the hf CLI ref file names, or '' when
211
+ // the ref is absent or unreadable (a cache written by an older CLI).
212
+ function readHubCacheRef(refPath) {
213
+ try {
214
+ return readFileSync(refPath, 'utf8').trim();
215
+ }
216
+ catch {
217
+ return '';
218
+ }
60
219
  }
61
220
  /**
62
221
  * modelEntriesForEngine filters a model directory listing down to the model
@@ -98,4 +257,37 @@ export function modelEntriesForEngine(entries, engineId) {
98
257
  }
99
258
  return names.sort();
100
259
  }
101
- //# sourceMappingURL=models.js.map
260
+ /**
261
+ * modelCacheEntriesForEngine filters the hub cache's `models--*` directories
262
+ * down to the models the engine's Model dropdown offers, by the artifact types
263
+ * each engine serves: Basalt `.basalt`, NInfer `.ninfer`, Infernix
264
+ * `.ninfer`/`.infernix`, llama.cpp `.gguf`, Hyper-Qwen a repo holding a
265
+ * `.safetensors` weight file, and Strata `.gguf`/`.safetensors`. An engine with
266
+ * no matching cached model lists none. The result is the repo ids the
267
+ * dropdown shows, sorted for a stable order across summary fetches.
268
+ */
269
+ export function modelCacheEntriesForEngine(entries, engineId) {
270
+ const serves = (files) => {
271
+ switch (engineId) {
272
+ case 'basalt':
273
+ return files.some((file) => file.endsWith('.basalt'));
274
+ case 'ninfer':
275
+ return files.some((file) => file.endsWith('.ninfer'));
276
+ case 'infernix':
277
+ return files.some((file) => file.endsWith('.ninfer') || file.endsWith('.infernix'));
278
+ case 'llamacpp':
279
+ return files.some((file) => file.endsWith('.gguf'));
280
+ case 'hyperqwen':
281
+ return files.some((file) => file.endsWith('.safetensors'));
282
+ case 'strata':
283
+ return files.some((file) => file.endsWith('.gguf') || file.endsWith('.safetensors'));
284
+ default:
285
+ return false;
286
+ }
287
+ };
288
+ return entries
289
+ .filter((entry) => serves(entry.files))
290
+ .map((entry) => entry.repoId)
291
+ .sort();
292
+ }
293
+ //# sourceMappingURL=models.js.map
@@ -68,6 +68,29 @@ export type ParameterForm = {
68
68
  kind: 'combo';
69
69
  options: ComboOption[];
70
70
  };
71
+ /**
72
+ * ParameterDeploy declares where a parameter's value lands at deploy time:
73
+ * on the command line, in the process environment, or in a config file the
74
+ * deploy step writes. A `config` target names the file format and the
75
+ * nesting path: `block` is the top-level key, `key` the leaf. The config-file
76
+ * renderer nests `toConfig(value)` (or the raw value) under that path. A
77
+ * `block` ending in `[]` (e.g. `models[]`) is the array-entry convention: the
78
+ * key lands inside the single object of a one-element array named by the
79
+ * prefix, and specs sharing that block merge into that one entry. A spec
80
+ * declares one target, or a list of targets when the value lands in more than
81
+ * one place (a Strata shared spec lands on the CLI in the binary mode and in
82
+ * the env in the docker mode).
83
+ */
84
+ export type ParameterDeploy = {
85
+ target: 'cli';
86
+ } | {
87
+ target: 'env';
88
+ } | {
89
+ target: 'config';
90
+ format: 'json' | 'yaml' | 'env';
91
+ block?: string;
92
+ key?: string;
93
+ };
71
94
  /**
72
95
  * ParameterSpec is the unit of parameter management: a declarative description
73
96
  * of one engine parameter. It is the object that makes the parameter-to-
@@ -77,8 +100,11 @@ export type ParameterForm = {
77
100
  * of adding these specs, never rewiring the core.
78
101
  *
79
102
  * `description` is behavior-first: it says what the parameter does to the run,
80
- * not what it is. `toArgv` and `toEnv` are the engine-specific spellings that
81
- * turn a value into a CLI flag or an environment variable.
103
+ * not what it is. `toArgv`, `toEnv`, and `toConfig` are the engine-specific
104
+ * spellings that turn a value into a CLI flag, an environment variable, or a
105
+ * config-file entry. `deploy` declares which spelling the deploy step uses;
106
+ * a list declares several, so one spec can serve more than one build mode
107
+ * (the flags in the binary mode and the env vars in the docker mode).
82
108
  */
83
109
  export interface ParameterSpec {
84
110
  key: string;
@@ -92,5 +118,7 @@ export interface ParameterSpec {
92
118
  requires?: (config: Config) => string | null;
93
119
  toArgv?: (value: unknown) => string[];
94
120
  toEnv?: (value: unknown) => [string, string];
121
+ toConfig?: (value: unknown) => unknown;
122
+ deploy?: ParameterDeploy | readonly ParameterDeploy[];
95
123
  }
96
- //# sourceMappingURL=parameter.d.ts.map
124
+ //# sourceMappingURL=parameter.d.ts.map
@@ -1,2 +1,2 @@
1
1
  export {};
2
- //# sourceMappingURL=parameter.js.map
2
+ //# sourceMappingURL=parameter.js.map
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The pure hf (huggingface_hub) tqdm progress parser the get and launch routes
3
+ * share: it turns the raw tqdm stderr lines into a structured HfProgress
4
+ * state, so a route's onChunk sink (the download runner's streamed stderr)
5
+ * feeds the card's progress events without a node import. The parser
6
+ * recognizes the two tqdm bar shapes the hf CLI emits with `--format human`:
7
+ * the file-count bar (`Fetching 102 files: 42%|...| 43/102 [00:01<00:02,
8
+ * 20.5it/s]`, where the done/total fields carry file counts, not bytes) and
9
+ * the byte bar (`Downloading x.safetensors: 12% | 5.2G/43.5G [01:23<10:11,
10
+ * 72.3MB/s]`, where the done/total fields carry human byte sizes). It
11
+ * converts the human byte sizes to bytes and the `[elapsed<remaining, rate]`
12
+ * tail to remaining seconds, and marks the unit the done/total amounts carry
13
+ * (`'files'` for the file-count bar, `'bytes'` for the byte bar), so a
14
+ * readout renders the amounts in the unit the bar measured. The client
15
+ * package mirrors this parser in
16
+ * `packages/client/src/store/progress.ts` (the TASK-006 browser-side copy):
17
+ * the core package is not browser-safe, so the client bundle keeps its own
18
+ * copy and the two shapes (`HfProgress` and the client's `HfProgressShape`)
19
+ * must stay in sync when a tqdm bar shape changes.
20
+ * @module dsh-plugin-local-infer/core/progress
21
+ */
22
+ /**
23
+ * HfProgress is the structured state one tqdm bar update folds to: the step
24
+ * label the bar names (the file, or the file-count fetch), the percent
25
+ * complete, the done and total amounts (bytes for the byte bar, file counts
26
+ * for the file-count bar), the remaining time in seconds (0 when the bar
27
+ * carries no tail), and the unit the done/total amounts carry ('bytes' for
28
+ * the byte bar, 'files' for the file-count bar), so a readout renders the
29
+ * amounts in the unit the bar measured.
30
+ */
31
+ export interface HfProgress {
32
+ step: string;
33
+ percent: number;
34
+ doneBytes: number;
35
+ totalBytes: number;
36
+ etaSeconds: number;
37
+ unit: 'bytes' | 'files';
38
+ }
39
+ /**
40
+ * parseHfProgressLine parses one tqdm bar line into an HfProgress state, or
41
+ * undefined when the line is not a bar update (a plain log line, a command
42
+ * echo). It recognizes the file-count and byte shapes above.
43
+ */
44
+ export declare function parseHfProgressLine(line: string): HfProgress | undefined;
45
+ /**
46
+ * foldHfProgressChunk folds a raw stderr chunk into the latest HfProgress
47
+ * state it carries: the chunk splits on the line separators tqdm writes
48
+ * (carriage returns between bar redraws, newlines between steps), each line
49
+ * parses through parseHfProgressLine, and the last parseable line wins. A
50
+ * chunk with no bar update returns the prior state, so a caller threads the
51
+ * fold across chunks and always holds the newest state.
52
+ */
53
+ export declare function foldHfProgressChunk(chunk: string, prior: HfProgress | undefined): HfProgress | undefined;
54
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The pure hf (huggingface_hub) tqdm progress parser the get and launch routes
3
+ * share: it turns the raw tqdm stderr lines into a structured HfProgress
4
+ * state, so a route's onChunk sink (the download runner's streamed stderr)
5
+ * feeds the card's progress events without a node import. The parser
6
+ * recognizes the two tqdm bar shapes the hf CLI emits with `--format human`:
7
+ * the file-count bar (`Fetching 102 files: 42%|...| 43/102 [00:01<00:02,
8
+ * 20.5it/s]`, where the done/total fields carry file counts, not bytes) and
9
+ * the byte bar (`Downloading x.safetensors: 12% | 5.2G/43.5G [01:23<10:11,
10
+ * 72.3MB/s]`, where the done/total fields carry human byte sizes). It
11
+ * converts the human byte sizes to bytes and the `[elapsed<remaining, rate]`
12
+ * tail to remaining seconds, and marks the unit the done/total amounts carry
13
+ * (`'files'` for the file-count bar, `'bytes'` for the byte bar), so a
14
+ * readout renders the amounts in the unit the bar measured. The client
15
+ * package mirrors this parser in
16
+ * `packages/client/src/store/progress.ts` (the TASK-006 browser-side copy):
17
+ * the core package is not browser-safe, so the client bundle keeps its own
18
+ * copy and the two shapes (`HfProgress` and the client's `HfProgressShape`)
19
+ * must stay in sync when a tqdm bar shape changes.
20
+ * @module dsh-plugin-local-infer/core/progress
21
+ */
22
+ // The file-count bar: `Fetching 102 files: 42%|...| 43/102 [00:01<00:02, ...]`.
23
+ // The bar glyph run between the pipes is skipped, and the counts are plain
24
+ // integers.
25
+ const FILES_LINE = /^Fetching (\d+) files:\s*(\d+(?:\.\d+)?)%\|[^|]*\|\s*(\d+)\s*\/\s*(\d+)(?:\s*\[([^\]]*)\])?/;
26
+ // The byte bar: `Downloading x.safetensors: 12% | 5.2G/43.5G [01:23<10:11, ...]`.
27
+ // The sizes carry an optional K/M/G/T/P unit (decimal, or binary with an
28
+ // `i`), and the tail is optional (a finished bar drops it).
29
+ const BYTES_LINE = /^(?:Downloading|Fetching)\s+([^:]+):\s*(\d+(?:\.\d+)?)%\s*\|\s*(\d+(?:\.\d+)?[KMGTP]?i?B?)\s*\/\s*(\d+(?:\.\d+)?[KMGTP]?i?B?)\s*(?:\[([^\]]*)\])?/;
30
+ // The unit exponents for the decimal (1000-based) sizes the hf CLI's tqdm
31
+ // renders; a binary `i` suffix (Gi, Mi, ...) switches the base to 1024.
32
+ const UNIT_EXPONENTS = { K: 1, M: 2, G: 3, T: 4, P: 5 };
33
+ // parseHumanSize converts one human byte size (`5.2G`) to bytes: the decimal
34
+ // base the hf CLI's tqdm uses, with a 1024 base when the unit carries the
35
+ // binary `i` suffix. A size with no unit is a plain byte count.
36
+ function parseHumanSize(text) {
37
+ const match = /^(\d+(?:\.\d+)?)([KMGTP]?)i?B?$/.exec(text);
38
+ if (match === null)
39
+ return 0;
40
+ const exponent = UNIT_EXPONENTS[match[2]] ?? 0;
41
+ const base = text.includes('i') ? 1024 : 1000;
42
+ return Number(match[1]) * base ** exponent;
43
+ }
44
+ // durationSeconds converts a `MM:SS`, `H:MM:SS`, or `D:H:MM:SS` clock string
45
+ // to seconds, the tqdm tail's remaining-time format.
46
+ function durationSeconds(text) {
47
+ let seconds = 0;
48
+ for (const part of text.split(':')) {
49
+ seconds = seconds * 60 + Number(part);
50
+ }
51
+ return seconds;
52
+ }
53
+ // etaSecondsFromTail reads the remaining time out of a tqdm tail
54
+ // (`01:23<10:11, 72.3MB/s`): the clock string after the `<`, 0 when the tail
55
+ // is absent or carries no remaining time.
56
+ function etaSecondsFromTail(tail) {
57
+ if (tail === undefined)
58
+ return 0;
59
+ const match = /<\s*(\d+(?::\d+)+)/.exec(tail);
60
+ if (match === null)
61
+ return 0;
62
+ return durationSeconds(match[1]);
63
+ }
64
+ /**
65
+ * parseHfProgressLine parses one tqdm bar line into an HfProgress state, or
66
+ * undefined when the line is not a bar update (a plain log line, a command
67
+ * echo). It recognizes the file-count and byte shapes above.
68
+ */
69
+ export function parseHfProgressLine(line) {
70
+ const trimmed = line.trim();
71
+ if (trimmed === '')
72
+ return undefined;
73
+ const files = FILES_LINE.exec(trimmed);
74
+ if (files !== null) {
75
+ // The file-count bar carries counts, not bytes: the done/total fields
76
+ // hold the file numbers, the step label names the fetch, and the unit
77
+ // marks the amounts as file counts, so a readout renders them as files.
78
+ return {
79
+ step: `Fetching ${files[1]} files`,
80
+ percent: Number(files[2]),
81
+ doneBytes: Number(files[3]),
82
+ totalBytes: Number(files[4]),
83
+ etaSeconds: etaSecondsFromTail(files[5]),
84
+ unit: 'files',
85
+ };
86
+ }
87
+ const bytes = BYTES_LINE.exec(trimmed);
88
+ if (bytes !== null) {
89
+ const verb = trimmed.startsWith('Fetching') ? 'Fetching' : 'Downloading';
90
+ // The byte bar carries human byte sizes: the done/total fields hold the
91
+ // parsed byte counts, and the unit marks the amounts as bytes.
92
+ return {
93
+ step: `${verb} ${bytes[1].trim()}`,
94
+ percent: Number(bytes[2]),
95
+ doneBytes: parseHumanSize(bytes[3]),
96
+ totalBytes: parseHumanSize(bytes[4]),
97
+ etaSeconds: etaSecondsFromTail(bytes[5]),
98
+ unit: 'bytes',
99
+ };
100
+ }
101
+ return undefined;
102
+ }
103
+ /**
104
+ * foldHfProgressChunk folds a raw stderr chunk into the latest HfProgress
105
+ * state it carries: the chunk splits on the line separators tqdm writes
106
+ * (carriage returns between bar redraws, newlines between steps), each line
107
+ * parses through parseHfProgressLine, and the last parseable line wins. A
108
+ * chunk with no bar update returns the prior state, so a caller threads the
109
+ * fold across chunks and always holds the newest state.
110
+ */
111
+ export function foldHfProgressChunk(chunk, prior) {
112
+ let folded = prior;
113
+ for (const line of chunk.split(/\r\n|\r|\n/)) {
114
+ const parsed = parseHfProgressLine(line);
115
+ if (parsed !== undefined)
116
+ folded = parsed;
117
+ }
118
+ return folded;
119
+ }
120
+ //# sourceMappingURL=progress.js.map