dsh-plugin-local-infer 0.1.1 → 0.1.3
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 +14 -3
- package/docs/zh/README.md +14 -3
- package/dsh/client.js +1214 -242
- package/package.json +16 -10
- package/packages/core/lib/adapter.d.ts +119 -6
- package/packages/core/lib/deps.d.ts +4 -3
- package/packages/core/lib/index.d.ts +2 -1
- package/packages/core/lib/index.js +1 -0
- package/packages/core/lib/launch-command.d.ts +13 -0
- package/packages/core/lib/launch-command.js +64 -0
- package/packages/core/lib/models.d.ts +2 -1
- package/packages/core/lib/models.js +10 -1
- package/packages/core/lib/registrar.d.ts +5 -5
- package/packages/core/lib/registrar.js +3 -3
- package/packages/core/lib/status.d.ts +9 -1
- package/packages/core/lib/status.js +6 -1
- package/packages/core/package.json +1 -1
- package/packages/providers/lib/acquire.d.ts +127 -0
- package/packages/providers/lib/acquire.js +346 -0
- package/packages/providers/lib/adapters.d.ts +19 -172
- package/packages/providers/lib/adapters.js +114 -659
- package/packages/providers/lib/deps.d.ts +26 -2
- package/packages/providers/lib/deps.js +37 -4
- package/packages/providers/lib/engines/hyperqwenAdapter.d.ts +38 -0
- package/packages/providers/lib/engines/hyperqwenAdapter.js +105 -0
- package/packages/providers/lib/engines/infernix.d.ts +170 -0
- package/packages/providers/lib/engines/infernix.js +671 -0
- package/packages/providers/lib/engines/infernixAdapter.d.ts +53 -0
- package/packages/providers/lib/engines/infernixAdapter.js +202 -0
- package/packages/providers/lib/engines/llamacppAdapter.d.ts +51 -0
- package/packages/providers/lib/engines/llamacppAdapter.js +232 -0
- package/packages/providers/lib/{ninfer.d.ts → engines/ninfer.d.ts} +7 -0
- package/packages/providers/lib/{ninfer.js → engines/ninfer.js} +8 -1
- package/packages/providers/lib/engines/ninferAdapter.d.ts +82 -0
- package/packages/providers/lib/engines/ninferAdapter.js +324 -0
- package/packages/providers/lib/engines/strata.d.ts +53 -0
- package/packages/providers/lib/engines/strata.js +197 -0
- package/packages/providers/lib/engines/strataAdapter.d.ts +98 -0
- package/packages/providers/lib/engines/strataAdapter.js +427 -0
- package/packages/providers/lib/engines.d.ts +5 -3
- package/packages/providers/lib/engines.js +16 -8
- package/packages/providers/lib/guidelines.js +16 -0
- package/packages/providers/lib/index.d.ts +21 -10
- package/packages/providers/lib/index.js +23 -9
- package/packages/providers/lib/model-defaults.d.ts +8 -5
- package/packages/providers/lib/model-defaults.js +47 -5
- package/packages/providers/lib/platform.d.ts +31 -0
- package/packages/providers/lib/platform.js +64 -0
- package/packages/providers/package.json +1 -1
- package/packages/service/lib/index.d.ts +74 -22
- package/packages/service/lib/index.js +354 -44
- package/packages/service/lib/types.d.ts +48 -5
- package/packages/service/package.json +1 -1
- package/packages/tool/package.json +1 -1
- package/packages/ui/lib/config.d.ts +79 -0
- package/packages/ui/lib/config.js +235 -0
- package/packages/ui/lib/deps.d.ts +3 -3
- package/packages/ui/lib/ops/engine.d.ts +108 -0
- package/packages/ui/lib/ops/engine.js +493 -0
- package/packages/ui/lib/ops/hf.d.ts +27 -0
- package/packages/ui/lib/ops/hf.js +60 -0
- package/packages/ui/lib/ops/logs.d.ts +23 -0
- package/packages/ui/lib/ops/logs.js +58 -0
- package/packages/ui/lib/ops/model.d.ts +79 -0
- package/packages/ui/lib/ops/model.js +130 -0
- package/packages/ui/lib/request.d.ts +106 -0
- package/packages/ui/lib/request.js +80 -0
- package/packages/ui/lib/route.d.ts +96 -357
- package/packages/ui/lib/route.js +123 -1415
- package/packages/ui/lib/routes/chat-template.d.ts +14 -0
- package/packages/ui/lib/routes/chat-template.js +37 -0
- package/packages/ui/lib/routes/deps.d.ts +16 -0
- package/packages/ui/lib/routes/deps.js +27 -0
- package/packages/ui/lib/routes/download.d.ts +16 -0
- package/packages/ui/lib/routes/download.js +48 -0
- package/packages/ui/lib/routes/get.d.ts +18 -0
- package/packages/ui/lib/routes/get.js +57 -0
- package/packages/ui/lib/routes/install.d.ts +16 -0
- package/packages/ui/lib/routes/install.js +36 -0
- package/packages/ui/lib/routes/launch.d.ts +18 -0
- package/packages/ui/lib/routes/launch.js +50 -0
- package/packages/ui/lib/routes/provider-delete.d.ts +15 -0
- package/packages/ui/lib/routes/provider-delete.js +37 -0
- package/packages/ui/lib/routes/register.d.ts +16 -0
- package/packages/ui/lib/routes/register.js +28 -0
- package/packages/ui/lib/routes/save.d.ts +18 -0
- package/packages/ui/lib/routes/save.js +139 -0
- package/packages/ui/lib/routes/stop.d.ts +16 -0
- package/packages/ui/lib/routes/stop.js +29 -0
- package/packages/ui/lib/routes/summary.d.ts +15 -0
- package/packages/ui/lib/routes/summary.js +26 -0
- package/packages/ui/lib/routes/unregister.d.ts +14 -0
- package/packages/ui/lib/routes/unregister.js +26 -0
- package/packages/ui/lib/viewmodels/deps.d.ts +31 -0
- package/packages/ui/lib/viewmodels/deps.js +89 -0
- package/packages/ui/lib/viewmodels/depsHelpers.d.ts +28 -0
- package/packages/ui/lib/viewmodels/depsHelpers.js +33 -0
- package/packages/ui/lib/viewmodels/summary.d.ts +140 -0
- package/packages/ui/lib/viewmodels/summary.js +225 -0
- package/packages/ui/lib/viewmodels/summaryHelpers.d.ts +30 -0
- package/packages/ui/lib/viewmodels/summaryHelpers.js +42 -0
- package/packages/ui/package.json +1 -1
- package/packages/providers/lib/strata.d.ts +0 -15
- package/packages/providers/lib/strata.js +0 -14
- /package/packages/providers/lib/{hyperqwen.d.ts → engines/hyperqwen.d.ts} +0 -0
- /package/packages/providers/lib/{hyperqwen.js → engines/hyperqwen.js} +0 -0
- /package/packages/providers/lib/{llamacpp.d.ts → engines/llamacpp.d.ts} +0 -0
- /package/packages/providers/lib/{llamacpp.js → engines/llamacpp.js} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-local-infer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,7 +21,12 @@
|
|
|
21
21
|
"ai-agent"
|
|
22
22
|
],
|
|
23
23
|
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/cybtachyon/dsh-plugin-local-infer"
|
|
27
|
+
},
|
|
24
28
|
"type": "module",
|
|
29
|
+
"packageManager": "pnpm@12.11.2",
|
|
25
30
|
"engines": {
|
|
26
31
|
"node": "^22.19.0 || >=24.0.0"
|
|
27
32
|
},
|
|
@@ -85,22 +90,23 @@
|
|
|
85
90
|
"peerDependencies": {
|
|
86
91
|
"@deepseek-ai/cordis": ">=4.0.5-alpha.2"
|
|
87
92
|
},
|
|
93
|
+
"scripts": {
|
|
94
|
+
"build": "tsc -b",
|
|
95
|
+
"typecheck": "tsc -b",
|
|
96
|
+
"test": "vitest run",
|
|
97
|
+
"test:coverage": "vitest run --coverage",
|
|
98
|
+
"lint": "eslint .",
|
|
99
|
+
"clean": "tsc -b --clean"
|
|
100
|
+
},
|
|
88
101
|
"devDependencies": {
|
|
89
102
|
"@eslint/js": "^10.0.1",
|
|
90
103
|
"@types/node": "^22.10.0",
|
|
91
104
|
"@vitest/coverage-v8": "^5.0.4",
|
|
92
105
|
"eslint": "^10.12.0",
|
|
106
|
+
"tsx": "^4.23.15",
|
|
93
107
|
"typescript": "^5.9.0",
|
|
94
108
|
"typescript-eslint": "^8.71.2",
|
|
95
109
|
"vite-tsconfig-paths": "^5.1.4",
|
|
96
110
|
"vitest": "^5.0.4"
|
|
97
|
-
},
|
|
98
|
-
"scripts": {
|
|
99
|
-
"build": "tsc -b",
|
|
100
|
-
"typecheck": "tsc -b",
|
|
101
|
-
"test": "vitest run",
|
|
102
|
-
"test:coverage": "vitest run --coverage",
|
|
103
|
-
"lint": "eslint .",
|
|
104
|
-
"clean": "tsc -b --clean"
|
|
105
111
|
}
|
|
106
|
-
}
|
|
112
|
+
}
|
|
@@ -5,6 +5,13 @@ import type { HardwareProfile } from './hardware.ts';
|
|
|
5
5
|
import type { ParameterSpec } from './parameter.ts';
|
|
6
6
|
import type { SystemDep } from './deps.ts';
|
|
7
7
|
import type { EngineLaunchSignature } from './reserve.ts';
|
|
8
|
+
/**
|
|
9
|
+
* BuildMode is the deploy mode an engine renders a plan for: a docker
|
|
10
|
+
* container, a local source build, or a prebuilt binary install (the Strata
|
|
11
|
+
* Terminal the install script places on the path). The adapter reads it from
|
|
12
|
+
* the config `buildMode` field and renders the matching plan.
|
|
13
|
+
*/
|
|
14
|
+
export type BuildMode = 'docker' | 'local' | 'binary';
|
|
8
15
|
/**
|
|
9
16
|
* LaunchPlan is the engine-neutral result of rendering a config: how to start
|
|
10
17
|
* the engine (a local process, a docker container, or a compose file), the
|
|
@@ -21,6 +28,7 @@ export interface LaunchPlan {
|
|
|
21
28
|
env?: Record<string, string>;
|
|
22
29
|
composeFile?: string;
|
|
23
30
|
profile?: string;
|
|
31
|
+
composeArgs?: string;
|
|
24
32
|
containerName?: string;
|
|
25
33
|
modelId?: string;
|
|
26
34
|
modelDirectory?: string;
|
|
@@ -32,12 +40,31 @@ export interface LaunchPlan {
|
|
|
32
40
|
* specific engine: where the engine platform lives locally (the checkout and
|
|
33
41
|
* build location) and the git repo that overrides the engine's default
|
|
34
42
|
* upstream for this config. The deploy step consumes both: it clones the fork
|
|
35
|
-
* (or the default upstream) into the engine directory.
|
|
43
|
+
* (or the default upstream) into the engine directory. `buildCommands`
|
|
44
|
+
* overrides the engine's local build command (the local build mode) and
|
|
45
|
+
* `dockerTag` overrides the docker image tag the docker deploy pulls (the
|
|
46
|
+
* docker build mode); each rides the platform map, so an engine switch keeps
|
|
47
|
+
* them.
|
|
36
48
|
*/
|
|
37
49
|
export interface EnginePlatformConfig {
|
|
38
50
|
engineId: string;
|
|
39
51
|
engineDirectory?: string;
|
|
40
52
|
engineFork?: string;
|
|
53
|
+
buildCommands?: string;
|
|
54
|
+
dockerTag?: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* ProcessExitInfo is the one-shot answer to a spawned process's lifetime end:
|
|
58
|
+
* the exit code (null when a signal or a spawn failure ended it), the signal
|
|
59
|
+
* name (null when the process exited on its own), and the spawn error message
|
|
60
|
+
* when the child never ran (a missing binary). The host emits it exactly once
|
|
61
|
+
* per child, from the close event or the error event, so a crash or a pkill
|
|
62
|
+
* reaches the plugin's state through one seam instead of an uncaughtException.
|
|
63
|
+
*/
|
|
64
|
+
export interface ProcessExitInfo {
|
|
65
|
+
code: number | null;
|
|
66
|
+
signal: string | null;
|
|
67
|
+
error?: string;
|
|
41
68
|
}
|
|
42
69
|
/**
|
|
43
70
|
* ProcessHandle is the handle to a spawned engine process: its pid and a kill
|
|
@@ -46,12 +73,17 @@ export interface EnginePlatformConfig {
|
|
|
46
73
|
* the host captures the child's stdout and stderr, is the accumulated output
|
|
47
74
|
* the launch step surfaces in the card's Logs section and writes to the log
|
|
48
75
|
* file. A host that does not capture streams (a container it cannot read)
|
|
49
|
-
* omits it.
|
|
76
|
+
* omits it. `onExit`, when the host watches the child, registers a listener
|
|
77
|
+
* fired once with the ProcessExitInfo when the child ends (a crash, a signal
|
|
78
|
+
* like a pkill, or a clean stop); a listener registered after the child has
|
|
79
|
+
* already ended fires immediately. A host that cannot watch (a stub, or a
|
|
80
|
+
* container it cannot read) omits it.
|
|
50
81
|
*/
|
|
51
82
|
export interface ProcessHandle {
|
|
52
83
|
pid: number;
|
|
53
84
|
kill(): void;
|
|
54
85
|
logs?: string;
|
|
86
|
+
onExit?(listener: (exit: ProcessExitInfo) => void): void;
|
|
55
87
|
}
|
|
56
88
|
/**
|
|
57
89
|
* FetchResult is the answer to a health poll: the HTTP status and whether it
|
|
@@ -71,6 +103,15 @@ export interface FetchResult {
|
|
|
71
103
|
*/
|
|
72
104
|
export interface LifecycleHost {
|
|
73
105
|
run(command: string): Promise<CommandOutcome>;
|
|
106
|
+
/**
|
|
107
|
+
* Optional: run a command line and stream each stdout/stderr chunk to
|
|
108
|
+
* onOutput while it runs, so the Get step can append build output to the
|
|
109
|
+
* card's Logs section as it lands. A host that cannot stream omits it,
|
|
110
|
+
* and the caller falls back to run. No overall timeout: a full CUDA
|
|
111
|
+
* build legitimately runs past any fixed cap, and the card prices a
|
|
112
|
+
* stalled step with its own output-idle watchdog.
|
|
113
|
+
*/
|
|
114
|
+
runStream?(command: string, onOutput: (chunk: string) => void): Promise<CommandOutcome>;
|
|
74
115
|
spawn(argv: readonly string[], env: Record<string, string>, cwd?: string): ProcessHandle;
|
|
75
116
|
fetch(url: string): Promise<FetchResult>;
|
|
76
117
|
debug?: DebugLogger;
|
|
@@ -84,26 +125,75 @@ export interface HealthCheckOptions {
|
|
|
84
125
|
pollMs?: number;
|
|
85
126
|
maxAttempts?: number;
|
|
86
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* LaunchStep is the phase of a launch the card's Launch control prices: the
|
|
130
|
+
* system-dependency install (prereqs), the model and git checkout download
|
|
131
|
+
* (download), the source build or image pull (build), and the health poll that
|
|
132
|
+
* waits for the engine to come ready (launch). The service and the adapters
|
|
133
|
+
* report the step as each phase begins, so the card's button reads the phase
|
|
134
|
+
* that is actually running instead of a single "Launching..." for the whole
|
|
135
|
+
* rebuild. The card times out only the launch step; the rebuild steps (prereqs,
|
|
136
|
+
* download, build) run as long as they need to.
|
|
137
|
+
*/
|
|
138
|
+
export type LaunchStep = 'prereqs' | 'download' | 'build' | 'launch';
|
|
139
|
+
/**
|
|
140
|
+
* LaunchProgress is the callback the launch flow calls as each phase begins.
|
|
141
|
+
* The route threads it from the streamed launch response through the service
|
|
142
|
+
* and the adapter's deploy step; a launch with no progress sink omits it.
|
|
143
|
+
*/
|
|
144
|
+
export type LaunchProgress = (step: LaunchStep) => void;
|
|
145
|
+
/**
|
|
146
|
+
* EngineLaunchState is the phase of an engine start the health poll reports:
|
|
147
|
+
* downloading (the engine is fetching its engine or model files, the health
|
|
148
|
+
* endpoint is not up yet), starting (the files are in place and the engine is
|
|
149
|
+
* coming up), ready (the health endpoint reports 200), and failed (the start
|
|
150
|
+
* did not reach readiness). An engine that downloads before it can serve (the
|
|
151
|
+
* Strata Terminal) spends a long time in downloading, so the poll reports the
|
|
152
|
+
* phase instead of timing out and reading the start as broken.
|
|
153
|
+
*/
|
|
154
|
+
export type EngineLaunchState = 'downloading' | 'starting' | 'ready' | 'failed';
|
|
87
155
|
/**
|
|
88
156
|
* HealthResult is the answer to a /health poll: whether the engine is up, the
|
|
89
|
-
* HTTP status,
|
|
157
|
+
* HTTP status, a detail string for the UI, and the start phase the poll
|
|
158
|
+
* observed (absent for an engine whose start has no download phase).
|
|
90
159
|
*/
|
|
91
160
|
export interface HealthResult {
|
|
92
161
|
healthy: boolean;
|
|
93
162
|
status?: number;
|
|
94
163
|
detail?: string;
|
|
164
|
+
state?: EngineLaunchState;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* DeployOptions tunes a deploy run: `allowRunDeps` is the Play/Run trust gate
|
|
168
|
+
* (the card's "Allow one-click install (sudo)" checkbox). A local deploy that
|
|
169
|
+
* rebuilds the engine and leaves its binary out of the path links it into
|
|
170
|
+
* /usr/local/bin; the gate decides whether that sudo link runs (on) or is
|
|
171
|
+
* written to the card's Logs section for the user to run (off). `autoRebuild`
|
|
172
|
+
* is the card's "Auto Rebuild" checkbox: when false, the git sync (fetch,
|
|
173
|
+
* rebase, and the conditional rebuild) is skipped and the checkout launches
|
|
174
|
+
* as-is. Absent reads as true (the rebuild runs).
|
|
175
|
+
*/
|
|
176
|
+
export interface DeployOptions {
|
|
177
|
+
allowRunDeps?: boolean;
|
|
178
|
+
autoRebuild?: boolean;
|
|
95
179
|
}
|
|
96
180
|
/**
|
|
97
181
|
* DeployResult reports whether a build-or-pull succeeded, with a detail for the
|
|
98
182
|
* UI. `handle` is the spawned engine process when the deploy step started one
|
|
99
183
|
* locally: the service reads its accumulated `logs` after the health poll, so
|
|
100
184
|
* the launch result carries the engine's output for the card's Logs section and
|
|
101
|
-
* the log file
|
|
185
|
+
* the log file, and attaches the handle's `onExit` listener to learn of a crash
|
|
186
|
+
* or a pkill. A deploy that starts no process (a compose up) omits it. `logs`
|
|
187
|
+
* is the deploy step's own captured output (the rebuild decision, the build
|
|
188
|
+
* command, and its output) the service prepends to the engine's output, so the
|
|
189
|
+
* card's Logs section shows the build a launch ran. A deploy that runs no
|
|
190
|
+
* rebuild (a docker pull, a compose up) omits it.
|
|
102
191
|
*/
|
|
103
192
|
export interface DeployResult {
|
|
104
193
|
ok: boolean;
|
|
105
194
|
detail?: string;
|
|
106
195
|
handle?: ProcessHandle;
|
|
196
|
+
logs?: string;
|
|
107
197
|
}
|
|
108
198
|
/**
|
|
109
199
|
* EngineAdapter is the abstract base one subclass implements per engine. It
|
|
@@ -119,11 +209,12 @@ export declare abstract class EngineAdapter {
|
|
|
119
209
|
abstract readonly supports: {
|
|
120
210
|
docker: boolean;
|
|
121
211
|
local: boolean;
|
|
212
|
+
binary?: boolean;
|
|
122
213
|
};
|
|
123
214
|
abstract parameters(): readonly ParameterSpec[];
|
|
124
215
|
abstract renderLaunch(config: Config, hw: HardwareProfile): LaunchPlan;
|
|
125
216
|
abstract healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
|
|
126
|
-
abstract deploy(plan: LaunchPlan, platform?: EnginePlatformConfig): Promise<DeployResult>;
|
|
217
|
+
abstract deploy(plan: LaunchPlan, platform?: EnginePlatformConfig, onProgress?: LaunchProgress, options?: DeployOptions): Promise<DeployResult>;
|
|
127
218
|
abstract stop(plan: LaunchPlan): Promise<void>;
|
|
128
219
|
/**
|
|
129
220
|
* Optional: the host deps this engine's deploy step needs for a build mode,
|
|
@@ -131,7 +222,7 @@ export declare abstract class EngineAdapter {
|
|
|
131
222
|
* registered adapter first and falls back to the provider-registered plan
|
|
132
223
|
* for the engine id when the adapter declares none.
|
|
133
224
|
*/
|
|
134
|
-
systemDeps?(buildMode:
|
|
225
|
+
systemDeps?(buildMode: BuildMode, hw: HardwareProfile): readonly SystemDep[];
|
|
135
226
|
/**
|
|
136
227
|
* Optional: the model the engine serves under a config: the id the engine
|
|
137
228
|
* advertises on its OpenAI endpoint and the display name the registrar
|
|
@@ -143,6 +234,28 @@ export declare abstract class EngineAdapter {
|
|
|
143
234
|
id: string;
|
|
144
235
|
name: string;
|
|
145
236
|
} | undefined;
|
|
237
|
+
/**
|
|
238
|
+
* Optional: the model the running engine actually serves, read live from the
|
|
239
|
+
* engine (a terminal query against its model endpoint) rather than derived
|
|
240
|
+
* from the config. An engine that sizes and picks the model itself publishes
|
|
241
|
+
* the served id this returns instead of the config-derived modelRef; it
|
|
242
|
+
* returns undefined when the engine is not up, the answer cannot be read, or
|
|
243
|
+
* the config names a model, and the route falls back to modelRef. The
|
|
244
|
+
* register, save-sync, unregister, and summary paths await it, so it must
|
|
245
|
+
* never reject.
|
|
246
|
+
*/
|
|
247
|
+
discoverModel?(config: Config): Promise<{
|
|
248
|
+
id: string;
|
|
249
|
+
name: string;
|
|
250
|
+
} | undefined>;
|
|
251
|
+
/**
|
|
252
|
+
* Optional: the request modalities the engine serves under a config, the
|
|
253
|
+
* input types the DSH model row carries. An engine whose vision control is
|
|
254
|
+
* not the plain boolean flag (Strata's on|off|gpu|cpu enum, on by default)
|
|
255
|
+
* declares this so the Image input follows the engine's own vocabulary; an
|
|
256
|
+
* engine that declares none keeps the register step's boolean rule.
|
|
257
|
+
*/
|
|
258
|
+
modelInput?(config: Config): string[] | undefined;
|
|
146
259
|
/**
|
|
147
260
|
* Optional: the launch signature the engine's toArgv/toEnv produce for a
|
|
148
261
|
* config: the binary (or docker image) it runs under, the port it binds,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EngineAdapter } from './adapter.ts';
|
|
1
|
+
import type { BuildMode, EngineAdapter } from './adapter.ts';
|
|
2
2
|
import type { HardwareProfile } from './hardware.ts';
|
|
3
3
|
/**
|
|
4
4
|
* DepStatus is the lifecycle state of one host dependency: satisfied, missing,
|
|
@@ -60,6 +60,7 @@ export interface SystemDep {
|
|
|
60
60
|
export interface EngineDepPlan {
|
|
61
61
|
docker: readonly SystemDep[];
|
|
62
62
|
local: readonly SystemDep[];
|
|
63
|
+
binary?: readonly SystemDep[];
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* DepCheck is the per-dep answer from checkDeps: the dep and its current
|
|
@@ -103,7 +104,7 @@ export interface InstallResult {
|
|
|
103
104
|
* service implements this interface over the pure functions below.
|
|
104
105
|
*/
|
|
105
106
|
export interface SystemDepProvisioner {
|
|
106
|
-
planDeps(engine: EngineAdapter, buildMode:
|
|
107
|
+
planDeps(engine: EngineAdapter, buildMode: BuildMode, hw: HardwareProfile): readonly SystemDep[];
|
|
107
108
|
checkDeps(deps: readonly SystemDep[], hw: HardwareProfile): Promise<DepCheck[]>;
|
|
108
109
|
renderInstallString(deps: readonly SystemDep[], hw: HardwareProfile): string;
|
|
109
110
|
runInstall(deps: readonly SystemDep[], hw: HardwareProfile, runCommand: CommandRunner): Promise<InstallResult>;
|
|
@@ -122,7 +123,7 @@ export declare function detectPackageManager(probes: PackageManagerProbes): Pack
|
|
|
122
123
|
* declares none (the Phase 5 adapters will) plans an empty list, and the
|
|
123
124
|
* service falls back to the provider-registered plan for the engine id.
|
|
124
125
|
*/
|
|
125
|
-
export declare function planDeps(engine: EngineAdapter, buildMode:
|
|
126
|
+
export declare function planDeps(engine: EngineAdapter, buildMode: BuildMode, hw: HardwareProfile): readonly SystemDep[];
|
|
126
127
|
/**
|
|
127
128
|
* checkDeps probes every dep and reports its status. A dep without a detect
|
|
128
129
|
* probe reads as missing, not satisfied: an unknown state degrades to the
|
|
@@ -13,13 +13,14 @@ export { DEFAULT_OS_RESERVE_MIB, estimateVram, KV_PAGE_TOKENS, pageRoundUp, TIGH
|
|
|
13
13
|
export type { EstimateContext, EstimateOptions, SpeculationTerms, VramBreakdown, VramContribution, VramEstimate, VramModel, VramVerdict, } from './estimator.ts';
|
|
14
14
|
export { GPU_USAGE_BUSY_THRESHOLD, matchLaunchSignature, parseNvidiaSmiGpuUsage, resolveOsReserve, } from './reserve.ts';
|
|
15
15
|
export { commandMatchesArgv, launchRecordFromPlan, reLinkRecord, } from './launch-record.ts';
|
|
16
|
+
export { formatLaunchCommand } from './launch-command.ts';
|
|
16
17
|
export type { ProviderLaunchRecord, ReLinkInput, ReLinkOutcome, } from './launch-record.ts';
|
|
17
18
|
export type { EngineLaunchSignature, GpuUsageProbe, ProcessLine, ReserveResolution, ReserveSource, } from './reserve.ts';
|
|
18
19
|
export { computeProviderStatuses, isGpuBusy, } from './status.ts';
|
|
19
20
|
export type { ProviderRef, ProviderStatus, ProviderStatusInput, RunningEngineRef, } from './status.ts';
|
|
20
21
|
export { DEFAULT_LOG_PATH_TEMPLATE, LOG_FILE_NAME_TEMPLATE, LOG_TEMPLATE_ENGINE, LOG_TEMPLATE_HOME, LOG_TEMPLATE_MODEL, LOG_TEMPLATE_TIMESTAMP, formatLogTimestamp, resolveLogPath, slugifyModelName, } from './logs.ts';
|
|
21
22
|
export { EngineAdapter } from './adapter.ts';
|
|
22
|
-
export type { DeployResult, EnginePlatformConfig, FetchResult, HealthCheckOptions, HealthResult, LaunchPlan, LifecycleHost, ProcessHandle, } from './adapter.ts';
|
|
23
|
+
export type { BuildMode, DeployOptions, DeployResult, EngineLaunchState, EnginePlatformConfig, FetchResult, HealthCheckOptions, HealthResult, LaunchPlan, LaunchProgress, LaunchStep, LifecycleHost, ProcessExitInfo, ProcessHandle, } from './adapter.ts';
|
|
23
24
|
export { NOOP_DEBUG_LOGGER, createCommandDebugLogger, isHarnessLogDebug, } from './debug.ts';
|
|
24
25
|
export type { CreateCommandDebugLoggerArgs, DebugLogger, } from './debug.ts';
|
|
25
26
|
export { constraintId, evaluateGuidelines, modelGuidelines } from './guideline.ts';
|
|
@@ -9,6 +9,7 @@ export { detectHardware, parseNvidiaSmiGpu, } from "./hardware.js";
|
|
|
9
9
|
export { DEFAULT_OS_RESERVE_MIB, estimateVram, KV_PAGE_TOKENS, pageRoundUp, TIGHT_HEADROOM_BYTES, } from "./estimator.js";
|
|
10
10
|
export { GPU_USAGE_BUSY_THRESHOLD, matchLaunchSignature, parseNvidiaSmiGpuUsage, resolveOsReserve, } from "./reserve.js";
|
|
11
11
|
export { commandMatchesArgv, launchRecordFromPlan, reLinkRecord, } from "./launch-record.js";
|
|
12
|
+
export { formatLaunchCommand } from "./launch-command.js";
|
|
12
13
|
export { computeProviderStatuses, isGpuBusy, } from "./status.js";
|
|
13
14
|
export { DEFAULT_LOG_PATH_TEMPLATE, LOG_FILE_NAME_TEMPLATE, LOG_TEMPLATE_ENGINE, LOG_TEMPLATE_HOME, LOG_TEMPLATE_MODEL, LOG_TEMPLATE_TIMESTAMP, formatLogTimestamp, resolveLogPath, slugifyModelName, } from "./logs.js";
|
|
14
15
|
export { EngineAdapter } from "./adapter.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LaunchPlan } from './adapter.ts';
|
|
2
|
+
/**
|
|
3
|
+
* formatLaunchCommand renders a launch plan as the shell command string the
|
|
4
|
+
* deploy step runs to start the engine: the quoted argv joined for a process
|
|
5
|
+
* or docker plan, or the `docker compose up` line for a compose plan. The
|
|
6
|
+
* card's Logs section shows the line above the engine's own output, so a
|
|
7
|
+
* user can read and copy the exact binary and arguments a launch started
|
|
8
|
+
* with. The Hyper-Qwen deploy runs this same string, so the printed line and
|
|
9
|
+
* the host command cannot drift. Returns undefined when the plan names no
|
|
10
|
+
* command (a non-compose plan with no argv).
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatLaunchCommand(plan: LaunchPlan): string | undefined;
|
|
13
|
+
//# sourceMappingURL=launch-command.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* formatLaunchCommand renders a launch plan as the shell command string the
|
|
3
|
+
* deploy step runs to start the engine: the quoted argv joined for a process
|
|
4
|
+
* or docker plan, or the `docker compose up` line for a compose plan. The
|
|
5
|
+
* card's Logs section shows the line above the engine's own output, so a
|
|
6
|
+
* user can read and copy the exact binary and arguments a launch started
|
|
7
|
+
* with. The Hyper-Qwen deploy runs this same string, so the printed line and
|
|
8
|
+
* the host command cannot drift. Returns undefined when the plan names no
|
|
9
|
+
* command (a non-compose plan with no argv).
|
|
10
|
+
*/
|
|
11
|
+
export function formatLaunchCommand(plan) {
|
|
12
|
+
if (plan.kind === 'compose') {
|
|
13
|
+
// The user's compose arguments (the card's docker-tag field) override the
|
|
14
|
+
// default profile: the flags the up step runs before the required `up -d`.
|
|
15
|
+
// An empty field reads as "use the default profile", so the up step falls
|
|
16
|
+
// back to the engine's own default.
|
|
17
|
+
const composeArgs = plan.composeArgs?.split(/\s+/).filter((token) => token !== '');
|
|
18
|
+
if (composeArgs !== undefined && composeArgs.length > 0) {
|
|
19
|
+
return [
|
|
20
|
+
'docker',
|
|
21
|
+
'compose',
|
|
22
|
+
'-f',
|
|
23
|
+
plan.composeFile ?? 'docker-compose.yml',
|
|
24
|
+
...composeArgs,
|
|
25
|
+
'up',
|
|
26
|
+
'-d',
|
|
27
|
+
]
|
|
28
|
+
.map(quoteArg)
|
|
29
|
+
.join(' ');
|
|
30
|
+
}
|
|
31
|
+
// The compose defaults match the adapter's renderLaunch fallbacks, so a
|
|
32
|
+
// plan built from a bare config still spells a runnable command.
|
|
33
|
+
return [
|
|
34
|
+
'docker',
|
|
35
|
+
'compose',
|
|
36
|
+
'-f',
|
|
37
|
+
plan.composeFile ?? 'docker-compose.yml',
|
|
38
|
+
'--profile',
|
|
39
|
+
plan.profile ?? 'single',
|
|
40
|
+
'up',
|
|
41
|
+
'--pull',
|
|
42
|
+
'always',
|
|
43
|
+
'-d',
|
|
44
|
+
]
|
|
45
|
+
.map(quoteArg)
|
|
46
|
+
.join(' ');
|
|
47
|
+
}
|
|
48
|
+
const argv = plan.argv;
|
|
49
|
+
if (argv === undefined || argv.length === 0)
|
|
50
|
+
return undefined;
|
|
51
|
+
return argv.map(quoteArg).join(' ');
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* quoteArg renders one argv token for display: a token made only of shell-
|
|
55
|
+
* safe characters rides bare, anything else lands in single quotes with
|
|
56
|
+
* embedded quotes escaped, so the printed line pastes back into a shell
|
|
57
|
+
* unchanged.
|
|
58
|
+
*/
|
|
59
|
+
function quoteArg(token) {
|
|
60
|
+
if (token !== '' && /^[A-Za-z0-9@%+=:,./_-]+$/.test(token))
|
|
61
|
+
return token;
|
|
62
|
+
return `'${token.replaceAll("'", "'\\''")}'`;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=launch-command.js.map
|
|
@@ -67,7 +67,8 @@ export interface ModelDirectoryEntry {
|
|
|
67
67
|
/**
|
|
68
68
|
* modelEntriesForEngine filters a model directory listing down to the model
|
|
69
69
|
* entries the engine's Model dropdown offers: NInfer takes `.ninfer`
|
|
70
|
-
* artifacts,
|
|
70
|
+
* artifacts, Infernix takes `.ninfer` artifacts and its own `.infernix`
|
|
71
|
+
* files, llama.cpp takes `.gguf` files, and Hyper-Qwen takes the repo
|
|
71
72
|
* directories that hold a `.safetensors` weight file. Every other engine
|
|
72
73
|
* (Strata) offers nothing, matching its empty default list. The result is
|
|
73
74
|
* sorted, so the dropdown order is stable across summary fetches.
|
|
@@ -61,7 +61,8 @@ export function hfChatTemplateCommand(repo, directory) {
|
|
|
61
61
|
/**
|
|
62
62
|
* modelEntriesForEngine filters a model directory listing down to the model
|
|
63
63
|
* entries the engine's Model dropdown offers: NInfer takes `.ninfer`
|
|
64
|
-
* artifacts,
|
|
64
|
+
* artifacts, Infernix takes `.ninfer` artifacts and its own `.infernix`
|
|
65
|
+
* files, llama.cpp takes `.gguf` files, and Hyper-Qwen takes the repo
|
|
65
66
|
* directories that hold a `.safetensors` weight file. Every other engine
|
|
66
67
|
* (Strata) offers nothing, matching its empty default list. The result is
|
|
67
68
|
* sorted, so the dropdown order is stable across summary fetches.
|
|
@@ -74,6 +75,14 @@ export function modelEntriesForEngine(entries, engineId) {
|
|
|
74
75
|
.filter((entry) => !entry.isDirectory && entry.name.endsWith('.ninfer'))
|
|
75
76
|
.map((entry) => entry.name);
|
|
76
77
|
break;
|
|
78
|
+
case 'infernix':
|
|
79
|
+
// Infernix loads NInfer artifacts unchanged plus its own `.infernix`
|
|
80
|
+
// files, so the dropdown offers both extensions.
|
|
81
|
+
names = entries
|
|
82
|
+
.filter((entry) => !entry.isDirectory &&
|
|
83
|
+
(entry.name.endsWith('.ninfer') || entry.name.endsWith('.infernix')))
|
|
84
|
+
.map((entry) => entry.name);
|
|
85
|
+
break;
|
|
77
86
|
case 'llamacpp':
|
|
78
87
|
names = entries
|
|
79
88
|
.filter((entry) => !entry.isDirectory && entry.name.endsWith('.gguf'))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LaunchPlan } from './adapter.ts';
|
|
1
|
+
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
|
|
@@ -83,11 +83,11 @@ export interface DshModelRegistrar {
|
|
|
83
83
|
export declare function modelSlug(modelId: string): string;
|
|
84
84
|
/**
|
|
85
85
|
* providerIdFor derives the provider id the registrar writes for an engine
|
|
86
|
-
* and model: the engine id, the build mode (local or
|
|
87
|
-
* slug, so a profile can carry the same engine in
|
|
88
|
-
* several models per engine without a collision.
|
|
86
|
+
* and model: the engine id, the build mode (local, docker, or binary), and the
|
|
87
|
+
* model slug, so a profile can carry the same engine in several build modes
|
|
88
|
+
* and several models per engine without a collision.
|
|
89
89
|
*/
|
|
90
|
-
export declare function providerIdFor(engineId: string, modelId: string, buildMode:
|
|
90
|
+
export declare function providerIdFor(engineId: string, modelId: string, buildMode: BuildMode): string;
|
|
91
91
|
/**
|
|
92
92
|
* apiKeyEnvFor derives the env-var name a local provider reads its optional
|
|
93
93
|
* API key from: the engine id, uppercased and non-alphanumerics mapped to
|
|
@@ -27,9 +27,9 @@ export function modelSlug(modelId) {
|
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* providerIdFor derives the provider id the registrar writes for an engine
|
|
30
|
-
* and model: the engine id, the build mode (local or
|
|
31
|
-
* slug, so a profile can carry the same engine in
|
|
32
|
-
* several models per engine without a collision.
|
|
30
|
+
* and model: the engine id, the build mode (local, docker, or binary), and the
|
|
31
|
+
* model slug, so a profile can carry the same engine in several build modes
|
|
32
|
+
* and several models per engine without a collision.
|
|
33
33
|
*/
|
|
34
34
|
export function providerIdFor(engineId, modelId, buildMode) {
|
|
35
35
|
return `${engineId}-${buildMode}-${modelSlug(modelId)}`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { GpuUsageProbe } from './reserve.ts';
|
|
2
|
+
import type { Config } from './config.ts';
|
|
2
3
|
/**
|
|
3
4
|
* ProviderStatus is the running-state the plugin card paints each saved
|
|
4
5
|
* provider's status dot: green while the engine is confirmed serving the
|
|
@@ -10,12 +11,19 @@ export type ProviderStatus = 'running' | 'stopped' | 'unsure';
|
|
|
10
11
|
* ProviderRef is the identity side of one saved provider config: the stable
|
|
11
12
|
* id the card renders and the engine and model it serves. The model is
|
|
12
13
|
* optional because a config that names no model cannot be confirmed against
|
|
13
|
-
* a running engine, and reads as unsure rather than a guess.
|
|
14
|
+
* a running engine, and reads as unsure rather than a guess. The config is
|
|
15
|
+
* optional and lets the detector price the provider's own launch signature
|
|
16
|
+
* (the engine binary the build mode runs, the port it binds) rather than the
|
|
17
|
+
* adapter's default-port signature; the port is the resolved bind port the
|
|
18
|
+
* detector read from that signature, and the resolver ties a running engine
|
|
19
|
+
* to the provider only when the ports agree.
|
|
14
20
|
*/
|
|
15
21
|
export interface ProviderRef {
|
|
16
22
|
id: string;
|
|
17
23
|
engine: string;
|
|
18
24
|
model?: string;
|
|
25
|
+
config?: Config;
|
|
26
|
+
port?: number;
|
|
19
27
|
}
|
|
20
28
|
/**
|
|
21
29
|
* RunningEngineRef is one engine the detector confirmed live: the engine id,
|
|
@@ -28,7 +28,12 @@ export function isGpuBusy(usage) {
|
|
|
28
28
|
export function computeProviderStatuses(input) {
|
|
29
29
|
const statuses = {};
|
|
30
30
|
for (const provider of input.providers) {
|
|
31
|
-
|
|
31
|
+
// A provider that names a port only counts an engine running on that
|
|
32
|
+
// port: two configs of one engine on different ports are distinct
|
|
33
|
+
// engines, and a match on the other port must not confirm (or deny) this
|
|
34
|
+
// config's model. An unnamed port keeps the engine-wide match.
|
|
35
|
+
const matches = input.running.filter((ref) => ref.engineId === provider.engine &&
|
|
36
|
+
(provider.port === undefined || ref.port === undefined || ref.port === provider.port));
|
|
32
37
|
if (matches.length > 0) {
|
|
33
38
|
// The engine is running. The question is which model it serves: the
|
|
34
39
|
// detector's identified model, if it tied one, else unknown.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-local-infer-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Pure, framework-free domain model for the dsh local-inference plugin: ParameterSpec, HardwareProfile, EngineAdapter, VramEstimator, GuidelineEngine, DefaultsResolver, DshModelRegistrar, and SystemDepProvisioner primitives shared by every engine and model",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|