@cortexkit/opencode-magic-context 0.49.34 → 0.49.36
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/README.md +1 -1
- package/dist/auto-search-worker.js +163 -155
- package/dist/chunk-embedding-write-worker.js +70 -66
- package/dist/{compaction-marker-candidates-31h86ph0.js → compaction-marker-candidates-5p1qkve9.js} +5 -2
- package/dist/compaction-marker-candidates-worker.js +24 -23
- package/dist/{compartment-chunk-embedding-5q5gj67r.js → compartment-chunk-embedding-ypktm0tk.js} +10 -8
- package/dist/{conflict-warning-hook-xgskea1v.js → conflict-warning-hook-b75jn458.js} +11 -9
- package/dist/{context-p3xrarzt.js → context-969z683s.js} +1839 -746
- package/dist/{derive-budgets-pqybnx09.js → derive-budgets-htj16n4x.js} +3 -2
- package/dist/embedding-backfill-rma0v2ct.js +28 -0
- package/dist/embedding-worker-process.js +2 -1
- package/dist/embedding-worker.js +6 -5
- package/dist/expand-attachments-h33jbgyz.js +21 -0
- package/dist/features/magic-context/auto-search-diagnostics.d.ts +21 -0
- package/dist/features/magic-context/auto-search-diagnostics.d.ts.map +1 -0
- package/dist/features/magic-context/compaction-marker-candidates.d.ts.map +1 -1
- package/dist/features/magic-context/compaction-marker.d.ts +5 -3
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts +1 -1
- package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-gate.d.ts +2 -0
- package/dist/features/magic-context/dreamer/verify-gate.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/verify-state.d.ts +9 -0
- package/dist/features/magic-context/dreamer/verify-state.d.ts.map +1 -0
- package/dist/features/magic-context/dreamer/verify.d.ts +2 -1
- package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
- package/dist/features/magic-context/migration-worker-client.d.ts +3 -0
- package/dist/features/magic-context/migration-worker-client.d.ts.map +1 -1
- package/dist/features/magic-context/migration-worker.d.ts +15 -0
- package/dist/features/magic-context/migration-worker.d.ts.map +1 -1
- package/dist/features/magic-context/overflow-detection.d.ts +2 -2
- package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
- package/dist/features/magic-context/search-rerank.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +4 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +1 -0
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tags.d.ts +4 -0
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/store-generation-rebase-labels.d.ts +6 -0
- package/dist/features/magic-context/store-generation-rebase-labels.d.ts.map +1 -0
- package/dist/features/magic-context/store-generation-rebase.d.ts.map +1 -1
- package/dist/features/magic-context/work-metrics-carry-storage.d.ts +10 -0
- package/dist/features/magic-context/work-metrics-carry-storage.d.ts.map +1 -0
- package/dist/{history-owner-36wp3mkb.js → history-owner-0z620wgz.js} +3 -2
- package/dist/hooks/magic-context/apply-operations.d.ts +20 -3
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-observation.d.ts +13 -0
- package/dist/hooks/magic-context/auto-search-observation.d.ts.map +1 -0
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts +10 -2
- package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
- package/dist/hooks/magic-context/compaction-marker-publication.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-commit-hashes.d.ts +4 -0
- package/dist/hooks/magic-context/compartment-commit-hashes.d.ts.map +1 -0
- package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts +1 -0
- package/dist/hooks/magic-context/compartment-runner-validation.d.ts.map +1 -1
- package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
- package/dist/hooks/magic-context/final-wire-completeness.d.ts +15 -0
- package/dist/hooks/magic-context/final-wire-completeness.d.ts.map +1 -0
- package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
- package/dist/hooks/magic-context/issue-423-fixture.d.ts +1 -1
- package/dist/hooks/magic-context/issue-423-fixture.d.ts.map +1 -1
- package/dist/hooks/magic-context/issue-424-fixture.d.ts +1 -1
- package/dist/hooks/magic-context/issue-424-fixture.d.ts.map +1 -1
- package/dist/hooks/magic-context/project-structural-sentinels.d.ts +25 -0
- package/dist/hooks/magic-context/project-structural-sentinels.d.ts.map +1 -0
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts +8 -1
- package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts +1 -0
- package/dist/hooks/magic-context/raw-ordinal-warmup.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +11 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts +2 -0
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/release-recovery-prefix.d.ts +9 -0
- package/dist/hooks/magic-context/release-recovery-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-structural-noise.d.ts +6 -3
- package/dist/hooks/magic-context/strip-structural-noise.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-context-state.d.ts +3 -0
- package/dist/hooks/magic-context/transform-context-state.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +3 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/{index-cpjk5jd2.js → index-1d042x6w.js} +16 -14
- package/dist/{index-2743x98y.js → index-21fgrfrf.js} +35 -142
- package/dist/index-2amn2s73.js +123 -0
- package/dist/{index-c7phnbvk.js → index-2p37txes.js} +1 -1
- package/dist/index-2qbtqg1w.js +529 -0
- package/dist/{index-9gpw8hrm.js → index-2rs7912w.js} +4 -4
- package/dist/{index-m1x9ghk5.js → index-4ks89h5a.js} +37 -7
- package/dist/{index-b88dwwrh.js → index-4xyjr62e.js} +1 -1
- package/dist/index-4y35msh5.js +531 -0
- package/dist/index-66a50f3e.js +777 -0
- package/dist/index-72czy45z.js +4557 -0
- package/dist/index-7v05d9b7.js +58 -0
- package/dist/{index-qgh1qwjj.js → index-850vthn3.js} +9 -3
- package/dist/{index-np3rgfw4.js → index-8jjjmhab.js} +15 -4
- package/dist/index-96ztjvkn.js +204 -0
- package/dist/{index-fm36bjv4.js → index-9fgmkfaf.js} +22 -277
- package/dist/{index-atekmqef.js → index-9tdvbdv1.js} +508 -5547
- package/dist/{index-xrnsygfq.js → index-9wnbnx8f.js} +1 -1
- package/dist/{index-waktfbjy.js → index-ae1ar4v1.js} +4 -4
- package/dist/{index-v15ne3a3.js → index-b1ydbp95.js} +2 -2
- package/dist/{index-nxrsns5x.js → index-c5dzns43.js} +75 -75
- package/dist/{index-v7287tzq.js → index-dcjkw41m.js} +19 -8
- package/dist/{index-hbx7m8he.js → index-dfdg2cgg.js} +338 -86
- package/dist/{index-spwjbkc7.js → index-dnqqqc5f.js} +1 -1
- package/dist/{index-04z754rd.js → index-dz48h1wx.js} +33 -5
- package/dist/{index-rrv26qjz.js → index-fw42ms3m.js} +1 -1
- package/dist/{index-t5pck3ss.js → index-fxbk7gk3.js} +1 -1
- package/dist/{index-wfybj1dw.js → index-g4t7850m.js} +2 -2
- package/dist/{index-97spytxq.js → index-gnmhbyyc.js} +583 -474
- package/dist/{index-4pnsgvfk.js → index-hacf2tyx.js} +1 -1
- package/dist/index-j105mf16.js +270 -0
- package/dist/{index-gkee6p4g.js → index-jggt5gf2.js} +3 -3
- package/dist/{index-s1n8dd2n.js → index-jkanybgq.js} +2 -2
- package/dist/{index-h7tgn49j.js → index-jrfre9ah.js} +5 -222
- package/dist/{index-kfyb3k6n.js → index-jz5bk7xd.js} +2 -2
- package/dist/{index-7kkphb6c.js → index-nj360hcs.js} +4 -4
- package/dist/{index-07vskjn8.js → index-pp8vdn01.js} +15 -13
- package/dist/index-prw8apnc.js +194 -0
- package/dist/{index-rverk2vz.js → index-r2epb000.js} +34 -4
- package/dist/{index-7g9dr8gy.js → index-tn9drm1a.js} +125 -143
- package/dist/{index-kq5w68dp.js → index-txs8tce6.js} +1 -1
- package/dist/{index-rfxzazzy.js → index-ty4vhe4n.js} +5 -5
- package/dist/{index-y1qwzvxn.js → index-vd2ywmfe.js} +2 -2
- package/dist/{index-0677w9sd.js → index-wcwhhtdh.js} +58 -23
- package/dist/index-wh9fxds5.js +265 -0
- package/dist/{index-51rdvtkz.js → index-xd2p95m7.js} +3 -3
- package/dist/{index-as2amvn3.js → index-xnm0wq1r.js} +6 -531
- package/dist/{index-ftr84kkv.js → index-ys7j6679.js} +7 -5
- package/dist/index-z4p0ry94.js +222 -0
- package/dist/index-z9zygwse.js +89 -0
- package/dist/index.js +86 -74
- package/dist/{logger-94kew5wm.js → logger-qwnbcfj9.js} +2 -1
- package/dist/{message-fts-rowid-map-va36knh4.js → message-fts-rowid-map-t6qsyg9s.js} +7 -5
- package/dist/{message-index-bounded-qh91fdr3.js → message-index-bounded-wfk6aqxk.js} +15 -13
- package/dist/{message-time-backfill-4qva0b4f.js → message-time-backfill-39bm498k.js} +3 -2
- package/dist/migration-worker.js +55 -48
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{project-embedding-registry-6yex0r9f.js → project-embedding-registry-3yyegjma.js} +16 -13
- package/dist/raw-ordinal-warmup-worker.js +114 -113
- package/dist/{read-session-chunk-kaghtr75.js → read-session-chunk-26yrrhyz.js} +18 -12
- package/dist/{read-session-raw-b2sd67v4.js → read-session-raw-j7c9w57v.js} +5 -3
- package/dist/recomp-orchestrator-wk509qkp.js +69 -0
- package/dist/render-h1qarr8a.js +44 -0
- package/dist/{safe-notification-target-mkr9yzvr.js → safe-notification-target-wztd7bgk.js} +3 -2
- package/dist/search-5h9fydyq.js +54 -0
- package/dist/search-archive-q79hyqxs.js +29 -0
- package/dist/{send-session-notification-vz86nt79.js → send-session-notification-14p3yje4.js} +9 -7
- package/dist/shared/model-suggestion-retry.d.ts +7 -0
- package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
- package/dist/shared/prompt-async-transport.d.ts.map +1 -1
- package/dist/shared/reusable-worker-entry.d.ts +4 -0
- package/dist/shared/reusable-worker-entry.d.ts.map +1 -0
- package/dist/shared/reusable-worker.d.ts +6 -0
- package/dist/shared/reusable-worker.d.ts.map +1 -0
- package/dist/shared/reusable-worker.fixture.d.ts +2 -0
- package/dist/shared/reusable-worker.fixture.d.ts.map +1 -0
- package/dist/shared/worker-shutdown.d.ts +1 -1
- package/dist/shared/worker-shutdown.d.ts.map +1 -1
- package/dist/{storage-tags-6hvkk01c.js → storage-tags-vj0yj7ed.js} +5 -4
- package/dist/store-reader-yh19h38c.js +14 -0
- package/dist/store-s3eykdjt.js +21 -0
- package/dist/tools/ctx-expand/render.d.ts +5 -3
- package/dist/tools/ctx-expand/render.d.ts.map +1 -1
- package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -1
- package/dist/tools/ctx-expand/tools.d.ts +2 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-expand/v2-archive-reader.d.ts +33 -0
- package/dist/tools/ctx-expand/v2-archive-reader.d.ts.map +1 -0
- package/dist/{transform-postprocess-phase-ph38mhrs.js → transform-postprocess-phase-4gj0mtcg.js} +39 -32
- package/dist/v2/auto-search-worker.js +163 -155
- package/dist/v2/chunk-embedding-write-worker.js +71 -67
- package/dist/v2/compaction-marker-candidates-worker.js +24 -23
- package/dist/v2/{compaction-marker-candidates-m4vmye3w.js → compaction-marker-candidates-yeb2ky46.js} +6 -3
- package/dist/v2/{compartment-chunk-embedding-rc31e6md.js → compartment-chunk-embedding-qfk791bd.js} +11 -9
- package/dist/v2/{context-s60hcatx.js → context-bxr039be.js} +2678 -1246
- package/dist/v2/{derive-budgets-knf763tt.js → derive-budgets-sa0v7bz0.js} +4 -3
- package/dist/v2/embedding-backfill-00tw59rx.js +27 -0
- package/dist/v2/embedding-worker-process.js +2 -1
- package/dist/v2/embedding-worker.js +6 -5
- package/dist/v2/expand-attachments-h33jbgyz.js +21 -0
- package/dist/v2/fold/code-mode-catalog.d.ts +3 -0
- package/dist/v2/fold/code-mode-catalog.d.ts.map +1 -0
- package/dist/v2/fold/idle.d.ts +16 -0
- package/dist/v2/fold/idle.d.ts.map +1 -0
- package/dist/v2/fold/manual-baseline.d.ts +8 -0
- package/dist/v2/fold/manual-baseline.d.ts.map +1 -0
- package/dist/v2/fold/native-replay-v3.d.ts +75 -0
- package/dist/v2/fold/native-replay-v3.d.ts.map +1 -0
- package/dist/v2/fold/native-replay.d.ts +81 -8
- package/dist/v2/fold/native-replay.d.ts.map +1 -1
- package/dist/v2/fold/policy.d.ts +2 -1
- package/dist/v2/fold/policy.d.ts.map +1 -1
- package/dist/v2/fold/restore.d.ts.map +1 -1
- package/dist/v2/fold/summary.d.ts +4 -0
- package/dist/v2/fold/summary.d.ts.map +1 -0
- package/dist/v2/hidden-completion.d.ts.map +1 -1
- package/dist/v2/{history-owner-ad0crnrn.js → history-owner-fpka43cn.js} +3 -2
- package/dist/v2/hooks/channel2.d.ts +6 -0
- package/dist/v2/hooks/channel2.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/expand-attachments.d.ts +8 -0
- package/dist/v2/hooks/expand-attachments.d.ts.map +1 -0
- package/dist/v2/hooks/overflow-recovery.d.ts +45 -0
- package/dist/v2/hooks/overflow-recovery.d.ts.map +1 -0
- package/dist/v2/hooks/restore-rows.d.ts +12 -2
- package/dist/v2/hooks/restore-rows.d.ts.map +1 -1
- package/dist/v2/hooks/store.d.ts +7 -2
- package/dist/v2/hooks/store.d.ts.map +1 -1
- package/dist/v2/hooks/synthetic-admission.d.ts +7 -0
- package/dist/v2/hooks/synthetic-admission.d.ts.map +1 -0
- package/dist/v2/hooks/usage-persist.d.ts.map +1 -1
- package/dist/v2/{logger-p34mjtja.js → logger-4cj6d03m.js} +2 -1
- package/dist/v2/{message-fts-rowid-map-78awh03v.js → message-fts-rowid-map-z86avy0n.js} +8 -6
- package/dist/v2/{message-index-bounded-4htdr1j6.js → message-index-bounded-w14496s9.js} +16 -14
- package/dist/v2/{message-time-backfill-zvthw6xb.js → message-time-backfill-0c4h7sg6.js} +3 -2
- package/dist/v2/migration-worker.js +56 -49
- package/dist/v2/ordinal-range.fixture.d.ts +7 -0
- package/dist/v2/ordinal-range.fixture.d.ts.map +1 -0
- package/dist/v2/{project-embedding-registry-1x5qe2fy.js → project-embedding-registry-jqq2qeqb.js} +17 -14
- package/dist/v2/raw-ordinal-warmup-worker.js +114 -113
- package/dist/v2/{read-session-chunk-1fa9qzwb.js → read-session-chunk-tqnh1ret.js} +18 -12
- package/dist/v2/{read-session-raw-5x088amc.js → read-session-raw-qpp6x9kg.js} +6 -4
- package/dist/v2/recomp-orchestrator-9cjk6aej.js +68 -0
- package/dist/v2/render-5dz1knf2.js +43 -0
- package/dist/v2/{safe-notification-target-khnzg57c.js → safe-notification-target-gphhast7.js} +3 -2
- package/dist/v2/search-8yfet25y.js +52 -0
- package/dist/v2/search-archive-z6z9jqwf.js +28 -0
- package/dist/v2/{send-session-notification-x5nzy34v.js → send-session-notification-kxp47tsw.js} +9 -7
- package/dist/v2/{server-cpjk5jd2.js → server-1d042x6w.js} +16 -14
- package/dist/v2/server-2amn2s73.js +123 -0
- package/dist/v2/{server-6g98c227.js → server-3schkz95.js} +4 -4
- package/dist/v2/server-468mya5v.js +209 -0
- package/dist/v2/{server-z2wft9zv.js → server-5by3vdzs.js} +562 -5560
- package/dist/v2/{server-qjvk4a9t.js → server-69m30b21.js} +1 -1
- package/dist/v2/server-6emy0v9a.js +531 -0
- package/dist/v2/{server-vr4szghm.js → server-6vzh6wej.js} +3 -3
- package/dist/v2/{server-ajxhrgjv.js → server-7094pk3w.js} +80 -19
- package/dist/v2/{server-ab8017gw.js → server-7acq7815.js} +34 -141
- package/dist/v2/server-7v05d9b7.js +58 -0
- package/dist/v2/{server-24g8r2d0.js → server-7zacmty5.js} +75 -75
- package/dist/v2/{server-3mz2qh5a.js → server-969cdpmg.js} +1 -1
- package/dist/v2/server-96ztjvkn.js +204 -0
- package/dist/v2/{server-grakwy1v.js → server-a9w5f0yw.js} +37 -7
- package/dist/v2/{server-835q39kd.js → server-avdveykk.js} +3 -3
- package/dist/v2/{server-qc915kw2.js → server-bez34e60.js} +4 -4
- package/dist/v2/{server-h1byrhwx.js → server-cp1a03vc.js} +19 -8
- package/dist/v2/{server-bsgd4dk1.js → server-dcws5831.js} +2 -2
- package/dist/v2/{server-m1pfg2d4.js → server-dfq5vb8j.js} +4 -4
- package/dist/v2/server-e51xmr4d.js +194 -0
- package/dist/v2/server-ef1mskas.js +777 -0
- package/dist/v2/{server-1bw1wcbp.js → server-f0j864ma.js} +1 -1
- package/dist/v2/{server-jw5qe9y8.js → server-g3gqq4ac.js} +18 -217
- package/dist/v2/{server-2aasmpsp.js → server-gkse1wyz.js} +5 -5
- package/dist/v2/{server-6495nmn9.js → server-jb6tjyeb.js} +5 -222
- package/dist/v2/{server-qvy4qavp.js → server-jd7vzwn4.js} +125 -143
- package/dist/v2/{server-a7x00tw8.js → server-mfn1yf9d.js} +1 -1
- package/dist/v2/{server-awr8qa4c.js → server-nmyganc8.js} +2 -2
- package/dist/v2/{server-tkdabx8q.js → server-nq3cb7be.js} +5 -530
- package/dist/v2/server-qjyp27vf.js +270 -0
- package/dist/v2/{server-gyy4k6mf.js → server-qmmkhz2z.js} +1 -1
- package/dist/v2/{server-29qp8nz4.js → server-qxzbmtqt.js} +1 -1
- package/dist/v2/{server-806rzhs6.js → server-r4430x9m.js} +10 -4
- package/dist/v2/{server-53eh1r8r.js → server-sd8hvzte.js} +2 -2
- package/dist/v2/{server-k3t06fxr.js → server-sefxj8k1.js} +1 -1
- package/dist/v2/server-t8y64xj7.js +4513 -0
- package/dist/v2/{server-6vd2n183.js → server-tnzbk64q.js} +35 -5
- package/dist/v2/{server-v77xa5wj.js → server-tpt7bwq8.js} +1 -1
- package/dist/v2/{server-51779zs2.js → server-v0p37hm2.js} +4 -1
- package/dist/v2/{server-nxas8v1d.js → server-xfjjbrkt.js} +15 -4
- package/dist/v2/{server-cqjvxyrp.js → server-xy7w7hrd.js} +2 -2
- package/dist/v2/server-ypf1ap0v.js +529 -0
- package/dist/v2/server-z4p0ry94.js +222 -0
- package/dist/v2/server-z9zygwse.js +89 -0
- package/dist/v2/{server-ab1g0wn9.js → server-zzgtgqmd.js} +2 -2
- package/dist/v2/server.js +7 -6
- package/dist/v2/{storage-tags-18nbaanf.js → storage-tags-cw07ky67.js} +5 -4
- package/dist/v2/store-reader-cgx47zkp.js +14 -0
- package/dist/v2/store-reader.d.ts +9 -2
- package/dist/v2/store-reader.d.ts.map +1 -1
- package/dist/v2/store-z3qe67cg.js +21 -0
- package/dist/v2/v2-archive-reader-z7wr42ry.js +11 -0
- package/dist/v2/{wrapup-orchestrator-wxf7n5k6.js → wrapup-orchestrator-j1v62bkj.js} +50 -42
- package/dist/v2-archive-reader-028z6kck.js +11 -0
- package/dist/wrapup-orchestrator-xg9avt2p.js +56 -0
- package/package.json +1 -1
- package/src/shared/model-suggestion-retry.ts +1 -1
- package/src/shared/prompt-async-transport.test.ts +64 -3
- package/src/shared/prompt-async-transport.ts +61 -16
- package/src/shared/reusable-worker-entry.ts +58 -0
- package/src/shared/reusable-worker-reset.test.ts +108 -0
- package/src/shared/reusable-worker.fixture.ts +35 -0
- package/src/shared/reusable-worker.test.ts +253 -0
- package/src/shared/reusable-worker.ts +240 -0
- package/src/shared/sqlite-transaction-mode-guard.test.ts +2 -0
- package/src/shared/worker-shutdown.ts +21 -17
- package/dist/embedding-backfill-0jgtqxen.js +0 -25
- package/dist/recomp-orchestrator-0y983w7h.js +0 -62
- package/dist/search-archive-1kw2rp19.js +0 -26
- package/dist/search-p684j8ww.js +0 -50
- package/dist/v2/embedding-backfill-f43hd8y6.js +0 -24
- package/dist/v2/recomp-orchestrator-7q9nvxte.js +0 -61
- package/dist/v2/search-archive-xfp51s0g.js +0 -25
- package/dist/v2/search-wf8rqxhm.js +0 -48
- package/dist/wrapup-orchestrator-ys2nrkkb.js +0 -49
|
@@ -6,34 +6,6 @@ import {
|
|
|
6
6
|
dreamerRunConfig,
|
|
7
7
|
pluginConfigReader,
|
|
8
8
|
withLiveDreamerOutputCap,
|
|
9
|
-
advanceSessionActivity,
|
|
10
|
-
backfillSessionActivity,
|
|
11
|
-
acquireCompartmentLease,
|
|
12
|
-
releaseCompartmentLeaseBestEffort,
|
|
13
|
-
isCompartmentLeaseHeld,
|
|
14
|
-
queueM0Mutation,
|
|
15
|
-
getUncoveredCompartmentEndsThrough,
|
|
16
|
-
providerResponseFailed,
|
|
17
|
-
isSuccessfulProviderCompletion,
|
|
18
|
-
gaDatabasePath,
|
|
19
|
-
RAW_MESSAGE_TYPES,
|
|
20
|
-
V2StoreReaderPool,
|
|
21
|
-
V2StoreReader,
|
|
22
|
-
getOrCreateSessionMeta,
|
|
23
|
-
updateSessionMeta,
|
|
24
|
-
markSessionCleanupPending,
|
|
25
|
-
clearSession,
|
|
26
|
-
requestPendingMaterialization,
|
|
27
|
-
clearPendingMaterialization,
|
|
28
|
-
bindSystemPromptResponse,
|
|
29
|
-
retirePendingSystemPromptDelivery,
|
|
30
|
-
lkgProviderInputTotal,
|
|
31
|
-
beginV2LkgRequest,
|
|
32
|
-
currentLkgRequestIdentity,
|
|
33
|
-
noteLkgProviderResponse,
|
|
34
|
-
clearLkgMeasuredRequest,
|
|
35
|
-
getSlot,
|
|
36
|
-
copySessionStateForClone,
|
|
37
9
|
HiddenCompletionRefusal,
|
|
38
10
|
HIDDEN_HISTORIAN_AGENT,
|
|
39
11
|
HIDDEN_DREAMER_AGENT,
|
|
@@ -65,7 +37,7 @@ import {
|
|
|
65
37
|
rebaseSessionCoordinatesAsync,
|
|
66
38
|
resolveOpenCodeProtectedTailBoundary,
|
|
67
39
|
getActiveCompartmentRun
|
|
68
|
-
} from "./index-
|
|
40
|
+
} from "./index-9tdvbdv1.js";
|
|
69
41
|
import"./index-sd3egckz.js";
|
|
70
42
|
import {
|
|
71
43
|
getHarness2
|
|
@@ -74,10 +46,11 @@ import {
|
|
|
74
46
|
getDataDir,
|
|
75
47
|
getMagicContextStorageDir
|
|
76
48
|
} from "./index-g2q4htwp.js";
|
|
49
|
+
import"./index-z4p0ry94.js";
|
|
77
50
|
import {
|
|
78
51
|
log2,
|
|
79
52
|
sessionLog2
|
|
80
|
-
} from "./index-
|
|
53
|
+
} from "./index-jrfre9ah.js";
|
|
81
54
|
import {
|
|
82
55
|
isSaneLimit,
|
|
83
56
|
setOutputReserveConfig,
|
|
@@ -87,8 +60,8 @@ import {
|
|
|
87
60
|
deriveHistorianChunkTokens2,
|
|
88
61
|
resolveKnownHistorianContextLimit2,
|
|
89
62
|
resolveHistorianContextLimit2
|
|
90
|
-
} from "./index-
|
|
91
|
-
import"./index-
|
|
63
|
+
} from "./index-dnqqqc5f.js";
|
|
64
|
+
import"./index-c5dzns43.js";
|
|
92
65
|
import {
|
|
93
66
|
CANONICAL_DREAM_TASKS,
|
|
94
67
|
DREAM_TASK_CAPABILITIES,
|
|
@@ -112,7 +85,9 @@ import {
|
|
|
112
85
|
ensureProjectRegisteredFromOpenCodeDirectory,
|
|
113
86
|
resolveContextLimit,
|
|
114
87
|
resolveModelKey,
|
|
88
|
+
parseCacheTtl,
|
|
115
89
|
createScheduler,
|
|
90
|
+
computeHardCacheExpired,
|
|
116
91
|
describeStorageUnavailability,
|
|
117
92
|
getSessionErrorInfo,
|
|
118
93
|
summarizeManualDream,
|
|
@@ -156,7 +131,7 @@ import {
|
|
|
156
131
|
applyJsonSchemaParameterDescriptions,
|
|
157
132
|
MagicContextRpcServer,
|
|
158
133
|
subagentTemperature
|
|
159
|
-
} from "./index-
|
|
134
|
+
} from "./index-gnmhbyyc.js";
|
|
160
135
|
import {
|
|
161
136
|
resolveHistorianModel2
|
|
162
137
|
} from "./index-5kym00ag.js";
|
|
@@ -164,19 +139,13 @@ import {
|
|
|
164
139
|
formatFailClosedBlockingMessage,
|
|
165
140
|
formatFailClosedBlockingSummary,
|
|
166
141
|
createFailClosedBlockingError,
|
|
167
|
-
isFailClosedBlockingError
|
|
168
|
-
|
|
169
|
-
BOOT_SQLITE_BUSY_TIMEOUT_MS,
|
|
170
|
-
openCurrentDatabase,
|
|
171
|
-
openDatabaseAsync,
|
|
172
|
-
isDatabasePersisted,
|
|
173
|
-
getDatabasePersistenceError
|
|
174
|
-
} from "./index-fm36bjv4.js";
|
|
142
|
+
isFailClosedBlockingError
|
|
143
|
+
} from "./index-wh9fxds5.js";
|
|
175
144
|
import {
|
|
176
145
|
setHomeProjectPermission,
|
|
177
146
|
resolveProjectIdentityForSession,
|
|
178
147
|
scheduleAfterBootQuiet
|
|
179
|
-
} from "./index-
|
|
148
|
+
} from "./index-txs8tce6.js";
|
|
180
149
|
import"./index-v0p37hm2.js";
|
|
181
150
|
import {
|
|
182
151
|
inRootAsyncContext2,
|
|
@@ -185,8 +154,9 @@ import {
|
|
|
185
154
|
isTransientSqliteError2,
|
|
186
155
|
withAsyncPrivilegedWriter2
|
|
187
156
|
} from "./index-gzy5w8ya.js";
|
|
188
|
-
import"./index-
|
|
189
|
-
import"./index-
|
|
157
|
+
import"./index-96ztjvkn.js";
|
|
158
|
+
import"./index-1d042x6w.js";
|
|
159
|
+
import"./index-r2epb000.js";
|
|
190
160
|
import"./index-1zx87sdm.js";
|
|
191
161
|
import {
|
|
192
162
|
stripPersistedAssistantText,
|
|
@@ -195,22 +165,19 @@ import {
|
|
|
195
165
|
isDroppedToolOutput,
|
|
196
166
|
evaluateChannel2,
|
|
197
167
|
buildChannel2Reminder
|
|
198
|
-
} from "./index-
|
|
168
|
+
} from "./index-8jjjmhab.js";
|
|
199
169
|
import {
|
|
200
170
|
hasMeaningfulUserText2,
|
|
201
171
|
preloadTokenizer,
|
|
202
172
|
estimateTokens
|
|
203
|
-
} from "./index-
|
|
173
|
+
} from "./index-4xyjr62e.js";
|
|
204
174
|
import {
|
|
205
175
|
getTableColumnNames
|
|
206
|
-
} from "./index-
|
|
176
|
+
} from "./index-9wnbnx8f.js";
|
|
207
177
|
import"./index-58e3y90n.js";
|
|
208
|
-
import"./index-
|
|
178
|
+
import"./index-vd2ywmfe.js";
|
|
209
179
|
import {
|
|
210
180
|
needsBlockedRead,
|
|
211
|
-
markHostUnservedRow,
|
|
212
|
-
markCoveredInstructionRow,
|
|
213
|
-
isCoveredInstructionRow,
|
|
214
181
|
DreamTokenBudgetExceeded,
|
|
215
182
|
createDreamTokenBudget,
|
|
216
183
|
recordToolParameters,
|
|
@@ -241,34 +208,72 @@ import {
|
|
|
241
208
|
cleanUserText2,
|
|
242
209
|
readRawSessionMessageIdOrdinalsForRange2,
|
|
243
210
|
readRawSessionMessageOrdinalById2
|
|
244
|
-
} from "./index-
|
|
211
|
+
} from "./index-tn9drm1a.js";
|
|
245
212
|
import {
|
|
246
213
|
BoundedSessionMap,
|
|
247
214
|
recordToolDefinitionSet,
|
|
248
215
|
getCurrentToolSetHash
|
|
249
|
-
} from "./index-
|
|
250
|
-
import"./index-
|
|
251
|
-
import"./index-
|
|
216
|
+
} from "./index-jkanybgq.js";
|
|
217
|
+
import"./index-2rs7912w.js";
|
|
218
|
+
import"./index-b1ydbp95.js";
|
|
252
219
|
import {
|
|
253
220
|
scheduleClearAndReindex
|
|
254
|
-
} from "./index-
|
|
221
|
+
} from "./index-dz48h1wx.js";
|
|
255
222
|
import {
|
|
256
223
|
invalidateAutoEmbedSession,
|
|
257
|
-
clearEmbedSessionState
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
import"./index-wfybj1dw.js";
|
|
224
|
+
clearEmbedSessionState
|
|
225
|
+
} from "./index-2amn2s73.js";
|
|
226
|
+
import"./index-g4t7850m.js";
|
|
261
227
|
import {
|
|
262
228
|
deleteChunkEmbedBackoffForSession2
|
|
263
|
-
} from "./index-
|
|
264
|
-
import"./index-
|
|
229
|
+
} from "./index-dcjkw41m.js";
|
|
230
|
+
import"./index-2p37txes.js";
|
|
231
|
+
import {
|
|
232
|
+
advanceSessionActivity,
|
|
233
|
+
backfillSessionActivity,
|
|
234
|
+
acquireCompartmentLease,
|
|
235
|
+
releaseCompartmentLeaseBestEffort,
|
|
236
|
+
isCompartmentLeaseHeld,
|
|
237
|
+
queueM0Mutation,
|
|
238
|
+
getUncoveredCompartmentEndsThrough,
|
|
239
|
+
providerResponseFailed,
|
|
240
|
+
isSuccessfulProviderCompletion,
|
|
241
|
+
readSessionMeta,
|
|
242
|
+
getOrCreateSessionMeta,
|
|
243
|
+
updateSessionMeta,
|
|
244
|
+
markSessionCleanupPending,
|
|
245
|
+
clearSession,
|
|
246
|
+
requestPendingMaterialization,
|
|
247
|
+
clearPendingMaterialization,
|
|
248
|
+
bindSystemPromptResponse,
|
|
249
|
+
retirePendingSystemPromptDelivery,
|
|
250
|
+
lkgProviderInputTotal,
|
|
251
|
+
beginV2LkgRequest,
|
|
252
|
+
currentLkgRequestIdentity,
|
|
253
|
+
noteLkgProviderResponse,
|
|
254
|
+
clearLkgMeasuredRequest,
|
|
255
|
+
getSlot,
|
|
256
|
+
dropSlot,
|
|
257
|
+
copySessionStateForClone
|
|
258
|
+
} from "./index-72czy45z.js";
|
|
259
|
+
import {
|
|
260
|
+
startBootDeadline,
|
|
261
|
+
BOOT_SQLITE_BUSY_TIMEOUT_MS,
|
|
262
|
+
openCurrentDatabase,
|
|
263
|
+
openDatabaseAsync,
|
|
264
|
+
isDatabasePersisted,
|
|
265
|
+
getDatabasePersistenceError
|
|
266
|
+
} from "./index-9fgmkfaf.js";
|
|
265
267
|
import"./index-fr0wbhdn.js";
|
|
266
|
-
import"./index-
|
|
267
|
-
import"./index-fb3zxn06.js";
|
|
268
|
+
import"./index-nj360hcs.js";
|
|
268
269
|
import {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
270
|
+
gaDatabasePath2,
|
|
271
|
+
RAW_MESSAGE_TYPES2,
|
|
272
|
+
V2StoreReaderPool2,
|
|
273
|
+
V2StoreReader2
|
|
274
|
+
} from "./index-66a50f3e.js";
|
|
275
|
+
import"./index-fb3zxn06.js";
|
|
276
|
+
import"./index-2qbtqg1w.js";
|
|
272
277
|
import {
|
|
273
278
|
createTagger,
|
|
274
279
|
cavemanWordRulesForLanguage,
|
|
@@ -277,41 +282,71 @@ import {
|
|
|
277
282
|
EmergencyFailClosedError,
|
|
278
283
|
DegradedPassRefusalError,
|
|
279
284
|
isSyntheticHeadMessage2
|
|
280
|
-
} from "./index-
|
|
281
|
-
import"./index-
|
|
285
|
+
} from "./index-dfdg2cgg.js";
|
|
286
|
+
import"./index-850vthn3.js";
|
|
282
287
|
import"./index-qt1qqasc.js";
|
|
283
|
-
import
|
|
288
|
+
import {
|
|
289
|
+
retainProjectEmbedding2
|
|
290
|
+
} from "./index-21fgrfrf.js";
|
|
291
|
+
import"./index-jz5bk7xd.js";
|
|
284
292
|
import"./index-4dhv7mqz.js";
|
|
285
|
-
import"./index-
|
|
286
|
-
import"./index-
|
|
293
|
+
import"./index-xd2p95m7.js";
|
|
294
|
+
import"./index-ty4vhe4n.js";
|
|
287
295
|
import"./index-jjvbk92s.js";
|
|
296
|
+
import {
|
|
297
|
+
renderUserFacingFailure,
|
|
298
|
+
userFacingFailureCode
|
|
299
|
+
} from "./index-xnm0wq1r.js";
|
|
288
300
|
import {
|
|
289
301
|
pushNotification2,
|
|
290
302
|
isTuiConnected2
|
|
291
303
|
} from "./index-x8a7jmkh.js";
|
|
292
|
-
import"./index-
|
|
293
|
-
import"./index-
|
|
294
|
-
import"./index-
|
|
295
|
-
import"./index-
|
|
304
|
+
import"./index-fw42ms3m.js";
|
|
305
|
+
import"./index-ae1ar4v1.js";
|
|
306
|
+
import"./index-wcwhhtdh.js";
|
|
307
|
+
import"./index-ys7j6679.js";
|
|
296
308
|
import"./index-gp3kcpc4.js";
|
|
297
309
|
import {
|
|
298
310
|
detectConflicts
|
|
299
|
-
} from "./index-
|
|
311
|
+
} from "./index-hacf2tyx.js";
|
|
312
|
+
import {
|
|
313
|
+
STORAGE_NOTICE_PREFIX,
|
|
314
|
+
formatStorageRefusalNotice,
|
|
315
|
+
formatStorageRecoveryNotice,
|
|
316
|
+
hasStorageNoticeShape,
|
|
317
|
+
dropStorageNotices,
|
|
318
|
+
restoreRow,
|
|
319
|
+
isToolError,
|
|
320
|
+
toolErrorText,
|
|
321
|
+
toolStateContent,
|
|
322
|
+
servedBoundaryRow2,
|
|
323
|
+
resolveV2BoundaryUserMessage2,
|
|
324
|
+
readAllV2RawMessagesForConversion2,
|
|
325
|
+
readV2RawMessagePagesForConversion2,
|
|
326
|
+
createV2RawMessageReader2,
|
|
327
|
+
createV2RawMessageProvider2
|
|
328
|
+
} from "./index-4y35msh5.js";
|
|
300
329
|
import"./index-fmsr7v69.js";
|
|
330
|
+
import"./index-j105mf16.js";
|
|
301
331
|
import"./index-kaqs6h31.js";
|
|
302
|
-
import"./index-
|
|
332
|
+
import"./index-prw8apnc.js";
|
|
333
|
+
import"./index-4ks89h5a.js";
|
|
303
334
|
import {
|
|
304
335
|
isDreamerRunnable,
|
|
305
336
|
isSmartNoteSurfaceAvailable,
|
|
306
337
|
isCompactionEnabled
|
|
307
338
|
} from "./index-ksdyrrav.js";
|
|
339
|
+
import {
|
|
340
|
+
markCoveredInstructionRow,
|
|
341
|
+
isCoveredInstructionRow
|
|
342
|
+
} from "./index-z9zygwse.js";
|
|
308
343
|
import {
|
|
309
344
|
sameProjectDirectory
|
|
310
345
|
} from "./index-knvkbfvh.js";
|
|
311
346
|
import {
|
|
312
347
|
getErrorMessage
|
|
313
348
|
} from "./index-y8v6yerm.js";
|
|
314
|
-
import"./index-
|
|
349
|
+
import"./index-fxbk7gk3.js";
|
|
315
350
|
|
|
316
351
|
// src/v2/hooks/context.ts
|
|
317
352
|
import { setTimeout as delay } from "node:timers/promises";
|
|
@@ -748,6 +783,93 @@ function hostMediaFromEncoded(value) {
|
|
|
748
783
|
return `${first}; ${second}`;
|
|
749
784
|
}
|
|
750
785
|
|
|
786
|
+
// src/v2/fold/idle.ts
|
|
787
|
+
class HostFoldIdle {
|
|
788
|
+
fold;
|
|
789
|
+
now;
|
|
790
|
+
timers;
|
|
791
|
+
windows = new Map;
|
|
792
|
+
attempted = new Map;
|
|
793
|
+
constructor(fold, now = Date.now, timers = { setTimeout, clearTimeout }) {
|
|
794
|
+
this.fold = fold;
|
|
795
|
+
this.now = now;
|
|
796
|
+
this.timers = timers;
|
|
797
|
+
}
|
|
798
|
+
active(sessionID) {
|
|
799
|
+
const window = this.windows.get(sessionID);
|
|
800
|
+
if (window?.timer)
|
|
801
|
+
this.timers.clearTimeout(window.timer);
|
|
802
|
+
this.windows.delete(sessionID);
|
|
803
|
+
}
|
|
804
|
+
idle(sessionID, cacheTtl, lastResponseTime) {
|
|
805
|
+
this.active(sessionID);
|
|
806
|
+
let ttl;
|
|
807
|
+
try {
|
|
808
|
+
ttl = parseCacheTtl(cacheTtl);
|
|
809
|
+
} catch {
|
|
810
|
+
ttl = 5 * 60 * 1000;
|
|
811
|
+
}
|
|
812
|
+
if (!Number.isFinite(ttl) || lastResponseTime <= 0)
|
|
813
|
+
return;
|
|
814
|
+
const attempted = this.attempted.get(sessionID);
|
|
815
|
+
if (attempted?.cacheTtl === cacheTtl && attempted.lastResponseTime === lastResponseTime)
|
|
816
|
+
return;
|
|
817
|
+
const window = { cacheTtl, lastResponseTime };
|
|
818
|
+
this.windows.set(sessionID, window);
|
|
819
|
+
const eligible = () => this.windows.get(sessionID) === window && computeHardCacheExpired(window.cacheTtl, window.lastResponseTime, this.now());
|
|
820
|
+
const wake = () => {
|
|
821
|
+
if (this.windows.get(sessionID) !== window)
|
|
822
|
+
return;
|
|
823
|
+
if (eligible()) {
|
|
824
|
+
window.timer = undefined;
|
|
825
|
+
this.attempted.set(sessionID, { cacheTtl, lastResponseTime });
|
|
826
|
+
const release = () => {
|
|
827
|
+
if (this.windows.get(sessionID) === window)
|
|
828
|
+
this.windows.delete(sessionID);
|
|
829
|
+
};
|
|
830
|
+
this.fold(sessionID, eligible).then(release, release);
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
const remaining = Math.max(1, lastResponseTime + ttl - this.now() + 1);
|
|
834
|
+
window.timer = this.timers.setTimeout(wake, Math.min(remaining, 2147483647));
|
|
835
|
+
window.timer.unref?.();
|
|
836
|
+
};
|
|
837
|
+
wake();
|
|
838
|
+
}
|
|
839
|
+
dispose() {
|
|
840
|
+
for (const sessionID of this.windows.keys())
|
|
841
|
+
this.active(sessionID);
|
|
842
|
+
this.attempted.clear();
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// src/v2/fold/manual-baseline.ts
|
|
847
|
+
function stageManualBaseline(db, sessionID, render) {
|
|
848
|
+
const read = () => db.prepare("SELECT * FROM session_meta WHERE session_id = ?").get(sessionID);
|
|
849
|
+
const before = read();
|
|
850
|
+
const columns = Object.keys(before).filter((key) => key.startsWith("cached_m0_") || key.startsWith("cached_m1_") || key === "memory_block_count" || key === "memory_block_ids");
|
|
851
|
+
const update = db.prepare(`UPDATE session_meta SET ${columns.map((key) => `${key} = ?`).join(", ")} WHERE session_id = ?`);
|
|
852
|
+
const restore = (row) => update.run(...columns.map((key) => row[key] ?? null), sessionID);
|
|
853
|
+
let summary;
|
|
854
|
+
let staged;
|
|
855
|
+
try {
|
|
856
|
+
summary = render();
|
|
857
|
+
staged = read();
|
|
858
|
+
} finally {
|
|
859
|
+
restore(before);
|
|
860
|
+
}
|
|
861
|
+
const commit = db.prepare(`UPDATE session_meta SET ${columns.map((key) => `${key} = ?`).join(", ")} WHERE session_id = ? AND ${columns.map((key) => `${key} IS ?`).join(" AND ")}`);
|
|
862
|
+
return {
|
|
863
|
+
summary,
|
|
864
|
+
boundaryID: staged.cached_m0_last_baseline_end_message_id,
|
|
865
|
+
commit() {
|
|
866
|
+
const result = commit.run(...columns.map((key) => staged[key] ?? null), sessionID, ...columns.map((key) => before[key] ?? null));
|
|
867
|
+
if (result.changes !== 1)
|
|
868
|
+
throw new Error("Manual compaction baseline changed during admission");
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
|
|
751
873
|
// src/v2/fold/memory-cache.ts
|
|
752
874
|
import { randomUUID } from "node:crypto";
|
|
753
875
|
|
|
@@ -1077,39 +1199,6 @@ function nativeFoldCache(db, budget) {
|
|
|
1077
1199
|
return new NativeFoldCache(typeof db === "function" ? db : () => db, budget);
|
|
1078
1200
|
}
|
|
1079
1201
|
|
|
1080
|
-
// src/v2/tool-result.ts
|
|
1081
|
-
function isToolError(part) {
|
|
1082
|
-
const result = part.result;
|
|
1083
|
-
return part.resultType === "error" || result?.type === "error" || result !== null && typeof result === "object" && "error" in result;
|
|
1084
|
-
}
|
|
1085
|
-
function toolErrorText(result) {
|
|
1086
|
-
const value = result.value === undefined ? result : result.value;
|
|
1087
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
1088
|
-
}
|
|
1089
|
-
function toolStateContent(state) {
|
|
1090
|
-
if (typeof state.output === "string")
|
|
1091
|
-
return state.output;
|
|
1092
|
-
if (state.status === "error")
|
|
1093
|
-
return toolErrorText({ error: state.error, content: state.content ?? [] });
|
|
1094
|
-
if (typeof state.content === "string")
|
|
1095
|
-
return state.content;
|
|
1096
|
-
if (!Array.isArray(state.content))
|
|
1097
|
-
return "";
|
|
1098
|
-
return state.content.map((part) => {
|
|
1099
|
-
if (typeof part === "string")
|
|
1100
|
-
return part;
|
|
1101
|
-
if (!part || typeof part !== "object")
|
|
1102
|
-
return "";
|
|
1103
|
-
const value = part;
|
|
1104
|
-
if (typeof value.text === "string")
|
|
1105
|
-
return value.text;
|
|
1106
|
-
if (typeof value.value === "string")
|
|
1107
|
-
return value.value;
|
|
1108
|
-
return "";
|
|
1109
|
-
}).filter(Boolean).join(`
|
|
1110
|
-
`);
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
1202
|
// src/v2/hooks/copied-tag-notation.ts
|
|
1114
1203
|
function stripCopiedTagNotation(text, acceptsEmpty = true) {
|
|
1115
1204
|
return text.includes("§") ? stripPersistedAssistantText(text, acceptsEmpty) : text;
|
|
@@ -1567,6 +1656,30 @@ function adaptPayload(draft, admittedIDs = new Set, messageTimes = new Map, hidd
|
|
|
1567
1656
|
};
|
|
1568
1657
|
}
|
|
1569
1658
|
|
|
1659
|
+
// src/v2/fold/code-mode-catalog.ts
|
|
1660
|
+
var changed = "The Code Mode tool catalog has changed.";
|
|
1661
|
+
var replacement = `${changed} This catalog supersedes the previous Code Mode tool catalog.`;
|
|
1662
|
+
function codeModeCatalogKind(data) {
|
|
1663
|
+
const text = data.text ?? "";
|
|
1664
|
+
const metadata = data.metadata;
|
|
1665
|
+
const keyed = typeof metadata === "object" && metadata !== null && "instructionSources" in metadata;
|
|
1666
|
+
if (keyed) {
|
|
1667
|
+
const sources = metadata.instructionSources;
|
|
1668
|
+
if (!Array.isArray(sources) || !sources.includes("core/codemode"))
|
|
1669
|
+
return;
|
|
1670
|
+
if (sources.length !== 1)
|
|
1671
|
+
return text.startsWith(replacement) ? "combined-replacement" : undefined;
|
|
1672
|
+
}
|
|
1673
|
+
if (text.startsWith(replacement))
|
|
1674
|
+
return "replacement";
|
|
1675
|
+
if (text.startsWith(changed))
|
|
1676
|
+
return "incremental";
|
|
1677
|
+
if (keyed || text.startsWith(`# Code Mode
|
|
1678
|
+
`) || text.startsWith("No Code Mode tools are currently available."))
|
|
1679
|
+
return "initial";
|
|
1680
|
+
return;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1570
1683
|
// src/v2/fold/native-codec.ts
|
|
1571
1684
|
class NativeReplayUnavailable extends Error {
|
|
1572
1685
|
}
|
|
@@ -1608,246 +1721,206 @@ function reviveNative(messages) {
|
|
|
1608
1721
|
return result;
|
|
1609
1722
|
}
|
|
1610
1723
|
|
|
1611
|
-
// src/v2/fold/
|
|
1612
|
-
|
|
1724
|
+
// src/v2/fold/native-replay-v3.ts
|
|
1725
|
+
var IMPORTED_MC_SUMMARY = "[Compacted by magic-context — session history is managed by the plugin]";
|
|
1726
|
+
var MAX_CONTROL_BYTES = 128 * 1024;
|
|
1727
|
+
var efforts = new Set(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);
|
|
1613
1728
|
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1729
|
+
class ControlMetadataUnavailable extends Error {
|
|
1730
|
+
}
|
|
1731
|
+
var object = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
1732
|
+
var keys = (value, allowed) => Object.keys(value).every((key) => allowed.includes(key));
|
|
1733
|
+
var identity = (value) => typeof value === "string" && value.length > 0 && Buffer.byteLength(value) <= 1024;
|
|
1734
|
+
var digest = (value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
1735
|
+
function validReplayState(value) {
|
|
1736
|
+
if (!object(value) || !keys(value, [
|
|
1737
|
+
"floor",
|
|
1738
|
+
"controls",
|
|
1739
|
+
"blocked",
|
|
1740
|
+
"upgrade",
|
|
1741
|
+
"withoutRecentContext",
|
|
1742
|
+
"retiredInstructionThrough",
|
|
1743
|
+
"retiredInstructionIDs"
|
|
1744
|
+
]))
|
|
1745
|
+
return false;
|
|
1746
|
+
const floor = value.floor;
|
|
1747
|
+
const upgrade = value.upgrade;
|
|
1748
|
+
return object(floor) && keys(floor, ["kind", "id", "seq", "after", "digest"]) && ["start", "summary", "checkpoint", "host-checkpoint"].includes(floor.kind) && identity(floor.id) && typeof floor.seq === "number" && typeof floor.after === "number" && Number.isSafeInteger(floor.seq) && Number.isSafeInteger(floor.after) && floor.after === (floor.kind === "start" || floor.kind === "host-checkpoint" ? floor.seq - 1 : floor.seq) && digest(floor.digest) && validControls(value.controls) && (value.blocked === undefined || typeof value.blocked === "boolean") && (value.withoutRecentContext === undefined || typeof value.withoutRecentContext === "boolean") && (value.retiredInstructionThrough === undefined || Number.isSafeInteger(value.retiredInstructionThrough) && value.retiredInstructionThrough >= 0) && (value.retiredInstructionIDs === undefined || Array.isArray(value.retiredInstructionIDs) && value.retiredInstructionIDs.every(identity)) && (upgrade === undefined || object(upgrade) && keys(upgrade, ["admissionID", "mode"]) && identity(upgrade.admissionID) && ["bounded", "host-checkpoint", "source-repair"].includes(upgrade.mode));
|
|
1621
1749
|
}
|
|
1622
|
-
function
|
|
1623
|
-
|
|
1750
|
+
function instructionRetirement(replay) {
|
|
1751
|
+
const ids = new Set(replay?.retiredInstructionIDs);
|
|
1752
|
+
const through = replay?.retiredInstructionThrough ?? -1;
|
|
1753
|
+
return (row) => row.type === "system" && (row.seq <= through || ids.has(row.id));
|
|
1624
1754
|
}
|
|
1625
|
-
function
|
|
1626
|
-
if (
|
|
1755
|
+
function validAdmissionV3(value) {
|
|
1756
|
+
if (!object(value) || !keys(value, ["version", "proof", "replay"]) || value.version !== 3 || !object(value.proof))
|
|
1627
1757
|
return false;
|
|
1628
|
-
|
|
1758
|
+
const proof = value.proof;
|
|
1759
|
+
return keys(proof, [
|
|
1760
|
+
"sourceDigest",
|
|
1761
|
+
"sessionID",
|
|
1762
|
+
"admissionID",
|
|
1763
|
+
"summaryDigest",
|
|
1764
|
+
"historyDigest"
|
|
1765
|
+
]) && identity(proof.sessionID) && identity(proof.admissionID) && digest(proof.sourceDigest) && digest(proof.summaryDigest) && digest(proof.historyDigest) && validReplayState(value.replay);
|
|
1766
|
+
}
|
|
1767
|
+
function encodeAdmissionV3(value) {
|
|
1768
|
+
if (!validAdmissionV3(value))
|
|
1769
|
+
throw new Error("Unsupported native fold admission metadata");
|
|
1770
|
+
return JSON.stringify(value);
|
|
1771
|
+
}
|
|
1772
|
+
function validCapturedReplayV3(value) {
|
|
1773
|
+
return object(value) && keys(value, ["version", "sessionID", "sourceDigest", "through", "replay"]) && value.version === 3 && identity(value.sessionID) && digest(value.sourceDigest) && Number.isSafeInteger(value.through) && validReplayState(value.replay);
|
|
1774
|
+
}
|
|
1775
|
+
function floorFor(row, kind) {
|
|
1776
|
+
return {
|
|
1777
|
+
kind,
|
|
1778
|
+
id: row.id,
|
|
1779
|
+
seq: row.seq,
|
|
1780
|
+
after: inclusiveFloor(kind) ? row.seq - 1 : row.seq,
|
|
1781
|
+
digest: foldDigest(JSON.stringify(row))
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
function validFloor(reader, sessionID, value) {
|
|
1785
|
+
if (!value || !["checkpoint", "summary", "start", "host-checkpoint"].includes(value.kind) || !Number.isSafeInteger(value.seq) || !Number.isSafeInteger(value.after) || value.after !== (inclusiveFloor(value.kind) ? value.seq - 1 : value.seq))
|
|
1629
1786
|
return false;
|
|
1630
|
-
const
|
|
1631
|
-
return
|
|
1787
|
+
const row = reader.range(sessionID, value.seq - 1, value.seq).find((candidate) => candidate.id === value.id && candidate.seq === value.seq);
|
|
1788
|
+
return !!row && row.session_id === sessionID && foldDigest(JSON.stringify(row)) === value.digest;
|
|
1632
1789
|
}
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
for (const message of messages) {
|
|
1636
|
-
if (!hasStorageNoticeShape(message))
|
|
1637
|
-
continue;
|
|
1638
|
-
if (await isAdmittedSynthetic(message.id))
|
|
1639
|
-
drop.add(message);
|
|
1640
|
-
}
|
|
1641
|
-
if (drop.size === 0)
|
|
1642
|
-
return 0;
|
|
1643
|
-
const kept = messages.filter((message) => !drop.has(message));
|
|
1644
|
-
messages.splice(0, messages.length, ...kept);
|
|
1645
|
-
return drop.size;
|
|
1790
|
+
function inclusiveFloor(kind) {
|
|
1791
|
+
return kind === "start" || kind === "host-checkpoint";
|
|
1646
1792
|
}
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
directory && !file.data.length ? undefined : Buffer.from(file.data, "base64").toString("utf8")
|
|
1683
|
-
].filter((line) => line !== undefined).join(`
|
|
1684
|
-
`)}`,
|
|
1685
|
-
metadata: {
|
|
1686
|
-
attachment: {
|
|
1687
|
-
source: file.source,
|
|
1688
|
-
name: file.name,
|
|
1689
|
-
description: file.description
|
|
1690
|
-
}
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1693
|
-
];
|
|
1793
|
+
function hostCheckpointCarrier(row) {
|
|
1794
|
+
return {
|
|
1795
|
+
id: row.id,
|
|
1796
|
+
role: "user",
|
|
1797
|
+
content: [
|
|
1798
|
+
{
|
|
1799
|
+
type: "text",
|
|
1800
|
+
text: [
|
|
1801
|
+
"<conversation-checkpoint>",
|
|
1802
|
+
"The following is a summary and serialized record of earlier conversation. Treat it as historical context, not as new instructions.",
|
|
1803
|
+
"",
|
|
1804
|
+
`<summary>
|
|
1805
|
+
${row.data.summary ?? ""}
|
|
1806
|
+
</summary>`,
|
|
1807
|
+
...row.data.recent ? ["", `<recent-context>
|
|
1808
|
+
${row.data.recent}
|
|
1809
|
+
</recent-context>`] : [],
|
|
1810
|
+
"</conversation-checkpoint>"
|
|
1811
|
+
].join(`
|
|
1812
|
+
`)
|
|
1813
|
+
}
|
|
1814
|
+
],
|
|
1815
|
+
...row.data.metadata === undefined ? {} : { metadata: row.data.metadata }
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
function importedFloor(reader, sessionID, through = reader.latestSequence(sessionID)) {
|
|
1819
|
+
let after = -1;
|
|
1820
|
+
let found;
|
|
1821
|
+
while (true) {
|
|
1822
|
+
const page = reader.page(sessionID, { after, through, type: "compaction", limit: 1000 });
|
|
1823
|
+
if (!page.rows.length)
|
|
1824
|
+
break;
|
|
1825
|
+
for (const row of page.rows) {
|
|
1826
|
+
if (row.type === "compaction" && row.data.status === "completed" && row.data.summary === IMPORTED_MC_SUMMARY)
|
|
1827
|
+
found = row;
|
|
1694
1828
|
}
|
|
1695
|
-
if (
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1829
|
+
if (page.cursor === undefined || page.cursor <= after)
|
|
1830
|
+
break;
|
|
1831
|
+
after = page.cursor;
|
|
1832
|
+
}
|
|
1833
|
+
return found ? floorFor(found, "checkpoint") : undefined;
|
|
1834
|
+
}
|
|
1835
|
+
function effortPart(message) {
|
|
1836
|
+
return message.role === "system" && message.content.length === 1 && message.content[0]?.type === "effort" ? message.content[0] : undefined;
|
|
1837
|
+
}
|
|
1838
|
+
function validControls(value) {
|
|
1839
|
+
return Array.isArray(value) && Buffer.byteLength(JSON.stringify(value)) <= MAX_CONTROL_BYTES && value.every((control) => control && typeof control === "object" && !Array.isArray(control) && Object.keys(control).every((key) => ["after", "effort", "previous"].includes(key)) && (control.after === undefined || identity(control.after)) && (control.effort === undefined || efforts.has(control.effort)) && (control.previous === undefined || efforts.has(control.previous)));
|
|
1840
|
+
}
|
|
1841
|
+
function captureControls(draft, coordinate, visibleIDs) {
|
|
1842
|
+
let after;
|
|
1843
|
+
const controls = [];
|
|
1844
|
+
for (const message of draft.messages) {
|
|
1845
|
+
const part = effortPart(message);
|
|
1846
|
+
if (part) {
|
|
1847
|
+
const control = {
|
|
1848
|
+
after,
|
|
1849
|
+
effort: part.effort,
|
|
1850
|
+
previous: part.previous
|
|
1851
|
+
};
|
|
1852
|
+
if (!validControls([control]))
|
|
1853
|
+
throw new ControlMetadataUnavailable("unsupported host effort control");
|
|
1854
|
+
controls.push(control);
|
|
1855
|
+
} else {
|
|
1856
|
+
const id = coordinate(message);
|
|
1857
|
+
if (id && visibleIDs.has(id))
|
|
1858
|
+
after = id;
|
|
1717
1859
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1860
|
+
}
|
|
1861
|
+
if (!validControls(controls))
|
|
1862
|
+
throw new ControlMetadataUnavailable("host effort controls exceed replay metadata budget");
|
|
1863
|
+
return controls;
|
|
1720
1864
|
}
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
...metadata === undefined ? {} : { metadata }
|
|
1865
|
+
var controlCoordinates = new WeakMap;
|
|
1866
|
+
function controlKey(control) {
|
|
1867
|
+
return JSON.stringify({
|
|
1868
|
+
after: control.after,
|
|
1869
|
+
effort: control.effort,
|
|
1870
|
+
previous: control.previous
|
|
1728
1871
|
});
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
})
|
|
1741
|
-
] : [];
|
|
1742
|
-
}
|
|
1743
|
-
if (row.type === "system")
|
|
1744
|
-
return [{ role: "system", content: [{ type: "text", text: data.text ?? "" }] }];
|
|
1745
|
-
if (row.type === "synthetic" && isStorageNoticeText(data.text))
|
|
1746
|
-
return [];
|
|
1747
|
-
if (["synthetic", "skill"].includes(row.type))
|
|
1748
|
-
return [make("user", [{ type: "text", text: data.text ?? "" }])];
|
|
1749
|
-
if (row.type === "location-switched")
|
|
1750
|
-
return [
|
|
1751
|
-
make("user", [
|
|
1752
|
-
{
|
|
1753
|
-
type: "text",
|
|
1754
|
-
text: `The working directory has been changed to ${data.location.directory}.`
|
|
1755
|
-
}
|
|
1756
|
-
])
|
|
1757
|
-
];
|
|
1758
|
-
if (row.type === "shell")
|
|
1759
|
-
return data.metadata?.background === true ? [] : [
|
|
1760
|
-
make("user", [
|
|
1872
|
+
}
|
|
1873
|
+
function rememberedControlKey(message) {
|
|
1874
|
+
return controlCoordinates.get(message);
|
|
1875
|
+
}
|
|
1876
|
+
function insertControls(messages, controls, coordinate) {
|
|
1877
|
+
const remaining = new Set(controls);
|
|
1878
|
+
const emit = (control) => {
|
|
1879
|
+
remaining.delete(control);
|
|
1880
|
+
const message = {
|
|
1881
|
+
role: "system",
|
|
1882
|
+
content: [
|
|
1761
1883
|
{
|
|
1762
|
-
type: "
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
Command:
|
|
1766
|
-
${data.command}
|
|
1767
|
-
|
|
1768
|
-
Output:
|
|
1769
|
-
${data.output?.output ?? ""}`
|
|
1884
|
+
type: "effort",
|
|
1885
|
+
...control.effort === undefined ? {} : { effort: control.effort },
|
|
1886
|
+
...control.previous === undefined ? {} : { previous: control.previous }
|
|
1770
1887
|
}
|
|
1771
|
-
]
|
|
1772
|
-
];
|
|
1773
|
-
if (row.type !== "assistant")
|
|
1774
|
-
return [];
|
|
1775
|
-
const previousModel = data.model;
|
|
1776
|
-
const sameProvider = previousModel?.providerID === model.providerID;
|
|
1777
|
-
const sameModel = sameProvider && previousModel?.id === model.id;
|
|
1778
|
-
const reuse = sameModel && data.error === undefined;
|
|
1779
|
-
const metadata = (state) => state === undefined ? undefined : { [model.providerID]: state };
|
|
1780
|
-
const reasoningInterrupted = data.content?.some((part) => part.type === "reasoning" && part.time !== undefined && part.time.completed === undefined);
|
|
1781
|
-
const content = [];
|
|
1782
|
-
const results = [];
|
|
1783
|
-
for (const part of data.content ?? []) {
|
|
1784
|
-
let native = "native" in part ? part.native : part.type === "tool" ? part.providerState : part.state;
|
|
1785
|
-
if (part.type === "tool" && part.providerResultState !== null && typeof part.providerResultState === "object" && !Array.isArray(part.providerResultState))
|
|
1786
|
-
native = {
|
|
1787
|
-
...native !== null && typeof native === "object" && !Array.isArray(native) ? native : {},
|
|
1788
|
-
...part.providerResultState
|
|
1789
|
-
};
|
|
1790
|
-
if (part.type === "text") {
|
|
1791
|
-
if (part.text !== "")
|
|
1792
|
-
content.push({
|
|
1793
|
-
type: "text",
|
|
1794
|
-
text: part.text,
|
|
1795
|
-
providerMetadata: reuse ? metadata(native) : undefined
|
|
1796
|
-
});
|
|
1797
|
-
continue;
|
|
1798
|
-
}
|
|
1799
|
-
if (part.type === "reasoning") {
|
|
1800
|
-
if (part.text !== "" || reuse && !reasoningInterrupted && native !== undefined)
|
|
1801
|
-
content.push({
|
|
1802
|
-
type: data.error === undefined && !reasoningInterrupted ? "reasoning" : "text",
|
|
1803
|
-
text: part.text,
|
|
1804
|
-
providerMetadata: reuse && !reasoningInterrupted ? metadata(native) : undefined
|
|
1805
|
-
});
|
|
1806
|
-
continue;
|
|
1807
|
-
}
|
|
1808
|
-
const state = part.state;
|
|
1809
|
-
const completed = state.status === "completed" || state.status === "error";
|
|
1810
|
-
const toolReuse = reuse || sameModel && part.executed === true && completed;
|
|
1811
|
-
let input = state.input;
|
|
1812
|
-
if (state.status === "streaming" && typeof input === "string") {
|
|
1813
|
-
try {
|
|
1814
|
-
input = JSON.parse(input);
|
|
1815
|
-
} catch {}
|
|
1816
|
-
}
|
|
1817
|
-
content.push({
|
|
1818
|
-
type: "tool-call",
|
|
1819
|
-
id: part.id,
|
|
1820
|
-
name: part.name,
|
|
1821
|
-
input,
|
|
1822
|
-
providerExecuted: part.executed,
|
|
1823
|
-
providerMetadata: toolReuse ? metadata(native) : undefined
|
|
1824
|
-
});
|
|
1825
|
-
if (!completed)
|
|
1826
|
-
continue;
|
|
1827
|
-
const toolContent = state.content ?? [];
|
|
1828
|
-
const single = toolContent.length === 1 ? toolContent[0] : undefined;
|
|
1829
|
-
const result = {
|
|
1830
|
-
type: "tool-result",
|
|
1831
|
-
id: part.id,
|
|
1832
|
-
name: part.name,
|
|
1833
|
-
providerExecuted: part.executed,
|
|
1834
|
-
providerMetadata: (part.executed === true ? sameProvider : reuse) ? metadata(native) : undefined,
|
|
1835
|
-
result: state.status === "error" ? { error: state.error, content: toolContent } : single?.type === "text" ? { type: "text", value: single.text } : { type: "content", value: toolContent },
|
|
1836
|
-
...state.status === "error" ? { resultType: "error" } : {}
|
|
1888
|
+
]
|
|
1837
1889
|
};
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1890
|
+
controlCoordinates.set(message, controlKey(control));
|
|
1891
|
+
return message;
|
|
1892
|
+
};
|
|
1893
|
+
const ids = new Set(messages.flatMap((message) => coordinate(message) ?? []));
|
|
1894
|
+
const output = controls.filter((control) => !control.after || !ids.has(control.after)).map(emit);
|
|
1895
|
+
for (const message of messages) {
|
|
1896
|
+
output.push(message);
|
|
1897
|
+
const id = coordinate(message);
|
|
1898
|
+
if (id) {
|
|
1899
|
+
for (const control of remaining)
|
|
1900
|
+
if (control.after === id)
|
|
1901
|
+
output.push(emit(control));
|
|
1902
|
+
}
|
|
1842
1903
|
}
|
|
1843
|
-
return
|
|
1904
|
+
return output;
|
|
1905
|
+
}
|
|
1906
|
+
function controlsThrough(controls, reader, sessionID, through) {
|
|
1907
|
+
return controls.filter((control) => !control.after || (reader.sequenceForId(sessionID, control.after) ?? Infinity) <= through);
|
|
1844
1908
|
}
|
|
1845
1909
|
|
|
1846
1910
|
// src/v2/fold/native-replay.ts
|
|
1847
1911
|
var coordinates = new WeakMap;
|
|
1912
|
+
var sequences = new WeakMap;
|
|
1913
|
+
function nativeRowSequence(message) {
|
|
1914
|
+
return sequences.get(message);
|
|
1915
|
+
}
|
|
1848
1916
|
function nativeRowID(message) {
|
|
1849
1917
|
return coordinates.get(message) ?? message.id;
|
|
1850
1918
|
}
|
|
1919
|
+
function bindNativeRowID(message, id, seq) {
|
|
1920
|
+
coordinates.set(message, id);
|
|
1921
|
+
if (seq !== undefined)
|
|
1922
|
+
sequences.set(message, seq);
|
|
1923
|
+
}
|
|
1851
1924
|
function copyNativeInput(messages) {
|
|
1852
1925
|
const copies = reviveNative(encodeNative(messages));
|
|
1853
1926
|
copies.forEach((copy, i) => {
|
|
@@ -1855,6 +1928,9 @@ function copyNativeInput(messages) {
|
|
|
1855
1928
|
const id = original && nativeRowID(original);
|
|
1856
1929
|
if (id !== undefined)
|
|
1857
1930
|
coordinates.set(copy, id);
|
|
1931
|
+
const seq = original && sequences.get(original);
|
|
1932
|
+
if (seq !== undefined)
|
|
1933
|
+
sequences.set(copy, seq);
|
|
1858
1934
|
});
|
|
1859
1935
|
return copies;
|
|
1860
1936
|
}
|
|
@@ -1874,9 +1950,10 @@ function isAdmittedLocalCheckpoint(storage, sessionID, cut) {
|
|
|
1874
1950
|
return false;
|
|
1875
1951
|
}
|
|
1876
1952
|
}
|
|
1877
|
-
var conversational = (row) =>
|
|
1878
|
-
var historyDigest = (reader, sessionID, through) => foldDigest(JSON.stringify(reader.range(sessionID,
|
|
1953
|
+
var conversational = (row) => RAW_MESSAGE_TYPES2.includes(row.type) || row.type === "location-switched";
|
|
1954
|
+
var historyDigest = (reader, sessionID, through, after = -1) => foldDigest(JSON.stringify(reader.range(sessionID, after, through).filter(conversational)));
|
|
1879
1955
|
var admissionKey = (sessionID) => `native-fold/v2/${encodeURIComponent(sessionID)}`;
|
|
1956
|
+
var capturedReplayKey = (sessionID) => `native-fold-state/v3/${encodeURIComponent(sessionID)}`;
|
|
1880
1957
|
async function forgetNativeFoldProvenance(storage, sessionID, legacyOnly = false) {
|
|
1881
1958
|
const remove = async (key) => {
|
|
1882
1959
|
if (storage.remove)
|
|
@@ -1884,8 +1961,11 @@ async function forgetNativeFoldProvenance(storage, sessionID, legacyOnly = false
|
|
|
1884
1961
|
else
|
|
1885
1962
|
await storage.set(key, null);
|
|
1886
1963
|
};
|
|
1887
|
-
if (!legacyOnly)
|
|
1964
|
+
if (!legacyOnly) {
|
|
1888
1965
|
await remove(admissionKey(sessionID));
|
|
1966
|
+
await remove(`native-fold/v3/${encodeURIComponent(sessionID)}`);
|
|
1967
|
+
await remove(capturedReplayKey(sessionID));
|
|
1968
|
+
}
|
|
1889
1969
|
if (!storage.scan)
|
|
1890
1970
|
return;
|
|
1891
1971
|
let after;
|
|
@@ -1903,18 +1983,25 @@ class NativeFoldReplay {
|
|
|
1903
1983
|
storage;
|
|
1904
1984
|
openReader;
|
|
1905
1985
|
admissions;
|
|
1986
|
+
options;
|
|
1906
1987
|
changed = new Set;
|
|
1907
1988
|
dirty = new Set;
|
|
1908
1989
|
unavailable = new Set;
|
|
1909
1990
|
metadata = new Map;
|
|
1910
1991
|
metadataThrough = new Map;
|
|
1992
|
+
metadataAfter = new Map;
|
|
1993
|
+
stampMRU;
|
|
1911
1994
|
loaded = new Map;
|
|
1912
1995
|
sources = new Map;
|
|
1913
1996
|
staleHeads = new Set;
|
|
1914
|
-
|
|
1997
|
+
unprovenControls = new Set;
|
|
1998
|
+
editedAdmissions = new Map;
|
|
1999
|
+
legacyUpgrades = new Map;
|
|
2000
|
+
constructor(storage, openReader, admissions, options = {}) {
|
|
1915
2001
|
this.storage = storage;
|
|
1916
2002
|
this.openReader = openReader;
|
|
1917
2003
|
this.admissions = admissions;
|
|
2004
|
+
this.options = options;
|
|
1918
2005
|
storage.onEvict((sessionID) => this.clear(sessionID));
|
|
1919
2006
|
}
|
|
1920
2007
|
account(sessionID) {
|
|
@@ -1938,6 +2025,8 @@ class NativeFoldReplay {
|
|
|
1938
2025
|
this.invalidate(sessionID);
|
|
1939
2026
|
}
|
|
1940
2027
|
invalidate(sessionID, suppressNomination = false) {
|
|
2028
|
+
if (this.stampMRU?.sessionID === sessionID)
|
|
2029
|
+
this.stampMRU = undefined;
|
|
1941
2030
|
if (suppressNomination)
|
|
1942
2031
|
this.unavailable.add(sessionID);
|
|
1943
2032
|
this.dirty.add(sessionID);
|
|
@@ -1953,8 +2042,333 @@ class NativeFoldReplay {
|
|
|
1953
2042
|
async baseline(sessionID) {
|
|
1954
2043
|
return this.tail(sessionID)?.baseline;
|
|
1955
2044
|
}
|
|
2045
|
+
async retiredInstructionThrough(sessionID, reader) {
|
|
2046
|
+
if (!reader.latestCompaction(sessionID))
|
|
2047
|
+
return -1;
|
|
2048
|
+
return (await this.floorState(sessionID, reader))?.retiredInstructionThrough ?? -1;
|
|
2049
|
+
}
|
|
2050
|
+
async instructionRetirement(sessionID, reader) {
|
|
2051
|
+
if (!reader.latestCompaction(sessionID))
|
|
2052
|
+
return instructionRetirement();
|
|
2053
|
+
return instructionRetirement(await this.floorState(sessionID, reader));
|
|
2054
|
+
}
|
|
2055
|
+
async prepareManualFold(sessionID, reader, boundaryID, summary) {
|
|
2056
|
+
const running = reader.latestRunningCompaction(sessionID);
|
|
2057
|
+
if (!running || this.options.protocol !== 3)
|
|
2058
|
+
throw new NativeReplayUnavailable("Manual compaction has no running host checkpoint");
|
|
2059
|
+
const previous = await this.floorState(sessionID, reader);
|
|
2060
|
+
if (this.unprovenControls.has(sessionID) || previous?.blocked)
|
|
2061
|
+
throw new NativeReplayUnavailable("Manual compaction controls have not been captured");
|
|
2062
|
+
const seq = boundaryID ? reader.sequenceForId(sessionID, boundaryID) : undefined;
|
|
2063
|
+
const row = seq === undefined ? undefined : reader.range(sessionID, seq - 1, seq)[0];
|
|
2064
|
+
const first = reader.page(sessionID, { limit: 1 }).rows[0];
|
|
2065
|
+
let floor = row ? floorFor(row, "summary") : undefined;
|
|
2066
|
+
floor ??= first ? floorFor(first, "start") : undefined;
|
|
2067
|
+
if (!floor)
|
|
2068
|
+
throw new NativeReplayUnavailable("Manual compaction has no history boundary");
|
|
2069
|
+
const instructions = reader.instructionRowsThrough(sessionID, running.seq - 1);
|
|
2070
|
+
const retiredInstructionIDs = [];
|
|
2071
|
+
let newerFullCatalog = false;
|
|
2072
|
+
for (const instruction of [...instructions].reverse()) {
|
|
2073
|
+
const text = instruction.data.text ?? "";
|
|
2074
|
+
const catalog = codeModeCatalogKind(instruction.data);
|
|
2075
|
+
if (instruction.seq > floor.after && (catalog && catalog !== "combined-replacement" && newerFullCatalog || text.length > 0 && summary.includes(text)))
|
|
2076
|
+
retiredInstructionIDs.push(instruction.id);
|
|
2077
|
+
if (catalog === "replacement" || catalog === "combined-replacement")
|
|
2078
|
+
newerFullCatalog = true;
|
|
2079
|
+
}
|
|
2080
|
+
return {
|
|
2081
|
+
floor,
|
|
2082
|
+
controls: previous?.controls ?? [],
|
|
2083
|
+
...floor.after >= 0 ? { retiredInstructionThrough: floor.after } : {},
|
|
2084
|
+
retiredInstructionIDs
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
1956
2087
|
admissionKey(sessionID) {
|
|
1957
|
-
return admissionKey(sessionID);
|
|
2088
|
+
return this.options.protocol === 3 ? `native-fold/v3/${encodeURIComponent(sessionID)}` : admissionKey(sessionID);
|
|
2089
|
+
}
|
|
2090
|
+
report(sessionID, reason) {
|
|
2091
|
+
try {
|
|
2092
|
+
this.options.log?.(sessionID, `v3 host fold: ${reason}`);
|
|
2093
|
+
} catch {}
|
|
2094
|
+
}
|
|
2095
|
+
async floorState(sessionID, reader, boundary, served, preferCapture = false) {
|
|
2096
|
+
const retained = this.tail(sessionID)?.replay;
|
|
2097
|
+
const controlsKnown = (replay) => replay.controls.every((control) => !control.after || reader.sequenceForId(sessionID, control.after) !== undefined);
|
|
2098
|
+
const memory = retained && validReplayState(retained) && controlsKnown(retained) && validFloor(reader, sessionID, retained.floor) ? retained : undefined;
|
|
2099
|
+
const cut = reader.latestCompaction(sessionID);
|
|
2100
|
+
const saved = await this.readV3(sessionID);
|
|
2101
|
+
const durable = saved && saved.proof.sourceDigest === foldDigest(reader.hostIdentity()) && (!cut || saved.proof.admissionID === cut.id) && controlsKnown(saved.replay) && validFloor(reader, sessionID, saved.replay.floor) ? saved.replay : undefined;
|
|
2102
|
+
const imported = importedFloor(reader, sessionID, cut?.seq);
|
|
2103
|
+
const captured = await this.readCapturedReplay(sessionID, reader);
|
|
2104
|
+
const existing = preferCapture ? captured ?? memory ?? durable : memory ?? durable ?? captured;
|
|
2105
|
+
if (preferCapture && !existing && !served)
|
|
2106
|
+
return;
|
|
2107
|
+
let floor = existing?.floor ?? imported;
|
|
2108
|
+
if (imported && (!floor || imported.after > floor.after))
|
|
2109
|
+
floor = imported;
|
|
2110
|
+
if (cut) {
|
|
2111
|
+
const meta = readSessionMeta(this.storage.db, sessionID);
|
|
2112
|
+
const max = this.storage.db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM m0_mutation_log WHERE session_id=?").get(sessionID);
|
|
2113
|
+
const bound = this.storage.db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(sessionID);
|
|
2114
|
+
const seq = bound?.id ? reader.sequenceForId(sessionID, bound.id) : undefined;
|
|
2115
|
+
if (meta.cachedM0Bytes && max.id <= (meta.cachedM0MaxMutationId ?? 0) && seq !== undefined && (!floor || seq > floor.after)) {
|
|
2116
|
+
const row = reader.range(sessionID, seq - 1, seq).find((row) => row.id === bound?.id);
|
|
2117
|
+
if (row)
|
|
2118
|
+
floor = floorFor(row, "summary");
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
const baseline = served ? this.servedBaseline(served) : undefined;
|
|
2122
|
+
if (boundary && baseline === boundary.summary) {
|
|
2123
|
+
const seq = reader.sequenceForId(sessionID, boundary.id);
|
|
2124
|
+
if (seq !== undefined && (!floor || seq > floor.after)) {
|
|
2125
|
+
const row = reader.range(sessionID, seq - 1, seq).find((row) => row.id === boundary.id);
|
|
2126
|
+
if (row)
|
|
2127
|
+
floor = floorFor(row, "summary");
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
if (!floor && !cut) {
|
|
2131
|
+
const row = reader.page(sessionID, { limit: 1 }).rows[0];
|
|
2132
|
+
if (row)
|
|
2133
|
+
floor = floorFor(row, "start");
|
|
2134
|
+
}
|
|
2135
|
+
return floor ? { ...existing, floor, controls: existing?.controls ?? [], blocked: existing?.blocked } : undefined;
|
|
2136
|
+
}
|
|
2137
|
+
async readV3(sessionID) {
|
|
2138
|
+
const saved = await this.admissions?.get(this.admissionKey(sessionID));
|
|
2139
|
+
if (typeof saved?.payload !== "string" || saved.digest !== foldDigest(saved.payload))
|
|
2140
|
+
return;
|
|
2141
|
+
try {
|
|
2142
|
+
const value = JSON.parse(saved.payload);
|
|
2143
|
+
return validAdmissionV3(value) && value.proof.sessionID === sessionID ? value : undefined;
|
|
2144
|
+
} catch {
|
|
2145
|
+
return;
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
async readCapturedReplay(sessionID, reader) {
|
|
2149
|
+
const saved = await this.admissions?.get(capturedReplayKey(sessionID));
|
|
2150
|
+
if (typeof saved?.payload !== "string" || saved.digest !== foldDigest(saved.payload))
|
|
2151
|
+
return;
|
|
2152
|
+
try {
|
|
2153
|
+
const value = JSON.parse(saved.payload);
|
|
2154
|
+
return validCapturedReplayV3(value) && value.sessionID === sessionID && value.sourceDigest === foldDigest(reader.hostIdentity()) && value.through <= reader.latestSequence(sessionID) && validFloor(reader, sessionID, value.replay.floor) && value.replay.controls.every((control) => !control.after || reader.sequenceForId(sessionID, control.after) !== undefined) ? value.replay : undefined;
|
|
2155
|
+
} catch {
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
async saveCapturedReplay(sessionID, replay, reader) {
|
|
2160
|
+
const value = {
|
|
2161
|
+
version: 3,
|
|
2162
|
+
sessionID,
|
|
2163
|
+
sourceDigest: foldDigest(reader.hostIdentity()),
|
|
2164
|
+
through: reader.latestSequence(sessionID),
|
|
2165
|
+
replay
|
|
2166
|
+
};
|
|
2167
|
+
if (!validCapturedReplayV3(value))
|
|
2168
|
+
throw new Error("Unsupported captured native replay metadata");
|
|
2169
|
+
const payload = JSON.stringify(value);
|
|
2170
|
+
try {
|
|
2171
|
+
await this.admissions?.set(capturedReplayKey(sessionID), {
|
|
2172
|
+
payload,
|
|
2173
|
+
digest: foldDigest(payload)
|
|
2174
|
+
});
|
|
2175
|
+
this.unprovenControls.delete(sessionID);
|
|
2176
|
+
} catch (error) {
|
|
2177
|
+
this.unprovenControls.add(sessionID);
|
|
2178
|
+
throw error;
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
servedBaseline(draft) {
|
|
2182
|
+
const identified = draft.messages.find((message) => message.id === HEAD_IDS[0])?.content.find((part) => part.type === "text")?.text;
|
|
2183
|
+
if (typeof identified === "string")
|
|
2184
|
+
return identified;
|
|
2185
|
+
if (this.options.protocol !== 3)
|
|
2186
|
+
return;
|
|
2187
|
+
const cached = readSessionMeta(this.storage.db, draft.sessionID).cachedM0Bytes?.toString("utf8");
|
|
2188
|
+
const checkpointID = this.tail(draft.sessionID)?.replay?.floor.kind === "host-checkpoint" ? this.tail(draft.sessionID)?.replay?.floor.id : undefined;
|
|
2189
|
+
return cached && draft.messages.some((message) => message.content.some((part) => part.type === "text" && (part.text === cached || message.id === checkpointID && typeof part.text === "string" && part.text.includes(`<summary>
|
|
2190
|
+
${cached}
|
|
2191
|
+
</summary>`)))) ? cached : undefined;
|
|
2192
|
+
}
|
|
2193
|
+
async retainReplay(sessionID, replay, model, sourceSeq) {
|
|
2194
|
+
const tail = this.tail(sessionID) ?? { model, sourceSeq };
|
|
2195
|
+
await this.storage.saveTail(sessionID, JSON.stringify({ ...tail, replay }), []);
|
|
2196
|
+
if (!this.storage.tail(sessionID))
|
|
2197
|
+
await this.storage.saveTail(sessionID, JSON.stringify({ model, sourceSeq, replay }), []);
|
|
2198
|
+
}
|
|
2199
|
+
async canFold(sessionID, reader) {
|
|
2200
|
+
if (this.options.protocol !== 3) {
|
|
2201
|
+
const future = await this.admissions?.get(`native-fold/v3/${encodeURIComponent(sessionID)}`);
|
|
2202
|
+
if (future) {
|
|
2203
|
+
this.report(sessionID, "refused: unsupported admission version");
|
|
2204
|
+
return false;
|
|
2205
|
+
}
|
|
2206
|
+
return true;
|
|
2207
|
+
}
|
|
2208
|
+
if (await this.admissions?.get(admissionKey(sessionID)) && !await this.readV3(sessionID)) {
|
|
2209
|
+
this.report(sessionID, "fold refused: V2 upgrade has not completed a rebuilding pass");
|
|
2210
|
+
return false;
|
|
2211
|
+
}
|
|
2212
|
+
if (this.unprovenControls.has(sessionID)) {
|
|
2213
|
+
this.report(sessionID, "fold refused: capture controls have not been persisted");
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
const replay = await this.floorState(sessionID, reader, undefined, undefined, true);
|
|
2217
|
+
if (!replay || replay.blocked) {
|
|
2218
|
+
this.report(sessionID, "refused: no usable host replay boundary; waiting for a permitted rebuild");
|
|
2219
|
+
return false;
|
|
2220
|
+
}
|
|
2221
|
+
return true;
|
|
2222
|
+
}
|
|
2223
|
+
async restorationFloor(sessionID, _cut, reader) {
|
|
2224
|
+
if (this.options.protocol !== 3)
|
|
2225
|
+
return;
|
|
2226
|
+
const replay = await this.floorState(sessionID, reader);
|
|
2227
|
+
if (replay)
|
|
2228
|
+
return replay.floor.after;
|
|
2229
|
+
const current = await this.admissions?.get(this.admissionKey(sessionID));
|
|
2230
|
+
const legacy = await this.admissions?.get(admissionKey(sessionID));
|
|
2231
|
+
if (current || legacy?.payload) {
|
|
2232
|
+
this.report(sessionID, "replay refused: no usable host checkpoint boundary");
|
|
2233
|
+
throw new NativeReplayUnavailable("Host checkpoint replay boundary is unavailable");
|
|
2234
|
+
}
|
|
2235
|
+
return;
|
|
2236
|
+
}
|
|
2237
|
+
async prepareLegacyUpgrade(args) {
|
|
2238
|
+
const { draft, cut, reader } = args;
|
|
2239
|
+
const admissions = this.admissions;
|
|
2240
|
+
if (this.options.protocol !== 3 || !admissions || !isLocalCheckpoint(cut))
|
|
2241
|
+
return false;
|
|
2242
|
+
if (await this.readV3(draft.sessionID))
|
|
2243
|
+
return false;
|
|
2244
|
+
this.legacyUpgrades.delete(draft.sessionID);
|
|
2245
|
+
const started = performance.now();
|
|
2246
|
+
const receipt = await this.admissions?.get(admissionKey(draft.sessionID));
|
|
2247
|
+
if (!receipt?.payload || receipt.digest !== foldDigest(receipt.payload))
|
|
2248
|
+
return false;
|
|
2249
|
+
let legacy;
|
|
2250
|
+
try {
|
|
2251
|
+
legacy = JSON.parse(receipt.payload);
|
|
2252
|
+
} catch {
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2255
|
+
if (legacy.sourceDigest !== foldDigest(reader.hostIdentity()) || legacy.sessionID !== draft.sessionID || legacy.admissionID !== cut.id || legacy.summaryDigest !== foldDigest(cut.data.summary ?? "") || !/^[a-f0-9]{64}$/.test(legacy.historyDigest))
|
|
2256
|
+
return false;
|
|
2257
|
+
const rows = reader.range(draft.sessionID, -1, cut.seq - 1).filter(conversational);
|
|
2258
|
+
if (foldDigest(JSON.stringify(rows)) !== legacy.historyDigest)
|
|
2259
|
+
return false;
|
|
2260
|
+
let floor;
|
|
2261
|
+
if (!floor) {
|
|
2262
|
+
const candidate = await this.floorState(draft.sessionID, reader);
|
|
2263
|
+
const cached = readSessionMeta(this.storage.db, draft.sessionID).cachedM0Bytes?.toString("utf8");
|
|
2264
|
+
if (candidate && (candidate.floor.kind === "checkpoint" || candidate.floor.kind === "summary" && cached === cut.data.summary))
|
|
2265
|
+
floor = candidate.floor;
|
|
2266
|
+
}
|
|
2267
|
+
const mode = floor ? "bounded" : "source-repair";
|
|
2268
|
+
floor ??= rows[0] ? floorFor(rows[0], "start") : floorFor(cut, "checkpoint");
|
|
2269
|
+
let controls = [];
|
|
2270
|
+
let blocked = false;
|
|
2271
|
+
try {
|
|
2272
|
+
controls = captureControls(draft, nativeRowID, new Set(draft.messages.flatMap((message) => nativeRowID(message) ?? [])));
|
|
2273
|
+
} catch (error) {
|
|
2274
|
+
if (!(error instanceof ControlMetadataUnavailable))
|
|
2275
|
+
throw error;
|
|
2276
|
+
blocked = true;
|
|
2277
|
+
}
|
|
2278
|
+
const replay = {
|
|
2279
|
+
floor,
|
|
2280
|
+
controls,
|
|
2281
|
+
...blocked ? { blocked } : {},
|
|
2282
|
+
upgrade: { admissionID: cut.id, mode }
|
|
2283
|
+
};
|
|
2284
|
+
const value = {
|
|
2285
|
+
version: 3,
|
|
2286
|
+
replay,
|
|
2287
|
+
proof: {
|
|
2288
|
+
sourceDigest: legacy.sourceDigest,
|
|
2289
|
+
sessionID: draft.sessionID,
|
|
2290
|
+
admissionID: cut.id,
|
|
2291
|
+
summaryDigest: legacy.summaryDigest,
|
|
2292
|
+
historyDigest: foldDigest(JSON.stringify(rows.filter((row) => row.seq > floor.after)))
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
this.legacyUpgrades.set(draft.sessionID, { value, rows, started });
|
|
2296
|
+
await this.retainReplay(draft.sessionID, replay, `${draft.model.providerID}/${draft.model.id}`, cut.seq - 1);
|
|
2297
|
+
return true;
|
|
2298
|
+
}
|
|
2299
|
+
legacyUpgradeInput(sessionID, model) {
|
|
2300
|
+
const pending = this.legacyUpgrades.get(sessionID);
|
|
2301
|
+
if (!pending)
|
|
2302
|
+
return;
|
|
2303
|
+
return pending.rows.filter((row) => row.seq > pending.value.replay.floor.after).flatMap((row) => {
|
|
2304
|
+
const messages = this.rendered(structuredClone(row), model);
|
|
2305
|
+
for (const message of messages)
|
|
2306
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
2307
|
+
return messages;
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
async commitLegacyUpgrade(sessionID, prefixMutationPermitted) {
|
|
2311
|
+
if (!prefixMutationPermitted)
|
|
2312
|
+
return false;
|
|
2313
|
+
const pending = this.legacyUpgrades.get(sessionID);
|
|
2314
|
+
const admissions = this.admissions;
|
|
2315
|
+
if (!pending || !admissions)
|
|
2316
|
+
return false;
|
|
2317
|
+
const replay = this.tail(sessionID)?.replay ?? pending.value.replay;
|
|
2318
|
+
if (replay.blocked)
|
|
2319
|
+
return false;
|
|
2320
|
+
const value = {
|
|
2321
|
+
...pending.value,
|
|
2322
|
+
replay,
|
|
2323
|
+
proof: {
|
|
2324
|
+
...pending.value.proof,
|
|
2325
|
+
historyDigest: foldDigest(JSON.stringify(pending.rows.filter((row) => row.seq > replay.floor.after)))
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
const payload = encodeAdmissionV3(value);
|
|
2329
|
+
await admissions.set(this.admissionKey(sessionID), {
|
|
2330
|
+
payload,
|
|
2331
|
+
digest: foldDigest(payload)
|
|
2332
|
+
});
|
|
2333
|
+
this.legacyUpgrades.delete(sessionID);
|
|
2334
|
+
this.report(sessionID, `V2 upgrade-state HARD mode=${replay.upgrade?.mode} rows_read=${pending.rows.length} duration_ms=${Math.round(performance.now() - pending.started)} floor=${replay.floor.id}:${replay.floor.after}`);
|
|
2335
|
+
return true;
|
|
2336
|
+
}
|
|
2337
|
+
cancelLegacyUpgrade(sessionID) {
|
|
2338
|
+
this.legacyUpgrades.delete(sessionID);
|
|
2339
|
+
}
|
|
2340
|
+
async checkpointForReplay(sessionID, reader) {
|
|
2341
|
+
if (this.options.protocol !== 3)
|
|
2342
|
+
return;
|
|
2343
|
+
const replay = await this.floorState(sessionID, reader);
|
|
2344
|
+
if (replay?.floor.kind !== "host-checkpoint")
|
|
2345
|
+
return;
|
|
2346
|
+
const row = reader.range(sessionID, replay.floor.seq - 1, replay.floor.seq).find((row) => row.id === replay.floor.id && row.type === "compaction");
|
|
2347
|
+
if (!row || !isLocalCheckpoint(row))
|
|
2348
|
+
return;
|
|
2349
|
+
const rendered = hostCheckpointCarrier(row);
|
|
2350
|
+
if (replay.withoutRecentContext)
|
|
2351
|
+
stripCheckpointRecentContext(rendered, row.data.summary ?? "");
|
|
2352
|
+
return { row, rendered, submitted: row.data.summary ?? "" };
|
|
2353
|
+
}
|
|
2354
|
+
async checkpointCovered(sessionID, checkpointID) {
|
|
2355
|
+
const admissions = this.admissions;
|
|
2356
|
+
if (!admissions)
|
|
2357
|
+
return;
|
|
2358
|
+
const pending = this.legacyUpgrades.get(sessionID);
|
|
2359
|
+
const value = await this.readV3(sessionID) ?? pending?.value;
|
|
2360
|
+
if (value?.replay.floor.kind !== "host-checkpoint" || value.replay.floor.id !== checkpointID || value.replay.withoutRecentContext)
|
|
2361
|
+
return;
|
|
2362
|
+
value.replay.withoutRecentContext = true;
|
|
2363
|
+
const payload = encodeAdmissionV3(value);
|
|
2364
|
+
if (!pending)
|
|
2365
|
+
await admissions.set(this.admissionKey(sessionID), {
|
|
2366
|
+
payload,
|
|
2367
|
+
digest: foldDigest(payload)
|
|
2368
|
+
});
|
|
2369
|
+
const tail = this.tail(sessionID);
|
|
2370
|
+
if (tail)
|
|
2371
|
+
await this.retainReplay(sessionID, value.replay, tail.model, tail.sourceSeq);
|
|
1958
2372
|
}
|
|
1959
2373
|
async removeAdmission(key) {
|
|
1960
2374
|
if (this.admissions?.remove)
|
|
@@ -1967,6 +2381,46 @@ class NativeFoldReplay {
|
|
|
1967
2381
|
await forgetNativeFoldProvenance(this.admissions, sessionID, true);
|
|
1968
2382
|
}
|
|
1969
2383
|
async admits(sessionID, cut, reader) {
|
|
2384
|
+
if (this.options.protocol === 3) {
|
|
2385
|
+
const saved = await this.readV3(sessionID);
|
|
2386
|
+
if (!saved || !isLocalCheckpoint(cut) || cut.session_id !== sessionID)
|
|
2387
|
+
return false;
|
|
2388
|
+
const proof = saved.proof;
|
|
2389
|
+
if (proof.sourceDigest !== foldDigest(reader.hostIdentity()) || proof.admissionID !== cut.id || proof.summaryDigest !== foldDigest(cut.data.summary ?? "")) {
|
|
2390
|
+
this.report(sessionID, "replay refused: invalid checkpoint floor or provenance");
|
|
2391
|
+
return false;
|
|
2392
|
+
}
|
|
2393
|
+
let replay = saved.replay;
|
|
2394
|
+
if (!validFloor(reader, sessionID, replay.floor)) {
|
|
2395
|
+
const floor = replay.floor;
|
|
2396
|
+
const anchor = floor?.kind === "start" && Number.isSafeInteger(floor.seq) && floor.after === floor.seq - 1 ? reader.range(sessionID, floor.seq - 1, floor.seq).find((row) => row.id === floor.id && row.session_id === sessionID && conversational(row)) : undefined;
|
|
2397
|
+
if (!anchor) {
|
|
2398
|
+
this.report(sessionID, "replay refused: invalid checkpoint floor or provenance");
|
|
2399
|
+
return false;
|
|
2400
|
+
}
|
|
2401
|
+
replay = { ...replay, floor: floorFor(anchor, "start") };
|
|
2402
|
+
this.editedAdmissions.set(sessionID, { original: saved, replay });
|
|
2403
|
+
this.staleHeads.add(sessionID);
|
|
2404
|
+
this.invalidate(sessionID);
|
|
2405
|
+
await this.retainReplay(sessionID, replay, this.tail(sessionID)?.model ?? "", cut.seq - 1);
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2408
|
+
await this.retainReplay(sessionID, saved.replay, this.tail(sessionID)?.model ?? "", cut.seq - 1);
|
|
2409
|
+
if (proof.historyDigest !== historyDigest(reader, sessionID, cut.seq - 1, saved.replay.floor.after)) {
|
|
2410
|
+
this.staleHeads.add(sessionID);
|
|
2411
|
+
this.invalidate(sessionID);
|
|
2412
|
+
this.editedAdmissions.set(sessionID, { original: saved, replay });
|
|
2413
|
+
await this.retainReplay(sessionID, saved.replay, this.tail(sessionID)?.model ?? "", cut.seq - 1);
|
|
2414
|
+
return false;
|
|
2415
|
+
}
|
|
2416
|
+
await this.storage.supply(sessionID, cut.id, JSON.stringify({
|
|
2417
|
+
source: this.storage.sourceID,
|
|
2418
|
+
sessionID,
|
|
2419
|
+
admissionID: cut.id,
|
|
2420
|
+
summary: cut.data.summary
|
|
2421
|
+
}));
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
1970
2424
|
if (!isLocalCheckpoint(cut) || cut.session_id !== sessionID)
|
|
1971
2425
|
return false;
|
|
1972
2426
|
if (isAdmittedLocalCheckpoint(this.storage, sessionID, cut))
|
|
@@ -1998,6 +2452,122 @@ class NativeFoldReplay {
|
|
|
1998
2452
|
return false;
|
|
1999
2453
|
}
|
|
2000
2454
|
}
|
|
2455
|
+
async commitEditedAdmission(sessionID) {
|
|
2456
|
+
const pending = this.editedAdmissions.get(sessionID);
|
|
2457
|
+
const admissions = this.admissions;
|
|
2458
|
+
if (!pending || !admissions)
|
|
2459
|
+
return false;
|
|
2460
|
+
const current = await this.readV3(sessionID);
|
|
2461
|
+
if (JSON.stringify(current) !== JSON.stringify(pending.original))
|
|
2462
|
+
return false;
|
|
2463
|
+
const reader = this.openReader(sessionID);
|
|
2464
|
+
try {
|
|
2465
|
+
const cut = reader.latestCompaction(sessionID);
|
|
2466
|
+
const proof = pending.original.proof;
|
|
2467
|
+
const replay = this.tail(sessionID)?.replay ?? pending.replay;
|
|
2468
|
+
if (!cut || cut.id !== proof.admissionID || !isLocalCheckpoint(cut) || proof.sourceDigest !== foldDigest(reader.hostIdentity()) || proof.summaryDigest !== foldDigest(cut.data.summary ?? "") || !validFloor(reader, sessionID, replay.floor))
|
|
2469
|
+
return false;
|
|
2470
|
+
const value = {
|
|
2471
|
+
...pending.original,
|
|
2472
|
+
replay: {
|
|
2473
|
+
...replay,
|
|
2474
|
+
controls: controlsThrough(replay.controls, reader, sessionID, cut.seq - 1)
|
|
2475
|
+
},
|
|
2476
|
+
proof: {
|
|
2477
|
+
...proof,
|
|
2478
|
+
historyDigest: historyDigest(reader, sessionID, cut.seq - 1, replay.floor.after)
|
|
2479
|
+
}
|
|
2480
|
+
};
|
|
2481
|
+
const payload = encodeAdmissionV3(value);
|
|
2482
|
+
await admissions.set(this.admissionKey(sessionID), {
|
|
2483
|
+
payload,
|
|
2484
|
+
digest: foldDigest(payload)
|
|
2485
|
+
});
|
|
2486
|
+
this.editedAdmissions.delete(sessionID);
|
|
2487
|
+
return true;
|
|
2488
|
+
} finally {
|
|
2489
|
+
reader.close();
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
cancelEditedAdmission(sessionID) {
|
|
2493
|
+
this.editedAdmissions.delete(sessionID);
|
|
2494
|
+
}
|
|
2495
|
+
async replayAdmission(sessionID, cut, reader) {
|
|
2496
|
+
if (this.options.protocol === 3) {
|
|
2497
|
+
const saved = await this.readV3(sessionID);
|
|
2498
|
+
if (!saved)
|
|
2499
|
+
return "legacy";
|
|
2500
|
+
if (saved.proof.admissionID !== cut.id)
|
|
2501
|
+
return "legacy";
|
|
2502
|
+
return saved.proof.sourceDigest === foldDigest(reader.hostIdentity()) && saved.proof.summaryDigest === foldDigest(cut.data.summary ?? "") && validFloor(reader, sessionID, saved.replay.floor) && saved.proof.historyDigest === historyDigest(reader, sessionID, cut.seq - 1, saved.replay.floor.after) ? "native" : undefined;
|
|
2503
|
+
}
|
|
2504
|
+
if (!isLocalCheckpoint(cut) || cut.session_id !== sessionID)
|
|
2505
|
+
return;
|
|
2506
|
+
try {
|
|
2507
|
+
const source = reader.hostIdentity();
|
|
2508
|
+
const observed = this.sources.get(sessionID);
|
|
2509
|
+
if (observed && observed !== source)
|
|
2510
|
+
return;
|
|
2511
|
+
if (observed === source && isAdmittedLocalCheckpoint(this.storage, sessionID, cut))
|
|
2512
|
+
return "native";
|
|
2513
|
+
const saved = await this.admissions?.get(this.admissionKey(sessionID));
|
|
2514
|
+
if (!saved)
|
|
2515
|
+
return "legacy";
|
|
2516
|
+
if (!saved.payload || saved.digest !== foldDigest(saved.payload))
|
|
2517
|
+
return;
|
|
2518
|
+
const snapshot = JSON.parse(saved.payload);
|
|
2519
|
+
if (snapshot.admissionID !== cut.id)
|
|
2520
|
+
return "legacy";
|
|
2521
|
+
if (snapshot.sourceDigest !== foldDigest(source) || snapshot.sessionID !== sessionID || snapshot.summaryDigest !== foldDigest(cut.data.summary ?? "") || snapshot.historyDigest !== historyDigest(reader, sessionID, cut.seq - 1))
|
|
2522
|
+
return;
|
|
2523
|
+
return "native";
|
|
2524
|
+
} catch {
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
replayInput(args, replayOverride) {
|
|
2529
|
+
const { sessionID, cut, model, reader } = args;
|
|
2530
|
+
if (!isLocalCheckpoint(cut) || cut.session_id !== sessionID)
|
|
2531
|
+
return;
|
|
2532
|
+
let after = -1;
|
|
2533
|
+
const retired = instructionRetirement(replayOverride ?? this.tail(sessionID)?.replay);
|
|
2534
|
+
if (this.options.protocol === 3) {
|
|
2535
|
+
const replay = replayOverride ?? this.tail(sessionID)?.replay;
|
|
2536
|
+
if (!replay || !validFloor(reader, sessionID, replay.floor))
|
|
2537
|
+
return;
|
|
2538
|
+
after = replay.floor.after;
|
|
2539
|
+
} else if (args.bounded && !this.changed.has(sessionID)) {
|
|
2540
|
+
const state = readSessionMeta(this.storage.db, sessionID);
|
|
2541
|
+
const max = this.storage.db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM m0_mutation_log WHERE session_id=?").get(sessionID);
|
|
2542
|
+
const boundary = this.storage.db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(sessionID)?.id;
|
|
2543
|
+
if (max.id <= (state.cachedM0MaxMutationId ?? 0) && boundary)
|
|
2544
|
+
after = reader.sequenceForId(sessionID, boundary) ?? -1;
|
|
2545
|
+
}
|
|
2546
|
+
const through = cut.seq - 1;
|
|
2547
|
+
const metadata = (this.metadataThrough.get(sessionID) ?? -1) >= through ? this.metadata.get(sessionID) : undefined;
|
|
2548
|
+
const required = (metadata ?? reader.rowStampsThrough(sessionID, through, this.options.protocol === 3 ? after : undefined)).filter(conversational).filter((row) => !retired(row)).filter((row) => row.seq > after && row.seq <= through);
|
|
2549
|
+
const tail = this.tail(sessionID);
|
|
2550
|
+
let records;
|
|
2551
|
+
if (!this.dirty.has(sessionID) && tail?.model === `${model.providerID}/${model.id}` && this.storage.containsRows(sessionID, required.map((row) => row.id))) {
|
|
2552
|
+
records = this.storage.rows(sessionID, after, through);
|
|
2553
|
+
} else {
|
|
2554
|
+
records = reader.range(sessionID, after, through).filter(conversational).map((row) => this.record(row, this.rendered(row, model)));
|
|
2555
|
+
const restored = new Set(records.map((row) => row.id));
|
|
2556
|
+
if (required.some((row) => !restored.has(row.id)))
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
const projected = records.filter((row) => !retired(row)).flatMap((row) => {
|
|
2560
|
+
const messages = reviveNative(JSON.parse(row.data));
|
|
2561
|
+
for (const message of messages)
|
|
2562
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
2563
|
+
return messages;
|
|
2564
|
+
});
|
|
2565
|
+
return this.options.protocol === 3 ? insertControls(projected, controlsThrough((replayOverride ?? this.tail(sessionID)?.replay)?.controls ?? [], reader, sessionID, through), nativeRowID) : projected;
|
|
2566
|
+
}
|
|
2567
|
+
async projectReplay(args) {
|
|
2568
|
+
const replay = this.options.protocol === 3 ? await this.floorState(args.sessionID, args.reader) : undefined;
|
|
2569
|
+
return this.replayInput(args, replay);
|
|
2570
|
+
}
|
|
2001
2571
|
rendered(row, model) {
|
|
2002
2572
|
return restoreRow(row, model, hostUsesMediaAssets() ? {
|
|
2003
2573
|
asset: hostMediaAsset,
|
|
@@ -2008,15 +2578,31 @@ class NativeFoldReplay {
|
|
|
2008
2578
|
const data = JSON.stringify(encodeNative(messages));
|
|
2009
2579
|
return { id: row.id, type: row.type, seq: row.seq, data, digest: foldDigest(data) };
|
|
2010
2580
|
}
|
|
2011
|
-
records(sessionID, native, reader) {
|
|
2012
|
-
let metadata = this.metadata.get(sessionID);
|
|
2581
|
+
records(sessionID, native, reader, after) {
|
|
2013
2582
|
const through = reader.latestSequence(sessionID);
|
|
2583
|
+
const retained = this.stampMRU;
|
|
2584
|
+
let metadata = this.metadata.get(sessionID);
|
|
2585
|
+
if (!metadata && retained?.sessionID === sessionID && retained.source === reader.hostIdentity() && retained.after === after && retained.through === through) {
|
|
2586
|
+
metadata = retained.rows;
|
|
2587
|
+
this.metadata.set(sessionID, metadata);
|
|
2588
|
+
this.metadataThrough.set(sessionID, through);
|
|
2589
|
+
this.metadataAfter.set(sessionID, after);
|
|
2590
|
+
}
|
|
2014
2591
|
const known = new Set(metadata?.map((row) => row.id));
|
|
2015
|
-
if (!metadata || (this.metadataThrough.get(sessionID) ?? -1) < through || native.some((message) => message.id && !known.has(message.id))) {
|
|
2016
|
-
metadata = reader.rowStampsThrough(sessionID, through).filter(conversational);
|
|
2592
|
+
if (!metadata || this.metadataAfter.get(sessionID) !== after || (this.metadataThrough.get(sessionID) ?? -1) < through || native.some((message) => message.id && !known.has(message.id))) {
|
|
2593
|
+
metadata = reader.rowStampsThrough(sessionID, through, after).filter(conversational);
|
|
2017
2594
|
this.metadata.set(sessionID, metadata);
|
|
2018
2595
|
this.metadataThrough.set(sessionID, through);
|
|
2596
|
+
this.metadataAfter.set(sessionID, after);
|
|
2019
2597
|
}
|
|
2598
|
+
if (this.options.protocol === 3)
|
|
2599
|
+
this.stampMRU = {
|
|
2600
|
+
sessionID,
|
|
2601
|
+
source: reader.hostIdentity(),
|
|
2602
|
+
through,
|
|
2603
|
+
after,
|
|
2604
|
+
rows: metadata
|
|
2605
|
+
};
|
|
2020
2606
|
const byID = new Map(metadata.map((row) => [row.id, row]));
|
|
2021
2607
|
const grouped = new Map;
|
|
2022
2608
|
const anchorIndex = native.findIndex((message) => {
|
|
@@ -2033,6 +2619,14 @@ class NativeFoldReplay {
|
|
|
2033
2619
|
let owner;
|
|
2034
2620
|
for (const message of native) {
|
|
2035
2621
|
let id = nativeRowID(message);
|
|
2622
|
+
if (this.options.protocol === 3 && !id && message.role === "system") {
|
|
2623
|
+
const text = message.content.filter((part) => part.type === "text").map((part) => part.text).join(`
|
|
2624
|
+
`);
|
|
2625
|
+
const source = metadata.filter((row) => row.type === "system" && row.seq > cursor).find((row) => reader.range(sessionID, row.seq - 1, row.seq).some((stored) => stored.id === row.id && stored.data.text === text));
|
|
2626
|
+
id = source?.id;
|
|
2627
|
+
if (!id)
|
|
2628
|
+
continue;
|
|
2629
|
+
}
|
|
2036
2630
|
if (!id && message.role === "system") {
|
|
2037
2631
|
if (leadingIDs.has(message)) {
|
|
2038
2632
|
id = leadingIDs.get(message);
|
|
@@ -2047,7 +2641,7 @@ class NativeFoldReplay {
|
|
|
2047
2641
|
if (!row)
|
|
2048
2642
|
throw new NativeReplayUnavailable("Native carrier has no source row coordinate");
|
|
2049
2643
|
cursor = row.seq;
|
|
2050
|
-
|
|
2644
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
2051
2645
|
if (message.role !== "tool")
|
|
2052
2646
|
owner = row.id;
|
|
2053
2647
|
const messages = grouped.get(row) ?? [];
|
|
@@ -2056,15 +2650,65 @@ class NativeFoldReplay {
|
|
|
2056
2650
|
}
|
|
2057
2651
|
return [...grouped].map(([row, messages]) => this.record(row, messages));
|
|
2058
2652
|
}
|
|
2059
|
-
async capture(draft, native) {
|
|
2653
|
+
async capture(draft, native, boundary) {
|
|
2060
2654
|
const release = this.storage.hold(draft.sessionID);
|
|
2655
|
+
let replay;
|
|
2656
|
+
let sourceSeq = -1;
|
|
2061
2657
|
try {
|
|
2062
2658
|
rememberHostMedia(native);
|
|
2063
2659
|
const reader = this.openReader(draft.sessionID);
|
|
2064
2660
|
try {
|
|
2065
|
-
|
|
2066
|
-
|
|
2661
|
+
let captured = native;
|
|
2662
|
+
if (this.options.protocol === 3) {
|
|
2663
|
+
replay = await this.floorState(draft.sessionID, reader, boundary, draft);
|
|
2664
|
+
if (!replay)
|
|
2665
|
+
throw new NativeReplayUnavailable("No usable host replay boundary");
|
|
2666
|
+
replay = { ...replay, blocked: false };
|
|
2667
|
+
const replayAfter = replay.floor.after;
|
|
2668
|
+
const replayStart = replay.floor.kind === "start";
|
|
2669
|
+
const baseline = this.servedBaseline(draft);
|
|
2670
|
+
captured = native.filter((message) => {
|
|
2671
|
+
if (effortPart(message))
|
|
2672
|
+
return false;
|
|
2673
|
+
const id = nativeRowID(message);
|
|
2674
|
+
if (HEAD_IDS.some((head) => head === id))
|
|
2675
|
+
return false;
|
|
2676
|
+
if (!id)
|
|
2677
|
+
return !(baseline && message.role === "user" && message.content.some((part) => part.type === "text" && part.text === baseline));
|
|
2678
|
+
if (replayStart)
|
|
2679
|
+
return true;
|
|
2680
|
+
const seq = reader.sequenceForId(draft.sessionID, id);
|
|
2681
|
+
return seq === undefined || seq > replayAfter;
|
|
2682
|
+
});
|
|
2683
|
+
}
|
|
2684
|
+
let rows = this.records(draft.sessionID, captured, reader, replay?.floor.after);
|
|
2685
|
+
if (replay) {
|
|
2686
|
+
const identities = new Map;
|
|
2687
|
+
for (const row of rows.filter((row) => row.type === "system")) {
|
|
2688
|
+
for (const message of reviveNative(JSON.parse(row.data))) {
|
|
2689
|
+
const key = JSON.stringify(message.content);
|
|
2690
|
+
const found = identities.get(key) ?? [];
|
|
2691
|
+
found.push(row.id);
|
|
2692
|
+
identities.set(key, found);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
const ids = new Set(rows.map((row) => row.id));
|
|
2696
|
+
replay = {
|
|
2697
|
+
...replay,
|
|
2698
|
+
blocked: false,
|
|
2699
|
+
controls: captureControls(draft, (message) => nativeRowID(message) ?? (message.role === "system" ? identities.get(JSON.stringify(message.content))?.shift() : undefined), ids)
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
const baseline = this.servedBaseline(draft);
|
|
2067
2703
|
const through = Math.max(-1, ...rows.map((row) => row.seq));
|
|
2704
|
+
sourceSeq = through;
|
|
2705
|
+
if (boundary && baseline === boundary.summary) {
|
|
2706
|
+
const after = reader.sequenceForId(draft.sessionID, boundary.id);
|
|
2707
|
+
if (after !== undefined) {
|
|
2708
|
+
rows = rows.filter((row) => row.seq > after);
|
|
2709
|
+
this.storage.replaceRows(draft.sessionID, through, rows);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2068
2712
|
const tail = {
|
|
2069
2713
|
model: `${draft.model.providerID}/${draft.model.id}`,
|
|
2070
2714
|
sourceSeq: through,
|
|
@@ -2079,13 +2723,48 @@ class NativeFoldReplay {
|
|
|
2079
2723
|
} finally {
|
|
2080
2724
|
reader.close();
|
|
2081
2725
|
}
|
|
2082
|
-
} catch {
|
|
2726
|
+
} catch (error) {
|
|
2083
2727
|
this.unavailable.add(draft.sessionID);
|
|
2084
2728
|
this.invalidate(draft.sessionID);
|
|
2729
|
+
if (replay)
|
|
2730
|
+
replay = { ...replay, blocked: true };
|
|
2731
|
+
if (this.options.protocol === 3)
|
|
2732
|
+
this.report(draft.sessionID, `capture unavailable: ${String(error)}`);
|
|
2085
2733
|
} finally {
|
|
2086
2734
|
this.account(draft.sessionID);
|
|
2087
2735
|
release();
|
|
2088
2736
|
}
|
|
2737
|
+
if (replay) {
|
|
2738
|
+
await this.retainReplay(draft.sessionID, replay, `${draft.model.providerID}/${draft.model.id}`, sourceSeq);
|
|
2739
|
+
const reader = this.openReader(draft.sessionID);
|
|
2740
|
+
try {
|
|
2741
|
+
await this.saveCapturedReplay(draft.sessionID, replay, reader);
|
|
2742
|
+
const saved = await this.readV3(draft.sessionID);
|
|
2743
|
+
const cut = reader.latestCompaction(draft.sessionID);
|
|
2744
|
+
if (saved && !this.editedAdmissions.has(draft.sessionID) && cut?.id === saved.proof.admissionID && replay.floor.after > saved.replay.floor.after && boundary && this.servedBaseline(draft) === boundary.summary) {
|
|
2745
|
+
const value = {
|
|
2746
|
+
...saved,
|
|
2747
|
+
replay: {
|
|
2748
|
+
...replay,
|
|
2749
|
+
controls: controlsThrough(replay.controls, reader, draft.sessionID, cut.seq - 1)
|
|
2750
|
+
},
|
|
2751
|
+
proof: {
|
|
2752
|
+
...saved.proof,
|
|
2753
|
+
historyDigest: historyDigest(reader, draft.sessionID, cut.seq - 1, replay.floor.after)
|
|
2754
|
+
}
|
|
2755
|
+
};
|
|
2756
|
+
const payload = encodeAdmissionV3(value);
|
|
2757
|
+
await this.admissions?.set(this.admissionKey(draft.sessionID), {
|
|
2758
|
+
payload,
|
|
2759
|
+
digest: foldDigest(payload)
|
|
2760
|
+
});
|
|
2761
|
+
}
|
|
2762
|
+
} catch (error) {
|
|
2763
|
+
this.report(draft.sessionID, `capture provenance update unavailable: ${String(error)}`);
|
|
2764
|
+
} finally {
|
|
2765
|
+
reader.close();
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2089
2768
|
}
|
|
2090
2769
|
async canReplay(sessionID, _reader) {
|
|
2091
2770
|
return !this.unavailable.has(sessionID) && typeof await this.baseline(sessionID) === "string";
|
|
@@ -2101,20 +2780,115 @@ class NativeFoldReplay {
|
|
|
2101
2780
|
}
|
|
2102
2781
|
async supplyHeld(args) {
|
|
2103
2782
|
const { draft, reader, summary } = args;
|
|
2783
|
+
if (this.options.protocol === 3) {
|
|
2784
|
+
if (this.unprovenControls.has(draft.sessionID))
|
|
2785
|
+
return false;
|
|
2786
|
+
if (await this.admissions?.get(admissionKey(draft.sessionID)) && !await this.readV3(draft.sessionID))
|
|
2787
|
+
return false;
|
|
2788
|
+
const running = reader.latestRunningCompaction(draft.sessionID);
|
|
2789
|
+
const replay = args.manual?.replay ?? await this.floorState(draft.sessionID, reader, undefined, undefined, true);
|
|
2790
|
+
if (!running || !replay || replay.blocked) {
|
|
2791
|
+
this.report(draft.sessionID, "fold refused: no usable host checkpoint boundary");
|
|
2792
|
+
return false;
|
|
2793
|
+
}
|
|
2794
|
+
const model = `${draft.model.providerID}/${draft.model.id}`;
|
|
2795
|
+
if (!args.manual && this.tail(draft.sessionID)?.model !== model)
|
|
2796
|
+
this.storage.replaceRows(draft.sessionID, reader.latestSequence(draft.sessionID), []);
|
|
2797
|
+
if (!args.manual)
|
|
2798
|
+
await this.retainReplay(draft.sessionID, replay, model, reader.latestSequence(draft.sessionID));
|
|
2799
|
+
if (!args.manual)
|
|
2800
|
+
await this.storage.supply(draft.sessionID, running.id, JSON.stringify({
|
|
2801
|
+
source: this.storage.sourceID,
|
|
2802
|
+
sessionID: draft.sessionID,
|
|
2803
|
+
admissionID: running.id,
|
|
2804
|
+
summary
|
|
2805
|
+
}));
|
|
2806
|
+
const value = {
|
|
2807
|
+
version: 3,
|
|
2808
|
+
replay,
|
|
2809
|
+
proof: {
|
|
2810
|
+
sourceDigest: foldDigest(reader.hostIdentity()),
|
|
2811
|
+
sessionID: draft.sessionID,
|
|
2812
|
+
admissionID: running.id,
|
|
2813
|
+
summaryDigest: foldDigest(summary),
|
|
2814
|
+
historyDigest: historyDigest(reader, draft.sessionID, running.seq - 1, replay.floor.after)
|
|
2815
|
+
}
|
|
2816
|
+
};
|
|
2817
|
+
const payload = encodeAdmissionV3(value);
|
|
2818
|
+
if (args.manual) {
|
|
2819
|
+
const keys = [
|
|
2820
|
+
capturedReplayKey(draft.sessionID),
|
|
2821
|
+
this.admissionKey(draft.sessionID)
|
|
2822
|
+
];
|
|
2823
|
+
const old = await Promise.all(keys.map((key) => this.admissions?.get(key)));
|
|
2824
|
+
const capture = {
|
|
2825
|
+
version: 3,
|
|
2826
|
+
sessionID: draft.sessionID,
|
|
2827
|
+
sourceDigest: foldDigest(reader.hostIdentity()),
|
|
2828
|
+
through: reader.latestSequence(draft.sessionID),
|
|
2829
|
+
replay
|
|
2830
|
+
};
|
|
2831
|
+
const capturedPayload = JSON.stringify(capture);
|
|
2832
|
+
let written = 0;
|
|
2833
|
+
try {
|
|
2834
|
+
for (const [index, key] of keys.entries()) {
|
|
2835
|
+
const data = index === 0 ? capturedPayload : payload;
|
|
2836
|
+
await this.admissions?.set(key, {
|
|
2837
|
+
payload: data,
|
|
2838
|
+
digest: foldDigest(data)
|
|
2839
|
+
});
|
|
2840
|
+
written++;
|
|
2841
|
+
}
|
|
2842
|
+
args.manual.commit();
|
|
2843
|
+
} catch (error) {
|
|
2844
|
+
for (let index = written - 1;index >= 0; index--) {
|
|
2845
|
+
const key = keys[index];
|
|
2846
|
+
if (!key)
|
|
2847
|
+
continue;
|
|
2848
|
+
if (old[index] !== undefined)
|
|
2849
|
+
await this.admissions?.set(key, old[index]);
|
|
2850
|
+
else if (this.admissions?.remove)
|
|
2851
|
+
await this.admissions.remove(key);
|
|
2852
|
+
else
|
|
2853
|
+
await this.admissions?.set(key, null);
|
|
2854
|
+
}
|
|
2855
|
+
throw error;
|
|
2856
|
+
}
|
|
2857
|
+
this.invalidate(draft.sessionID);
|
|
2858
|
+
this.cancelLegacyUpgrade(draft.sessionID);
|
|
2859
|
+
this.cancelEditedAdmission(draft.sessionID);
|
|
2860
|
+
await this.retainReplay(draft.sessionID, replay, model, running.seq - 1);
|
|
2861
|
+
await this.storage.supply(draft.sessionID, running.id, JSON.stringify({
|
|
2862
|
+
source: this.storage.sourceID,
|
|
2863
|
+
sessionID: draft.sessionID,
|
|
2864
|
+
admissionID: running.id,
|
|
2865
|
+
summary
|
|
2866
|
+
}));
|
|
2867
|
+
return true;
|
|
2868
|
+
}
|
|
2869
|
+
await this.admissions?.set(this.admissionKey(draft.sessionID), {
|
|
2870
|
+
payload,
|
|
2871
|
+
digest: foldDigest(payload)
|
|
2872
|
+
});
|
|
2873
|
+
return true;
|
|
2874
|
+
}
|
|
2104
2875
|
const tail = this.tail(draft.sessionID);
|
|
2105
2876
|
const running = reader.latestRunningCompaction(draft.sessionID);
|
|
2106
2877
|
const id = running?.id;
|
|
2107
|
-
|
|
2878
|
+
const model = `${draft.model.providerID}/${draft.model.id}`;
|
|
2879
|
+
if (!id || tail && tail.model !== model)
|
|
2108
2880
|
return false;
|
|
2109
2881
|
const through = reader.latestSequence(draft.sessionID);
|
|
2110
|
-
const after = this.dirty.has(draft.sessionID) ? -1 : tail
|
|
2111
|
-
const fresh = reader.range(draft.sessionID, after, through).filter(conversational);
|
|
2882
|
+
const after = this.dirty.has(draft.sessionID) ? -1 : tail?.sourceSeq ?? through;
|
|
2883
|
+
const fresh = tail ? reader.range(draft.sessionID, after, through).filter(conversational) : [];
|
|
2112
2884
|
const records = fresh.map((row) => this.record(row, this.rendered(row, draft.model)));
|
|
2113
2885
|
if (this.dirty.has(draft.sessionID))
|
|
2114
2886
|
this.storage.replaceRows(draft.sessionID, through, records);
|
|
2115
2887
|
await this.storage.saveTail(draft.sessionID, JSON.stringify({
|
|
2116
2888
|
...tail,
|
|
2117
|
-
|
|
2889
|
+
model,
|
|
2890
|
+
baseline: tail?.baseline ?? summary,
|
|
2891
|
+
sourceSeq: Math.max(tail?.sourceSeq ?? through, ...fresh.map((row) => row.seq))
|
|
2118
2892
|
}), records);
|
|
2119
2893
|
this.dirty.delete(draft.sessionID);
|
|
2120
2894
|
this.metadata.delete(draft.sessionID);
|
|
@@ -2145,13 +2919,42 @@ class NativeFoldReplay {
|
|
|
2145
2919
|
return true;
|
|
2146
2920
|
}
|
|
2147
2921
|
async restore(sessionID, cut, model, options = {}) {
|
|
2922
|
+
let replay;
|
|
2923
|
+
let controls = [];
|
|
2924
|
+
if (this.options.protocol === 3) {
|
|
2925
|
+
const reader = this.openReader(sessionID);
|
|
2926
|
+
try {
|
|
2927
|
+
replay = await this.floorState(sessionID, reader);
|
|
2928
|
+
if (replay)
|
|
2929
|
+
controls = controlsThrough(replay.controls, reader, sessionID, cut.seq - 1);
|
|
2930
|
+
} finally {
|
|
2931
|
+
reader.close();
|
|
2932
|
+
}
|
|
2933
|
+
if (!replay) {
|
|
2934
|
+
this.report(sessionID, "replay refused: missing usable checkpoint boundary");
|
|
2935
|
+
throw new NativeReplayUnavailable("Host checkpoint replay boundary is unavailable");
|
|
2936
|
+
}
|
|
2937
|
+
options = {
|
|
2938
|
+
...options,
|
|
2939
|
+
bounded: false,
|
|
2940
|
+
after: replay.floor.after,
|
|
2941
|
+
retiredInstructionThrough: replay.retiredInstructionThrough,
|
|
2942
|
+
retiredInstructionIDs: replay.retiredInstructionIDs
|
|
2943
|
+
};
|
|
2944
|
+
}
|
|
2148
2945
|
const release = this.storage.hold(sessionID);
|
|
2946
|
+
let result;
|
|
2149
2947
|
try {
|
|
2150
|
-
|
|
2948
|
+
result = await this.restoreHeld(sessionID, cut, model, options);
|
|
2151
2949
|
} finally {
|
|
2152
2950
|
this.account(sessionID);
|
|
2153
2951
|
release();
|
|
2154
2952
|
}
|
|
2953
|
+
if (replay) {
|
|
2954
|
+
await this.retainReplay(sessionID, replay, model, cut.seq - 1);
|
|
2955
|
+
return result && insertControls(result, controls, nativeRowID);
|
|
2956
|
+
}
|
|
2957
|
+
return result;
|
|
2155
2958
|
}
|
|
2156
2959
|
async restoreHeld(sessionID, cut, model, options) {
|
|
2157
2960
|
if (!isLocalCheckpoint(cut))
|
|
@@ -2161,23 +2964,24 @@ class NativeFoldReplay {
|
|
|
2161
2964
|
id: model.slice(model.indexOf("/") + 1)
|
|
2162
2965
|
};
|
|
2163
2966
|
const tail = this.tail(sessionID);
|
|
2164
|
-
if (tail && tail.model !== model)
|
|
2967
|
+
if (tail && tail.model !== model && !(this.options.protocol === 3 && tail.model === ""))
|
|
2165
2968
|
this.invalidate(sessionID);
|
|
2166
2969
|
let after = options.after ?? -1;
|
|
2167
|
-
if (options.bounded && options.after === undefined && !this.changed.has(sessionID)) {
|
|
2168
|
-
const state = getOrCreateSessionMeta(this.storage.db, sessionID);
|
|
2169
|
-
const max = this.storage.db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM m0_mutation_log WHERE session_id=?").get(sessionID);
|
|
2170
|
-
const boundary = this.storage.db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(sessionID)?.id;
|
|
2171
|
-
if (max.id <= (state.cachedM0MaxMutationId ?? 0) && boundary)
|
|
2172
|
-
after = this.storage.sequenceForID(sessionID, boundary) ?? -1;
|
|
2173
|
-
}
|
|
2174
|
-
const through = cut.seq - 1;
|
|
2175
2970
|
let reader;
|
|
2176
2971
|
try {
|
|
2972
|
+
if (options.bounded && options.after === undefined && !this.changed.has(sessionID)) {
|
|
2973
|
+
const state = getOrCreateSessionMeta(this.storage.db, sessionID);
|
|
2974
|
+
const max = this.storage.db.prepare("SELECT COALESCE(MAX(id),0) AS id FROM m0_mutation_log WHERE session_id=?").get(sessionID);
|
|
2975
|
+
const boundary = this.storage.db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(sessionID)?.id;
|
|
2976
|
+
if (max.id <= (state.cachedM0MaxMutationId ?? 0) && boundary) {
|
|
2977
|
+
after = this.storage.sequenceForID(sessionID, boundary) ?? (reader = this.openReader(sessionID)).sequenceForId(sessionID, boundary) ?? -1;
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
const through = cut.seq - 1;
|
|
2177
2981
|
let metadata = this.metadata.get(sessionID);
|
|
2178
2982
|
if (!metadata || (this.metadataThrough.get(sessionID) ?? -1) < through) {
|
|
2179
|
-
reader
|
|
2180
|
-
metadata = reader.rowStampsThrough(sessionID, through).filter(conversational);
|
|
2983
|
+
reader ??= this.openReader(sessionID);
|
|
2984
|
+
metadata = reader.rowStampsThrough(sessionID, through, this.options.protocol === 3 ? after : undefined).filter(conversational);
|
|
2181
2985
|
this.metadata.set(sessionID, metadata);
|
|
2182
2986
|
this.metadataThrough.set(sessionID, through);
|
|
2183
2987
|
}
|
|
@@ -2202,10 +3006,13 @@ class NativeFoldReplay {
|
|
|
2202
3006
|
reader?.close();
|
|
2203
3007
|
}
|
|
2204
3008
|
const messages = [];
|
|
3009
|
+
const retired = instructionRetirement(options);
|
|
2205
3010
|
for (const row of this.storage.rows(sessionID, after, cut.seq - 1)) {
|
|
3011
|
+
if (retired(row))
|
|
3012
|
+
continue;
|
|
2206
3013
|
const revived = reviveNative(JSON.parse(row.data));
|
|
2207
3014
|
for (const message of revived)
|
|
2208
|
-
|
|
3015
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
2209
3016
|
messages.push(...revived);
|
|
2210
3017
|
}
|
|
2211
3018
|
return messages;
|
|
@@ -2213,26 +3020,35 @@ class NativeFoldReplay {
|
|
|
2213
3020
|
async restoreRead(sessionID, cut, model) {
|
|
2214
3021
|
const reader = this.openReader(sessionID);
|
|
2215
3022
|
try {
|
|
2216
|
-
|
|
3023
|
+
const replay = this.options.protocol === 3 ? await this.floorState(sessionID, reader) : undefined;
|
|
3024
|
+
if (this.options.protocol === 3 && !replay) {
|
|
3025
|
+
this.report(sessionID, "replay refused: missing usable checkpoint boundary");
|
|
3026
|
+
throw new NativeReplayUnavailable("Host checkpoint replay boundary is unavailable");
|
|
3027
|
+
}
|
|
3028
|
+
const retired = instructionRetirement(replay);
|
|
3029
|
+
const messages = reader.range(sessionID, replay?.floor.after ?? -1, cut.seq - 1).filter(conversational).filter((row) => !retired(row)).flatMap((row) => {
|
|
2217
3030
|
const messages = this.rendered(row, model);
|
|
2218
3031
|
for (const message of messages)
|
|
2219
|
-
|
|
3032
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
2220
3033
|
return messages;
|
|
2221
3034
|
});
|
|
3035
|
+
return replay ? insertControls(messages, controlsThrough(replay.controls, reader, sessionID, cut.seq - 1), nativeRowID) : messages;
|
|
2222
3036
|
} finally {
|
|
2223
3037
|
reader.close();
|
|
2224
3038
|
}
|
|
2225
3039
|
}
|
|
2226
3040
|
sourceChanged(sessionID) {
|
|
2227
|
-
return this.changed.has(sessionID);
|
|
3041
|
+
return this.changed.has(sessionID) || this.editedAdmissions.has(sessionID);
|
|
2228
3042
|
}
|
|
2229
3043
|
needsHeadRebuild(sessionID) {
|
|
2230
|
-
return this.staleHeads.has(sessionID);
|
|
3044
|
+
return this.staleHeads.has(sessionID) || this.editedAdmissions.has(sessionID);
|
|
2231
3045
|
}
|
|
2232
3046
|
clear(sessionID) {
|
|
2233
3047
|
this.sources.delete(sessionID);
|
|
2234
3048
|
this.metadata.delete(sessionID);
|
|
2235
3049
|
this.metadataThrough.delete(sessionID);
|
|
3050
|
+
this.metadataAfter.delete(sessionID);
|
|
3051
|
+
this.metadataAfter.delete(sessionID);
|
|
2236
3052
|
this.loaded.delete(sessionID);
|
|
2237
3053
|
this.unavailable.delete(sessionID);
|
|
2238
3054
|
this.dirty.delete(sessionID);
|
|
@@ -2240,6 +3056,11 @@ class NativeFoldReplay {
|
|
|
2240
3056
|
this.staleHeads.delete(sessionID);
|
|
2241
3057
|
}
|
|
2242
3058
|
async forget(sessionID) {
|
|
3059
|
+
if (this.stampMRU?.sessionID === sessionID)
|
|
3060
|
+
this.stampMRU = undefined;
|
|
3061
|
+
this.unprovenControls.delete(sessionID);
|
|
3062
|
+
this.cancelLegacyUpgrade(sessionID);
|
|
3063
|
+
this.cancelEditedAdmission(sessionID);
|
|
2243
3064
|
if (this.admissions)
|
|
2244
3065
|
await forgetNativeFoldProvenance(this.admissions, sessionID);
|
|
2245
3066
|
await this.storage.forget(sessionID);
|
|
@@ -2258,9 +3079,9 @@ class HostFoldPolicy {
|
|
|
2258
3079
|
owned(sessionID, cut, id) {
|
|
2259
3080
|
return cut.id === id && isAdmittedLocalCheckpoint(this.deps.storage, sessionID, cut);
|
|
2260
3081
|
}
|
|
2261
|
-
async idle(sessionID) {
|
|
3082
|
+
async idle(sessionID, eligible = () => true) {
|
|
2262
3083
|
const { storage, session, threshold } = this.deps;
|
|
2263
|
-
if (!Number.isSafeInteger(threshold) || threshold <= 0 || typeof session.compact !== "function" || this.active.has(sessionID))
|
|
3084
|
+
if (!Number.isSafeInteger(threshold) || threshold <= 0 || typeof session.compact !== "function" || !eligible() || this.active.has(sessionID))
|
|
2264
3085
|
return;
|
|
2265
3086
|
this.active.add(sessionID);
|
|
2266
3087
|
const now = this.deps.now ?? Date.now;
|
|
@@ -2279,8 +3100,11 @@ class HostFoldPolicy {
|
|
|
2279
3100
|
}
|
|
2280
3101
|
const after = cut?.seq ?? -1;
|
|
2281
3102
|
const before = reader.storedRowsAfter(sessionID, after);
|
|
2282
|
-
if (before < threshold
|
|
3103
|
+
if (before < threshold)
|
|
2283
3104
|
return;
|
|
3105
|
+
if (this.deps.canFold && !await this.deps.canFold(sessionID, reader))
|
|
3106
|
+
return;
|
|
3107
|
+
const capture = await this.deps.canReplay(sessionID, reader);
|
|
2284
3108
|
const retry = old?.after === after ? old.attempt + (previous?.status === "failed" || previous?.status === "coalesced" ? 1 : 0) : 0;
|
|
2285
3109
|
const id = old?.after === after && previous?.status === "pending" ? old.id : `msg_mc_fold_${foldDigest(`${storage.sourceID}/${sessionID}/${after}/${retry}`).slice(0, 24)}`;
|
|
2286
3110
|
attempt = {
|
|
@@ -2289,7 +3113,8 @@ class HostFoldPolicy {
|
|
|
2289
3113
|
watermark: reader.latestSequence(sessionID),
|
|
2290
3114
|
attempt: retry,
|
|
2291
3115
|
id,
|
|
2292
|
-
started: now()
|
|
3116
|
+
started: now(),
|
|
3117
|
+
capture
|
|
2293
3118
|
};
|
|
2294
3119
|
claimed = await storage.claim(sessionID, id, JSON.stringify(attempt), this.owner, now());
|
|
2295
3120
|
if (!claimed)
|
|
@@ -2297,6 +3122,10 @@ class HostFoldPolicy {
|
|
|
2297
3122
|
} finally {
|
|
2298
3123
|
reader.close();
|
|
2299
3124
|
}
|
|
3125
|
+
if (!eligible()) {
|
|
3126
|
+
await storage.finish(sessionID, attempt.id, this.owner, "coalesced", now());
|
|
3127
|
+
return;
|
|
3128
|
+
}
|
|
2300
3129
|
const admitted = await session.compact({
|
|
2301
3130
|
sessionID,
|
|
2302
3131
|
id: attempt.id,
|
|
@@ -2313,7 +3142,7 @@ class HostFoldPolicy {
|
|
|
2313
3142
|
}
|
|
2314
3143
|
const after = settled.storedRowsAfter(sessionID, cut.seq);
|
|
2315
3144
|
if (await storage.finish(sessionID, attempt.id, this.owner, "completed", now()))
|
|
2316
|
-
this.deps.log(sessionID, `v2 host fold: rows_before=${attempt.before} rows_after=${after} duration_ms=${now() - attempt.started} reason=row_threshold id=${cut.id} status=completed`);
|
|
3145
|
+
this.deps.log(sessionID, `v2 host fold: rows_before=${attempt.before} rows_after=${after} duration_ms=${now() - attempt.started} reason=row_threshold id=${cut.id} capture=${attempt.capture ? "present" : "absent"} status=completed`);
|
|
2317
3146
|
} finally {
|
|
2318
3147
|
settled.close();
|
|
2319
3148
|
}
|
|
@@ -2335,8 +3164,14 @@ class HostFoldPolicy {
|
|
|
2335
3164
|
}
|
|
2336
3165
|
}
|
|
2337
3166
|
|
|
3167
|
+
// src/v2/fold/summary.ts
|
|
3168
|
+
var RAW_HISTORY_ACCOUNT = "Magic Context retains the conversation as raw messages; no summarized history is available yet.";
|
|
3169
|
+
function hasFoldSummary(summary) {
|
|
3170
|
+
return typeof summary === "string" && summary.replace(/<[^>]*>/g, "").trim().length > 0;
|
|
3171
|
+
}
|
|
3172
|
+
|
|
2338
3173
|
// src/v2/fork-inheritance.ts
|
|
2339
|
-
var RAW_TYPES = new Set(
|
|
3174
|
+
var RAW_TYPES = new Set(RAW_MESSAGE_TYPES2);
|
|
2340
3175
|
function forkBoundarySeq(origin, sequenceForId) {
|
|
2341
3176
|
const seq = sequenceForId(origin.parentSessionID, origin.boundary.messageID);
|
|
2342
3177
|
if (seq === undefined)
|
|
@@ -3224,6 +4059,26 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
3224
4059
|
const budgetStopped = new Promise((_resolve, reject) => {
|
|
3225
4060
|
budgetReject = reject;
|
|
3226
4061
|
});
|
|
4062
|
+
const chargeBudgetRows = (rows) => {
|
|
4063
|
+
if (!budget)
|
|
4064
|
+
return;
|
|
4065
|
+
for (const row of rows) {
|
|
4066
|
+
if (row.seq <= usageSeq)
|
|
4067
|
+
continue;
|
|
4068
|
+
if (!row.data.finish)
|
|
4069
|
+
break;
|
|
4070
|
+
usageSeq = row.seq;
|
|
4071
|
+
const tokens = row.data.tokens;
|
|
4072
|
+
const decision = budget.charge(Math.max(0, tokens?.input ?? 0), Math.max(0, tokens?.cache?.read ?? 0), Math.max(0, tokens?.cache?.write ?? 0), row.data.finish === "stop" && !(row.data.content ?? []).some((part) => part.type === "tool-call"), false);
|
|
4073
|
+
const onBudgetUpdate = run.identity.metadata?.onBudgetUpdate;
|
|
4074
|
+
if (typeof onBudgetUpdate === "function")
|
|
4075
|
+
onBudgetUpdate({ ...budget.snapshot(), sessionId: run.child.id });
|
|
4076
|
+
if (decision !== "continue") {
|
|
4077
|
+
attempt.budgetExceeded = new DreamTokenBudgetExceeded(run.child.id, budget.snapshot().spent);
|
|
4078
|
+
return attempt.budgetExceeded;
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
};
|
|
3227
4082
|
if (budget) {
|
|
3228
4083
|
budgetPoll = inRootAsyncContext2(() => setInterval(() => {
|
|
3229
4084
|
try {
|
|
@@ -3231,25 +4086,12 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
3231
4086
|
const latest = reader.latestAssistant(run.child.id);
|
|
3232
4087
|
return latest ? [latest] : [];
|
|
3233
4088
|
})());
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
const onBudgetUpdate = run.identity.metadata?.onBudgetUpdate;
|
|
3241
|
-
if (typeof onBudgetUpdate === "function")
|
|
3242
|
-
onBudgetUpdate({
|
|
3243
|
-
...budget.snapshot(),
|
|
3244
|
-
sessionId: run.child.id
|
|
3245
|
-
});
|
|
3246
|
-
if (decision !== "continue") {
|
|
3247
|
-
if (budgetPoll)
|
|
3248
|
-
clearInterval(budgetPoll);
|
|
3249
|
-
attempt.budgetExceeded = new DreamTokenBudgetExceeded(run.child.id, budget.snapshot().spent);
|
|
3250
|
-
interruptAndRetire(run, "token-budget").finally(() => budgetReject(attempt.budgetExceeded));
|
|
3251
|
-
return;
|
|
3252
|
-
}
|
|
4089
|
+
const exceeded = chargeBudgetRows(fresh);
|
|
4090
|
+
if (exceeded) {
|
|
4091
|
+
if (budgetPoll)
|
|
4092
|
+
clearInterval(budgetPoll);
|
|
4093
|
+
interruptAndRetire(run, "token-budget").finally(() => budgetReject(exceeded));
|
|
4094
|
+
return;
|
|
3253
4095
|
}
|
|
3254
4096
|
} catch (error) {
|
|
3255
4097
|
if (budgetPoll)
|
|
@@ -3346,6 +4188,11 @@ async function createV2HiddenCompletionExecutor(host, options) {
|
|
|
3346
4188
|
const tokens = row.data.tokens;
|
|
3347
4189
|
const tokenNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
3348
4190
|
const steps = withReader(options.openReader, (reader) => reader.assistantSince?.(run.child.id, baseline) ?? [row]).filter((step) => step.seq > baseline && step.seq <= row.seq);
|
|
4191
|
+
const exceeded = chargeBudgetRows(steps);
|
|
4192
|
+
if (exceeded) {
|
|
4193
|
+
await interruptAndRetire(run, "token-budget");
|
|
4194
|
+
throw exceeded;
|
|
4195
|
+
}
|
|
3349
4196
|
const reportedUsage = steps.some((step) => tokenNumber(step.data.tokens?.input) !== undefined || tokenNumber(step.data.tokens?.output) !== undefined);
|
|
3350
4197
|
const usage = sumRowUsage(steps);
|
|
3351
4198
|
if (request.signal?.aborted || run.retired || Date.now() >= deadline) {
|
|
@@ -3565,6 +4412,100 @@ class V2MessageTimesCache {
|
|
|
3565
4412
|
|
|
3566
4413
|
// src/v2/hooks/channel2.ts
|
|
3567
4414
|
import { randomBytes } from "node:crypto";
|
|
4415
|
+
|
|
4416
|
+
// src/v2/hooks/synthetic-admission.ts
|
|
4417
|
+
var memos = new WeakMap;
|
|
4418
|
+
var MAX_SESSIONS = 64;
|
|
4419
|
+
var MAX_IDS = 50000;
|
|
4420
|
+
function admissionSession(key) {
|
|
4421
|
+
if (!key.startsWith("synthetic/"))
|
|
4422
|
+
return;
|
|
4423
|
+
const end = key.indexOf("/", "synthetic/".length);
|
|
4424
|
+
return end < 0 ? undefined : key.slice("synthetic/".length, end);
|
|
4425
|
+
}
|
|
4426
|
+
function memoFor(storage) {
|
|
4427
|
+
const prior = memos.get(storage);
|
|
4428
|
+
if (prior)
|
|
4429
|
+
return prior;
|
|
4430
|
+
const sessions = new Map;
|
|
4431
|
+
const set = storage.set;
|
|
4432
|
+
const remove = storage.remove;
|
|
4433
|
+
const invalidate = (key) => {
|
|
4434
|
+
const sessionID = admissionSession(key);
|
|
4435
|
+
if (sessionID !== undefined) {
|
|
4436
|
+
sessions.delete(sessionID);
|
|
4437
|
+
const current = memos.get(storage);
|
|
4438
|
+
if (current) {
|
|
4439
|
+
current.sessions.delete(sessionID);
|
|
4440
|
+
current.revision++;
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
};
|
|
4444
|
+
const wrappedSet = async (key, value) => {
|
|
4445
|
+
invalidate(key);
|
|
4446
|
+
try {
|
|
4447
|
+
await set.call(storage, key, value);
|
|
4448
|
+
} finally {
|
|
4449
|
+
invalidate(key);
|
|
4450
|
+
}
|
|
4451
|
+
};
|
|
4452
|
+
const wrappedRemove = remove && (async (key) => {
|
|
4453
|
+
invalidate(key);
|
|
4454
|
+
try {
|
|
4455
|
+
await remove.call(storage, key);
|
|
4456
|
+
} finally {
|
|
4457
|
+
invalidate(key);
|
|
4458
|
+
}
|
|
4459
|
+
});
|
|
4460
|
+
const memo = { sessions, revision: 0, set, remove, wrappedSet, wrappedRemove };
|
|
4461
|
+
storage.set = wrappedSet;
|
|
4462
|
+
if (wrappedRemove)
|
|
4463
|
+
storage.remove = wrappedRemove;
|
|
4464
|
+
memos.set(storage, memo);
|
|
4465
|
+
return memo;
|
|
4466
|
+
}
|
|
4467
|
+
function forgetSyntheticAdmission(storage, sessionID) {
|
|
4468
|
+
const memo = memoFor(storage);
|
|
4469
|
+
memo.sessions.delete(sessionID);
|
|
4470
|
+
memo.revision++;
|
|
4471
|
+
}
|
|
4472
|
+
function clearSyntheticAdmissions(storage) {
|
|
4473
|
+
const memo = memos.get(storage);
|
|
4474
|
+
if (!memo)
|
|
4475
|
+
return;
|
|
4476
|
+
memo.sessions.clear();
|
|
4477
|
+
if (storage.set === memo.wrappedSet)
|
|
4478
|
+
storage.set = memo.set;
|
|
4479
|
+
if (storage.remove === memo.wrappedRemove)
|
|
4480
|
+
storage.remove = memo.remove;
|
|
4481
|
+
memos.delete(storage);
|
|
4482
|
+
}
|
|
4483
|
+
async function admittedSynthetic(storage, sessionID, id) {
|
|
4484
|
+
for (;; ) {
|
|
4485
|
+
const memo = memoFor(storage);
|
|
4486
|
+
const session = memo.sessions.get(sessionID) ?? new Map;
|
|
4487
|
+
memo.sessions.delete(sessionID);
|
|
4488
|
+
memo.sessions.set(sessionID, session);
|
|
4489
|
+
if (memo.sessions.size > MAX_SESSIONS)
|
|
4490
|
+
memo.sessions.delete(memo.sessions.keys().next().value);
|
|
4491
|
+
const known = session.get(id);
|
|
4492
|
+
if (known !== undefined)
|
|
4493
|
+
return known;
|
|
4494
|
+
const revision = memo.revision;
|
|
4495
|
+
const record = await storage.get(`synthetic/${sessionID}/${id}`);
|
|
4496
|
+
if (memos.get(storage) !== memo || memo.revision !== revision)
|
|
4497
|
+
continue;
|
|
4498
|
+
const admitted = record !== null && typeof record === "object" && "id" in record && record.id === id;
|
|
4499
|
+
if (memo.sessions.get(sessionID) !== session)
|
|
4500
|
+
return admitted;
|
|
4501
|
+
if (session.size >= MAX_IDS)
|
|
4502
|
+
session.delete(session.keys().next().value);
|
|
4503
|
+
session.set(id, admitted);
|
|
4504
|
+
return admitted;
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4508
|
+
// src/v2/hooks/channel2.ts
|
|
3568
4509
|
var pendingCandidates = new WeakMap;
|
|
3569
4510
|
function syntheticCandidates(context, sessionID, stored) {
|
|
3570
4511
|
const pending = pendingCandidates.get(context.storage);
|
|
@@ -3580,9 +4521,17 @@ function syntheticCandidates(context, sessionID, stored) {
|
|
|
3580
4521
|
}
|
|
3581
4522
|
function clearSyntheticCandidates(context) {
|
|
3582
4523
|
pendingCandidates.delete(context.storage);
|
|
4524
|
+
clearSyntheticAdmissions(context.storage);
|
|
4525
|
+
}
|
|
4526
|
+
function observeSyntheticAdmissionEvent(context, event) {
|
|
4527
|
+
const sessionID = event.data?.sessionID;
|
|
4528
|
+
if (!sessionID || !(event.type === "session.deleted" || event.type?.startsWith("session.revert.")))
|
|
4529
|
+
return;
|
|
4530
|
+
forgetSyntheticAdmission(context.storage, sessionID);
|
|
3583
4531
|
}
|
|
3584
4532
|
async function deliverSynthetic(context, sessionID, text) {
|
|
3585
4533
|
const id = `msg_${randomBytes(12).toString("hex")}`;
|
|
4534
|
+
forgetSyntheticAdmission(context.storage, sessionID);
|
|
3586
4535
|
await context.storage.set(`synthetic/${sessionID}/${id}`, { id });
|
|
3587
4536
|
let candidates = pendingCandidates.get(context.storage);
|
|
3588
4537
|
if (!candidates) {
|
|
@@ -3594,8 +4543,7 @@ async function deliverSynthetic(context, sessionID, text) {
|
|
|
3594
4543
|
return id;
|
|
3595
4544
|
}
|
|
3596
4545
|
async function isAdmittedSynthetic(context, sessionID, id) {
|
|
3597
|
-
|
|
3598
|
-
return record !== null && typeof record === "object" && "id" in record && record.id === id;
|
|
4546
|
+
return admittedSynthetic(context.storage, sessionID, id);
|
|
3599
4547
|
}
|
|
3600
4548
|
async function deliverPendingChannel2(context, db, sessionID, baseline) {
|
|
3601
4549
|
if (getChannel2NudgeState(db, sessionID) !== "pending")
|
|
@@ -3801,7 +4749,7 @@ class V2RetrospectiveRawProvider {
|
|
|
3801
4749
|
contextDb;
|
|
3802
4750
|
openReader;
|
|
3803
4751
|
reader;
|
|
3804
|
-
constructor(contextDb, openReader = () => new
|
|
4752
|
+
constructor(contextDb, openReader = () => new V2StoreReader2(gaDatabasePath2(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"))) {
|
|
3805
4753
|
this.contextDb = contextDb;
|
|
3806
4754
|
this.openReader = openReader;
|
|
3807
4755
|
}
|
|
@@ -4002,7 +4950,7 @@ function startDreamTrigger(context, args) {
|
|
|
4002
4950
|
if (!db)
|
|
4003
4951
|
continue;
|
|
4004
4952
|
try {
|
|
4005
|
-
const reader = args.openReader?.() ?? new
|
|
4953
|
+
const reader = args.openReader?.() ?? new V2StoreReader2(gaDatabasePath2(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
4006
4954
|
try {
|
|
4007
4955
|
const activity = reader.rootSessionActivity([event.data.sessionID]).get(event.data.sessionID);
|
|
4008
4956
|
if (activity !== undefined)
|
|
@@ -4206,7 +5154,7 @@ function hiddenTerminalError(event) {
|
|
|
4206
5154
|
|
|
4207
5155
|
// src/v2/hooks/lkg-system.ts
|
|
4208
5156
|
import { createHash as createHash2 } from "node:crypto";
|
|
4209
|
-
function
|
|
5157
|
+
function identity2(slot) {
|
|
4210
5158
|
return createHash2("sha256").update(JSON.stringify({
|
|
4211
5159
|
capturedAt: slot.capturedAt,
|
|
4212
5160
|
captureSequence: slot.captureSequence,
|
|
@@ -4222,7 +5170,7 @@ class V2LkgSystemReplay {
|
|
|
4222
5170
|
systems = new BoundedSessionMap(1000);
|
|
4223
5171
|
capture(sessionId, slot, input, served, head) {
|
|
4224
5172
|
this.systems.set(sessionId, {
|
|
4225
|
-
slot:
|
|
5173
|
+
slot: identity2(slot),
|
|
4226
5174
|
input: hostInputKey(input),
|
|
4227
5175
|
served: structuredClone(served),
|
|
4228
5176
|
head: head ? structuredClone(head) : null
|
|
@@ -4230,7 +5178,7 @@ class V2LkgSystemReplay {
|
|
|
4230
5178
|
}
|
|
4231
5179
|
restore(sessionId, slot, input, target) {
|
|
4232
5180
|
const saved = this.systems.get(sessionId);
|
|
4233
|
-
if (!slot || !saved || saved.slot !==
|
|
5181
|
+
if (!slot || !saved || saved.slot !== identity2(slot) || saved.input !== hostInputKey(input))
|
|
4234
5182
|
return;
|
|
4235
5183
|
target.splice(0, target.length, ...structuredClone(saved.served));
|
|
4236
5184
|
return { head: saved.head ? structuredClone(saved.head) : null };
|
|
@@ -4278,11 +5226,117 @@ async function warmModelLimitCacheFromCatalog(context, options = {}) {
|
|
|
4278
5226
|
retries: options.retries ?? 3,
|
|
4279
5227
|
retryDelayMs: options.retryDelayMs ?? 1000
|
|
4280
5228
|
});
|
|
4281
|
-
} catch (error) {
|
|
4282
|
-
sessionLog2("global", `v2 model-limit cache warm failed: ${getErrorMessage(error)}`);
|
|
4283
|
-
} finally {
|
|
4284
|
-
if (!modelLimitCacheWarm())
|
|
4285
|
-
warmStarted = false;
|
|
5229
|
+
} catch (error) {
|
|
5230
|
+
sessionLog2("global", `v2 model-limit cache warm failed: ${getErrorMessage(error)}`);
|
|
5231
|
+
} finally {
|
|
5232
|
+
if (!modelLimitCacheWarm())
|
|
5233
|
+
warmStarted = false;
|
|
5234
|
+
}
|
|
5235
|
+
}
|
|
5236
|
+
|
|
5237
|
+
// src/v2/hooks/overflow-recovery.ts
|
|
5238
|
+
function isRateLimit(error) {
|
|
5239
|
+
const pending = [error];
|
|
5240
|
+
const seen = new Set;
|
|
5241
|
+
for (let i = 0;pending.length && i < 16; i++) {
|
|
5242
|
+
const value = pending.shift();
|
|
5243
|
+
if (seen.has(value))
|
|
5244
|
+
continue;
|
|
5245
|
+
seen.add(value);
|
|
5246
|
+
if (typeof value === "string") {
|
|
5247
|
+
try {
|
|
5248
|
+
pending.push(JSON.parse(value));
|
|
5249
|
+
} catch {}
|
|
5250
|
+
} else if (value && typeof value === "object") {
|
|
5251
|
+
const p = value;
|
|
5252
|
+
if (p.status === 429 || p.statusCode === 429 || [p.type, p.name, p.code, p._tag].some((tag) => typeof tag === "string" && /rate[_ .-]?limit|throttl/i.test(tag)))
|
|
5253
|
+
return true;
|
|
5254
|
+
pending.push(p.data, p.error, p.cause);
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5257
|
+
return false;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
class V2OverflowRecovery {
|
|
5261
|
+
deps;
|
|
5262
|
+
requests = new BoundedSessionMap(1000);
|
|
5263
|
+
constructor(deps) {
|
|
5264
|
+
this.deps = deps;
|
|
5265
|
+
}
|
|
5266
|
+
begin(input) {
|
|
5267
|
+
if (input.kind !== "primary" || this.deps.isHidden(input.sessionID))
|
|
5268
|
+
return;
|
|
5269
|
+
const prior = this.requests.get(input.sessionID);
|
|
5270
|
+
if (input.assistantMessageID && prior?.assistantMessageID === input.assistantMessageID && prior.model.providerID === input.model.providerID && prior.model.id === input.model.id)
|
|
5271
|
+
return;
|
|
5272
|
+
this.requests.set(input.sessionID, {
|
|
5273
|
+
model: { ...input.model },
|
|
5274
|
+
assistantMessageID: input.assistantMessageID,
|
|
5275
|
+
observed: false
|
|
5276
|
+
});
|
|
5277
|
+
}
|
|
5278
|
+
forget(sessionID) {
|
|
5279
|
+
this.requests.delete(sessionID);
|
|
5280
|
+
}
|
|
5281
|
+
observeTerminal(event, readStep) {
|
|
5282
|
+
if (!["session.step.failed", "session.execution.failed", "session.error"].includes(event.type ?? ""))
|
|
5283
|
+
return;
|
|
5284
|
+
const sessionID = event.data?.sessionID;
|
|
5285
|
+
if (!sessionID || this.deps.isHidden(sessionID))
|
|
5286
|
+
return;
|
|
5287
|
+
const error = event.type === "session.step.failed" ? event.data?.error : hiddenTerminalError(event);
|
|
5288
|
+
if (error === undefined)
|
|
5289
|
+
return;
|
|
5290
|
+
const prior = this.requests.get(sessionID);
|
|
5291
|
+
if (prior?.observed || isRateLimit(error) || !detectOverflow(error).isOverflow)
|
|
5292
|
+
return;
|
|
5293
|
+
const messageID = event.data?.assistantMessageID;
|
|
5294
|
+
const step = readStep(sessionID, messageID);
|
|
5295
|
+
if (!step)
|
|
5296
|
+
return;
|
|
5297
|
+
if (!messageID && (!step?.error || !detectOverflow(step.error).isOverflow))
|
|
5298
|
+
return;
|
|
5299
|
+
if (!prior && step.model)
|
|
5300
|
+
this.begin({
|
|
5301
|
+
sessionID,
|
|
5302
|
+
kind: "primary",
|
|
5303
|
+
model: step.model,
|
|
5304
|
+
assistantMessageID: step.id
|
|
5305
|
+
});
|
|
5306
|
+
const request = this.requests.get(sessionID);
|
|
5307
|
+
if (!request)
|
|
5308
|
+
return;
|
|
5309
|
+
this.observe({
|
|
5310
|
+
sessionID,
|
|
5311
|
+
error,
|
|
5312
|
+
model: step?.model ?? request.model,
|
|
5313
|
+
assistantMessageID: messageID ?? step?.id
|
|
5314
|
+
});
|
|
5315
|
+
}
|
|
5316
|
+
observe(input) {
|
|
5317
|
+
if (!this.requests.has(input.sessionID) && input.kind === "primary")
|
|
5318
|
+
this.begin({ ...input, kind: "primary" });
|
|
5319
|
+
const request = this.requests.get(input.sessionID);
|
|
5320
|
+
if (!request || request.observed || this.deps.isHidden(input.sessionID) || request.model.providerID !== input.model.providerID || request.model.id !== input.model.id || input.assistantMessageID && request.assistantMessageID && input.assistantMessageID !== request.assistantMessageID)
|
|
5321
|
+
return;
|
|
5322
|
+
if (input.status === 429 || isRateLimit(input.error))
|
|
5323
|
+
return;
|
|
5324
|
+
const detection = detectOverflow(input.error);
|
|
5325
|
+
if (!detection.isOverflow)
|
|
5326
|
+
return;
|
|
5327
|
+
const db = this.deps.database();
|
|
5328
|
+
if (!db)
|
|
5329
|
+
return;
|
|
5330
|
+
const modelKey = `${input.model.providerID}/${input.model.id}`;
|
|
5331
|
+
if (this.deps.compactionOff) {
|
|
5332
|
+
if (detection.reportedLimit)
|
|
5333
|
+
recordDetectedContextLimit(db, input.sessionID, detection.reportedLimit, modelKey, detection.reportedLimitProvenance);
|
|
5334
|
+
} else {
|
|
5335
|
+
recordOverflowDetected(db, input.sessionID, detection.reportedLimit, modelKey, "provider_overflow", detection.reportedLimitProvenance, detection.reportedInputTokens);
|
|
5336
|
+
}
|
|
5337
|
+
request.observed = true;
|
|
5338
|
+
if (!this.deps.compactionOff && detection.reportedInputTokens)
|
|
5339
|
+
this.deps.onInputTokens?.(input.sessionID, detection.reportedInputTokens, getOverflowState(db, input.sessionID, modelKey).detectedContextLimit);
|
|
4286
5340
|
}
|
|
4287
5341
|
}
|
|
4288
5342
|
|
|
@@ -4318,16 +5372,31 @@ async function interruptBeforeProvider(session, sessionID, timers = systemTimers
|
|
|
4318
5372
|
}
|
|
4319
5373
|
|
|
4320
5374
|
// src/v2/hooks/restore-rows.ts
|
|
5375
|
+
var DEFAULT_LIMITS = {
|
|
5376
|
+
maxSessions: 16,
|
|
5377
|
+
sessionRows: 40000,
|
|
5378
|
+
totalRows: 80000,
|
|
5379
|
+
sessionBytes: 192 * 1024 * 1024,
|
|
5380
|
+
totalBytes: 256 * 1024 * 1024
|
|
5381
|
+
};
|
|
5382
|
+
|
|
4321
5383
|
class RestoredRowCache {
|
|
4322
|
-
capacity;
|
|
4323
5384
|
sessions = new Map;
|
|
4324
|
-
|
|
4325
|
-
|
|
5385
|
+
limits;
|
|
5386
|
+
totalRows = 0;
|
|
5387
|
+
totalBytes = 0;
|
|
5388
|
+
constructor(limits = {}) {
|
|
5389
|
+
this.limits = {
|
|
5390
|
+
...DEFAULT_LIMITS,
|
|
5391
|
+
...typeof limits === "number" ? { maxSessions: limits } : limits
|
|
5392
|
+
};
|
|
4326
5393
|
}
|
|
4327
5394
|
rows(reader, sessionID, after, through) {
|
|
4328
|
-
if (through <= after)
|
|
5395
|
+
if (through <= after) {
|
|
5396
|
+
this.forget(sessionID);
|
|
4329
5397
|
return [];
|
|
4330
|
-
|
|
5398
|
+
}
|
|
5399
|
+
const kept = this.sessions.get(sessionID)?.rows ?? new Map;
|
|
4331
5400
|
const stamps = reader.spanRowStamps(sessionID, after, through);
|
|
4332
5401
|
const runs = [];
|
|
4333
5402
|
let previous = after;
|
|
@@ -4349,28 +5418,44 @@ class RestoredRowCache {
|
|
|
4349
5418
|
fresh.set(row.seq, row);
|
|
4350
5419
|
const next = new Map;
|
|
4351
5420
|
const rows = [];
|
|
5421
|
+
let bytes = 0;
|
|
4352
5422
|
for (const [seq, stamp] of stamps) {
|
|
4353
5423
|
const row = fresh.get(seq) ?? kept.get(seq)?.row;
|
|
4354
5424
|
if (!row)
|
|
4355
5425
|
continue;
|
|
4356
|
-
next.set(seq, { stamp, row });
|
|
4357
5426
|
rows.push(row);
|
|
5427
|
+
const rowBytes = Number(stamp.slice(stamp.lastIndexOf("\x00") + 1));
|
|
5428
|
+
if (!Number.isSafeInteger(rowBytes) || rowBytes < 0 || next.size >= Math.min(this.limits.sessionRows, this.limits.totalRows) || bytes + rowBytes > Math.min(this.limits.sessionBytes, this.limits.totalBytes))
|
|
5429
|
+
continue;
|
|
5430
|
+
next.set(seq, { stamp, row });
|
|
5431
|
+
bytes += rowBytes;
|
|
4358
5432
|
}
|
|
4359
|
-
this.
|
|
4360
|
-
|
|
4361
|
-
|
|
5433
|
+
this.forget(sessionID);
|
|
5434
|
+
if (next.size) {
|
|
5435
|
+
this.sessions.set(sessionID, { rows: next, bytes });
|
|
5436
|
+
this.totalRows += next.size;
|
|
5437
|
+
this.totalBytes += bytes;
|
|
5438
|
+
}
|
|
5439
|
+
while (this.sessions.size > this.limits.maxSessions || this.totalRows > this.limits.totalRows || this.totalBytes > this.limits.totalBytes) {
|
|
4362
5440
|
const oldest = this.sessions.keys().next().value;
|
|
4363
5441
|
if (oldest === undefined)
|
|
4364
5442
|
break;
|
|
4365
|
-
this.
|
|
5443
|
+
this.forget(oldest);
|
|
4366
5444
|
}
|
|
4367
5445
|
return structuredClone(rows);
|
|
4368
5446
|
}
|
|
4369
5447
|
forget(sessionID) {
|
|
5448
|
+
const prior = this.sessions.get(sessionID);
|
|
5449
|
+
if (prior) {
|
|
5450
|
+
this.totalRows -= prior.rows.size;
|
|
5451
|
+
this.totalBytes -= prior.bytes;
|
|
5452
|
+
}
|
|
4370
5453
|
this.sessions.delete(sessionID);
|
|
4371
5454
|
}
|
|
4372
5455
|
clear() {
|
|
4373
5456
|
this.sessions.clear();
|
|
5457
|
+
this.totalRows = 0;
|
|
5458
|
+
this.totalBytes = 0;
|
|
4374
5459
|
}
|
|
4375
5460
|
}
|
|
4376
5461
|
function readPages(reader, sessionID, after, through) {
|
|
@@ -4519,257 +5604,6 @@ async function probeV2StorageAtBoot(storage, timeoutMs = 15000) {
|
|
|
4519
5604
|
}
|
|
4520
5605
|
}
|
|
4521
5606
|
|
|
4522
|
-
// src/v2/hooks/store.ts
|
|
4523
|
-
var rawMessageTypes = new Set(RAW_MESSAGE_TYPES);
|
|
4524
|
-
var isRawRow = (row) => rawMessageTypes.has(row.type);
|
|
4525
|
-
var NO_MODEL = { providerID: "", id: "" };
|
|
4526
|
-
function hostServesRowById(row) {
|
|
4527
|
-
return isRawRow(row) && restoreRow(row, NO_MODEL).some((message) => message.id === row.id);
|
|
4528
|
-
}
|
|
4529
|
-
function projectRawMessages(rows, ordinalFor) {
|
|
4530
|
-
return rows.filter(isRawRow).map((row, index) => {
|
|
4531
|
-
const message = {
|
|
4532
|
-
id: row.id,
|
|
4533
|
-
ordinal: ordinalFor(row, index),
|
|
4534
|
-
role: row.type === "assistant" ? "assistant" : row.type === "system" ? "system" : "user",
|
|
4535
|
-
createdAt: row.time_created ?? row.data.time?.created,
|
|
4536
|
-
parts: row.type === "assistant" ? (row.data.content ?? []).map((part) => {
|
|
4537
|
-
if (part.type !== "tool")
|
|
4538
|
-
return { ...part };
|
|
4539
|
-
const state = part.state;
|
|
4540
|
-
const content = state.content;
|
|
4541
|
-
return {
|
|
4542
|
-
type: "tool",
|
|
4543
|
-
tool: part.name,
|
|
4544
|
-
callID: part.id,
|
|
4545
|
-
state: {
|
|
4546
|
-
...state,
|
|
4547
|
-
output: state.status === "error" ? toolStateContent(state) : content?.filter((p) => p.type === "text").map((p) => p.text).join(`
|
|
4548
|
-
`) ?? ""
|
|
4549
|
-
}
|
|
4550
|
-
};
|
|
4551
|
-
}) : [{ type: "text", text: row.data.text ?? "" }]
|
|
4552
|
-
};
|
|
4553
|
-
Object.defineProperty(message, "storeType", { value: row.type, enumerable: false });
|
|
4554
|
-
if (!hostServesRowById(row))
|
|
4555
|
-
markHostUnservedRow(message);
|
|
4556
|
-
return message;
|
|
4557
|
-
});
|
|
4558
|
-
}
|
|
4559
|
-
function rawMessages(rows, history = rows) {
|
|
4560
|
-
const ordinals = new Map(history.filter(isRawRow).map((row, index) => [row.id, index + 1]));
|
|
4561
|
-
return projectRawMessages(rows, (row) => {
|
|
4562
|
-
return ordinals.get(row.id) ?? 0;
|
|
4563
|
-
});
|
|
4564
|
-
}
|
|
4565
|
-
function rawMessagePage(rows, afterOrdinal) {
|
|
4566
|
-
return projectRawMessages(rows, (_row, index) => afterOrdinal + index + 1);
|
|
4567
|
-
}
|
|
4568
|
-
var SERVED_BOUNDARY_PAGE = 50;
|
|
4569
|
-
function servedBoundaryRow(reader, sessionID, messageID) {
|
|
4570
|
-
const boundary = reader.messageById(sessionID, messageID);
|
|
4571
|
-
if (!boundary)
|
|
4572
|
-
return null;
|
|
4573
|
-
if (hostServesRowById(boundary))
|
|
4574
|
-
return boundary;
|
|
4575
|
-
let through = boundary.seq - 1;
|
|
4576
|
-
for (;; ) {
|
|
4577
|
-
const rows = reader.rawRowsThrough(sessionID, through, SERVED_BOUNDARY_PAGE);
|
|
4578
|
-
const served = rows.find(hostServesRowById);
|
|
4579
|
-
if (served)
|
|
4580
|
-
return served;
|
|
4581
|
-
const oldest = rows.at(-1);
|
|
4582
|
-
if (rows.length < SERVED_BOUNDARY_PAGE || !oldest)
|
|
4583
|
-
return null;
|
|
4584
|
-
through = oldest.seq - 1;
|
|
4585
|
-
}
|
|
4586
|
-
}
|
|
4587
|
-
function resolveV2BoundaryUserMessage(reader, sessionID, endMessageID) {
|
|
4588
|
-
const end = reader.messageById(sessionID, endMessageID);
|
|
4589
|
-
if (!end || !isRawRow(end))
|
|
4590
|
-
return null;
|
|
4591
|
-
let through = end.seq;
|
|
4592
|
-
for (;; ) {
|
|
4593
|
-
const rows = reader.rawRowsThrough(sessionID, through, SERVED_BOUNDARY_PAGE);
|
|
4594
|
-
const user = rows.find((row) => row.type !== "assistant");
|
|
4595
|
-
if (user)
|
|
4596
|
-
return rawMessagePage([user], 0)[0] ?? null;
|
|
4597
|
-
const oldest = rows.at(-1);
|
|
4598
|
-
if (rows.length < SERVED_BOUNDARY_PAGE || !oldest)
|
|
4599
|
-
return null;
|
|
4600
|
-
through = oldest.seq - 1;
|
|
4601
|
-
}
|
|
4602
|
-
}
|
|
4603
|
-
function readAllV2RawMessagesForConversion(openReader, sessionID) {
|
|
4604
|
-
const reader = openReader();
|
|
4605
|
-
try {
|
|
4606
|
-
return rawMessages(reader.history(sessionID));
|
|
4607
|
-
} finally {
|
|
4608
|
-
reader.close();
|
|
4609
|
-
}
|
|
4610
|
-
}
|
|
4611
|
-
var CONVERSION_PAGE_ROWS = 1000;
|
|
4612
|
-
function* readV2RawMessagePagesForConversion(openReader, sessionID, pageRows = CONVERSION_PAGE_ROWS) {
|
|
4613
|
-
const reader = openReader();
|
|
4614
|
-
try {
|
|
4615
|
-
let after = -1;
|
|
4616
|
-
let ordinal = 0;
|
|
4617
|
-
for (;; ) {
|
|
4618
|
-
const page = reader.page(sessionID, { after, limit: pageRows });
|
|
4619
|
-
const messages = rawMessagePage(page.rows, ordinal);
|
|
4620
|
-
ordinal += messages.length;
|
|
4621
|
-
if (messages.length > 0)
|
|
4622
|
-
yield messages;
|
|
4623
|
-
if (page.rows.length < pageRows || page.cursor === undefined)
|
|
4624
|
-
return;
|
|
4625
|
-
after = page.cursor;
|
|
4626
|
-
}
|
|
4627
|
-
} finally {
|
|
4628
|
-
reader.close();
|
|
4629
|
-
}
|
|
4630
|
-
}
|
|
4631
|
-
function createV2RawMessageReader(openReader) {
|
|
4632
|
-
const servedBoundaryCache = new Map;
|
|
4633
|
-
return {
|
|
4634
|
-
getRevision: (sessionID) => {
|
|
4635
|
-
const reader = openReader();
|
|
4636
|
-
try {
|
|
4637
|
-
return reader.latestSequence(sessionID);
|
|
4638
|
-
} finally {
|
|
4639
|
-
reader.close();
|
|
4640
|
-
}
|
|
4641
|
-
},
|
|
4642
|
-
getCountAfterRevision: (sessionID, after, through) => {
|
|
4643
|
-
const reader = openReader();
|
|
4644
|
-
try {
|
|
4645
|
-
return reader.messageCountAfterSequence(sessionID, after, through);
|
|
4646
|
-
} finally {
|
|
4647
|
-
reader.close();
|
|
4648
|
-
}
|
|
4649
|
-
},
|
|
4650
|
-
readPage: (sessionID, afterOrdinal, limit, finalWatermark, after) => {
|
|
4651
|
-
const reader = openReader();
|
|
4652
|
-
try {
|
|
4653
|
-
return rawMessagePage(reader.messagePage(sessionID, afterOrdinal, limit, finalWatermark, after), afterOrdinal);
|
|
4654
|
-
} finally {
|
|
4655
|
-
reader.close();
|
|
4656
|
-
}
|
|
4657
|
-
},
|
|
4658
|
-
findById: (sessionID, messageID) => {
|
|
4659
|
-
const reader = openReader();
|
|
4660
|
-
try {
|
|
4661
|
-
const ordinal = reader.messageOrdinalById(sessionID, messageID);
|
|
4662
|
-
const row = reader.messageById(sessionID, messageID);
|
|
4663
|
-
if (ordinal === null || row === null)
|
|
4664
|
-
return null;
|
|
4665
|
-
return rawMessagePage([row], ordinal - 1)[0] ?? null;
|
|
4666
|
-
} finally {
|
|
4667
|
-
reader.close();
|
|
4668
|
-
}
|
|
4669
|
-
},
|
|
4670
|
-
findPartsById: (sessionID, messageID) => {
|
|
4671
|
-
const reader = openReader();
|
|
4672
|
-
try {
|
|
4673
|
-
const row = reader.messageById(sessionID, messageID);
|
|
4674
|
-
return row ? rawMessagePage([row], 0)[0] ?? null : null;
|
|
4675
|
-
} finally {
|
|
4676
|
-
reader.close();
|
|
4677
|
-
}
|
|
4678
|
-
},
|
|
4679
|
-
hasById: (sessionID, messageID) => {
|
|
4680
|
-
const reader = openReader();
|
|
4681
|
-
try {
|
|
4682
|
-
return reader.messageExistsById(sessionID, messageID);
|
|
4683
|
-
} finally {
|
|
4684
|
-
reader.close();
|
|
4685
|
-
}
|
|
4686
|
-
},
|
|
4687
|
-
ordinalOf: (sessionID, messageID) => {
|
|
4688
|
-
const reader = openReader();
|
|
4689
|
-
try {
|
|
4690
|
-
return reader.messageOrdinalById(sessionID, messageID);
|
|
4691
|
-
} finally {
|
|
4692
|
-
reader.close();
|
|
4693
|
-
}
|
|
4694
|
-
},
|
|
4695
|
-
orderOf: (sessionID, messageID) => {
|
|
4696
|
-
const reader = openReader();
|
|
4697
|
-
try {
|
|
4698
|
-
return reader.sequenceForId(sessionID, messageID) ?? null;
|
|
4699
|
-
} finally {
|
|
4700
|
-
reader.close();
|
|
4701
|
-
}
|
|
4702
|
-
},
|
|
4703
|
-
ordinalMapForRange: (sessionID, fromOrdinal, toOrdinal) => {
|
|
4704
|
-
const reader = openReader();
|
|
4705
|
-
try {
|
|
4706
|
-
return reader.messageIdOrdinals(sessionID, fromOrdinal, toOrdinal);
|
|
4707
|
-
} finally {
|
|
4708
|
-
reader.close();
|
|
4709
|
-
}
|
|
4710
|
-
},
|
|
4711
|
-
readOrdinalPage: (sessionID, after, limit) => {
|
|
4712
|
-
const reader = openReader();
|
|
4713
|
-
try {
|
|
4714
|
-
return reader.messageOrdinalPage(sessionID, after, limit);
|
|
4715
|
-
} finally {
|
|
4716
|
-
reader.close();
|
|
4717
|
-
}
|
|
4718
|
-
},
|
|
4719
|
-
getCount: (sessionID) => {
|
|
4720
|
-
const reader = openReader();
|
|
4721
|
-
try {
|
|
4722
|
-
return reader.messageCount(sessionID);
|
|
4723
|
-
} finally {
|
|
4724
|
-
reader.close();
|
|
4725
|
-
}
|
|
4726
|
-
},
|
|
4727
|
-
getStoredCount: (sessionID) => {
|
|
4728
|
-
const reader = openReader();
|
|
4729
|
-
try {
|
|
4730
|
-
return reader.storedMessageCount(sessionID);
|
|
4731
|
-
} finally {
|
|
4732
|
-
reader.close();
|
|
4733
|
-
}
|
|
4734
|
-
},
|
|
4735
|
-
servedBoundaryIdOf: (sessionID, messageID) => {
|
|
4736
|
-
const key = `${sessionID}\x00${messageID}`;
|
|
4737
|
-
if (servedBoundaryCache.has(key))
|
|
4738
|
-
return servedBoundaryCache.get(key) ?? null;
|
|
4739
|
-
const reader = openReader();
|
|
4740
|
-
try {
|
|
4741
|
-
const served = servedBoundaryRow(reader, sessionID, messageID)?.id ?? null;
|
|
4742
|
-
if (servedBoundaryCache.size >= 1000)
|
|
4743
|
-
servedBoundaryCache.clear();
|
|
4744
|
-
if (served !== null)
|
|
4745
|
-
servedBoundaryCache.set(key, served);
|
|
4746
|
-
return served;
|
|
4747
|
-
} finally {
|
|
4748
|
-
reader.close();
|
|
4749
|
-
}
|
|
4750
|
-
}
|
|
4751
|
-
};
|
|
4752
|
-
}
|
|
4753
|
-
function createV2RawMessageProvider(reader, sessionID) {
|
|
4754
|
-
return {
|
|
4755
|
-
readMessagePage: (afterOrdinal, limit, finalWatermark, after) => reader.readPage(sessionID, afterOrdinal, limit, finalWatermark, after),
|
|
4756
|
-
readMessageById: (messageID) => reader.findById(sessionID, messageID),
|
|
4757
|
-
readMessagePartsById: (messageID) => reader.findPartsById(sessionID, messageID),
|
|
4758
|
-
hasMessageById: (messageID) => reader.hasById(sessionID, messageID),
|
|
4759
|
-
readMessageOrdinalById: (messageID) => reader.ordinalOf(sessionID, messageID),
|
|
4760
|
-
...reader.orderOf ? {
|
|
4761
|
-
readMessageOrderById: (messageID) => reader.orderOf?.(sessionID, messageID) ?? null
|
|
4762
|
-
} : {},
|
|
4763
|
-
readMessageIdOrdinalsForRange: (fromOrdinal, toOrdinal) => reader.ordinalMapForRange(sessionID, fromOrdinal, toOrdinal),
|
|
4764
|
-
readMessageOrdinalPage: (after, limit) => reader.readOrdinalPage(sessionID, after, limit),
|
|
4765
|
-
getMessageCount: () => reader.getCount(sessionID),
|
|
4766
|
-
getStoredMessageCount: () => reader.getStoredCount(sessionID),
|
|
4767
|
-
...reader.servedBoundaryIdOf ? {
|
|
4768
|
-
readServedBoundaryId: (messageID) => reader.servedBoundaryIdOf?.(sessionID, messageID) ?? null
|
|
4769
|
-
} : {}
|
|
4770
|
-
};
|
|
4771
|
-
}
|
|
4772
|
-
|
|
4773
5607
|
// src/v2/hooks/system-prompt-response.ts
|
|
4774
5608
|
function bindV2SystemPromptResponse(sessionId, reader) {
|
|
4775
5609
|
const request = currentLkgRequestIdentity(sessionId);
|
|
@@ -5021,7 +5855,7 @@ function persistV2UsageReading(args) {
|
|
|
5021
5855
|
args.contextUsageMap.set(sessionID, {
|
|
5022
5856
|
usage: { inputTokens: reading.inputTokens, percentage },
|
|
5023
5857
|
hasUsageTokens: true,
|
|
5024
|
-
updatedAt: Date.now()
|
|
5858
|
+
updatedAt: reading.completed || Date.now()
|
|
5025
5859
|
});
|
|
5026
5860
|
} else {
|
|
5027
5861
|
args.contextUsageMap.delete(sessionID);
|
|
@@ -5035,8 +5869,10 @@ function applyCheckpointHead(draft, head) {
|
|
|
5035
5869
|
const { checkpoint, submitted } = head;
|
|
5036
5870
|
const first = draft.messages.find((message) => message.id === HEAD_IDS[0]);
|
|
5037
5871
|
const baseline = first?.content.find((part) => part.type === "text")?.text;
|
|
5038
|
-
if (typeof baseline !== "string")
|
|
5039
|
-
|
|
5872
|
+
if (typeof baseline !== "string") {
|
|
5873
|
+
draft.messages.unshift(checkpoint);
|
|
5874
|
+
return true;
|
|
5875
|
+
}
|
|
5040
5876
|
for (const part of checkpoint.content)
|
|
5041
5877
|
if (part.type === "text" && typeof part.text === "string") {
|
|
5042
5878
|
part.text = part.text.replace(`<summary>
|
|
@@ -5051,6 +5887,105 @@ ${baseline}
|
|
|
5051
5887
|
draft.messages.splice(0, draft.messages.length, checkpoint, ...draft.messages.filter((message) => message !== first));
|
|
5052
5888
|
return true;
|
|
5053
5889
|
}
|
|
5890
|
+
function bindKeptInstructionCoordinates(messages, incoming, reader, sessionID) {
|
|
5891
|
+
const rows = reader.instructionRowsThrough(sessionID, reader.latestSequence(sessionID));
|
|
5892
|
+
let previous;
|
|
5893
|
+
let pending = [];
|
|
5894
|
+
const bind = (next) => {
|
|
5895
|
+
if (!pending.length)
|
|
5896
|
+
return;
|
|
5897
|
+
const candidates = rows.filter((row) => (previous === undefined || row.seq > previous) && (next === undefined || row.seq < next));
|
|
5898
|
+
const selected = previous === undefined ? candidates.slice(-pending.length) : next === undefined ? candidates.slice(0, pending.length) : candidates;
|
|
5899
|
+
if (selected.length === pending.length && selected.every((row, index) => {
|
|
5900
|
+
const message = pending[index];
|
|
5901
|
+
return message?.role === "system" && message.content.length === 1 && message.content[0]?.type === "text" && message.content[0].text === row.data.text;
|
|
5902
|
+
})) {
|
|
5903
|
+
selected.forEach((row, index) => {
|
|
5904
|
+
const message = pending[index];
|
|
5905
|
+
if (message)
|
|
5906
|
+
bindNativeRowID(message, row.id, row.seq);
|
|
5907
|
+
});
|
|
5908
|
+
}
|
|
5909
|
+
pending = [];
|
|
5910
|
+
};
|
|
5911
|
+
for (const message of messages) {
|
|
5912
|
+
if (message === incoming || effortPart(message))
|
|
5913
|
+
continue;
|
|
5914
|
+
const id = nativeRowID(message);
|
|
5915
|
+
const seq = id ? reader.sequenceForId(sessionID, id) : undefined;
|
|
5916
|
+
if (seq !== undefined) {
|
|
5917
|
+
bind(seq);
|
|
5918
|
+
previous = seq;
|
|
5919
|
+
} else if (!id && message.role === "system")
|
|
5920
|
+
pending.push(message);
|
|
5921
|
+
}
|
|
5922
|
+
bind();
|
|
5923
|
+
}
|
|
5924
|
+
function controlSuffixKeys(messages, skip) {
|
|
5925
|
+
const keys = new Map;
|
|
5926
|
+
let before;
|
|
5927
|
+
let occurrence = 0;
|
|
5928
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
5929
|
+
const message = messages[index];
|
|
5930
|
+
if (!message || message === skip)
|
|
5931
|
+
continue;
|
|
5932
|
+
const part = effortPart(message);
|
|
5933
|
+
if (part) {
|
|
5934
|
+
if (before)
|
|
5935
|
+
keys.set(message, JSON.stringify({
|
|
5936
|
+
before,
|
|
5937
|
+
occurrence: occurrence++,
|
|
5938
|
+
effort: part.effort,
|
|
5939
|
+
previous: part.previous
|
|
5940
|
+
}));
|
|
5941
|
+
} else {
|
|
5942
|
+
before = nativeRowID(message);
|
|
5943
|
+
occurrence = 0;
|
|
5944
|
+
}
|
|
5945
|
+
}
|
|
5946
|
+
return keys;
|
|
5947
|
+
}
|
|
5948
|
+
function restoreNativeCheckpointInput(messages, incoming, restored, reader, sessionID) {
|
|
5949
|
+
bindKeptInstructionCoordinates(messages, incoming, reader, sessionID);
|
|
5950
|
+
const present = new Set(messages.flatMap((message) => nativeRowID(message) ?? []));
|
|
5951
|
+
const currentControls = new Map;
|
|
5952
|
+
const currentSuffixKeys = controlSuffixKeys(messages, incoming);
|
|
5953
|
+
const restoredSuffixKeys = controlSuffixKeys(restored);
|
|
5954
|
+
const leadingControls = new Set;
|
|
5955
|
+
let after;
|
|
5956
|
+
for (const message of messages) {
|
|
5957
|
+
const part = effortPart(message);
|
|
5958
|
+
if (part) {
|
|
5959
|
+
const suffixKey = currentSuffixKeys.get(message);
|
|
5960
|
+
if (!after && suffixKey) {
|
|
5961
|
+
leadingControls.add(suffixKey);
|
|
5962
|
+
continue;
|
|
5963
|
+
}
|
|
5964
|
+
const key = controlKey({
|
|
5965
|
+
after,
|
|
5966
|
+
effort: part.effort,
|
|
5967
|
+
previous: part.previous
|
|
5968
|
+
});
|
|
5969
|
+
currentControls.set(key, (currentControls.get(key) ?? 0) + 1);
|
|
5970
|
+
} else if (message !== incoming && nativeRowID(message))
|
|
5971
|
+
after = nativeRowID(message);
|
|
5972
|
+
}
|
|
5973
|
+
const hidden = restored.filter((message) => {
|
|
5974
|
+
const suffixKey = restoredSuffixKeys.get(message);
|
|
5975
|
+
if (suffixKey && leadingControls.delete(suffixKey))
|
|
5976
|
+
return false;
|
|
5977
|
+
const key = rememberedControlKey(message);
|
|
5978
|
+
const count = key ? currentControls.get(key) ?? 0 : 0;
|
|
5979
|
+
if (key && count > 0) {
|
|
5980
|
+
currentControls.set(key, count - 1);
|
|
5981
|
+
return false;
|
|
5982
|
+
}
|
|
5983
|
+
const id = nativeRowID(message);
|
|
5984
|
+
return !id || !present.has(id);
|
|
5985
|
+
});
|
|
5986
|
+
const at = messages.indexOf(incoming);
|
|
5987
|
+
return [...messages.slice(0, at), ...hidden, ...messages.slice(at + 1)];
|
|
5988
|
+
}
|
|
5054
5989
|
function estimateCheckpointRequest(draft) {
|
|
5055
5990
|
let toolDefinitionTokens = 0;
|
|
5056
5991
|
for (const tool of Object.values(draft.tools)) {
|
|
@@ -5262,10 +6197,10 @@ async function applyV2SystemPrompt(systemPrompt, draft) {
|
|
|
5262
6197
|
text
|
|
5263
6198
|
})));
|
|
5264
6199
|
}
|
|
5265
|
-
function coveredInstructionRows(reader, sessionID, throughSeq, model) {
|
|
6200
|
+
function coveredInstructionRows(reader, sessionID, throughSeq, model, retired = () => false) {
|
|
5266
6201
|
if (throughSeq < 0)
|
|
5267
6202
|
return [];
|
|
5268
|
-
return reader.instructionRowsThrough(sessionID, throughSeq).flatMap((row) => restoreRow(row, model)).map((message) => markCoveredInstructionRow(message));
|
|
6203
|
+
return reader.instructionRowsThrough(sessionID, throughSeq).filter((row) => !retired(row)).flatMap((row) => restoreRow(row, model)).map((message) => markCoveredInstructionRow(message));
|
|
5269
6204
|
}
|
|
5270
6205
|
async function registerContext(context) {
|
|
5271
6206
|
const directory = context.location.directory;
|
|
@@ -5307,8 +6242,11 @@ async function registerContext(context) {
|
|
|
5307
6242
|
}
|
|
5308
6243
|
const embeddings = createV2EmbeddingScope(resolveProjectIdentityForSession(directory, config.allow_home_project));
|
|
5309
6244
|
const folds = new FoldOwner(context.storage);
|
|
5310
|
-
const nativeFoldMemory =
|
|
5311
|
-
const nativeFoldReplay = nativeFoldMemory ? new NativeFoldReplay(nativeFoldMemory, () => openStoreReader(), context.storage
|
|
6245
|
+
const nativeFoldMemory = compactionOff ? undefined : nativeFoldCache(() => storage.require());
|
|
6246
|
+
const nativeFoldReplay = nativeFoldMemory ? new NativeFoldReplay(nativeFoldMemory, () => openStoreReader(), context.storage, {
|
|
6247
|
+
protocol: 3,
|
|
6248
|
+
log: sessionLog2
|
|
6249
|
+
}) : undefined;
|
|
5312
6250
|
setOutputReserveConfig(config.output_reserve);
|
|
5313
6251
|
const queriedModels = new Set;
|
|
5314
6252
|
const rawLimits = new Map;
|
|
@@ -5362,34 +6300,38 @@ async function registerContext(context) {
|
|
|
5362
6300
|
memorySyncRequestedSessions: rustMemorySyncRequestedSessions
|
|
5363
6301
|
}) : undefined;
|
|
5364
6302
|
const hiddenChildHook = new HiddenChildHook;
|
|
5365
|
-
await context.session.hook("http.request", (draft) => hiddenChildHook.cacheRequest(draft));
|
|
5366
|
-
const tools = db && isDatabasePersisted(db) ? await registerTools(context, db, config, moduleToolBackends?.backends, (id) => hiddenChildHook.owns(id), embeddings.ensureRegistered) : undefined;
|
|
5367
6303
|
const usage = new Map;
|
|
6304
|
+
const overflowRecovery = new V2OverflowRecovery({
|
|
6305
|
+
database: () => db ?? null,
|
|
6306
|
+
compactionOff,
|
|
6307
|
+
isHidden: (sessionID) => hiddenChildHook.owns(sessionID),
|
|
6308
|
+
onInputTokens: (sessionID, inputTokens, limit) => usage.set(sessionID, {
|
|
6309
|
+
usage: { inputTokens, percentage: limit > 0 ? inputTokens / limit * 100 : 100 },
|
|
6310
|
+
hasUsageTokens: true,
|
|
6311
|
+
updatedAt: Date.now()
|
|
6312
|
+
})
|
|
6313
|
+
});
|
|
6314
|
+
await context.session.hook("http.request", async (draft) => {
|
|
6315
|
+
await hiddenChildHook.cacheRequest(draft);
|
|
6316
|
+
if (draft.kind !== "primary" || hiddenChildHook.owns(draft.sessionID))
|
|
6317
|
+
return;
|
|
6318
|
+
const selectedModel = liveModels.get(draft.sessionID);
|
|
6319
|
+
if (selectedModel)
|
|
6320
|
+
overflowRecovery.begin({
|
|
6321
|
+
...draft,
|
|
6322
|
+
model: { providerID: selectedModel.providerID, id: selectedModel.modelID }
|
|
6323
|
+
});
|
|
6324
|
+
});
|
|
6325
|
+
const tools = db && isDatabasePersisted(db) ? await registerTools(context, db, config, moduleToolBackends?.backends, (id) => hiddenChildHook.owns(id), embeddings.ensureRegistered) : undefined;
|
|
5368
6326
|
const generateReplay = new V2GenerateReplay;
|
|
5369
6327
|
await context.session.hook("http.response", async (draft) => {
|
|
5370
6328
|
if (!db || draft.kind !== "primary" || draft.response.ok)
|
|
5371
6329
|
return;
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
if (detection.reportedLimit)
|
|
5378
|
-
recordDetectedContextLimit(db, draft.sessionID, detection.reportedLimit, modelKey, detection.reportedLimitProvenance);
|
|
5379
|
-
} else {
|
|
5380
|
-
recordOverflowDetected(db, draft.sessionID, detection.reportedLimit, modelKey, "provider_overflow", detection.reportedLimitProvenance, detection.reportedInputTokens);
|
|
5381
|
-
if (detection.reportedInputTokens) {
|
|
5382
|
-
const provenLimit = getOverflowState(db, draft.sessionID, modelKey).detectedContextLimit;
|
|
5383
|
-
usage.set(draft.sessionID, {
|
|
5384
|
-
usage: {
|
|
5385
|
-
inputTokens: detection.reportedInputTokens,
|
|
5386
|
-
percentage: provenLimit > 0 ? detection.reportedInputTokens / provenLimit * 100 : 100
|
|
5387
|
-
},
|
|
5388
|
-
hasUsageTokens: true,
|
|
5389
|
-
updatedAt: Date.now()
|
|
5390
|
-
});
|
|
5391
|
-
}
|
|
5392
|
-
}
|
|
6330
|
+
overflowRecovery.observe({
|
|
6331
|
+
...draft,
|
|
6332
|
+
error: await draft.response.clone().text(),
|
|
6333
|
+
status: draft.response.status
|
|
6334
|
+
});
|
|
5393
6335
|
});
|
|
5394
6336
|
await registerHiddenChildAgents(context.agent);
|
|
5395
6337
|
await context.tool.hook("execute.before", (draft) => {
|
|
@@ -5403,9 +6345,9 @@ async function registerContext(context) {
|
|
|
5403
6345
|
throw new HiddenCompletionRefusal("hidden_prompt_unrecognized", refusal, true);
|
|
5404
6346
|
});
|
|
5405
6347
|
let hiddenAgentsReady;
|
|
5406
|
-
const readerPool = new
|
|
6348
|
+
const readerPool = new V2StoreReaderPool2;
|
|
5407
6349
|
const messageTimesCache = new V2MessageTimesCache;
|
|
5408
|
-
const openStoreReader = () => readerPool.open(
|
|
6350
|
+
const openStoreReader = () => readerPool.open(gaDatabasePath2(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
5409
6351
|
const createHiddenExecutor = async (database) => {
|
|
5410
6352
|
await cleanupLegacyOnce(database);
|
|
5411
6353
|
return createV2HiddenCompletionExecutor({
|
|
@@ -5565,10 +6507,10 @@ async function registerContext(context) {
|
|
|
5565
6507
|
log2("[magic-context] v2 Channel 2 delivery deferred", error);
|
|
5566
6508
|
}
|
|
5567
6509
|
});
|
|
5568
|
-
const pagedRead =
|
|
6510
|
+
const pagedRead = createV2RawMessageReader2(openStoreReader, gaDatabasePath2(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"));
|
|
5569
6511
|
const prepareHistorySession = (sessionID) => {
|
|
5570
6512
|
if (!rawProviders.has(sessionID))
|
|
5571
|
-
rawProviders.set(sessionID, setBoundedRawMessageProvider2(sessionID,
|
|
6513
|
+
rawProviders.set(sessionID, setBoundedRawMessageProvider2(sessionID, createV2RawMessageProvider2(pagedRead, sessionID)));
|
|
5572
6514
|
};
|
|
5573
6515
|
if (db && isDatabasePersisted(db)) {
|
|
5574
6516
|
const backfillDb = db;
|
|
@@ -5583,7 +6525,7 @@ async function registerContext(context) {
|
|
|
5583
6525
|
})).catch((error) => log2("[session-project-backfill] OpenCode 2 backfill failed:", error));
|
|
5584
6526
|
});
|
|
5585
6527
|
}
|
|
5586
|
-
const readAllForConversion = (sessionID) =>
|
|
6528
|
+
const readAllForConversion = (sessionID) => readAllV2RawMessagesForConversion2(openStoreReader, sessionID);
|
|
5587
6529
|
const readRowsFrom = (sessionID, messageID) => {
|
|
5588
6530
|
const reader = openStoreReader();
|
|
5589
6531
|
try {
|
|
@@ -5737,9 +6679,19 @@ async function registerContext(context) {
|
|
|
5737
6679
|
storage: nativeFoldMemory,
|
|
5738
6680
|
openReader: openStoreReader,
|
|
5739
6681
|
canReplay: (sessionID, reader) => nativeFoldReplay.canReplay(sessionID, reader),
|
|
6682
|
+
canFold: async (sessionID, reader) => {
|
|
6683
|
+
const meta = getOrCreateSessionMeta(storage.require(), sessionID);
|
|
6684
|
+
const summary = [
|
|
6685
|
+
servedModuleM0Text(sessionID),
|
|
6686
|
+
await nativeFoldReplay.baseline(sessionID),
|
|
6687
|
+
meta.cachedM0Bytes?.toString("utf8")
|
|
6688
|
+
].find((value) => value !== RAW_HISTORY_ACCOUNT && hasFoldSummary(value));
|
|
6689
|
+
return !meta.isSubagent && summary !== RAW_HISTORY_ACCOUNT && hasFoldSummary(summary) && nativeFoldReplay.canFold(sessionID, reader);
|
|
6690
|
+
},
|
|
5740
6691
|
threshold: Number(process.env.MC_OC2_HOST_FOLD_ROWS ?? 1000),
|
|
5741
6692
|
log: sessionLog2
|
|
5742
6693
|
}) : undefined;
|
|
6694
|
+
const hostFoldIdle = hostFolds ? new HostFoldIdle((sessionID, eligible) => hostFolds.idle(sessionID, eligible)) : undefined;
|
|
5743
6695
|
const usageController = new AbortController;
|
|
5744
6696
|
const usageDone = (async () => {
|
|
5745
6697
|
let retry = 0;
|
|
@@ -5761,10 +6713,27 @@ async function registerContext(context) {
|
|
|
5761
6713
|
if (!event.data?.sessionID)
|
|
5762
6714
|
continue;
|
|
5763
6715
|
const sessionID = event.data.sessionID;
|
|
6716
|
+
observeSyntheticAdmissionEvent(context, event);
|
|
6717
|
+
overflowRecovery.observeTerminal(event, (id, messageID) => {
|
|
6718
|
+
const reader = openStoreReader();
|
|
6719
|
+
try {
|
|
6720
|
+
const latest = reader.latestAssistant(id);
|
|
6721
|
+
if (messageID && latest?.id !== messageID)
|
|
6722
|
+
return;
|
|
6723
|
+
const row = messageID ? reader.messageById(id, messageID) : latest;
|
|
6724
|
+
return row ? { id: row.id, model: row.data.model, error: row.data.error } : undefined;
|
|
6725
|
+
} finally {
|
|
6726
|
+
reader.close();
|
|
6727
|
+
}
|
|
6728
|
+
});
|
|
5764
6729
|
if (db && event.type === "session.revert.committed") {
|
|
5765
6730
|
const indexDb = db;
|
|
5766
6731
|
withoutSqliteTransformPass2(() => scheduleClearAndReindex(indexDb, sessionID, pagedRead));
|
|
5767
6732
|
}
|
|
6733
|
+
if (event.type === "session.execution.started" || event.type === "session.execution.interrupted") {
|
|
6734
|
+
hostFoldIdle?.active(sessionID);
|
|
6735
|
+
continue;
|
|
6736
|
+
}
|
|
5768
6737
|
if (event.type?.startsWith("session.revert.") || event.type === "session.message.content.updated") {
|
|
5769
6738
|
nativeFoldReplay?.onEvent(event);
|
|
5770
6739
|
restoredRows.forget(sessionID);
|
|
@@ -5776,6 +6745,7 @@ async function registerContext(context) {
|
|
|
5776
6745
|
messageTimesCache.deleteMessage(sessionID, messageID);
|
|
5777
6746
|
}
|
|
5778
6747
|
if (event.type === "session.error" || event.type === "session.execution.failed") {
|
|
6748
|
+
hostFoldIdle?.active(sessionID);
|
|
5779
6749
|
const error = hiddenTerminalError(event);
|
|
5780
6750
|
if (error !== undefined)
|
|
5781
6751
|
hiddenSessionErrors.set(sessionID, error);
|
|
@@ -5796,6 +6766,8 @@ async function registerContext(context) {
|
|
|
5796
6766
|
continue;
|
|
5797
6767
|
}
|
|
5798
6768
|
if (event.type === "session.deleted") {
|
|
6769
|
+
overflowRecovery.forget(sessionID);
|
|
6770
|
+
hostFoldIdle?.active(sessionID);
|
|
5799
6771
|
clearLkgMeasuredRequest(sessionID);
|
|
5800
6772
|
deletedSessions.add(sessionID);
|
|
5801
6773
|
const failures = [];
|
|
@@ -5850,8 +6822,12 @@ async function registerContext(context) {
|
|
|
5850
6822
|
sessionID,
|
|
5851
6823
|
model: { providerID: model.providerID, id: model.modelID }
|
|
5852
6824
|
});
|
|
5853
|
-
if (!compactionOff
|
|
5854
|
-
|
|
6825
|
+
if (!compactionOff) {
|
|
6826
|
+
if (db) {
|
|
6827
|
+
const meta = getOrCreateSessionMeta(db, sessionID);
|
|
6828
|
+
hostFoldIdle?.idle(sessionID, meta.cacheTtl, meta.lastResponseTime);
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
5855
6831
|
}
|
|
5856
6832
|
} catch (error) {
|
|
5857
6833
|
log2(`[magic-context] v2 event handler failed (type=${event.type ?? "unknown"}, session=${event.data?.sessionID ?? "none"})`, error);
|
|
@@ -5919,24 +6895,46 @@ async function registerContext(context) {
|
|
|
5919
6895
|
await storage.probe();
|
|
5920
6896
|
const watermark = reader.latestSequenceForIds(draft.sessionID, draft.messages.flatMap((message) => message.id ? [message.id] : []));
|
|
5921
6897
|
const running = reader.latestRunningCompaction(draft.sessionID);
|
|
6898
|
+
const attempt = running && nativeFoldMemory?.admission(draft.sessionID, running.id);
|
|
6899
|
+
const manual = running?.data.reason === "manual" && !(attempt?.status === "pending" && attempt.owner_token);
|
|
5922
6900
|
const moduleBaseline = rustModeModuleClient ? servedModuleM0Text(draft.sessionID) : undefined;
|
|
5923
6901
|
const source = !rustModeModuleClient ? "typescript" : moduleBaseline === null ? "typescript_fallback" : "module";
|
|
5924
6902
|
if (nativeFoldReplay) {
|
|
5925
6903
|
try {
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
6904
|
+
const state = getOrCreateSessionMeta(storage.require(), draft.sessionID);
|
|
6905
|
+
const staged = manual && moduleBaseline == null ? stageManualBaseline(storage.require(), draft.sessionID, () => materialize(draft)) : undefined;
|
|
6906
|
+
const publishedHistory = Boolean(storage.require().prepare("SELECT 1 FROM compartments WHERE session_id = ? LIMIT 1").get(draft.sessionID));
|
|
6907
|
+
const candidate = [
|
|
6908
|
+
moduleBaseline,
|
|
6909
|
+
await nativeFoldReplay.baseline(draft.sessionID),
|
|
6910
|
+
state.cachedM0Bytes?.toString("utf8"),
|
|
6911
|
+
(await folds.read(draft.sessionID))?.submitted
|
|
6912
|
+
].find((value) => value !== RAW_HISTORY_ACCOUNT && (publishedHistory && value?.includes("<session-history>") || hasFoldSummary(value)));
|
|
6913
|
+
const manualHistory = manual && hasFoldSummary(staged?.summary ?? moduleBaseline);
|
|
6914
|
+
const summary = manualHistory ? staged?.summary ?? candidate ?? RAW_HISTORY_ACCOUNT : candidate ?? RAW_HISTORY_ACCOUNT;
|
|
6915
|
+
const manualReplay = manualHistory && summary ? await nativeFoldReplay.prepareManualFold(draft.sessionID, reader, staged ? staged.boundaryID : storage.require().prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id = ?").get(draft.sessionID).id, summary) : undefined;
|
|
6916
|
+
if ((hasFoldSummary(summary) || publishedHistory) && await nativeFoldReplay.supply({
|
|
6917
|
+
draft,
|
|
6918
|
+
reader,
|
|
6919
|
+
previousCut: reader.latestCompaction(draft.sessionID),
|
|
6920
|
+
summary,
|
|
6921
|
+
manual: manualReplay ? { replay: manualReplay, commit: () => staged?.commit() } : undefined
|
|
6922
|
+
})) {
|
|
6923
|
+
if (manualHistory) {
|
|
6924
|
+
dropSlot(draft.sessionID, "manual host compaction");
|
|
6925
|
+
generateReplay.forget(draft.sessionID);
|
|
6926
|
+
restoredRows.forget(draft.sessionID);
|
|
6927
|
+
historyRefreshSessions.add(draft.sessionID);
|
|
6928
|
+
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "host_compaction");
|
|
5937
6929
|
}
|
|
6930
|
+
draft.result = { summary, metadata: { keepID: undefined } };
|
|
6931
|
+
return;
|
|
5938
6932
|
}
|
|
6933
|
+
if (manual)
|
|
6934
|
+
throw new V2ContextRefusal("Magic Context could not admit the manual fold.");
|
|
5939
6935
|
} catch (error) {
|
|
6936
|
+
if (error instanceof V2ContextRefusal || manual)
|
|
6937
|
+
throw error;
|
|
5940
6938
|
nativeFoldReplay.invalidate(draft.sessionID, true);
|
|
5941
6939
|
sessionLog2(draft.sessionID, `v2 host fold: legacy compaction reason=${JSON.stringify(String(error))}`);
|
|
5942
6940
|
}
|
|
@@ -5945,7 +6943,10 @@ async function registerContext(context) {
|
|
|
5945
6943
|
sessionID: draft.sessionID,
|
|
5946
6944
|
watermark,
|
|
5947
6945
|
runningCut: running?.seq,
|
|
5948
|
-
materialize: () =>
|
|
6946
|
+
materialize: () => {
|
|
6947
|
+
const summary = moduleBaseline ?? materialize(draft);
|
|
6948
|
+
return hasFoldSummary(summary) ? summary : RAW_HISTORY_ACCOUNT;
|
|
6949
|
+
}
|
|
5949
6950
|
});
|
|
5950
6951
|
sessionLog2(draft.sessionID, `v2 compaction hook: fired answered=true source=${source}`);
|
|
5951
6952
|
draft.result = { summary: fold.submitted, metadata: { keepID: undefined } };
|
|
@@ -5960,6 +6961,19 @@ async function registerContext(context) {
|
|
|
5960
6961
|
});
|
|
5961
6962
|
const temporalTimes = config.temporal_awareness === true;
|
|
5962
6963
|
const anchorTimesOnly = !temporalTimes && !rustModeModuleClient;
|
|
6964
|
+
const retireInstructionMessages = async (sessionID, reader, messages) => {
|
|
6965
|
+
const retired = await nativeFoldReplay?.instructionRetirement(sessionID, reader);
|
|
6966
|
+
if (!retired)
|
|
6967
|
+
return messages;
|
|
6968
|
+
return messages.filter((message) => {
|
|
6969
|
+
const id = nativeRowID(message);
|
|
6970
|
+
return message.role !== "system" || !id || !retired({
|
|
6971
|
+
type: "system",
|
|
6972
|
+
id,
|
|
6973
|
+
seq: nativeRowSequence(message) ?? reader.sequenceForId(sessionID, id) ?? Infinity
|
|
6974
|
+
});
|
|
6975
|
+
});
|
|
6976
|
+
};
|
|
5963
6977
|
const timeIds = (messages) => {
|
|
5964
6978
|
if (temporalTimes)
|
|
5965
6979
|
return messages.flatMap((message) => message.id ? [message.id] : []);
|
|
@@ -5974,28 +6988,31 @@ async function registerContext(context) {
|
|
|
5974
6988
|
}
|
|
5975
6989
|
return ids;
|
|
5976
6990
|
};
|
|
5977
|
-
const restoreAfterCheckpoint = (args) => {
|
|
6991
|
+
const restoreAfterCheckpoint = async (args) => {
|
|
5978
6992
|
const { db, reader, draft, cut, boundaryRepair } = args;
|
|
5979
6993
|
const moduleBoundaryID = rustModeModuleClient ? getPersistedCompactionMarkerState(db, draft.sessionID)?.boundaryMessageId ?? null : null;
|
|
5980
6994
|
const moduleBoundarySeq = moduleBoundaryID ? reader.sequenceForId(draft.sessionID, moduleBoundaryID) : undefined;
|
|
5981
6995
|
const boundaryID = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id = ?").get(draft.sessionID)?.id ?? (boundaryRepair?.kind === "repaired" || boundaryRepair?.kind === "baseline-reset" ? boundaryRepair.anchorEndMessageId : null);
|
|
5982
|
-
const servedBoundary = boundaryID ?
|
|
5983
|
-
const
|
|
6996
|
+
const servedBoundary = boundaryID ? servedBoundaryRow2(reader, draft.sessionID, boundaryID) : null;
|
|
6997
|
+
const nativeFloor = await nativeFoldReplay?.restorationFloor(draft.sessionID, cut, reader);
|
|
6998
|
+
const retiredInstructions = await nativeFoldReplay?.instructionRetirement(draft.sessionID, reader) ?? (() => false);
|
|
6999
|
+
const boundary = Math.max(nativeFloor ?? -Infinity, (nativeFoldReplay?.sourceChanged(draft.sessionID) && !rustModeModuleClient ? (reader.earliestSequence(draft.sessionID) ?? 0) - 1 : undefined) ?? (moduleBoundarySeq !== undefined ? moduleBoundarySeq - 1 : undefined) ?? servedBoundary?.seq ?? reader.sequenceForId(draft.sessionID, boundaryID) ?? (reader.earliestSequence(draft.sessionID) ?? 0) - 1);
|
|
5984
7000
|
if (moduleBoundarySeq !== undefined)
|
|
5985
7001
|
sessionLog2(draft.sessionID, `v2 restore: from the module boundary ${moduleBoundaryID} to the host checkpoint`);
|
|
5986
7002
|
const present = new Set(args.messages.map((message) => message.id));
|
|
5987
|
-
const restored = restoredRows.rows(reader, draft.sessionID, boundary, cut.seq).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
|
|
7003
|
+
const restored = restoredRows.rows(reader, draft.sessionID, boundary, cut.seq).filter((row) => !retiredInstructions(row)).filter((row) => !present.has(row.id)).flatMap((row) => restoreRow(row, draft.model, hostUsesMediaAssets() ? {
|
|
5988
7004
|
asset: hostMediaAsset,
|
|
5989
7005
|
unavailable: (detail) => sessionLog2(draft.sessionID, `v2 restore: attachment replaced by a note row=${detail.rowID} name=${JSON.stringify(detail.name ?? null)} mediaType=${detail.mediaType} reason=${JSON.stringify(detail.reason)}`)
|
|
5990
7006
|
} : undefined));
|
|
5991
7007
|
return [
|
|
5992
|
-
...rustModeModuleClient ? [] : coveredInstructionRows(reader, draft.sessionID, Math.min(boundary, cut.seq), draft.model),
|
|
7008
|
+
...rustModeModuleClient ? [] : coveredInstructionRows(reader, draft.sessionID, Math.min(boundary, cut.seq), draft.model, retiredInstructions),
|
|
5993
7009
|
...restored,
|
|
5994
7010
|
...args.messages.filter((message) => message !== args.incoming)
|
|
5995
7011
|
];
|
|
5996
7012
|
};
|
|
5997
7013
|
const checkpointPassPermissions = new Map;
|
|
5998
7014
|
const checkpointInputEstimates = new Map;
|
|
7015
|
+
const admissionRebuildPasses = new Set;
|
|
5999
7016
|
const initializeTransform = (database) => transform ??= createTransform({
|
|
6000
7017
|
...createV2TransformFeatureDeps(config, compactionOff, directory, embeddings.ensureRegistered),
|
|
6001
7018
|
cacheTtlConfig: config.cache_ttl,
|
|
@@ -6065,7 +7082,7 @@ async function registerContext(context) {
|
|
|
6065
7082
|
compactionMarkerStrategy: rustModeModuleClient ? createV2RustCompactionMarkerStrategy((sessionID, endMessageID) => {
|
|
6066
7083
|
const reader = openStoreReader();
|
|
6067
7084
|
try {
|
|
6068
|
-
return
|
|
7085
|
+
return resolveV2BoundaryUserMessage2(reader, sessionID, endMessageID);
|
|
6069
7086
|
} finally {
|
|
6070
7087
|
reader.close();
|
|
6071
7088
|
}
|
|
@@ -6123,6 +7140,7 @@ async function registerContext(context) {
|
|
|
6123
7140
|
providerID: draft.model.providerID,
|
|
6124
7141
|
modelID: draft.model.id
|
|
6125
7142
|
});
|
|
7143
|
+
overflowRecovery.begin({ sessionID: draft.sessionID, kind: "primary", model: draft.model });
|
|
6126
7144
|
variants.set(draft.sessionID, draft.model.variant);
|
|
6127
7145
|
if (!modelLimitCacheWarm())
|
|
6128
7146
|
withoutSqliteTransformPass2(() => warmModelLimitCacheFromCatalog(context));
|
|
@@ -6177,7 +7195,7 @@ async function registerContext(context) {
|
|
|
6177
7195
|
const cut = reader.latestCompaction(draft.sessionID);
|
|
6178
7196
|
const localCut = cut && isLocalCheckpoint(cut) ? cut : undefined;
|
|
6179
7197
|
const incoming = localCut && messages.find((message) => message.id === localCut.id);
|
|
6180
|
-
if (localCut && !incoming
|
|
7198
|
+
if (localCut && !incoming)
|
|
6181
7199
|
return;
|
|
6182
7200
|
checkpointAtEntry = incoming || null;
|
|
6183
7201
|
const modeDb = db ?? storage.current();
|
|
@@ -6192,18 +7210,35 @@ async function registerContext(context) {
|
|
|
6192
7210
|
if (message.id && candidates.has(message.id) && await isAdmittedSynthetic(context, draft.sessionID, message.id))
|
|
6193
7211
|
admitted.add(message.id);
|
|
6194
7212
|
const replayDb = db ?? storage.current();
|
|
6195
|
-
if (localCut && incoming && replayDb)
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
7213
|
+
if (localCut && incoming && replayDb) {
|
|
7214
|
+
const admission = nativeFoldReplay ? await nativeFoldReplay.replayAdmission(draft.sessionID, localCut, reader) : "legacy";
|
|
7215
|
+
if (admission === undefined)
|
|
7216
|
+
return;
|
|
7217
|
+
if (admission === "native" && nativeFoldReplay) {
|
|
7218
|
+
const restored = await nativeFoldReplay.projectReplay({
|
|
7219
|
+
sessionID: draft.sessionID,
|
|
7220
|
+
cut: localCut,
|
|
7221
|
+
model: draft.model,
|
|
7222
|
+
reader,
|
|
7223
|
+
bounded: true
|
|
7224
|
+
});
|
|
7225
|
+
if (!restored)
|
|
7226
|
+
return;
|
|
7227
|
+
messages = restoreNativeCheckpointInput(messages, incoming, restored, reader, draft.sessionID);
|
|
7228
|
+
} else {
|
|
7229
|
+
messages = await restoreAfterCheckpoint({
|
|
7230
|
+
db: replayDb,
|
|
7231
|
+
reader,
|
|
7232
|
+
draft,
|
|
7233
|
+
messages,
|
|
7234
|
+
cut: localCut,
|
|
7235
|
+
incoming,
|
|
7236
|
+
boundaryRepair: undefined
|
|
7237
|
+
});
|
|
7238
|
+
}
|
|
7239
|
+
} else if (localCut)
|
|
6206
7240
|
return;
|
|
7241
|
+
messages = await retireInstructionMessages(draft.sessionID, reader, messages);
|
|
6207
7242
|
times = readTimes(reader, messages);
|
|
6208
7243
|
}
|
|
6209
7244
|
} finally {
|
|
@@ -6283,7 +7318,7 @@ async function registerContext(context) {
|
|
|
6283
7318
|
sessionId: draft.sessionID,
|
|
6284
7319
|
generation: "v2",
|
|
6285
7320
|
readMessages: readAllForConversion,
|
|
6286
|
-
readMessagePages: (sessionID) =>
|
|
7321
|
+
readMessagePages: (sessionID) => readV2RawMessagePagesForConversion2(openStoreReader, sessionID)
|
|
6287
7322
|
});
|
|
6288
7323
|
} catch (error) {
|
|
6289
7324
|
sessionLog2(draft.sessionID, "store projection rebase failed before system prompt (retrying in transform):", error);
|
|
@@ -6342,6 +7377,7 @@ async function registerContext(context) {
|
|
|
6342
7377
|
const reader = openStoreReader();
|
|
6343
7378
|
let checkpoint;
|
|
6344
7379
|
let submitted;
|
|
7380
|
+
let upgradeCheckpointSequence;
|
|
6345
7381
|
try {
|
|
6346
7382
|
const candidates = syntheticCandidates(context, draft.sessionID, reader.syntheticMessageIDs(draft.sessionID));
|
|
6347
7383
|
for (const message of draft.messages) {
|
|
@@ -6362,8 +7398,31 @@ async function registerContext(context) {
|
|
|
6362
7398
|
if (localCut && !incoming)
|
|
6363
7399
|
throw new Error("The host checkpoint disappeared from the context draft");
|
|
6364
7400
|
checkpointAtEntry = incoming || null;
|
|
6365
|
-
|
|
6366
|
-
|
|
7401
|
+
if (localCut && nativeFoldReplay) {
|
|
7402
|
+
await nativeFoldReplay.prepareLegacyUpgrade({
|
|
7403
|
+
draft,
|
|
7404
|
+
cut: localCut,
|
|
7405
|
+
reader
|
|
7406
|
+
});
|
|
7407
|
+
const carrier = await nativeFoldReplay.checkpointForReplay(draft.sessionID, reader);
|
|
7408
|
+
if (carrier) {
|
|
7409
|
+
const identity = await folds.observe({
|
|
7410
|
+
sessionID: draft.sessionID,
|
|
7411
|
+
cutSeq: carrier.row.seq,
|
|
7412
|
+
summary: carrier.submitted,
|
|
7413
|
+
rendered: carrier.rendered,
|
|
7414
|
+
onHard: () => {
|
|
7415
|
+
historyRefreshSessions.add(draft.sessionID);
|
|
7416
|
+
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "host_compaction");
|
|
7417
|
+
}
|
|
7418
|
+
});
|
|
7419
|
+
checkpoint = structuredClone(identity.rendered ?? carrier.rendered);
|
|
7420
|
+
submitted = identity.renderedSummary ?? carrier.submitted;
|
|
7421
|
+
upgradeCheckpointSequence = carrier.row.seq;
|
|
7422
|
+
}
|
|
7423
|
+
}
|
|
7424
|
+
let nativeRestored = localCut ? nativeFoldReplay?.legacyUpgradeInput(draft.sessionID, draft.model) : undefined;
|
|
7425
|
+
if (nativeRestored === undefined && cut && nativeFoldReplay && await nativeFoldReplay.admits(draft.sessionID, cut, reader)) {
|
|
6367
7426
|
try {
|
|
6368
7427
|
nativeRestored = await nativeFoldReplay.restore(draft.sessionID, cut, `${draft.model.providerID}/${draft.model.id}`, { bounded: !rustModeModuleClient });
|
|
6369
7428
|
} catch (error) {
|
|
@@ -6381,14 +7440,10 @@ async function registerContext(context) {
|
|
|
6381
7440
|
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "host_history_change");
|
|
6382
7441
|
}
|
|
6383
7442
|
if (cut && incoming && nativeRestored) {
|
|
6384
|
-
|
|
6385
|
-
const hidden = nativeRestored.filter((message) => {
|
|
6386
|
-
const id = nativeRowID(message);
|
|
6387
|
-
return !id || !present.has(id);
|
|
6388
|
-
});
|
|
6389
|
-
draft.messages.splice(0, draft.messages.length, ...hidden, ...draft.messages.filter((message) => message !== incoming));
|
|
7443
|
+
draft.messages.splice(0, draft.messages.length, ...restoreNativeCheckpointInput(draft.messages, incoming, nativeRestored, reader, draft.sessionID));
|
|
6390
7444
|
} else if (localCut && cut && incoming) {
|
|
6391
|
-
|
|
7445
|
+
const legacy = await folds.read(draft.sessionID);
|
|
7446
|
+
if (legacy?.cutSeq === cut.seq && legacy.submittedSha === foldDigest(cut.data.summary ?? "")) {
|
|
6392
7447
|
const identity = await folds.observe({
|
|
6393
7448
|
sessionID: draft.sessionID,
|
|
6394
7449
|
cutSeq: cut.seq,
|
|
@@ -6403,7 +7458,7 @@ async function registerContext(context) {
|
|
|
6403
7458
|
checkpoint = structuredClone(identity.rendered ?? incoming);
|
|
6404
7459
|
submitted = identity.rendered ? identity.renderedSummary ?? identity.submitted : cut.data.summary ?? "";
|
|
6405
7460
|
}
|
|
6406
|
-
draft.messages.splice(0, draft.messages.length, ...restoreAfterCheckpoint({
|
|
7461
|
+
draft.messages.splice(0, draft.messages.length, ...await restoreAfterCheckpoint({
|
|
6407
7462
|
db,
|
|
6408
7463
|
reader,
|
|
6409
7464
|
draft,
|
|
@@ -6413,6 +7468,7 @@ async function registerContext(context) {
|
|
|
6413
7468
|
boundaryRepair
|
|
6414
7469
|
}));
|
|
6415
7470
|
}
|
|
7471
|
+
draft.messages = await retireInstructionMessages(draft.sessionID, reader, draft.messages);
|
|
6416
7472
|
messageTimes = readTimes(reader, draft.messages);
|
|
6417
7473
|
} finally {
|
|
6418
7474
|
reader.close();
|
|
@@ -6459,9 +7515,28 @@ async function registerContext(context) {
|
|
|
6459
7515
|
checkpointPassPermissions.delete(draft.sessionID);
|
|
6460
7516
|
checkpointInputEstimates.delete(draft.sessionID);
|
|
6461
7517
|
if (checkpoint?.id && checkpointPermission && replayHead === undefined) {
|
|
6462
|
-
|
|
6463
|
-
if (
|
|
6464
|
-
|
|
7518
|
+
let covered = upgradeCheckpointSequence === undefined;
|
|
7519
|
+
if (upgradeCheckpointSequence !== undefined) {
|
|
7520
|
+
const boundary = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(draft.sessionID);
|
|
7521
|
+
const source = openStoreReader();
|
|
7522
|
+
try {
|
|
7523
|
+
const through = upgradeCheckpointSequence - 1;
|
|
7524
|
+
const last = source.rowStampsThrough(draft.sessionID, through).filter((row) => RAW_MESSAGE_TYPES2.includes(row.type)).at(-1)?.seq;
|
|
7525
|
+
const end = boundary?.id ? source.sequenceForId(draft.sessionID, boundary.id) : undefined;
|
|
7526
|
+
covered = last === undefined || end !== undefined && end >= last;
|
|
7527
|
+
} finally {
|
|
7528
|
+
source.close();
|
|
7529
|
+
}
|
|
7530
|
+
}
|
|
7531
|
+
if (covered) {
|
|
7532
|
+
const checkpointID = checkpoint.id;
|
|
7533
|
+
const stripped = await folds.stripRecentContext(draft.sessionID, checkpointID);
|
|
7534
|
+
if (stripped?.rendered) {
|
|
7535
|
+
checkpoint = structuredClone(stripped.rendered);
|
|
7536
|
+
if (upgradeCheckpointSequence !== undefined)
|
|
7537
|
+
await nativeFoldReplay?.checkpointCovered(draft.sessionID, checkpointID);
|
|
7538
|
+
}
|
|
7539
|
+
}
|
|
6465
7540
|
}
|
|
6466
7541
|
stageOpenCodeV2TransformDecision({
|
|
6467
7542
|
sessionId: draft.sessionID,
|
|
@@ -6473,14 +7548,18 @@ async function registerContext(context) {
|
|
|
6473
7548
|
const head = replayHead !== undefined ? replayHead : checkpoint && submitted !== undefined ? { checkpoint, submitted } : null;
|
|
6474
7549
|
const servedHead = head && structuredClone(head);
|
|
6475
7550
|
const headApplied = head ? applyCheckpointHead(draft, head) : false;
|
|
6476
|
-
if (nativeMessages && !checkpoint) {
|
|
7551
|
+
if (nativeMessages && (!checkpoint || upgradeCheckpointSequence !== undefined)) {
|
|
6477
7552
|
try {
|
|
6478
|
-
|
|
7553
|
+
const state = db && getOrCreateSessionMeta(db, draft.sessionID);
|
|
7554
|
+
const boundary = db?.prepare("SELECT cached_m0_last_baseline_end_message_id AS id FROM session_meta WHERE session_id=?").get(draft.sessionID);
|
|
7555
|
+
await nativeFoldReplay?.capture(draft, nativeMessages, boundary?.id && state?.cachedM0Bytes ? { id: boundary.id, summary: state.cachedM0Bytes.toString("utf8") } : undefined);
|
|
6479
7556
|
} catch (error) {
|
|
6480
7557
|
nativeFoldReplay?.invalidate(draft.sessionID, true);
|
|
6481
7558
|
sessionLog2(draft.sessionID, "v2 host fold: optional capture unavailable", error);
|
|
6482
7559
|
}
|
|
6483
7560
|
}
|
|
7561
|
+
if (checkpointPermission === true && replayHead === undefined)
|
|
7562
|
+
admissionRebuildPasses.add(draft.sessionID);
|
|
6484
7563
|
const capturedSlot = getSlot(draft.sessionID);
|
|
6485
7564
|
if (capturedSlot && (!slotAtEntry || capturedSlot.capturedAt !== slotAtEntry.capturedAt || capturedSlot.captureSequence !== slotAtEntry.captureSequence || capturedSlot.jsonPrefix !== slotAtEntry.jsonPrefix)) {
|
|
6486
7565
|
lkgSystems.capture(draft.sessionID, capturedSlot, { system: systemAtEntry, checkpoint: checkpointAtEntry ?? null }, draft.system, headApplied ? servedHead : null);
|
|
@@ -6561,12 +7640,25 @@ async function registerContext(context) {
|
|
|
6561
7640
|
throw new V2ContextRefusal("Magic Context refused an oversized host checkpoint.");
|
|
6562
7641
|
};
|
|
6563
7642
|
await context.session.hook("context", (draft) => withSqliteTransformPass2(async () => {
|
|
7643
|
+
hostFoldIdle?.active(draft.sessionID);
|
|
6564
7644
|
const anchor = generateReplayAnchor(draft.messages);
|
|
6565
7645
|
try {
|
|
6566
7646
|
await runManagedContext(draft);
|
|
6567
7647
|
if (!compactionOff)
|
|
6568
7648
|
await refuseOversizedCheckpoint(draft);
|
|
7649
|
+
if (!deletedSessions.has(draft.sessionID) && admissionRebuildPasses.has(draft.sessionID)) {
|
|
7650
|
+
await nativeFoldReplay?.commitLegacyUpgrade(draft.sessionID, true);
|
|
7651
|
+
await nativeFoldReplay?.commitEditedAdmission(draft.sessionID);
|
|
7652
|
+
if (db && hostFoldIdle) {
|
|
7653
|
+
const meta = getOrCreateSessionMeta(db, draft.sessionID);
|
|
7654
|
+
if (computeHardCacheExpired(meta.cacheTtl, meta.lastResponseTime, Date.now()))
|
|
7655
|
+
hostFoldIdle.idle(draft.sessionID, meta.cacheTtl, meta.lastResponseTime);
|
|
7656
|
+
}
|
|
7657
|
+
}
|
|
6569
7658
|
} finally {
|
|
7659
|
+
admissionRebuildPasses.delete(draft.sessionID);
|
|
7660
|
+
nativeFoldReplay?.cancelLegacyUpgrade(draft.sessionID);
|
|
7661
|
+
nativeFoldReplay?.cancelEditedAdmission(draft.sessionID);
|
|
6570
7662
|
checkpointInputEstimates.delete(draft.sessionID);
|
|
6571
7663
|
checkpointPassPermissions.delete(draft.sessionID);
|
|
6572
7664
|
}
|
|
@@ -6695,6 +7787,7 @@ async function registerContext(context) {
|
|
|
6695
7787
|
return {
|
|
6696
7788
|
async dispose() {
|
|
6697
7789
|
messageTimesCache.clear();
|
|
7790
|
+
hostFoldIdle?.dispose();
|
|
6698
7791
|
usageController.abort();
|
|
6699
7792
|
await hiddenCompletionExecutor?.dispose();
|
|
6700
7793
|
await usageDone;
|