pi-mega-compact 0.11.4 → 0.11.6
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/cache-stripes.js +8 -0
- package/dist/extensions/dashboard-server/api-contracts/endpoints.js +32 -0
- package/dist/extensions/dashboard-server/api-contracts/memory-map.js +1 -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 +135 -47
- package/dist/extensions/dashboard-server/routes-game.js +3 -0
- package/dist/extensions/dashboard-server/routes-memory-map.js +50 -0
- 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 +267 -0
- package/dist/extensions/dashboard-server/routes.js +4 -0
- package/dist/extensions/dashboard-server/server.js +13 -1
- package/dist/extensions/mega-commands.js +189 -1
- package/dist/extensions/mega-compact.js +5 -0
- package/dist/extensions/mega-config.js +7 -0
- package/dist/extensions/mega-events/agent-handlers.js +19 -4
- package/dist/extensions/mega-events/compact-handlers.js +1 -0
- package/dist/extensions/mega-events/context-handler.js +45 -92
- package/dist/extensions/mega-events/context-hwm.js +51 -0
- package/dist/extensions/mega-events/error-classifier.js +16 -5
- package/dist/extensions/mega-events/mirror-append.js +107 -0
- package/dist/extensions/mega-events/outage-advisor.js +7 -1
- package/dist/extensions/mega-events/perf-handler.js +134 -2
- package/dist/extensions/mega-events/recall-tail.js +59 -0
- package/dist/extensions/mega-events/separated-prompt.js +248 -0
- package/dist/extensions/mega-events/session-handlers.js +15 -8
- package/dist/extensions/mega-runtime/env-loader.js +56 -0
- package/dist/extensions/mega-runtime/reset-runtime.js +6 -0
- package/dist/extensions/mega-runtime/runtime-snapshot.js +1 -0
- package/dist/extensions/mega-runtime/runtime.js +7 -0
- package/dist/extensions/mega-runtime/snapshot.js +1 -0
- package/dist/extensions/mega-runtime/widget.js +5 -0
- package/dist/src/cache-stripe-impl.js +288 -0
- package/dist/src/cache-stripe.js +11 -0
- package/dist/src/config/stopwords.js +24 -0
- package/dist/src/config.js +17 -0
- package/dist/src/embedder.js +41 -2
- package/dist/src/memoryGraph.js +299 -0
- package/dist/src/memoryStats.js +75 -0
- package/dist/src/monitoring.js +13 -0
- package/dist/src/prefix-break.js +43 -0
- package/dist/src/pricing.js +1 -1
- package/dist/src/queryExpansion.js +163 -0
- package/dist/src/queryReformulation/cache.js +123 -0
- package/dist/src/queryReformulation/rrf.js +29 -0
- package/dist/src/queryReformulation/tfidf.js +61 -0
- package/dist/src/queryReformulation/vagueness.js +33 -0
- package/dist/src/queryReformulation.js +225 -0
- package/dist/src/recallMetrics.js +258 -0
- package/dist/src/store/sqlite/cache-stripes.js +133 -0
- package/dist/src/store/sqlite/fts5-search.js +68 -0
- package/dist/src/store/sqlite/perf-samples.js +145 -16
- package/dist/src/store/sqlite/schema.js +60 -1
- package/dist/src/store/sqlite.js +1 -0
- 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 +55 -10
- package/dist/src/tiered-router/types.js +18 -0
- package/dist/src/tieredRouter.js +421 -0
- package/dist/src/vectorStore.js +8 -6
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-vEo2MtE2.js → AchievementTiles-DR9cLGDL.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{AchievementTiles-vEo2MtE2.js.map → AchievementTiles-DR9cLGDL.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/AchievementsTab-svNUgJ1e.js +2 -0
- package/extensions/dashboard-client/dist/assets/{AchievementsTab-DjxfYrDc.js.map → AchievementsTab-svNUgJ1e.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/CacheTab-ASwhOMjR.js +2 -0
- package/extensions/dashboard-client/dist/assets/CacheTab-ASwhOMjR.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{ConfigTab-Cm6ymbmx.js → ConfigTab-CmmWheuW.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{ConfigTab-Cm6ymbmx.js.map → ConfigTab-CmmWheuW.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{EventsTab-DXWl_YzI.js → EventsTab-CFE7jLsa.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{EventsTab-DXWl_YzI.js.map → EventsTab-CFE7jLsa.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/GameTab-CJAX_th_.js +2 -0
- package/extensions/dashboard-client/dist/assets/{GameTab-BLDudcO5.js.map → GameTab-CJAX_th_.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLkKCztn.js → MaintenanceTab-P4SUsvMf.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MaintenanceTab-DLkKCztn.js.map → MaintenanceTab-P4SUsvMf.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-BBiH76eF.js +2 -0
- package/extensions/dashboard-client/dist/assets/MemoryMapTab-BBiH76eF.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{MetricsTab-Cq4u-rZF.js → MetricsTab-CHQscixy.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{MetricsTab-Cq4u-rZF.js.map → MetricsTab-CHQscixy.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/OverviewTab-DBs4DJdd.js +2 -0
- package/extensions/dashboard-client/dist/assets/{OverviewTab-D4kGvsiQ.js.map → OverviewTab-DBs4DJdd.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/ReposTab-DeFz76L5.js +2 -0
- package/extensions/dashboard-client/dist/assets/ReposTab-DeFz76L5.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DZC2-GCn.js → SessionsTab-BWNsj1OB.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{SessionsTab-DZC2-GCn.js.map → SessionsTab-BWNsj1OB.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/SetupTab-uS6A0xmw.js +2 -0
- package/extensions/dashboard-client/dist/assets/SetupTab-uS6A0xmw.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-CiqCOQuL.js +2 -0
- package/extensions/dashboard-client/dist/assets/TimeSavedCard-CiqCOQuL.js.map +1 -0
- package/extensions/dashboard-client/dist/assets/{TopicsTab-01G71hv1.js → TopicsTab-BWWQxltv.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TopicsTab-01G71hv1.js.map → TopicsTab-BWWQxltv.js.map} +1 -1
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DLRg0LZT.js → TurnsTab-CVz4f4-o.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{TurnsTab-DLRg0LZT.js.map → TurnsTab-CVz4f4-o.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-CUNn22iV.css +1 -0
- package/extensions/dashboard-client/dist/assets/index-DrktNOoT.js +42 -0
- package/extensions/dashboard-client/dist/assets/index-DrktNOoT.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-Bf5LOLSi.js} +2 -2
- package/extensions/dashboard-client/dist/assets/{useSSE-BBYt5UPB.js.map → useSSE-Bf5LOLSi.js.map} +1 -1
- package/extensions/dashboard-client/dist/index.html +2 -2
- package/extensions/dashboard-client/src/App.tsx +28 -8
- package/extensions/dashboard-client/src/api/client.ts +29 -0
- package/extensions/dashboard-client/src/components/ActiveReposTable.tsx +21 -12
- package/extensions/dashboard-client/src/components/CacheHitRateTrendCard.tsx +100 -0
- 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/components/StripeDistributionCard.tsx +110 -0
- package/extensions/dashboard-client/src/components/TabBar.tsx +49 -4
- package/extensions/dashboard-client/src/main.tsx +1 -0
- package/extensions/dashboard-client/src/styles/base.css +30 -0
- package/extensions/dashboard-client/src/styles/cache.css +167 -0
- package/extensions/dashboard-client/src/tabs/CacheTab.tsx +75 -12
- package/extensions/dashboard-client/src/tabs/MemoryMapTab.tsx +440 -0
- package/extensions/dashboard-client/src/tabs/SetupTab.tsx +418 -0
- package/extensions/dashboard-client/tsconfig.json +3 -2
- package/extensions/dashboard-client/vite.config.ts +2 -0
- package/extensions/dashboard-server/api-contracts/cache-stripes.ts +49 -0
- package/extensions/dashboard-server/api-contracts/endpoints.ts +66 -3
- package/extensions/dashboard-server/api-contracts/index.ts +22 -0
- package/extensions/dashboard-server/api-contracts/memory-map.ts +50 -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 +80 -0
- package/extensions/dashboard-server/index-reader.ts +138 -121
- package/extensions/dashboard-server/routes-cache.ts +186 -75
- package/extensions/dashboard-server/routes-game.ts +3 -0
- package/extensions/dashboard-server/routes-memory-map.ts +105 -0
- 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 +293 -0
- package/extensions/dashboard-server/routes.ts +4 -0
- package/extensions/dashboard-server/server.ts +12 -0
- package/extensions/mega-commands.ts +211 -1
- package/extensions/mega-compact.ts +5 -0
- package/extensions/mega-config.ts +27 -0
- package/extensions/mega-events/agent-handlers.ts +20 -4
- package/extensions/mega-events/compact-handlers.ts +1 -0
- package/extensions/mega-events/context-handler.ts +53 -110
- package/extensions/mega-events/context-hwm.ts +85 -0
- package/extensions/mega-events/error-classifier.ts +15 -4
- package/extensions/mega-events/mirror-append.ts +155 -0
- package/extensions/mega-events/outage-advisor.ts +11 -5
- package/extensions/mega-events/perf-handler.ts +190 -6
- package/extensions/mega-events/recall-tail.ts +88 -0
- package/extensions/mega-events/separated-prompt.ts +329 -0
- package/extensions/mega-events/session-handlers.ts +14 -7
- package/extensions/mega-runtime/env-loader.ts +55 -0
- package/extensions/mega-runtime/helpers.ts +14 -0
- package/extensions/mega-runtime/reset-runtime.ts +6 -0
- package/extensions/mega-runtime/runtime-snapshot.ts +1 -0
- package/extensions/mega-runtime/runtime.ts +7 -0
- package/extensions/mega-runtime/snapshot.ts +6 -0
- package/extensions/mega-runtime/widget-types.ts +3 -0
- package/extensions/mega-runtime/widget.ts +5 -0
- package/package.json +5 -2
- package/src/cache-stripe-impl.ts +385 -0
- package/src/cache-stripe.ts +18 -0
- package/src/config/stopwords.ts +25 -0
- package/src/config.ts +26 -0
- package/src/embedder.ts +42 -2
- package/src/memoryGraph.ts +438 -0
- package/src/memoryStats.ts +107 -0
- package/src/monitoring.ts +35 -0
- package/src/prefix-break.ts +83 -0
- package/src/pricing.ts +2 -2
- package/src/queryExpansion.ts +206 -0
- package/src/queryReformulation/cache.ts +169 -0
- package/src/queryReformulation/rrf.ts +51 -0
- package/src/queryReformulation/tfidf.ts +79 -0
- package/src/queryReformulation/vagueness.ts +38 -0
- package/src/queryReformulation.ts +355 -0
- package/src/recallMetrics.ts +388 -0
- package/src/store/sqlite/cache-stripes.ts +196 -0
- package/src/store/sqlite/fts5-search.ts +90 -0
- package/src/store/sqlite/perf-samples.ts +218 -23
- package/src/store/sqlite/schema.ts +60 -1
- package/src/store/sqlite.ts +1 -0
- 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 +71 -11
- package/src/tiered-router/types.ts +64 -0
- package/src/tieredRouter.ts +489 -0
- package/src/vectorStore.ts +9 -5
- 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 -1383
- 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/GameTab-BLDudcO5.js +0 -2
- 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-BEdKlpAB.css +0 -1
- package/extensions/dashboard-client/dist/assets/index-BX0bcgLu.js +0 -42
- 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 -1433
- 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
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { getStateDir } from "../../store.js";
|
|
17
17
|
import { openStore } from "./utils.js";
|
|
18
|
+
import type { PrefixBreak } from "../../prefix-break.js";
|
|
18
19
|
|
|
19
20
|
/** Sample kinds recorded into perf_samples. */
|
|
20
21
|
export type PerfKind =
|
|
@@ -22,12 +23,14 @@ export type PerfKind =
|
|
|
22
23
|
| "provider_latency_ms"
|
|
23
24
|
| "tps"
|
|
24
25
|
| "cache_hit_pct"
|
|
26
|
+
| "prefix_break"
|
|
25
27
|
| "rss_mb"
|
|
26
28
|
| "heap_mb"
|
|
27
29
|
| "cpu_user_ms"
|
|
28
30
|
| "cpu_sys_ms"
|
|
29
31
|
| "db_recompute_ms"
|
|
30
|
-
| "disk_write_ms"
|
|
32
|
+
| "disk_write_ms"
|
|
33
|
+
| "cache_health";
|
|
31
34
|
|
|
32
35
|
/** Allow-list of valid perf sample kinds (mirrors the table's domain). */
|
|
33
36
|
export const PERF_KINDS: readonly PerfKind[] = [
|
|
@@ -35,12 +38,14 @@ export const PERF_KINDS: readonly PerfKind[] = [
|
|
|
35
38
|
"provider_latency_ms",
|
|
36
39
|
"tps",
|
|
37
40
|
"cache_hit_pct",
|
|
41
|
+
"prefix_break",
|
|
38
42
|
"rss_mb",
|
|
39
43
|
"heap_mb",
|
|
40
44
|
"cpu_user_ms",
|
|
41
45
|
"cpu_sys_ms",
|
|
42
46
|
"db_recompute_ms",
|
|
43
47
|
"disk_write_ms",
|
|
48
|
+
"cache_health",
|
|
44
49
|
];
|
|
45
50
|
|
|
46
51
|
/** A single perf sample row (as stored + returned). */
|
|
@@ -137,30 +142,69 @@ export interface ProviderCacheLifetime {
|
|
|
137
142
|
firstSampleAt: string | null;
|
|
138
143
|
/** ISO timestamp of the most recent sample, or null if no samples. */
|
|
139
144
|
latestSampleAt: string | null;
|
|
145
|
+
/**
|
|
146
|
+
* Per-model breakdown of aggregates (F4). Samples without a model tag are
|
|
147
|
+
* omitted from this array (they remain in the flat totals above).
|
|
148
|
+
*/
|
|
149
|
+
byModel: ProviderCacheModelAgg[];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Per-model provider cache aggregate (F4). */
|
|
153
|
+
export interface ProviderCacheModelAgg {
|
|
154
|
+
/** Model label (modelName || modelId from meta, or null for untagged). */
|
|
155
|
+
model: string;
|
|
156
|
+
/** Average hit rate for this model (0-100). */
|
|
157
|
+
hitPct: number;
|
|
158
|
+
/** Sum of cache-read tokens for this model. */
|
|
159
|
+
totalCacheRead: number;
|
|
160
|
+
/** Sum of cache-write tokens for this model. */
|
|
161
|
+
totalCacheWrite: number;
|
|
162
|
+
/** Number of samples for this model. */
|
|
163
|
+
sampleCount: number;
|
|
140
164
|
}
|
|
141
165
|
|
|
142
166
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* Aggregates `cache_creation_input_tokens` / `cache_read_input_tokens` from
|
|
146
|
-
* the `meta` JSON column of `cache_hit_pct` samples (`json_extract`,
|
|
147
|
-
* available in node:sqlite ≥22.13 / SQLite ≥3.38). Returns a zeroed
|
|
148
|
-
* `ProviderCacheLifetime` when no samples exist (never undefined).
|
|
167
|
+
* Extract a model label from parsed meta (modelName or modelId), or null.
|
|
149
168
|
*/
|
|
150
|
-
|
|
151
|
-
|
|
169
|
+
function extractModelLabel(
|
|
170
|
+
meta: Record<string, unknown>,
|
|
171
|
+
): string | null {
|
|
172
|
+
if (typeof meta.modelName === "string" && meta.modelName.length > 0)
|
|
173
|
+
return meta.modelName;
|
|
174
|
+
if (typeof meta.modelId === "string" && meta.modelId.length > 0)
|
|
175
|
+
return meta.modelId;
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Build sorted byModel array from the model aggregation map.
|
|
181
|
+
*/
|
|
182
|
+
function byModelFromMap(
|
|
183
|
+
map: Map<string, { sumCr: number; sumCw: number; sumInp: number; sumHitPct: number; hitCount: number; samples: number }>,
|
|
184
|
+
): ProviderCacheModelAgg[] {
|
|
185
|
+
const out: ProviderCacheModelAgg[] = [];
|
|
186
|
+
for (const [model, m] of map) {
|
|
187
|
+
out.push({
|
|
188
|
+
model,
|
|
189
|
+
hitPct: m.hitCount > 0 ? m.sumHitPct / m.hitCount : 0,
|
|
190
|
+
totalCacheRead: m.sumCr,
|
|
191
|
+
totalCacheWrite: m.sumCw,
|
|
192
|
+
sampleCount: m.samples,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
out.sort((a, b) => b.sampleCount - a.sampleCount);
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Aggregate `cache_hit_pct` rows (ts + parsed meta) into a
|
|
201
|
+
* `ProviderCacheLifetime`. Shared by the lifetime and window readers so both
|
|
202
|
+
* use the identical aggregation formula. `meta` is parsed defensively
|
|
203
|
+
* (PREVENT-001 null-safe). Rows must be ascending by ts.
|
|
204
|
+
*/
|
|
205
|
+
function aggregateCacheRows(
|
|
206
|
+
rows: Array<{ ts: number; meta: string | null }>,
|
|
152
207
|
): ProviderCacheLifetime {
|
|
153
|
-
const db = openStore(stateDir);
|
|
154
|
-
const rows = db
|
|
155
|
-
.prepare(
|
|
156
|
-
`SELECT ts, meta FROM perf_samples
|
|
157
|
-
WHERE kind = ?
|
|
158
|
-
ORDER BY ts ASC`,
|
|
159
|
-
)
|
|
160
|
-
.all("cache_hit_pct") as Array<{
|
|
161
|
-
ts: number;
|
|
162
|
-
meta: string | null;
|
|
163
|
-
}>;
|
|
164
208
|
if (rows.length === 0) {
|
|
165
209
|
return {
|
|
166
210
|
sampleCount: 0,
|
|
@@ -170,6 +214,7 @@ export function readProviderCacheLifetime(
|
|
|
170
214
|
totalInput: 0,
|
|
171
215
|
firstSampleAt: null,
|
|
172
216
|
latestSampleAt: null,
|
|
217
|
+
byModel: [],
|
|
173
218
|
};
|
|
174
219
|
}
|
|
175
220
|
let totalCacheRead = 0;
|
|
@@ -177,6 +222,17 @@ export function readProviderCacheLifetime(
|
|
|
177
222
|
let totalInput = 0;
|
|
178
223
|
let sumHitPct = 0;
|
|
179
224
|
let hitPctCount = 0;
|
|
225
|
+
const modelMap = new Map<
|
|
226
|
+
string,
|
|
227
|
+
{
|
|
228
|
+
sumCr: number;
|
|
229
|
+
sumCw: number;
|
|
230
|
+
sumInp: number;
|
|
231
|
+
sumHitPct: number;
|
|
232
|
+
hitCount: number;
|
|
233
|
+
samples: number;
|
|
234
|
+
}
|
|
235
|
+
>();
|
|
180
236
|
for (const r of rows) {
|
|
181
237
|
if (r.meta != null) {
|
|
182
238
|
let meta: Record<string, unknown> | null = null;
|
|
@@ -208,6 +264,31 @@ export function readProviderCacheLifetime(
|
|
|
208
264
|
sumHitPct += (cr / denom) * 100;
|
|
209
265
|
hitPctCount++;
|
|
210
266
|
}
|
|
267
|
+
// Per-model grouping (F4)
|
|
268
|
+
const modelLabel = extractModelLabel(meta);
|
|
269
|
+
if (modelLabel != null) {
|
|
270
|
+
let m = modelMap.get(modelLabel);
|
|
271
|
+
if (!m) {
|
|
272
|
+
m = {
|
|
273
|
+
sumCr: 0,
|
|
274
|
+
sumCw: 0,
|
|
275
|
+
sumInp: 0,
|
|
276
|
+
sumHitPct: 0,
|
|
277
|
+
hitCount: 0,
|
|
278
|
+
samples: 0,
|
|
279
|
+
};
|
|
280
|
+
modelMap.set(modelLabel, m);
|
|
281
|
+
}
|
|
282
|
+
m.sumCr += cr;
|
|
283
|
+
m.sumCw += cw;
|
|
284
|
+
m.sumInp += inp;
|
|
285
|
+
m.samples++;
|
|
286
|
+
if (denom > 0) {
|
|
287
|
+
m.sumHitPct += (cr / denom) * 100;
|
|
288
|
+
m.hitCount++;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Untagged samples are omitted from byModel
|
|
211
292
|
}
|
|
212
293
|
}
|
|
213
294
|
}
|
|
@@ -219,9 +300,62 @@ export function readProviderCacheLifetime(
|
|
|
219
300
|
totalInput,
|
|
220
301
|
firstSampleAt: new Date(rows[0].ts).toISOString(),
|
|
221
302
|
latestSampleAt: new Date(rows[rows.length - 1].ts).toISOString(),
|
|
303
|
+
byModel: byModelFromMap(modelMap),
|
|
222
304
|
};
|
|
223
305
|
}
|
|
224
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Read lifetime provider prompt cache aggregates from `perf_samples`.
|
|
309
|
+
*
|
|
310
|
+
* Aggregates `cache_creation_input_tokens` / `cache_read_input_tokens` from
|
|
311
|
+
* the `meta` JSON column of `cache_hit_pct` samples (`json_extract`,
|
|
312
|
+
* available in node:sqlite >=22.13 / SQLite >=3.38). Returns a zeroed
|
|
313
|
+
* `ProviderCacheLifetime` when no samples exist (never undefined).
|
|
314
|
+
*/
|
|
315
|
+
export function readProviderCacheLifetime(
|
|
316
|
+
stateDir: string = getStateDir(),
|
|
317
|
+
): ProviderCacheLifetime {
|
|
318
|
+
const db = openStore(stateDir);
|
|
319
|
+
const rows = db
|
|
320
|
+
.prepare(
|
|
321
|
+
`SELECT ts, meta FROM perf_samples
|
|
322
|
+
WHERE kind = ?
|
|
323
|
+
ORDER BY ts ASC`,
|
|
324
|
+
)
|
|
325
|
+
.all("cache_hit_pct") as Array<{
|
|
326
|
+
ts: number;
|
|
327
|
+
meta: string | null;
|
|
328
|
+
}>;
|
|
329
|
+
return aggregateCacheRows(rows);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Read provider prompt cache aggregates over a trailing window of `minutes`
|
|
334
|
+
* (samples with ts >= now - minutes*60_000). Same aggregate shape as
|
|
335
|
+
* `readProviderCacheLifetime`; the existing lifetime reader is untouched.
|
|
336
|
+
* Returns a zeroed `ProviderCacheLifetime` when no samples fall in the window.
|
|
337
|
+
*/
|
|
338
|
+
export function readProviderCacheWindow(
|
|
339
|
+
stateDir: string = getStateDir(),
|
|
340
|
+
minutes: number,
|
|
341
|
+
): ProviderCacheLifetime {
|
|
342
|
+
const db = openStore(stateDir);
|
|
343
|
+
const sinceTs = Date.now() - minutes * 60_000;
|
|
344
|
+
const rows = db
|
|
345
|
+
.prepare(
|
|
346
|
+
`SELECT ts, meta FROM perf_samples
|
|
347
|
+
WHERE kind = ? AND ts >= ?
|
|
348
|
+
ORDER BY ts ASC`,
|
|
349
|
+
)
|
|
350
|
+
.all("cache_hit_pct", sinceTs) as Array<{
|
|
351
|
+
ts: number;
|
|
352
|
+
meta: string | null;
|
|
353
|
+
}>;
|
|
354
|
+
return aggregateCacheRows(rows);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// ... keep every function below unchanged ...
|
|
358
|
+
|
|
225
359
|
/**
|
|
226
360
|
* Read the most recent `cache_hit_pct` value from `perf_samples`.
|
|
227
361
|
*
|
|
@@ -236,9 +370,9 @@ export function readLatestCacheHitPct(
|
|
|
236
370
|
const row = db
|
|
237
371
|
.prepare(
|
|
238
372
|
`SELECT value FROM perf_samples
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
373
|
+
WHERE kind = ?
|
|
374
|
+
ORDER BY ts DESC, id DESC
|
|
375
|
+
LIMIT 1`,
|
|
242
376
|
)
|
|
243
377
|
.get("cache_hit_pct") as { value: number } | undefined;
|
|
244
378
|
if (!row || typeof row.value !== "number" || !Number.isFinite(row.value))
|
|
@@ -259,3 +393,64 @@ export function readProviderCacheForRepo(
|
|
|
259
393
|
): ProviderCacheLifetime {
|
|
260
394
|
return readProviderCacheLifetime(stateDir);
|
|
261
395
|
}
|
|
396
|
+
|
|
397
|
+
// ─── Prefix-break reader (S53A) ───────────────────────────────────────────────
|
|
398
|
+
|
|
399
|
+
/** Re-exported for consumers that import via perf-samples. */
|
|
400
|
+
export type { PrefixBreak } from "../../prefix-break.js";
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Read `prefix_break` samples in a time window.
|
|
404
|
+
*
|
|
405
|
+
* @param stateDir State directory for this repo.
|
|
406
|
+
* @param sinceTs Lower bound (epoch ms). Pass 0 for no lower bound.
|
|
407
|
+
* @param untilTs Upper bound (epoch ms). Pass 0 for no upper bound.
|
|
408
|
+
* Rows with ts > untilTs are excluded.
|
|
409
|
+
* @returns Sorted ascending array of PrefixBreak rows.
|
|
410
|
+
*
|
|
411
|
+
* SQL is fully parameterized (PREVENT-002). `meta` is parsed defensively
|
|
412
|
+
* (PREVENT-001 null-safe). When no rows exist the return is an empty array.
|
|
413
|
+
*/
|
|
414
|
+
export function readPrefixBreaks(
|
|
415
|
+
stateDir: string = getStateDir(),
|
|
416
|
+
sinceTs: number = 0,
|
|
417
|
+
untilTs: number = 0,
|
|
418
|
+
): PrefixBreak[] {
|
|
419
|
+
const db = openStore(stateDir);
|
|
420
|
+
let rows: Array<{
|
|
421
|
+
id: number;
|
|
422
|
+
ts: number;
|
|
423
|
+
value: number;
|
|
424
|
+
meta: string | null;
|
|
425
|
+
}>;
|
|
426
|
+
|
|
427
|
+
if (untilTs > 0) {
|
|
428
|
+
const sql = `SELECT id, ts, value, meta FROM perf_samples
|
|
429
|
+
WHERE kind = ? AND ts >= ? AND ts <= ? ORDER BY ts ASC`;
|
|
430
|
+
rows = db.prepare(sql).all("prefix_break", sinceTs, untilTs) as typeof rows;
|
|
431
|
+
} else {
|
|
432
|
+
const sql = `SELECT id, ts, value, meta FROM perf_samples
|
|
433
|
+
WHERE kind = ? AND ts >= ? ORDER BY ts ASC`;
|
|
434
|
+
rows = db.prepare(sql).all("prefix_break", sinceTs) as typeof rows;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const out: PrefixBreak[] = [];
|
|
438
|
+
for (const r of rows) {
|
|
439
|
+
let meta: unknown = null;
|
|
440
|
+
if (r.meta != null) {
|
|
441
|
+
try {
|
|
442
|
+
meta = JSON.parse(r.meta);
|
|
443
|
+
} catch {
|
|
444
|
+
meta = null;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
out.push({
|
|
448
|
+
id: r.id,
|
|
449
|
+
ts: r.ts,
|
|
450
|
+
kind: "prefix_break",
|
|
451
|
+
value: r.value,
|
|
452
|
+
meta: meta as PrefixBreak["meta"],
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
return out;
|
|
456
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type { DatabaseSync } from "node:sqlite";
|
|
5
5
|
import { ACHIEVEMENT_DEFS } from "../../game/scoring.js";
|
|
6
6
|
|
|
7
|
-
const SCHEMA_VERSION =
|
|
7
|
+
const SCHEMA_VERSION = 4;
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Add `column` (with `decl`, e.g. "INTEGER") to `table` if it does not already
|
|
@@ -366,6 +366,65 @@ export function initSchema(db: DatabaseSync): void {
|
|
|
366
366
|
);
|
|
367
367
|
CREATE INDEX IF NOT EXISTS idx_perf_samples_ts ON perf_samples(ts);
|
|
368
368
|
CREATE INDEX IF NOT EXISTS idx_perf_samples_kind_ts ON perf_samples(kind, ts);
|
|
369
|
+
|
|
370
|
+
-- A1 PLAN_V2 Phase 2: Message Separation tables (SCHEMA_VERSION 3).
|
|
371
|
+
-- Stable conversation thread: user + assistant turns ONLY. Tool results are
|
|
372
|
+
-- stored in tool_results to keep the conversation thread cache-predictable.
|
|
373
|
+
-- Parameterized queries only (PREVENT-002). CREATE TABLE IF NOT EXISTS is
|
|
374
|
+
-- a no-op on re-open — no migration needed.
|
|
375
|
+
CREATE TABLE IF NOT EXISTS conversation_thread (
|
|
376
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
377
|
+
conversation_id TEXT NOT NULL,
|
|
378
|
+
role TEXT NOT NULL CHECK(role IN ('user','assistant')),
|
|
379
|
+
content TEXT NOT NULL,
|
|
380
|
+
turn_index INTEGER NOT NULL,
|
|
381
|
+
timestamp INTEGER NOT NULL
|
|
382
|
+
);
|
|
383
|
+
CREATE INDEX IF NOT EXISTS idx_conv_thread_conv_turn
|
|
384
|
+
ON conversation_thread(conversation_id, turn_index);
|
|
385
|
+
|
|
386
|
+
-- Volatile tool results: appended at END so they never disrupt the
|
|
387
|
+
-- conversation thread prefix (the prompt-cache-friendly prefix).
|
|
388
|
+
CREATE TABLE IF NOT EXISTS tool_results (
|
|
389
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
390
|
+
conversation_id TEXT NOT NULL,
|
|
391
|
+
tool_call_id TEXT NOT NULL,
|
|
392
|
+
tool_result TEXT NOT NULL,
|
|
393
|
+
turn_index INTEGER NOT NULL,
|
|
394
|
+
timestamp INTEGER NOT NULL
|
|
395
|
+
);
|
|
396
|
+
CREATE INDEX IF NOT EXISTS idx_tool_results_conv_turn
|
|
397
|
+
ON tool_results(conversation_id, turn_index);
|
|
398
|
+
|
|
399
|
+
-- A2 PLAN_V2 Phase 3: Vector-Aware Cache Striping (SCHEMA_VERSION 4).
|
|
400
|
+
-- Cache stripe assignments: maps each context chunk to a cache stability
|
|
401
|
+
-- tier (stripe). Layer 0=permanent, 1=epoch, 2=topic, 3=thread, 4=volatile.
|
|
402
|
+
-- stability is the composite score (0.0-1.0) from computeStabilityScore.
|
|
403
|
+
-- Primary key is (chunk_id, epoch_id) so the same chunk can be reassigned
|
|
404
|
+
-- across epochs without conflict. See cache-stripe.ts for scoring details.
|
|
405
|
+
-- Parameterized queries only (PREVENT-002). IF NOT EXISTS is a no-op on re-open.
|
|
406
|
+
CREATE TABLE IF NOT EXISTS cache_stripes (
|
|
407
|
+
chunk_id TEXT NOT NULL,
|
|
408
|
+
stripe INTEGER NOT NULL,
|
|
409
|
+
stability REAL NOT NULL,
|
|
410
|
+
assigned_at INTEGER NOT NULL,
|
|
411
|
+
epoch_id TEXT,
|
|
412
|
+
PRIMARY KEY (chunk_id, epoch_id)
|
|
413
|
+
);
|
|
414
|
+
CREATE INDEX IF NOT EXISTS idx_cs_stripe_stability
|
|
415
|
+
ON cache_stripes(stripe, stability DESC);
|
|
416
|
+
|
|
417
|
+
-- Embedding computation cache: avoids re-embedding content every time
|
|
418
|
+
-- stability scores are recomputed across epochs. Keyed by content_hash
|
|
419
|
+
-- (SHA-256 64-hex-char string). Embeddings are serialized via
|
|
420
|
+
-- Float64Array-to-Buffer to match the embedding_blob convention.
|
|
421
|
+
CREATE TABLE IF NOT EXISTS embedding_cache (
|
|
422
|
+
content_hash TEXT PRIMARY KEY,
|
|
423
|
+
embedding BLOB NOT NULL,
|
|
424
|
+
computed_at INTEGER NOT NULL
|
|
425
|
+
);
|
|
426
|
+
CREATE INDEX IF NOT EXISTS idx_emb_cache_computed
|
|
427
|
+
ON embedding_cache(computed_at DESC);
|
|
369
428
|
`);
|
|
370
429
|
// Idempotent column migrations. `CREATE TABLE IF NOT EXISTS` is a no-op on a
|
|
371
430
|
// pre-existing table, so new columns added to context_chunks after a store was
|
package/src/store/sqlite.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { randomBytes } from "node:crypto";
|
|
11
|
-
import type
|
|
11
|
+
import { DuplicateTurnError, type
|
|
12
12
|
TurnStore,
|
|
13
13
|
TurnReader,
|
|
14
14
|
TurnWriter,
|
|
@@ -198,6 +198,15 @@ export class InMemoryTurnStore implements TurnStore {
|
|
|
198
198
|
// ── TurnWriter ──────────────────────────────────────────────
|
|
199
199
|
|
|
200
200
|
appendTurn(entry: TurnEntry): TurnId {
|
|
201
|
+
// Check for duplicate (conversationId, turnIndex)
|
|
202
|
+
for (const [, row] of this.turns) {
|
|
203
|
+
if (
|
|
204
|
+
row.entry.conversationId === entry.conversationId &&
|
|
205
|
+
row.entry.turnIndex === entry.turnIndex
|
|
206
|
+
) {
|
|
207
|
+
throw new DuplicateTurnError(entry.conversationId, entry.turnIndex);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
201
210
|
const id = allocId();
|
|
202
211
|
const sid = normalizeSessionId(entry.sessionId);
|
|
203
212
|
const normalized = { ...entry, sessionId: sid };
|
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
ConversationStats,
|
|
34
34
|
TurnStoreOptions,
|
|
35
35
|
} from "./types.js";
|
|
36
|
+
import { DuplicateTurnError } from "./types.js";
|
|
36
37
|
|
|
37
38
|
// ─── Helpers ──────────────────────────────────────────────────────
|
|
38
39
|
|
|
@@ -237,23 +238,34 @@ export class SqliteTurnStore implements TurnStore {
|
|
|
237
238
|
appendTurn(entry: TurnEntry): TurnId {
|
|
238
239
|
const sid = normalizeSessionId(entry.sessionId);
|
|
239
240
|
this.persistSessionConv(sid, entry.conversationId);
|
|
240
|
-
|
|
241
|
-
.
|
|
242
|
-
|
|
241
|
+
try {
|
|
242
|
+
this.db
|
|
243
|
+
.prepare(
|
|
244
|
+
`INSERT INTO turns (conversation_id, session_id, turn_index, role, ended_at,
|
|
243
245
|
ctx_tokens, ctx_percent, pressure_band, model)
|
|
244
246
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
247
|
+
)
|
|
248
|
+
.run(
|
|
249
|
+
entry.conversationId,
|
|
250
|
+
sid,
|
|
251
|
+
entry.turnIndex,
|
|
252
|
+
entry.role,
|
|
253
|
+
entry.endedAt,
|
|
254
|
+
entry.ctxTokens ?? null,
|
|
255
|
+
entry.ctxPercent ?? null,
|
|
256
|
+
entry.pressureBand ?? null,
|
|
257
|
+
entry.model ?? null,
|
|
258
|
+
);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
if (
|
|
261
|
+
e instanceof Error &&
|
|
262
|
+
e.message.includes("UNIQUE constraint") &&
|
|
263
|
+
(e as { code?: string }).code === "ERR_SQLITE_ERROR"
|
|
264
|
+
) {
|
|
265
|
+
throw new DuplicateTurnError(entry.conversationId, entry.turnIndex);
|
|
266
|
+
}
|
|
267
|
+
throw e;
|
|
268
|
+
}
|
|
257
269
|
const row = this.db
|
|
258
270
|
.prepare(
|
|
259
271
|
"SELECT id FROM turns WHERE conversation_id = ? AND turn_index = ?",
|
package/src/store/turns/types.ts
CHANGED
|
@@ -16,6 +16,27 @@
|
|
|
16
16
|
|
|
17
17
|
// ─── Domain types ───────────────────────────────────────────────────
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Thrown when appendTurn is called with a (conversationId, turnIndex) pair
|
|
21
|
+
* that already exists. Both backends must throw this in lieu of a raw
|
|
22
|
+
* SQLite error (SqliteTurnStore) or silent success (InMemoryTurnStore).
|
|
23
|
+
*/
|
|
24
|
+
export class DuplicateTurnError extends Error {
|
|
25
|
+
/** The conversation that already has this turn index. */
|
|
26
|
+
readonly conversationId: ConversationId;
|
|
27
|
+
/** The duplicate turn index. */
|
|
28
|
+
readonly turnIndex: number;
|
|
29
|
+
|
|
30
|
+
constructor(conversationId: ConversationId, turnIndex: number) {
|
|
31
|
+
super(
|
|
32
|
+
`Duplicate turn: conversation "${conversationId}" already has turnIndex ${turnIndex}`,
|
|
33
|
+
);
|
|
34
|
+
this.name = "DuplicateTurnError";
|
|
35
|
+
this.conversationId = conversationId;
|
|
36
|
+
this.turnIndex = turnIndex;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
19
40
|
/** Unique turn identifier (string to stay backend-agnostic). */
|
|
20
41
|
export type TurnId = string;
|
|
21
42
|
|
package/src/store/vectorIndex.ts
CHANGED
|
@@ -230,13 +230,21 @@ export async function upsertEmbedding(
|
|
|
230
230
|
const pg = await initVectorIndex();
|
|
231
231
|
if (!pg) return;
|
|
232
232
|
const lit = toVectorLiteral(embedding);
|
|
233
|
-
await
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
233
|
+
const upserted = await withOpenTimeout(
|
|
234
|
+
pg.query(
|
|
235
|
+
`INSERT INTO vector_index (repo_id, session_id, checkpoint_id, embedding)
|
|
236
|
+
VALUES ($1, $2, $3, $4::vector)
|
|
237
|
+
ON CONFLICT (repo_id, session_id, checkpoint_id)
|
|
238
|
+
DO UPDATE SET embedding = EXCLUDED.embedding;`,
|
|
239
|
+
[repoId, sessionId, checkpointId, lit],
|
|
240
|
+
),
|
|
241
|
+
(reason) => {
|
|
242
|
+
disabled = true;
|
|
243
|
+
logWarn(`upsert query timed out after ${queryTimeoutMs()}ms: ${reason}`);
|
|
244
|
+
},
|
|
245
|
+
queryTimeoutMs(),
|
|
239
246
|
);
|
|
247
|
+
if (upserted === undefined) return; // timed out — non-fatal
|
|
240
248
|
} catch (err) {
|
|
241
249
|
disabled = true;
|
|
242
250
|
logWarn(`upsert failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -274,7 +282,15 @@ export async function searchAsync(
|
|
|
274
282
|
params.push(repoId);
|
|
275
283
|
}
|
|
276
284
|
sql += " ORDER BY embedding <=> $1::vector LIMIT $2";
|
|
277
|
-
const res = await
|
|
285
|
+
const res = await withOpenTimeout(
|
|
286
|
+
pg.query(sql, params),
|
|
287
|
+
(reason) => {
|
|
288
|
+
disabled = true;
|
|
289
|
+
logWarn(`search query timed out after ${queryTimeoutMs()}ms: ${reason}`);
|
|
290
|
+
},
|
|
291
|
+
queryTimeoutMs(),
|
|
292
|
+
);
|
|
293
|
+
if (!res) return []; // query timed out — degrade to empty (non-fatal)
|
|
278
294
|
return res.rows.map((r: any) => ({
|
|
279
295
|
repoId: r.repo_id as string,
|
|
280
296
|
sessionId: r.session_id as string,
|
|
@@ -288,13 +304,57 @@ export async function searchAsync(
|
|
|
288
304
|
}
|
|
289
305
|
}
|
|
290
306
|
|
|
307
|
+
/** Default cap for the WASM close (PGlite can stall ~40 min on teardown). */
|
|
308
|
+
export const DEFAULT_CLOSE_TIMEOUT_MS = 5_000;
|
|
309
|
+
|
|
310
|
+
function closeTimeoutMs(): number {
|
|
311
|
+
const raw = process.env.MEGACOMPACT_PGLITE_CLOSE_TIMEOUT_MS;
|
|
312
|
+
if (raw) {
|
|
313
|
+
const n = Number(raw);
|
|
314
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
315
|
+
}
|
|
316
|
+
return DEFAULT_CLOSE_TIMEOUT_MS;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** Default cap for a PGlite search query. A WASM query that never resolves would
|
|
320
|
+
* otherwise hang the calling turn (and node --test) forever — the catch below
|
|
321
|
+
* only handles thrown errors, not a stalled promise. 0 disables the guard
|
|
322
|
+
* (preserve original unbounded behavior). Mirrors the open/close timeouts. */
|
|
323
|
+
export const DEFAULT_QUERY_TIMEOUT_MS = 10_000;
|
|
324
|
+
|
|
325
|
+
function queryTimeoutMs(): number {
|
|
326
|
+
const raw = process.env.MEGACOMPACT_PGLITE_QUERY_TIMEOUT_MS;
|
|
327
|
+
if (raw !== undefined) {
|
|
328
|
+
const n = Number(raw);
|
|
329
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
330
|
+
}
|
|
331
|
+
return DEFAULT_QUERY_TIMEOUT_MS;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Race a promise against a timeout. If the inner promise never settles, the
|
|
336
|
+
* timer fires, resolves with `undefined`, and the caller proceeds. This mirrors
|
|
337
|
+
* `withOpenTimeout` (pgOpenGuard.ts) but is local to the close path.
|
|
338
|
+
*/
|
|
339
|
+
function withCloseTimeout<T>(
|
|
340
|
+
promise: Promise<T>,
|
|
341
|
+
timeoutMs: number,
|
|
342
|
+
): Promise<T | undefined> {
|
|
343
|
+
return Promise.race([
|
|
344
|
+
promise,
|
|
345
|
+
new Promise<undefined>((resolve) => setTimeout(() => resolve(undefined), timeoutMs)),
|
|
346
|
+
]);
|
|
347
|
+
}
|
|
348
|
+
|
|
291
349
|
/** Close the index (test teardown / shutdown). Safe to call when unopened. */
|
|
292
350
|
export async function closeVectorIndex(): Promise<void> {
|
|
293
351
|
if (db) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
352
|
+
const closePromise = db.close().catch(() => {});
|
|
353
|
+
const result = await withCloseTimeout(closePromise, closeTimeoutMs());
|
|
354
|
+
if (result === undefined) {
|
|
355
|
+
logWarn(
|
|
356
|
+
`close timed out after ${closeTimeoutMs()}ms (WASM teardown stalled; OS will reclaim)`,
|
|
357
|
+
);
|
|
298
358
|
}
|
|
299
359
|
}
|
|
300
360
|
db = undefined;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tiered-router/types.ts — S44 tiered router types, interfaces, and defaults.
|
|
3
|
+
*
|
|
4
|
+
* Shell file: pure data/type definitions. Zero runtime dependencies on store
|
|
5
|
+
* internals. Imported by tieredRouter.ts and any consumer that needs the
|
|
6
|
+
* RecallResult / TieredRouterMetrics shapes.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { SearchHit } from "../vectorStore.js";
|
|
10
|
+
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Public interfaces
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
export interface TieredRecallOpts {
|
|
16
|
+
/** Session ID to scope search. When absent, searches cross-session. */
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
/** Max number of results to return (default 10). */
|
|
19
|
+
k?: number;
|
|
20
|
+
/** Skip LRU-cache lookup (force L1 hit). */
|
|
21
|
+
bypassCache?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* FTS5 max BM25 score for the L1 confidence gate.
|
|
24
|
+
* Read from calibration.json at construction; overridable per-call.
|
|
25
|
+
*/
|
|
26
|
+
overrideFts5MaxBm25?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface RecallResult {
|
|
30
|
+
/** Checkpoint search hits, ranked by relevance. */
|
|
31
|
+
hits: SearchHit[];
|
|
32
|
+
/** Which tier produced the result. */
|
|
33
|
+
tier: "L0" | "L1" | "L2";
|
|
34
|
+
/** Per-tier latency deltas in ms (contains only tiers that ran). */
|
|
35
|
+
latencyMs: { l0?: number; l1?: number; l2?: number };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface TieredRouterMetrics {
|
|
39
|
+
l0Hits: number;
|
|
40
|
+
l0Misses: number;
|
|
41
|
+
l1Hits: number;
|
|
42
|
+
l1Misses: number;
|
|
43
|
+
l2Hits: number;
|
|
44
|
+
l2Misses: number;
|
|
45
|
+
totalQueries: number;
|
|
46
|
+
avgLatencyMs: { l0: number; l1: number; l2: number };
|
|
47
|
+
fts5MaxBm25: number | null;
|
|
48
|
+
uncalibrated: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Defaults
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
/** Default LRU cache size. */
|
|
56
|
+
export const DEFAULT_CACHE_SIZE = 256;
|
|
57
|
+
|
|
58
|
+
/** Default latency budgets per tier (ms). */
|
|
59
|
+
export const DEFAULT_BUDGET_L0_MS = 1;
|
|
60
|
+
export const DEFAULT_BUDGET_L1_MS = 50;
|
|
61
|
+
export const DEFAULT_BUDGET_L2_MS = 500;
|
|
62
|
+
|
|
63
|
+
/** Default cadence for tiered-metrics logging (every N queries). */
|
|
64
|
+
export const DEFAULT_LOG_CADENCE = 100;
|