dsh-plugin-local-infer 0.1.2 → 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.
Files changed (100) hide show
  1. package/README.md +10 -2
  2. package/docs/zh/README.md +10 -2
  3. package/dsh/client.js +669 -191
  4. package/package.json +6 -1
  5. package/packages/core/lib/adapter.d.ts +44 -2
  6. package/packages/core/lib/deps.d.ts +4 -3
  7. package/packages/core/lib/index.d.ts +1 -1
  8. package/packages/core/lib/registrar.d.ts +5 -5
  9. package/packages/core/lib/registrar.js +3 -3
  10. package/packages/core/package.json +1 -1
  11. package/packages/providers/lib/acquire.d.ts +5 -3
  12. package/packages/providers/lib/acquire.js +30 -9
  13. package/packages/providers/lib/adapters.d.ts +19 -209
  14. package/packages/providers/lib/adapters.js +13 -886
  15. package/packages/providers/lib/deps.d.ts +24 -2
  16. package/packages/providers/lib/deps.js +23 -4
  17. package/packages/providers/lib/engines/hyperqwenAdapter.d.ts +38 -0
  18. package/packages/providers/lib/engines/hyperqwenAdapter.js +105 -0
  19. package/packages/providers/lib/{infernix.js → engines/infernix.js} +1 -1
  20. package/packages/providers/lib/engines/infernixAdapter.d.ts +53 -0
  21. package/packages/providers/lib/engines/infernixAdapter.js +202 -0
  22. package/packages/providers/lib/engines/llamacppAdapter.d.ts +51 -0
  23. package/packages/providers/lib/engines/llamacppAdapter.js +232 -0
  24. package/packages/providers/lib/{ninfer.js → engines/ninfer.js} +1 -1
  25. package/packages/providers/lib/engines/ninferAdapter.d.ts +82 -0
  26. package/packages/providers/lib/engines/ninferAdapter.js +324 -0
  27. package/packages/providers/lib/engines/strata.d.ts +53 -0
  28. package/packages/providers/lib/engines/strata.js +197 -0
  29. package/packages/providers/lib/engines/strataAdapter.d.ts +98 -0
  30. package/packages/providers/lib/engines/strataAdapter.js +427 -0
  31. package/packages/providers/lib/engines.d.ts +5 -4
  32. package/packages/providers/lib/engines.js +10 -10
  33. package/packages/providers/lib/guidelines.js +1 -1
  34. package/packages/providers/lib/index.d.ts +14 -9
  35. package/packages/providers/lib/index.js +17 -7
  36. package/packages/providers/lib/model-defaults.d.ts +5 -4
  37. package/packages/providers/lib/model-defaults.js +22 -4
  38. package/packages/providers/lib/platform.js +7 -1
  39. package/packages/providers/package.json +1 -1
  40. package/packages/service/lib/index.d.ts +13 -4
  41. package/packages/service/lib/index.js +79 -5
  42. package/packages/service/lib/types.d.ts +5 -4
  43. package/packages/service/package.json +1 -1
  44. package/packages/tool/package.json +1 -1
  45. package/packages/ui/lib/config.d.ts +79 -0
  46. package/packages/ui/lib/config.js +235 -0
  47. package/packages/ui/lib/deps.d.ts +3 -3
  48. package/packages/ui/lib/ops/engine.d.ts +108 -0
  49. package/packages/ui/lib/ops/engine.js +493 -0
  50. package/packages/ui/lib/ops/hf.d.ts +27 -0
  51. package/packages/ui/lib/ops/hf.js +60 -0
  52. package/packages/ui/lib/ops/logs.d.ts +23 -0
  53. package/packages/ui/lib/ops/logs.js +58 -0
  54. package/packages/ui/lib/ops/model.d.ts +79 -0
  55. package/packages/ui/lib/ops/model.js +130 -0
  56. package/packages/ui/lib/request.d.ts +106 -0
  57. package/packages/ui/lib/request.js +80 -0
  58. package/packages/ui/lib/route.d.ts +88 -420
  59. package/packages/ui/lib/route.js +111 -1843
  60. package/packages/ui/lib/routes/chat-template.d.ts +14 -0
  61. package/packages/ui/lib/routes/chat-template.js +37 -0
  62. package/packages/ui/lib/routes/deps.d.ts +16 -0
  63. package/packages/ui/lib/routes/deps.js +27 -0
  64. package/packages/ui/lib/routes/download.d.ts +16 -0
  65. package/packages/ui/lib/routes/download.js +48 -0
  66. package/packages/ui/lib/routes/get.d.ts +18 -0
  67. package/packages/ui/lib/routes/get.js +57 -0
  68. package/packages/ui/lib/routes/install.d.ts +16 -0
  69. package/packages/ui/lib/routes/install.js +36 -0
  70. package/packages/ui/lib/routes/launch.d.ts +18 -0
  71. package/packages/ui/lib/routes/launch.js +50 -0
  72. package/packages/ui/lib/routes/provider-delete.d.ts +15 -0
  73. package/packages/ui/lib/routes/provider-delete.js +37 -0
  74. package/packages/ui/lib/routes/register.d.ts +16 -0
  75. package/packages/ui/lib/routes/register.js +28 -0
  76. package/packages/ui/lib/routes/save.d.ts +18 -0
  77. package/packages/ui/lib/routes/save.js +139 -0
  78. package/packages/ui/lib/routes/stop.d.ts +16 -0
  79. package/packages/ui/lib/routes/stop.js +29 -0
  80. package/packages/ui/lib/routes/summary.d.ts +15 -0
  81. package/packages/ui/lib/routes/summary.js +26 -0
  82. package/packages/ui/lib/routes/unregister.d.ts +14 -0
  83. package/packages/ui/lib/routes/unregister.js +26 -0
  84. package/packages/ui/lib/viewmodels/deps.d.ts +31 -0
  85. package/packages/ui/lib/viewmodels/deps.js +89 -0
  86. package/packages/ui/lib/viewmodels/depsHelpers.d.ts +28 -0
  87. package/packages/ui/lib/viewmodels/depsHelpers.js +33 -0
  88. package/packages/ui/lib/viewmodels/summary.d.ts +140 -0
  89. package/packages/ui/lib/viewmodels/summary.js +225 -0
  90. package/packages/ui/lib/viewmodels/summaryHelpers.d.ts +30 -0
  91. package/packages/ui/lib/viewmodels/summaryHelpers.js +42 -0
  92. package/packages/ui/package.json +1 -1
  93. package/packages/providers/lib/strata.d.ts +0 -15
  94. package/packages/providers/lib/strata.js +0 -14
  95. /package/packages/providers/lib/{hyperqwen.d.ts → engines/hyperqwen.d.ts} +0 -0
  96. /package/packages/providers/lib/{hyperqwen.js → engines/hyperqwen.js} +0 -0
  97. /package/packages/providers/lib/{infernix.d.ts → engines/infernix.d.ts} +0 -0
  98. /package/packages/providers/lib/{llamacpp.d.ts → engines/llamacpp.d.ts} +0 -0
  99. /package/packages/providers/lib/{llamacpp.js → engines/llamacpp.js} +0 -0
  100. /package/packages/providers/lib/{ninfer.d.ts → engines/ninfer.d.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-local-infer",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,6 +21,10 @@
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",
25
29
  "packageManager": "pnpm@12.11.2",
26
30
  "engines": {
@@ -99,6 +103,7 @@
99
103
  "@types/node": "^22.10.0",
100
104
  "@vitest/coverage-v8": "^5.0.4",
101
105
  "eslint": "^10.12.0",
106
+ "tsx": "^4.23.15",
102
107
  "typescript": "^5.9.0",
103
108
  "typescript-eslint": "^8.71.2",
104
109
  "vite-tsconfig-paths": "^5.1.4",
@@ -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
@@ -135,14 +142,26 @@ export type LaunchStep = 'prereqs' | 'download' | 'build' | 'launch';
135
142
  * and the adapter's deploy step; a launch with no progress sink omits it.
136
143
  */
137
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';
138
155
  /**
139
156
  * HealthResult is the answer to a /health poll: whether the engine is up, the
140
- * HTTP status, and a detail string for the UI.
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).
141
159
  */
142
160
  export interface HealthResult {
143
161
  healthy: boolean;
144
162
  status?: number;
145
163
  detail?: string;
164
+ state?: EngineLaunchState;
146
165
  }
147
166
  /**
148
167
  * DeployOptions tunes a deploy run: `allowRunDeps` is the Play/Run trust gate
@@ -190,6 +209,7 @@ export declare abstract class EngineAdapter {
190
209
  abstract readonly supports: {
191
210
  docker: boolean;
192
211
  local: boolean;
212
+ binary?: boolean;
193
213
  };
194
214
  abstract parameters(): readonly ParameterSpec[];
195
215
  abstract renderLaunch(config: Config, hw: HardwareProfile): LaunchPlan;
@@ -202,7 +222,7 @@ export declare abstract class EngineAdapter {
202
222
  * registered adapter first and falls back to the provider-registered plan
203
223
  * for the engine id when the adapter declares none.
204
224
  */
205
- systemDeps?(buildMode: 'docker' | 'local', hw: HardwareProfile): readonly SystemDep[];
225
+ systemDeps?(buildMode: BuildMode, hw: HardwareProfile): readonly SystemDep[];
206
226
  /**
207
227
  * Optional: the model the engine serves under a config: the id the engine
208
228
  * advertises on its OpenAI endpoint and the display name the registrar
@@ -214,6 +234,28 @@ export declare abstract class EngineAdapter {
214
234
  id: string;
215
235
  name: string;
216
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;
217
259
  /**
218
260
  * Optional: the launch signature the engine's toArgv/toEnv produce for a
219
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: 'docker' | 'local', hw: HardwareProfile): readonly SystemDep[];
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: 'docker' | 'local', hw: HardwareProfile): readonly SystemDep[];
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
@@ -20,7 +20,7 @@ export { computeProviderStatuses, isGpuBusy, } from './status.ts';
20
20
  export type { ProviderRef, ProviderStatus, ProviderStatusInput, RunningEngineRef, } from './status.ts';
21
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';
22
22
  export { EngineAdapter } from './adapter.ts';
23
- export type { DeployOptions, DeployResult, EnginePlatformConfig, FetchResult, HealthCheckOptions, HealthResult, LaunchPlan, LaunchProgress, LaunchStep, LifecycleHost, ProcessExitInfo, ProcessHandle, } from './adapter.ts';
23
+ export type { BuildMode, DeployOptions, DeployResult, EngineLaunchState, EnginePlatformConfig, FetchResult, HealthCheckOptions, HealthResult, LaunchPlan, LaunchProgress, LaunchStep, LifecycleHost, ProcessExitInfo, ProcessHandle, } from './adapter.ts';
24
24
  export { NOOP_DEBUG_LOGGER, createCommandDebugLogger, isHarnessLogDebug, } from './debug.ts';
25
25
  export type { CreateCommandDebugLoggerArgs, DebugLogger, } from './debug.ts';
26
26
  export { constraintId, evaluateGuidelines, modelGuidelines } from './guideline.ts';
@@ -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 docker), and the model
87
- * slug, so a profile can carry the same engine in both build modes and
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: 'local' | 'docker'): string;
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 docker), and the model
31
- * slug, so a profile can carry the same engine in both build modes and
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,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-local-infer-core",
3
- "version": "0.1.0",
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",
@@ -31,8 +31,8 @@ export declare const FORK_REMOTE = "dsh-fork";
31
31
  * through cmake (Infernix through its own preset); llama.cpp builds through
32
32
  * the same cmake shape as NInfer; Hyper-Qwen is the compose-driven vLLM
33
33
  * engine, so it carries no local build steps (the compose up pulls the
34
- * image); Strata is the placeholder engine, and its repo and pull step land
35
- * with the engine, the same way its docker image constant did.
34
+ * image); Strata builds through its own setup.sh (the README's
35
+ * Build-from-source route), which the source-build mode runs in the checkout.
36
36
  */
37
37
  export declare const ENGINE_SOURCES: Record<string, EngineSource>;
38
38
  /**
@@ -86,6 +86,8 @@ export interface SyncRebuildRequest {
86
86
  fork?: string;
87
87
  binary?: string;
88
88
  allowRunDeps?: boolean;
89
+ buildCommands?: string;
90
+ onBuildStart?: () => void;
89
91
  }
90
92
  /**
91
93
  * SyncRebuildResult reports the conditional rebuild: whether it passed,
@@ -121,5 +123,5 @@ export declare function syncAndRebuildEngine(host: LifecycleHost, request: SyncR
121
123
  * engines) passes through with a note; a failing step stops the build with
122
124
  * the step's detail.
123
125
  */
124
- export declare function buildEngineRepo(host: LifecycleHost, engineId: string, directory: string, log: AcquireLog): Promise<EngineStepResult>;
126
+ export declare function buildEngineRepo(host: LifecycleHost, engineId: string, directory: string, log: AcquireLog, buildCommands?: string): Promise<EngineStepResult>;
125
127
  //# sourceMappingURL=acquire.d.ts.map
@@ -18,8 +18,8 @@ export const FORK_REMOTE = 'dsh-fork';
18
18
  * through cmake (Infernix through its own preset); llama.cpp builds through
19
19
  * the same cmake shape as NInfer; Hyper-Qwen is the compose-driven vLLM
20
20
  * engine, so it carries no local build steps (the compose up pulls the
21
- * image); Strata is the placeholder engine, and its repo and pull step land
22
- * with the engine, the same way its docker image constant did.
21
+ * image); Strata builds through its own setup.sh (the README's
22
+ * Build-from-source route), which the source-build mode runs in the checkout.
23
23
  */
24
24
  export const ENGINE_SOURCES = {
25
25
  ninfer: {
@@ -47,9 +47,13 @@ export const ENGINE_SOURCES = {
47
47
  buildSteps: ['cd {dir} && cmake --preset release && cmake --build build -j'],
48
48
  },
49
49
  strata: {
50
- repo: 'https://github.com/strata/strata',
50
+ // The README's Build-from-source route: git clone the repo, then run the
51
+ // engine's own setup.sh. `--yes` takes the recommended answer to every
52
+ // question (no prompts) and `--no-start` builds and installs the engine
53
+ // without starting the server, which the adapter's launch step then does.
54
+ repo: 'https://github.com/Niko1221/Strata',
51
55
  branch: 'main',
52
- buildSteps: ['docker pull ghcr.io/strata/strata'],
56
+ buildSteps: ['cd {dir} && ./setup.sh --yes --no-start'],
53
57
  },
54
58
  };
55
59
  /**
@@ -264,8 +268,20 @@ export async function syncAndRebuildEngine(host, request, log) {
264
268
  }
265
269
  }
266
270
  if (rebuilt) {
267
- // Run the engine's build steps, capturing the command and its output.
268
- for (const step of source.buildSteps) {
271
+ // The user's local build command (the card's Build commands field)
272
+ // overrides the engine's default build steps: it runs in the checkout, so
273
+ // it is wrapped with a cd into the directory. Absent falls back to the
274
+ // engine's acquisition build steps.
275
+ const buildCommands = request.buildCommands !== undefined && request.buildCommands.trim() !== ''
276
+ ? request.buildCommands
277
+ : undefined;
278
+ const steps = buildCommands !== undefined
279
+ ? [`cd ${directory} && ${buildCommands}`]
280
+ : source.buildSteps;
281
+ // Report the build phase before the first step runs, so the card's button
282
+ // reads "Building..." while the build is in flight, not after it completes.
283
+ request.onBuildStart?.();
284
+ for (const step of steps) {
269
285
  const command = step.replaceAll('{dir}', directory);
270
286
  const outcome = await runLogged(host, command, emit);
271
287
  if (!outcome.ok) {
@@ -304,16 +320,21 @@ export async function syncAndRebuildEngine(host, request, log) {
304
320
  * engines) passes through with a note; a failing step stops the build with
305
321
  * the step's detail.
306
322
  */
307
- export async function buildEngineRepo(host, engineId, directory, log) {
323
+ export async function buildEngineRepo(host, engineId, directory, log, buildCommands) {
308
324
  const source = engineSource(engineId);
309
325
  if (source === undefined) {
310
326
  return { ok: false, detail: `no engine source is registered for "${engineId}"` };
311
327
  }
312
- if (source.buildSteps.length === 0) {
328
+ // The user's local build command (the card's Build commands field) overrides
329
+ // the engine's default build steps: it runs in the checkout, so it is wrapped
330
+ // with a cd into the directory. Absent falls back to the engine's steps.
331
+ const commands = buildCommands !== undefined && buildCommands.trim() !== '' ? buildCommands : undefined;
332
+ const steps = commands !== undefined ? [`cd ${directory} && ${commands}`] : source.buildSteps;
333
+ if (steps.length === 0) {
313
334
  log(`no local build steps for ${engineId}\n`);
314
335
  return { ok: true };
315
336
  }
316
- for (const step of source.buildSteps) {
337
+ for (const step of steps) {
317
338
  const command = step.replaceAll('{dir}', directory);
318
339
  const outcome = await runLogged(host, command, log);
319
340
  if (!outcome.ok) {
@@ -1,33 +1,13 @@
1
1
  /**
2
- * The concrete engine adapters: NInfer (docker and local) and Hyper-Qwen
3
- * (compose). Each composes the provider `ParameterSpec` data into a
4
- * `LaunchPlan` and drives its deploy, health-check, and stop steps through an
5
- * injectable `LifecycleHost`, so the tests stub the host and never run a real
6
- * build, docker, or network in CI. The node implementation
7
- * (`nodeLifecycleHost`) is what the service wires in on a live host.
2
+ * The shared engine-adapter helpers: the spec-to-argv and spec-to-env
3
+ * translators the concrete adapters (the `engines/*Adapter.ts` files) compose
4
+ * into a `LaunchPlan`, the card's Custom Arguments translators, the
5
+ * `LifecycleHost` the deploy, health-check, and stop steps drive, and the
6
+ * health poll. The node implementation (`nodeLifecycleHost`) is what the
7
+ * service wires in on a live host.
8
8
  * @module dsh-plugin-local-infer/providers/adapters
9
9
  */
10
- import { EngineAdapter } from '../../core/lib/index.js';
11
- import type { Config, DebugLogger, DeployOptions, DeployResult, EngineLaunchSignature, EnginePlatformConfig, HealthCheckOptions, HealthResult, HardwareProfile, LaunchPlan, LaunchProgress, LifecycleHost, ParameterSpec } from '../../core/lib/index.js';
12
- export { INFERNIX_MODEL_ARTIFACTS } from './infernix.ts';
13
- /**
14
- * NInferModelArtifact is the per-model deploy data: the `.ninfer` artifact
15
- * file, the Hugging Face repo the model download pulls it from, and the
16
- * `--model-id` alias the server advertises. The data is the surface; adding a
17
- * model is a data edit here, never an adapter rewire.
18
- */
19
- export interface NInferModelArtifact {
20
- file: string;
21
- repo: string;
22
- modelId: string;
23
- }
24
- /**
25
- * The NInfer model artifacts, keyed by the model registry id. The 27B entry
26
- * is the default the DEFAULT_MODELS list names; the 35B-A3B entries are the
27
- * Qwen3.8 measured artifact (`qwen3-35b`) and the Qwen3.6 default
28
- * (`qwen36-35b`).
29
- */
30
- export declare const NINFER_MODEL_ARTIFACTS: Record<string, NInferModelArtifact>;
10
+ import type { Config, DebugLogger, HealthCheckOptions, HealthResult, LaunchPlan, LifecycleHost, ParameterSpec, ProcessHandle } from '../../core/lib/index.js';
31
11
  /**
32
12
  * flagsFromSpecs turns a spec surface and a config into the CLI flag list: each
33
13
  * spec's `toArgv` runs over the config value (falling back to the spec
@@ -76,6 +56,14 @@ export declare function createNodeLifecycleHost(debug?: DebugLogger): LifecycleH
76
56
  * in debug mode.
77
57
  */
78
58
  export declare const nodeLifecycleHost: LifecycleHost;
59
+ /**
60
+ * trackChild stores a spawned handle in the adapter's children map and ties
61
+ * the entry's lifetime to the child's: when the child ends (a crash, a pkill,
62
+ * or the adapter's own stop kill) the entry is dropped, so a later stop never
63
+ * signals a pid a recycled process has taken over. A handle whose host cannot
64
+ * watch (onExit absent) stays tracked until stop removes it.
65
+ */
66
+ export declare function trackChild(children: Map<string, ProcessHandle>, key: string, handle: ProcessHandle): void;
79
67
  /**
80
68
  * pollHealth polls a plan's health URL until a 200 or the attempt cap, the
81
69
  * same loop the qwen-ninfer launcher runs. A poll interval of 0 skips the
@@ -83,187 +71,9 @@ export declare const nodeLifecycleHost: LifecycleHost;
83
71
  */
84
72
  export declare function pollHealth(host: LifecycleHost, plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
85
73
  /**
86
- * The NInfer docker image the adapter pulls and runs. The engineFork platform
87
- * config overrides the git source for a local build; the image stays the
88
- * upstream ghcr artifact.
89
- */
90
- export declare const NINFER_DOCKER_IMAGE = "ghcr.io/iamwavecut/ninfer-all";
91
- /**
92
- * NInferAdapter is the canonical both-capable engine. `renderLaunch` renders a
93
- * local `ninfer-serve` process or a `docker run` of the ghcr image from the
94
- * same spec surface; `deploy` builds the engine in the engine directory (or
95
- * pulls the image), downloads the model into the model directory, and starts
96
- * the engine; `healthCheck` polls the health URL; `stop` signals the tracked
97
- * process and stops the named container.
98
- */
99
- export declare class NInferAdapter extends EngineAdapter {
100
- readonly id = "ninfer";
101
- readonly supports: {
102
- docker: boolean;
103
- local: boolean;
104
- };
105
- private readonly host;
106
- private readonly children;
107
- constructor(host?: LifecycleHost);
108
- parameters(): readonly ParameterSpec[];
109
- modelRef(config: Config): {
110
- id: string;
111
- name: string;
112
- };
113
- launchSignature(config?: Config): EngineLaunchSignature;
114
- renderLaunch(config: Config, _hw: HardwareProfile): LaunchPlan;
115
- deploy(plan: LaunchPlan, platform?: EnginePlatformConfig, onProgress?: LaunchProgress, options?: DeployOptions): Promise<DeployResult>;
116
- healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
117
- stop(plan: LaunchPlan): Promise<void>;
118
- private buildMode;
119
- private port;
120
- private planKey;
121
- private downloadModel;
122
- /**
123
- * resolveChatTemplate rewrites a --chat-template flag that carries an HF repo
124
- * reference into the local file the engine reads. A value with a slash that
125
- * is not an absolute path (the combo control's known choices) is a repo the
126
- * deploy step downloads into the model directory; an already-local path is
127
- * left as-is. The download is best-effort: a template that is already on
128
- * disk is used without a re-fetch, and a missing hf CLI leaves the flag
129
- * untouched so the engine reports the missing template itself.
130
- */
131
- private resolveChatTemplate;
132
- }
133
- /**
134
- * HyperQwenAdapter is the docker-compose engine. `renderLaunch` renders a
135
- * compose plan (the compose file, the profile, and the `.env` the spec surface
136
- * maps to); `deploy` runs `docker compose up`; `healthCheck` polls the health
137
- * URL; `stop` runs `docker compose down`.
138
- */
139
- export declare class HyperQwenAdapter extends EngineAdapter {
140
- readonly id = "hyperqwen";
141
- readonly supports: {
142
- docker: boolean;
143
- local: boolean;
144
- };
145
- private readonly host;
146
- constructor(host?: LifecycleHost);
147
- parameters(): readonly ParameterSpec[];
148
- modelRef(_config: Config): {
149
- id: string;
150
- name: string;
151
- };
152
- launchSignature(config?: Config): EngineLaunchSignature;
153
- renderLaunch(config: Config, _hw: HardwareProfile): LaunchPlan;
154
- deploy(plan: LaunchPlan, platform?: EnginePlatformConfig, onProgress?: LaunchProgress, _options?: DeployOptions): Promise<DeployResult>;
155
- healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
156
- stop(plan: LaunchPlan): Promise<void>;
157
- private port;
158
- private profile;
159
- }
160
- /**
161
- * The llama.cpp docker image the adapter pulls and runs. The engineFork
162
- * platform config overrides the git source for a local build; the image stays
163
- * the upstream ggml artifact.
164
- */
165
- export declare const LLAMACPP_DOCKER_IMAGE = "ghcr.io/ggml-org/llama.cpp";
166
- /**
167
- * LlamaCppAdapter is the llama.cpp engine, both-capable like NInfer.
168
- * `renderLaunch` renders a local `llama-server` process or a `docker run` of the
169
- * ggml image from the same `LLAMACPP_PARAMETERS` surface; `deploy` builds the
170
- * engine in the engine directory (or pulls the image), downloads the GGUF model
171
- * into the model directory, and starts the engine; `healthCheck` polls the health
172
- * URL; `stop` signals the tracked process and stops the named container.
173
- */
174
- export declare class LlamaCppAdapter extends EngineAdapter {
175
- readonly id = "llamacpp";
176
- readonly supports: {
177
- docker: boolean;
178
- local: boolean;
179
- };
180
- private readonly host;
181
- private readonly children;
182
- constructor(host?: LifecycleHost);
183
- parameters(): readonly ParameterSpec[];
184
- modelRef(config: Config): {
185
- id: string;
186
- name: string;
187
- };
188
- launchSignature(config?: Config): EngineLaunchSignature;
189
- renderLaunch(config: Config, _hw: HardwareProfile): LaunchPlan;
190
- deploy(plan: LaunchPlan, platform?: EnginePlatformConfig, onProgress?: LaunchProgress, options?: DeployOptions): Promise<DeployResult>;
191
- healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
192
- stop(plan: LaunchPlan): Promise<void>;
193
- private buildMode;
194
- private port;
195
- private planKey;
196
- private downloadModel;
197
- }
198
- /**
199
- * The Strata docker image the adapter pulls and runs. Strata is the
200
- * placeholder engine: the image and the parameter data land when the engine
201
- * is available, and the adapter renders a bare docker plan until then.
202
- */
203
- export declare const STRATA_DOCKER_IMAGE = "ghcr.io/strata/strata";
204
- /**
205
- * StrataAdapter is the placeholder docker-only engine. `renderLaunch` renders
206
- * a `docker run` of the Strata image (no spec surface yet, so no flags);
207
- * `deploy` pulls the image and starts the container; `healthCheck` polls the
208
- * health URL; `stop` stops the named container. The parameter surface and the
209
- * per-model data land with the engine, as data edits, never an adapter rewire.
210
- */
211
- export declare class StrataAdapter extends EngineAdapter {
212
- readonly id = "strata";
213
- readonly supports: {
214
- docker: boolean;
215
- local: boolean;
216
- };
217
- private readonly host;
218
- private readonly children;
219
- constructor(host?: LifecycleHost);
220
- parameters(): readonly ParameterSpec[];
221
- modelRef(_config: Config): {
222
- id: string;
223
- name: string;
224
- };
225
- launchSignature(config?: Config): EngineLaunchSignature;
226
- renderLaunch(config: Config, _hw: HardwareProfile): LaunchPlan;
227
- deploy(plan: LaunchPlan, _platform?: EnginePlatformConfig, onProgress?: LaunchProgress, _options?: DeployOptions): Promise<DeployResult>;
228
- healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
229
- stop(plan: LaunchPlan): Promise<void>;
230
- private port;
231
- private planKey;
232
- }
233
- /**
234
- * InfernixAdapter is the local-only engine for Infernix, the C++/CUDA fork
235
- * of NInfer (https://github.com/wallawalla47/infernix) tuned for Qwen models
236
- * on a single RTX 50-series GPU. `renderLaunch` renders a local
237
- * `infernix-serve` process from the `INFERNIX_PARAMETERS` surface (the
238
- * Infernix-only fields, from `--ngram-volume` to the quality routes, spell
239
- * onto the argv only for this engine); `deploy` builds the engine in the
240
- * engine directory (the engine's own cmake preset), downloads the model
241
- * artifact (and the n-gram volume, for the multi-file Flash-Next repo) into
242
- * the model directory, and starts the engine; `healthCheck` polls the health
243
- * URL; `stop` signals the tracked process. The engine ships no docker image,
244
- * so the adapter supports the local build mode only.
74
+ * delay waits `ms` milliseconds. The health polls use it between attempts; a
75
+ * poll interval of 0 skips the wait, which the tests use to run the loop
76
+ * without a real sleep.
245
77
  */
246
- export declare class InfernixAdapter extends EngineAdapter {
247
- readonly id = "infernix";
248
- readonly supports: {
249
- docker: boolean;
250
- local: boolean;
251
- };
252
- private readonly host;
253
- private readonly children;
254
- constructor(host?: LifecycleHost);
255
- parameters(): readonly ParameterSpec[];
256
- modelRef(config: Config): {
257
- id: string;
258
- name: string;
259
- };
260
- launchSignature(config?: Config): EngineLaunchSignature;
261
- renderLaunch(config: Config, _hw: HardwareProfile): LaunchPlan;
262
- deploy(plan: LaunchPlan, platform?: EnginePlatformConfig, onProgress?: LaunchProgress, options?: DeployOptions): Promise<DeployResult>;
263
- healthCheck(plan: LaunchPlan, options?: HealthCheckOptions): Promise<HealthResult>;
264
- stop(plan: LaunchPlan): Promise<void>;
265
- private port;
266
- private planKey;
267
- private downloadModel;
268
- }
78
+ export declare function delay(ms: number): Promise<void>;
269
79
  //# sourceMappingURL=adapters.d.ts.map