pi-mega-compact 0.20.22 → 0.20.23
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/extensions/dashboard-server/resolve-snapshot.js +42 -28
- package/dist/extensions/dashboard-server/routes-setup.js +4 -1
- package/dist/extensions/dashboard-server/routes-vector-cortex-crystals.js +11 -3
- package/dist/extensions/dashboard-server/routes-vector-cortex-diagnostics.js +7 -2
- package/dist/extensions/dashboard-server/routes-vector-cortex-economics.js +1 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-heal.js +18 -6
- package/dist/extensions/dashboard-server/routes-vector-cortex-policy.js +1 -0
- package/dist/extensions/dashboard-server/routes-vector-cortex-reconstruct.js +10 -3
- package/dist/extensions/dashboard-server/routes-vector-cortex-repair.js +13 -5
- package/dist/extensions/dashboard-server/routes-vector-cortex-shards.js +12 -4
- package/dist/extensions/dashboard-server/vc-event-counts.js +63 -0
- package/dist/extensions/mega-events/context-handler/afterCompact.js +34 -0
- package/dist/extensions/mega-events/context-handler/pipelineRun.js +33 -0
- package/dist/extensions/mega-runtime/dashboard-snapshot.js +9 -6
- package/dist/extensions/mega-runtime/runtime-snapshot.js +2 -0
- package/dist/extensions/mega-runtime/vc-observer.js +98 -0
- package/extensions/dashboard-client/dist/assets/{AreaChart-BkfB-LSQ.js → AreaChart-BzEedilo.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AreaChart-BkfB-LSQ.js.map → AreaChart-BzEedilo.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{BarChart-Cs1kogko.js → BarChart-CzAVg1_J.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{BarChart-Cs1kogko.js.map → BarChart-CzAVg1_J.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{CacheTab-BZgaguGr.js → CacheTab-D2-rzTuX.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{CacheTab-BZgaguGr.js.map → CacheTab-D2-rzTuX.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-BFbkI_MO.js → EventsTab-DB7g1Szy.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-BFbkI_MO.js.map → EventsTab-DB7g1Szy.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{HealthTab-CvlOENCX.js → HealthTab-Cvkmi-R3.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{HealthTab-CvlOENCX.js.map → HealthTab-Cvkmi-R3.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CtBuz2qL.js → MaintenanceTab-g_udcOO7.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-CtBuz2qL.js.map → MaintenanceTab-g_udcOO7.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-K4775S4d.js → MemoryMapTab-DAjBaf8P.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MemoryMapTab-K4775S4d.js.map → MemoryMapTab-DAjBaf8P.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DVGcFInz.js → MetricsTab-13dYYocB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-DVGcFInz.js.map → MetricsTab-13dYYocB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{OverviewTab-4LmW5ZCl.js → OverviewTab-CLpCyLvx.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{OverviewTab-4LmW5ZCl.js.map → OverviewTab-CLpCyLvx.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{ReposTab-StebchgQ.js → ReposTab-EdAqUrwG.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ReposTab-StebchgQ.js.map → ReposTab-EdAqUrwG.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C3D_XAkX.js → SessionsTab-C21ZuOL_.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-C3D_XAkX.js.map → SessionsTab-C21ZuOL_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-CP7lE3L_.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-CP7lE3L_.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CTPi_AAW.js → TimeSavedCard-DZ3QR8qt.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TimeSavedCard-CTPi_AAW.js.map → TimeSavedCard-DZ3QR8qt.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DSOGcY5Q.js → TurnsTab-CNchE5rD.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DSOGcY5Q.js.map → TurnsTab-CNchE5rD.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-OMW8_RFf.js → VectorCortexTab-B3WuPeyn.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{VectorCortexTab-OMW8_RFf.js.map → VectorCortexTab-B3WuPeyn.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{WikiTab-Db-qFDdg.js → WikiTab-BIe5Z9Nc.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{WikiTab-Db-qFDdg.js.map → WikiTab-BIe5Z9Nc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{button-BF4UgBAD.js → button-BrVreSt5.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{button-BF4UgBAD.js.map → button-BrVreSt5.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{card-XmXoYQqB.js → card-D9F4wbqs.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{card-XmXoYQqB.js.map → card-D9F4wbqs.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Be8hM1aU.js → generateCategoricalChart-mkdzCnMP.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{generateCategoricalChart-Be8hM1aU.js.map → generateCategoricalChart-mkdzCnMP.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{index-NXDgILxv.js → index-CtlmOlj1.js} +3 -3
- package/extensions/dashboard-client/dist/assets/{index-NXDgILxv.js.map → index-CtlmOlj1.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{switch-kUZCrbia.js → switch-BXmp5iwA.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{switch-kUZCrbia.js.map → switch-BXmp5iwA.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{toggle-DEe5mCwF.js → toggle-BgawNwW9.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{toggle-DEe5mCwF.js.map → toggle-BgawNwW9.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{useSSE-BlCyLqge.js → useSSE-DZKX73Ea.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BlCyLqge.js.map → useSSE-DZKX73Ea.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/tabs/SetupTab/CustomEndpointSection.tsx +65 -0
- package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetup.tsx +19 -108
- package/extensions/dashboard-client/src/tabs/SetupTab/EmbedderSetupStyles.ts +69 -0
- package/extensions/dashboard-client/src/tabs/VectorCortexTab.tsx +5 -3
- package/extensions/dashboard-server/api-contracts/setup.ts +4 -3
- package/extensions/dashboard-server/api-contracts/vector-cortex-cache.ts +5 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-diagnostics.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-economics.ts +2 -0
- package/extensions/dashboard-server/api-contracts/vector-cortex-policy.ts +2 -0
- package/extensions/dashboard-server/resolve-snapshot.ts +42 -28
- package/extensions/dashboard-server/routes-setup.ts +3 -1
- package/extensions/dashboard-server/routes-vector-cortex-crystals.ts +12 -3
- package/extensions/dashboard-server/routes-vector-cortex-diagnostics.ts +8 -2
- package/extensions/dashboard-server/routes-vector-cortex-economics.ts +1 -0
- package/extensions/dashboard-server/routes-vector-cortex-heal.ts +19 -6
- package/extensions/dashboard-server/routes-vector-cortex-policy.ts +1 -0
- package/extensions/dashboard-server/routes-vector-cortex-reconstruct.ts +11 -3
- package/extensions/dashboard-server/routes-vector-cortex-repair.ts +14 -5
- package/extensions/dashboard-server/routes-vector-cortex-shards.ts +13 -4
- package/extensions/dashboard-server/vc-event-counts.ts +67 -0
- package/extensions/mega-dashboard.ts +2 -0
- package/extensions/mega-events/context-handler/afterCompact.ts +46 -0
- package/extensions/mega-events/context-handler/pipelineRun.ts +39 -0
- package/extensions/mega-runtime/dashboard-snapshot.ts +12 -6
- package/extensions/mega-runtime/runtime-snapshot.ts +6 -0
- package/extensions/mega-runtime/vc-observer.ts +120 -0
- package/package.json +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-BTBGyppF.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-BTBGyppF.js.map +0 -1
|
@@ -8,16 +8,14 @@
|
|
|
8
8
|
* Resolution order (the launch dir is the OWNer of this dashboard):
|
|
9
9
|
* 1. The launch stateDir's OWN dashboard.json — the pi process that launched
|
|
10
10
|
* this dashboard server is the session you are coding in, so its snapshot
|
|
11
|
-
* is "this session" by definition.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* the launch dir has no live snapshot yet (e.g. dashboard launched before
|
|
20
|
-
* any compaction wrote dashboard.json).
|
|
11
|
+
* is "this session" by definition. It must be fresh (updatedAt within
|
|
12
|
+
* STALE_MS) to win; otherwise the launch dir's pi process has exited or
|
|
13
|
+
* stopped snapshotting, and showing its stale data as "this session" is
|
|
14
|
+
* misleading. When stale, fall through to the most-recently-active repo.
|
|
15
|
+
* 2. Most recently seen repo (by last_seen in repo_registry) whose
|
|
16
|
+
* dashboard.json exists and has a non-null updatedAt — this includes the
|
|
17
|
+
* launch dir via the registry, so an exited-but-recent launch session
|
|
18
|
+
* still appears.
|
|
21
19
|
* 3. The static launch stateDir's dashboard.json (original behavior).
|
|
22
20
|
*/
|
|
23
21
|
import { existsSync } from "node:fs";
|
|
@@ -25,14 +23,29 @@ import { join } from "node:path";
|
|
|
25
23
|
import { createRequire } from "node:module";
|
|
26
24
|
import { readSnapshot } from "./snapshot.js";
|
|
27
25
|
import { getIndexDir } from "./index-reader.js";
|
|
26
|
+
/** Snapshots older than this are stale — the owning pi session has exited or
|
|
27
|
+
* stopped snapshotting. 5 minutes covers the slowest possible context event
|
|
28
|
+
* cadence + debounce + snapshot throttle. */
|
|
29
|
+
const STALE_MS = 5 * 60 * 1000;
|
|
30
|
+
/** Age of a snapshot's updatedAt in ms. Returns Infinity for invalid dates. */
|
|
31
|
+
function snapshotAgeMs(updatedAt) {
|
|
32
|
+
if (!updatedAt)
|
|
33
|
+
return Infinity;
|
|
34
|
+
const t = Date.parse(updatedAt);
|
|
35
|
+
if (Number.isNaN(t))
|
|
36
|
+
return Infinity;
|
|
37
|
+
return Date.now() - t;
|
|
38
|
+
}
|
|
28
39
|
const require = createRequire(import.meta.url);
|
|
29
40
|
/**
|
|
30
|
-
* Find the most recently active
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
41
|
+
* Find the most recently active repo's stateDir by scanning the repo registry
|
|
42
|
+
* for the repo with the highest last_seen whose dashboard.json exists and has
|
|
43
|
+
* a non-null updatedAt. Unlike the old `mostRecentOtherRepoStateDir`, this
|
|
44
|
+
* does NOT exclude the launch dir — when the launch dir's snapshot is stale
|
|
45
|
+
* but its registry entry has a recent last_seen (e.g. session just exited),
|
|
46
|
+
* it should still be eligible.
|
|
34
47
|
*/
|
|
35
|
-
function
|
|
48
|
+
function mostRecentActiveRepoStateDir(_launchStateDir) {
|
|
36
49
|
const indexPath = join(getIndexDir(), "index.sqlite");
|
|
37
50
|
if (!existsSync(indexPath))
|
|
38
51
|
return null;
|
|
@@ -43,9 +56,8 @@ function mostRecentOtherRepoStateDir(launchStateDir) {
|
|
|
43
56
|
const rows = db
|
|
44
57
|
.prepare(`SELECT state_dir, last_seen FROM repo_registry
|
|
45
58
|
WHERE state_dir IS NOT NULL AND last_seen IS NOT NULL
|
|
46
|
-
AND state_dir != @launch
|
|
47
59
|
ORDER BY last_seen DESC`)
|
|
48
|
-
.all(
|
|
60
|
+
.all();
|
|
49
61
|
for (const r of rows) {
|
|
50
62
|
const dashPath = join(r.state_dir, "dashboard.json");
|
|
51
63
|
if (!existsSync(dashPath))
|
|
@@ -70,24 +82,26 @@ function mostRecentOtherRepoStateDir(launchStateDir) {
|
|
|
70
82
|
}
|
|
71
83
|
}
|
|
72
84
|
/**
|
|
73
|
-
* Resolve the best snapshot to serve.
|
|
74
|
-
*
|
|
85
|
+
* Resolve the best snapshot to serve. The launch dir wins when its snapshot is
|
|
86
|
+
* fresh; when stale (or missing) the most recently active repo wins instead.
|
|
75
87
|
*/
|
|
76
88
|
export function resolveSnapshot(staticSnapshotPath, staticStateDir) {
|
|
77
|
-
// 1. The launch dir's OWN snapshot is "this session" —
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
89
|
+
// 1. The launch dir's OWN snapshot is "this session" — but only when it's
|
|
90
|
+
// fresh (updated within STALE_MS). A stale launch-dir snapshot means
|
|
91
|
+
// the pi process that owned it has exited or stopped snapshotting; serving
|
|
92
|
+
// its frozen data as "this session" is misleading. Fall through to the
|
|
93
|
+
// most-recently-active repo so the user sees the session that is actually
|
|
94
|
+
// running.
|
|
82
95
|
if (existsSync(staticSnapshotPath)) {
|
|
83
96
|
const launchSnap = readSnapshot(staticSnapshotPath);
|
|
84
|
-
if (launchSnap.updatedAt) {
|
|
97
|
+
if (launchSnap.updatedAt && snapshotAgeMs(launchSnap.updatedAt) < STALE_MS) {
|
|
85
98
|
return { snapshot: launchSnap, stateDir: staticStateDir };
|
|
86
99
|
}
|
|
87
100
|
}
|
|
88
|
-
// 2. Fall back to the most recently active OTHER repo (launch dir
|
|
89
|
-
// live snapshot yet).
|
|
90
|
-
|
|
101
|
+
// 2. Fall back to the most recently active OTHER repo (launch dir stale or
|
|
102
|
+
// had no live snapshot yet). The registry includes the launch dir too,
|
|
103
|
+
// so a recently-exited launch session can still appear.
|
|
104
|
+
const activeDir = mostRecentActiveRepoStateDir(staticStateDir);
|
|
91
105
|
if (activeDir) {
|
|
92
106
|
const activePath = join(activeDir, "dashboard.json");
|
|
93
107
|
const snap = readSnapshot(activePath);
|
|
@@ -193,6 +193,7 @@ export function handleSetupDetect(req, res, _ctx) {
|
|
|
193
193
|
// ---------------------------------------------------------------------------
|
|
194
194
|
const OLLAMA_DEFAULT_URL = "http://localhost:11434/api/embeddings"; // guardrails-allow PREVENT-PI-004: localhost-only config string, not a runtime fetch
|
|
195
195
|
const LLAMA_DEFAULT_URL = "http://localhost:8080/v1/embeddings"; // guardrails-allow PREVENT-PI-004: localhost-only config string, not a runtime fetch
|
|
196
|
+
const ONNX_DEFAULT_URL = "http://localhost:8081/v1/embeddings"; // guardrails-allow PREVENT-PI-004: localhost-only config string, not a runtime fetch — TEI / ONNX embedding server
|
|
196
197
|
function readJsonBody(req, cb) {
|
|
197
198
|
let body = "";
|
|
198
199
|
let tooBig = false;
|
|
@@ -237,7 +238,7 @@ export function handleSetupConfigure(req, res, ctx) {
|
|
|
237
238
|
}
|
|
238
239
|
const body = parsed.value;
|
|
239
240
|
const embedder = body.embedder;
|
|
240
|
-
if (embedder !== "ollama" && embedder !== "llama" && embedder !== "trigram" && embedder !== "custom") {
|
|
241
|
+
if (embedder !== "ollama" && embedder !== "llama" && embedder !== "trigram" && embedder !== "custom" && embedder !== "onnx") {
|
|
241
242
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
242
243
|
res.end(JSON.stringify({ error: "invalid_embedder" }));
|
|
243
244
|
return;
|
|
@@ -249,6 +250,8 @@ export function handleSetupConfigure(req, res, ctx) {
|
|
|
249
250
|
resolvedUrl = typeof url === "string" && url ? url : OLLAMA_DEFAULT_URL;
|
|
250
251
|
else if (embedder === "llama")
|
|
251
252
|
resolvedUrl = typeof url === "string" && url ? url : LLAMA_DEFAULT_URL;
|
|
253
|
+
else if (embedder === "onnx")
|
|
254
|
+
resolvedUrl = typeof url === "string" && url ? url : ONNX_DEFAULT_URL;
|
|
252
255
|
else if (embedder === "custom") {
|
|
253
256
|
// Third-party / remote endpoint. Requires a URL; opts in to the
|
|
254
257
|
// non-loopback allowlist so embeddingConfigFromEnv() accepts it.
|
|
@@ -25,13 +25,19 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { VC7A_ENABLED } from "../../src/config.js";
|
|
27
27
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
28
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
29
|
+
// Actual events emitted by src/vector-cortex/cache/crystal-emit.ts.
|
|
30
|
+
const CRYSTAL_EVENTS = [
|
|
31
|
+
"vector_cortex_crystal_written",
|
|
32
|
+
"vector_cortex_crystal_collision",
|
|
33
|
+
];
|
|
28
34
|
/**
|
|
29
35
|
* Reader-only GET /api/vector-cortex/cache-crystals (VC7A).
|
|
30
36
|
*
|
|
31
37
|
* Counts, byte volumes, and CRY_* codes only — a static reader-only aggregate
|
|
32
38
|
* seam with the same shape as the VC6A/VC6B/VC6C handlers.
|
|
33
39
|
*/
|
|
34
|
-
export function handleVectorCortexCrystals(req, res,
|
|
40
|
+
export function handleVectorCortexCrystals(req, res, ctx) {
|
|
35
41
|
const url = req.url ?? "";
|
|
36
42
|
const path = url.split("?")[0] ?? url;
|
|
37
43
|
if (path !== "/api/vector-cortex/cache-crystals")
|
|
@@ -41,6 +47,7 @@ export function handleVectorCortexCrystals(req, res, _ctx) {
|
|
|
41
47
|
return true;
|
|
42
48
|
}
|
|
43
49
|
const enabled = VC7A_ENABLED();
|
|
50
|
+
const counts = countVcEvents(ctx.stateDir, CRYSTAL_EVENTS);
|
|
44
51
|
// Flag-off routes to mode C: with VC7A off nothing is served from the crystal
|
|
45
52
|
// cache, which is exactly the spec's "cache bypass" outcome. Reporting A (hit)
|
|
46
53
|
// or B (fresh render forced by a miss) would imply a cache path that is not
|
|
@@ -49,16 +56,17 @@ export function handleVectorCortexCrystals(req, res, _ctx) {
|
|
|
49
56
|
const body = {
|
|
50
57
|
enabled,
|
|
51
58
|
mode,
|
|
52
|
-
crystalCount:
|
|
59
|
+
crystalCount: vcCount(counts, "vector_cortex_crystal_written"),
|
|
53
60
|
totalBytes: 0,
|
|
54
61
|
hits: 0,
|
|
55
62
|
misses: 0,
|
|
56
63
|
hitBytes: 0,
|
|
57
64
|
writes: 0,
|
|
58
65
|
duplicateWrites: 0,
|
|
59
|
-
collisions:
|
|
66
|
+
collisions: vcCount(counts, "vector_cortex_crystal_collision"),
|
|
60
67
|
lastFailure: null,
|
|
61
68
|
updatedAt: new Date().toISOString(),
|
|
69
|
+
deferredReason: "crystal_store_not_instantiated_v0_20_23",
|
|
62
70
|
};
|
|
63
71
|
sendJson(res, 200, body);
|
|
64
72
|
return true;
|
|
@@ -27,13 +27,16 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { VC7C_ENABLED } from "../../src/config.js";
|
|
29
29
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
30
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
31
|
+
// Actual events emitted by src/vector-cortex/cache/diagnostics-emit.ts.
|
|
32
|
+
const DIAGNOSTICS_EVENTS = ["vector_cortex_cache_serve_blocked"];
|
|
30
33
|
/**
|
|
31
34
|
* Reader-only GET /api/vector-cortex/cache-diagnostics (VC7C).
|
|
32
35
|
*
|
|
33
36
|
* Per-miss-class counts, breaker state, and CACHE and M5 codes only — a static
|
|
34
37
|
* reader-only aggregate seam with the same shape as the VC7B economics handler.
|
|
35
38
|
*/
|
|
36
|
-
export function handleVectorCortexDiagnostics(req, res,
|
|
39
|
+
export function handleVectorCortexDiagnostics(req, res, ctx) {
|
|
37
40
|
const url = req.url ?? "";
|
|
38
41
|
const path = url.split("?")[0] ?? url;
|
|
39
42
|
if (path !== "/api/vector-cortex/cache-diagnostics")
|
|
@@ -43,6 +46,7 @@ export function handleVectorCortexDiagnostics(req, res, _ctx) {
|
|
|
43
46
|
return true;
|
|
44
47
|
}
|
|
45
48
|
const enabled = VC7C_ENABLED();
|
|
49
|
+
const counts = countVcEvents(ctx.stateDir, DIAGNOSTICS_EVENTS);
|
|
46
50
|
// Flag-off routes to mode C: with VC7C off the diagnostics/breaker reporter is
|
|
47
51
|
// suppressed, so no cache serve is attested here and the surface reports the
|
|
48
52
|
// all-cache bypass outcome. Reporting A (crystal served) or B (fresh render
|
|
@@ -58,10 +62,11 @@ export function handleVectorCortexDiagnostics(req, res, _ctx) {
|
|
|
58
62
|
requestMisses: 0,
|
|
59
63
|
generationMisses: 0,
|
|
60
64
|
unknownMisses: 0,
|
|
61
|
-
serveBlocked:
|
|
65
|
+
serveBlocked: vcCount(counts, "vector_cortex_cache_serve_blocked"),
|
|
62
66
|
breakerState: "closed",
|
|
63
67
|
lastFailure: null,
|
|
64
68
|
updatedAt: new Date().toISOString(),
|
|
69
|
+
deferredReason: "cache_classifier_not_wired_v0_20_23",
|
|
65
70
|
};
|
|
66
71
|
sendJson(res, 200, body);
|
|
67
72
|
return true;
|
|
@@ -21,8 +21,18 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { VC6A_ENABLED, VC6B_ENABLED } from "../../src/config.js";
|
|
23
23
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
24
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
25
|
+
// Actual event names emitted by src/vector-cortex/heal/emit.ts + restore-emit.ts.
|
|
26
|
+
const CLOSURE_EVENTS = [
|
|
27
|
+
"vector_cortex_closure_optimized",
|
|
28
|
+
"vector_cortex_closure_proof_rejected",
|
|
29
|
+
];
|
|
30
|
+
const RESTORE_EVENTS = [
|
|
31
|
+
"vector_cortex_source_restored",
|
|
32
|
+
"vector_cortex_restore_digest_rejected",
|
|
33
|
+
];
|
|
24
34
|
/** Reader-only GET /api/vector-cortex/closure-proof (VC6A). */
|
|
25
|
-
export function handleVectorCortexClosureProof(req, res,
|
|
35
|
+
export function handleVectorCortexClosureProof(req, res, ctx) {
|
|
26
36
|
const url = req.url ?? "";
|
|
27
37
|
const path = url.split("?")[0] ?? url;
|
|
28
38
|
if (path !== "/api/vector-cortex/closure-proof")
|
|
@@ -32,13 +42,14 @@ export function handleVectorCortexClosureProof(req, res, _ctx) {
|
|
|
32
42
|
return true;
|
|
33
43
|
}
|
|
34
44
|
const enabled = VC6A_ENABLED();
|
|
45
|
+
const counts = countVcEvents(ctx.stateDir, CLOSURE_EVENTS);
|
|
35
46
|
// Flag-off routes to mode B (conservative closure, no reduction) per spec.
|
|
36
47
|
const mode = enabled ? "A" : "B";
|
|
37
48
|
const body = {
|
|
38
49
|
enabled,
|
|
39
50
|
mode,
|
|
40
|
-
optimizations:
|
|
41
|
-
proofRejections:
|
|
51
|
+
optimizations: vcCount(counts, "vector_cortex_closure_optimized"),
|
|
52
|
+
proofRejections: vcCount(counts, "vector_cortex_closure_proof_rejected"),
|
|
42
53
|
retainedEdgeTotal: 0,
|
|
43
54
|
removedEdgeTotal: 0,
|
|
44
55
|
conservativeTraversalTotal: 0,
|
|
@@ -56,7 +67,7 @@ export function handleVectorCortexClosureProof(req, res, _ctx) {
|
|
|
56
67
|
* seam (same shape as the VC6A handler): there is no payload endpoint and never
|
|
57
68
|
* will be, so no restored bytes/span ids/node ids/ledger text can leak here.
|
|
58
69
|
*/
|
|
59
|
-
export function handleVectorCortexRestore(req, res,
|
|
70
|
+
export function handleVectorCortexRestore(req, res, ctx) {
|
|
60
71
|
const url = req.url ?? "";
|
|
61
72
|
const path = url.split("?")[0] ?? url;
|
|
62
73
|
if (path !== "/api/vector-cortex/restore")
|
|
@@ -66,6 +77,7 @@ export function handleVectorCortexRestore(req, res, _ctx) {
|
|
|
66
77
|
return true;
|
|
67
78
|
}
|
|
68
79
|
const enabled = VC6B_ENABLED();
|
|
80
|
+
const counts = countVcEvents(ctx.stateDir, RESTORE_EVENTS);
|
|
69
81
|
// Flag-off routes to mode C: with VC6B off there is no exact-restoration path
|
|
70
82
|
// at all, so the honest OFF view is the disclose-loss mode (old context is
|
|
71
83
|
// omitted rather than inferred) — mirroring how VC6A's OFF view reports the
|
|
@@ -74,10 +86,10 @@ export function handleVectorCortexRestore(req, res, _ctx) {
|
|
|
74
86
|
const body = {
|
|
75
87
|
enabled,
|
|
76
88
|
mode,
|
|
77
|
-
restoreAttempts:
|
|
89
|
+
restoreAttempts: vcCount(counts, "vector_cortex_source_restored"),
|
|
78
90
|
restoredCount: 0,
|
|
79
91
|
missingCount: 0,
|
|
80
|
-
digestRejections:
|
|
92
|
+
digestRejections: vcCount(counts, "vector_cortex_restore_digest_rejected"),
|
|
81
93
|
lastRejection: null,
|
|
82
94
|
updatedAt: new Date().toISOString(),
|
|
83
95
|
};
|
|
@@ -8,7 +8,13 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { VC4C_ENABLED } from "../../src/config.js";
|
|
10
10
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
11
|
-
|
|
11
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
12
|
+
// Closure attempt/rejection events emitted by src/vector-cortex/heal/emit.ts.
|
|
13
|
+
const RECONSTRUCT_EVENTS = [
|
|
14
|
+
"vector_cortex_closure_optimized",
|
|
15
|
+
"vector_cortex_closure_proof_rejected",
|
|
16
|
+
];
|
|
17
|
+
export function handleVectorCortexReconstruct(req, res, ctx) {
|
|
12
18
|
const url = req.url ?? "";
|
|
13
19
|
const path = url.split("?")[0] ?? url;
|
|
14
20
|
if (path !== "/api/vector-cortex/reconstruct")
|
|
@@ -18,10 +24,11 @@ export function handleVectorCortexReconstruct(req, res, _ctx) {
|
|
|
18
24
|
return true;
|
|
19
25
|
}
|
|
20
26
|
const enabled = VC4C_ENABLED();
|
|
27
|
+
const counts = countVcEvents(ctx.stateDir, RECONSTRUCT_EVENTS);
|
|
21
28
|
const body = {
|
|
22
29
|
enabled,
|
|
23
|
-
closureAttempts:
|
|
24
|
-
closureRejections:
|
|
30
|
+
closureAttempts: vcCount(counts, "vector_cortex_closure_optimized"),
|
|
31
|
+
closureRejections: vcCount(counts, "vector_cortex_closure_proof_rejected"),
|
|
25
32
|
validatedCount: 0,
|
|
26
33
|
invalidatedCount: 0,
|
|
27
34
|
spanTotal: 0,
|
|
@@ -22,6 +22,13 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { VC6C_ENABLED } from "../../src/config.js";
|
|
24
24
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
25
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
26
|
+
// Actual event names emitted by src/vector-cortex/heal/repair-emit.ts.
|
|
27
|
+
const REPAIR_EVENTS = [
|
|
28
|
+
"vector_cortex_repair_planned",
|
|
29
|
+
"vector_cortex_repair_pointer_switched",
|
|
30
|
+
"vector_cortex_repair_backoff",
|
|
31
|
+
];
|
|
25
32
|
/**
|
|
26
33
|
* Reader-only GET /api/vector-cortex/repair (VC6C).
|
|
27
34
|
*
|
|
@@ -30,7 +37,7 @@ import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
|
30
37
|
* never will be, so no subsystem bytes, gap ranges, high-water marks, or root
|
|
31
38
|
* digests can leak here.
|
|
32
39
|
*/
|
|
33
|
-
export function handleVectorCortexRepair(req, res,
|
|
40
|
+
export function handleVectorCortexRepair(req, res, ctx) {
|
|
34
41
|
const url = req.url ?? "";
|
|
35
42
|
const path = url.split("?")[0] ?? url;
|
|
36
43
|
if (path !== "/api/vector-cortex/repair")
|
|
@@ -40,6 +47,7 @@ export function handleVectorCortexRepair(req, res, _ctx) {
|
|
|
40
47
|
return true;
|
|
41
48
|
}
|
|
42
49
|
const enabled = VC6C_ENABLED();
|
|
50
|
+
const counts = countVcEvents(ctx.stateDir, REPAIR_EVENTS);
|
|
43
51
|
// Flag-off routes to mode C: with VC6C off no self-healing controller runs at
|
|
44
52
|
// all, so neither the targeted rebuild (mode A) nor the full deterministic
|
|
45
53
|
// rebuild (mode B) path is available. Mode C is exactly the spec's "derived
|
|
@@ -50,10 +58,10 @@ export function handleVectorCortexRepair(req, res, _ctx) {
|
|
|
50
58
|
const body = {
|
|
51
59
|
enabled,
|
|
52
60
|
mode,
|
|
53
|
-
repairAttempts:
|
|
54
|
-
repairsPlanned:
|
|
55
|
-
pointersSwitched:
|
|
56
|
-
backoffs:
|
|
61
|
+
repairAttempts: vcCount(counts, "vector_cortex_repair_planned"),
|
|
62
|
+
repairsPlanned: vcCount(counts, "vector_cortex_repair_planned"),
|
|
63
|
+
pointersSwitched: vcCount(counts, "vector_cortex_repair_pointer_switched"),
|
|
64
|
+
backoffs: vcCount(counts, "vector_cortex_repair_backoff"),
|
|
57
65
|
lastBackoffMs: null,
|
|
58
66
|
lastFailure: null,
|
|
59
67
|
updatedAt: new Date().toISOString(),
|
|
@@ -19,10 +19,16 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { VC4A_ENABLED } from "../../src/config.js";
|
|
21
21
|
import { sendJson } from "./routes-vector-cortex-shared.js";
|
|
22
|
+
import { countVcEvents, vcCount } from "./vc-event-counts.js";
|
|
23
|
+
// Actual events emitted by src/vector-cortex/shards/manifest.ts. VC4A has no
|
|
24
|
+
// per-tier (semantic/exact) write event — the manifest build is the single
|
|
25
|
+
// shard-write signal — so semanticCount is wired to it and exactCount stays 0
|
|
26
|
+
// until a per-tier write event exists.
|
|
27
|
+
const SHARD_EVENTS = ["vector_cortex_shard_manifest_built"];
|
|
22
28
|
/**
|
|
23
29
|
* Reader-only GET /api/vector-cortex/shards (VC4A).
|
|
24
30
|
*/
|
|
25
|
-
export function handleVectorCortexShards(req, res,
|
|
31
|
+
export function handleVectorCortexShards(req, res, ctx) {
|
|
26
32
|
const url = req.url ?? "";
|
|
27
33
|
const path = url.split("?")[0] ?? url;
|
|
28
34
|
if (path !== "/api/vector-cortex/shards")
|
|
@@ -33,11 +39,13 @@ export function handleVectorCortexShards(req, res, _ctx) {
|
|
|
33
39
|
return true;
|
|
34
40
|
}
|
|
35
41
|
const enabled = VC4A_ENABLED();
|
|
42
|
+
const counts = countVcEvents(ctx.stateDir, SHARD_EVENTS);
|
|
36
43
|
const body = {
|
|
37
44
|
enabled,
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
|
|
45
|
+
// The manifest-build event is the only VC4A shard-write signal; semanticCount
|
|
46
|
+
// reflects manifests built and exactCount stays 0 (no per-tier write event
|
|
47
|
+
// distinguishes exact shards in events.log yet).
|
|
48
|
+
semanticCount: vcCount(counts, "vector_cortex_shard_manifest_built"),
|
|
41
49
|
exactCount: 0,
|
|
42
50
|
byteTotal: 0,
|
|
43
51
|
protectedByteTotal: 0,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dashboard-server/vc-event-counts.ts — lightweight events.log tail reader for
|
|
3
|
+
* the Vector Cortex dashboard routes.
|
|
4
|
+
*
|
|
5
|
+
* The VC event reporters in `src/vector-cortex/*` emit structured JSON events
|
|
6
|
+
* (one per line) into the per-repo `events.log`. Instead of the dashboard
|
|
7
|
+
* hardcoding zero for aggregate counters, this module reads the event tail and
|
|
8
|
+
* counts real occurrences of named events. It is the single shared seam so every
|
|
9
|
+
* route stays a small, thin consumer and the counting logic lives in one place
|
|
10
|
+
* (extensions/ 400-line soft-as-hard split trigger).
|
|
11
|
+
*
|
|
12
|
+
* NEVER throws: a missing/unreadable file degrades to an empty Map, malformed
|
|
13
|
+
* lines are skipped silently, and only the `.event` string field is inspected —
|
|
14
|
+
* no payload, bytes, span ids, digests, or ledger text ever leaves this module
|
|
15
|
+
* (SECURITY_PRIVACY, reader-only aggregate).
|
|
16
|
+
*
|
|
17
|
+
* Guardrails: PREVENT-PI-004 (local in-process file read only), PREVENT-011
|
|
18
|
+
* (no `any`).
|
|
19
|
+
*/
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { readFileSync } from "node:fs";
|
|
22
|
+
/**
|
|
23
|
+
* Count occurrences of the given named events within the last `maxLines` of the
|
|
24
|
+
* per-repo events.log adjacent to `stateDir`. Returns a Map keyed by event name;
|
|
25
|
+
* a missing/unreadable log or zero matching lines yields an empty Map. Best-effort
|
|
26
|
+
* and non-fatal by construction (matches the non-fatal-stores invariant).
|
|
27
|
+
*/
|
|
28
|
+
export function countVcEvents(stateDir, eventNames, maxLines = 10000) {
|
|
29
|
+
const counts = new Map();
|
|
30
|
+
let raw;
|
|
31
|
+
try {
|
|
32
|
+
raw = readFileSync(join(stateDir, "events.log"), "utf-8");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Missing or unreadable log → nothing to count, never throw.
|
|
36
|
+
return counts;
|
|
37
|
+
}
|
|
38
|
+
// Walk only the tail: split into lines and keep the last `maxLines`.
|
|
39
|
+
const lines = raw.split("\n");
|
|
40
|
+
const start = Math.max(0, lines.length - maxLines);
|
|
41
|
+
const wanted = new Set(eventNames);
|
|
42
|
+
for (let i = start; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i];
|
|
44
|
+
if (line.length === 0)
|
|
45
|
+
continue;
|
|
46
|
+
let ev = null;
|
|
47
|
+
try {
|
|
48
|
+
ev = JSON.parse(line);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Malformed line — skip silently, never break the reader.
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (typeof ev?.event === "string" && wanted.has(ev.event)) {
|
|
55
|
+
counts.set(ev.event, (counts.get(ev.event) ?? 0) + 1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return counts;
|
|
59
|
+
}
|
|
60
|
+
/** Read a value from an event-count map, defaulting to 0 when absent. */
|
|
61
|
+
export function vcCount(counts, name) {
|
|
62
|
+
return counts.get(name) ?? 0;
|
|
63
|
+
}
|
|
@@ -15,6 +15,9 @@ import { openTurnStore } from "../../../src/store/turns/connection.js";
|
|
|
15
15
|
import { buildTopicModel, createTopicStore, bumpWikiCompactCounter, applyOverridesAfterRebuild, applyFullOverridesAfterRebuild, } from "../../../src/topics/index.js";
|
|
16
16
|
import { assignNewMemoriesIncremental } from "../../../src/wiki/index.js";
|
|
17
17
|
import { TrigramEmbedder } from "../../../src/embedder.js";
|
|
18
|
+
import { reportClosureOptimized } from "../../../src/vector-cortex/heal/emit.js";
|
|
19
|
+
import { reportRepairPlanned } from "../../../src/vector-cortex/heal/repair-emit.js";
|
|
20
|
+
import { VC6A_ENABLED, VC6C_ENABLED } from "../../../src/config/vector-cortex.js";
|
|
18
21
|
/**
|
|
19
22
|
* Persist the checkpoint_epoch, stamp turns, rebuild the auto-wiki, seed the
|
|
20
23
|
* topic model, and dedup — gated on dbMirror. Non-fatal end-to-end.
|
|
@@ -193,4 +196,35 @@ export async function persistEpochAndMaintain(runtime, config, ran) {
|
|
|
193
196
|
runtime.logger.warn("db-mirror-epoch-fail", { error: String(e) });
|
|
194
197
|
}
|
|
195
198
|
}
|
|
199
|
+
// VC6 Heal lifecycle emits (post-compact). Wiring stubs — dashboard graph +
|
|
200
|
+
// event counts move; real gap detection/rebuild is a future sprint.
|
|
201
|
+
// VC6A: closure-optimization savings from the compact token delta.
|
|
202
|
+
const savings = Math.max(0, (ran.result.originalTokenEstimate ?? 0) - (ran.result.tokenEstimate ?? 0));
|
|
203
|
+
if (VC6A_ENABLED()) {
|
|
204
|
+
try {
|
|
205
|
+
reportClosureOptimized((name, payload) => runtime.appendEvent(name, payload), {
|
|
206
|
+
sessionId: runtime.rt.sessionId,
|
|
207
|
+
removed: 0,
|
|
208
|
+
retained: ran.result.compactedFrom,
|
|
209
|
+
savings,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
/* non-fatal: VC6A heal emit never breaks compaction */
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// VC6C: repair-planner placeholder (no real gap detection yet).
|
|
217
|
+
if (VC6C_ENABLED()) {
|
|
218
|
+
try {
|
|
219
|
+
reportRepairPlanned((name, payload) => runtime.appendEvent(name, payload), {
|
|
220
|
+
subsystem: "post_compact",
|
|
221
|
+
generation: 1,
|
|
222
|
+
backoffMs: 0,
|
|
223
|
+
gapSize: 0,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
/* non-fatal: VC6C heal emit never breaks compaction */
|
|
228
|
+
}
|
|
229
|
+
}
|
|
196
230
|
}
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
import { runCompact } from "../../mega-pipeline.js";
|
|
2
2
|
import { pressureFromPct, pressureRatio } from "../../mega-config.js";
|
|
3
|
+
import { recordCompactLatency } from "../../mega-runtime/vc-observer.js";
|
|
4
|
+
import { decideLivePath } from "../../mega-runtime/vector-cortex-live.js";
|
|
5
|
+
import { VC5C_ENABLED } from "../../../src/config/vector-cortex.js";
|
|
3
6
|
/**
|
|
4
7
|
* Invoke the compaction pipeline with adaptive pressure. Returns a tailed view
|
|
5
8
|
* ("return") when compaction skipped, or "proceed" with the non-skipped result
|
|
6
9
|
* and the computed pressure (consumed by live-trim's critical-over hatch).
|
|
7
10
|
*/
|
|
8
11
|
export function invokePipeline(pi, runtime, config, ctx, opts) {
|
|
12
|
+
// VC5C: emit the rollout decision per compact event (observability seam).
|
|
13
|
+
// vcGate/vcHardFaults are not yet declared on MegaRuntime.rt — cast to the
|
|
14
|
+
// rollout shapes. Best-effort + non-fatal; decision does NOT gate behavior yet.
|
|
15
|
+
if (VC5C_ENABLED()) {
|
|
16
|
+
try {
|
|
17
|
+
const decision = decideLivePath(runtime.rt.sessionId, {
|
|
18
|
+
emit: runtime.appendEvent.bind(runtime),
|
|
19
|
+
currentGate: runtime.rt.vcGate ?? 0,
|
|
20
|
+
hardFaults: runtime.rt
|
|
21
|
+
.vcHardFaults ?? [],
|
|
22
|
+
});
|
|
23
|
+
runtime.appendEvent("vector_cortex_rollout_decision", {
|
|
24
|
+
sessionId: runtime.rt.sessionId,
|
|
25
|
+
vcActive: decision.vcActive,
|
|
26
|
+
forcedPreVc: decision.forcedPreVc,
|
|
27
|
+
mode: decision.mode,
|
|
28
|
+
bucket: decision.bucket,
|
|
29
|
+
gateIndex: decision.gateIndex,
|
|
30
|
+
promotionBlocked: decision.promotionBlocked,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* non-fatal: rollout decision emission never breaks compaction */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
9
37
|
// Adaptive compression (Fix E): scale compression strength + keepFrom depth
|
|
10
38
|
// with how close we are to the model context limit. Null-safe: when the
|
|
11
39
|
// token-fallback path ran (pct unavailable) use the token-basis pressure
|
|
@@ -13,9 +41,14 @@ export function invokePipeline(pi, runtime, config, ctx, opts) {
|
|
|
13
41
|
const pressure = opts.pct != null
|
|
14
42
|
? pressureFromPct(opts.pct)
|
|
15
43
|
: pressureRatio(opts.currentTokens, runtime.effectiveThreshold);
|
|
44
|
+
const t0 = Date.now();
|
|
16
45
|
const ran = runCompact(pi, runtime, config, ctx, opts.messages, {
|
|
17
46
|
compressionPressure: pressure,
|
|
18
47
|
});
|
|
48
|
+
// VC0A: record compact latency on the eval observer (mode A) on every
|
|
49
|
+
// outcome so the dashboard histogram reflects real data. No-op when the
|
|
50
|
+
// observer is absent (flag off / construction failure).
|
|
51
|
+
recordCompactLatency(runtime, Date.now() - t0, runtime.rt.sessionId, runtime.rt.compactCount);
|
|
19
52
|
// D.3: skip paths fall back to replay instead of returning empty.
|
|
20
53
|
// If runCompact skipped and we have a valid trimCache, replay it
|
|
21
54
|
// (free stability win) — otherwise defer to the next event.
|
|
@@ -17,6 +17,7 @@ export function buildDashboardSnapshot(ctx) {
|
|
|
17
17
|
tier: ctx.pressureBand,
|
|
18
18
|
presetTier: ctx.config.tier,
|
|
19
19
|
pressure: ctx.pressure,
|
|
20
|
+
vcObserverSamples: ctx.vcObserverSamples ?? 0,
|
|
20
21
|
config: {
|
|
21
22
|
fastGatePct: ctx.config.fastGatePct,
|
|
22
23
|
thresholdTokens: ctx.effectiveThreshold,
|
|
@@ -73,17 +74,17 @@ export function buildDashboardSnapshot(ctx) {
|
|
|
73
74
|
repo: ctx.repo,
|
|
74
75
|
compression: {
|
|
75
76
|
session: {
|
|
76
|
-
tokensIn: ctx.
|
|
77
|
+
tokensIn: ctx.st.originalTokens,
|
|
77
78
|
tokensOut: ctx.st.totalTokenEstimate,
|
|
78
79
|
tokensFreed: ctx.rt.tokensSaved,
|
|
79
|
-
compressionPct: ctx.rt.tokensSaved / Math.max(1, ctx.
|
|
80
|
+
compressionPct: ctx.rt.tokensSaved / Math.max(1, ctx.st.originalTokens),
|
|
80
81
|
dedupPct: ctx.rt.dedupAttempts > 0 ? ctx.rt.dedupSkips / ctx.rt.dedupAttempts : 0,
|
|
81
82
|
},
|
|
82
83
|
repo: {
|
|
83
|
-
tokensIn: ctx.repo.
|
|
84
|
+
tokensIn: ctx.repo.originalTokens,
|
|
84
85
|
tokensOut: ctx.repo.totalTokenEstimate,
|
|
85
86
|
tokensFreed: ctx.repo.tokensSaved,
|
|
86
|
-
compressionPct: ctx.repo.tokensSaved / Math.max(1, ctx.repo.
|
|
87
|
+
compressionPct: ctx.repo.tokensSaved / Math.max(1, ctx.repo.originalTokens),
|
|
87
88
|
dedupPct: ctx.repo.dedupAttempts > 0 ? ctx.repo.dedupCollapsed / ctx.repo.dedupAttempts : 0,
|
|
88
89
|
},
|
|
89
90
|
},
|
|
@@ -96,7 +97,9 @@ export function buildDashboardSnapshot(ctx) {
|
|
|
96
97
|
// per-session in rt and there's no cumulative counter yet.
|
|
97
98
|
total: ctx.repo.dedupCollapsed,
|
|
98
99
|
sessionTokensSaved: ctx.rt.cacheHitTokens,
|
|
99
|
-
|
|
100
|
+
// Cumulative tokens saved across all sessions in this repo —
|
|
101
|
+
// was a placeholder (dedupCollapsed * 100).
|
|
102
|
+
totalTokensSaved: ctx.repo.tokensSaved,
|
|
100
103
|
},
|
|
101
104
|
compacts: {
|
|
102
105
|
session: ctx.rt.compactCount,
|
|
@@ -109,7 +112,7 @@ export function buildDashboardSnapshot(ctx) {
|
|
|
109
112
|
},
|
|
110
113
|
cacheHit: {
|
|
111
114
|
sessionSec: ctx.rt.cacheHitTokens / 1000,
|
|
112
|
-
totalSec:
|
|
115
|
+
totalSec: ctx.repo.tokensSaved / 1000,
|
|
113
116
|
},
|
|
114
117
|
},
|
|
115
118
|
model: ctx.currentModel
|