@cortexkit/opencode-magic-context 0.49.30 → 0.49.32

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.
Files changed (79) hide show
  1. package/dist/auto-search-worker.js +4 -4
  2. package/dist/chunk-embedding-write-worker.js +1 -1
  3. package/dist/{compartment-chunk-embedding-qgp0tbf7.js → compartment-chunk-embedding-5q5gj67r.js} +1 -1
  4. package/dist/{context-vnfr6d7t.js → context-n27jdyyh.js} +150 -19
  5. package/dist/{embedding-backfill-mms9nb0h.js → embedding-backfill-0jgtqxen.js} +3 -3
  6. package/dist/features/magic-context/chunk-scope-repair-revision.d.ts +4 -0
  7. package/dist/features/magic-context/chunk-scope-repair-revision.d.ts.map +1 -0
  8. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  9. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +3 -3
  10. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  11. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/task-gates.d.ts +2 -0
  13. package/dist/features/magic-context/dreamer/task-gates.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/verify.d.ts +13 -17
  15. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  16. package/dist/features/magic-context/message-index-async.d.ts +3 -0
  17. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  18. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  19. package/dist/features/magic-context/search.d.ts.map +1 -1
  20. package/dist/features/magic-context/storage-native-replay.d.ts +2 -0
  21. package/dist/features/magic-context/storage-native-replay.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/apply-operations.d.ts +11 -1
  23. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  24. package/dist/hooks/magic-context/auto-search-branch-index.fixture.d.ts +2 -0
  25. package/dist/hooks/magic-context/auto-search-branch-index.fixture.d.ts.map +1 -0
  26. package/dist/hooks/magic-context/auto-search-worker-client.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  28. package/dist/hooks/magic-context/tag-messages.d.ts +2 -0
  29. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  30. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +2 -0
  31. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/transform.d.ts +11 -0
  33. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  34. package/dist/{index-gxkhzmjq.js → index-2743x98y.js} +65 -2
  35. package/dist/{index-adr4vfys.js → index-2agkcr3y.js} +2 -2
  36. package/dist/{index-ekzzw66a.js → index-3drcgsnf.js} +74 -385
  37. package/dist/index-94ef0qe2.js +429 -0
  38. package/dist/{index-pe6b4bhs.js → index-as2amvn3.js} +1 -1
  39. package/dist/{index-k0dpkyn7.js → index-bzwh06cp.js} +4 -3
  40. package/dist/{index-vzz570j8.js → index-g0kqnc6y.js} +13 -4
  41. package/dist/{index-vtz789ex.js → index-qr2mb02j.js} +16 -5
  42. package/dist/{index-vnn5405n.js → index-rfxzazzy.js} +1 -1
  43. package/dist/{index-69gd2scx.js → index-t6b3px80.js} +2 -2
  44. package/dist/{index-mm93m7y6.js → index-v7287tzq.js} +47 -7
  45. package/dist/index.js +16 -14
  46. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  47. package/dist/{project-embedding-registry-cg281d9j.js → project-embedding-registry-6yex0r9f.js} +2 -2
  48. package/dist/{recomp-orchestrator-w3pjp33d.js → recomp-orchestrator-6ncc6wrw.js} +6 -6
  49. package/dist/{search-fbaz1m8r.js → search-040pac3a.js} +6 -5
  50. package/dist/shared/tag-transcript.d.ts +4 -1
  51. package/dist/shared/tag-transcript.d.ts.map +1 -1
  52. package/dist/shared/transcript.d.ts +3 -1
  53. package/dist/shared/transcript.d.ts.map +1 -1
  54. package/dist/{transform-postprocess-phase-6ccazq85.js → transform-postprocess-phase-wvt1k03d.js} +7 -6
  55. package/dist/v2/auto-search-worker.js +4 -4
  56. package/dist/v2/chunk-embedding-write-worker.js +1 -1
  57. package/dist/v2/{compartment-chunk-embedding-63dzs31c.js → compartment-chunk-embedding-rc31e6md.js} +1 -1
  58. package/dist/v2/{context-wx4sfhgr.js → context-ehews84p.js} +229 -286
  59. package/dist/v2/{embedding-backfill-35k6czrr.js → embedding-backfill-f43hd8y6.js} +3 -3
  60. package/dist/v2/fold/owner.d.ts +4 -0
  61. package/dist/v2/fold/owner.d.ts.map +1 -1
  62. package/dist/v2/hooks/context.d.ts.map +1 -1
  63. package/dist/v2/hooks/types.d.ts +3 -0
  64. package/dist/v2/hooks/types.d.ts.map +1 -1
  65. package/dist/v2/{project-embedding-registry-p1p10ks7.js → project-embedding-registry-1x5qe2fy.js} +2 -2
  66. package/dist/v2/{recomp-orchestrator-wb28kr9k.js → recomp-orchestrator-3r9kcs61.js} +5 -5
  67. package/dist/v2/{search-q3jjw6zp.js → search-q3wkpe8t.js} +5 -5
  68. package/dist/v2/{server-p0snacz3.js → server-2aasmpsp.js} +1 -1
  69. package/dist/v2/{server-k33t88h3.js → server-4n176b5m.js} +4 -3
  70. package/dist/v2/{server-zh3esb0z.js → server-ab8017gw.js} +65 -2
  71. package/dist/v2/{server-4sn3at8p.js → server-h1byrhwx.js} +47 -7
  72. package/dist/v2/{server-42nebt63.js → server-n14edf07.js} +336 -25
  73. package/dist/v2/{server-ph300d6m.js → server-tkdabx8q.js} +1 -1
  74. package/dist/v2/server.js +2 -2
  75. package/dist/v2/{wrapup-orchestrator-2t0pdqzm.js → wrapup-orchestrator-ddmvbkra.js} +5 -5
  76. package/dist/{wrapup-orchestrator-kjmkms5g.js → wrapup-orchestrator-fyvyzcbm.js} +7 -7
  77. package/package.json +1 -1
  78. package/src/shared/tag-transcript.ts +34 -5
  79. package/src/shared/transcript.ts +1 -1
