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
|
@@ -29,14 +29,16 @@ export function parseNvidiaSmiGpuUsage(output) {
|
|
|
29
29
|
* signature. The binary marker must appear in the command line (the image
|
|
30
30
|
* name for a docker plan, the engine binary for a local one); a declared port
|
|
31
31
|
* must appear as a standalone number (the `--port N` flag or the docker
|
|
32
|
-
* `-p host:port:port` mapping)
|
|
33
|
-
*
|
|
32
|
+
* `-p host:port:port` mapping) unless `portInArgv` is false, which means the
|
|
33
|
+
* engine binds its port from a file; a declared env key must be set when the
|
|
34
|
+
* line carries env data, and is neutral when it does not.
|
|
34
35
|
*/
|
|
35
36
|
export function matchLaunchSignature(line, signature) {
|
|
36
37
|
if (!line.command.includes(signature.binary))
|
|
37
38
|
return false;
|
|
38
|
-
if (signature.port !== undefined && !portAppears(line.command, signature.port))
|
|
39
|
+
if (signature.portInArgv !== false && signature.port !== undefined && !portAppears(line.command, signature.port)) {
|
|
39
40
|
return false;
|
|
41
|
+
}
|
|
40
42
|
if (signature.envKeys !== undefined && signature.envKeys.length > 0 && line.env !== undefined) {
|
|
41
43
|
const hit = signature.envKeys.some(key => key in line.env);
|
|
42
44
|
if (!hit)
|
|
@@ -90,4 +92,4 @@ export function resolveOsReserve(input) {
|
|
|
90
92
|
}
|
|
91
93
|
return { reserveMiB: DEFAULT_OS_RESERVE_MIB, source: 'default' };
|
|
92
94
|
}
|
|
93
|
-
//# sourceMappingURL=reserve.js.map
|
|
95
|
+
//# sourceMappingURL=reserve.js.map
|
|
@@ -10,8 +10,10 @@ export type ProviderStatus = 'running' | 'stopped' | 'unsure';
|
|
|
10
10
|
/**
|
|
11
11
|
* ProviderRef is the identity side of one saved provider config: the stable
|
|
12
12
|
* id the card renders and the engine and model it serves. The model is
|
|
13
|
-
* optional
|
|
14
|
-
* a
|
|
13
|
+
* optional: a config that names no model (an absent or empty value) confirms
|
|
14
|
+
* against a plugin-launched engine the detector tied to any model on its
|
|
15
|
+
* port, and reads as unsure only while no running engine carries a model tie.
|
|
16
|
+
* The config is
|
|
15
17
|
* optional and lets the detector price the provider's own launch signature
|
|
16
18
|
* (the engine binary the build mode runs, the port it binds) rather than the
|
|
17
19
|
* adapter's default-port signature; the port is the resolved bind port the
|
|
@@ -60,9 +62,13 @@ export declare function isGpuBusy(usage?: GpuUsageProbe | null): boolean;
|
|
|
60
62
|
* the detector's answer. The order is the plan's contract:
|
|
61
63
|
* 1. A provider whose engine the process probe confirmed running is running
|
|
62
64
|
* (green) when the detector tied that engine to the provider's exact model,
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
65
|
+
* or when the provider names no model and the detector tied the engine to
|
|
66
|
+
* any model: only this plugin's launches and re-links stamp a model tie, so
|
|
67
|
+
* a model-tied engine on the provider's port is that provider's own engine.
|
|
68
|
+
* A provider reads as unsure (yellow) when the engine serves an
|
|
69
|
+
* unidentified or a different model. A running engine using its VRAM does
|
|
70
|
+
* not read as a busy card, so the dot is green, not the unattributable
|
|
71
|
+
* yellow.
|
|
66
72
|
* 2. A provider whose engine is not running falls back to the card state: a
|
|
67
73
|
* busy card (a foreign engine holding the VRAM at 75% or more) reads as
|
|
68
74
|
* unsure, because a full card cannot be attributed to a single model, and
|
|
@@ -70,4 +76,4 @@ export declare function isGpuBusy(usage?: GpuUsageProbe | null): boolean;
|
|
|
70
76
|
* a saved config whose engine is down is stopped.
|
|
71
77
|
*/
|
|
72
78
|
export declare function computeProviderStatuses(input: ProviderStatusInput): Record<string, ProviderStatus>;
|
|
73
|
-
//# sourceMappingURL=status.d.ts.map
|
|
79
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -11,14 +11,26 @@ export function isGpuBusy(usage) {
|
|
|
11
11
|
return false;
|
|
12
12
|
return usage.usedMiB / usage.totalMiB >= GPU_USAGE_BUSY_THRESHOLD;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* namesNoModel reports whether one model field names no model: the absent
|
|
16
|
+
* value or the empty string. The provider side and the engine-ref side of the
|
|
17
|
+
* status tie both read it, so one rule decides both representations.
|
|
18
|
+
*/
|
|
19
|
+
function namesNoModel(model) {
|
|
20
|
+
return model === undefined || model === '';
|
|
21
|
+
}
|
|
14
22
|
/**
|
|
15
23
|
* computeProviderStatuses resolves each saved provider's running-state from
|
|
16
24
|
* the detector's answer. The order is the plan's contract:
|
|
17
25
|
* 1. A provider whose engine the process probe confirmed running is running
|
|
18
26
|
* (green) when the detector tied that engine to the provider's exact model,
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
27
|
+
* or when the provider names no model and the detector tied the engine to
|
|
28
|
+
* any model: only this plugin's launches and re-links stamp a model tie, so
|
|
29
|
+
* a model-tied engine on the provider's port is that provider's own engine.
|
|
30
|
+
* A provider reads as unsure (yellow) when the engine serves an
|
|
31
|
+
* unidentified or a different model. A running engine using its VRAM does
|
|
32
|
+
* not read as a busy card, so the dot is green, not the unattributable
|
|
33
|
+
* yellow.
|
|
22
34
|
* 2. A provider whose engine is not running falls back to the card state: a
|
|
23
35
|
* busy card (a foreign engine holding the VRAM at 75% or more) reads as
|
|
24
36
|
* unsure, because a full card cannot be attributed to a single model, and
|
|
@@ -37,16 +49,15 @@ export function computeProviderStatuses(input) {
|
|
|
37
49
|
if (matches.length > 0) {
|
|
38
50
|
// The engine is running. The question is which model it serves: the
|
|
39
51
|
// detector's identified model, if it tied one, else unknown.
|
|
40
|
-
const identified = matches.find((ref) => ref.modelId
|
|
52
|
+
const identified = matches.find((ref) => !namesNoModel(ref.modelId));
|
|
41
53
|
if (identified !== undefined &&
|
|
42
|
-
provider.model
|
|
43
|
-
identified.modelId === provider.model) {
|
|
54
|
+
(namesNoModel(provider.model) || identified.modelId === provider.model)) {
|
|
44
55
|
statuses[provider.id] = 'running';
|
|
45
56
|
continue;
|
|
46
57
|
}
|
|
47
|
-
// The engine is running but the
|
|
48
|
-
//
|
|
49
|
-
//
|
|
58
|
+
// The engine is running but the detector could not tie it to a model, or
|
|
59
|
+
// it serves a different model than the provider names: unsure, not a
|
|
60
|
+
// guess.
|
|
50
61
|
statuses[provider.id] = 'unsure';
|
|
51
62
|
continue;
|
|
52
63
|
}
|
|
@@ -56,4 +67,4 @@ export function computeProviderStatuses(input) {
|
|
|
56
67
|
}
|
|
57
68
|
return statuses;
|
|
58
69
|
}
|
|
59
|
-
//# sourceMappingURL=status.js.map
|
|
70
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure half of the sudo-prompt rule. A sudo command run by the plugin
|
|
3
|
+
* prompts on the terminal that launched the host, where the card user cannot
|
|
4
|
+
* see it, so the runners announce the prompt and cap how long it may wait.
|
|
5
|
+
* This module holds the constants and the injected-callback guard both
|
|
6
|
+
* runners drive; the child-process wiring stays in the service and the
|
|
7
|
+
* providers, so core never touches node.
|
|
8
|
+
* @module dsh-plugin-local-infer/core/sudo
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* SUDO_CLI_NOTE is the line the Logs section, the log file, and the streamed
|
|
12
|
+
* run show when a sudo command is waiting for the user to type the password
|
|
13
|
+
* on the CLI.
|
|
14
|
+
*/
|
|
15
|
+
export declare const SUDO_CLI_NOTE = "Check your CLI for a sudo prompt";
|
|
16
|
+
/**
|
|
17
|
+
* SUDO_PASSWORD_TIMEOUT_MS caps how long a sudo command may wait for the user
|
|
18
|
+
* to type the password on the CLI before the run kills it and fails.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SUDO_PASSWORD_TIMEOUT_MS = 60000;
|
|
21
|
+
/**
|
|
22
|
+
* SUDO_PROBE_COMMAND is the non-interactive probe that answers whether sudo
|
|
23
|
+
* already holds cached credentials (exit 0) or is about to prompt on the
|
|
24
|
+
* terminal (non-zero). The runners execute it; core only declares it.
|
|
25
|
+
*/
|
|
26
|
+
export declare const SUDO_PROBE_COMMAND: readonly string[];
|
|
27
|
+
/**
|
|
28
|
+
* sudoFailureDetail builds the CommandOutcome.detail text for a command the
|
|
29
|
+
* sudo deadline killed, naming the CLI note and the timeout seconds so the
|
|
30
|
+
* Logs section explains what the user missed.
|
|
31
|
+
*/
|
|
32
|
+
export declare function sudoFailureDetail(command: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* SudoTimer is the injectable set/clear pair a sudo guard arms and disarms.
|
|
35
|
+
* Tests drive the clock through a fake; the default is setTimeout and
|
|
36
|
+
* clearTimeout.
|
|
37
|
+
*/
|
|
38
|
+
export interface SudoTimer {
|
|
39
|
+
set: (callback: () => void, ms: number) => unknown;
|
|
40
|
+
clear: (handle: unknown) => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* SudoGuardOptions tunes one guarded command run. `needsSudo` is the caller's
|
|
44
|
+
* declaration (SystemDep.requiresSudo on the install path, RunOptions.needsSudo
|
|
45
|
+
* on the lifecycle path), never inferred from the command text. `probe`
|
|
46
|
+
* answers whether sudo already holds cached credentials, `notify` announces
|
|
47
|
+
* the coming prompt once, `kill` stops the command, `timeoutMs` overrides the
|
|
48
|
+
* deadline, and `timer` swaps the clock.
|
|
49
|
+
*/
|
|
50
|
+
export interface SudoGuardOptions {
|
|
51
|
+
needsSudo?: boolean;
|
|
52
|
+
command: string;
|
|
53
|
+
probe: () => Promise<boolean>;
|
|
54
|
+
notify: (command: string) => void;
|
|
55
|
+
kill: () => void;
|
|
56
|
+
timeoutMs?: number;
|
|
57
|
+
timer?: SudoTimer;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* SudoGuard is the guard's answer, read by the caller around the command run.
|
|
61
|
+
* `announced` says the prompt was announced and a deadline is armed;
|
|
62
|
+
* `disarm` clears the armed deadline once the command finishes; `timedOut`
|
|
63
|
+
* reads whether the deadline already fired, so a failed run can carry
|
|
64
|
+
* sudoFailureDetail instead of a bare exit.
|
|
65
|
+
*/
|
|
66
|
+
export interface SudoGuard {
|
|
67
|
+
announced: boolean;
|
|
68
|
+
disarm(): void;
|
|
69
|
+
timedOut(): boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* guardSudoCommand applies the shared sudo-prompt rule for one command, so
|
|
73
|
+
* the service install runner and the providers lifecycle host drive one rule.
|
|
74
|
+
* A command the caller does not declare sudo runs through unguarded: no
|
|
75
|
+
* probe, no announcement, no timer. A declared command probes first; cached
|
|
76
|
+
* credentials (probe resolves true) run through the same way. Otherwise the
|
|
77
|
+
* guard calls notify once and arms the timeout whose fire calls kill.
|
|
78
|
+
*/
|
|
79
|
+
export declare function guardSudoCommand(options: SudoGuardOptions): Promise<SudoGuard>;
|
|
80
|
+
//# sourceMappingURL=sudo.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure half of the sudo-prompt rule. A sudo command run by the plugin
|
|
3
|
+
* prompts on the terminal that launched the host, where the card user cannot
|
|
4
|
+
* see it, so the runners announce the prompt and cap how long it may wait.
|
|
5
|
+
* This module holds the constants and the injected-callback guard both
|
|
6
|
+
* runners drive; the child-process wiring stays in the service and the
|
|
7
|
+
* providers, so core never touches node.
|
|
8
|
+
* @module dsh-plugin-local-infer/core/sudo
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* SUDO_CLI_NOTE is the line the Logs section, the log file, and the streamed
|
|
12
|
+
* run show when a sudo command is waiting for the user to type the password
|
|
13
|
+
* on the CLI.
|
|
14
|
+
*/
|
|
15
|
+
export const SUDO_CLI_NOTE = 'Check your CLI for a sudo prompt';
|
|
16
|
+
/**
|
|
17
|
+
* SUDO_PASSWORD_TIMEOUT_MS caps how long a sudo command may wait for the user
|
|
18
|
+
* to type the password on the CLI before the run kills it and fails.
|
|
19
|
+
*/
|
|
20
|
+
export const SUDO_PASSWORD_TIMEOUT_MS = 60_000;
|
|
21
|
+
/**
|
|
22
|
+
* SUDO_PROBE_COMMAND is the non-interactive probe that answers whether sudo
|
|
23
|
+
* already holds cached credentials (exit 0) or is about to prompt on the
|
|
24
|
+
* terminal (non-zero). The runners execute it; core only declares it.
|
|
25
|
+
*/
|
|
26
|
+
export const SUDO_PROBE_COMMAND = ['sudo', '-n', 'true'];
|
|
27
|
+
/**
|
|
28
|
+
* sudoFailureDetail builds the CommandOutcome.detail text for a command the
|
|
29
|
+
* sudo deadline killed, naming the CLI note and the timeout seconds so the
|
|
30
|
+
* Logs section explains what the user missed.
|
|
31
|
+
*/
|
|
32
|
+
export function sudoFailureDetail(command) {
|
|
33
|
+
return (`${command} was killed: no sudo password was entered within ` +
|
|
34
|
+
`${SUDO_PASSWORD_TIMEOUT_MS / 1000} seconds. ${SUDO_CLI_NOTE}`);
|
|
35
|
+
}
|
|
36
|
+
/** DEFAULT_SUDO_TIMER is the guard clock when the caller injects none. */
|
|
37
|
+
const DEFAULT_SUDO_TIMER = {
|
|
38
|
+
set: (callback, ms) => setTimeout(callback, ms),
|
|
39
|
+
clear: (handle) => clearTimeout(handle),
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* guardSudoCommand applies the shared sudo-prompt rule for one command, so
|
|
43
|
+
* the service install runner and the providers lifecycle host drive one rule.
|
|
44
|
+
* A command the caller does not declare sudo runs through unguarded: no
|
|
45
|
+
* probe, no announcement, no timer. A declared command probes first; cached
|
|
46
|
+
* credentials (probe resolves true) run through the same way. Otherwise the
|
|
47
|
+
* guard calls notify once and arms the timeout whose fire calls kill.
|
|
48
|
+
*/
|
|
49
|
+
export async function guardSudoCommand(options) {
|
|
50
|
+
if (options.needsSudo !== true) {
|
|
51
|
+
return unguarded();
|
|
52
|
+
}
|
|
53
|
+
if (await options.probe()) {
|
|
54
|
+
return unguarded();
|
|
55
|
+
}
|
|
56
|
+
options.notify(options.command);
|
|
57
|
+
const timer = options.timer ?? DEFAULT_SUDO_TIMER;
|
|
58
|
+
const timeoutMs = options.timeoutMs ?? SUDO_PASSWORD_TIMEOUT_MS;
|
|
59
|
+
let timedOut = false;
|
|
60
|
+
const handle = timer.set(() => {
|
|
61
|
+
timedOut = true;
|
|
62
|
+
options.kill();
|
|
63
|
+
}, timeoutMs);
|
|
64
|
+
return {
|
|
65
|
+
announced: true,
|
|
66
|
+
disarm: () => timer.clear(handle),
|
|
67
|
+
timedOut: () => timedOut,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** unguarded is the pass-through guard for a run nothing was armed for. */
|
|
71
|
+
function unguarded() {
|
|
72
|
+
return {
|
|
73
|
+
announced: false,
|
|
74
|
+
disarm: () => { },
|
|
75
|
+
timedOut: () => false,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=sudo.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-local-infer-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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",
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator prompt store: the saved prompt file under
|
|
3
|
+
* ~/.dsh/local-infer/orchestrator.json, the shipped prompt.md default, and
|
|
4
|
+
* the in-memory holder the system-prompt section and the settings routes
|
|
5
|
+
* share. Every read sanitizes the file, so a by-hand edit never poisons the
|
|
6
|
+
* injected prompt. Mirrors the sanitize-on-read discipline of
|
|
7
|
+
* packages/ui/src/config.ts.
|
|
8
|
+
* @module dsh-plugin-local-infer/orchestrator/config
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* orchestratorConfigPath names the file this package owns. It sits in the
|
|
12
|
+
* shared local-infer dir beside the ui config so one place holds everything
|
|
13
|
+
* the plugin persists.
|
|
14
|
+
*/
|
|
15
|
+
export declare function orchestratorConfigPath(): string;
|
|
16
|
+
/**
|
|
17
|
+
* StoredOrchestratorConfig is the whole persisted shape: the saved prompt,
|
|
18
|
+
* where an empty string carries "no saved prompt" so the holder falls back
|
|
19
|
+
* to the shipped default.
|
|
20
|
+
*/
|
|
21
|
+
export interface StoredOrchestratorConfig {
|
|
22
|
+
prompt: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* readOrchestratorConfig reads the saved prompt. A missing or broken file,
|
|
26
|
+
* or a prompt field that is not a string, reads as no saved prompt (empty),
|
|
27
|
+
* so a first open and a by-hand edit both land on the default instead of
|
|
28
|
+
* throwing.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readOrchestratorConfig(): StoredOrchestratorConfig;
|
|
31
|
+
/**
|
|
32
|
+
* writeOrchestratorConfig persists the prompt, creating the directory tree
|
|
33
|
+
* on first write the same way the ui config write does.
|
|
34
|
+
*/
|
|
35
|
+
export declare function writeOrchestratorConfig(config: StoredOrchestratorConfig): void;
|
|
36
|
+
/**
|
|
37
|
+
* defaultOrchestratorPrompt returns the shipped prompt.md text read from the
|
|
38
|
+
* package root. The URL hop is relative to this module, so src/ and lib/
|
|
39
|
+
* depths both resolve one level up to the package root. The read is cached;
|
|
40
|
+
* an unreadable file yields '' without throwing.
|
|
41
|
+
*/
|
|
42
|
+
export declare function defaultOrchestratorPrompt(): string;
|
|
43
|
+
/**
|
|
44
|
+
* getOrchestratorPrompt returns the effective prompt: the saved value when a
|
|
45
|
+
* non-empty one exists, otherwise the shipped default. The first call reads
|
|
46
|
+
* the file once and caches, so the system-prompt section pays no per-message
|
|
47
|
+
* disk read.
|
|
48
|
+
*/
|
|
49
|
+
export declare function getOrchestratorPrompt(): string;
|
|
50
|
+
/**
|
|
51
|
+
* setOrchestratorPrompt persists the prompt and refreshes the holder, so the
|
|
52
|
+
* injected section picks the new text up without another file read. An empty
|
|
53
|
+
* save means "no saved prompt" and falls back to the default.
|
|
54
|
+
*/
|
|
55
|
+
export declare function setOrchestratorPrompt(prompt: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* hasSavedOrchestratorPrompt reports whether the file holds a saved prompt
|
|
58
|
+
* override. The empty string is the store's sentinel for "no saved prompt",
|
|
59
|
+
* so the settings routes read the flag through here instead of re-deriving
|
|
60
|
+
* the sentinel rule the holder already applies.
|
|
61
|
+
*/
|
|
62
|
+
export declare function hasSavedOrchestratorPrompt(): boolean;
|
|
63
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator prompt store: the saved prompt file under
|
|
3
|
+
* ~/.dsh/local-infer/orchestrator.json, the shipped prompt.md default, and
|
|
4
|
+
* the in-memory holder the system-prompt section and the settings routes
|
|
5
|
+
* share. Every read sanitizes the file, so a by-hand edit never poisons the
|
|
6
|
+
* injected prompt. Mirrors the sanitize-on-read discipline of
|
|
7
|
+
* packages/ui/src/config.ts.
|
|
8
|
+
* @module dsh-plugin-local-infer/orchestrator/config
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
/**
|
|
14
|
+
* orchestratorConfigPath names the file this package owns. It sits in the
|
|
15
|
+
* shared local-infer dir beside the ui config so one place holds everything
|
|
16
|
+
* the plugin persists.
|
|
17
|
+
*/
|
|
18
|
+
export function orchestratorConfigPath() {
|
|
19
|
+
return join(homedir(), '.dsh', 'local-infer', 'orchestrator.json');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* readOrchestratorConfig reads the saved prompt. A missing or broken file,
|
|
23
|
+
* or a prompt field that is not a string, reads as no saved prompt (empty),
|
|
24
|
+
* so a first open and a by-hand edit both land on the default instead of
|
|
25
|
+
* throwing.
|
|
26
|
+
*/
|
|
27
|
+
export function readOrchestratorConfig() {
|
|
28
|
+
const path = orchestratorConfigPath();
|
|
29
|
+
if (!existsSync(path)) {
|
|
30
|
+
return { prompt: '' };
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
34
|
+
return { prompt: typeof parsed.prompt === 'string' ? parsed.prompt : '' };
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return { prompt: '' };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* writeOrchestratorConfig persists the prompt, creating the directory tree
|
|
42
|
+
* on first write the same way the ui config write does.
|
|
43
|
+
*/
|
|
44
|
+
export function writeOrchestratorConfig(config) {
|
|
45
|
+
const path = orchestratorConfigPath();
|
|
46
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
47
|
+
writeFileSync(path, JSON.stringify({ prompt: config.prompt }, null, 2));
|
|
48
|
+
}
|
|
49
|
+
// Cache of the shipped prompt.md text: the file never changes while the
|
|
50
|
+
// process runs, so only a successful read is kept and a failed read retries
|
|
51
|
+
// on the next call instead of locking in the empty fallback.
|
|
52
|
+
let defaultPromptCache;
|
|
53
|
+
/**
|
|
54
|
+
* defaultOrchestratorPrompt returns the shipped prompt.md text read from the
|
|
55
|
+
* package root. The URL hop is relative to this module, so src/ and lib/
|
|
56
|
+
* depths both resolve one level up to the package root. The read is cached;
|
|
57
|
+
* an unreadable file yields '' without throwing.
|
|
58
|
+
*/
|
|
59
|
+
export function defaultOrchestratorPrompt() {
|
|
60
|
+
if (defaultPromptCache === undefined) {
|
|
61
|
+
try {
|
|
62
|
+
defaultPromptCache = readFileSync(new URL('../prompt.md', import.meta.url), 'utf8');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return '';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return defaultPromptCache;
|
|
69
|
+
}
|
|
70
|
+
// The effective prompt holder: null until the first read refreshes it from
|
|
71
|
+
// the file, then the saved value or the default until the setter persists a
|
|
72
|
+
// new one.
|
|
73
|
+
let effectivePrompt = null;
|
|
74
|
+
/**
|
|
75
|
+
* getOrchestratorPrompt returns the effective prompt: the saved value when a
|
|
76
|
+
* non-empty one exists, otherwise the shipped default. The first call reads
|
|
77
|
+
* the file once and caches, so the system-prompt section pays no per-message
|
|
78
|
+
* disk read.
|
|
79
|
+
*/
|
|
80
|
+
export function getOrchestratorPrompt() {
|
|
81
|
+
if (effectivePrompt === null) {
|
|
82
|
+
effectivePrompt = toEffective(readOrchestratorConfig().prompt);
|
|
83
|
+
}
|
|
84
|
+
return effectivePrompt;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* setOrchestratorPrompt persists the prompt and refreshes the holder, so the
|
|
88
|
+
* injected section picks the new text up without another file read. An empty
|
|
89
|
+
* save means "no saved prompt" and falls back to the default.
|
|
90
|
+
*/
|
|
91
|
+
export function setOrchestratorPrompt(prompt) {
|
|
92
|
+
writeOrchestratorConfig({ prompt });
|
|
93
|
+
effectivePrompt = toEffective(prompt);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* hasSavedOrchestratorPrompt reports whether the file holds a saved prompt
|
|
97
|
+
* override. The empty string is the store's sentinel for "no saved prompt",
|
|
98
|
+
* so the settings routes read the flag through here instead of re-deriving
|
|
99
|
+
* the sentinel rule the holder already applies.
|
|
100
|
+
*/
|
|
101
|
+
export function hasSavedOrchestratorPrompt() {
|
|
102
|
+
return readOrchestratorConfig().prompt !== '';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* toEffective resolves one saved value against the default: an empty saved
|
|
106
|
+
* prompt reads as no saved prompt.
|
|
107
|
+
*/
|
|
108
|
+
function toEffective(saved) {
|
|
109
|
+
return saved === '' ? defaultOrchestratorPrompt() : saved;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator capability: an editable "Orchestrator Prompt" persisted
|
|
3
|
+
* under `~/.dsh/local-infer`, defaulted from the shipped `prompt.md`, and
|
|
4
|
+
* injected into the system prompt while the component is enabled.
|
|
5
|
+
*
|
|
6
|
+
* The prompt store (saved file, shipped default, effective-prompt holder)
|
|
7
|
+
* lives in ./config.js and is re-exported here as the single source of truth
|
|
8
|
+
* the system-prompt seam (TASK-003) and the settings routes (TASK-004) pull
|
|
9
|
+
* from.
|
|
10
|
+
* @module dsh-plugin-local-infer/orchestrator
|
|
11
|
+
*/
|
|
12
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
13
|
+
export { defaultOrchestratorPrompt, getOrchestratorPrompt, hasSavedOrchestratorPrompt, orchestratorConfigPath, readOrchestratorConfig, setOrchestratorPrompt, writeOrchestratorConfig, } from './config.js';
|
|
14
|
+
export type { StoredOrchestratorConfig } from './config.js';
|
|
15
|
+
export declare const name = "local-infer-orchestrator";
|
|
16
|
+
export declare const inject: string[];
|
|
17
|
+
/**
|
|
18
|
+
* SystemPromptService narrows the dsh-system-prompt service to the one
|
|
19
|
+
* member this package uses. That package augments the cordis Context with
|
|
20
|
+
* `systemPrompt` and is not a dependency here, so the scoped inject casts
|
|
21
|
+
* the scope locally (same shape as the ui's WebServerService narrowing).
|
|
22
|
+
*/
|
|
23
|
+
export interface SystemPromptService {
|
|
24
|
+
/**
|
|
25
|
+
* Registers one ordered prompt section in the calling scope and returns
|
|
26
|
+
* the Cordis effect disposer. `text` may be a provider re-evaluated at
|
|
27
|
+
* each assembly.
|
|
28
|
+
*/
|
|
29
|
+
section(section: {
|
|
30
|
+
name: string;
|
|
31
|
+
order: number;
|
|
32
|
+
text: string | (() => string);
|
|
33
|
+
interpolate?: boolean;
|
|
34
|
+
}): () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Mount the Orchestrator prompt. The scoped `systemPrompt` inject registers
|
|
38
|
+
* the one global `orchestrator` section where the seam exists; the effect
|
|
39
|
+
* scope ties the registration to the plugin, so it unregisters with the
|
|
40
|
+
* plugin. The scoped `webServer` inject registers the /local-infer/
|
|
41
|
+
* orchestrator settings routes where that seam exists, so a headless profile
|
|
42
|
+
* keeps no routes.
|
|
43
|
+
*/
|
|
44
|
+
export declare function apply(ctx: Context): void;
|
|
45
|
+
declare const plugin: {
|
|
46
|
+
name: string;
|
|
47
|
+
inject: string[];
|
|
48
|
+
apply: typeof apply;
|
|
49
|
+
};
|
|
50
|
+
export default plugin;
|
|
51
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator capability: an editable "Orchestrator Prompt" persisted
|
|
3
|
+
* under `~/.dsh/local-infer`, defaulted from the shipped `prompt.md`, and
|
|
4
|
+
* injected into the system prompt while the component is enabled.
|
|
5
|
+
*
|
|
6
|
+
* The prompt store (saved file, shipped default, effective-prompt holder)
|
|
7
|
+
* lives in ./config.js and is re-exported here as the single source of truth
|
|
8
|
+
* the system-prompt seam (TASK-003) and the settings routes (TASK-004) pull
|
|
9
|
+
* from.
|
|
10
|
+
* @module dsh-plugin-local-infer/orchestrator
|
|
11
|
+
*/
|
|
12
|
+
import { getOrchestratorPrompt } from './config.js';
|
|
13
|
+
import { registerOrchestratorRoutes } from './route.js';
|
|
14
|
+
export { defaultOrchestratorPrompt, getOrchestratorPrompt, hasSavedOrchestratorPrompt, orchestratorConfigPath, readOrchestratorConfig, setOrchestratorPrompt, writeOrchestratorConfig, } from './config.js';
|
|
15
|
+
export const name = 'local-infer-orchestrator';
|
|
16
|
+
// No required top-level services: the `systemPrompt` and `webServer` seams
|
|
17
|
+
// are pulled with scoped injects in their own effects, so the component
|
|
18
|
+
// stays loadable in profiles that lack either service.
|
|
19
|
+
export const inject = [];
|
|
20
|
+
// The section placement: the deployment persona prefix sits at 0 and the
|
|
21
|
+
// first centrally allocated policy section (PLAN_POLICY) at 500, so 100
|
|
22
|
+
// puts the Orchestrator instructions just after the persona and ahead of
|
|
23
|
+
// first-party guidance. dsh-system-prompt allocates nothing between 0 and
|
|
24
|
+
// 500, and external contributions may pick any finite order.
|
|
25
|
+
const orchestratorSectionOrder = 100;
|
|
26
|
+
/**
|
|
27
|
+
* mountSeam pulls one optional service through a scoped inject and mounts
|
|
28
|
+
* the half that needs it. A profile without the seam never runs the
|
|
29
|
+
* callback, and a mount failure is logged and swallowed so the component
|
|
30
|
+
* still loads without that half. `skipped` names the half in the catch log.
|
|
31
|
+
*/
|
|
32
|
+
function mountSeam(ctx, service, skipped, mount) {
|
|
33
|
+
ctx.inject([service], (scope) => {
|
|
34
|
+
try {
|
|
35
|
+
mount(scope);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(`[local-infer] orchestrator ${skipped}: ${error}`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Mount the Orchestrator prompt. The scoped `systemPrompt` inject registers
|
|
44
|
+
* the one global `orchestrator` section where the seam exists; the effect
|
|
45
|
+
* scope ties the registration to the plugin, so it unregisters with the
|
|
46
|
+
* plugin. The scoped `webServer` inject registers the /local-infer/
|
|
47
|
+
* orchestrator settings routes where that seam exists, so a headless profile
|
|
48
|
+
* keeps no routes.
|
|
49
|
+
*/
|
|
50
|
+
export function apply(ctx) {
|
|
51
|
+
if (typeof ctx.inject !== 'function') {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
mountSeam(ctx, 'systemPrompt', 'prompt section skipped', (scope) => {
|
|
55
|
+
const systemPrompt = scope.systemPrompt;
|
|
56
|
+
systemPrompt.section({
|
|
57
|
+
name: 'orchestrator',
|
|
58
|
+
order: orchestratorSectionOrder,
|
|
59
|
+
// The prompt is user-editable text: a stray {{var}} stays literal
|
|
60
|
+
// instead of failing every later prompt assembly.
|
|
61
|
+
interpolate: false,
|
|
62
|
+
// Provider form re-reads the holder per assembly, so a settings
|
|
63
|
+
// Save reaches the next assembly without a host restart.
|
|
64
|
+
text: () => getOrchestratorPrompt(),
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
mountSeam(ctx, 'webServer', 'settings routes skipped', (scope) => {
|
|
68
|
+
registerOrchestratorRoutes(scope);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const plugin = { name, inject, apply };
|
|
72
|
+
export default plugin;
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Orchestrator settings routes the Web card talks to: GET
|
|
3
|
+
* /local-infer/orchestrator answers { prompt, defaultPrompt, saved } (the
|
|
4
|
+
* effective prompt, the shipped prompt.md default, and whether the effective
|
|
5
|
+
* prompt is a saved value), and POST /local-infer/orchestrator/save persists
|
|
6
|
+
* { prompt } through the config setter (an empty string clears the saved
|
|
7
|
+
* override back to the default) and answers with the same payload. The routes
|
|
8
|
+
* are held by an effect, so they go when the component does.
|
|
9
|
+
*
|
|
10
|
+
* The HTTP plumbing is a minimal local mirror of the ui package's defineRoute
|
|
11
|
+
* template (method guard 405, bounded body 413, JSON answer). The ui package
|
|
12
|
+
* does export its template, but this package deliberately keeps no dependency
|
|
13
|
+
* on ui: importing ui's route module would load its whole route graph (the
|
|
14
|
+
* service, providers, and core packages) into a component that ships disabled
|
|
15
|
+
* and must stay loadable headless, so the shared shape is copied rather than
|
|
16
|
+
* imported, and the two copies change together by hand. The stream helpers
|
|
17
|
+
* the ui template carries are dropped; these two routes only ever answer with
|
|
18
|
+
* one JSON body.
|
|
19
|
+
* @module dsh-plugin-local-infer/orchestrator/route
|
|
20
|
+
*/
|
|
21
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
22
|
+
/**
|
|
23
|
+
* OrchestratorRoute is one webServer route definition the register step holds
|
|
24
|
+
* by an effect: the stable name, the exact-match path, and the handler the web
|
|
25
|
+
* server invokes per request.
|
|
26
|
+
*/
|
|
27
|
+
export interface OrchestratorRoute {
|
|
28
|
+
name: string;
|
|
29
|
+
kind: 'exact';
|
|
30
|
+
path: string;
|
|
31
|
+
handler: (req: IncomingLike, res: OutgoingLike) => void | Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The webServer service is dsh-specific and absent from the cordis Context
|
|
35
|
+
* type, so the route narrows the scoped context to the one member it needs
|
|
36
|
+
* (same shape as the ui's WebServerService narrowing).
|
|
37
|
+
*/
|
|
38
|
+
export interface WebServerService {
|
|
39
|
+
register(route: OrchestratorRoute): () => void;
|
|
40
|
+
}
|
|
41
|
+
interface IncomingLike extends AsyncIterable<Buffer> {
|
|
42
|
+
method: string;
|
|
43
|
+
url: string;
|
|
44
|
+
destroy(): void;
|
|
45
|
+
}
|
|
46
|
+
interface OutgoingLike {
|
|
47
|
+
writeHead(status: number, headers?: Record<string, string>): OutgoingLike;
|
|
48
|
+
end(body?: string): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* registerOrchestratorRoutes registers the GET and save routes on the web
|
|
52
|
+
* server and holds them by an effect, so a component switch off removes them
|
|
53
|
+
* before the next switch on re-registers. The scoped context carries the
|
|
54
|
+
* webServer.
|
|
55
|
+
*/
|
|
56
|
+
export declare function registerOrchestratorRoutes(scope: Context & {
|
|
57
|
+
webServer: WebServerService;
|
|
58
|
+
}): void;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=route.d.ts.map
|