pi-mega-compact 0.20.22 → 0.20.24
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-rag-settings-helpers.js +2 -0
- 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/agent-handlers/turnEndHandler/cacheStripe.js +15 -4
- package/dist/extensions/mega-events/context-handler/afterCompact.js +57 -4
- package/dist/extensions/mega-events/context-handler/dbMirrorAppend.js +35 -7
- package/dist/extensions/mega-events/context-handler/pipelineRun.js +33 -0
- package/dist/extensions/mega-events/context-handler/tailResult.js +45 -12
- 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/dist/src/cache-stripe-impl.js +52 -214
- package/dist/src/cache-stripe-score.js +115 -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-rag-settings-helpers.ts +12 -0
- 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/agent-handlers/turnEndHandler/cacheStripe.ts +13 -4
- package/extensions/mega-events/context-handler/afterCompact.ts +69 -4
- package/extensions/mega-events/context-handler/dbMirrorAppend.ts +39 -7
- package/extensions/mega-events/context-handler/pipelineRun.ts +39 -0
- package/extensions/mega-events/context-handler/tailResult.ts +56 -15
- 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/src/cache-stripe-impl.ts +73 -277
- package/src/cache-stripe-score.ts +170 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-BTBGyppF.js +0 -2
- package/extensions/dashboard-client/dist/assets/SetupTab-BTBGyppF.js.map +0 -1
|
@@ -3,6 +3,21 @@ import { appendMirrorMessages } from "../mirror-append.js";
|
|
|
3
3
|
import { appendMessagesToLedger } from "../../mega-runtime/vector-cortex-ledger.js";
|
|
4
4
|
import { epochIdFor } from "../../../src/mirror/epoch.js";
|
|
5
5
|
import { messageContentText } from "./messageText.js";
|
|
6
|
+
/**
|
|
7
|
+
* Best-effort tool_call_id for the tool_results insert. The toolResult variant
|
|
8
|
+
* carries a top-level toolCallId (read via an `unknown`-narrowed cast — never
|
|
9
|
+
* reach into `.content`, which is variant-specific and requires narrowing).
|
|
10
|
+
* bashExecution has no toolCallId, so fall back to a stable synthetic id keyed
|
|
11
|
+
* on (turn, index) to satisfy the NOT NULL column. No `any` (PREVENT-011).
|
|
12
|
+
*/
|
|
13
|
+
function toolCallIdOf(m, fallback) {
|
|
14
|
+
if (m.role === "toolResult") {
|
|
15
|
+
const id = m.toolCallId;
|
|
16
|
+
if (typeof id === "string" && id.length > 0)
|
|
17
|
+
return id;
|
|
18
|
+
}
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
6
21
|
/**
|
|
7
22
|
* Append incoming messages to the DB mirror (raw_transcript + thread/tool
|
|
8
23
|
* tables) and the v2 ledger. Gated on config.dbMirror for the mirror; the VC1B
|
|
@@ -26,22 +41,35 @@ export function appendMirrorAndLedger(runtime, config, messages) {
|
|
|
26
41
|
// separation (buildSeparatedPrompt / buildCacheOptimizedPrompt in
|
|
27
42
|
// tailResult) is sufficient for the prompt-construction path;
|
|
28
43
|
// these DB writes persist the split for post-hoc analysis, dashboard
|
|
29
|
-
// queries, and future readers.
|
|
30
|
-
//
|
|
31
|
-
|
|
44
|
+
// queries, and future readers. Gated on (messageSeparation ||
|
|
45
|
+
// cacheStriping) so flag-OFF remains byte-identical to the
|
|
46
|
+
// predecessor — when both flags are OFF the live prompt is never
|
|
47
|
+
// separated, and growing these tables would be dead state.
|
|
48
|
+
// Non-fatal — failure here never breaks the agent loop
|
|
49
|
+
// (PREVENT-PI-004: zero network, local SQLite only).
|
|
50
|
+
if (config.messageSeparation || config.cacheStriping) {
|
|
32
51
|
const sid = runtime.rt.sessionId;
|
|
33
52
|
const turn = runtime.currentTurn;
|
|
34
53
|
const now = Date.now();
|
|
35
54
|
const threadStmt = db.prepare("INSERT OR IGNORE INTO conversation_thread (conversation_id, role, content, turn_index, timestamp) VALUES (?, ?, ?, ?, ?)");
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
// Schema (plan-v2.ts) is (conversation_id, tool_call_id,
|
|
56
|
+
// tool_result, turn_index, timestamp) — NOT role/content.
|
|
57
|
+
const toolStmt = db.prepare("INSERT OR IGNORE INTO tool_results (conversation_id, tool_call_id, tool_result, turn_index, timestamp) VALUES (?, ?, ?, ?, ?)");
|
|
58
|
+
const toolHas = db.prepare("SELECT 1 FROM tool_results WHERE conversation_id = ? AND turn_index = ? AND tool_call_id = ? AND tool_result = ? LIMIT 1");
|
|
59
|
+
const threadHas = db.prepare("SELECT 1 FROM conversation_thread WHERE conversation_id = ? AND turn_index = ? AND role = ? AND content = ? LIMIT 1");
|
|
60
|
+
for (const [idx, m] of messages.entries()) {
|
|
38
61
|
const role = m.role;
|
|
39
62
|
const content = messageContentText(m);
|
|
40
63
|
if (role === "user" || role === "assistant") {
|
|
41
|
-
|
|
64
|
+
if (threadHas.get(sid, turn, role, content) == null) {
|
|
65
|
+
threadStmt.run(sid, role, content, turn, now);
|
|
66
|
+
}
|
|
42
67
|
}
|
|
43
68
|
else if (role === "toolResult" || role === "bashExecution") {
|
|
44
|
-
|
|
69
|
+
const toolCallId = toolCallIdOf(m, `bash:${turn}:${idx}`);
|
|
70
|
+
if (toolHas.get(sid, turn, toolCallId, content) == null) {
|
|
71
|
+
toolStmt.run(sid, toolCallId, content, turn, now);
|
|
72
|
+
}
|
|
45
73
|
}
|
|
46
74
|
}
|
|
47
75
|
}
|
|
@@ -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.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { stagedForTail, withRecallTail } from "../recall-tail.js";
|
|
2
2
|
import { buildSeparatedPrompt, buildCacheOptimizedPrompt } from "../separated-prompt.js";
|
|
3
3
|
import { messageContentText } from "./messageText.js";
|
|
4
|
+
import { computeContentDigest } from "../../../src/dedup/digest.js";
|
|
5
|
+
const lastTurnPrefix = new WeakMap();
|
|
4
6
|
/**
|
|
5
7
|
* Build the tail injection closure. Returns undefined when nothing is staged
|
|
6
8
|
* (or the flags are OFF) so the caller falls through to its normal return.
|
|
@@ -25,20 +27,51 @@ export function buildTailResult(runtime, config, messages) {
|
|
|
25
27
|
else if (config.messageSeparation) {
|
|
26
28
|
result = buildSeparatedPrompt(result);
|
|
27
29
|
}
|
|
28
|
-
// P2.5: log prefix
|
|
29
|
-
//
|
|
30
|
+
// P2.5: log cross-turn stable-prefix length (cache-hit proxy). After the
|
|
31
|
+
// prompt is built (separated or cache-optimized), fingerprint each leading
|
|
32
|
+
// message and count how many are byte-identical to the previous turn's
|
|
33
|
+
// prompt, in order. A high stablePrefix = the provider KV-cache prefix is
|
|
34
|
+
// re-used (cache hit). Fire-and-forget + non-fatal.
|
|
35
|
+
//
|
|
36
|
+
// tailResult may run several times per turn (gate return / replay /
|
|
37
|
+
// debounce / live-trim), so the sessionId+turn guard measures once per
|
|
38
|
+
// turn — compare against the PREVIOUS turn's stored footprint, then store
|
|
39
|
+
// this turn's for the next comparison. Cross-session compares are skipped
|
|
40
|
+
// via the stored sessionId check (belt-and-suspenders; the WeakMap entry
|
|
41
|
+
// is scoped to this runtime, which owns the session).
|
|
30
42
|
if (result.length > 1) {
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
runtime.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
try {
|
|
44
|
+
const sessionId = runtime.rt.sessionId;
|
|
45
|
+
const turn = runtime.currentTurn;
|
|
46
|
+
const prev = lastTurnPrefix.get(runtime);
|
|
47
|
+
const isNewTurn = !prev || prev.sessionId !== sessionId || prev.turn !== turn;
|
|
48
|
+
if (isNewTurn) {
|
|
49
|
+
const fingerprints = result.map((m) =>
|
|
50
|
+
// Role prefix disambiguates identical text across variants
|
|
51
|
+
// (roles are a fixed enum — no realistic fingerprint collision).
|
|
52
|
+
computeContentDigest(`${m.role}|${messageContentText(m)}`).contentHash);
|
|
53
|
+
let stablePrefix = 0;
|
|
54
|
+
if (prev && prev.sessionId === sessionId) {
|
|
55
|
+
for (let i = 0; i < fingerprints.length; i++) {
|
|
56
|
+
if (i >= prev.fingerprints.length ||
|
|
57
|
+
prev.fingerprints[i] !== fingerprints[i]) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
stablePrefix++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
lastTurnPrefix.set(runtime, { sessionId, turn, fingerprints });
|
|
64
|
+
runtime.logger.info("prefix_stability", {
|
|
65
|
+
stablePrefix,
|
|
66
|
+
totalMessages: result.length,
|
|
67
|
+
separation: config.messageSeparation ? "v2" : "off",
|
|
68
|
+
striping: config.cacheStriping ? "v3" : "off",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
40
73
|
// Non-fatal: stability logging is best-effort.
|
|
41
|
-
}
|
|
74
|
+
}
|
|
42
75
|
}
|
|
43
76
|
return { messages: result };
|
|
44
77
|
};
|
|
@@ -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
|
|
@@ -22,6 +22,7 @@ import { latestModelSnapshot, readLatestCacheHitPct, recordPerfSample, recordSes
|
|
|
22
22
|
import { resolveRepoRoot, } from "../mega-config.js";
|
|
23
23
|
import { computeMegaSnapshot } from "./snapshot.js";
|
|
24
24
|
import { buildDashboardSnapshot } from "./dashboard-snapshot.js";
|
|
25
|
+
import { getVcObserver } from "./vc-observer.js";
|
|
25
26
|
import { materialSigImpl, embedderNameImpl, driftStatusImpl, getTurnLevelImpl, } from "./runtime-helpers.js";
|
|
26
27
|
// -------------------------------------------------------------- snapshotImpl
|
|
27
28
|
/** Collect live state and write it to disk (+ paint the above-editor widget).
|
|
@@ -85,6 +86,7 @@ export function snapshotImpl(self, ctx) {
|
|
|
85
86
|
pressureBand: self.pressureBand,
|
|
86
87
|
pressure: self.pressure,
|
|
87
88
|
effectiveThreshold: self.effectiveThreshold,
|
|
89
|
+
vcObserverSamples: getVcObserver(self)?.rows().length ?? 0,
|
|
88
90
|
statusKey: self.statusKey,
|
|
89
91
|
lastCtxTokens: self.lastCtxTokens,
|
|
90
92
|
lastCtxPercent: self.lastCtxPercent,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vc-observer.ts — VC0A mode-A eval observer wiring for MegaRuntime.
|
|
3
|
+
*
|
|
4
|
+
* Bridges the pure in-memory EvalObserver (src/vector-cortex/eval/observer.ts)
|
|
5
|
+
* into the production runtime: every recorded compact/recall latency sample is
|
|
6
|
+
* both emitted to events.log (via MegaRuntime.appendEvent) and appended to the
|
|
7
|
+
* redacted evaluation.jsonl (via appendEvalRow) so the Vector Cortex dashboard
|
|
8
|
+
* "Observer" histogram reads real data instead of an empty file.
|
|
9
|
+
*
|
|
10
|
+
* All wiring is gated on VC0A_ENABLED() (MEGACOMPACT_VC0A). Flag-off and any
|
|
11
|
+
* construction/persistence error are non-fatal (PREVENT-PI-004: local FS only,
|
|
12
|
+
* no network) and degrade to a null observer — byte-identical to the
|
|
13
|
+
* predecessor (mode C). PREVENT-011: no `any` type.
|
|
14
|
+
*
|
|
15
|
+
* Follows the capture-model.ts / append-event.ts pattern: a context interface +
|
|
16
|
+
* free functions + a thin delegate. No import-time side effects — merely
|
|
17
|
+
* importing these functions is inert regardless of the flag.
|
|
18
|
+
*/
|
|
19
|
+
import { VC0A_ENABLED } from "../../src/config.js";
|
|
20
|
+
import { createEvalObserver } from "../../src/vector-cortex/eval/observer.js";
|
|
21
|
+
import { appendEvalRow } from "../../src/vector-cortex/eval/persist.js";
|
|
22
|
+
// ------------------------------------------------------------- construction
|
|
23
|
+
/**
|
|
24
|
+
* Build the production-wired eval observer (mode A) if the VC0A flag is on.
|
|
25
|
+
* Returns null when the flag is off or on any construction error (non-fatal).
|
|
26
|
+
* The returned observer is a thin, best-effort observability seam that never
|
|
27
|
+
* breaks the agent loop.
|
|
28
|
+
*/
|
|
29
|
+
export function createVcObserver(self) {
|
|
30
|
+
if (!VC0A_ENABLED())
|
|
31
|
+
return null;
|
|
32
|
+
try {
|
|
33
|
+
return createEvalObserver({
|
|
34
|
+
emit: self.appendEvent.bind(self),
|
|
35
|
+
persist: (sample) => appendEvalRow(self.currentStateDir, [sample]),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* non-fatal observability — never break the agent loop */
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// ---------------------------------------------------------------- weak cache
|
|
44
|
+
/**
|
|
45
|
+
* Module-level observer cache keyed by the runtime object. Avoids adding a
|
|
46
|
+
* `vcObserver` field to MegaRuntime (keeping runtime.ts under its soft limit
|
|
47
|
+
* — no field, no constructor line, no import bloat). One observer per runtime
|
|
48
|
+
* instance, lazily built on the first latency recording.
|
|
49
|
+
*/
|
|
50
|
+
const observerCache = new WeakMap();
|
|
51
|
+
/** Lazily create + cache the observer for the given runtime context. */
|
|
52
|
+
export function getVcObserver(self) {
|
|
53
|
+
let obs = observerCache.get(self);
|
|
54
|
+
if (obs === undefined) {
|
|
55
|
+
obs = createVcObserver(self);
|
|
56
|
+
observerCache.set(self, obs);
|
|
57
|
+
}
|
|
58
|
+
return obs;
|
|
59
|
+
}
|
|
60
|
+
// ---------------------------------------------------------------- reporting
|
|
61
|
+
/** Record a compact latency sample on the observer (no-op when absent). */
|
|
62
|
+
export function recordCompactLatency(self, elapsedMs, sessionId, epoch) {
|
|
63
|
+
const obs = getVcObserver(self);
|
|
64
|
+
if (obs == null)
|
|
65
|
+
return;
|
|
66
|
+
try {
|
|
67
|
+
obs.record({
|
|
68
|
+
session: sessionId,
|
|
69
|
+
seq: epoch,
|
|
70
|
+
event: "compact",
|
|
71
|
+
value: elapsedMs,
|
|
72
|
+
unit: "ms",
|
|
73
|
+
mode: "A",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
/* non-fatal observability */
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Record a recall latency sample on the observer (no-op when absent). */
|
|
81
|
+
export function recordRecallLatency(self, elapsedMs, sessionId, epoch) {
|
|
82
|
+
const obs = getVcObserver(self);
|
|
83
|
+
if (obs == null)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
obs.record({
|
|
87
|
+
session: sessionId,
|
|
88
|
+
seq: epoch,
|
|
89
|
+
event: "recall",
|
|
90
|
+
value: elapsedMs,
|
|
91
|
+
unit: "ms",
|
|
92
|
+
mode: "A",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* non-fatal observability */
|
|
97
|
+
}
|
|
98
|
+
}
|