@@ -304,7 +304,7 @@ import {
304
304
  startCompartmentAgent,
305
305
  setRecompStarting2,
306
306
  setRecompTerminal2
307
- } from "./server-k33t88h3.js";
307
+ } from "./server-4n176b5m.js";
308
308
  import {
309
309
  resolveHistorianModel2
310
310
  } from "./server-5kym00ag.js";
@@ -712,13 +712,34 @@ import {
712
712
  import {
713
713
  cleanSearchText,
714
714
  matchedSearchSnippet,
715
- getLastIndexedOrdinal,
716
- getMessageIndexReconciliationStartOrdinal,
717
- isMessageIndexReconciledThrough,
718
- clearIndexedMessages,
719
- indexMessagesAfterOrdinal
715
+ getLastIndexedOrdinal
720
716
  } from "./server-hwag0khr.js";
721
717
  import"./server-awr8qa4c.js";
718
+ import {
719
+ getMessageIndexEpoch,
720
+ isMessageIndexSearchable,
721
+ scheduleReconciliation,
722
+ scheduleClearAndReindex,
723
+ getMessageIndexQueueHeapStats,
724
+ renderSingleStoreMigrationRequiredRefusal,
725
+ SingleStoreMigrationRequiredError,
726
+ singleStoreMigrationRequiredFailure,
727
+ projectNeedsSingleStoreMigration,
728
+ STORE_AHEAD_OF_BINARY_CODE,
729
+ storeAheadOfBinaryFailure,
730
+ TRANSFORM_PAGE_UPLOAD_TIMEOUT_MS,
731
+ transformColdStartExecuteTimeoutMs,
732
+ getDefaultSubcConnectionFile,
733
+ isModuleTransportGenerationChangedResult,
734
+ SubcModuleTransport,
735
+ indexCommitsForProject,
736
+ embedUnembeddedCommits,
737
+ createUnifiedSearchDiagnostics2,
738
+ parseIdShapedQuery2,
739
+ resolveMemoriesByIdsForSearch2,
740
+ unifiedSearch2,
741
+ formatSearchResults2
742
+ } from "./server-n14edf07.js";
722
743
  import {
723
744
  embedPauseBySession,
724
745
  embedRunStateBySession,
@@ -748,7 +769,7 @@ import {
748
769
  embedSessionCompartmentChunks2,
749
770
  getEmbeddingCoverageStatus2,
750
771
  getAutoEmbeddingSessionCoverage2
751
- } from "./server-zh3esb0z.js";
772
+ } from "./server-ab8017gw.js";
752
773
  import {
753
774
  SubcClient,
754
775
  connectionFileExists,
@@ -759,7 +780,7 @@ import {
759
780
  } from "./server-ab1g0wn9.js";
760
781
  import {
761
782
  deleteChunkEmbedBackoffForSession2
762
- } from "./server-4sn3at8p.js";
783
+ } from "./server-h1byrhwx.js";
763
784
  import {
764
785
  registerOwnRpcServerInstance,
765
786
  rpcPortDir,
@@ -825,7 +846,7 @@ import {
825
846
  readGitFileChangeTimesSince,
826
847
  verificationFileExists,
827
848
  normalizeVerificationFiles
828
- } from "./server-ph300d6m.js";
849
+ } from "./server-tkdabx8q.js";
829
850
  import {
830
851
  deriveTriggerBudget2,
831
852
  deriveHistorianChunkTokens2,
@@ -859,7 +880,7 @@ import {
859
880
  } from "./server-vr4szghm.js";
860
881
  import {
861
882
  cosineSimilarity
862
- } from "./server-p0snacz3.js";
883
+ } from "./server-2aasmpsp.js";
863
884
  import {
864
885
  computeCueContentHash,
865
886
  hasMuralCueColumns,
@@ -897,26 +918,6 @@ import {
897
918
  flushIgnoredMessages2,
898
919
  sendStatusNotification2
899
920
  } from "./server-qc915kw2.js";
900
- import {
901
- renderSingleStoreMigrationRequiredRefusal,
902
- SingleStoreMigrationRequiredError,
903
- singleStoreMigrationRequiredFailure,
904
- projectNeedsSingleStoreMigration,
905
- STORE_AHEAD_OF_BINARY_CODE,
906
- storeAheadOfBinaryFailure,
907
- TRANSFORM_PAGE_UPLOAD_TIMEOUT_MS,
908
- transformColdStartExecuteTimeoutMs,
909
- getDefaultSubcConnectionFile,
910
- isModuleTransportGenerationChangedResult,
911
- SubcModuleTransport,
912
- indexCommitsForProject,
913
- embedUnembeddedCommits,
914
- createUnifiedSearchDiagnostics2,
915
- parseIdShapedQuery2,
916
- resolveMemoriesByIdsForSearch2,
917
- unifiedSearch2,
918
- formatSearchResults2
919
- } from "./server-42nebt63.js";
920
921
  import {
921
922
  resolvePromptContext2
922
923
  } from "./server-fmsr7v69.js";
@@ -1739,234 +1740,6 @@ function summarizeManualDream(summary) {
1739
1740
  `);
1740
1741
  }
1741
1742
 
1742
- // src/features/magic-context/message-index-async.ts
1743
- var indexCancellations = new Map;
1744
- var sessionEpochs = new Map;
1745
- var workerMeasurements = new WeakMap;
1746
- function isDatabaseLockedError(error) {
1747
- if (!error || typeof error !== "object")
1748
- return false;
1749
- const e = error;
1750
- if (typeof e.code === "string") {
1751
- if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
1752
- return true;
1753
- }
1754
- if (typeof e.message === "string") {
1755
- if (/database is locked/i.test(e.message))
1756
- return true;
1757
- if (/sqlite_(busy|locked)/i.test(e.message))
1758
- return true;
1759
- }
1760
- return false;
1761
- }
1762
- var RECONCILIATION_BATCH_SIZE = 100;
1763
-
1764
- class MagicContextMessageIndexHeapHolder {
1765
- reconciledSessions = new Set;
1766
- reconciledSnapshots = new Map;
1767
- stalledSessions = new Set;
1768
- reconciliationScheduledSessions = new Set;
1769
- clearAndReindexScheduledSessions = new Map;
1770
- sessionLocks = new Map;
1771
- incrementalTimers = new Map;
1772
- pendingIncrementalKeys = new Set;
1773
- completedIncrementalKeys = new Set;
1774
- activeReconcilerBuffers = new Map;
1775
- }
1776
- var heapHolder = new MagicContextMessageIndexHeapHolder;
1777
- function clearCompletedIncrementalKeys(sessionId) {
1778
- const prefix = `${sessionId}\x00`;
1779
- for (const key of heapHolder.completedIncrementalKeys) {
1780
- if (key.startsWith(prefix))
1781
- heapHolder.completedIncrementalKeys.delete(key);
1782
- }
1783
- }
1784
- var PREPARE_RETRY_MS = 60000;
1785
- async function sourceReady(source, sessionId) {
1786
- const prepare = source?.prepare;
1787
- return typeof prepare === "function" ? prepare(sessionId) : true;
1788
- }
1789
- function defer(fn) {
1790
- const immediate = globalThis.setImmediate;
1791
- if (typeof immediate === "function") {
1792
- inRootAsyncContext2(() => immediate(fn));
1793
- return;
1794
- }
1795
- inRootAsyncContext2(() => setTimeout(fn, 0));
1796
- }
1797
- function yieldToEventLoop() {
1798
- return new Promise((resolve) => defer(resolve));
1799
- }
1800
- function runWithSessionLock(sessionId, operation) {
1801
- const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
1802
- const run = previous.catch(() => {
1803
- return;
1804
- }).then(async () => {
1805
- await operation();
1806
- });
1807
- heapHolder.sessionLocks.set(sessionId, run);
1808
- run.finally(() => {
1809
- if (heapHolder.sessionLocks.get(sessionId) === run) {
1810
- heapHolder.sessionLocks.delete(sessionId);
1811
- }
1812
- }).catch(() => {
1813
- return;
1814
- });
1815
- return run;
1816
- }
1817
- function logIndexingError(sessionId, action, error) {
1818
- if (isDatabaseLockedError(error)) {
1819
- sessionLog2(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
1820
- return;
1821
- }
1822
- sessionLog2(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
1823
- log2(`[message-index-async] ${action} failed for ${sessionId}:`, error);
1824
- }
1825
- function serializedMessageBytes(messages) {
1826
- try {
1827
- return Buffer.byteLength(JSON.stringify(messages));
1828
- } catch {
1829
- return 0;
1830
- }
1831
- }
1832
- function logReconciliationStall(sessionId, reason) {
1833
- if (heapHolder.stalledSessions.has(sessionId))
1834
- return;
1835
- heapHolder.stalledSessions.add(sessionId);
1836
- sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
1837
- }
1838
- async function reconcileSessionIndex(db, sessionId, readMessages) {
1839
- if (!await sourceReady(readMessages, sessionId)) {
1840
- logReconciliationStall(sessionId, "raw message reader is not ready");
1841
- return false;
1842
- }
1843
- await runWithSessionLock(sessionId, async () => {
1844
- if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId))
1845
- return;
1846
- let fallbackSnapshot = null;
1847
- try {
1848
- const fullReader = typeof readMessages === "function" ? readMessages : null;
1849
- const revision = readMessages.getRevision?.(sessionId);
1850
- const previous = heapHolder.reconciledSnapshots.get(sessionId);
1851
- const finalWatermark = previous && revision === previous.revision ? previous.count : revision !== undefined && readMessages.getCountAfterRevision ? previous && revision > previous.revision ? previous.count + readMessages.getCountAfterRevision(sessionId, previous.revision, revision) : readMessages.getCountAfterRevision(sessionId, -1, revision) : readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
1852
- let cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
1853
- let after = cursor === previous?.count ? previous.after : undefined;
1854
- while (cursor < finalWatermark) {
1855
- const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
1856
- const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
1857
- const retainedMessages = fallbackSnapshot ?? messages;
1858
- heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
1859
- withSqliteBackgroundWriter2(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd));
1860
- const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
1861
- if (nextCursor <= cursor)
1862
- break;
1863
- cursor = nextCursor;
1864
- const last = messages.at(-1);
1865
- after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
1866
- if (cursor < finalWatermark) {
1867
- await yieldToEventLoop();
1868
- }
1869
- }
1870
- if (isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
1871
- heapHolder.reconciledSessions.add(sessionId);
1872
- if (revision !== undefined) {
1873
- if (!after && finalWatermark > 0 && readMessages.readPage) {
1874
- const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
1875
- if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
1876
- after = { timeCreated: last.createdAt, id: last.id };
1877
- }
1878
- heapHolder.reconciledSnapshots.set(sessionId, {
1879
- revision,
1880
- count: finalWatermark,
1881
- after
1882
- });
1883
- }
1884
- } else {
1885
- logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
1886
- }
1887
- } finally {
1888
- heapHolder.activeReconcilerBuffers.delete(sessionId);
1889
- }
1890
- });
1891
- return true;
1892
- }
1893
- function scheduleReconciliation(db, sessionId, readMessages) {
1894
- if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
1895
- return;
1896
- }
1897
- heapHolder.reconciliationScheduledSessions.add(sessionId);
1898
- scheduleAfterBootQuiet(() => {
1899
- defer(() => {
1900
- let appendedDuringReconciliation = false;
1901
- const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
1902
- reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
1903
- if (ran) {
1904
- const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
1905
- appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
1906
- return;
1907
- }
1908
- inRootAsyncContext2(() => setTimeout(() => {
1909
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
1910
- scheduleReconciliation(db, sessionId, readMessages);
1911
- }, PREPARE_RETRY_MS)).unref?.();
1912
- }).catch((error) => {
1913
- logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
1914
- if (isDatabaseLockedError(error))
1915
- inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
1916
- }).finally(() => {
1917
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
1918
- if (appendedDuringReconciliation)
1919
- scheduleReconciliation(db, sessionId, readMessages);
1920
- });
1921
- });
1922
- });
1923
- }
1924
- function scheduleClearAndReindex(db, sessionId, readMessages) {
1925
- heapHolder.reconciledSessions.delete(sessionId);
1926
- heapHolder.reconciledSnapshots.delete(sessionId);
1927
- heapHolder.reconciliationScheduledSessions.delete(sessionId);
1928
- clearCompletedIncrementalKeys(sessionId);
1929
- const existing = heapHolder.clearAndReindexScheduledSessions.get(sessionId);
1930
- if (existing) {
1931
- existing.source = readMessages;
1932
- return;
1933
- }
1934
- const pending = { source: readMessages };
1935
- heapHolder.clearAndReindexScheduledSessions.set(sessionId, pending);
1936
- scheduleAfterBootQuiet(() => {
1937
- defer(() => {
1938
- let cleared = false;
1939
- runWithSessionLock(sessionId, () => {
1940
- if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) !== pending)
1941
- return;
1942
- heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
1943
- heapHolder.reconciledSessions.delete(sessionId);
1944
- heapHolder.reconciledSnapshots.delete(sessionId);
1945
- clearCompletedIncrementalKeys(sessionId);
1946
- clearIndexedMessages(db, sessionId);
1947
- cleared = true;
1948
- }).then(() => cleared ? reconcileSessionIndex(db, sessionId, pending.source) : undefined).catch((error) => {
1949
- heapHolder.reconciledSessions.delete(sessionId);
1950
- if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) === pending)
1951
- heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
1952
- logIndexingError(sessionId, "clear and reindex", error);
1953
- });
1954
- });
1955
- });
1956
- }
1957
- function getMessageIndexQueueHeapStats() {
1958
- return {
1959
- queueLength: heapHolder.reconciliationScheduledSessions.size + heapHolder.incrementalTimers.size + heapHolder.pendingIncrementalKeys.size,
1960
- reconciliationScheduled: heapHolder.reconciliationScheduledSessions.size,
1961
- incrementalTimers: heapHolder.incrementalTimers.size,
1962
- pendingIncremental: heapHolder.pendingIncrementalKeys.size,
1963
- activeSessionLocks: heapHolder.sessionLocks.size,
1964
- completedIncrementalKeys: heapHolder.completedIncrementalKeys.size,
1965
- activeBufferMessages: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + messages.length, 0),
1966
- activeBufferBytes: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + serializedMessageBytes(messages), 0)
1967
- };
1968
- }
1969
-
1970
1743
  // src/shared/model-cache-ttl.ts
1971
1744
  var MODEL_CACHE_LIFETIMES = [
1972
1745
  {
@@ -4328,6 +4101,8 @@ class AutoSearchBusyError extends Error {
4328
4101
  }
4329
4102
  }
4330
4103
  async function searchAutoHint(db, sessionId, projectPath, query, options, entry = new URL(new URL(import.meta.url).pathname.endsWith(".ts") ? "./auto-search-worker.ts" : "./auto-search-worker.js", import.meta.url)) {
4104
+ const messageIndexEpoch = getMessageIndexEpoch(sessionId);
4105
+ const messageIndexWasSearchable = isMessageIndexSearchable(sessionId);
4331
4106
  const {
4332
4107
  rerankConfig: _rerankConfig,
4333
4108
  rerankClient: _rerankClient,
@@ -4336,7 +4111,8 @@ async function searchAutoHint(db, sessionId, projectPath, query, options, entry
4336
4111
  captureRerankLanes: _captureRerankLanes,
4337
4112
  ...hintOptions
4338
4113
  } = options;
4339
- return executeAutoSearchWorker(db, sessionId, projectPath, query, { ...hintOptions, explicitSearch: false, rerank: false }, entry, "search");
4114
+ const results = await executeAutoSearchWorker(db, sessionId, projectPath, query, { ...hintOptions, explicitSearch: false, rerank: false }, entry, "search");
4115
+ return messageIndexWasSearchable && isMessageIndexSearchable(sessionId) && getMessageIndexEpoch(sessionId) === messageIndexEpoch ? results : results.filter((result) => result.source !== "message");
4340
4116
  }
4341
4117
  var pendingBackfills = new WeakMap;
4342
4118
  var searchWorkers = new WeakMap;
@@ -5812,16 +5588,47 @@ function getDreamTaskBacklog(db, projectPath, task, options = {}) {
5812
5588
  }
5813
5589
  }
5814
5590
  var backlogCaches = new WeakMap;
5591
+ var displayBacklogCaches = new WeakMap;
5592
+ var DISPLAY_BACKLOG_MAX_AGE_MS = 60000;
5815
5593
  function getDreamTaskBacklogs(db, projectPath, tasks = CANONICAL_DREAM_TASKS, options = {}) {
5816
5594
  if (tasks.length === 0)
5817
5595
  return {};
5818
5596
  if (!isKnownAutocommit(db)) {
5819
5597
  backlogCaches.delete(db);
5598
+ displayBacklogCaches.delete(db);
5820
5599
  const result = {};
5821
5600
  for (const task of tasks)
5822
5601
  result[task] = getDreamTaskBacklog(db, projectPath, task, options);
5823
5602
  return result;
5824
5603
  }
5604
+ if (options.display) {
5605
+ let entries = displayBacklogCaches.get(db);
5606
+ if (!entries) {
5607
+ entries = new Map;
5608
+ displayBacklogCaches.set(db, entries);
5609
+ }
5610
+ const optionKey = (value) => value === undefined ? "omitted" : value === null ? "null" : `number:${value}`;
5611
+ const key = JSON.stringify([
5612
+ projectPath,
5613
+ tasks,
5614
+ optionKey(options.lastRunAt),
5615
+ optionKey(options.retrospectiveWatermarkMs)
5616
+ ]);
5617
+ const now = Date.now();
5618
+ const cached = entries.get(key);
5619
+ if (cached && now < cached.expiresAt && now >= cached.expiresAt - DISPLAY_BACKLOG_MAX_AGE_MS)
5620
+ return structuredClone(cached.value);
5621
+ const value = {};
5622
+ for (const task of tasks)
5623
+ value[task] = getDreamTaskBacklog(db, projectPath, task, options);
5624
+ if (entries.size >= 256)
5625
+ entries.delete(entries.keys().next().value);
5626
+ entries.set(key, {
5627
+ expiresAt: now + DISPLAY_BACKLOG_MAX_AGE_MS,
5628
+ value: structuredClone(value)
5629
+ });
5630
+ return value;
5631
+ }
5825
5632
  let cache = backlogCaches.get(db);
5826
5633
  if (!cache) {
5827
5634
  cache = {
@@ -7640,6 +7447,7 @@ function prepareLegacyToolSkeletonConversions(db, sessionId, targets, options =
7640
7447
  });
7641
7448
  };
7642
7449
  const rows = readRows(db);
7450
+ options.prepareRemovals?.(rows);
7643
7451
  const converted = new Map;
7644
7452
  for (const row of rows) {
7645
7453
  const target = targets.get(row.tagNumber);
@@ -11990,6 +11798,7 @@ async function runPostTransformPhase(args) {
11990
11798
  emergencyReclaimedTokens,
11991
11799
  droppedCount,
11992
11800
  emergency,
11801
+ prefixMutationPermitted: isCacheBustingPass,
11993
11802
  bustedThisPass,
11994
11803
  prefixTrimStatus: deliveredPrefix?.prefixTrimStatus ?? null,
11995
11804
  thinkingBindingRecovery,
@@ -13431,7 +13240,7 @@ var MODULE_PAGE_MAX_BYTES = SUBC_MAX_FRAME_BODY_BYTES - MODULE_PAGE_ENVELOPE_HEA
13431
13240
  var MODULE_ITEM_CONTINUATION_CHUNK_BYTES = 64 * 1024;
13432
13241
  var MODULE_ITEM_CONTINUATION_KEY = "__shadow_item_continuation";
13433
13242
  var MODULE_ORDINAL_PAGE_SIZE = 500;
13434
- function yieldToEventLoop2() {
13243
+ function yieldToEventLoop() {
13435
13244
  return new Promise((resolve) => setTimeout(resolve, 0));
13436
13245
  }
13437
13246
  function canonicalJson(value) {
@@ -13521,7 +13330,7 @@ async function resolveOrdinalsForModule(args) {
13521
13330
  pageEnds.push({ anchor: pageAnchor, entryCount: entries.length });
13522
13331
  if (page.length < MODULE_ORDINAL_PAGE_SIZE)
13523
13332
  break;
13524
- await yieldToEventLoop2();
13333
+ await yieldToEventLoop();
13525
13334
  }
13526
13335
  return { entries, end: pageAnchor, pageEnds };
13527
13336
  };
@@ -19656,6 +19465,15 @@ function createTransform(deps) {
19656
19465
  db,
19657
19466
  sessionID: sessionId
19658
19467
  }) : undefined;
19468
+ const hostEstimate = deps.hostInputEstimate?.(sessionId);
19469
+ const hostOverWindow = fullFeatureMode && !compactionOff && resolvedContextLimit !== undefined && resolvedContextLimit > 0 && hostEstimate !== undefined && Number.isFinite(hostEstimate.tokens) && Number.isFinite(hostEstimate.pressureTokens) && hostEstimate.tokens > resolvedContextLimit;
19470
+ if (hostOverWindow) {
19471
+ contextUsageEarly = {
19472
+ inputTokens: Math.max(contextUsageEarly.inputTokens, hostEstimate.pressureTokens),
19473
+ percentage: Math.max(100, contextUsageEarly.percentage, hostEstimate.pressureTokens / resolvedContextLimit * 100)
19474
+ };
19475
+ usagePercentageSynthetic = true;
19476
+ }
19659
19477
  let unmanagedOverWindowPass = null;
19660
19478
  const unmanagedOverWindowCarried = unmanagedOverWindowSessions.has(sessionId);
19661
19479
  if (fullFeatureMode && !compactionOff && typeof resolvedContextLimit === "number" && resolvedContextLimit > 0 && (unmanagedOverWindowCarried || isFirstTransformPassForSession && getLastCompartmentEndMessage(db, sessionId) < 0 && getMaxDroppedTagNumber2(db, sessionId) === 0)) {
@@ -20198,7 +20016,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
20198
20016
  bustReason: calibrationBustReason,
20199
20017
  onAdopt: (message) => sessionLog2(sessionId, message)
20200
20018
  });
20201
- let contextUsageFromEstimate = false;
20019
+ let contextUsageFromEstimate = hostOverWindow;
20202
20020
  if (contextUsage.inputTokens <= 0 && protectionCacheBustingPass) {
20203
20021
  const overflowRecoveryPass = usagePercentageSynthetic || emergencyRecoveryArmed;
20204
20022
  const savedProviderReading = overflowRecoveryPass ? null : savedProviderReadingForPass({
@@ -20752,6 +20570,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
20752
20570
  sessionId,
20753
20571
  systemPromptHash: sessionMeta.systemPromptHash
20754
20572
  });
20573
+ deps.onPassPermission?.(sessionId, postTransformResult.prefixMutationPermitted);
20755
20574
  };
20756
20575
  const timedTransform = (input, output) => withTransformTimingSummary(() => transform(input, output));
20757
20576
  return Object.assign(timedTransform, {
@@ -23258,7 +23077,7 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
23258
23077
  const dreamerProgress = projectIdentity ? liveSessionState?.dreamerProgressByProject?.get(projectIdentity) ?? null : null;
23259
23078
  if (projectIdentity) {
23260
23079
  try {
23261
- dreamerBacklog = getDreamTaskBacklogs(db, projectIdentity, CANONICAL_DREAM_TASKS.filter((task) => smartNotesEnabled || task !== "evaluate-smart-notes"));
23080
+ dreamerBacklog = getDreamTaskBacklogs(db, projectIdentity, CANONICAL_DREAM_TASKS.filter((task) => smartNotesEnabled || task !== "evaluate-smart-notes"), { display: true });
23262
23081
  } catch {}
23263
23082
  }
23264
23083
  if (projectIdentity) {
@@ -24010,7 +23829,7 @@ function registerRpcHandlers(rpcServer, args) {
24010
23829
  const db = readDatabase();
24011
23830
  if (!db)
24012
23831
  return { ok: false, error: "db unavailable" };
24013
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-wb28kr9k.js"));
23832
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-3r9kcs61.js"));
24014
23833
  const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-x5nzy34v.js"));
24015
23834
  log2(`[rpc] recomp requested for session ${sessionId}`);
24016
23835
  if (!args.client && !args.hiddenCompletionExecutor) {
@@ -24095,7 +23914,7 @@ function registerRpcHandlers(rpcServer, args) {
24095
23914
  const db = readDatabase();
24096
23915
  if (!db)
24097
23916
  return { ok: false, error: "db unavailable" };
24098
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-2t0pdqzm.js"));
23917
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-ddmvbkra.js"));
24099
23918
  const model = liveSessionState.liveModelBySession.get(sessionId);
24100
23919
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
24101
23920
  const ctx = {
@@ -25208,8 +25027,14 @@ class FoldOwner {
25208
25027
  async observe(args) {
25209
25028
  return this.serial(args.sessionID, async () => {
25210
25029
  let state = await this.read(args.sessionID);
25030
+ if (state?.rendered && state.rendered.id !== args.rendered.id)
25031
+ state = undefined;
25211
25032
  let changed = !state;
25212
- const renderedSha = foldDigest(JSON.stringify(args.rendered));
25033
+ const observedSha = foldDigest(JSON.stringify(args.rendered));
25034
+ const rendered = structuredClone(args.rendered);
25035
+ if (state?.withoutRecentContext && state.withoutRecentContext === rendered.id)
25036
+ stripCheckpointRecentContext(rendered, args.summary);
25037
+ const renderedSha = foldDigest(JSON.stringify(rendered));
25213
25038
  if (!state) {
25214
25039
  args.onHard("boot_recovery");
25215
25040
  state = {
@@ -25220,10 +25045,10 @@ class FoldOwner {
25220
25045
  };
25221
25046
  }
25222
25047
  const reason = args.cutSeq < state.watermark ? "host_cut_before_watermark" : state.submittedSha !== foldDigest(args.summary) || state.renderedSha && state.renderedSha !== renderedSha ? "host_rerender" : undefined;
25223
- if (reason && state.rejectedSha !== renderedSha) {
25048
+ if (reason && state.rejectedSha !== observedSha) {
25224
25049
  args.onHard(reason);
25225
25050
  state.reason = reason;
25226
- state.rejectedSha = renderedSha;
25051
+ state.rejectedSha = observedSha;
25227
25052
  changed = true;
25228
25053
  }
25229
25054
  if (state.cutSeq === undefined && args.cutSeq >= state.watermark) {
@@ -25231,7 +25056,7 @@ class FoldOwner {
25231
25056
  changed = true;
25232
25057
  }
25233
25058
  if (!state.rendered && reason !== "host_cut_before_watermark") {
25234
- state.rendered = structuredClone(args.rendered);
25059
+ state.rendered = rendered;
25235
25060
  state.renderedSha = renderedSha;
25236
25061
  state.renderedSummary = args.summary;
25237
25062
  changed = true;
@@ -25241,6 +25066,50 @@ class FoldOwner {
25241
25066
  return state;
25242
25067
  });
25243
25068
  }
25069
+ async stripRecentContext(sessionID, checkpointID) {
25070
+ return this.serial(sessionID, async () => {
25071
+ const state = await this.read(sessionID);
25072
+ if (!state?.rendered || state.rendered.id !== checkpointID)
25073
+ return;
25074
+ if (state.withoutRecentContext === checkpointID)
25075
+ return state;
25076
+ if (!stripCheckpointRecentContext(state.rendered, state.renderedSummary ?? state.submitted))
25077
+ return state;
25078
+ state.withoutRecentContext = checkpointID;
25079
+ state.renderedSha = foldDigest(JSON.stringify(state.rendered));
25080
+ await this.storage.set(this.key(sessionID), state);
25081
+ return state;
25082
+ });
25083
+ }
25084
+ }
25085
+ function stripCheckpointRecentContext(message, summary) {
25086
+ let changed = false;
25087
+ for (const part of message.content) {
25088
+ if (part.type !== "text" || typeof part.text !== "string")
25089
+ continue;
25090
+ const summaryStart = part.text.indexOf("<summary>");
25091
+ if (summaryStart < 0)
25092
+ continue;
25093
+ const summaryText = part.text.indexOf(summary, summaryStart + "<summary>".length);
25094
+ if (summaryText < 0)
25095
+ continue;
25096
+ const start = part.text.indexOf("</summary>", summaryText + summary.length) + "</summary>".length;
25097
+ const end = part.text.lastIndexOf("</conversation-checkpoint>");
25098
+ if (start < "</summary>".length || end < start)
25099
+ continue;
25100
+ const suffix = part.text.slice(start, end);
25101
+ if (!/^\s*<recent-context>[\s\S]*<\/recent-context>\s*$/.test(suffix))
25102
+ continue;
25103
+ part.text = `${part.text.slice(0, start)}
25104
+ ${part.text.slice(end)}`;
25105
+ changed = true;
25106
+ }
25107
+ if (changed && message.metadata && typeof message.metadata === "object") {
25108
+ const metadata = { ...message.metadata };
25109
+ delete metadata.recent;
25110
+ message.metadata = metadata;
25111
+ }
25112
+ return changed;
25244
25113
  }
25245
25114
 
25246
25115
  // src/v2/fold/memory-cache.ts
@@ -32200,7 +32069,6 @@ function parseMapMemoriesManifest(text) {
32200
32069
  }
32201
32070
  function validateMapMemoriesManifest(text, expectedIds) {
32202
32071
  const parsed = parseMapMemoriesManifest(text);
32203
- assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
32204
32072
  assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
32205
32073
  return parsed;
32206
32074
  }
@@ -34414,8 +34282,7 @@ function parsePartialVerifyManifest(text, expectedIds) {
34414
34282
  var VERIFY_BATCH_SIZE = 5;
34415
34283
  var VERIFY_TOKENS_PER_MEMORY = 1e5;
34416
34284
  var VERIFY_RUN_TOKEN_BUDGET = 2500000;
34417
- var VERIFY_RUN_SLICE_MS = 240000;
34418
- var VERIFY_IN_FLIGHT_GRACE_MS = 120000;
34285
+ var VERIFY_BATCH_DEFAULT_MS = 240000;
34419
34286
  function verifyBatchTokenBudget(size, configured) {
34420
34287
  return Math.min(configured ?? Number.MAX_SAFE_INTEGER, size * VERIFY_TOKENS_PER_MEMORY);
34421
34288
  }
@@ -34445,8 +34312,8 @@ function validateVerifyCompletion(messages, text, expectedIds, responseText = te
34445
34312
  }
34446
34313
  var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
34447
34314
  var VERIFY_BATCH_FLOOR_MS = 30000;
34448
- function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
34449
- return Math.min(remainingMs, VERIFY_RUN_SLICE_MS);
34315
+ function computeVerifyBatchSliceMs(remainingMs, batchesRemaining) {
34316
+ return Math.min(remainingMs, Math.max(VERIFY_BATCH_DEFAULT_MS, remainingMs / Math.max(1, batchesRemaining)));
34450
34317
  }
34451
34318
  function closeBroadCycle(args, cycleStartAt) {
34452
34319
  if (!args.forceBroad || cycleStartAt === undefined)
@@ -34470,7 +34337,6 @@ async function runVerify(args) {
34470
34337
  }
34471
34338
  async function runVerifyWithCooldown(args) {
34472
34339
  const runStartedAt = Date.now();
34473
- const sliceDeadline = runStartedAt + VERIFY_RUN_SLICE_MS;
34474
34340
  const result = {
34475
34341
  verified: 0,
34476
34342
  updated: 0,
@@ -34518,12 +34384,10 @@ async function runVerifyWithCooldown(args) {
34518
34384
  try {
34519
34385
  for (let i = 0;i < batches.length; i += 1) {
34520
34386
  const now = Date.now();
34521
- const startCutoff = Math.min(args.deadline, sliceDeadline);
34522
- const hardStop = Math.min(args.deadline, sliceDeadline + VERIFY_IN_FLIGHT_GRACE_MS);
34523
- const remainingMs = Math.max(0, hardStop - now);
34524
- if (now >= startCutoff) {
34387
+ const remainingMs = Math.max(0, args.deadline - now);
34388
+ if (now >= args.deadline) {
34525
34389
  result.stopReason = "deadline";
34526
- log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — the run deadline passed ${now - startCutoff}ms ago`);
34390
+ log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — the run deadline passed ${now - args.deadline}ms ago`);
34527
34391
  break;
34528
34392
  }
34529
34393
  if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
@@ -35462,7 +35326,7 @@ function createDreamTaskExecutor(deps) {
35462
35326
  return { status: "failed", transient: true, error };
35463
35327
  }
35464
35328
  const processed = result.mapped + result.independent;
35465
- if (processed > 0) {
35329
+ if (processed > 0 || result.failure === undefined) {
35466
35330
  const progress = `map-memories: committed ${processed} mapping(s) (mapped ${result.mapped}, independent ${result.independent}); ${result.remaining} remain`;
35467
35331
  recordRun("completed", null, { progress });
35468
35332
  return { status: "completed" };
@@ -53183,6 +53047,28 @@ ${baseline}
53183
53047
  draft.messages.splice(0, draft.messages.length, checkpoint, ...draft.messages.filter((message) => message !== first));
53184
53048
  return true;
53185
53049
  }
53050
+ function estimateCheckpointRequest(draft) {
53051
+ let toolDefinitionTokens = 0;
53052
+ for (const tool of Object.values(draft.tools)) {
53053
+ const schema = JSON.stringify(tool.input);
53054
+ if (schema === undefined)
53055
+ throw new Error("Checkpoint request has an unserializable tool schema");
53056
+ toolDefinitionTokens += estimateTokens(tool.description) + estimateTokens(schema);
53057
+ }
53058
+ const estimateDraft = {
53059
+ ...draft,
53060
+ messages: draft.messages.map((message) => HEAD_IDS.some((id) => message.id === id) ? { ...message, id: undefined } : message)
53061
+ };
53062
+ return estimateFinalWireInputTokens({
53063
+ messages: adaptPayload(estimateDraft).messages,
53064
+ toolDefinitionTokens,
53065
+ systemPromptTokens: estimateTokens(JSON.stringify(draft.system)),
53066
+ providerID: draft.model.providerID,
53067
+ modelID: draft.model.id,
53068
+ agentName: draft.agent,
53069
+ sessionId: draft.sessionID
53070
+ });
53071
+ }
53186
53072
  var HIDDEN_SESSION_ERROR_GRACE_MS = 50;
53187
53073
  var STORE_POOL_DISPOSE_WAIT_MS = 1000;
53188
53074
  function isBlockingV2TransformError(error) {
@@ -54015,7 +53901,7 @@ async function registerContext(context) {
54015
53901
  await context.session.hook("compaction", async (draft) => {
54016
53902
  const hiddenSummary = hiddenChildHook.compactionSummary(draft.sessionID, draft.agent);
54017
53903
  if (hiddenSummary !== undefined) {
54018
- draft.result = { summary: hiddenSummary };
53904
+ draft.result = { summary: hiddenSummary, metadata: { keepID: undefined } };
54019
53905
  return;
54020
53906
  }
54021
53907
  if (compactionOff)
@@ -54040,7 +53926,7 @@ async function registerContext(context) {
54040
53926
  previousCut: reader.latestCompaction(draft.sessionID),
54041
53927
  summary
54042
53928
  })) {
54043
- draft.result = { summary };
53929
+ draft.result = { summary, metadata: { keepID: undefined } };
54044
53930
  return;
54045
53931
  }
54046
53932
  }
@@ -54056,7 +53942,7 @@ async function registerContext(context) {
54056
53942
  materialize: () => moduleBaseline ?? materialize(draft)
54057
53943
  });
54058
53944
  sessionLog2(draft.sessionID, `v2 compaction hook: fired answered=true source=${source}`);
54059
- draft.result = { summary: fold.submitted };
53945
+ draft.result = { summary: fold.submitted, metadata: { keepID: undefined } };
54060
53946
  } catch (cause) {
54061
53947
  await refuseBeforeProvider(context.session, draft.sessionID, "compaction-fold", cause);
54062
53948
  throw new V2ContextRefusal("Magic Context could not preserve the host checkpoint.", {
@@ -54102,6 +53988,8 @@ async function registerContext(context) {
54102
53988
  ...args.messages.filter((message) => message !== args.incoming)
54103
53989
  ];
54104
53990
  };
53991
+ const checkpointPassPermissions = new Map;
53992
+ const checkpointInputEstimates = new Map;
54105
53993
  const initializeTransform = (database) => transform ??= createTransform({
54106
53994
  ...createV2TransformFeatureDeps(config, compactionOff, directory, embeddings.ensureRegistered),
54107
53995
  cacheTtlConfig: config.cache_ttl,
@@ -54111,6 +53999,10 @@ async function registerContext(context) {
54111
53999
  tagger,
54112
54000
  ...createV2ThresholdDeps(config),
54113
54001
  contextUsageMap: usage,
54002
+ hostInputEstimate: (sessionID) => checkpointInputEstimates.get(sessionID),
54003
+ onPassPermission: (sessionID, permission) => {
54004
+ checkpointPassPermissions.set(sessionID, permission);
54005
+ },
54114
54006
  compactionOff,
54115
54007
  storeGeneration: "v2",
54116
54008
  normalizeRestoredAssistantText: (text, providerID) => stripCopiedTagNotation(text, providerID === "anthropic"),
@@ -54532,6 +54424,21 @@ async function registerContext(context) {
54532
54424
  }
54533
54425
  const mapped = adaptPayload(draft, admitted, messageTimes, anchorTimesOnly);
54534
54426
  bindSystemDateRequestIdentity(mapped, draft);
54427
+ checkpointPassPermissions.delete(draft.sessionID);
54428
+ checkpointInputEstimates.delete(draft.sessionID);
54429
+ if (checkpoint && submitted !== undefined) {
54430
+ const projected = structuredClone(checkpoint);
54431
+ if (stripCheckpointRecentContext(projected, submitted)) {
54432
+ const estimate = estimateCheckpointRequest({
54433
+ ...draft,
54434
+ messages: [checkpoint, ...draft.messages]
54435
+ });
54436
+ checkpointInputEstimates.set(draft.sessionID, {
54437
+ tokens: estimate.tokens,
54438
+ pressureTokens: estimate.pressureTokens ?? estimate.tokens
54439
+ });
54440
+ }
54441
+ }
54535
54442
  await createMessagesTransformHandler({
54536
54443
  magicContext: { "experimental.chat.messages.transform": transform },
54537
54444
  compactionOff,
@@ -54540,6 +54447,14 @@ async function registerContext(context) {
54540
54447
  rustReplayParticipant: () => transform?.getRustReplayParticipant() ?? null
54541
54448
  })({}, mapped);
54542
54449
  mapped.commit();
54450
+ const checkpointPermission = checkpointPassPermissions.get(draft.sessionID);
54451
+ checkpointPassPermissions.delete(draft.sessionID);
54452
+ checkpointInputEstimates.delete(draft.sessionID);
54453
+ if (checkpoint?.id && checkpointPermission && replayHead === undefined) {
54454
+ const stripped = await folds.stripRecentContext(draft.sessionID, checkpoint.id);
54455
+ if (stripped?.rendered)
54456
+ checkpoint = structuredClone(stripped.rendered);
54457
+ }
54543
54458
  stageOpenCodeV2TransformDecision({
54544
54459
  sessionId: draft.sessionID,
54545
54460
  responseAfterSequence
@@ -54618,17 +54533,45 @@ async function registerContext(context) {
54618
54533
  }
54619
54534
  }
54620
54535
  };
54536
+ const refuseOversizedCheckpoint = async (draft) => {
54537
+ const hasCheckpoint = draft.messages.some((message) => message.content.some((part) => part.type === "text" && typeof part.text === "string" && part.text.startsWith("<conversation-checkpoint>")));
54538
+ const limit = draft.model.limit?.input ?? draft.model.limit?.context;
54539
+ if (!hasCheckpoint || !limit)
54540
+ return;
54541
+ let estimate;
54542
+ try {
54543
+ estimate = estimateCheckpointRequest(draft);
54544
+ } catch (cause) {
54545
+ await refuseBeforeProvider(context.session, draft.sessionID, "checkpoint-fit-estimate", cause);
54546
+ throw new V2ContextRefusal("Magic Context could not size the host checkpoint.", {
54547
+ cause
54548
+ });
54549
+ }
54550
+ if (estimate.tokens <= limit)
54551
+ return;
54552
+ await refuseBeforeProvider(context.session, draft.sessionID, "checkpoint-over-window");
54553
+ throw new V2ContextRefusal("Magic Context refused an oversized host checkpoint.");
54554
+ };
54621
54555
  await context.session.hook("context", (draft) => withSqliteTransformPass2(async () => {
54622
54556
  const anchor = generateReplayAnchor(draft.messages);
54623
- await runManagedContext(draft);
54557
+ try {
54558
+ await runManagedContext(draft);
54559
+ if (!compactionOff)
54560
+ await refuseOversizedCheckpoint(draft);
54561
+ } finally {
54562
+ checkpointInputEstimates.delete(draft.sessionID);
54563
+ checkpointPassPermissions.delete(draft.sessionID);
54564
+ }
54624
54565
  if (!compactionOff)
54625
54566
  generateReplay.capture(draft, anchor);
54626
54567
  else
54627
54568
  sessionLog2(draft.sessionID, "generate replay capture skipped: compaction-disabled");
54628
54569
  }));
54629
54570
  await context.session.hook("generate", async (draft) => {
54630
- if (!compactionOff && !deletedSessions.has(draft.sessionID))
54571
+ if (!compactionOff && !deletedSessions.has(draft.sessionID)) {
54631
54572
  generateReplay.apply(draft);
54573
+ await refuseOversizedCheckpoint(draft);
54574
+ }
54632
54575
  });
54633
54576
  withoutSqliteTransformPass2(() => warmModelLimitCacheFromCatalog(context));
54634
54577
  const rpcLiveSessionState = createV2RpcLiveSessionState({