pi-mega-compact 0.11.3 → 0.11.5
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/api-contracts/endpoints.js +19 -0
- package/dist/extensions/dashboard-server/api-contracts/memory.js +8 -0
- package/dist/extensions/dashboard-server/api-contracts/provider-cache.js +1 -0
- package/dist/extensions/dashboard-server/api-contracts/setup.js +10 -0
- package/dist/extensions/dashboard-server/index-reader.js +6 -2
- package/dist/extensions/dashboard-server/routes-cache.js +115 -55
- package/dist/extensions/dashboard-server/routes-memory.js +51 -0
- package/dist/extensions/dashboard-server/routes-repo.js +2 -2
- package/dist/extensions/dashboard-server/routes-setup.js +162 -0
- package/dist/extensions/dashboard-server/routes.js +2 -0
- package/dist/extensions/dashboard-server/server.js +7 -1
- package/dist/extensions/mega-commands.js +189 -1
- package/dist/extensions/mega-config.js +3 -0
- package/dist/extensions/mega-events/agent-handlers.js +41 -6
- package/dist/extensions/mega-events/compact-handlers.js +1 -0
- package/dist/extensions/mega-events/context-handler.js +37 -92
- package/dist/extensions/mega-events/context-hwm.js +51 -0
- package/dist/extensions/mega-events/error-classifier.js +118 -128
- package/dist/extensions/mega-events/mirror-append.js +107 -0
- package/dist/extensions/mega-events/outage-advisor.js +59 -0
- package/dist/extensions/mega-events/perf-handler.js +51 -1
- package/dist/extensions/mega-events/recall-tail.js +59 -0
- package/dist/extensions/mega-events/session-handlers.js +15 -8
- package/dist/extensions/mega-runtime/reset-runtime.js +6 -0
- package/dist/extensions/mega-runtime/runtime.js +7 -0
- package/dist/src/embedder.js +41 -2
- package/dist/src/memoryStats.js +75 -0
- package/dist/src/prefix-break.js +43 -0
- package/dist/src/pricing.js +1 -1
- package/dist/src/store/sqlite/perf-samples.js +144 -16
- package/dist/src/store/turns/memory-store.js +8 -0
- package/dist/src/store/turns/sqlite-store.js +14 -3
- package/dist/src/store/turns/types.js +18 -1
- package/dist/src/store/vectorIndex.js +26 -5
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-vEo2MtE2.js → AchievementTiles-BoL7qBOJ.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-vEo2MtE2.js.map → AchievementTiles-BoL7qBOJ.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/AchievementsTab-BFDE3HYc.js +2 -0
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-DjxfYrDc.js.map → AchievementsTab-BFDE3HYc.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-eKVc-NV1.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-eKVc-NV1.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{ConfigTab-Cm6ymbmx.js → ConfigTab-DDFE-ckA.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-Cm6ymbmx.js.map → ConfigTab-DDFE-ckA.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DXWl_YzI.js → EventsTab-B6UxZ7PM.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DXWl_YzI.js.map → EventsTab-B6UxZ7PM.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{GameTab-BLDudcO5.js → GameTab-DehUX-KE.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{GameTab-BLDudcO5.js.map → GameTab-DehUX-KE.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLkKCztn.js → MaintenanceTab-0GWRt4wn.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLkKCztn.js.map → MaintenanceTab-0GWRt4wn.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MetricsTab-Cq4u-rZF.js → MetricsTab-C3rwMVsN.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-Cq4u-rZF.js.map → MetricsTab-C3rwMVsN.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-39O9_x5j.js +2 -0
- package/extensions/dashboard-client/dist/assets/{OverviewTab-D4kGvsiQ.js.map → OverviewTab-39O9_x5j.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/ReposTab-Cfj6Q5sH.js +2 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-Cfj6Q5sH.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DZC2-GCn.js → SessionsTab-DXDTCi3r.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DZC2-GCn.js.map → SessionsTab-DXDTCi3r.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-mMlfunJa.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-mMlfunJa.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-Cw1dJ4e9.js +2 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-Cw1dJ4e9.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TopicsTab-01G71hv1.js → TopicsTab-BAw972BV.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TopicsTab-01G71hv1.js.map → TopicsTab-BAw972BV.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DLRg0LZT.js → TurnsTab-Cf5mGIdl.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DLRg0LZT.js.map → TurnsTab-Cf5mGIdl.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/format-COjDIVGj.js +2 -0
- package/extensions/dashboard-client/dist/assets/format-COjDIVGj.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{index-BX0bcgLu.js → index-4gQ7auad.js} +10 -10
- package/extensions/dashboard-client/dist/assets/index-4gQ7auad.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js +2 -0
- package/extensions/dashboard-client/dist/assets/pricing-CvE4NllQ.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{useSSE-BBYt5UPB.js → useSSE-DNgMuyP6.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BBYt5UPB.js.map → useSSE-DNgMuyP6.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +1 -1
- package/extensions/dashboard-client/src/App.tsx +4 -0
- package/extensions/dashboard-client/src/api/client.ts +14 -0
- package/extensions/dashboard-client/src/components/ActiveReposTable.tsx +21 -12
- package/extensions/dashboard-client/src/components/ProviderCacheCard.tsx +56 -0
- package/extensions/dashboard-client/src/components/SavingsByModelTable.tsx +38 -57
- package/extensions/dashboard-client/src/tabs/CacheTab.tsx +1 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +355 -0
- package/extensions/dashboard-client/tsconfig.json +3 -2
- package/extensions/dashboard-client/vite.config.ts +2 -0
- package/extensions/dashboard-server/api-contracts/endpoints.ts +36 -3
- package/extensions/dashboard-server/api-contracts/index.ts +7 -0
- package/extensions/dashboard-server/api-contracts/memory.ts +27 -0
- package/extensions/dashboard-server/api-contracts/multi-repo.ts +231 -231
- package/extensions/dashboard-server/api-contracts/provider-cache.ts +37 -0
- package/extensions/dashboard-server/api-contracts/setup.ts +58 -0
- package/extensions/dashboard-server/index-reader.ts +138 -121
- package/extensions/dashboard-server/routes-cache.ts +161 -85
- package/extensions/dashboard-server/routes-memory.ts +63 -0
- package/extensions/dashboard-server/routes-repo.ts +36 -36
- package/extensions/dashboard-server/routes-setup.ts +181 -0
- package/extensions/dashboard-server/routes.ts +2 -0
- package/extensions/dashboard-server/server.ts +6 -0
- package/extensions/mega-commands.ts +211 -1
- package/extensions/mega-config.ts +18 -0
- package/extensions/mega-events/agent-handlers.ts +44 -5
- package/extensions/mega-events/compact-handlers.ts +1 -0
- package/extensions/mega-events/context-handler.ts +45 -110
- package/extensions/mega-events/context-hwm.ts +85 -0
- package/extensions/mega-events/error-classifier.ts +156 -124
- package/extensions/mega-events/mirror-append.ts +155 -0
- package/extensions/mega-events/outage-advisor.ts +79 -0
- package/extensions/mega-events/perf-handler.ts +79 -5
- package/extensions/mega-events/recall-tail.ts +88 -0
- package/extensions/mega-events/session-handlers.ts +14 -7
- package/extensions/mega-runtime/helpers.ts +14 -0
- package/extensions/mega-runtime/reset-runtime.ts +6 -0
- package/extensions/mega-runtime/runtime.ts +7 -0
- package/package.json +5 -2
- package/src/embedder.ts +42 -2
- package/src/memoryStats.ts +107 -0
- package/src/prefix-break.ts +83 -0
- package/src/pricing.ts +2 -2
- package/src/store/sqlite/perf-samples.ts +215 -22
- package/src/store/turns/memory-store.ts +10 -1
- package/src/store/turns/sqlite-store.ts +27 -15
- package/src/store/turns/types.ts +21 -0
- package/src/store/vectorIndex.ts +33 -4
- package/dist/extensions/conflict-scan.test.js +0 -115
- package/dist/extensions/dashboard-server/api-contracts.test.js +0 -884
- package/dist/extensions/dashboard-server/html.test.js +0 -52
- package/dist/extensions/dashboard-server/perf-server.test.js +0 -80
- package/dist/extensions/dashboard-server/routes-cache.test.js +0 -248
- package/dist/extensions/dashboard-server/server.test.js +0 -120
- package/dist/extensions/dashboard-server-s32.test.js +0 -181
- package/dist/extensions/dashboard-server.test.js +0 -339
- package/dist/extensions/mega-cache-replay.test.js +0 -400
- package/dist/extensions/mega-compact-s38.test.js +0 -820
- package/dist/extensions/mega-compact.test.js +0 -1112
- package/dist/extensions/mega-events.test.js +0 -47
- package/dist/extensions/mega-game-cmds.test.js +0 -163
- package/dist/extensions/mega-runtime/snapshot.test.js +0 -127
- package/dist/extensions/mega-runtime/state.test.js +0 -266
- package/dist/extensions/mega-runtime/widget.test.js +0 -343
- package/dist/extensions/mega-shutdown-widget.test.js +0 -121
- package/dist/extensions/mega-teamrun.test.js +0 -156
- package/dist/extensions/mega-trim.test.js +0 -58
- package/dist/extensions/mega-turn-store.test.js +0 -68
- package/dist/src/boundary.test.js +0 -170
- package/dist/src/compact.test.js +0 -78
- package/dist/src/config/themes.test.js +0 -94
- package/dist/src/dedup/dedup.test.js +0 -41
- package/dist/src/dedup/l1.test.js +0 -50
- package/dist/src/dedup/raptor/buildHistory.test.js +0 -292
- package/dist/src/dedup/raptor/multilevel-serve.test.js +0 -229
- package/dist/src/dedup/raptor/multilevel.test.js +0 -238
- package/dist/src/dedup/raptor/promote.test.js +0 -69
- package/dist/src/dedup/raptor/raptor.test.js +0 -248
- package/dist/src/dedup/raptor/retrieval.test.js +0 -95
- package/dist/src/dedup/raptor/serve-gate.test.js +0 -298
- package/dist/src/dedup/sprint12.test.js +0 -219
- package/dist/src/dedup-engine.test.js +0 -472
- package/dist/src/driftDetection.test.js +0 -87
- package/dist/src/e2e.test.js +0 -698
- package/dist/src/engine.test.js +0 -111
- package/dist/src/extractive.test.js +0 -147
- package/dist/src/fork.test.js +0 -81
- package/dist/src/game/scoring.test.js +0 -98
- package/dist/src/httpEmbedder.test.js +0 -277
- package/dist/src/importance.test.js +0 -372
- package/dist/src/intent.test.js +0 -78
- package/dist/src/log.test.js +0 -42
- package/dist/src/mechanical-fix.test.js +0 -65
- package/dist/src/memory.test.js +0 -70
- package/dist/src/memoryConsolidate.test.js +0 -38
- package/dist/src/memoryOps.test.js +0 -129
- package/dist/src/memoryRecall.test.js +0 -171
- package/dist/src/memoryRoundtrip.test.js +0 -137
- package/dist/src/metrics/turns.test.js +0 -152
- package/dist/src/mirror/mirror.test.js +0 -185
- package/dist/src/raptor-inject-summaries.test.js +0 -162
- package/dist/src/ratio.bench.test.js +0 -897
- package/dist/src/recall.integration.test.js +0 -77
- package/dist/src/recall.test.js +0 -379
- package/dist/src/sprint14.test.js +0 -219
- package/dist/src/sprint4x-rag-verification.test.js +0 -93
- package/dist/src/store/compression.test.js +0 -139
- package/dist/src/store/memoryIndex.test.js +0 -51
- package/dist/src/store/migrate.test.js +0 -139
- package/dist/src/store/pgOpenGuard.test.js +0 -74
- package/dist/src/store/phase01.test.js +0 -81
- package/dist/src/store/phase04.test.js +0 -54
- package/dist/src/store/sprint10.test.js +0 -186
- package/dist/src/store/sqlite/game-achievements.test.js +0 -67
- package/dist/src/store/sqlite/game-scores.test.js +0 -106
- package/dist/src/store/sqlite/game-state.test.js +0 -76
- package/dist/src/store/sqlite/global-index.test.js +0 -136
- package/dist/src/store/sqlite/mechanical-fix.test.js +0 -146
- package/dist/src/store/sqlite/perf-samples.test.js +0 -146
- package/dist/src/store/sqlite/raptor.test.js +0 -106
- package/dist/src/store/sqlite/turns.test.js +0 -183
- package/dist/src/store/sqlite.cachehit.test.js +0 -55
- package/dist/src/store/sqlite.dbmaint.test.js +0 -158
- package/dist/src/store/sqlite.dbmirror.test.js +0 -184
- package/dist/src/store/turns/contract-compliance.test.js +0 -428
- package/dist/src/store/turns/memory-store.test.js +0 -9
- package/dist/src/store/turns/migrations.test.js +0 -138
- package/dist/src/store/turns/sqlite-store.test.js +0 -144
- package/dist/src/store/vectorIndex.test.js +0 -123
- package/dist/src/store.test.js +0 -161
- package/dist/src/supersede.test.js +0 -36
- package/dist/src/topics/cluster.test.js +0 -150
- package/dist/src/topics/store.test.js +0 -117
- package/dist/src/types.test.js +0 -9
- package/dist/src/vector-search-cache.test.js +0 -157
- package/dist/src/vectorStore.test.js +0 -479
- package/dist/src/wiki.test.js +0 -171
- package/extensions/conflict-scan.test.ts +0 -129
- package/extensions/dashboard-client/dist/assets/AchievementsTab-DjxfYrDc.js +0 -2
- package/extensions/dashboard-client/dist/assets/CacheTab-Dnpv94wq.js +0 -2
- package/extensions/dashboard-client/dist/assets/CacheTab-Dnpv94wq.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-D4kGvsiQ.js +0 -2
- package/extensions/dashboard-client/dist/assets/ReposTab-C0Wnrf2u.js +0 -2
- package/extensions/dashboard-client/dist/assets/ReposTab-C0Wnrf2u.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-UqljSyP-.js +0 -2
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-UqljSyP-.js.map +0 -1
- package/extensions/dashboard-client/dist/assets/index-BX0bcgLu.js.map +0 -1
- package/extensions/dashboard-server/api-contracts.test.ts +0 -1065
- package/extensions/dashboard-server/html.test.ts +0 -62
- package/extensions/dashboard-server/perf-server.test.ts +0 -101
- package/extensions/dashboard-server/routes-cache.test.ts +0 -302
- package/extensions/dashboard-server/server.test.ts +0 -131
- package/extensions/dashboard-server-s32.test.ts +0 -195
- package/extensions/dashboard-server.test.ts +0 -382
- package/extensions/mega-cache-replay.test.ts +0 -526
- package/extensions/mega-compact-s38.test.ts +0 -872
- package/extensions/mega-compact.test.ts +0 -1509
- package/extensions/mega-events.test.ts +0 -55
- package/extensions/mega-game-cmds.test.ts +0 -197
- package/extensions/mega-runtime/snapshot.test.ts +0 -139
- package/extensions/mega-runtime/state.test.ts +0 -262
- package/extensions/mega-runtime/widget.test.ts +0 -468
- package/extensions/mega-shutdown-widget.test.ts +0 -141
- package/extensions/mega-teamrun.test.ts +0 -176
- package/extensions/mega-trim.test.ts +0 -64
- package/extensions/mega-turn-store.test.ts +0 -108
- package/src/boundary.test.ts +0 -187
- package/src/compact.test.ts +0 -99
- package/src/config/themes.test.ts +0 -116
- package/src/dedup/dedup.test.ts +0 -46
- package/src/dedup/l1.test.ts +0 -57
- package/src/dedup/raptor/buildHistory.test.ts +0 -353
- package/src/dedup/raptor/multilevel-serve.test.ts +0 -273
- package/src/dedup/raptor/multilevel.test.ts +0 -325
- package/src/dedup/raptor/promote.test.ts +0 -82
- package/src/dedup/raptor/raptor.test.ts +0 -297
- package/src/dedup/raptor/retrieval.test.ts +0 -118
- package/src/dedup/raptor/serve-gate.test.ts +0 -348
- package/src/dedup/sprint12.test.ts +0 -242
- package/src/dedup-engine.test.ts +0 -670
- package/src/driftDetection.test.ts +0 -100
- package/src/e2e.test.ts +0 -843
- package/src/engine.test.ts +0 -123
- package/src/extractive.test.ts +0 -174
- package/src/fork.test.ts +0 -94
- package/src/game/scoring.test.ts +0 -103
- package/src/httpEmbedder.test.ts +0 -286
- package/src/importance.test.ts +0 -538
- package/src/intent.test.ts +0 -87
- package/src/log.test.ts +0 -47
- package/src/mechanical-fix.test.ts +0 -70
- package/src/memory.test.ts +0 -92
- package/src/memoryConsolidate.test.ts +0 -47
- package/src/memoryOps.test.ts +0 -148
- package/src/memoryRecall.test.ts +0 -194
- package/src/memoryRoundtrip.test.ts +0 -155
- package/src/metrics/turns.test.ts +0 -165
- package/src/mirror/mirror.test.ts +0 -240
- package/src/raptor-inject-summaries.test.ts +0 -228
- package/src/ratio.bench.test.ts +0 -1316
- package/src/recall.integration.test.ts +0 -96
- package/src/recall.test.ts +0 -467
- package/src/sprint14.test.ts +0 -245
- package/src/sprint4x-rag-verification.test.ts +0 -119
- package/src/store/compression.test.ts +0 -168
- package/src/store/memoryIndex.test.ts +0 -61
- package/src/store/migrate.test.ts +0 -158
- package/src/store/pgOpenGuard.test.ts +0 -89
- package/src/store/phase01.test.ts +0 -88
- package/src/store/phase04.test.ts +0 -58
- package/src/store/sprint10.test.ts +0 -214
- package/src/store/sqlite/game-achievements.test.ts +0 -80
- package/src/store/sqlite/game-scores.test.ts +0 -132
- package/src/store/sqlite/game-state.test.ts +0 -89
- package/src/store/sqlite/global-index.test.ts +0 -222
- package/src/store/sqlite/mechanical-fix.test.ts +0 -162
- package/src/store/sqlite/perf-samples.test.ts +0 -169
- package/src/store/sqlite/raptor.test.ts +0 -139
- package/src/store/sqlite/turns.test.ts +0 -218
- package/src/store/sqlite.cachehit.test.ts +0 -68
- package/src/store/sqlite.dbmaint.test.ts +0 -193
- package/src/store/sqlite.dbmirror.test.ts +0 -229
- package/src/store/turns/contract-compliance.test.ts +0 -562
- package/src/store/turns/memory-store.test.ts +0 -15
- package/src/store/turns/migrations.test.ts +0 -161
- package/src/store/turns/sqlite-store.test.ts +0 -161
- package/src/store/vectorIndex.test.ts +0 -140
- package/src/store.test.ts +0 -191
- package/src/supersede.test.ts +0 -42
- package/src/topics/cluster.test.ts +0 -176
- package/src/topics/store.test.ts +0 -132
- package/src/types.test.ts +0 -10
- package/src/vector-search-cache.test.ts +0 -190
- package/src/vectorStore.test.ts +0 -533
- package/src/wiki.test.ts +0 -217
|
@@ -18,11 +18,13 @@ import { isMegaCache } from "../../src/game/scoring.js";
|
|
|
18
18
|
import { resolveRepoRoot } from "../mega-config.js";
|
|
19
19
|
import {
|
|
20
20
|
classifyError,
|
|
21
|
+
classifyErrorDetailed,
|
|
21
22
|
errorRetryBackoffMs,
|
|
22
23
|
extractErrorSignature,
|
|
23
24
|
isKnownRetryableTransient,
|
|
24
25
|
} from "./error-classifier.js";
|
|
25
26
|
import { safeSendUserMessage } from "./send-safe.js";
|
|
27
|
+
import { maybeSendProviderOutageAdvisory } from "./outage-advisor.js";
|
|
26
28
|
import { vectorStats } from "../../src/vectorStore.js";
|
|
27
29
|
|
|
28
30
|
/** Register agent/turn tracking event handlers. */
|
|
@@ -187,7 +189,10 @@ export function registerAgentHandlers(
|
|
|
187
189
|
setTimeout(() => {
|
|
188
190
|
try {
|
|
189
191
|
if (runtime.rt.sessionId !== liveSid) return; // session reset
|
|
190
|
-
|
|
192
|
+
// IMPORTANT: recompute Date.now() inside the timeout.
|
|
193
|
+
// `now` above is the durable-trim handler's timestamp and can be
|
|
194
|
+
// ~500ms stale by the time this callback runs.
|
|
195
|
+
const since2 = Date.now() - (runtime.rt.lastNativeCompactAt ?? 0);
|
|
191
196
|
if (
|
|
192
197
|
runtime.rt.lastNativeCompactAt !== stamp &&
|
|
193
198
|
since2 < cooldownMs
|
|
@@ -265,6 +270,16 @@ export function registerAgentHandlers(
|
|
|
265
270
|
runtime.dashboard.event("turn_end", { turnIndex: event.turnIndex });
|
|
266
271
|
runtime.snapshot(ctx);
|
|
267
272
|
|
|
273
|
+
// S53: consume staged recall blocks ONLY if they were actually injected
|
|
274
|
+
// into a view this turn. If no context event fired (edge: turn ended
|
|
275
|
+
// before any LLM call), recallInjectedThisTurn stays false and the blocks
|
|
276
|
+
// remain staged for the next turn's first context event.
|
|
277
|
+
if (config.recallTailInject && runtime.rt.recallInjectedThisTurn) {
|
|
278
|
+
runtime.pendingRecallBlock = undefined;
|
|
279
|
+
runtime.pendingMemoryRecallBlock = undefined;
|
|
280
|
+
runtime.rt.recallInjectedThisTurn = false;
|
|
281
|
+
}
|
|
282
|
+
|
|
268
283
|
// S43 (per-turn tracking): record one turn row with the cached metrics so
|
|
269
284
|
// the turn layer is queryable + forkable. Best-effort + non-fatal: a write
|
|
270
285
|
// failure never breaks the agent loop.
|
|
@@ -393,6 +408,7 @@ export function registerAgentHandlers(
|
|
|
393
408
|
// S28 handles; nothing for S38 to do here.
|
|
394
409
|
} else {
|
|
395
410
|
const category = classifyError(event.message);
|
|
411
|
+
const detail = classifyErrorDetailed(event.message);
|
|
396
412
|
// R3: stateful poisoned-context signal — repeated identical error text
|
|
397
413
|
// across consecutive turns. The classifier is stateless, so this
|
|
398
414
|
// upgrade happens here. A 'transient' (or 'poisoned-context') turn
|
|
@@ -430,6 +446,12 @@ export function registerAgentHandlers(
|
|
|
430
446
|
// (error-classifier.ts) so the two never drift.
|
|
431
447
|
if (!isKnownRetryableTransient(errSig)) {
|
|
432
448
|
effectiveCategory = "poisoned-context";
|
|
449
|
+
} else {
|
|
450
|
+
runtime.logger.info("repeat-upgrade-declined", {
|
|
451
|
+
sessionId: runtime.rt.sessionId,
|
|
452
|
+
signature: (errSig || '').slice(0, 500),
|
|
453
|
+
repeatCount: runtime.rt.errorTextRepeatCount,
|
|
454
|
+
});
|
|
433
455
|
}
|
|
434
456
|
}
|
|
435
457
|
}
|
|
@@ -445,6 +467,9 @@ export function registerAgentHandlers(
|
|
|
445
467
|
runtime.rt.consecutiveErrors = 0; // S38.6: circuit-breaker reset on success
|
|
446
468
|
// R4: a successful assistant turn consumes any queued nudge.
|
|
447
469
|
runtime.rt.retryNudgePending = false;
|
|
470
|
+
// R10: reset outage advisory so a recovered-then-flapping
|
|
471
|
+
// provider re-advises once per episode.
|
|
472
|
+
runtime.rt.providerOutageAdvised = false;
|
|
448
473
|
} else if (effectiveCategory === "compaction-noop") {
|
|
449
474
|
// (4) pi race / manual compact catch — NOT retryable. The compaction
|
|
450
475
|
// already succeeded via pi's native path; retrying would race again
|
|
@@ -540,22 +565,31 @@ export function registerAgentHandlers(
|
|
|
540
565
|
runtime.rt.consecutiveErrors++; // still counts toward the circuit breaker
|
|
541
566
|
runtime.rt.poisonedCount++; // R7: dashboard counter
|
|
542
567
|
const sig = errSig || "unknown";
|
|
543
|
-
// (a) dashboard + log
|
|
568
|
+
// (a) dashboard + log — R11: include signal + rawText for forensics
|
|
544
569
|
runtime.dashboard.event("poisoned_context", {
|
|
545
570
|
signature: sig,
|
|
546
571
|
repeatCount: runtime.rt.errorTextRepeatCount,
|
|
547
572
|
turnIndex: event.turnIndex,
|
|
548
573
|
sessionId: runtime.rt.sessionId,
|
|
574
|
+
signal: detail.signal,
|
|
575
|
+
rawText: (errSig || '').slice(0, 500),
|
|
576
|
+
...(detail.httpStatus !== undefined ? { httpStatus: detail.httpStatus } : {}),
|
|
549
577
|
});
|
|
550
578
|
runtime.logger.warn("poisoned-context", {
|
|
551
579
|
sessionId: runtime.rt.sessionId,
|
|
552
580
|
turnIndex: event.turnIndex,
|
|
553
581
|
signature: sig,
|
|
554
582
|
repeatCount: runtime.rt.errorTextRepeatCount,
|
|
583
|
+
signal: detail.signal,
|
|
584
|
+
rawText: (errSig || '').slice(0, 500),
|
|
585
|
+
...(detail.httpStatus !== undefined ? { httpStatus: detail.httpStatus } : {}),
|
|
555
586
|
});
|
|
556
|
-
// (b)
|
|
557
|
-
|
|
558
|
-
|
|
587
|
+
// (b) throttle flag: set unconditionally so the advise fires at
|
|
588
|
+
// most once per session regardless of channel.
|
|
589
|
+
runtime.rt.poisonedAdviseSent = true;
|
|
590
|
+
// Legacy flag-OFF path: user-role advise message.
|
|
591
|
+
// Default ON (advisoryChannel=true): dashboard-only, no user message.
|
|
592
|
+
if (!config.advisoryChannel) {
|
|
559
593
|
// PREVENT-PI-003: user-role sendUserMessage only.
|
|
560
594
|
await safeSendUserMessage(
|
|
561
595
|
pi,
|
|
@@ -607,6 +641,11 @@ export function registerAgentHandlers(
|
|
|
607
641
|
}
|
|
608
642
|
// S38.6: circuit-breaker — stop retrying after too many consecutive errors.
|
|
609
643
|
runtime.rt.consecutiveErrors++;
|
|
644
|
+
// R10: send calm "provider outage" advisory once per episode.
|
|
645
|
+
await maybeSendProviderOutageAdvisory(
|
|
646
|
+
effectiveCategory, runtime, pi, config,
|
|
647
|
+
{ signal: detail.signal, rawText: (errSig || '').slice(0, 500) },
|
|
648
|
+
);
|
|
610
649
|
if (runtime.rt.consecutiveErrors > config.maxConsecutiveErrors) {
|
|
611
650
|
runtime.dashboard.event("error_retry_circuit_open", {
|
|
612
651
|
consecutive: runtime.rt.consecutiveErrors,
|
|
@@ -69,6 +69,7 @@ async function nudgeResume(pi: ExtensionAPI, runtime: MegaRuntime): Promise<void
|
|
|
69
69
|
const now = Date.now();
|
|
70
70
|
if (now >= runtime.resumeNudgeUntil) {
|
|
71
71
|
runtime.resumeNudgeUntil = now + 30_000;
|
|
72
|
+
runtime.rt.extensionInitiatedTurn = true; // R13: suppress self-classification
|
|
72
73
|
await safeSendUserMessage(
|
|
73
74
|
pi,
|
|
74
75
|
"[mega-compact] continue from the compacted context above.",
|
|
@@ -13,10 +13,8 @@ import type {
|
|
|
13
13
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
14
14
|
import {
|
|
15
15
|
openStore,
|
|
16
|
-
appendRawTranscript,
|
|
17
16
|
writeCheckpointEpoch,
|
|
18
17
|
type CheckpointEpoch,
|
|
19
|
-
type RawTranscriptRow,
|
|
20
18
|
} from "../../src/store/sqlite.js";
|
|
21
19
|
import { epochIdFor } from "../../src/mirror/epoch.js";
|
|
22
20
|
import { autoCompactCheck } from "../../src/compact.js";
|
|
@@ -37,84 +35,8 @@ import {
|
|
|
37
35
|
pressureRatio,
|
|
38
36
|
type MegaConfig,
|
|
39
37
|
} from "../mega-config.js";
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Recursively canonicalize a value for deterministic JSON serialization:
|
|
44
|
-
* - Objects: keys sorted alphabetically, values recursively canonicalized
|
|
45
|
-
* - Arrays: elements recursively canonicalized (array ORDER is preserved)
|
|
46
|
-
* - Primitives: returned as-is
|
|
47
|
-
*
|
|
48
|
-
* F5 fix: shallow-sorted JSON.stringify(content, Object.keys(content).sort())
|
|
49
|
-
* omitted nested keys not in the top-level keys array and only sorted one level.
|
|
50
|
-
* This recursively sorts every object at every depth so semantically-equal
|
|
51
|
-
* differently-ordered content hashes identically.
|
|
52
|
-
*/
|
|
53
|
-
function canonicalize(value: unknown): unknown {
|
|
54
|
-
if (value === null || value === undefined) return value;
|
|
55
|
-
if (typeof value !== "object") return value;
|
|
56
|
-
if (Array.isArray(value)) return value.map(canonicalize);
|
|
57
|
-
// Plain object: sort keys, recursively canonicalize values.
|
|
58
|
-
const sorted = Object.keys(value as Record<string, unknown>).sort();
|
|
59
|
-
const out: Record<string, unknown> = {};
|
|
60
|
-
for (const k of sorted) {
|
|
61
|
-
out[k] = canonicalize((value as Record<string, unknown>)[k]);
|
|
62
|
-
}
|
|
63
|
-
return out;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Convert a pi AgentMessage to a RawTranscriptRow for the DB mirror.
|
|
68
|
-
* content_bytes is canonical JSON (sorted keys, recursive) for deterministic
|
|
69
|
-
* storage; contentHash is the canonical digest (normalize + hash) that matches
|
|
70
|
-
* what dedupTranscript computes so the two pipelines use the same linkage key.
|
|
71
|
-
*
|
|
72
|
-
* F4 fix: the hash key MUST match on both sides of the append/dedup split.
|
|
73
|
-
* Using computeContentDigest here (normalize → hash) ensures content_ref set
|
|
74
|
-
* by dedupTranscript always resolves to an existing dedup_mirror row even for
|
|
75
|
-
* whitespace/case-variant content. F5 fix: recursive canonicalize replaces the
|
|
76
|
-
* broken shallow-sorted JSON.stringify replacer.
|
|
77
|
-
*/
|
|
78
|
-
function toRawTranscriptRow(
|
|
79
|
-
msg: AgentMessage,
|
|
80
|
-
sessionId: string,
|
|
81
|
-
epochId: string,
|
|
82
|
-
currentTurn?: number,
|
|
83
|
-
): RawTranscriptRow | null {
|
|
84
|
-
// Narrow to Message union (has content + timestamp).
|
|
85
|
-
const m = msg as {
|
|
86
|
-
role?: string;
|
|
87
|
-
content?: unknown;
|
|
88
|
-
timestamp?: number;
|
|
89
|
-
toolName?: string;
|
|
90
|
-
};
|
|
91
|
-
const content = m.content;
|
|
92
|
-
if (content == null || content === "") return null;
|
|
93
|
-
// Canonical bytes: string content → normalize for consistent byte content;
|
|
94
|
-
// object content → recursive canonicalize then JSON (no replacer).
|
|
95
|
-
const contentBytes =
|
|
96
|
-
typeof content === "string"
|
|
97
|
-
? content // F5: strings are primitives; their byte content is fixed
|
|
98
|
-
: JSON.stringify(canonicalize(content));
|
|
99
|
-
// F4 fix: use the same digest as dedupTranscript so contentHash is consistent
|
|
100
|
-
// on both sides of the append/dedup split. computeContentDigest normalizes
|
|
101
|
-
// (strip ANSI, NFC, case-fold, collapse whitespace) then hashes → the same
|
|
102
|
-
// key is stored in raw_transcript.content_hash AND used as the dedup link.
|
|
103
|
-
const { contentHash } = computeContentDigest(contentBytes);
|
|
104
|
-
return {
|
|
105
|
-
contentHash,
|
|
106
|
-
sessionId,
|
|
107
|
-
seq: 0, // assigned by appendRawTranscript (COALESCE(MAX(seq),0)+1)
|
|
108
|
-
role: m.role ?? "unknown",
|
|
109
|
-
contentBytes,
|
|
110
|
-
toolName: m.toolName ?? null,
|
|
111
|
-
messageTimestamp: m.timestamp ?? null,
|
|
112
|
-
checkpointEpoch: epochId,
|
|
113
|
-
// S50: label the row with the turn that produced it (per-turn dedup /
|
|
114
|
-
// compression-by-turn metrics). Null when the writer omits it (back-compat).
|
|
115
|
-
turnIndex: currentTurn ?? null,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
38
|
+
import { appendMirrorMessages } from "./mirror-append.js";
|
|
39
|
+
import { stagedForTail, withRecallTail } from "./recall-tail.js";
|
|
118
40
|
|
|
119
41
|
/** Register the context event handler (live-trim auto-trigger). */
|
|
120
42
|
export function registerContextHandler(
|
|
@@ -140,6 +62,16 @@ export function registerContextHandler(
|
|
|
140
62
|
const usage = ctx.getContextUsage();
|
|
141
63
|
const pct = usage?.percent;
|
|
142
64
|
const messages = event.messages;
|
|
65
|
+
// S53: helper to inject the staged recall/memory block as a user-role
|
|
66
|
+
// tail message at any view-return point. Returns undefined when nothing
|
|
67
|
+
// is staged (or the flag is OFF) so the caller falls through to its
|
|
68
|
+
// normal return. The F3 mirror append (above the gates) runs on the
|
|
69
|
+
// REAL transcript before any view is built, so the injected tail never
|
|
70
|
+
// reaches raw_transcript (PREVENT-PI: append-only, view-only).
|
|
71
|
+
const tailResult = (msgs?: readonly AgentMessage[]) => {
|
|
72
|
+
if (!stagedForTail(runtime, config)) return undefined;
|
|
73
|
+
return { messages: withRecallTail(msgs ?? messages, runtime, config) };
|
|
74
|
+
};
|
|
143
75
|
// Always track context for the dashboard/widget, even when auto is off.
|
|
144
76
|
// (v0.8 regression: !config.auto gate sat above this, leaving ctx stats
|
|
145
77
|
// null -> widget '?% / ?/?' when auto disabled. Track first, THEN gate.)
|
|
@@ -162,30 +94,35 @@ export function registerContextHandler(
|
|
|
162
94
|
runtime.lastCtxPercent = pct ?? null;
|
|
163
95
|
runtime.lastCtxWindow = usage?.contextWindow ?? 0;
|
|
164
96
|
runtime.snapshot(ctx);
|
|
165
|
-
if (!config.auto)
|
|
97
|
+
if (!config.auto) {
|
|
98
|
+
const tailed = tailResult();
|
|
99
|
+
if (tailed) return tailed;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
166
102
|
|
|
167
103
|
const view = viewForFallback ?? runtime.engineView(messages);
|
|
168
104
|
|
|
169
|
-
// S27 DB-mirror: append
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
105
|
+
// S27 DB-mirror: append incoming messages to raw_transcript.
|
|
106
|
+
// Runs BEFORE fast-gate so every message is captured, even if we
|
|
107
|
+
// don't compact this turn. Append is idempotent (content_hash PK).
|
|
108
|
+
// F3: high-water mark (mirror-append.ts) skips already-processed
|
|
109
|
+
// messages on subsequent events. On fork/rewind (shorter list or
|
|
110
|
+
// boundary hash mismatch) the mark is dropped, falling back to a
|
|
111
|
+
// full reprocess.
|
|
112
|
+
if (config.dbMirror) {
|
|
113
|
+
try {
|
|
114
|
+
const db = openStore(runtime.currentStateDir);
|
|
115
|
+
appendMirrorMessages(
|
|
116
|
+
db,
|
|
117
|
+
messages,
|
|
179
118
|
runtime.rt.sessionId,
|
|
180
|
-
|
|
119
|
+
epochIdFor(runtime.rt.sessionId),
|
|
181
120
|
runtime.currentTurn,
|
|
182
121
|
);
|
|
183
|
-
|
|
122
|
+
} catch (e) {
|
|
123
|
+
runtime.logger.warn("db-mirror-append-fail", { error: String(e) });
|
|
184
124
|
}
|
|
185
|
-
} catch (e) {
|
|
186
|
-
runtime.logger.warn("db-mirror-append-fail", { error: String(e) });
|
|
187
125
|
}
|
|
188
|
-
}
|
|
189
126
|
|
|
190
127
|
// S29 FAST GATE: drive the auto-trigger off the context % (the number the
|
|
191
128
|
// menu bar shows), NOT the token count — the model under-reports tokens,
|
|
@@ -205,18 +142,18 @@ export function registerContextHandler(
|
|
|
205
142
|
// custom tier OR tiered-but-pct-unavailable → token gate (S27 fallback).
|
|
206
143
|
if (currentTokens < runtime.effectiveThreshold) {
|
|
207
144
|
runtime.diagCtxFastGate++;
|
|
208
|
-
return;
|
|
145
|
+
return tailResult() ?? undefined;
|
|
209
146
|
}
|
|
210
147
|
const check = autoCompactCheck(currentTokens, runtime.effectiveThreshold); // SERVER-STYLE CONFIRM (local)
|
|
211
148
|
if (!check.shouldCompact) {
|
|
212
149
|
runtime.diagCtxNoCompact++;
|
|
213
|
-
return;
|
|
150
|
+
return tailResult() ?? undefined;
|
|
214
151
|
}
|
|
215
152
|
gatePassed = true;
|
|
216
153
|
}
|
|
217
154
|
if (!gatePassed) {
|
|
218
155
|
runtime.diagCtxFastGate++;
|
|
219
|
-
return;
|
|
156
|
+
return tailResult() ?? undefined;
|
|
220
157
|
}
|
|
221
158
|
|
|
222
159
|
// D.2: Replay MUST be exempt from debounce — replay is free (no compute,
|
|
@@ -249,9 +186,8 @@ export function registerContextHandler(
|
|
|
249
186
|
runtime.snapshot(ctx);
|
|
250
187
|
// v0.8.7: shallow-copy the cached summary so pi's transformContext can't
|
|
251
188
|
// mutate the shared reference across replays (audit P3).
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
};
|
|
189
|
+
const replayView = [{ ...runtime.trimCache.summaryAgentMsg }, ...recent];
|
|
190
|
+
return tailResult(replayView) ?? { messages: replayView };
|
|
255
191
|
}
|
|
256
192
|
// else: context grew enough → fall through to re-compact (cache is stale)
|
|
257
193
|
}
|
|
@@ -261,7 +197,7 @@ export function registerContextHandler(
|
|
|
261
197
|
const now = Date.now();
|
|
262
198
|
if (now < runtime.debounceUntil) {
|
|
263
199
|
runtime.diagCtxDebounce++;
|
|
264
|
-
return;
|
|
200
|
+
return tailResult() ?? undefined;
|
|
265
201
|
}
|
|
266
202
|
runtime.debounceUntil = now + 2000;
|
|
267
203
|
|
|
@@ -290,11 +226,10 @@ export function registerContextHandler(
|
|
|
290
226
|
runtime.diagLiveTrimFires++;
|
|
291
227
|
runtime.diagLiveTrimReplays++;
|
|
292
228
|
runtime.snapshot(ctx);
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
};
|
|
229
|
+
const skipView = [{ ...runtime.trimCache.summaryAgentMsg }, ...recent];
|
|
230
|
+
return tailResult(skipView) ?? { messages: skipView };
|
|
296
231
|
}
|
|
297
|
-
return;
|
|
232
|
+
return tailResult() ?? undefined;
|
|
298
233
|
}
|
|
299
234
|
|
|
300
235
|
// S27 DB-mirror: write checkpoint_epoch with deterministic nonce.
|
|
@@ -460,7 +395,7 @@ export function registerContextHandler(
|
|
|
460
395
|
viewLen: view.length,
|
|
461
396
|
anchorUserMessages,
|
|
462
397
|
});
|
|
463
|
-
return; // unsafe / below anchor floor — no trim this call
|
|
398
|
+
return tailResult() ?? undefined; // unsafe / below anchor floor — no trim this call
|
|
464
399
|
}
|
|
465
400
|
const summaryMsg = liveTrimSummaryMessage({
|
|
466
401
|
compactedFrom: ran.result.compactedFrom,
|
|
@@ -515,10 +450,10 @@ export function registerContextHandler(
|
|
|
515
450
|
ctxPct: pct,
|
|
516
451
|
ctxTokens: usage?.tokens ?? null,
|
|
517
452
|
});
|
|
518
|
-
return { messages: [summaryAgentMsg, ...recent] };
|
|
453
|
+
return tailResult([summaryAgentMsg, ...recent]) ?? { messages: [summaryAgentMsg, ...recent] };
|
|
519
454
|
} catch {
|
|
520
455
|
runtime.diagCtxThrown++;
|
|
521
|
-
return; // non-fatal: no trim this call; the next context event retries
|
|
456
|
+
return tailResult() ?? undefined; // non-fatal: no trim this call; the next context event retries
|
|
522
457
|
}
|
|
523
458
|
});
|
|
524
459
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mega-events/context-hwm.ts — high-water mark for DB-mirror raw_transcript
|
|
3
|
+
* incremental append (F3 sprint).
|
|
4
|
+
*
|
|
5
|
+
* Stores the last-processed seq + content_hash per session so the context
|
|
6
|
+
* event only appends the tail on subsequent events. On fork/rewind (shorter
|
|
7
|
+
* message list or hash mismatch at the boundary), the mark is dropped so the
|
|
8
|
+
* next event falls back to a full reprocess.
|
|
9
|
+
*
|
|
10
|
+
* Non-fatal: every function logs and swallows errors; the agent loop is never
|
|
11
|
+
* broken (repo invariant).
|
|
12
|
+
*
|
|
13
|
+
* All queries parameterized (PREVENT-002); no `any` (PREVENT-011).
|
|
14
|
+
*/
|
|
15
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
16
|
+
|
|
17
|
+
export interface ContextHwm {
|
|
18
|
+
sessionId: string;
|
|
19
|
+
lastSeq: number;
|
|
20
|
+
lastContentHash: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const TABLE_DDL = `CREATE TABLE IF NOT EXISTS context_hwm (
|
|
24
|
+
session_id TEXT PRIMARY KEY,
|
|
25
|
+
last_seq INTEGER NOT NULL,
|
|
26
|
+
last_content_hash TEXT NOT NULL
|
|
27
|
+
)`;
|
|
28
|
+
|
|
29
|
+
/** Ensure the context_hwm table exists. Idempotent. */
|
|
30
|
+
export function ensureHwmTable(db: DatabaseSync): void {
|
|
31
|
+
try {
|
|
32
|
+
db.exec(TABLE_DDL);
|
|
33
|
+
} catch {
|
|
34
|
+
// non-fatal
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Read the high-water mark for a session. Returns undefined if none. */
|
|
39
|
+
export function readHwm(
|
|
40
|
+
db: DatabaseSync,
|
|
41
|
+
sessionId: string,
|
|
42
|
+
): ContextHwm | undefined {
|
|
43
|
+
try {
|
|
44
|
+
const row = db
|
|
45
|
+
.prepare(
|
|
46
|
+
"SELECT session_id, last_seq, last_content_hash FROM context_hwm WHERE session_id = ?",
|
|
47
|
+
)
|
|
48
|
+
.get(sessionId) as
|
|
49
|
+
| { session_id: string; last_seq: number; last_content_hash: string }
|
|
50
|
+
| undefined;
|
|
51
|
+
if (!row) return undefined;
|
|
52
|
+
return {
|
|
53
|
+
sessionId: row.session_id,
|
|
54
|
+
lastSeq: Number(row.last_seq),
|
|
55
|
+
lastContentHash: row.last_content_hash,
|
|
56
|
+
};
|
|
57
|
+
} catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Write (INSERT OR REPLACE) the high-water mark for a session. */
|
|
63
|
+
export function writeHwm(
|
|
64
|
+
db: DatabaseSync,
|
|
65
|
+
hwm: ContextHwm,
|
|
66
|
+
): void {
|
|
67
|
+
try {
|
|
68
|
+
db.prepare(
|
|
69
|
+
"INSERT OR REPLACE INTO context_hwm (session_id, last_seq, last_content_hash) VALUES (?, ?, ?)",
|
|
70
|
+
).run(hwm.sessionId, hwm.lastSeq, hwm.lastContentHash);
|
|
71
|
+
} catch {
|
|
72
|
+
// non-fatal
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Drop the high-water mark for a session (invalidation). */
|
|
77
|
+
export function dropHwm(db: DatabaseSync, sessionId: string): void {
|
|
78
|
+
try {
|
|
79
|
+
db.prepare("DELETE FROM context_hwm WHERE session_id = ?").run(sessionId);
|
|
80
|
+
} catch {
|
|
81
|
+
// non-fatal
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const TEST_ONLY = { TABLE_DDL };
|