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.
- package/README.md +22 -4
- package/cordis.patch.yml +7 -0
- package/docs/zh/README.md +14 -2
- package/dsh/client.js +4195 -4522
- package/package.json +28 -11
- package/packages/core/lib/adapter.d.ts +133 -9
- package/packages/core/lib/adapter.js +74 -1
- package/packages/core/lib/config.d.ts +1 -1
- package/packages/core/lib/config.js +1 -1
- package/packages/core/lib/debug.d.ts +1 -1
- package/packages/core/lib/debug.js +1 -1
- package/packages/core/lib/defaults.d.ts +1 -1
- package/packages/core/lib/defaults.js +1 -1
- package/packages/core/lib/deps.d.ts +44 -17
- package/packages/core/lib/deps.js +24 -8
- package/packages/core/lib/estimator.d.ts +1 -1
- package/packages/core/lib/estimator.js +1 -1
- package/packages/core/lib/guideline.d.ts +1 -1
- package/packages/core/lib/guideline.js +1 -1
- package/packages/core/lib/hardware.d.ts +1 -1
- package/packages/core/lib/hardware.js +1 -1
- package/packages/core/lib/hf-cache.d.ts +70 -0
- package/packages/core/lib/hf-cache.js +83 -0
- package/packages/core/lib/index.d.ts +16 -9
- package/packages/core/lib/index.js +10 -6
- package/packages/core/lib/infer-cache.d.ts +39 -0
- package/packages/core/lib/infer-cache.js +53 -0
- package/packages/core/lib/launch-command.d.ts +8 -4
- package/packages/core/lib/launch-command.js +13 -6
- package/packages/core/lib/launch-record.d.ts +1 -1
- package/packages/core/lib/launch-record.js +1 -1
- package/packages/core/lib/logs.d.ts +8 -1
- package/packages/core/lib/logs.js +12 -4
- package/packages/core/lib/models.d.ts +120 -14
- package/packages/core/lib/models.js +209 -17
- package/packages/core/lib/parameter.d.ts +31 -3
- package/packages/core/lib/parameter.js +1 -1
- package/packages/core/lib/progress.d.ts +54 -0
- package/packages/core/lib/progress.js +120 -0
- package/packages/core/lib/registrar.d.ts +20 -9
- package/packages/core/lib/registrar.js +27 -7
- package/packages/core/lib/reserve.d.ts +11 -3
- package/packages/core/lib/reserve.js +6 -4
- package/packages/core/lib/status.d.ts +12 -6
- package/packages/core/lib/status.js +21 -10
- package/packages/core/lib/sudo.d.ts +80 -0
- package/packages/core/lib/sudo.js +78 -0
- package/packages/core/package.json +1 -1
- package/packages/orchestrator/lib/config.d.ts +63 -0
- package/packages/orchestrator/lib/config.js +111 -0
- package/packages/orchestrator/lib/index.d.ts +51 -0
- package/packages/orchestrator/lib/index.js +73 -0
- package/packages/orchestrator/lib/route.d.ts +60 -0
- package/packages/orchestrator/lib/route.js +159 -0
- package/packages/orchestrator/locale/en.json +6 -0
- package/packages/orchestrator/package.json +39 -0
- package/packages/orchestrator/prompt.md +87 -0
- package/packages/providers/lib/acquire.d.ts +92 -14
- package/packages/providers/lib/acquire.js +215 -37
- package/packages/providers/lib/adapters.d.ts +136 -12
- package/packages/providers/lib/adapters.js +597 -70
- package/packages/providers/lib/debug.d.ts +1 -1
- package/packages/providers/lib/debug.js +1 -1
- package/packages/providers/lib/deps.d.ts +27 -230
- package/packages/providers/lib/deps.js +61 -214
- package/packages/providers/lib/engines/basalt/basalt.d.ts +130 -0
- package/packages/providers/lib/engines/basalt/basalt.js +304 -0
- package/packages/providers/lib/engines/basalt/basaltAdapter.d.ts +85 -0
- package/packages/providers/lib/engines/basalt/basaltAdapter.js +439 -0
- package/packages/providers/lib/engines/basalt/basaltLinux.d.ts +23 -0
- package/packages/providers/lib/engines/basalt/basaltLinux.js +47 -0
- package/packages/providers/lib/engines/basalt/basaltMacOS.d.ts +17 -0
- package/packages/providers/lib/engines/basalt/basaltMacOS.js +19 -0
- package/packages/providers/lib/engines/basalt/basaltWindows.d.ts +24 -0
- package/packages/providers/lib/engines/basalt/basaltWindows.js +49 -0
- package/packages/providers/lib/engines/engineOs.d.ts +24 -0
- package/packages/providers/lib/engines/engineOs.js +17 -0
- package/packages/providers/lib/engines/{hyperqwen.d.ts → hyperqwen/hyperqwen.d.ts} +2 -2
- package/packages/providers/lib/engines/{hyperqwen.js → hyperqwen/hyperqwen.js} +14 -2
- package/packages/providers/lib/engines/{hyperqwenAdapter.d.ts → hyperqwen/hyperqwenAdapter.d.ts} +6 -6
- package/packages/providers/lib/engines/{hyperqwenAdapter.js → hyperqwen/hyperqwenAdapter.js} +24 -14
- package/packages/providers/lib/engines/hyperqwen/hyperqwenArch.d.ts +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenArch.js +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenDebian.d.ts +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenDebian.js +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenFedora.d.ts +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenFedora.js +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenLinux.d.ts +10 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenLinux.js +14 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenMacOS.d.ts +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenMacOS.js +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenWindows.d.ts +9 -0
- package/packages/providers/lib/engines/hyperqwen/hyperqwenWindows.js +9 -0
- package/packages/providers/lib/engines/{infernix.d.ts → infernix/infernix.d.ts} +7 -4
- package/packages/providers/lib/engines/{infernix.js → infernix/infernix.js} +52 -7
- package/packages/providers/lib/engines/{infernixAdapter.d.ts → infernix/infernixAdapter.d.ts} +5 -6
- package/packages/providers/lib/engines/{infernixAdapter.js → infernix/infernixAdapter.js} +75 -42
- package/packages/providers/lib/engines/infernix/infernixArch.d.ts +9 -0
- package/packages/providers/lib/engines/infernix/infernixArch.js +9 -0
- package/packages/providers/lib/engines/infernix/infernixDebian.d.ts +9 -0
- package/packages/providers/lib/engines/infernix/infernixDebian.js +9 -0
- package/packages/providers/lib/engines/infernix/infernixFedora.d.ts +9 -0
- package/packages/providers/lib/engines/infernix/infernixFedora.js +9 -0
- package/packages/providers/lib/engines/infernix/infernixLinux.d.ts +17 -0
- package/packages/providers/lib/engines/infernix/infernixLinux.js +35 -0
- package/packages/providers/lib/engines/infernix/infernixMacOS.d.ts +16 -0
- package/packages/providers/lib/engines/infernix/infernixMacOS.js +18 -0
- package/packages/providers/lib/engines/infernix/infernixWindows.d.ts +16 -0
- package/packages/providers/lib/engines/infernix/infernixWindows.js +34 -0
- package/packages/providers/lib/engines/{llamacpp.d.ts → llamacpp/llamacpp.d.ts} +2 -2
- package/packages/providers/lib/engines/{llamacpp.js → llamacpp/llamacpp.js} +12 -2
- package/packages/providers/lib/engines/{llamacppAdapter.d.ts → llamacpp/llamacppAdapter.d.ts} +5 -6
- package/packages/providers/lib/engines/{llamacppAdapter.js → llamacpp/llamacppAdapter.js} +87 -45
- package/packages/providers/lib/engines/llamacpp/llamacppArch.d.ts +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppArch.js +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppDebian.d.ts +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppDebian.js +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppFedora.d.ts +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppFedora.js +9 -0
- package/packages/providers/lib/engines/llamacpp/llamacppLinux.d.ts +17 -0
- package/packages/providers/lib/engines/llamacpp/llamacppLinux.js +28 -0
- package/packages/providers/lib/engines/llamacpp/llamacppMacOS.d.ts +15 -0
- package/packages/providers/lib/engines/llamacpp/llamacppMacOS.js +17 -0
- package/packages/providers/lib/engines/llamacpp/llamacppWindows.d.ts +15 -0
- package/packages/providers/lib/engines/llamacpp/llamacppWindows.js +26 -0
- package/packages/providers/lib/engines/{ninfer.d.ts → ninfer/ninfer.d.ts} +2 -2
- package/packages/providers/lib/engines/{ninfer.js → ninfer/ninfer.js} +24 -2
- package/packages/providers/lib/engines/{ninferAdapter.d.ts → ninfer/ninferAdapter.d.ts} +5 -6
- package/packages/providers/lib/engines/{ninferAdapter.js → ninfer/ninferAdapter.js} +123 -55
- package/packages/providers/lib/engines/ninfer/ninferArch.d.ts +9 -0
- package/packages/providers/lib/engines/ninfer/ninferArch.js +9 -0
- package/packages/providers/lib/engines/ninfer/ninferDebian.d.ts +9 -0
- package/packages/providers/lib/engines/ninfer/ninferDebian.js +9 -0
- package/packages/providers/lib/engines/ninfer/ninferFedora.d.ts +9 -0
- package/packages/providers/lib/engines/ninfer/ninferFedora.js +9 -0
- package/packages/providers/lib/engines/ninfer/ninferLinux.d.ts +17 -0
- package/packages/providers/lib/engines/ninfer/ninferLinux.js +37 -0
- package/packages/providers/lib/engines/ninfer/ninferMacOS.d.ts +15 -0
- package/packages/providers/lib/engines/ninfer/ninferMacOS.js +17 -0
- package/packages/providers/lib/engines/ninfer/ninferWindows.d.ts +29 -0
- package/packages/providers/lib/engines/ninfer/ninferWindows.js +59 -0
- package/packages/providers/lib/engines/strata/strata.d.ts +1 -0
- package/packages/providers/lib/engines/{strata.js → strata/strata.js} +70 -3
- package/packages/providers/lib/engines/{strataAdapter.d.ts → strata/strataAdapter.d.ts} +5 -6
- package/packages/providers/lib/engines/{strataAdapter.js → strata/strataAdapter.js} +147 -111
- package/packages/providers/lib/engines/strata/strataArch.d.ts +9 -0
- package/packages/providers/lib/engines/strata/strataArch.js +9 -0
- package/packages/providers/lib/engines/strata/strataDebian.d.ts +9 -0
- package/packages/providers/lib/engines/strata/strataDebian.js +9 -0
- package/packages/providers/lib/engines/strata/strataFedora.d.ts +9 -0
- package/packages/providers/lib/engines/strata/strataFedora.js +9 -0
- package/packages/providers/lib/engines/strata/strataLinux.d.ts +21 -0
- package/packages/providers/lib/engines/strata/strataLinux.js +30 -0
- package/packages/providers/lib/engines/strata/strataMacOS.d.ts +16 -0
- package/packages/providers/lib/engines/strata/strataMacOS.js +17 -0
- package/packages/providers/lib/engines/strata/strataWindows.d.ts +27 -0
- package/packages/providers/lib/engines/strata/strataWindows.js +37 -0
- package/packages/providers/lib/engines.d.ts +7 -5
- package/packages/providers/lib/engines.js +21 -10
- package/packages/providers/lib/guidelines.d.ts +5 -4
- package/packages/providers/lib/guidelines.js +18 -5
- package/packages/providers/lib/index.d.ts +33 -29
- package/packages/providers/lib/index.js +45 -33
- package/packages/providers/lib/model-defaults.d.ts +5 -1
- package/packages/providers/lib/model-defaults.js +25 -1
- package/packages/providers/lib/platform.d.ts +8 -5
- package/packages/providers/lib/platform.js +23 -9
- package/packages/providers/lib/presets.d.ts +6 -4
- package/packages/providers/lib/presets.js +53 -5
- package/packages/providers/lib/systemDeps.d.ts +313 -0
- package/packages/providers/lib/systemDeps.js +284 -0
- package/packages/providers/lib/vram.d.ts +34 -8
- package/packages/providers/lib/vram.js +81 -8
- package/packages/providers/package.json +2 -2
- package/packages/service/lib/index.d.ts +176 -21
- package/packages/service/lib/index.js +589 -86
- package/packages/service/lib/launch-target.d.ts +19 -0
- package/packages/service/lib/launch-target.js +28 -0
- package/packages/service/lib/run-logs.d.ts +72 -0
- package/packages/service/lib/run-logs.js +125 -0
- package/packages/service/lib/types.d.ts +163 -6
- package/packages/service/lib/types.js +1 -1
- package/packages/service/package.json +2 -2
- package/packages/tool/lib/index.d.ts +1 -1
- package/packages/tool/lib/index.js +1 -1
- package/packages/tool/package.json +2 -2
- package/packages/ui/lib/config.d.ts +12 -2
- package/packages/ui/lib/config.js +18 -2
- package/packages/ui/lib/deps.d.ts +1 -1
- package/packages/ui/lib/deps.js +1 -1
- package/packages/ui/lib/form.d.ts +1 -1
- package/packages/ui/lib/form.js +1 -1
- package/packages/ui/lib/index.d.ts +7 -1
- package/packages/ui/lib/index.js +12 -2
- package/packages/ui/lib/meter.d.ts +1 -1
- package/packages/ui/lib/meter.js +1 -1
- package/packages/ui/lib/ops/engine.d.ts +142 -34
- package/packages/ui/lib/ops/engine.js +469 -265
- package/packages/ui/lib/ops/get-steps.d.ts +98 -0
- package/packages/ui/lib/ops/get-steps.js +359 -0
- package/packages/ui/lib/ops/hf.d.ts +26 -11
- package/packages/ui/lib/ops/hf.js +115 -25
- package/packages/ui/lib/ops/logs.d.ts +70 -15
- package/packages/ui/lib/ops/logs.js +96 -35
- package/packages/ui/lib/ops/model.d.ts +2 -10
- package/packages/ui/lib/ops/model.js +9 -16
- package/packages/ui/lib/request.d.ts +1 -1
- package/packages/ui/lib/request.js +1 -1
- package/packages/ui/lib/route.d.ts +22 -6
- package/packages/ui/lib/route.js +32 -9
- package/packages/ui/lib/routes/chat-template.d.ts +1 -14
- package/packages/ui/lib/routes/chat-template.js +1 -37
- package/packages/ui/lib/routes/deps.d.ts +1 -16
- package/packages/ui/lib/routes/deps.js +1 -27
- package/packages/ui/lib/routes/download.d.ts +1 -16
- package/packages/ui/lib/routes/download.js +1 -48
- package/packages/ui/lib/routes/get.d.ts +1 -18
- package/packages/ui/lib/routes/get.js +66 -17
- package/packages/ui/lib/routes/install.d.ts +1 -1
- package/packages/ui/lib/routes/install.js +1 -1
- package/packages/ui/lib/routes/launch.d.ts +13 -7
- package/packages/ui/lib/routes/launch.js +33 -9
- package/packages/ui/lib/routes/logs.d.ts +57 -0
- package/packages/ui/lib/routes/logs.js +117 -0
- package/packages/ui/lib/routes/provider-delete.d.ts +1 -1
- package/packages/ui/lib/routes/provider-delete.js +1 -1
- package/packages/ui/lib/routes/register.d.ts +1 -1
- package/packages/ui/lib/routes/register.js +1 -1
- package/packages/ui/lib/routes/save.d.ts +1 -1
- package/packages/ui/lib/routes/save.js +22 -2
- package/packages/ui/lib/routes/stop.d.ts +7 -4
- package/packages/ui/lib/routes/stop.js +7 -4
- package/packages/ui/lib/routes/stream.d.ts +40 -0
- package/packages/ui/lib/routes/stream.js +68 -0
- package/packages/ui/lib/routes/summary.d.ts +1 -1
- package/packages/ui/lib/routes/summary.js +1 -1
- package/packages/ui/lib/routes/unregister.d.ts +1 -1
- package/packages/ui/lib/routes/unregister.js +1 -1
- package/packages/ui/lib/viewmodels/deps.d.ts +1 -31
- package/packages/ui/lib/viewmodels/deps.js +1 -89
- package/packages/ui/lib/viewmodels/depsHelpers.d.ts +1 -28
- package/packages/ui/lib/viewmodels/depsHelpers.js +72 -11
- package/packages/ui/lib/viewmodels/summary.d.ts +7 -2
- package/packages/ui/lib/viewmodels/summary.js +55 -35
- package/packages/ui/lib/viewmodels/summaryHelpers.d.ts +1 -1
- package/packages/ui/lib/viewmodels/summaryHelpers.js +1 -1
- package/packages/ui/lib/warnings.d.ts +1 -1
- package/packages/ui/lib/warnings.js +1 -1
- package/packages/ui/package.json +4 -4
- package/packages/providers/lib/engines/strata.d.ts +0 -53
|
@@ -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
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* directory
|
|
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
|
|
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
|
-
*
|
|
36
|
-
* repo, the
|
|
37
|
-
* target
|
|
38
|
-
*
|
|
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 !== '' ?
|
|
43
|
-
return
|
|
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.
|
|
55
|
-
*
|
|
56
|
-
*
|
|
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
|
|
59
|
-
|
|
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
|
-
|
|
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 `
|
|
81
|
-
* turn a value into a CLI flag
|
|
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
|
|
@@ -2,8 +2,9 @@ import type { BuildMode, LaunchPlan } from './adapter.ts';
|
|
|
2
2
|
/**
|
|
3
3
|
* DshModelEntry is the shape of the model row the registrar writes into the
|
|
4
4
|
* dsh-llm-pi-ai provider: the provider id, the model id and display name, the
|
|
5
|
-
* context window, the engine's base URL,
|
|
6
|
-
*
|
|
5
|
+
* context window, the engine's base URL, the env-var name the provider reads
|
|
6
|
+
* its optional API key from, and the placeholder API key value the engine
|
|
7
|
+
* ships with so a model the user has not keyed still activates.
|
|
7
8
|
*/
|
|
8
9
|
export interface DshModelEntry {
|
|
9
10
|
providerId: string;
|
|
@@ -12,6 +13,7 @@ export interface DshModelEntry {
|
|
|
12
13
|
contextWindow: number;
|
|
13
14
|
baseURL: string;
|
|
14
15
|
apiKeyEnv: string;
|
|
16
|
+
apiKey: string;
|
|
15
17
|
input?: string[];
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
@@ -94,13 +96,22 @@ export declare function providerIdFor(engineId: string, modelId: string, buildMo
|
|
|
94
96
|
* underscores, plus _LOCAL_API_KEY.
|
|
95
97
|
*/
|
|
96
98
|
export declare function apiKeyEnvFor(engineId: string): string;
|
|
99
|
+
/**
|
|
100
|
+
* defaultApiKeyFor derives the placeholder API key value a local engine ships
|
|
101
|
+
* with: the engine id, uppercased and non-alphanumerics mapped to underscores,
|
|
102
|
+
* wrapped in double braces plus _LOCAL_API_KEY. The double braces mark the
|
|
103
|
+
* value as a placeholder, not a real key, so a model the user has not keyed
|
|
104
|
+
* still activates the pi-ai OpenAI route. A user-added key replaces it in a
|
|
105
|
+
* future turn.
|
|
106
|
+
*/
|
|
107
|
+
export declare function defaultApiKeyFor(engineId: string): string;
|
|
97
108
|
/**
|
|
98
109
|
* buildModelEntry turns a launch plan and a model row into the DshModelEntry
|
|
99
110
|
* the registrar writes. The provider id is the engine, build mode, and model
|
|
100
111
|
* slug; the display name is the engine, the build mode in parentheses, and
|
|
101
112
|
* the model name (falling back to the slug when the row carries none). The
|
|
102
|
-
* API-key env name
|
|
103
|
-
* engine's OpenAI endpoint on its port.
|
|
113
|
+
* API-key env name and the placeholder API key value derive from the engine
|
|
114
|
+
* id, and the base URL is the engine's OpenAI endpoint on its port.
|
|
104
115
|
*/
|
|
105
116
|
export declare function buildModelEntry(plan: LaunchPlan, model: ModelRow): DshModelEntry;
|
|
106
117
|
/**
|
|
@@ -118,10 +129,10 @@ export declare function upsertModelRow(rows: readonly ModelRow[], row: ModelRow)
|
|
|
118
129
|
export declare function removeModelRow(rows: readonly ModelRow[], modelId: string): ModelRow[];
|
|
119
130
|
/**
|
|
120
131
|
* providerRegistrationOps computes the settings ops that upsert a provider
|
|
121
|
-
* entry: the API-key env name, the openai-completions api, the base URL,
|
|
122
|
-
* the models list with the entry's row
|
|
123
|
-
* fields by path, so a provider the user
|
|
124
|
-
* the registrar does not own.
|
|
132
|
+
* entry: the API-key env name, the openai-completions api, the base URL, the
|
|
133
|
+
* placeholder Authorization header, and the models list with the entry's row
|
|
134
|
+
* upserted. The ops write the provider fields by path, so a provider the user
|
|
135
|
+
* edited by hand keeps every field the registrar does not own.
|
|
125
136
|
*/
|
|
126
137
|
export declare function providerRegistrationOps(entry: DshModelEntry, rows: readonly ModelRow[]): SettingsOp[];
|
|
127
138
|
/**
|
|
@@ -154,4 +165,4 @@ export declare function modelRowsFrom(value: unknown, providerId: string): reado
|
|
|
154
165
|
* when it names the removed pair.
|
|
155
166
|
*/
|
|
156
167
|
export declare function agentDefaultPointsAt(value: unknown, providerId: string, modelId: string): boolean;
|
|
157
|
-
//# sourceMappingURL=registrar.d.ts.map
|
|
168
|
+
//# sourceMappingURL=registrar.d.ts.map
|
|
@@ -42,6 +42,17 @@ export function providerIdFor(engineId, modelId, buildMode) {
|
|
|
42
42
|
export function apiKeyEnvFor(engineId) {
|
|
43
43
|
return `${engineId.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_LOCAL_API_KEY`;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* defaultApiKeyFor derives the placeholder API key value a local engine ships
|
|
47
|
+
* with: the engine id, uppercased and non-alphanumerics mapped to underscores,
|
|
48
|
+
* wrapped in double braces plus _LOCAL_API_KEY. The double braces mark the
|
|
49
|
+
* value as a placeholder, not a real key, so a model the user has not keyed
|
|
50
|
+
* still activates the pi-ai OpenAI route. A user-added key replaces it in a
|
|
51
|
+
* future turn.
|
|
52
|
+
*/
|
|
53
|
+
export function defaultApiKeyFor(engineId) {
|
|
54
|
+
return `{{${engineId.toUpperCase().replace(/[^A-Z0-9]/g, '_')}}}_LOCAL_API_KEY`;
|
|
55
|
+
}
|
|
45
56
|
/**
|
|
46
57
|
* engineDisplayName capitalizes the first letter of an engine id for the
|
|
47
58
|
* display name: `ninfer` reads as `Ninfer`, `hyperqwen` as `Hyperqwen`.
|
|
@@ -54,8 +65,8 @@ function engineDisplayName(engineId) {
|
|
|
54
65
|
* the registrar writes. The provider id is the engine, build mode, and model
|
|
55
66
|
* slug; the display name is the engine, the build mode in parentheses, and
|
|
56
67
|
* the model name (falling back to the slug when the row carries none). The
|
|
57
|
-
* API-key env name
|
|
58
|
-
* engine's OpenAI endpoint on its port.
|
|
68
|
+
* API-key env name and the placeholder API key value derive from the engine
|
|
69
|
+
* id, and the base URL is the engine's OpenAI endpoint on its port.
|
|
59
70
|
*/
|
|
60
71
|
export function buildModelEntry(plan, model) {
|
|
61
72
|
const buildMode = plan.kind === 'docker' ? 'docker' : 'local';
|
|
@@ -68,6 +79,7 @@ export function buildModelEntry(plan, model) {
|
|
|
68
79
|
contextWindow: model.contextWindow,
|
|
69
80
|
baseURL: `http://127.0.0.1:${plan.port}/v1`,
|
|
70
81
|
apiKeyEnv: apiKeyEnvFor(plan.engineId),
|
|
82
|
+
apiKey: defaultApiKeyFor(plan.engineId),
|
|
71
83
|
};
|
|
72
84
|
// exactOptionalPropertyTypes: carry the input modalities only when the row
|
|
73
85
|
// names them, so a text-only registration never writes an empty list.
|
|
@@ -101,10 +113,10 @@ export function removeModelRow(rows, modelId) {
|
|
|
101
113
|
}
|
|
102
114
|
/**
|
|
103
115
|
* providerRegistrationOps computes the settings ops that upsert a provider
|
|
104
|
-
* entry: the API-key env name, the openai-completions api, the base URL,
|
|
105
|
-
* the models list with the entry's row
|
|
106
|
-
* fields by path, so a provider the user
|
|
107
|
-
* the registrar does not own.
|
|
116
|
+
* entry: the API-key env name, the openai-completions api, the base URL, the
|
|
117
|
+
* placeholder Authorization header, and the models list with the entry's row
|
|
118
|
+
* upserted. The ops write the provider fields by path, so a provider the user
|
|
119
|
+
* edited by hand keeps every field the registrar does not own.
|
|
108
120
|
*/
|
|
109
121
|
export function providerRegistrationOps(entry, rows) {
|
|
110
122
|
const providerPath = ['providers', entry.providerId];
|
|
@@ -119,10 +131,18 @@ export function providerRegistrationOps(entry, rows) {
|
|
|
119
131
|
if (entry.input !== undefined) {
|
|
120
132
|
row.input = entry.input;
|
|
121
133
|
}
|
|
134
|
+
// The pi-ai OpenAI route requires an API key or an Authorization header, so
|
|
135
|
+
// a keyless local server ships the placeholder key as a Bearer header. The
|
|
136
|
+
// profile schema has no literal apiKey field; headers carry the value.
|
|
122
137
|
return [
|
|
123
138
|
{ op: 'set', path: [...providerPath, 'apiKeyEnv'], value: entry.apiKeyEnv },
|
|
124
139
|
{ op: 'set', path: [...providerPath, 'api'], value: 'openai-completions' },
|
|
125
140
|
{ op: 'set', path: [...providerPath, 'baseURL'], value: entry.baseURL },
|
|
141
|
+
{
|
|
142
|
+
op: 'set',
|
|
143
|
+
path: [...providerPath, 'headers', 'Authorization'],
|
|
144
|
+
value: `Bearer ${entry.apiKey}`,
|
|
145
|
+
},
|
|
126
146
|
{ op: 'set', path: [...providerPath, 'models'], value: upsertModelRow(rows, row) },
|
|
127
147
|
];
|
|
128
148
|
}
|
|
@@ -205,4 +225,4 @@ export function agentDefaultPointsAt(value, providerId, modelId) {
|
|
|
205
225
|
const section = value;
|
|
206
226
|
return section.provider === providerId && section.model === modelId;
|
|
207
227
|
}
|
|
208
|
-
//# sourceMappingURL=registrar.js.map
|
|
228
|
+
//# sourceMappingURL=registrar.js.map
|
|
@@ -25,6 +25,13 @@ export declare function parseNvidiaSmiGpuUsage(output: string): GpuUsageProbe |
|
|
|
25
25
|
export interface EngineLaunchSignature {
|
|
26
26
|
binary: string;
|
|
27
27
|
port?: number;
|
|
28
|
+
/**
|
|
29
|
+
* When false the engine binds its port from a file (Basalt's
|
|
30
|
+
* basalt_config.json server block), so the matcher never sees the number
|
|
31
|
+
* in the command line and must skip the port element. Undefined reads as
|
|
32
|
+
* true: the port must appear as a standalone number, the current rule.
|
|
33
|
+
*/
|
|
34
|
+
portInArgv?: boolean;
|
|
28
35
|
envKeys?: readonly string[];
|
|
29
36
|
}
|
|
30
37
|
/**
|
|
@@ -44,8 +51,9 @@ export interface ProcessLine {
|
|
|
44
51
|
* signature. The binary marker must appear in the command line (the image
|
|
45
52
|
* name for a docker plan, the engine binary for a local one); a declared port
|
|
46
53
|
* must appear as a standalone number (the `--port N` flag or the docker
|
|
47
|
-
* `-p host:port:port` mapping)
|
|
48
|
-
*
|
|
54
|
+
* `-p host:port:port` mapping) unless `portInArgv` is false, which means the
|
|
55
|
+
* engine binds its port from a file; a declared env key must be set when the
|
|
56
|
+
* line carries env data, and is neutral when it does not.
|
|
49
57
|
*/
|
|
50
58
|
export declare function matchLaunchSignature(line: ProcessLine, signature: EngineLaunchSignature): boolean;
|
|
51
59
|
/**
|
|
@@ -86,4 +94,4 @@ export declare function resolveOsReserve(input: {
|
|
|
86
94
|
foreignProcess?: boolean;
|
|
87
95
|
gpuUsage?: GpuUsageProbe | null;
|
|
88
96
|
}): ReserveResolution;
|
|
89
|
-
//# sourceMappingURL=reserve.d.ts.map
|
|
97
|
+
//# sourceMappingURL=reserve.d.ts.map
|