pi-mega-compact 0.20.29 → 0.20.31
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/dist/config/vector-cortex-vc9d.js +32 -0
- package/dist/config/vector-cortex.js +2 -1
- package/dist/config.js +1 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-helpers.js +1 -1
- package/dist/extensions/dashboard-server/routes-rag-settings-vector-cortex.js +1 -0
- package/dist/extensions/dashboard-server/routes-setup-detect-cache.js +201 -0
- package/dist/extensions/dashboard-server/routes-setup.js +11 -83
- package/dist/extensions/mega-config-types.js +1 -0
- package/dist/extensions/mega-config.js +3 -1
- package/dist/extensions/mega-events/separated-prompt.js +7 -7
- package/dist/src/config/vector-cortex-vc9d.js +32 -0
- package/dist/src/config/vector-cortex.js +2 -1
- package/dist/src/config.js +1 -1
- package/extensions/dashboard-client/dist/assets/{AreaChart-DIKsPqLG.js → AreaChart-EL8l2Fcj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-DIKsPqLG.js.map → AreaChart-EL8l2Fcj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-DeqN74Hn.js → BarChart-TrwfSh0w.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-DeqN74Hn.js.map → BarChart-TrwfSh0w.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-x1YU4tYc.js → CacheTab-C3KWDFDm.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-x1YU4tYc.js.map → CacheTab-C3KWDFDm.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-6BuEbd8Y.js → EventsTab-CNrT-b7t.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-6BuEbd8Y.js.map → EventsTab-CNrT-b7t.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-B71Ft1ac.js → HealthTab-CkBCFPk6.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-B71Ft1ac.js.map → HealthTab-CkBCFPk6.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-dysyJtHk.js → MaintenanceTab-CcbKszwx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-dysyJtHk.js.map → MaintenanceTab-CcbKszwx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-B3dKRb_4.js → MemoryMapTab-B2LvwScj.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-B3dKRb_4.js.map → MemoryMapTab-B2LvwScj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-COn4GoUK.js → MetricsTab-Dv_xZtOG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-COn4GoUK.js.map → MetricsTab-Dv_xZtOG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-Cd9qAEB3.js → OverviewTab-D7xwhpOl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-Cd9qAEB3.js.map → OverviewTab-D7xwhpOl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-DpiP1-Vv.js → ReposTab-BfhiPXdA.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-DpiP1-Vv.js.map → ReposTab-BfhiPXdA.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BwRUeGZM.js → SessionsTab-tQM0TQLp.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-BwRUeGZM.js.map → SessionsTab-tQM0TQLp.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-G-MkdQiR.js +3 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-G-MkdQiR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-_XsdjQ7Z.js → TimeSavedCard-CYltysD3.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-_XsdjQ7Z.js.map → TimeSavedCard-CYltysD3.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CWPscPLL.js → TurnsTab-1Y_Lpxx-.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-CWPscPLL.js.map → TurnsTab-1Y_Lpxx-.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-Cx56rAIM.js → VcStatusBadge-BNHVeTG7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VcStatusBadge-Cx56rAIM.js.map → VcStatusBadge-BNHVeTG7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-B5ElUM7S.js → VectorCortexTab-goacPxL1.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-B5ElUM7S.js.map → VectorCortexTab-goacPxL1.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-uZ5Mq3XG.js → WikiTab-DTOemYtE.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-uZ5Mq3XG.js.map → WikiTab-DTOemYtE.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-Kc18bYFz.js → button-B_4j_PVR.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-Kc18bYFz.js.map → button-B_4j_PVR.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-COJZoG08.js → card-Ce58rSXG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-COJZoG08.js.map → card-Ce58rSXG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-ChEYo017.js → generateCategoricalChart-DtNoJ6fZ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-ChEYo017.js.map → generateCategoricalChart-DtNoJ6fZ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-CB7Rn5FP.js → index-eoCm0uxj.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-CB7Rn5FP.js.map → index-eoCm0uxj.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-BFhl_tNh.js → switch-B9kM0N7R.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-BFhl_tNh.js.map → switch-B9kM0N7R.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-DJ68kATc.js → toggle-BwoHYpMa.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-DJ68kATc.js.map → toggle-BwoHYpMa.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-CXWh42xX.js → useSSE-DohG5AGv.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-CXWh42xX.js.map → useSSE-DohG5AGv.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +14 -2
- package/extensions/dashboard-server/routes-rag-settings-helpers.ts +1 -1
- package/extensions/dashboard-server/routes-rag-settings-vector-cortex.ts +6 -0
- package/extensions/dashboard-server/routes-setup-detect-cache.ts +224 -0
- package/extensions/dashboard-server/routes-setup.ts +19 -79
- package/extensions/mega-config-types.ts +181 -0
- package/extensions/mega-config.ts +7 -171
- package/extensions/mega-events/separated-prompt.ts +7 -8
- package/package.json +1 -1
- package/src/config/vector-cortex-vc9d.ts +34 -0
- package/src/config/vector-cortex.ts +2 -1
- package/src/config.ts +1 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CJFDD2_v.js +0 -3
- package/extensions/dashboard-client/dist/assets/SetupTab-CJFDD2_v.js.map +0 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/routes-setup-detect-cache.ts — memoized embedder-barrier
|
|
3
|
+
* detection (VC9D).
|
|
4
|
+
*
|
|
5
|
+
* The three raw fresh detectors (`detectOllama` / `detectLlamaCpp` /
|
|
6
|
+
* `detectOnnx`) moved verbatim out of routes-setup.ts — they are the source of
|
|
7
|
+
* truth for "is this embedder backend present". Each also has a memoized
|
|
8
|
+
* sibling (`memoizedDetectOllama` / `memoizedDetectLlamaCpp` /
|
|
9
|
+
* `memoizedDetectOnnx`) that runs the expensive spawn ONLY when its mutable
|
|
10
|
+
* input changes, matching the `healthFactCacheKey` invalidation semantics from
|
|
11
|
+
* routes-vector-cortex-health.ts:71-122: the cache key is the resolved binary
|
|
12
|
+
* path + its size/mtime (onnx: resolved module path + package mtime), so an
|
|
13
|
+
* install/upgrade on PATH or in node_modules naturally invalidates the entry,
|
|
14
|
+
* while a steady environment reuses the result instead of re-spawning.
|
|
15
|
+
*
|
|
16
|
+
* A single module-level slot per target is shared across every
|
|
17
|
+
* /api/setup-detect request, so consecutive polls reuse the result.
|
|
18
|
+
*
|
|
19
|
+
* Guardrails: PREVENT-PI-004 (local subprocess + filesystem reads only, no
|
|
20
|
+
* network), PREVENT-011 (no `any`). Each decoration line carries a
|
|
21
|
+
* guardrails-allow annotation.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: local subprocess detection only
|
|
25
|
+
import { createRequire } from "node:module";
|
|
26
|
+
import { statSync } from "node:fs";
|
|
27
|
+
import type { DetectResult, OllamaDetectResult } from "./api-contracts/setup.js";
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Raw fresh detectors (moved verbatim from routes-setup.ts — single source).
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
export function detectOllama(): OllamaDetectResult | null {
|
|
34
|
+
try {
|
|
35
|
+
const version = spawnSync("ollama", ["--version"], {
|
|
36
|
+
timeout: 5000,
|
|
37
|
+
encoding: "utf-8",
|
|
38
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
39
|
+
});
|
|
40
|
+
if (version.status !== 0) {
|
|
41
|
+
return { installed: false, models: [], running: false, detail: version.stderr?.trim() || "not found" };
|
|
42
|
+
}
|
|
43
|
+
// Check for running server
|
|
44
|
+
let running = false;
|
|
45
|
+
let models: string[] = [];
|
|
46
|
+
try {
|
|
47
|
+
const listResult = spawnSync("ollama", ["list"], {
|
|
48
|
+
timeout: 5000,
|
|
49
|
+
encoding: "utf-8",
|
|
50
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
51
|
+
});
|
|
52
|
+
if (listResult.status === 0) {
|
|
53
|
+
running = true;
|
|
54
|
+
// Parse lines: NAME ID SIZE MODIFIED
|
|
55
|
+
const lines = listResult.stdout?.split("\n") ?? [];
|
|
56
|
+
for (const line of lines) {
|
|
57
|
+
const name = line.split(/\s+/)[0];
|
|
58
|
+
if (name && name !== "NAME") models.push(name);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
// ollama list failed — server may not be running
|
|
63
|
+
running = false;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
installed: true,
|
|
67
|
+
models,
|
|
68
|
+
running,
|
|
69
|
+
detail: version.stdout?.trim() || null,
|
|
70
|
+
};
|
|
71
|
+
} catch {
|
|
72
|
+
return { installed: false, models: [], running: false, detail: "detection error" };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function detectLlamaCpp(): DetectResult | null {
|
|
77
|
+
try {
|
|
78
|
+
const which = spawnSync("which", ["llama-server", "llama.cpp"], {
|
|
79
|
+
timeout: 3000,
|
|
80
|
+
encoding: "utf-8",
|
|
81
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
82
|
+
});
|
|
83
|
+
const installed = which.status === 0 && which.stdout.trim().length > 0;
|
|
84
|
+
return {
|
|
85
|
+
installed,
|
|
86
|
+
detail: installed ? which.stdout.trim() : null,
|
|
87
|
+
};
|
|
88
|
+
} catch {
|
|
89
|
+
return { installed: false, detail: "detection error" };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function detectOnnx(): DetectResult | null {
|
|
94
|
+
try {
|
|
95
|
+
// Check for onnxruntime-node in a parent node_modules
|
|
96
|
+
const req = createRequire(import.meta.url);
|
|
97
|
+
try {
|
|
98
|
+
req.resolve("onnxruntime-node");
|
|
99
|
+
return { installed: true, detail: "onnxruntime-node found in node_modules" };
|
|
100
|
+
} catch {
|
|
101
|
+
return { installed: false, detail: "onnxruntime-node not found in node_modules" };
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
return { installed: false, detail: "detection error" };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Detect memo slot — generic, deterministic, unit-testable.
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
export interface DetectMemoSlot<V> {
|
|
113
|
+
/** Return the stored value when `key` matches the cached key, else null. */
|
|
114
|
+
get(key: string): V | null;
|
|
115
|
+
/** Store a value under a key. */
|
|
116
|
+
set(key: string, value: V): void;
|
|
117
|
+
/** Drop the cached entry. */
|
|
118
|
+
clear(): void;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** A single memo slot. `value` is never null for a detect result (objects only). */
|
|
122
|
+
export function createDetectMemo<V>(): DetectMemoSlot<V> {
|
|
123
|
+
let key: string | null = null;
|
|
124
|
+
let value: V | null = null;
|
|
125
|
+
return {
|
|
126
|
+
get(k: string): V | null {
|
|
127
|
+
return key !== null && key === k ? value : null;
|
|
128
|
+
},
|
|
129
|
+
set(k: string, v: V): void {
|
|
130
|
+
key = k;
|
|
131
|
+
value = v;
|
|
132
|
+
},
|
|
133
|
+
clear(): void {
|
|
134
|
+
key = null;
|
|
135
|
+
value = null;
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Run `compute` only when the derived key changes; a null key (inputs not
|
|
142
|
+
* resolvable — e.g. the binary is absent) is never cached, so every call runs
|
|
143
|
+
* the (cheap, fast-failing) detect fresh. This ordering is what the
|
|
144
|
+
* SETUP-CORTEX-030/031 fixtures pin: an unchanged key returns the stored value
|
|
145
|
+
* without re-running compute; a key mutation forces a recompute.
|
|
146
|
+
*/
|
|
147
|
+
export function withDetectMemo<V>(
|
|
148
|
+
slot: DetectMemoSlot<V>,
|
|
149
|
+
deriveKey: () => string | null,
|
|
150
|
+
compute: () => V,
|
|
151
|
+
): V {
|
|
152
|
+
const key = deriveKey();
|
|
153
|
+
const cached = key !== null ? slot.get(key) : null;
|
|
154
|
+
if (cached !== null) return cached;
|
|
155
|
+
const value = compute();
|
|
156
|
+
if (key !== null) slot.set(key, value);
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// Mutable-input cache-key derivations.
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
/** Resolve the first PATH entry for a binary, or null when absent. */
|
|
165
|
+
function whichBin(bin: string): string | null {
|
|
166
|
+
const r = spawnSync("which", [bin], {
|
|
167
|
+
timeout: 3000,
|
|
168
|
+
encoding: "utf-8",
|
|
169
|
+
// guardrails-allow PREVENT-PI-004: local which lookup only
|
|
170
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
171
|
+
});
|
|
172
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
173
|
+
const first = r.stdout.trim().split("\n")[0]?.trim();
|
|
174
|
+
return first && first.length > 0 ? first : null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Key = resolved path + size + mtimeMs, so an install/upgrade invalidates. */
|
|
178
|
+
function fileKey(p: string | null): string | null {
|
|
179
|
+
if (p === null || p.length === 0) return null;
|
|
180
|
+
try {
|
|
181
|
+
const s = statSync(p);
|
|
182
|
+
return `${p}:${s.size}:${s.mtimeMs}`;
|
|
183
|
+
} catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Key = resolved module path + its package.json mtime (node_modules rebuild). */
|
|
189
|
+
function moduleKey(packageName: string): string | null {
|
|
190
|
+
try {
|
|
191
|
+
const req = createRequire(import.meta.url);
|
|
192
|
+
const resolved = req.resolve(packageName + "/package.json");
|
|
193
|
+
return fileKey(resolved);
|
|
194
|
+
} catch {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
// Memoized wrappers (shared module-level slots across requests).
|
|
201
|
+
// ---------------------------------------------------------------------------
|
|
202
|
+
|
|
203
|
+
const ollamaSlot = createDetectMemo<OllamaDetectResult | null>();
|
|
204
|
+
const llamaSlot = createDetectMemo<DetectResult | null>();
|
|
205
|
+
const onnxSlot = createDetectMemo<DetectResult | null>();
|
|
206
|
+
|
|
207
|
+
const ollamaKey = (): string | null => fileKey(whichBin("ollama"));
|
|
208
|
+
const llamaKey = (): string | null => fileKey(whichBin("llama-server") ?? whichBin("llama.cpp"));
|
|
209
|
+
const onnxKey = (): string | null => moduleKey("onnxruntime-node");
|
|
210
|
+
|
|
211
|
+
export function memoizedDetectOllama(): OllamaDetectResult | null {
|
|
212
|
+
// guardrails-allow PREVENT-PI-004: local subprocess detection only
|
|
213
|
+
return withDetectMemo(ollamaSlot, ollamaKey, detectOllama);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function memoizedDetectLlamaCpp(): DetectResult | null {
|
|
217
|
+
// guardrails-allow PREVENT-PI-004: local subprocess detection only
|
|
218
|
+
return withDetectMemo(llamaSlot, llamaKey, detectLlamaCpp);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export function memoizedDetectOnnx(): DetectResult | null {
|
|
222
|
+
// guardrails-allow PREVENT-PI-004: local module resolution only
|
|
223
|
+
return withDetectMemo(onnxSlot, onnxKey, detectOnnx);
|
|
224
|
+
}
|
|
@@ -9,12 +9,19 @@
|
|
|
9
9
|
* Each decoration line carries a guardrails-allow annotation.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { spawnSync } from "node:child_process"; // guardrails-allow PREVENT-PI-004: local subprocess detection only
|
|
13
|
-
import { createRequire } from "node:module";
|
|
14
12
|
import { writeFileSync, mkdirSync, readFileSync, existsSync } from "node:fs";
|
|
15
13
|
import { join } from "node:path";
|
|
16
14
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
17
15
|
import type { RouteContext } from "./routes-core.js";
|
|
16
|
+
import { VC9D_ENABLED } from "../../src/config.js";
|
|
17
|
+
import {
|
|
18
|
+
detectOllama,
|
|
19
|
+
detectLlamaCpp,
|
|
20
|
+
detectOnnx,
|
|
21
|
+
memoizedDetectOllama,
|
|
22
|
+
memoizedDetectLlamaCpp,
|
|
23
|
+
memoizedDetectOnnx,
|
|
24
|
+
} from "./routes-setup-detect-cache.js";
|
|
18
25
|
import type {
|
|
19
26
|
SetupStatusResponse,
|
|
20
27
|
SetupDetectResponse,
|
|
@@ -91,80 +98,10 @@ export function handleSetupStatus(
|
|
|
91
98
|
// handleSetupDetect — "/api/setup-detect"
|
|
92
99
|
// ---------------------------------------------------------------------------
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
encoding: "utf-8",
|
|
99
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
100
|
-
});
|
|
101
|
-
if (version.status !== 0) {
|
|
102
|
-
return { installed: false, models: [], running: false, detail: version.stderr?.trim() || "not found" };
|
|
103
|
-
}
|
|
104
|
-
// Check for running server
|
|
105
|
-
let running = false;
|
|
106
|
-
let models: string[] = [];
|
|
107
|
-
try {
|
|
108
|
-
const listResult = spawnSync("ollama", ["list"], {
|
|
109
|
-
timeout: 5000,
|
|
110
|
-
encoding: "utf-8",
|
|
111
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
-
});
|
|
113
|
-
if (listResult.status === 0) {
|
|
114
|
-
running = true;
|
|
115
|
-
// Parse lines: NAME ID SIZE MODIFIED
|
|
116
|
-
const lines = listResult.stdout?.split("\n") ?? [];
|
|
117
|
-
for (const line of lines) {
|
|
118
|
-
const name = line.split(/\s+/)[0];
|
|
119
|
-
if (name && name !== "NAME") models.push(name);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
// ollama list failed — server may not be running
|
|
124
|
-
running = false;
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
installed: true,
|
|
128
|
-
models,
|
|
129
|
-
running,
|
|
130
|
-
detail: version.stdout?.trim() || null,
|
|
131
|
-
};
|
|
132
|
-
} catch {
|
|
133
|
-
return { installed: false, models: [], running: false, detail: "detection error" };
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function detectLlamaCpp(): DetectResult | null {
|
|
138
|
-
try {
|
|
139
|
-
const which = spawnSync("which", ["llama-server", "llama.cpp"], {
|
|
140
|
-
timeout: 3000,
|
|
141
|
-
encoding: "utf-8",
|
|
142
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
143
|
-
});
|
|
144
|
-
const installed = which.status === 0 && which.stdout.trim().length > 0;
|
|
145
|
-
return {
|
|
146
|
-
installed,
|
|
147
|
-
detail: installed ? which.stdout.trim() : null,
|
|
148
|
-
};
|
|
149
|
-
} catch {
|
|
150
|
-
return { installed: false, detail: "detection error" };
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function detectOnnx(): DetectResult | null {
|
|
155
|
-
try {
|
|
156
|
-
// Check for onnxruntime-node in a parent node_modules
|
|
157
|
-
const req = createRequire(import.meta.url);
|
|
158
|
-
try {
|
|
159
|
-
req.resolve("onnxruntime-node");
|
|
160
|
-
return { installed: true, detail: "onnxruntime-node found in node_modules" };
|
|
161
|
-
} catch {
|
|
162
|
-
return { installed: false, detail: "onnxruntime-node not found in node_modules" };
|
|
163
|
-
}
|
|
164
|
-
} catch {
|
|
165
|
-
return { installed: false, detail: "detection error" };
|
|
166
|
-
}
|
|
167
|
-
}
|
|
101
|
+
// Detection bodies live in routes-setup-detect-cache.ts (single source). When
|
|
102
|
+
// MEGACOMPACT_VC9D is ON the memoized wrappers reuse the result across requests
|
|
103
|
+
// (keyed by the mutable input: resolved binary path + mtime); when OFF we call
|
|
104
|
+
// the raw fresh detectors — byte-identical to the VC9C-era per-request spawn.
|
|
168
105
|
|
|
169
106
|
export function handleSetupDetect(
|
|
170
107
|
req: IncomingMessage,
|
|
@@ -183,20 +120,23 @@ export function handleSetupDetect(
|
|
|
183
120
|
let llamaCpp: DetectResult | null = null;
|
|
184
121
|
let onnx: DetectResult | null = null;
|
|
185
122
|
|
|
123
|
+
// guardrails-allow PREVENT-PI-004: local subprocess detection only (memoized or fresh)
|
|
124
|
+
const cached = VC9D_ENABLED();
|
|
125
|
+
|
|
186
126
|
try {
|
|
187
|
-
ollama = detectOllama();
|
|
127
|
+
ollama = cached ? memoizedDetectOllama() : detectOllama();
|
|
188
128
|
} catch (e) {
|
|
189
129
|
error = `ollama detection failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
190
130
|
}
|
|
191
131
|
|
|
192
132
|
try {
|
|
193
|
-
llamaCpp = detectLlamaCpp();
|
|
133
|
+
llamaCpp = cached ? memoizedDetectLlamaCpp() : detectLlamaCpp();
|
|
194
134
|
} catch (e) {
|
|
195
135
|
error = error ?? `llama.cpp detection failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
196
136
|
}
|
|
197
137
|
|
|
198
138
|
try {
|
|
199
|
-
onnx = detectOnnx();
|
|
139
|
+
onnx = cached ? memoizedDetectOnnx() : detectOnnx();
|
|
200
140
|
} catch (e) {
|
|
201
141
|
error = error ?? `onnx detection failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
202
142
|
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mega-config-types.ts — MegaConfig type-only declarations for the extension.
|
|
3
|
+
*
|
|
4
|
+
* Split out of mega-config.ts (delegate-shell) so the runtime barrel stays under
|
|
5
|
+
* the extensions/ soft line limit. Type-only file: no runtime code, no logic.
|
|
6
|
+
* `import type` keeps the only cross-reference (CompactTier) erased at build,
|
|
7
|
+
* so there is no runtime import cycle.
|
|
8
|
+
*/
|
|
9
|
+
import type { CompactTier } from "./mega-config.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resolved, frozen-at-load config. `tier` is the base compaction PRESET chosen
|
|
13
|
+
* by env (low/medium/high/ultra/mega) — it sets the threshold token budget and
|
|
14
|
+
* is NOT changed at runtime (the /mega-tier command was removed in S24). The
|
|
15
|
+
* *displayed* tier the user sees in the toolbar/dashboard is the LIVE pressure
|
|
16
|
+
* band (see MegaRuntime.pressureBand), which climbs low→mega as context fills.
|
|
17
|
+
*/
|
|
18
|
+
export interface MegaConfig {
|
|
19
|
+
tier: CompactTier | "custom";
|
|
20
|
+
/**
|
|
21
|
+
* Compaction threshold as a fraction of the model context window (e.g. 0.70
|
|
22
|
+
* for "high"). null for `custom` (explicit MEGACOMPACT_THRESHOLD_TOKENS, which
|
|
23
|
+
* stays an ABSOLUTE token count, never percent-scaled).
|
|
24
|
+
*/
|
|
25
|
+
tierPct: number | null;
|
|
26
|
+
thresholdTokens: number;
|
|
27
|
+
stateDir: string;
|
|
28
|
+
fastGatePct: number;
|
|
29
|
+
anchorUserMessages: number;
|
|
30
|
+
preserveRecent: number;
|
|
31
|
+
/** High-pressure floor for preserveRecent — when context is near the limit
|
|
32
|
+
* we compact deeper, but never below this (keeps recent turns for coherence). */
|
|
33
|
+
preserveRecentMin: number;
|
|
34
|
+
/** D.1: minimum context-growth percentage delta before re-compacting instead of
|
|
35
|
+
* replaying the cached trim (Default 50). Set via MEGACOMPACT_RECOMPACT_PCT_DELTA.*/
|
|
36
|
+
recompactPctDelta: number;
|
|
37
|
+
auto: boolean;
|
|
38
|
+
autoInline: boolean;
|
|
39
|
+
autoInlineK: number;
|
|
40
|
+
/** S28: auto-continue the agent after a max-output-token length stop by
|
|
41
|
+
* reusing the existing S16 resume-nudge. Default true. Off = silent (the
|
|
42
|
+
* prior behavior). PREVENT-PI-003: restart via user-role sendUserMessage. */
|
|
43
|
+
autoContinueLengthStop: boolean;
|
|
44
|
+
/** S38: max retries for transient errors (5xx/429/network/max-output-token
|
|
45
|
+
* text that is NOT a length stopReason — S28 owns those). Default 5.
|
|
46
|
+
* `0` disables all transient retries (reverts to S28-only). */
|
|
47
|
+
autoRetryTransientMax: number;
|
|
48
|
+
/** S38: max retries for permanent errors (auth/config/malformed). Default 1.
|
|
49
|
+
* `0` disables permanent-error retries. */
|
|
50
|
+
autoRetryPermanentMax: number;
|
|
51
|
+
/** S38.5: strict race-guard — 30s cooldown + deferred ctx.compact() re-check
|
|
52
|
+
* (closes the first-race-in-burst window). Default true. `false` reverts to
|
|
53
|
+
* the v0.7.4 synchronous 10s-cooldown behavior. */
|
|
54
|
+
raceGuardStrict: boolean;
|
|
55
|
+
/** S38.6: max consecutive errors before circuit-breaker trips (stops retrying).
|
|
56
|
+
* Default 10. When `errorRetryCount` exceeds this across multiple turns,
|
|
57
|
+
* the extension stops retrying until a successful turn resets it. */
|
|
58
|
+
maxConsecutiveErrors: number;
|
|
59
|
+
/** S38.7: hard-stop switch — when true, ALL error retries are disabled.
|
|
60
|
+
* Default false. Set via env to force S28-only behavior (length-stop continues
|
|
61
|
+
* only). */
|
|
62
|
+
errorRetryHardStop: boolean;
|
|
63
|
+
/** R1 (retry redesign): base unit (ms) for errorRetryBackoffMs(count) pacing.
|
|
64
|
+
* The schedule is base, 2*base, 4*base, 6*base (cap) — so the default 5000
|
|
65
|
+
* yields 5s/10s/20s/30s. errorRetryUntil is now GATING (previously it was
|
|
66
|
+
* documented as non-gating); a nudge cannot fire before errorRetryUntil
|
|
67
|
+
* elapses. */
|
|
68
|
+
errorRetryBackoffMs: number;
|
|
69
|
+
/** R2: session-global cap on total S38 nudges across ALL bursts. Hitting it
|
|
70
|
+
* is terminal for the session — the extension stops nudging entirely,
|
|
71
|
+
* independent of the per-burst max and the circuit breaker. Default 3.
|
|
72
|
+
* `0` disables (reverts to per-burst + circuit-breaker only). */
|
|
73
|
+
errorRetrySessionMax: number;
|
|
74
|
+
/** R3: consecutive identical error-text count at which a 'transient'
|
|
75
|
+
* classification is upgraded to 'poisoned-context' (the stateful repeat
|
|
76
|
+
* signal). Default 3. Raise to make the upgrade less aggressive. */
|
|
77
|
+
poisonedContextRepeatThreshold: number;
|
|
78
|
+
/** R10: consecutive transient errors at which a calm "provider outage"
|
|
79
|
+
* advisory is sent to the user (distinct from the poisoned /clear advise).
|
|
80
|
+
* Default 3. `0` disables the advisory entirely. */
|
|
81
|
+
providerOutageAdviseThreshold: number;
|
|
82
|
+
/** R13: when true (default), poisoned-context and provider-outage advisories
|
|
83
|
+
* are dashboard-only (events tab + log) — no user-visible message injection.
|
|
84
|
+
* When false, the legacy sendUserMessage path runs (byte-identical pre-R13). */
|
|
85
|
+
advisoryChannel: boolean;
|
|
86
|
+
/** S29: override the auto-compact fire point for tiered configs, as a
|
|
87
|
+
* fraction of the context window (e.g. 0.85). null = inherit the tier's
|
|
88
|
+
* tierPct (default; preserves existing fire points). The context-handler
|
|
89
|
+
* gate fires on context % (reliable), not token count (under-reported),
|
|
90
|
+
* so it catches the overshoot that causes max-output-token truncation.
|
|
91
|
+
* `custom` (tierPct null) ignores this — it keeps the absolute token gate. */
|
|
92
|
+
autoPctTrigger: number | null;
|
|
93
|
+
dedupSim: number;
|
|
94
|
+
/** RAPTOR hierarchical recall enabled (Fix D). Drives both live recall and
|
|
95
|
+
* the durable-trim summary source (root summary). */
|
|
96
|
+
raptorEnabled: boolean;
|
|
97
|
+
/** Legacy v0.4.28 behavior: auto-trigger calls ctx.compact() (which STOPS
|
|
98
|
+
* the agent). Default false — the S16 redesign uses the live context-event
|
|
99
|
+
* trim + pi native auto-compaction instead (compact and continue). Kept for
|
|
100
|
+
* one release as rollback. */
|
|
101
|
+
legacyDurableTrim: boolean;
|
|
102
|
+
/** S27: durable raw-transcript DB mirror (MEGACOMPACT_DB_MIRROR). When on,
|
|
103
|
+
* raw message bytes + checkpoint-epoch bookkeeping are appended to the
|
|
104
|
+
* SQLite store so a compacted window can be rehydrated locally instead of
|
|
105
|
+
* from the pi runtime transcript. Default OFF — additive, no behavior
|
|
106
|
+
* change until flipped on. legacyDurableTrim takes precedence (the legacy
|
|
107
|
+
* v0.4.28 ctx.compact() path does not emit the S27 mirror hook). */
|
|
108
|
+
dbMirror: boolean;
|
|
109
|
+
/** S49: isolated per-turn store (turns.db). Default ON. OFF = legacy main-db
|
|
110
|
+
* turn path (S48 behavior — byte-identical). Mirrors TurnsConfig.TURNS_DB_ENABLED. */
|
|
111
|
+
turnsDbEnabled: boolean;
|
|
112
|
+
/** S51: auto-categorizing wiki (k-means + TF-IDF over real embeddings). Default ON.
|
|
113
|
+
* Mirrors TurnsConfig.AUTO_WIKI_ENABLED. Rebuild fires every Nth compaction. */
|
|
114
|
+
autoWikiEnabled: boolean;
|
|
115
|
+
/** Cross-repo recall enabled (S17). Resume + /mega-recall --cross-repo can
|
|
116
|
+
* pull checkpoints from OTHER repos via the PGlite HNSW index. Default true. */
|
|
117
|
+
crossRepoEnabled: boolean;
|
|
118
|
+
/** Stricter cosine floor for cross-repo hits (S17). Default 0.90 (trigram) /
|
|
119
|
+
* tighter than same-repo so only genuinely-relevant cross-repo context is
|
|
120
|
+
* injected. */
|
|
121
|
+
crossRepoCosine: number;
|
|
122
|
+
/** Memory-RAG auto-review enabled (S20). Every memoryReviewInterval turns the
|
|
123
|
+
* conversation is auto-reviewed into durable add/replace/remove memories. */
|
|
124
|
+
memoryAutoReview: boolean;
|
|
125
|
+
/** Turn cadence for the auto-review scan (S20). Default 10. */
|
|
126
|
+
memoryReviewInterval: number;
|
|
127
|
+
/** Token ceiling for the re-injected recall block (Fix C). Recall stops
|
|
128
|
+
* adding checkpoints once the block would exceed this — bounds read-path
|
|
129
|
+
* token cost so it can never net-inflate the window. */
|
|
130
|
+
recallMaxTokens: number;
|
|
131
|
+
/** Inline-dedupe recalled checkpoints against the live window (Fix C): drop
|
|
132
|
+
* a hit whose summary is ≥ dedupSim similar to a live message — "dedupe on
|
|
133
|
+
* inline/read" so we never re-inject context already resident. */
|
|
134
|
+
windowDedupe: boolean;
|
|
135
|
+
/** S53: Recall Tail Injection — inject staged recall block as a user message at
|
|
136
|
+
* the tail of the view when auto is OFF AND no trim action is needed. Default ON
|
|
137
|
+
* (true). When false, restores the pre-sprint systemPrompt prepend behavior. */
|
|
138
|
+
recallTailInject: boolean;
|
|
139
|
+
/** A1 PLAN_V2 Phase 2: Message Separation — isolate user/assistant turns
|
|
140
|
+
* from volatile tool results so the prompt-cache prefix stays stable.
|
|
141
|
+
* PC-A: positive sprint flag, now default ON; flag-OFF (=0) is byte-identical
|
|
142
|
+
* to the pre-change OFF state. The single gate lives at the call site
|
|
143
|
+
* (tailResult.ts, config.messageSeparation), not inside buildSeparatedPrompt. */
|
|
144
|
+
messageSeparation: boolean;
|
|
145
|
+
/** P3: Cache-aware striping (PLAN_V2 Phase 3). Inserts stability-ordered
|
|
146
|
+
* cache stripes between summaries and thread. Default OFF. */
|
|
147
|
+
cacheStriping: boolean;
|
|
148
|
+
debug: boolean;
|
|
149
|
+
/** Master reconciliation: TUI shutdown widget (MEGACOMPACT_TUI_WIDGET=0 to disable). */
|
|
150
|
+
tuiWidget: boolean;
|
|
151
|
+
/** S57 B1: Query reformulation via embedding-neighbor keyword expansion. */
|
|
152
|
+
ragQueryReformulation: boolean;
|
|
153
|
+
/** S57 B2: Tiered recall router (L0 cache -> L1 FTS5 -> L2). */
|
|
154
|
+
ragTieredRouter: boolean;
|
|
155
|
+
/** S57 B3: Recall quality metrics (precision/recall scoring + logging). */
|
|
156
|
+
ragRecallMetrics: boolean;
|
|
157
|
+
/** S57 B4: Memory graph traversal (dashboard-oriented). */
|
|
158
|
+
ragMemoryGraph: boolean;
|
|
159
|
+
/** D1: Seed initial wiki topic model from live turns when no context_chunks exist yet. */
|
|
160
|
+
wikiSeedFromTurns: boolean;
|
|
161
|
+
/** D3 Source A: Include structural turn nodes in the memory graph (metadata only, no content). */
|
|
162
|
+
memoryGraphSeedTurns: boolean;
|
|
163
|
+
/** D3 Source B: Include raw_transcript content nodes in the memory graph (requires dbMirror). */
|
|
164
|
+
memoryGraphSeedTurnContent: boolean;
|
|
165
|
+
/** D3 Source C: Include memory review nodes in the memory graph. */
|
|
166
|
+
memoryGraphSeedMemories: boolean;
|
|
167
|
+
/** D3 edges: Stricter cosine floor for cross-type edges (e.g. turn↔checkpoint). */
|
|
168
|
+
memoryGraphCrossTypeThreshold: number;
|
|
169
|
+
/** D3 edges: Cosine floor for within-type semantic edges. */
|
|
170
|
+
memoryGraphWithinTypeThreshold: number;
|
|
171
|
+
/** v0.12: Context health monitoring (drift + output quality + cache poison). Default ON. */
|
|
172
|
+
contextHealth: boolean;
|
|
173
|
+
/** Sub-flag: drift detection (topic drift + error escalation + prefix instability). */
|
|
174
|
+
contextHealthDrift: boolean;
|
|
175
|
+
/** Sub-flag: output quality analysis (repetition, coherence, token salad). */
|
|
176
|
+
contextHealthOutputQuality: boolean;
|
|
177
|
+
/** Sub-flag: tri-layer KV cache poison validation. */
|
|
178
|
+
contextHealthCachePoison: boolean;
|
|
179
|
+
/** v0.12: KV cache poison mitigation — inject prefix break on mismatch. Default OFF. */
|
|
180
|
+
contextHealthMitigate: boolean;
|
|
181
|
+
}
|