@retaw106/mmc-oc 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2 -2
- package/dist/config/deprecated-config.d.ts +4 -0
- package/dist/config/deprecated-config.d.ts.map +1 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/project-security.d.ts +2 -2
- package/dist/config/schema/magic-context.d.ts +3 -3
- package/dist/config/schema/magic-context.d.ts.map +1 -1
- package/dist/config-init.js +2 -2
- package/dist/{context-mrvm92n8.js → context-wt7g4f8k.js} +1641 -1543
- package/dist/{derive-budgets-rjjz5f7y.js → derive-budgets-s1p37t2g.js} +2 -2
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/historian-failure-reason.d.ts +7 -0
- package/dist/features/magic-context/historian-failure-reason.d.ts.map +1 -0
- package/dist/features/magic-context/message-index-async.d.ts +21 -3
- package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
- package/dist/features/magic-context/message-index.d.ts +7 -1
- package/dist/features/magic-context/message-index.d.ts.map +1 -1
- package/dist/features/magic-context/migrations.d.ts.map +1 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts +7 -1
- package/dist/features/magic-context/pi-content-decisions.d.ts.map +1 -1
- package/dist/features/magic-context/search.d.ts +29 -0
- package/dist/features/magic-context/search.d.ts.map +1 -1
- package/dist/features/magic-context/storage-clone.d.ts +2 -0
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-compartment-history-version.d.ts +4 -0
- package/dist/features/magic-context/storage-compartment-history-version.d.ts.map +1 -0
- package/dist/features/magic-context/storage-db.d.ts +1 -1
- package/dist/features/magic-context/storage-db.d.ts.map +1 -1
- package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +23 -5
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts +7 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-session-tables.d.ts +5 -1
- package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts +50 -0
- package/dist/features/magic-context/storage-tag-identity-revision.d.ts.map +1 -0
- package/dist/features/magic-context/storage-tags.d.ts +155 -5
- package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
- package/dist/features/magic-context/tagger.d.ts +2 -0
- package/dist/features/magic-context/tagger.d.ts.map +1 -1
- package/dist/features/magic-context/transform-decision-log.d.ts +3 -0
- package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts +2 -0
- package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -1
- package/dist/hooks/magic-context/apply-operations.d.ts +7 -0
- package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
- package/dist/hooks/magic-context/auto-search-runner.d.ts +2 -2
- package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
- package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/history-boundary-repair.d.ts +11 -2
- package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
- package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts +3 -1
- package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts +10 -13
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts +62 -0
- package/dist/hooks/magic-context/lkg-recovery-fence.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts +38 -0
- package/dist/hooks/magic-context/lkg-recovery-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/lkg-replay.d.ts +16 -9
- package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-slot.d.ts +141 -2
- package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
- package/dist/hooks/magic-context/opaque-thinking.d.ts +12 -0
- package/dist/hooks/magic-context/opaque-thinking.d.ts.map +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts +1 -0
- package/dist/hooks/magic-context/pass-outcome.d.ts.map +1 -1
- package/dist/hooks/magic-context/pending-materialization.d.ts +8 -0
- package/dist/hooks/magic-context/pending-materialization.d.ts.map +1 -0
- package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
- package/dist/hooks/magic-context/provider-visible-parts.d.ts +45 -0
- package/dist/hooks/magic-context/provider-visible-parts.d.ts.map +1 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts +22 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-db.d.ts +3 -0
- package/dist/hooks/magic-context/read-session-db.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-formatting.d.ts +5 -0
- package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts +123 -1
- package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-true-raw-tokens.d.ts.map +1 -1
- package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -1
- package/dist/hooks/magic-context/sentinel.d.ts +41 -1
- package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts +8 -0
- package/dist/hooks/magic-context/strict-thinking-prefix.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +38 -24
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/system-date-refresh.d.ts +29 -0
- package/dist/hooks/magic-context/system-date-refresh.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts +6 -0
- package/dist/hooks/magic-context/system-prompt-dates.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts +47 -0
- package/dist/hooks/magic-context/system-prompt-delivery.d.ts.map +1 -0
- package/dist/hooks/magic-context/system-prompt-hash.d.ts +18 -5
- package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +19 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts +14 -0
- package/dist/hooks/magic-context/tag-owner-warmup.d.ts.map +1 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts +35 -0
- package/dist/hooks/magic-context/token-count-exact.d.ts.map +1 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts +2 -0
- package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +7 -0
- package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
- package/dist/hooks/magic-context/transform.d.ts +21 -4
- package/dist/hooks/magic-context/transform.d.ts.map +1 -1
- package/dist/index-18yrysyj.js +1477 -0
- package/dist/{index-g2z2k5m4.js → index-3gj1ak4c.js} +2 -2
- package/dist/{index-5cep2r9n.js → index-5ty9rnbx.js} +60 -258
- package/dist/{index-amycb7b1.js → index-a5mw0xp3.js} +3 -3
- package/dist/{index-1j34a56j.js → index-czba8tw3.js} +266 -32
- package/dist/{index-qbkzdkk0.js → index-k59af64t.js} +6 -2
- package/dist/{index-53g38ggt.js → index-kmbme1v1.js} +1 -1
- package/dist/{index-5b7x80ec.js → index-kw21z5pe.js} +6055 -3973
- package/dist/{index-33gprt9g.js → index-yjv8dpht.js} +1 -1
- package/dist/{index-btp5tdc8.js → index-z2w1eq3y.js} +840 -456
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +114 -2
- package/dist/{message-time-backfill-phrwp2fz.js → message-time-backfill-sykevdax.js} +3 -3
- package/dist/plugin/rpc-handlers.d.ts.map +1 -1
- package/dist/{read-session-chunk-2xm4sc4y.js → read-session-chunk-863d6c06.js} +6 -4
- package/dist/recomp-orchestrator-wrjy3qym.js +21 -0
- package/dist/{safe-notification-target-ph3xd1ve.js → safe-notification-target-1jkf0m82.js} +2 -2
- package/dist/{send-session-notification-rnc4nrsr.js → send-session-notification-cz6ev088.js} +5 -5
- package/dist/shared/auto-search-lifecycle.d.ts +14 -0
- package/dist/shared/auto-search-lifecycle.d.ts.map +1 -1
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/models-dev-cache.d.ts.map +1 -1
- package/dist/shared/models-dev-temperature.d.ts +18 -0
- package/dist/shared/models-dev-temperature.d.ts.map +1 -0
- package/dist/shared/processed-image-eligibility.d.ts +22 -0
- package/dist/shared/processed-image-eligibility.d.ts.map +1 -0
- package/dist/shared/project-directory-key.d.ts +16 -0
- package/dist/shared/project-directory-key.d.ts.map +1 -1
- package/dist/shared/recovery-reasoning-prefix.d.ts +9 -0
- package/dist/shared/recovery-reasoning-prefix.d.ts.map +1 -0
- package/dist/shared/sqlite.d.ts +33 -1
- package/dist/shared/sqlite.d.ts.map +1 -1
- package/dist/shared/stable-json.d.ts.map +1 -1
- package/dist/shared/storage-file-mutex.d.ts +9 -0
- package/dist/shared/storage-file-mutex.d.ts.map +1 -0
- package/dist/shared/storage-permissions.d.ts +6 -0
- package/dist/shared/storage-permissions.d.ts.map +1 -1
- package/dist/shared/subagent-temperature.d.ts +46 -0
- package/dist/shared/subagent-temperature.d.ts.map +1 -0
- package/dist/shared/tag-owner-id.d.ts +1 -0
- package/dist/shared/tag-owner-id.d.ts.map +1 -1
- package/dist/shared/tag-transcript.d.ts +9 -0
- package/dist/shared/tag-transcript.d.ts.map +1 -1
- package/dist/shared/window-geometry.d.ts +9 -66
- package/dist/shared/window-geometry.d.ts.map +1 -1
- package/dist/standalone-plugin-marker.d.ts +8 -0
- package/dist/standalone-plugin-marker.d.ts.map +1 -0
- package/dist/tools/ctx-expand/search-archive.d.ts +4 -0
- package/dist/tools/ctx-expand/search-archive.d.ts.map +1 -0
- package/dist/tools/ctx-expand/tools.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/constants.d.ts +1 -2
- package/dist/tools/ctx-reduce/constants.d.ts.map +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts +1 -1
- package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
- package/dist/v2/hooks/context.d.ts +1 -1
- package/dist/v2/hooks/context.d.ts.map +1 -1
- package/dist/v2/hooks/copied-tag-notation.d.ts +19 -0
- package/dist/v2/hooks/copied-tag-notation.d.ts.map +1 -0
- package/dist/v2/hooks/generate.d.ts +9 -2
- package/dist/v2/hooks/generate.d.ts.map +1 -1
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/hooks/system-prompt-response.d.ts +5 -0
- package/dist/v2/hooks/system-prompt-response.d.ts.map +1 -0
- package/dist/v2/server.d.ts.map +1 -1
- package/dist/v2/server.js +34550 -30855
- package/dist/web/main.js +373 -19
- package/dist/{wrapup-orchestrator-yknks3ad.js → wrapup-orchestrator-bmybc5p5.js} +10 -10
- package/package.json +1 -1
- package/src/config/deprecated-config.ts +18 -0
- package/src/config/index.test.ts +13 -37
- package/src/config/index.ts +2 -2
- package/src/config/project-security.ts +3 -3
- package/src/config/schema/magic-context.ts +10 -6
- package/src/shared/auto-search-lifecycle.ts +43 -0
- package/src/shared/logger.ts +10 -2
- package/src/shared/models-dev-cache.ts +1 -7
- package/src/shared/models-dev-temperature.ts +107 -0
- package/src/shared/processed-image-eligibility.test.ts +68 -0
- package/src/shared/processed-image-eligibility.ts +41 -0
- package/src/shared/processed-image-position-review.json +20 -0
- package/src/shared/processed-image-position-review.test.ts +19 -0
- package/src/shared/project-directory-key.ts +20 -0
- package/src/shared/recovery-reasoning-prefix.test.ts +34 -0
- package/src/shared/recovery-reasoning-prefix.ts +35 -0
- package/src/shared/sqlite-acquisition-routing.test.ts +4 -3
- package/src/shared/sqlite-foreground-wait.test.ts +68 -0
- package/src/shared/sqlite-pass-scope.test.ts +4 -4
- package/src/shared/sqlite-writer-diagnostics.test.ts +52 -12
- package/src/shared/sqlite.ts +380 -39
- package/src/shared/stable-json.ts +37 -7
- package/src/shared/storage-file-mutex.test.ts +50 -0
- package/src/shared/storage-file-mutex.ts +130 -0
- package/src/shared/storage-permissions.ts +46 -0
- package/src/shared/subagent-temperature.ts +110 -0
- package/src/shared/tag-owner-id.ts +13 -0
- package/src/shared/tag-transcript.ts +118 -0
- package/src/shared/window-geometry.test.ts +102 -236
- package/src/shared/window-geometry.ts +23 -413
- package/dist/index-ramz5kkm.js +0 -514
- package/dist/recomp-orchestrator-frmwj9hz.js +0 -21
- package/src/shared/__fixtures__/window-overlay.v1.json +0 -337
|
@@ -58,11 +58,23 @@ import {
|
|
|
58
58
|
searchMemoriesFTSUnion,
|
|
59
59
|
clearMemoryVerifications,
|
|
60
60
|
queueMemoryMutation,
|
|
61
|
+
scheduleAfterBootQuiet,
|
|
62
|
+
BoundedSessionMap,
|
|
61
63
|
registerOwnRpcServerInstance,
|
|
62
64
|
rpcPortDir,
|
|
63
65
|
rpcPortFilePath,
|
|
64
66
|
parseRpcPortFile,
|
|
65
67
|
inspectProcessesAsync,
|
|
68
|
+
dirtyLkgRecoveryRevision,
|
|
69
|
+
ownsLkgDirtyFence,
|
|
70
|
+
invalidateCleanLkgRecoveryFence,
|
|
71
|
+
getLastIndexedOrdinal,
|
|
72
|
+
getIndexedMessageIdAtOrdinal,
|
|
73
|
+
getIndexedMessageCorpusSize,
|
|
74
|
+
getMessageIndexReconciliationStartOrdinal,
|
|
75
|
+
isMessageIndexReconciledThrough,
|
|
76
|
+
clearIndexedMessages,
|
|
77
|
+
indexMessagesAfterOrdinal,
|
|
66
78
|
acquireCompartmentLease,
|
|
67
79
|
releaseCompartmentLeaseBestEffort,
|
|
68
80
|
isCompartmentLeaseHeld,
|
|
@@ -74,15 +86,6 @@ import {
|
|
|
74
86
|
getLastCompartmentEndMessage,
|
|
75
87
|
getLastCompartmentEndMessageId,
|
|
76
88
|
getAuthorityManagedMarker,
|
|
77
|
-
getLastIndexedOrdinal,
|
|
78
|
-
getIndexedMessageIdAtOrdinal,
|
|
79
|
-
getIndexedMessageCorpusSize,
|
|
80
|
-
getMessageIndexReconciliationStartOrdinal,
|
|
81
|
-
isMessageIndexReconciledThrough,
|
|
82
|
-
clearIndexedMessages,
|
|
83
|
-
indexMessagesAfterOrdinal,
|
|
84
|
-
layoutLkgPrefix,
|
|
85
|
-
assembleLkgPrefix,
|
|
86
89
|
getTemporalDecisions,
|
|
87
90
|
observeTemporalDecisions,
|
|
88
91
|
freezeTemporalDecisions,
|
|
@@ -123,7 +126,7 @@ import {
|
|
|
123
126
|
casChannel2NudgeClaim,
|
|
124
127
|
getAutoSearchHintDecisions,
|
|
125
128
|
appendAutoSearchHintDecision,
|
|
126
|
-
|
|
129
|
+
flushAutoSearchHintDecisionRetirement,
|
|
127
130
|
getPersistedTodoPermissionDenied,
|
|
128
131
|
setPersistedTodoPermissionDenied,
|
|
129
132
|
getPersistedTodoSyntheticAnchor,
|
|
@@ -152,32 +155,66 @@ import {
|
|
|
152
155
|
addTrailingBlankDecisions,
|
|
153
156
|
demoteTrailingBlankKeepDecisions,
|
|
154
157
|
addStaleReduceStrippedIds,
|
|
158
|
+
getProcessedImageMarkers,
|
|
155
159
|
addProcessedImageStrippedIds,
|
|
156
160
|
getPendingCompactionMarkerState,
|
|
157
161
|
getCompactionMarkerHealth,
|
|
158
162
|
loadPostprocessReplaySnapshot,
|
|
159
163
|
clearPendingCompactionMarkerStateIf,
|
|
164
|
+
getPendingPiCompactionMarkerState,
|
|
165
|
+
clearPendingPiCompactionMarkerStateIf,
|
|
166
|
+
logPiCompactionMarkerClear,
|
|
160
167
|
setSessionWorkMetrics,
|
|
161
168
|
getObservedEpochFloor,
|
|
162
169
|
resolveEpochFloorForPass,
|
|
163
|
-
|
|
170
|
+
providerResponseFailed,
|
|
171
|
+
isSuccessfulProviderCompletion,
|
|
172
|
+
rememberUnpublishedAutoSearchNoHint,
|
|
173
|
+
getUnpublishedAutoSearchNoHint,
|
|
174
|
+
forgetUnpublishedAutoSearchNoHint,
|
|
175
|
+
registerAutoSearchWork,
|
|
176
|
+
gaDatabasePath,
|
|
177
|
+
RAW_MESSAGE_TYPES,
|
|
178
|
+
V2StoreReaderPool,
|
|
179
|
+
getOrCreateSessionMeta,
|
|
180
|
+
updateSessionMeta,
|
|
181
|
+
advanceToolReclaimWatermark,
|
|
182
|
+
markSessionCleanupPending,
|
|
183
|
+
clearSession,
|
|
184
|
+
requestPendingMaterialization,
|
|
185
|
+
pendingMaterializationOrigin,
|
|
186
|
+
clearPendingMaterialization,
|
|
187
|
+
recordSystemPromptForRequest,
|
|
188
|
+
recordHeldHeadForRequest,
|
|
189
|
+
bindSystemPromptResponse,
|
|
190
|
+
isHeldHeadForRequest,
|
|
191
|
+
deferDeliveredSystemRefresh,
|
|
192
|
+
retirePendingSystemPromptDelivery,
|
|
193
|
+
lkgProviderInputTotal,
|
|
194
|
+
beginV2LkgRequest,
|
|
195
|
+
currentLkgRequestIdentity,
|
|
196
|
+
noteLkgProviderResponse,
|
|
197
|
+
clearLkgMeasuredRequest,
|
|
198
|
+
saveLkgSlotToDb,
|
|
199
|
+
loadPersistedLkgSlot,
|
|
200
|
+
pruneStaleLkgSlots,
|
|
201
|
+
resolveLkgModelKeys,
|
|
202
|
+
createLkgEntryProjector,
|
|
203
|
+
captureLkgSlot,
|
|
204
|
+
replayLkg,
|
|
205
|
+
noteUncertifiedNormalLkg,
|
|
206
|
+
lkgDirtyRevision,
|
|
207
|
+
readLkgRecoveryPrefix,
|
|
208
|
+
noteLkgHealthyPrefix,
|
|
164
209
|
beginLkgPass,
|
|
165
|
-
lkgContentFields,
|
|
166
|
-
lkgContentDigestFromFields,
|
|
167
|
-
memoizedLkgContentDigestFromFields,
|
|
168
|
-
exactReusablePrefix,
|
|
169
|
-
lkgContentDigest,
|
|
170
|
-
captureSlot,
|
|
171
210
|
getInMemorySlot,
|
|
172
211
|
getSlot,
|
|
173
212
|
dropSlot,
|
|
174
|
-
noteEntry,
|
|
175
213
|
getLkgSlotHeapStats,
|
|
176
214
|
TOOL_SWEEP_SCOPED_MARKER,
|
|
177
215
|
useScopedToolSweep,
|
|
178
216
|
createPreAdoptionToolSweepResolver,
|
|
179
217
|
copySessionStateForClone,
|
|
180
|
-
scheduleAfterBootQuiet,
|
|
181
218
|
getSchemaFenceRejection,
|
|
182
219
|
getMigrationOnOpenRefusal,
|
|
183
220
|
LATEST_SUPPORTED_VERSION,
|
|
@@ -186,14 +223,6 @@ import {
|
|
|
186
223
|
openDatabaseAsync,
|
|
187
224
|
isDatabasePersisted,
|
|
188
225
|
getDatabasePersistenceError,
|
|
189
|
-
gaDatabasePath,
|
|
190
|
-
RAW_MESSAGE_TYPES,
|
|
191
|
-
V2StoreReaderPool,
|
|
192
|
-
getOrCreateSessionMeta,
|
|
193
|
-
updateSessionMeta,
|
|
194
|
-
advanceToolReclaimWatermark,
|
|
195
|
-
markSessionCleanupPending,
|
|
196
|
-
clearSession,
|
|
197
226
|
getNoteByIdInScope,
|
|
198
227
|
getNotes,
|
|
199
228
|
addNote,
|
|
@@ -265,7 +294,7 @@ import {
|
|
|
265
294
|
recordHighPressureNoEligibleHead,
|
|
266
295
|
getActiveCompartmentRun,
|
|
267
296
|
startCompartmentAgent
|
|
268
|
-
} from "./index-
|
|
297
|
+
} from "./index-kw21z5pe.js";
|
|
269
298
|
import {
|
|
270
299
|
getHarness,
|
|
271
300
|
getDataDir,
|
|
@@ -273,14 +302,13 @@ import {
|
|
|
273
302
|
log,
|
|
274
303
|
sessionLog,
|
|
275
304
|
getLoggerDiagnostics
|
|
276
|
-
} from "./index-
|
|
305
|
+
} from "./index-k59af64t.js";
|
|
277
306
|
import {
|
|
278
307
|
shouldEnforcePrivateStoragePermissions,
|
|
279
308
|
ensureStorageDirectorySync,
|
|
280
309
|
writeStorageFileAtomicSync,
|
|
281
310
|
writeStorageFileAsync,
|
|
282
311
|
createStorageWriteStream,
|
|
283
|
-
setWindowOverlayPath,
|
|
284
312
|
hasTrustedAbsoluteWall,
|
|
285
313
|
applyProvenInputFloor,
|
|
286
314
|
isSaneLimit,
|
|
@@ -294,14 +322,11 @@ import {
|
|
|
294
322
|
deriveHistorianChunkTokens2,
|
|
295
323
|
resolveKnownHistorianContextLimit2,
|
|
296
324
|
resolveHistorianContextLimit2
|
|
297
|
-
} from "./index-
|
|
325
|
+
} from "./index-5ty9rnbx.js";
|
|
298
326
|
import {
|
|
299
327
|
normalizeProtectedToolName,
|
|
300
328
|
mergeProtectedTools,
|
|
301
329
|
isRecord,
|
|
302
|
-
detectLatestTurnThinkingMismatch,
|
|
303
|
-
isPrefixBoundThinkingModel,
|
|
304
|
-
detectOverflow,
|
|
305
330
|
protectedToolTagNumbers,
|
|
306
331
|
protectedToolTokenCount,
|
|
307
332
|
textMentionsRecentCommit,
|
|
@@ -311,6 +336,7 @@ import {
|
|
|
311
336
|
estimateTokens,
|
|
312
337
|
estimateFixedPromptTokens,
|
|
313
338
|
stripWellFormedLeadingTagPrefix,
|
|
339
|
+
stripPersistedAssistantText,
|
|
314
340
|
byteSize,
|
|
315
341
|
stripTagPrefix,
|
|
316
342
|
peelLeadingMcTagNotation,
|
|
@@ -348,6 +374,7 @@ import {
|
|
|
348
374
|
getPendingOpsCount,
|
|
349
375
|
clearPendingOps,
|
|
350
376
|
removePendingOp,
|
|
377
|
+
tagIdentityRevisionKey,
|
|
351
378
|
getRecentTagOwnerMessageIds,
|
|
352
379
|
AGE_RECLAIM_MIN_TOKENS,
|
|
353
380
|
getOldestActiveUnprotectedToolTags,
|
|
@@ -355,12 +382,17 @@ import {
|
|
|
355
382
|
getTriggerTagTokenUpperBound,
|
|
356
383
|
getActiveTagTokenTotalsByMessage,
|
|
357
384
|
getReasoningTokenEstimatesByMessage,
|
|
385
|
+
tryGetReasoningTokenEstimatesByMessage,
|
|
386
|
+
getMaxTagNumberByOwnerMessage,
|
|
387
|
+
scanTagOwnerSummary,
|
|
388
|
+
isTagOwnerSummaryReady,
|
|
358
389
|
tagTokenCountIsNull,
|
|
359
390
|
backfillTagTokenCounts,
|
|
360
391
|
insertTag,
|
|
361
392
|
updateTagStatus,
|
|
362
393
|
markWhitespaceAssistantTagInert,
|
|
363
394
|
getInertWhitespaceAssistantTags,
|
|
395
|
+
getInertWhitespaceAssistantTagsByNumbers,
|
|
364
396
|
updateTagDropMode,
|
|
365
397
|
updateCavemanDepth,
|
|
366
398
|
updateTagMessageId,
|
|
@@ -384,8 +416,6 @@ import {
|
|
|
384
416
|
pickNearestPriorOwner,
|
|
385
417
|
expandToolPart,
|
|
386
418
|
markHostUnservedRow,
|
|
387
|
-
extractInMemoryMessageViews,
|
|
388
|
-
buildInMemoryTailRawMessages,
|
|
389
419
|
estimateTrueRawMessageTokens,
|
|
390
420
|
stripSystemInjection,
|
|
391
421
|
isTextPart,
|
|
@@ -405,6 +435,9 @@ import {
|
|
|
405
435
|
wireContentBytes,
|
|
406
436
|
createFinalWireUsageTracker,
|
|
407
437
|
estimateFinalWireInputTokens,
|
|
438
|
+
detectLatestTurnThinkingMismatch,
|
|
439
|
+
isPrefixBoundThinkingModel,
|
|
440
|
+
detectOverflow,
|
|
408
441
|
modelAcceptsEmptyContent,
|
|
409
442
|
isAnthropicFamilyRoute,
|
|
410
443
|
neutralizeDroppedReasoningPart,
|
|
@@ -414,6 +447,7 @@ import {
|
|
|
414
447
|
variantChangeBustsProviderCache,
|
|
415
448
|
makeSentinel,
|
|
416
449
|
makeWholeMessageSentinel,
|
|
450
|
+
neutralizeWholeMessage,
|
|
417
451
|
isSentinel,
|
|
418
452
|
replaySentinelByMessageIds,
|
|
419
453
|
SKELETON_REAL_INPUT_MAX_BYTES,
|
|
@@ -425,11 +459,13 @@ import {
|
|
|
425
459
|
withRawSessionMessageCache2,
|
|
426
460
|
readRawSessionMessages2,
|
|
427
461
|
visitRawSessionMessages2,
|
|
462
|
+
prepareRawSessionOrdinals2,
|
|
428
463
|
primeTailRawMessageCache2,
|
|
429
464
|
primeInMemoryTailRawMessageCache2,
|
|
465
|
+
readRawSessionMessageIdOrdinalsForRange2,
|
|
430
466
|
readRawSessionMessageById2,
|
|
431
467
|
readSessionChunk2
|
|
432
|
-
} from "./index-
|
|
468
|
+
} from "./index-z2w1eq3y.js";
|
|
433
469
|
import {
|
|
434
470
|
getSqliteMemoryStats,
|
|
435
471
|
withSqliteBackgroundWriter,
|
|
@@ -437,8 +473,10 @@ import {
|
|
|
437
473
|
withoutSqliteTransformPass,
|
|
438
474
|
isTransientSqliteError,
|
|
439
475
|
SqliteAcquisitionBusyError,
|
|
440
|
-
withAsyncPrivilegedWriter
|
|
441
|
-
|
|
476
|
+
withAsyncPrivilegedWriter,
|
|
477
|
+
indexCoordinationInput,
|
|
478
|
+
withIndexChunk
|
|
479
|
+
} from "./index-czba8tw3.js";
|
|
442
480
|
import {
|
|
443
481
|
canonicalModelIdentity,
|
|
444
482
|
piModelRefToCanonical,
|
|
@@ -448,11 +486,14 @@ import {
|
|
|
448
486
|
resolveDecisionCalibration
|
|
449
487
|
} from "./index-x37vg474.js";
|
|
450
488
|
import {
|
|
489
|
+
extractInMemoryMessageViews,
|
|
490
|
+
buildInMemoryTailRawMessages,
|
|
451
491
|
openCodeDbExists,
|
|
452
492
|
withReadOnlySessionDb,
|
|
493
|
+
latestRealUserTurnIdFromOpenCodeDb,
|
|
453
494
|
getMessageTimesFromOpenCodeDb,
|
|
454
495
|
findLastAssistantModelFromOpenCodeDb
|
|
455
|
-
} from "./index-
|
|
496
|
+
} from "./index-18yrysyj.js";
|
|
456
497
|
import {
|
|
457
498
|
registerNotificationSink2,
|
|
458
499
|
pushNotification2,
|
|
@@ -460,18 +501,18 @@ import {
|
|
|
460
501
|
drainNotifications2,
|
|
461
502
|
isTuiConnected2
|
|
462
503
|
} from "./index-jdxxq8cz.js";
|
|
463
|
-
import"./index-
|
|
504
|
+
import"./index-kmbme1v1.js";
|
|
464
505
|
import {
|
|
465
506
|
getErrorMessage,
|
|
466
507
|
flushIgnoredMessages2,
|
|
467
508
|
sendStatusNotification2
|
|
468
|
-
} from "./index-
|
|
509
|
+
} from "./index-a5mw0xp3.js";
|
|
469
510
|
import {
|
|
470
511
|
resolveHistorianModel2
|
|
471
512
|
} from "./index-z2g20msd.js";
|
|
472
513
|
import {
|
|
473
514
|
logSlowWriteTransaction
|
|
474
|
-
} from "./index-
|
|
515
|
+
} from "./index-yjv8dpht.js";
|
|
475
516
|
|
|
476
517
|
// src/config/index.ts
|
|
477
518
|
import { existsSync as existsSync4 } from "node:fs";
|
|
@@ -1578,6 +1619,15 @@ function migrateLegacyAgentEnabledInMemory(rawConfig, warnings) {
|
|
|
1578
1619
|
return patched;
|
|
1579
1620
|
}
|
|
1580
1621
|
|
|
1622
|
+
// src/config/deprecated-config.ts
|
|
1623
|
+
var WINDOW_OVERLAY_PATH_DEPRECATION_WARNING = "models.window_overlay_path is deprecated and ignored; Fusiform no longer publishes window-overlay data, so this setting no longer changes model window geometry. Remove this key.";
|
|
1624
|
+
function warnDeprecatedWindowOverlayPath(config, warnings) {
|
|
1625
|
+
const models = config.models;
|
|
1626
|
+
if (typeof models === "object" && models !== null && Object.hasOwn(models, "window_overlay_path") && !warnings.includes(WINDOW_OVERLAY_PATH_DEPRECATION_WARNING)) {
|
|
1627
|
+
warnings.push(WINDOW_OVERLAY_PATH_DEPRECATION_WARNING);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1581
1631
|
// src/config/legacy-harness-blocks.ts
|
|
1582
1632
|
function isPlainObject(value) {
|
|
1583
1633
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1915,7 +1965,7 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
1915
1965
|
const models = projectRaw.models;
|
|
1916
1966
|
if (isPlainObject2(models) && "window_overlay_path" in models) {
|
|
1917
1967
|
delete models.window_overlay_path;
|
|
1918
|
-
warnings.push("Ignoring models.window_overlay_path from project config (
|
|
1968
|
+
warnings.push("Ignoring models.window_overlay_path from project config (deprecated; this setting no longer changes model window geometry).");
|
|
1919
1969
|
}
|
|
1920
1970
|
if ("language" in projectRaw) {
|
|
1921
1971
|
delete projectRaw.language;
|
|
@@ -2633,6 +2683,7 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
|
|
|
2633
2683
|
const configWithoutRemovedAgent = stripRemovedAgentConfig(rawConfig, preMigrationWarnings);
|
|
2634
2684
|
const migratedExperimental = migrateLegacyExperimental(configWithoutRemovedAgent, preMigrationWarnings);
|
|
2635
2685
|
const migrated = migrateLegacyAgentEnabledInMemory(migratedExperimental, preMigrationWarnings);
|
|
2686
|
+
warnDeprecatedWindowOverlayPath(migrated, preMigrationWarnings);
|
|
2636
2687
|
const parsed = MagicContextConfigSchema.safeParse(migrated);
|
|
2637
2688
|
const disabledHooks = Array.isArray(rawConfig.disabled_hooks) ? rawConfig.disabled_hooks.filter((value) => typeof value === "string") : undefined;
|
|
2638
2689
|
const command = typeof rawConfig.command === "object" && rawConfig.command !== null ? rawConfig.command : undefined;
|
|
@@ -2851,7 +2902,6 @@ function loadPluginConfigDetailed(directory, applyRuntimeGlobals = true) {
|
|
|
2851
2902
|
config.profile = profileResolution.activeProfile;
|
|
2852
2903
|
if (applyRuntimeGlobals) {
|
|
2853
2904
|
setOutputReserveConfig(config.output_reserve);
|
|
2854
|
-
setWindowOverlayPath(config.models?.window_overlay_path);
|
|
2855
2905
|
}
|
|
2856
2906
|
const leafValidationWarnings = [...config.configWarnings ?? []];
|
|
2857
2907
|
if (config.configWarnings?.length) {
|
|
@@ -4876,6 +4926,236 @@ function createOc2MaintenanceRunFactory(options) {
|
|
|
4876
4926
|
};
|
|
4877
4927
|
}
|
|
4878
4928
|
|
|
4929
|
+
// src/features/magic-context/message-index-async.ts
|
|
4930
|
+
function isDatabaseLockedError(error) {
|
|
4931
|
+
if (!error || typeof error !== "object")
|
|
4932
|
+
return false;
|
|
4933
|
+
const e = error;
|
|
4934
|
+
if (typeof e.code === "string") {
|
|
4935
|
+
if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
|
|
4936
|
+
return true;
|
|
4937
|
+
}
|
|
4938
|
+
if (typeof e.message === "string") {
|
|
4939
|
+
if (/database is locked/i.test(e.message))
|
|
4940
|
+
return true;
|
|
4941
|
+
if (/sqlite_(busy|locked)/i.test(e.message))
|
|
4942
|
+
return true;
|
|
4943
|
+
}
|
|
4944
|
+
return false;
|
|
4945
|
+
}
|
|
4946
|
+
var RECONCILIATION_BATCH_SIZE = 100;
|
|
4947
|
+
|
|
4948
|
+
class MagicContextMessageIndexHeapHolder {
|
|
4949
|
+
reconciledSessions = new Set;
|
|
4950
|
+
reconciliationScheduledSessions = new Set;
|
|
4951
|
+
clearAndReindexScheduledSessions = new Map;
|
|
4952
|
+
sessionLocks = new Map;
|
|
4953
|
+
incrementalTimers = new Map;
|
|
4954
|
+
pendingIncrementalKeys = new Set;
|
|
4955
|
+
completedIncrementalKeys = new Set;
|
|
4956
|
+
activeReconcilerBuffers = new Map;
|
|
4957
|
+
}
|
|
4958
|
+
var heapHolder = new MagicContextMessageIndexHeapHolder;
|
|
4959
|
+
function clearCompletedIncrementalKeys(sessionId) {
|
|
4960
|
+
const prefix = `${sessionId}\x00`;
|
|
4961
|
+
for (const key of heapHolder.completedIncrementalKeys) {
|
|
4962
|
+
if (key.startsWith(prefix))
|
|
4963
|
+
heapHolder.completedIncrementalKeys.delete(key);
|
|
4964
|
+
}
|
|
4965
|
+
}
|
|
4966
|
+
var sessionEpochs = new Map;
|
|
4967
|
+
var PREPARE_RETRY_MS = 60000;
|
|
4968
|
+
async function sourceReady(source, sessionId) {
|
|
4969
|
+
const prepare = source?.prepare;
|
|
4970
|
+
return typeof prepare === "function" ? prepare(sessionId) : true;
|
|
4971
|
+
}
|
|
4972
|
+
function defer(fn) {
|
|
4973
|
+
const immediate = globalThis.setImmediate;
|
|
4974
|
+
if (typeof immediate === "function") {
|
|
4975
|
+
immediate(fn);
|
|
4976
|
+
return;
|
|
4977
|
+
}
|
|
4978
|
+
setTimeout(fn, 0);
|
|
4979
|
+
}
|
|
4980
|
+
function yieldToEventLoop() {
|
|
4981
|
+
return new Promise((resolve) => defer(resolve));
|
|
4982
|
+
}
|
|
4983
|
+
function runWithSessionLock(sessionId, operation) {
|
|
4984
|
+
const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
4985
|
+
const run = previous.catch(() => {
|
|
4986
|
+
return;
|
|
4987
|
+
}).then(async () => {
|
|
4988
|
+
await operation();
|
|
4989
|
+
});
|
|
4990
|
+
heapHolder.sessionLocks.set(sessionId, run);
|
|
4991
|
+
run.finally(() => {
|
|
4992
|
+
if (heapHolder.sessionLocks.get(sessionId) === run) {
|
|
4993
|
+
heapHolder.sessionLocks.delete(sessionId);
|
|
4994
|
+
}
|
|
4995
|
+
}).catch(() => {
|
|
4996
|
+
return;
|
|
4997
|
+
});
|
|
4998
|
+
return run;
|
|
4999
|
+
}
|
|
5000
|
+
function logIndexingError(sessionId, action, error) {
|
|
5001
|
+
if (isDatabaseLockedError(error)) {
|
|
5002
|
+
sessionLog(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
|
|
5003
|
+
return;
|
|
5004
|
+
}
|
|
5005
|
+
sessionLog(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
5006
|
+
log(`[message-index-async] ${action} failed for ${sessionId}:`, error);
|
|
5007
|
+
}
|
|
5008
|
+
function serializedMessageBytes(messages) {
|
|
5009
|
+
try {
|
|
5010
|
+
return Buffer.byteLength(JSON.stringify(messages));
|
|
5011
|
+
} catch {
|
|
5012
|
+
return 0;
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
function detectIndexMisalignment(db, sessionId, cursor, finalWatermark, readMessages, fallbackSnapshot) {
|
|
5016
|
+
if (finalWatermark <= 0)
|
|
5017
|
+
return null;
|
|
5018
|
+
const indexedWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
5019
|
+
if (indexedWatermark > finalWatermark) {
|
|
5020
|
+
return `indexed watermark ${indexedWatermark} exceeds projection watermark ${finalWatermark}`;
|
|
5021
|
+
}
|
|
5022
|
+
if (cursor <= 0 || cursor > finalWatermark)
|
|
5023
|
+
return null;
|
|
5024
|
+
const indexedId = getIndexedMessageIdAtOrdinal(db, sessionId, cursor);
|
|
5025
|
+
if (indexedId === null)
|
|
5026
|
+
return null;
|
|
5027
|
+
const projectedId = readMessages.readPage ? readMessages.readPage(sessionId, cursor - 1, 1, finalWatermark)[0]?.id ?? null : fallbackSnapshot?.find((message) => message.ordinal === cursor)?.id ?? null;
|
|
5028
|
+
if (projectedId === null || projectedId === indexedId)
|
|
5029
|
+
return null;
|
|
5030
|
+
return `indexed id '${indexedId}' at ordinal ${cursor} but projection has '${projectedId}'`;
|
|
5031
|
+
}
|
|
5032
|
+
async function reconcileSessionIndex(db, sessionId, readMessages) {
|
|
5033
|
+
if (!await sourceReady(readMessages, sessionId))
|
|
5034
|
+
return false;
|
|
5035
|
+
await runWithSessionLock(sessionId, async () => {
|
|
5036
|
+
if (heapHolder.reconciledSessions.has(sessionId))
|
|
5037
|
+
return;
|
|
5038
|
+
let fallbackSnapshot = null;
|
|
5039
|
+
try {
|
|
5040
|
+
const fullReader = typeof readMessages === "function" ? readMessages : null;
|
|
5041
|
+
const finalWatermark = readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
|
|
5042
|
+
let cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
5043
|
+
let after;
|
|
5044
|
+
const misalignment = detectIndexMisalignment(db, sessionId, cursor, finalWatermark, readMessages, fallbackSnapshot);
|
|
5045
|
+
if (misalignment !== null) {
|
|
5046
|
+
sessionLog(sessionId, `message FTS index misaligned (${misalignment}); clearing for full re-index`);
|
|
5047
|
+
withSqliteBackgroundWriter(() => clearIndexedMessages(db, sessionId));
|
|
5048
|
+
cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
5049
|
+
}
|
|
5050
|
+
while (cursor < finalWatermark) {
|
|
5051
|
+
const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
|
|
5052
|
+
const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
|
|
5053
|
+
const retainedMessages = fallbackSnapshot ?? messages;
|
|
5054
|
+
heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
|
|
5055
|
+
await withIndexChunk(indexCoordinationInput(), () => withSqliteBackgroundWriter(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd)));
|
|
5056
|
+
const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
5057
|
+
if (nextCursor <= cursor)
|
|
5058
|
+
break;
|
|
5059
|
+
cursor = nextCursor;
|
|
5060
|
+
const last = messages.at(-1);
|
|
5061
|
+
after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
|
|
5062
|
+
if (cursor < finalWatermark) {
|
|
5063
|
+
await yieldToEventLoop();
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
if (isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
|
|
5067
|
+
heapHolder.reconciledSessions.add(sessionId);
|
|
5068
|
+
}
|
|
5069
|
+
} finally {
|
|
5070
|
+
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
5071
|
+
}
|
|
5072
|
+
});
|
|
5073
|
+
return true;
|
|
5074
|
+
}
|
|
5075
|
+
function scheduleReconciliation(db, sessionId, readMessages) {
|
|
5076
|
+
if (heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
|
|
5077
|
+
return;
|
|
5078
|
+
}
|
|
5079
|
+
heapHolder.reconciliationScheduledSessions.add(sessionId);
|
|
5080
|
+
scheduleAfterBootQuiet(() => {
|
|
5081
|
+
defer(() => {
|
|
5082
|
+
reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
|
|
5083
|
+
if (ran)
|
|
5084
|
+
return;
|
|
5085
|
+
setTimeout(() => {
|
|
5086
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
5087
|
+
scheduleReconciliation(db, sessionId, readMessages);
|
|
5088
|
+
}, PREPARE_RETRY_MS).unref?.();
|
|
5089
|
+
}).catch((error) => {
|
|
5090
|
+
logIndexingError(sessionId, "reconciliation", error);
|
|
5091
|
+
if (isDatabaseLockedError(error))
|
|
5092
|
+
setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000).unref();
|
|
5093
|
+
}).finally(() => {
|
|
5094
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
5095
|
+
});
|
|
5096
|
+
});
|
|
5097
|
+
});
|
|
5098
|
+
}
|
|
5099
|
+
function scheduleReconciliationCatchup(db, sessionId, readMessages) {
|
|
5100
|
+
if (typeof readMessages.getCount !== "function") {
|
|
5101
|
+
scheduleReconciliation(db, sessionId, readMessages);
|
|
5102
|
+
return;
|
|
5103
|
+
}
|
|
5104
|
+
let count;
|
|
5105
|
+
try {
|
|
5106
|
+
count = readMessages.getCount(sessionId);
|
|
5107
|
+
} catch {
|
|
5108
|
+
return;
|
|
5109
|
+
}
|
|
5110
|
+
if (count <= getLastIndexedOrdinal(db, sessionId))
|
|
5111
|
+
return;
|
|
5112
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
5113
|
+
scheduleReconciliation(db, sessionId, readMessages);
|
|
5114
|
+
}
|
|
5115
|
+
function scheduleClearAndReindex(db, sessionId, readMessages) {
|
|
5116
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
5117
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
5118
|
+
clearCompletedIncrementalKeys(sessionId);
|
|
5119
|
+
const existing = heapHolder.clearAndReindexScheduledSessions.get(sessionId);
|
|
5120
|
+
if (existing) {
|
|
5121
|
+
existing.source = readMessages;
|
|
5122
|
+
return;
|
|
5123
|
+
}
|
|
5124
|
+
const pending = { source: readMessages };
|
|
5125
|
+
heapHolder.clearAndReindexScheduledSessions.set(sessionId, pending);
|
|
5126
|
+
scheduleAfterBootQuiet(() => {
|
|
5127
|
+
defer(() => {
|
|
5128
|
+
let cleared = false;
|
|
5129
|
+
runWithSessionLock(sessionId, () => {
|
|
5130
|
+
if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) !== pending)
|
|
5131
|
+
return;
|
|
5132
|
+
heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
|
|
5133
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
5134
|
+
clearCompletedIncrementalKeys(sessionId);
|
|
5135
|
+
clearIndexedMessages(db, sessionId);
|
|
5136
|
+
cleared = true;
|
|
5137
|
+
}).then(() => cleared ? reconcileSessionIndex(db, sessionId, pending.source) : undefined).catch((error) => {
|
|
5138
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
5139
|
+
if (heapHolder.clearAndReindexScheduledSessions.get(sessionId) === pending)
|
|
5140
|
+
heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
|
|
5141
|
+
logIndexingError(sessionId, "clear and reindex", error);
|
|
5142
|
+
});
|
|
5143
|
+
});
|
|
5144
|
+
});
|
|
5145
|
+
}
|
|
5146
|
+
function getMessageIndexQueueHeapStats() {
|
|
5147
|
+
return {
|
|
5148
|
+
queueLength: heapHolder.reconciliationScheduledSessions.size + heapHolder.incrementalTimers.size + heapHolder.pendingIncrementalKeys.size,
|
|
5149
|
+
reconciliationScheduled: heapHolder.reconciliationScheduledSessions.size,
|
|
5150
|
+
incrementalTimers: heapHolder.incrementalTimers.size,
|
|
5151
|
+
pendingIncremental: heapHolder.pendingIncrementalKeys.size,
|
|
5152
|
+
activeSessionLocks: heapHolder.sessionLocks.size,
|
|
5153
|
+
completedIncrementalKeys: heapHolder.completedIncrementalKeys.size,
|
|
5154
|
+
activeBufferMessages: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + messages.length, 0),
|
|
5155
|
+
activeBufferBytes: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + serializedMessageBytes(messages), 0)
|
|
5156
|
+
};
|
|
5157
|
+
}
|
|
5158
|
+
|
|
4879
5159
|
// src/shared/model-cache-ttl.ts
|
|
4880
5160
|
var MODEL_CACHE_LIFETIMES = [
|
|
4881
5161
|
{
|
|
@@ -5240,7 +5520,9 @@ function makeToolCompositeKey(ownerMsgId, callId) {
|
|
|
5240
5520
|
return `${ownerMsgId}${TOOL_COMPOSITE_KEY_SEP}${callId}`;
|
|
5241
5521
|
}
|
|
5242
5522
|
var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
|
|
5243
|
-
var GET_TAGS_VERSION_SQL = `SELECT
|
|
5523
|
+
var GET_TAGS_VERSION_SQL = `SELECT
|
|
5524
|
+
(SELECT tags_version FROM session_meta WHERE session_id = ?) AS tags_version,
|
|
5525
|
+
(SELECT value FROM schema_migrations_meta WHERE key = ?) AS identity_revision`;
|
|
5244
5526
|
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
5245
5527
|
var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
|
|
5246
5528
|
var probeTagsVersionStatements = new WeakMap;
|
|
@@ -5361,10 +5643,16 @@ function createTagger() {
|
|
|
5361
5643
|
const memCounter = heapHolder.counters.get(sessionId) ?? 0;
|
|
5362
5644
|
const dbMax = getMaxTagNumberBySession(db, sessionId);
|
|
5363
5645
|
const next = Math.max(memCounter, dbMax) + 1;
|
|
5646
|
+
const loaded = heapHolder.loadSignatures.get(sessionId);
|
|
5647
|
+
let ownedInitialIdentity;
|
|
5364
5648
|
try {
|
|
5365
5649
|
db.transaction(() => {
|
|
5650
|
+
const admitted = loaded?.db === db && loaded.identityRevision === null ? probeSignature(sessionId, db) : null;
|
|
5651
|
+
const initializesOwnedEpoch = admitted !== null && loaded !== undefined && admitted.identityRevision === null && admitted.tagsVersion === loaded.tagsVersion;
|
|
5366
5652
|
getUpsertCounterStatement(db).run(sessionId, next, getHarness());
|
|
5367
5653
|
insertTag(db, sessionId, messageId, type, byteSize, next, reasoningByteSize, toolName, inputByteSize, toolOwnerMessageId, entryFingerprint, tokenCounts);
|
|
5654
|
+
if (initializesOwnedEpoch)
|
|
5655
|
+
ownedInitialIdentity = probeSignature(sessionId, db).identityRevision;
|
|
5368
5656
|
}).immediate();
|
|
5369
5657
|
} catch (error) {
|
|
5370
5658
|
if (!isUniqueConstraintError(error)) {
|
|
@@ -5385,6 +5673,8 @@ function createTagger() {
|
|
|
5385
5673
|
const signature = heapHolder.loadSignatures.get(sessionId);
|
|
5386
5674
|
if (signature?.db === db) {
|
|
5387
5675
|
signature.tagsVersion += 1;
|
|
5676
|
+
if (signature === loaded && ownedInitialIdentity !== undefined)
|
|
5677
|
+
signature.identityRevision = ownedInitialIdentity;
|
|
5388
5678
|
}
|
|
5389
5679
|
if (type === "tool") {
|
|
5390
5680
|
getSessionToolAccounting(sessionId).set(next, {
|
|
@@ -5487,15 +5777,16 @@ function createTagger() {
|
|
|
5487
5777
|
return heapHolder.counters.get(sessionId) ?? 0;
|
|
5488
5778
|
}
|
|
5489
5779
|
function probeSignature(sessionId, db) {
|
|
5490
|
-
const row = getProbeTagsVersionStatement(db).get(sessionId);
|
|
5780
|
+
const row = getProbeTagsVersionStatement(db).get(sessionId, tagIdentityRevisionKey(sessionId));
|
|
5491
5781
|
return {
|
|
5492
|
-
tagsVersion: row?.tags_version ?? 0
|
|
5782
|
+
tagsVersion: row?.tags_version ?? 0,
|
|
5783
|
+
identityRevision: row?.identity_revision ?? null
|
|
5493
5784
|
};
|
|
5494
5785
|
}
|
|
5495
5786
|
function initFromDb(sessionId, db, floor = 0) {
|
|
5496
5787
|
const probe = probeSignature(sessionId, db);
|
|
5497
5788
|
const cached = heapHolder.loadSignatures.get(sessionId);
|
|
5498
|
-
if (cached !== undefined && cached.db === db && cached.tagsVersion === probe.tagsVersion && cached.floor === floor) {
|
|
5789
|
+
if (cached !== undefined && cached.db === db && cached.tagsVersion === probe.tagsVersion && cached.identityRevision === probe.identityRevision && cached.floor === floor) {
|
|
5499
5790
|
return;
|
|
5500
5791
|
}
|
|
5501
5792
|
const row = db.prepare(GET_COUNTER_SQL).get(sessionId);
|
|
@@ -5528,6 +5819,7 @@ function createTagger() {
|
|
|
5528
5819
|
heapHolder.loadSignatures.set(sessionId, {
|
|
5529
5820
|
db,
|
|
5530
5821
|
tagsVersion: probe.tagsVersion,
|
|
5822
|
+
identityRevision: probe.identityRevision,
|
|
5531
5823
|
floor
|
|
5532
5824
|
});
|
|
5533
5825
|
}
|
|
@@ -5535,6 +5827,10 @@ function createTagger() {
|
|
|
5535
5827
|
const signature = heapHolder.loadSignatures.get(sessionId);
|
|
5536
5828
|
return signature?.db === db ? signature.tagsVersion : undefined;
|
|
5537
5829
|
}
|
|
5830
|
+
function getLoadedTagIdentityRevision(sessionId, db) {
|
|
5831
|
+
const signature = heapHolder.loadSignatures.get(sessionId);
|
|
5832
|
+
return signature?.db === db ? signature.identityRevision : undefined;
|
|
5833
|
+
}
|
|
5538
5834
|
function cleanup(sessionId) {
|
|
5539
5835
|
heapHolder.counters.delete(sessionId);
|
|
5540
5836
|
heapHolder.assignments.delete(sessionId);
|
|
@@ -5577,6 +5873,7 @@ function createTagger() {
|
|
|
5577
5873
|
getCounter,
|
|
5578
5874
|
initFromDb,
|
|
5579
5875
|
getLoadedTagsVersion,
|
|
5876
|
+
getLoadedTagIdentityRevision,
|
|
5580
5877
|
cleanup,
|
|
5581
5878
|
getHeapStats
|
|
5582
5879
|
};
|
|
@@ -5936,25 +6233,35 @@ function forgetCachedPrefix(sessionId) {
|
|
|
5936
6233
|
clearInjectionCache(sessionId);
|
|
5937
6234
|
resetPrefixTrimFallbackState(sessionId);
|
|
5938
6235
|
}
|
|
5939
|
-
function dropCompartmentsAfter(db, sessionId, anchor, holderId) {
|
|
6236
|
+
function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = false, onRetire) {
|
|
5940
6237
|
db.exec("BEGIN IMMEDIATE");
|
|
5941
6238
|
let finished = false;
|
|
6239
|
+
let clearedMarker = null;
|
|
5942
6240
|
try {
|
|
5943
6241
|
if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
|
|
5944
6242
|
db.exec("ROLLBACK");
|
|
5945
6243
|
finished = true;
|
|
5946
6244
|
return null;
|
|
5947
6245
|
}
|
|
5948
|
-
const dropped = db.prepare("SELECT id, sequence FROM compartments WHERE session_id = ? AND sequence > ? ORDER BY sequence").all(sessionId, anchor
|
|
6246
|
+
const dropped = db.prepare("SELECT id, sequence FROM compartments WHERE session_id = ? AND sequence > ? ORDER BY sequence").all(sessionId, anchor?.sequence ?? -1);
|
|
6247
|
+
onRetire?.();
|
|
5949
6248
|
const deleteEmbeddings = db.prepare("DELETE FROM compartment_chunk_embeddings WHERE compartment_id = ?");
|
|
5950
6249
|
for (const row of dropped)
|
|
5951
6250
|
deleteEmbeddings.run(row.id);
|
|
5952
|
-
db.prepare("DELETE FROM compartments WHERE session_id = ? AND sequence > ?").run(sessionId, anchor
|
|
5953
|
-
db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal > ?").run(sessionId, anchor
|
|
6251
|
+
db.prepare("DELETE FROM compartments WHERE session_id = ? AND sequence > ?").run(sessionId, anchor?.sequence ?? -1);
|
|
6252
|
+
db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal > ?").run(sessionId, anchor?.endMessage ?? 0);
|
|
6253
|
+
if (activeBranch) {
|
|
6254
|
+
db.prepare("UPDATE session_meta SET prior_boundary_ordinal = ? WHERE session_id = ?").run((anchor?.endMessage ?? 0) + 1, sessionId);
|
|
6255
|
+
const marker = getPendingPiCompactionMarkerState(db, sessionId);
|
|
6256
|
+
if (marker && clearPendingPiCompactionMarkerStateIf(db, sessionId, marker, null))
|
|
6257
|
+
clearedMarker = marker;
|
|
6258
|
+
}
|
|
5954
6259
|
queueM0Mutation(db, { sessionId, mutationType: "recomp_boundary_change" });
|
|
5955
6260
|
clearCachedM0M1(db, sessionId);
|
|
5956
6261
|
db.exec("COMMIT");
|
|
5957
6262
|
finished = true;
|
|
6263
|
+
if (clearedMarker)
|
|
6264
|
+
logPiCompactionMarkerClear(sessionId, clearedMarker, "active-branch-retired");
|
|
5958
6265
|
return dropped.map((row) => row.sequence);
|
|
5959
6266
|
} finally {
|
|
5960
6267
|
if (!finished) {
|
|
@@ -5965,24 +6272,38 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId) {
|
|
|
5965
6272
|
}
|
|
5966
6273
|
}
|
|
5967
6274
|
function repairMissingHistoryBoundary(args) {
|
|
5968
|
-
const { db, sessionId, isInHostStore } = args;
|
|
5969
|
-
const compartments = getCompartments(db, sessionId);
|
|
6275
|
+
const { db, sessionId, isInHostStore, scope = "store" } = args;
|
|
6276
|
+
const compartments = scope === "active-branch" ? db.prepare("SELECT sequence, COALESCE(end_message_id, '') AS endMessageId FROM compartments WHERE session_id = ? ORDER BY sequence").all(sessionId) : getCompartments(db, sessionId);
|
|
5970
6277
|
let latestIndex = compartments.length - 1;
|
|
5971
6278
|
while (latestIndex >= 0 && !compartments[latestIndex]?.endMessageId)
|
|
5972
6279
|
latestIndex -= 1;
|
|
5973
6280
|
if (latestIndex < 0)
|
|
5974
6281
|
return { kind: "intact" };
|
|
6282
|
+
if (scope === "active-branch") {
|
|
6283
|
+
for (let index = 0;index <= latestIndex; index += 1) {
|
|
6284
|
+
const endId = compartments[index]?.endMessageId;
|
|
6285
|
+
if (!endId)
|
|
6286
|
+
continue;
|
|
6287
|
+
const present = isInHostStore(endId);
|
|
6288
|
+
if (present === null)
|
|
6289
|
+
return { kind: "unknown" };
|
|
6290
|
+
if (!present) {
|
|
6291
|
+
latestIndex = index;
|
|
6292
|
+
break;
|
|
6293
|
+
}
|
|
6294
|
+
}
|
|
6295
|
+
}
|
|
5975
6296
|
const latestEnd = compartments[latestIndex].endMessageId;
|
|
5976
6297
|
const latestPresent = isInHostStore(latestEnd);
|
|
5977
6298
|
if (latestPresent === null)
|
|
5978
6299
|
return { kind: "unknown" };
|
|
5979
6300
|
if (!latestPresent) {
|
|
5980
6301
|
const missing = latestEnd;
|
|
5981
|
-
const problem = `
|
|
6302
|
+
const problem = `compartment end ${latestEnd} is not in ${scope === "active-branch" ? "the active host branch" : "the host store"}`;
|
|
5982
6303
|
const anchor = findAnchor(compartments, latestIndex, isInHostStore);
|
|
5983
6304
|
if (anchor === "unknown")
|
|
5984
6305
|
return { kind: "unknown" };
|
|
5985
|
-
if (anchor === null) {
|
|
6306
|
+
if (anchor === null && scope === "store") {
|
|
5986
6307
|
sessionLog(sessionId, `history boundary unresolved: ${problem} and no older compartment end is in the host store; nothing to re-anchor on`);
|
|
5987
6308
|
return { kind: "unresolved", reason: "no-anchor", missingEndMessageId: missing };
|
|
5988
6309
|
}
|
|
@@ -5994,8 +6315,15 @@ function repairMissingHistoryBoundary(args) {
|
|
|
5994
6315
|
return { kind: "unresolved", reason: "busy", missingEndMessageId: missing };
|
|
5995
6316
|
}
|
|
5996
6317
|
let dropped;
|
|
6318
|
+
let anchorForDrop = anchor;
|
|
5997
6319
|
try {
|
|
5998
|
-
|
|
6320
|
+
if (scope === "active-branch" && anchor) {
|
|
6321
|
+
const row = db.prepare("SELECT end_message AS endMessage FROM compartments WHERE session_id = ? AND sequence = ?").get(sessionId, anchor.sequence);
|
|
6322
|
+
if (!row)
|
|
6323
|
+
return { kind: "unresolved", reason: "busy", missingEndMessageId: missing };
|
|
6324
|
+
anchorForDrop = { ...anchor, endMessage: row.endMessage };
|
|
6325
|
+
}
|
|
6326
|
+
dropped = dropCompartmentsAfter(db, sessionId, anchorForDrop, holderId, scope === "active-branch", () => args.onRetire?.(compartments.slice(latestIndex), anchor));
|
|
5999
6327
|
} finally {
|
|
6000
6328
|
releaseCompartmentLeaseBestEffort(db, sessionId, holderId);
|
|
6001
6329
|
}
|
|
@@ -6004,14 +6332,16 @@ function repairMissingHistoryBoundary(args) {
|
|
|
6004
6332
|
}
|
|
6005
6333
|
forgetCachedPrefix(sessionId);
|
|
6006
6334
|
const range = dropped.length === 0 ? "none" : `${dropped[0]}-${dropped[dropped.length - 1]} (${dropped.length})`;
|
|
6007
|
-
sessionLog(sessionId, `history boundary repair: ${problem}; re-anchored on compartment ${
|
|
6335
|
+
sessionLog(sessionId, `history boundary repair: ${problem}; re-anchored on ${anchorForDrop ? `compartment ${anchorForDrop.sequence} ending at ${anchorForDrop.endMessageId} (ordinal ${anchorForDrop.endMessage})` : "the start of history"}; removed compartments ${range} for the historian to rebuild; the cached prefix is rebuilt on this pass`);
|
|
6008
6336
|
return {
|
|
6009
6337
|
kind: "repaired",
|
|
6010
6338
|
missingEndMessageId: missing,
|
|
6011
|
-
anchorEndMessageId: anchor
|
|
6339
|
+
anchorEndMessageId: anchor?.endMessageId ?? "",
|
|
6012
6340
|
droppedSequences: dropped
|
|
6013
6341
|
};
|
|
6014
6342
|
}
|
|
6343
|
+
if (scope === "active-branch")
|
|
6344
|
+
return { kind: "intact" };
|
|
6015
6345
|
const baseline = readBaseline(db, sessionId);
|
|
6016
6346
|
if (!baseline.hasCachedM0 || baseline.boundary === null || baseline.boundary === latestEnd) {
|
|
6017
6347
|
return { kind: "intact" };
|
|
@@ -6028,175 +6358,15 @@ function repairMissingHistoryBoundary(args) {
|
|
|
6028
6358
|
};
|
|
6029
6359
|
}
|
|
6030
6360
|
|
|
6031
|
-
// src/
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
if (typeof e.message === "string") {
|
|
6041
|
-
if (/database is locked/i.test(e.message))
|
|
6042
|
-
return true;
|
|
6043
|
-
if (/sqlite_(busy|locked)/i.test(e.message))
|
|
6044
|
-
return true;
|
|
6045
|
-
}
|
|
6046
|
-
return false;
|
|
6047
|
-
}
|
|
6048
|
-
var RECONCILIATION_BATCH_SIZE = 100;
|
|
6049
|
-
|
|
6050
|
-
class MagicContextMessageIndexHeapHolder {
|
|
6051
|
-
reconciledSessions = new Set;
|
|
6052
|
-
reconciliationScheduledSessions = new Set;
|
|
6053
|
-
clearAndReindexScheduledSessions = new Map;
|
|
6054
|
-
sessionLocks = new Map;
|
|
6055
|
-
incrementalTimers = new Map;
|
|
6056
|
-
pendingIncrementalKeys = new Set;
|
|
6057
|
-
completedIncrementalKeys = new Set;
|
|
6058
|
-
activeReconcilerBuffers = new Map;
|
|
6059
|
-
}
|
|
6060
|
-
var heapHolder = new MagicContextMessageIndexHeapHolder;
|
|
6061
|
-
function defer(fn) {
|
|
6062
|
-
const immediate = globalThis.setImmediate;
|
|
6063
|
-
if (typeof immediate === "function") {
|
|
6064
|
-
immediate(fn);
|
|
6065
|
-
return;
|
|
6066
|
-
}
|
|
6067
|
-
setTimeout(fn, 0);
|
|
6068
|
-
}
|
|
6069
|
-
function yieldToEventLoop() {
|
|
6070
|
-
return new Promise((resolve) => defer(resolve));
|
|
6071
|
-
}
|
|
6072
|
-
function runWithSessionLock(sessionId, operation) {
|
|
6073
|
-
const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
6074
|
-
const run = previous.catch(() => {
|
|
6075
|
-
return;
|
|
6076
|
-
}).then(async () => {
|
|
6077
|
-
await operation();
|
|
6078
|
-
});
|
|
6079
|
-
heapHolder.sessionLocks.set(sessionId, run);
|
|
6080
|
-
run.finally(() => {
|
|
6081
|
-
if (heapHolder.sessionLocks.get(sessionId) === run) {
|
|
6082
|
-
heapHolder.sessionLocks.delete(sessionId);
|
|
6083
|
-
}
|
|
6084
|
-
}).catch(() => {
|
|
6085
|
-
return;
|
|
6086
|
-
});
|
|
6087
|
-
return run;
|
|
6088
|
-
}
|
|
6089
|
-
function logIndexingError(sessionId, action, error) {
|
|
6090
|
-
if (isDatabaseLockedError(error)) {
|
|
6091
|
-
sessionLog(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
|
|
6092
|
-
return;
|
|
6093
|
-
}
|
|
6094
|
-
sessionLog(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
6095
|
-
log(`[message-index-async] ${action} failed for ${sessionId}:`, error);
|
|
6096
|
-
}
|
|
6097
|
-
function serializedMessageBytes(messages) {
|
|
6098
|
-
try {
|
|
6099
|
-
return Buffer.byteLength(JSON.stringify(messages));
|
|
6100
|
-
} catch {
|
|
6101
|
-
return 0;
|
|
6102
|
-
}
|
|
6103
|
-
}
|
|
6104
|
-
function detectIndexMisalignment(db, sessionId, cursor, finalWatermark, readMessages, fallbackSnapshot) {
|
|
6105
|
-
if (finalWatermark <= 0)
|
|
6106
|
-
return null;
|
|
6107
|
-
const indexedWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
6108
|
-
if (indexedWatermark > finalWatermark) {
|
|
6109
|
-
return `indexed watermark ${indexedWatermark} exceeds projection watermark ${finalWatermark}`;
|
|
6110
|
-
}
|
|
6111
|
-
if (cursor <= 0 || cursor > finalWatermark)
|
|
6112
|
-
return null;
|
|
6113
|
-
const indexedId = getIndexedMessageIdAtOrdinal(db, sessionId, cursor);
|
|
6114
|
-
if (indexedId === null)
|
|
6115
|
-
return null;
|
|
6116
|
-
const projectedId = readMessages.readPage ? readMessages.readPage(sessionId, cursor - 1, 1, finalWatermark)[0]?.id ?? null : fallbackSnapshot?.find((message) => message.ordinal === cursor)?.id ?? null;
|
|
6117
|
-
if (projectedId === null || projectedId === indexedId)
|
|
6118
|
-
return null;
|
|
6119
|
-
return `indexed id '${indexedId}' at ordinal ${cursor} but projection has '${projectedId}'`;
|
|
6120
|
-
}
|
|
6121
|
-
async function reconcileSessionIndex(db, sessionId, readMessages) {
|
|
6122
|
-
await runWithSessionLock(sessionId, async () => {
|
|
6123
|
-
if (heapHolder.reconciledSessions.has(sessionId))
|
|
6124
|
-
return;
|
|
6125
|
-
let fallbackSnapshot = null;
|
|
6126
|
-
try {
|
|
6127
|
-
const fullReader = typeof readMessages === "function" ? readMessages : null;
|
|
6128
|
-
const finalWatermark = readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
|
|
6129
|
-
let cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
6130
|
-
let after;
|
|
6131
|
-
const misalignment = detectIndexMisalignment(db, sessionId, cursor, finalWatermark, readMessages, fallbackSnapshot);
|
|
6132
|
-
if (misalignment !== null) {
|
|
6133
|
-
sessionLog(sessionId, `message FTS index misaligned (${misalignment}); clearing for full re-index`);
|
|
6134
|
-
withSqliteBackgroundWriter(() => clearIndexedMessages(db, sessionId));
|
|
6135
|
-
cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
6136
|
-
}
|
|
6137
|
-
while (cursor < finalWatermark) {
|
|
6138
|
-
const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
|
|
6139
|
-
const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
|
|
6140
|
-
const retainedMessages = fallbackSnapshot ?? messages;
|
|
6141
|
-
heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
|
|
6142
|
-
withSqliteBackgroundWriter(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd));
|
|
6143
|
-
const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
6144
|
-
if (nextCursor <= cursor)
|
|
6145
|
-
break;
|
|
6146
|
-
cursor = nextCursor;
|
|
6147
|
-
const last = messages.at(-1);
|
|
6148
|
-
after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
|
|
6149
|
-
if (cursor < finalWatermark) {
|
|
6150
|
-
await yieldToEventLoop();
|
|
6151
|
-
}
|
|
6152
|
-
}
|
|
6153
|
-
if (isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
|
|
6154
|
-
heapHolder.reconciledSessions.add(sessionId);
|
|
6155
|
-
}
|
|
6156
|
-
} finally {
|
|
6157
|
-
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
6158
|
-
}
|
|
6159
|
-
});
|
|
6160
|
-
}
|
|
6161
|
-
function scheduleReconciliation(db, sessionId, readMessages) {
|
|
6162
|
-
if (heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
|
|
6163
|
-
return;
|
|
6164
|
-
}
|
|
6165
|
-
heapHolder.reconciliationScheduledSessions.add(sessionId);
|
|
6166
|
-
scheduleAfterBootQuiet(() => {
|
|
6167
|
-
defer(() => {
|
|
6168
|
-
reconcileSessionIndex(db, sessionId, readMessages).catch((error) => {
|
|
6169
|
-
logIndexingError(sessionId, "reconciliation", error);
|
|
6170
|
-
if (isDatabaseLockedError(error))
|
|
6171
|
-
setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000).unref();
|
|
6172
|
-
}).finally(() => {
|
|
6173
|
-
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
6174
|
-
});
|
|
6175
|
-
});
|
|
6176
|
-
});
|
|
6177
|
-
}
|
|
6178
|
-
function getMessageIndexQueueHeapStats() {
|
|
6179
|
-
return {
|
|
6180
|
-
queueLength: heapHolder.reconciliationScheduledSessions.size + heapHolder.incrementalTimers.size + heapHolder.pendingIncrementalKeys.size,
|
|
6181
|
-
reconciliationScheduled: heapHolder.reconciliationScheduledSessions.size,
|
|
6182
|
-
incrementalTimers: heapHolder.incrementalTimers.size,
|
|
6183
|
-
pendingIncremental: heapHolder.pendingIncrementalKeys.size,
|
|
6184
|
-
activeSessionLocks: heapHolder.sessionLocks.size,
|
|
6185
|
-
completedIncrementalKeys: heapHolder.completedIncrementalKeys.size,
|
|
6186
|
-
activeBufferMessages: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + messages.length, 0),
|
|
6187
|
-
activeBufferBytes: [...heapHolder.activeReconcilerBuffers.values()].reduce((sum, messages) => sum + serializedMessageBytes(messages), 0)
|
|
6188
|
-
};
|
|
6189
|
-
}
|
|
6190
|
-
|
|
6191
|
-
// src/plugin/sidebar-snapshot-cache.ts
|
|
6192
|
-
var MAX_CACHED_SESSIONS = 100;
|
|
6193
|
-
var STALE_SNAPSHOT_AGE_MS = 5 * 60 * 1000;
|
|
6194
|
-
var cache = new BoundedSessionMap(MAX_CACHED_SESSIONS);
|
|
6195
|
-
function applyStickySnapshotCache(sessionId, fresh) {
|
|
6196
|
-
const now = Date.now();
|
|
6197
|
-
if (fresh.inputTokens > 0) {
|
|
6198
|
-
cache.set(sessionId, { snapshot: fresh, cachedAt: now });
|
|
6199
|
-
return fresh;
|
|
6361
|
+
// src/plugin/sidebar-snapshot-cache.ts
|
|
6362
|
+
var MAX_CACHED_SESSIONS = 100;
|
|
6363
|
+
var STALE_SNAPSHOT_AGE_MS = 5 * 60 * 1000;
|
|
6364
|
+
var cache = new BoundedSessionMap(MAX_CACHED_SESSIONS);
|
|
6365
|
+
function applyStickySnapshotCache(sessionId, fresh) {
|
|
6366
|
+
const now = Date.now();
|
|
6367
|
+
if (fresh.inputTokens > 0) {
|
|
6368
|
+
cache.set(sessionId, { snapshot: fresh, cachedAt: now });
|
|
6369
|
+
return fresh;
|
|
6200
6370
|
}
|
|
6201
6371
|
const cached = cache.peek(sessionId);
|
|
6202
6372
|
if (!cached) {
|
|
@@ -6374,6 +6544,24 @@ function createUnifiedSearchDiagnostics() {
|
|
|
6374
6544
|
suppressedLiveMessageMatches: 0
|
|
6375
6545
|
};
|
|
6376
6546
|
}
|
|
6547
|
+
function searchMessageHistory(db, request) {
|
|
6548
|
+
const diagnostics = request.collectDiagnostics ? createUnifiedSearchDiagnostics() : undefined;
|
|
6549
|
+
const results = searchMessages({
|
|
6550
|
+
db,
|
|
6551
|
+
sessionId: request.sessionId,
|
|
6552
|
+
query: request.query,
|
|
6553
|
+
limit: request.limit,
|
|
6554
|
+
maxOrdinal: request.maxOrdinal,
|
|
6555
|
+
probes: request.probes,
|
|
6556
|
+
relaxedRecall: request.relaxedRecall,
|
|
6557
|
+
diagnostics,
|
|
6558
|
+
dateRange: request.dateRange
|
|
6559
|
+
});
|
|
6560
|
+
return {
|
|
6561
|
+
results,
|
|
6562
|
+
suppressedLiveMessageMatches: diagnostics?.suppressedLiveMessageMatches ?? 0
|
|
6563
|
+
};
|
|
6564
|
+
}
|
|
6377
6565
|
function normalizeLimit(limit) {
|
|
6378
6566
|
if (typeof limit !== "number" || !Number.isFinite(limit)) {
|
|
6379
6567
|
return DEFAULT_UNIFIED_SEARCH_LIMIT;
|
|
@@ -6900,15 +7088,18 @@ function searchMessagesInSnapshot(args, sessionFirst) {
|
|
|
6900
7088
|
args.diagnostics.suppressedLiveMessageMatches = outcome.suppressedCount;
|
|
6901
7089
|
}
|
|
6902
7090
|
const rows = outcome.rows.length > 0 || !args.relaxedRecall ? outcome.rows : runMessageFtsQuery(args.db, args.sessionId, relaxedFtsQuery(args.query), fetchLimit, cutoff, args.dateRange, sessionFirst);
|
|
6903
|
-
const
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
7091
|
+
const renderRows = (limit) => {
|
|
7092
|
+
const filtered = rows.slice(0, limit);
|
|
7093
|
+
return filtered.map((row, rank) => ({
|
|
7094
|
+
source: "message",
|
|
7095
|
+
content: previewText(row.content),
|
|
7096
|
+
score: linearDecayScore(rank, filtered.length),
|
|
7097
|
+
messageOrdinal: row.messageOrdinal,
|
|
7098
|
+
messageId: row.messageId,
|
|
7099
|
+
role: row.role
|
|
7100
|
+
}));
|
|
7101
|
+
};
|
|
7102
|
+
return renderRows(args.limit);
|
|
6912
7103
|
}
|
|
6913
7104
|
const sanitizedProbes = probes.map((probe) => ({ probe, query: sanitizeFtsQuery(probe) })).filter((entry) => entry.query.length > 0);
|
|
6914
7105
|
const corpusSize = getIndexedMessageCorpusSize(args.db, args.sessionId, cutoff);
|
|
@@ -6948,39 +7139,42 @@ function searchMessagesInSnapshot(args, sessionFirst) {
|
|
|
6948
7139
|
queryLists.push({ rows: rowsByQuery[queryIndex] ?? [], weight });
|
|
6949
7140
|
queryIndex += 1;
|
|
6950
7141
|
});
|
|
6951
|
-
const
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
existing
|
|
6958
|
-
|
|
6959
|
-
|
|
7142
|
+
const rankProbeLists = (rowLimit, resultLimit) => {
|
|
7143
|
+
const fused = new Map;
|
|
7144
|
+
for (const list of queryLists) {
|
|
7145
|
+
list.rows.slice(0, rowLimit).forEach((row, rank) => {
|
|
7146
|
+
const rrf = list.weight / (RRF_K + rank);
|
|
7147
|
+
const existing = fused.get(row.messageId);
|
|
7148
|
+
if (existing) {
|
|
7149
|
+
existing.score += rrf;
|
|
7150
|
+
} else {
|
|
7151
|
+
fused.set(row.messageId, { row, score: rrf });
|
|
7152
|
+
}
|
|
7153
|
+
});
|
|
7154
|
+
}
|
|
7155
|
+
for (const entry of fused.values()) {
|
|
7156
|
+
let best = 0;
|
|
7157
|
+
for (const probe of probes) {
|
|
7158
|
+
const weight = probeWeights.get(probe) ?? 0;
|
|
7159
|
+
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
7160
|
+
best = weight;
|
|
7161
|
+
}
|
|
6960
7162
|
}
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
for (const entry of fused.values()) {
|
|
6964
|
-
let best = 0;
|
|
6965
|
-
for (const probe of probes) {
|
|
6966
|
-
const weight = probeWeights.get(probe) ?? 0;
|
|
6967
|
-
if (weight > best && containsProbeVerbatim(entry.row.content, [probe])) {
|
|
6968
|
-
best = weight;
|
|
7163
|
+
if (best > 0) {
|
|
7164
|
+
entry.score += best * VERBATIM_RANK_BONUS;
|
|
6969
7165
|
}
|
|
6970
7166
|
}
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
role: entry.row.role
|
|
6983
|
-
}));
|
|
7167
|
+
const ranked = [...fused.values()].sort((a, b) => b.score !== a.score ? b.score - a.score : a.row.messageOrdinal - b.row.messageOrdinal).slice(0, resultLimit);
|
|
7168
|
+
return ranked.map((entry, rank) => ({
|
|
7169
|
+
source: "message",
|
|
7170
|
+
content: previewText(entry.row.content),
|
|
7171
|
+
score: linearDecayScore(rank, ranked.length),
|
|
7172
|
+
messageOrdinal: entry.row.messageOrdinal,
|
|
7173
|
+
messageId: entry.row.messageId,
|
|
7174
|
+
role: entry.row.role
|
|
7175
|
+
}));
|
|
7176
|
+
};
|
|
7177
|
+
return rankProbeLists(fetchLimit, args.limit);
|
|
6984
7178
|
}
|
|
6985
7179
|
var NOTE_SEARCHABLE_STATUSES = ["active"];
|
|
6986
7180
|
var MAX_NOTE_KEYWORD_SCORE = 3.5;
|
|
@@ -7270,17 +7464,28 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
7270
7464
|
const runPrimers = activeSources.has("primer") && memoryFeatureEnabled;
|
|
7271
7465
|
const runNotes = activeSources.has("note");
|
|
7272
7466
|
const messageProbes = options.explicitSearch ? extractLiteralProbes(trimmedQuery) : [];
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7467
|
+
let messageResults = [];
|
|
7468
|
+
if (runMessages) {
|
|
7469
|
+
const messageRequest = {
|
|
7470
|
+
sessionId,
|
|
7471
|
+
query: trimmedQuery,
|
|
7472
|
+
limit: tierLimit,
|
|
7473
|
+
maxOrdinal: options.maxMessageOrdinal,
|
|
7474
|
+
probes: messageProbes,
|
|
7475
|
+
relaxedRecall: options.explicitSearch,
|
|
7476
|
+
collectDiagnostics: options.diagnostics !== undefined,
|
|
7477
|
+
dateRange
|
|
7478
|
+
};
|
|
7479
|
+
const delegated = options.searchMessageHistory ? await options.searchMessageHistory(messageRequest).catch((error) => {
|
|
7480
|
+
log(`[search] off-thread message search failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
7481
|
+
return null;
|
|
7482
|
+
}) : null;
|
|
7483
|
+
const outcome = delegated ?? searchMessageHistory(db, messageRequest);
|
|
7484
|
+
if (options.diagnostics) {
|
|
7485
|
+
options.diagnostics.suppressedLiveMessageMatches = outcome.suppressedLiveMessageMatches;
|
|
7486
|
+
}
|
|
7487
|
+
messageResults = outcome.results;
|
|
7488
|
+
}
|
|
7284
7489
|
const workspace = resolveSearchWorkspaceContext(db, projectPath);
|
|
7285
7490
|
const [memoryOutcome, primerResults, noteResults] = await Promise.all([
|
|
7286
7491
|
runMemory ? searchMemories({
|
|
@@ -7425,7 +7630,7 @@ ${diagnosticLines.join(`
|
|
|
7425
7630
|
bodyParts.push(diagnosticLines.join(`
|
|
7426
7631
|
`));
|
|
7427
7632
|
if (results.some((result) => result.source === "message")) {
|
|
7428
|
-
bodyParts.push("Use mmc_expand(start, end) with the range from any message result above to read the
|
|
7633
|
+
bodyParts.push("Use mmc_expand(start, end) with the range from any message result above to read the conversation context. If the host no longer holds those messages, mmc_expand returns indexed text from the search archive only, with no surrounding messages or tool output.");
|
|
7429
7634
|
}
|
|
7430
7635
|
if (results.some((result) => result.source === "note" && result.anchorOrdinal !== null && result.sourceSessionId === currentSessionId)) {
|
|
7431
7636
|
bodyParts.push(SEARCH_NOTE_EXPAND_HINT);
|
|
@@ -7437,23 +7642,6 @@ ${bodyParts.join(`
|
|
|
7437
7642
|
`)}`;
|
|
7438
7643
|
}
|
|
7439
7644
|
|
|
7440
|
-
// src/shared/auto-search-lifecycle.ts
|
|
7441
|
-
var pending = new Map;
|
|
7442
|
-
function registerAutoSearchWork(sessionId) {
|
|
7443
|
-
const controller = new AbortController;
|
|
7444
|
-
const work = pending.get(sessionId) ?? new Set;
|
|
7445
|
-
pending.set(sessionId, work);
|
|
7446
|
-
work.add(controller);
|
|
7447
|
-
return {
|
|
7448
|
-
signal: controller.signal,
|
|
7449
|
-
done: () => {
|
|
7450
|
-
work.delete(controller);
|
|
7451
|
-
if (pending.get(sessionId) === work && work.size === 0)
|
|
7452
|
-
pending.delete(sessionId);
|
|
7453
|
-
}
|
|
7454
|
-
};
|
|
7455
|
-
}
|
|
7456
|
-
|
|
7457
7645
|
// src/hooks/magic-context/auto-search-deadline.ts
|
|
7458
7646
|
var AUTO_SEARCH_TIMEOUT_MS = 3000;
|
|
7459
7647
|
var operationDeadlines = new WeakMap;
|
|
@@ -8227,6 +8415,8 @@ async function runAutoSearchHint(args) {
|
|
|
8227
8415
|
return AUTO_SEARCH_OK;
|
|
8228
8416
|
}
|
|
8229
8417
|
const replayServedDecision = () => {
|
|
8418
|
+
if (getUnpublishedAutoSearchNoHint(sessionId, userMsgId) !== undefined)
|
|
8419
|
+
return;
|
|
8230
8420
|
const decisions = getAutoSearchHintDecisions(db, sessionId);
|
|
8231
8421
|
const decision = decisions.find((entry) => entry.messageId === userMsgId);
|
|
8232
8422
|
if (decision?.decision === "hint") {
|
|
@@ -8239,12 +8429,34 @@ async function runAutoSearchHint(args) {
|
|
|
8239
8429
|
if (messages.length === 0 || messages[messages.length - 1].info.id !== userMsgId) {
|
|
8240
8430
|
return AUTO_SEARCH_OK;
|
|
8241
8431
|
}
|
|
8432
|
+
const unpublishedReason = getUnpublishedAutoSearchNoHint(sessionId, userMsgId);
|
|
8433
|
+
if (unpublishedReason !== undefined) {
|
|
8434
|
+
try {
|
|
8435
|
+
const outcome = appendAutoSearchHintDecision(db, sessionId, {
|
|
8436
|
+
messageId: userMsgId,
|
|
8437
|
+
decision: "no-hint",
|
|
8438
|
+
reason: unpublishedReason
|
|
8439
|
+
});
|
|
8440
|
+
if (outcome.ok)
|
|
8441
|
+
forgetUnpublishedAutoSearchNoHint(sessionId, userMsgId);
|
|
8442
|
+
} catch {}
|
|
8443
|
+
return AUTO_SEARCH_OK;
|
|
8444
|
+
}
|
|
8242
8445
|
const writeNoHintAndReconcile = (reason) => {
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8446
|
+
let outcome;
|
|
8447
|
+
try {
|
|
8448
|
+
outcome = appendAutoSearchHintDecision(db, sessionId, {
|
|
8449
|
+
messageId: userMsgId,
|
|
8450
|
+
decision: "no-hint",
|
|
8451
|
+
reason
|
|
8452
|
+
});
|
|
8453
|
+
} catch (error) {
|
|
8454
|
+
if (isTransientSqliteError(error)) {
|
|
8455
|
+
rememberUnpublishedAutoSearchNoHint(sessionId, userMsgId, reason);
|
|
8456
|
+
return { ok: false, kind: "storage-busy" };
|
|
8457
|
+
}
|
|
8458
|
+
throw error;
|
|
8459
|
+
}
|
|
8248
8460
|
if (!outcome.ok)
|
|
8249
8461
|
return { ok: false, kind: "cas-exhaustion" };
|
|
8250
8462
|
if (outcome.kind === "already-present" && outcome.decision.decision === "hint") {
|
|
@@ -8281,8 +8493,11 @@ async function runAutoSearchHint(args) {
|
|
|
8281
8493
|
});
|
|
8282
8494
|
}, startedAt);
|
|
8283
8495
|
} catch (error) {
|
|
8284
|
-
|
|
8285
|
-
|
|
8496
|
+
if (lifecycleSignal.aborted)
|
|
8497
|
+
return AUTO_SEARCH_OK;
|
|
8498
|
+
log(`[auto-search] unified search failed for session ${sessionId} (no-hint frozen for this turn): ${error instanceof Error ? error.message : String(error)}`);
|
|
8499
|
+
const outcome = writeNoHintAndReconcile("error");
|
|
8500
|
+
return outcome.ok ? { ok: false, kind: "search-failure" } : outcome;
|
|
8286
8501
|
}
|
|
8287
8502
|
if (results === null) {
|
|
8288
8503
|
persistAutoSearchSkip(db, sessionId, userMsgId, "timeout");
|
|
@@ -8510,7 +8725,7 @@ function createChatMessageHook(args) {
|
|
|
8510
8725
|
sessionLog(sessionId, `variant changed (${previousVariant} -> ${input.variant}), triggering flush`);
|
|
8511
8726
|
args.historyRefreshSessions.add(sessionId);
|
|
8512
8727
|
args.systemPromptRefreshSessions.add(sessionId);
|
|
8513
|
-
args.pendingMaterializationSessions
|
|
8728
|
+
requestPendingMaterialization(args.pendingMaterializationSessions, sessionId, "variant_change");
|
|
8514
8729
|
args.lastHeuristicsTurnId.delete(sessionId);
|
|
8515
8730
|
} else {
|
|
8516
8731
|
sessionLog(sessionId, `variant changed (${previousVariant} -> ${input.variant}) on ${providerID ?? "unknown"}/${modelID ?? "unknown"} without a proven natural cache bust; deferring flush to next natural bust`);
|
|
@@ -8635,8 +8850,12 @@ function createToolExecuteAfterHook(args) {
|
|
|
8635
8850
|
|
|
8636
8851
|
// src/hooks/magic-context/active-anthropic-turn.ts
|
|
8637
8852
|
function isInActiveAnthropicTurn(messages, index, anthropic) {
|
|
8853
|
+
const start = activeAnthropicTurnStart(messages, anthropic);
|
|
8854
|
+
return start !== undefined && index >= start;
|
|
8855
|
+
}
|
|
8856
|
+
function activeAnthropicTurnStart(messages, anthropic) {
|
|
8638
8857
|
if (!anthropic)
|
|
8639
|
-
return
|
|
8858
|
+
return;
|
|
8640
8859
|
for (let user = messages.length - 1;user >= 0; user--) {
|
|
8641
8860
|
const message = messages[user];
|
|
8642
8861
|
if (!isRecord(message))
|
|
@@ -8650,9 +8869,9 @@ function isInActiveAnthropicTurn(messages, index, anthropic) {
|
|
|
8650
8869
|
const parts = Array.isArray(message.parts) ? message.parts : Array.isArray(message.content) ? message.content : [];
|
|
8651
8870
|
if (parts.length > 0 && parts.every((part) => isRecord(part) && (part.synthetic === true || part.ignored === true || ["tool_result", "toolResult", "tool-result"].includes(String(part.type)))))
|
|
8652
8871
|
continue;
|
|
8653
|
-
return
|
|
8872
|
+
return user + 1;
|
|
8654
8873
|
}
|
|
8655
|
-
return
|
|
8874
|
+
return;
|
|
8656
8875
|
}
|
|
8657
8876
|
function hasAnthropicReasoning(messages) {
|
|
8658
8877
|
return messages.some((message) => {
|
|
@@ -8666,6 +8885,27 @@ function hasAnthropicReasoning(messages) {
|
|
|
8666
8885
|
});
|
|
8667
8886
|
}
|
|
8668
8887
|
|
|
8888
|
+
// src/shared/processed-image-eligibility.ts
|
|
8889
|
+
function createProcessedImageEligibility(messages, messageTagNumbers, options) {
|
|
8890
|
+
const ageTags = new Map;
|
|
8891
|
+
let nextTag;
|
|
8892
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
8893
|
+
const message = messages[index];
|
|
8894
|
+
const ownTag = messageTagNumbers.get(message);
|
|
8895
|
+
if (ownTag !== undefined && Number.isFinite(ownTag) && ownTag > 0)
|
|
8896
|
+
nextTag = ownTag;
|
|
8897
|
+
if (nextTag !== undefined)
|
|
8898
|
+
ageTags.set(message, nextTag);
|
|
8899
|
+
}
|
|
8900
|
+
return {
|
|
8901
|
+
ageTags,
|
|
8902
|
+
mayStrip: (message) => {
|
|
8903
|
+
const age = ageTags.get(message);
|
|
8904
|
+
return options.watermark > 0 && age !== undefined && age <= options.watermark && ((options.contextPercentage ?? 0) >= 95 || options.protectedCutoff == null || age < options.protectedCutoff);
|
|
8905
|
+
}
|
|
8906
|
+
};
|
|
8907
|
+
}
|
|
8908
|
+
|
|
8669
8909
|
// src/hooks/magic-context/strip-content.ts
|
|
8670
8910
|
var MARKER_ONLY_PATTERN = /^(?:(?:§\d+§|\[dropped(?: §\d+§)?\]|\[cleared\])\s*)+$/;
|
|
8671
8911
|
function isMarkerOnlyText(text) {
|
|
@@ -8728,8 +8968,7 @@ function stripSystemInjectedMessages(messages, protectedTailStart, providerID, o
|
|
|
8728
8968
|
}
|
|
8729
8969
|
if (hasContentPart && allContentIsSystemInjection) {
|
|
8730
8970
|
onFirstApplication?.(msg, 0);
|
|
8731
|
-
msg
|
|
8732
|
-
msg.parts.push(makeWholeMessageSentinel(providerID));
|
|
8971
|
+
neutralizeWholeMessage(msg, providerID);
|
|
8733
8972
|
stripped++;
|
|
8734
8973
|
if (typeof msg.info.id === "string")
|
|
8735
8974
|
sentineledIds.push(msg.info.id);
|
|
@@ -8787,8 +9026,7 @@ function stripDroppedPlaceholderMessages(messages, providerID, onFirstApplicatio
|
|
|
8787
9026
|
}
|
|
8788
9027
|
if (hasContentPart && !hasNonDroppedContent) {
|
|
8789
9028
|
onFirstApplication?.(msg, 0);
|
|
8790
|
-
msg
|
|
8791
|
-
msg.parts.push(makeWholeMessageSentinel(providerID));
|
|
9029
|
+
neutralizeWholeMessage(msg, providerID);
|
|
8792
9030
|
stripped++;
|
|
8793
9031
|
if (typeof msg.info.id === "string")
|
|
8794
9032
|
sentineledIds.push(msg.info.id);
|
|
@@ -9187,7 +9425,7 @@ function stripReasoningFromMergedAssistants(messages, providerID, options) {
|
|
|
9187
9425
|
if (providerID !== "anthropic")
|
|
9188
9426
|
return 0;
|
|
9189
9427
|
let stripped = 0;
|
|
9190
|
-
const frozenParts = readFrozenMergedReasoningParts(options?.frozenMessageIds ?? new Set);
|
|
9428
|
+
const frozenParts = options?.frozenParts ?? readFrozenMergedReasoningParts(options?.frozenMessageIds ?? new Set);
|
|
9191
9429
|
for (const message of messages) {
|
|
9192
9430
|
if (message.info.role !== "assistant" || options?.restoreMessages?.has(message))
|
|
9193
9431
|
continue;
|
|
@@ -9204,7 +9442,7 @@ function stripReasoningFromMergedAssistants(messages, providerID, options) {
|
|
|
9204
9442
|
stripped++;
|
|
9205
9443
|
}
|
|
9206
9444
|
}
|
|
9207
|
-
for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, new Set(frozenParts.keys()), options?.frozenMessageIds ? options.restoreMessages : options?.protectedMessages)) {
|
|
9445
|
+
for (const entry of planMergedAssistantReasoningStrip(messages, options?.mutationExemptMessage, options?.frozenPartMessageIds ?? new Set(frozenParts.keys()), options?.frozenMessageIds ? options.restoreMessages : options?.protectedMessages)) {
|
|
9208
9446
|
if (options?.frozenMessageIds) {
|
|
9209
9447
|
const id = entry.message.info.id;
|
|
9210
9448
|
if (typeof id !== "string" || !options.frozenMessageIds.has(id))
|
|
@@ -9217,50 +9455,142 @@ function stripReasoningFromMergedAssistants(messages, providerID, options) {
|
|
|
9217
9455
|
}
|
|
9218
9456
|
return stripped;
|
|
9219
9457
|
}
|
|
9458
|
+
var emptyImageParts = new WeakMap;
|
|
9459
|
+
function getEmptyImageParts(messages) {
|
|
9460
|
+
return emptyImageParts.get(messages) ?? new Map;
|
|
9461
|
+
}
|
|
9462
|
+
function imageOmissionBreaksStructure(messages, index, omitted) {
|
|
9463
|
+
let before = index - 1;
|
|
9464
|
+
let after = index + 1;
|
|
9465
|
+
while (omitted.has(before))
|
|
9466
|
+
before--;
|
|
9467
|
+
while (omitted.has(after))
|
|
9468
|
+
after++;
|
|
9469
|
+
const previous = messages[before];
|
|
9470
|
+
const next = messages[after];
|
|
9471
|
+
return previous !== undefined && next !== undefined && previous.info.role === next.info.role;
|
|
9472
|
+
}
|
|
9220
9473
|
function stripProcessedImages(messages, frozenIds, options) {
|
|
9221
|
-
const
|
|
9474
|
+
const omissions = new Map;
|
|
9475
|
+
emptyImageParts.set(messages, omissions);
|
|
9476
|
+
const { detect, messageTagNumbers } = options;
|
|
9477
|
+
const eligibility = createProcessedImageEligibility(messages, messageTagNumbers, options);
|
|
9222
9478
|
let stripped = 0;
|
|
9223
9479
|
const newlyStrippedIds = [];
|
|
9480
|
+
const planned = [];
|
|
9481
|
+
const newMarkers = new Map;
|
|
9224
9482
|
let hasAssistantResponse = false;
|
|
9225
9483
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
9226
9484
|
const msg = messages[i];
|
|
9485
|
+
const answered = hasAssistantResponse;
|
|
9227
9486
|
if (msg.info.role === "assistant") {
|
|
9228
9487
|
hasAssistantResponse = true;
|
|
9229
|
-
continue;
|
|
9230
9488
|
}
|
|
9231
|
-
if (msg.info.role !== "user") {
|
|
9489
|
+
if (msg.info.role !== "user" && msg.info.role !== "assistant") {
|
|
9232
9490
|
continue;
|
|
9233
9491
|
}
|
|
9234
9492
|
const id = typeof msg.info.id === "string" ? msg.info.id : undefined;
|
|
9235
9493
|
const inFrozen = id !== undefined && frozenIds.has(id);
|
|
9236
|
-
const
|
|
9237
|
-
const isNewDetection = !inFrozen && detect && hasAssistantResponse && id !== undefined && maxTag <= watermark;
|
|
9494
|
+
const isNewDetection = !inFrozen && detect && answered && id !== undefined && eligibility.mayStrip(msg) && !options.protectedMessageIds?.has(id);
|
|
9238
9495
|
if (!inFrozen && !isNewDetection) {
|
|
9239
9496
|
continue;
|
|
9240
9497
|
}
|
|
9241
9498
|
let touchedThisMsg = false;
|
|
9242
9499
|
for (let j = 0;j < msg.parts.length; j++) {
|
|
9243
9500
|
const part = msg.parts[j];
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
msg.parts[j] = makeSentinel(part);
|
|
9254
|
-
stripped++;
|
|
9501
|
+
const tool = msg.info.role === "assistant" && isRecord(part) && part.type === "tool" && isRecord(part.state) && part.state.status === "completed";
|
|
9502
|
+
const images = tool && isRecord(part) && isRecord(part.state) && Array.isArray(part.state.attachments) ? part.state.attachments : msg.info.role === "user" ? [part] : [];
|
|
9503
|
+
if (images.some(isProcessedImagePart)) {
|
|
9504
|
+
planned.push({
|
|
9505
|
+
message: msg,
|
|
9506
|
+
partIndex: j,
|
|
9507
|
+
firstApplication: isNewDetection,
|
|
9508
|
+
tool
|
|
9509
|
+
});
|
|
9255
9510
|
touchedThisMsg = true;
|
|
9256
9511
|
}
|
|
9257
9512
|
}
|
|
9258
9513
|
if (touchedThisMsg && isNewDetection && id !== undefined) {
|
|
9259
9514
|
newlyStrippedIds.push(id);
|
|
9515
|
+
newMarkers.set(id, msg.info.role === "assistant" ? "[image stripped]" : options.replacementText ?? "");
|
|
9516
|
+
}
|
|
9517
|
+
}
|
|
9518
|
+
const imageIndices = new Map;
|
|
9519
|
+
for (const { message, partIndex, tool } of planned) {
|
|
9520
|
+
if (tool)
|
|
9521
|
+
continue;
|
|
9522
|
+
const indices = imageIndices.get(message) ?? new Set;
|
|
9523
|
+
indices.add(partIndex);
|
|
9524
|
+
imageIndices.set(message, indices);
|
|
9525
|
+
}
|
|
9526
|
+
const emptiedRows = new Set;
|
|
9527
|
+
const newEmptyRows = [];
|
|
9528
|
+
for (let index = 0;index < messages.length; index++) {
|
|
9529
|
+
const message = messages[index];
|
|
9530
|
+
if (message.parts.every((part) => isRecord(part) && part.type === "text" && part.text === ""))
|
|
9531
|
+
emptiedRows.add(index);
|
|
9532
|
+
const id = message.info.id;
|
|
9533
|
+
const indices = imageIndices.get(message);
|
|
9534
|
+
if (!id || !indices)
|
|
9535
|
+
continue;
|
|
9536
|
+
const marker = options.frozenMarkers?.get(id) ?? newMarkers.get(id) ?? "";
|
|
9537
|
+
if (marker !== "" || !message.parts.every((part, partIndex) => indices.has(partIndex) || isRecord(part) && part.type === "text" && part.text === ""))
|
|
9538
|
+
continue;
|
|
9539
|
+
if (newMarkers.has(id))
|
|
9540
|
+
newEmptyRows.push({ index, id });
|
|
9541
|
+
else
|
|
9542
|
+
emptiedRows.add(index);
|
|
9543
|
+
}
|
|
9544
|
+
for (const { index, id } of newEmptyRows) {
|
|
9545
|
+
if (imageOmissionBreaksStructure(messages, index, emptiedRows))
|
|
9546
|
+
newMarkers.set(id, "[image stripped]");
|
|
9547
|
+
else
|
|
9548
|
+
emptiedRows.add(index);
|
|
9549
|
+
}
|
|
9550
|
+
const persisted = newlyStrippedIds.length === 0 || options.persistNewIds?.(newlyStrippedIds, newMarkers) !== false;
|
|
9551
|
+
if (!persisted)
|
|
9552
|
+
newlyStrippedIds.length = 0;
|
|
9553
|
+
for (const { message, partIndex, firstApplication, tool } of planned) {
|
|
9554
|
+
if (firstApplication && !persisted)
|
|
9555
|
+
continue;
|
|
9556
|
+
if (firstApplication)
|
|
9557
|
+
options.onFirstApplication?.(message, partIndex);
|
|
9558
|
+
const marker = tool ? "[image stripped]" : options.frozenMarkers?.get(message.info.id ?? "") ?? (firstApplication ? newMarkers.get(message.info.id ?? "") : "") ?? "";
|
|
9559
|
+
const original = message.parts[partIndex];
|
|
9560
|
+
if (tool && isRecord(original) && isRecord(original.state) && Array.isArray(original.state.attachments)) {
|
|
9561
|
+
const attachments = original.state.attachments;
|
|
9562
|
+
const count = attachments.filter(isProcessedImagePart).length;
|
|
9563
|
+
const output = typeof original.state.output === "string" ? original.state.output : "";
|
|
9564
|
+
message.parts[partIndex] = {
|
|
9565
|
+
...original,
|
|
9566
|
+
state: {
|
|
9567
|
+
...original.state,
|
|
9568
|
+
output: [output, ...Array(count).fill(marker)].filter(Boolean).join(`
|
|
9569
|
+
`),
|
|
9570
|
+
attachments: attachments.filter((part) => !isProcessedImagePart(part))
|
|
9571
|
+
}
|
|
9572
|
+
};
|
|
9573
|
+
stripped += count;
|
|
9574
|
+
} else {
|
|
9575
|
+
message.parts[partIndex] = { ...makeSentinel(original), text: marker };
|
|
9576
|
+
if (marker === "" && message.info.id) {
|
|
9577
|
+
const indices = omissions.get(message.info.id) ?? new Set;
|
|
9578
|
+
indices.add(partIndex);
|
|
9579
|
+
omissions.set(message.info.id, indices);
|
|
9580
|
+
}
|
|
9581
|
+
stripped++;
|
|
9260
9582
|
}
|
|
9261
9583
|
}
|
|
9262
9584
|
return { stripped, newlyStrippedIds };
|
|
9263
9585
|
}
|
|
9586
|
+
function isProcessedImagePart(part) {
|
|
9587
|
+
if (isRecord(part) && part.type === "media" && isRecord(part.media)) {
|
|
9588
|
+
const { source, mediaType } = part.media;
|
|
9589
|
+
const inlineLength = isRecord(source) ? source.type === "base64" && typeof source.data === "string" ? source.data.length : source.type === "bytes" && source.data instanceof Uint8Array ? Math.ceil(source.data.byteLength / 3) * 4 : 0 : 0;
|
|
9590
|
+
return typeof mediaType === "string" && mediaType.startsWith("image/") && inlineLength > 0 && inlineLength + `data:${mediaType};base64,`.length > 200;
|
|
9591
|
+
}
|
|
9592
|
+
return isRecord(part) && part.type === "file" && typeof part.mime === "string" && part.mime.startsWith("image/") && typeof part.url === "string" && part.url.startsWith("data:") && part.url.length > 200;
|
|
9593
|
+
}
|
|
9264
9594
|
|
|
9265
9595
|
// src/hooks/magic-context/reasoning-removal.ts
|
|
9266
9596
|
var REMOVABLE_REASONING_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
|
|
@@ -9510,7 +9840,7 @@ function armLatestThinkingRecovery(db, sessionId) {
|
|
|
9510
9840
|
ensureSessionMetaRow(db, sessionId);
|
|
9511
9841
|
const current = getThinkingBindingRecoveryTarget(db, sessionId);
|
|
9512
9842
|
const anchor = lastPassTurnAnchor.get(sessionId);
|
|
9513
|
-
const next = current?.startsWith(ACTIVE) ? UNRECOVERABLE
|
|
9843
|
+
const next = current?.startsWith(ACTIVE) ? `${UNRECOVERABLE}:${current.slice(ACTIVE.length)}` : current?.startsWith(UNRECOVERABLE) || current?.startsWith(ARMED) ? current : anchor !== undefined ? `${ARMED}${anchor}` : LATEST_THINKING_RESTORE;
|
|
9514
9844
|
db.prepare("UPDATE session_meta SET thinking_binding_recovery_target = ? WHERE session_id = ?").run(next, sessionId);
|
|
9515
9845
|
}
|
|
9516
9846
|
function clone(value) {
|
|
@@ -9543,12 +9873,12 @@ function prepareLatestThinkingRecovery(args) {
|
|
|
9543
9873
|
let target;
|
|
9544
9874
|
try {
|
|
9545
9875
|
target = getThinkingBindingRecoveryTarget(args.db, args.sessionId);
|
|
9546
|
-
} catch
|
|
9876
|
+
} catch {
|
|
9547
9877
|
if (knownRejectedSessions.has(args.sessionId))
|
|
9548
9878
|
throw contextRefusalError(LATEST_THINKING_UNSAFE);
|
|
9549
9879
|
return { restore: false, ended: false };
|
|
9550
9880
|
}
|
|
9551
|
-
if (!target
|
|
9881
|
+
if (!target?.startsWith(LATEST_THINKING_RESTORE)) {
|
|
9552
9882
|
knownRejectedSessions.delete(args.sessionId);
|
|
9553
9883
|
return { restore: false, ended: false };
|
|
9554
9884
|
}
|
|
@@ -9559,7 +9889,7 @@ function prepareLatestThinkingRecovery(args) {
|
|
|
9559
9889
|
return { restore: false, ended: false };
|
|
9560
9890
|
}
|
|
9561
9891
|
knownRejectedSessions.add(args.sessionId);
|
|
9562
|
-
const savedAnchor = target.startsWith(ACTIVE) ? target.slice(ACTIVE.length) : target.startsWith(UNRECOVERABLE
|
|
9892
|
+
const savedAnchor = target.startsWith(ACTIVE) ? target.slice(ACTIVE.length) : target.startsWith(`${UNRECOVERABLE}:`) ? target.slice(UNRECOVERABLE.length + 1) : undefined;
|
|
9563
9893
|
if (savedAnchor !== undefined && savedAnchor !== anchor) {
|
|
9564
9894
|
args.db.prepare("UPDATE session_meta SET thinking_binding_recovery_target = '' WHERE session_id = ? AND thinking_binding_recovery_target = ?").run(args.sessionId, target);
|
|
9565
9895
|
knownRejectedSessions.delete(args.sessionId);
|
|
@@ -9572,7 +9902,7 @@ function prepareLatestThinkingRecovery(args) {
|
|
|
9572
9902
|
}
|
|
9573
9903
|
const active = args.messages.slice(start);
|
|
9574
9904
|
if (!active.some((message) => args.parts(message).some(replayableOriginal)))
|
|
9575
|
-
throw contextRefusalError(LATEST_THINKING_UNSAFE
|
|
9905
|
+
throw contextRefusalError(`${LATEST_THINKING_UNSAFE} [missing-thinking-original]`);
|
|
9576
9906
|
const ids = new Map(args.messages.map((message, index) => [args.id(message, index), index]));
|
|
9577
9907
|
for (const decision of getMergedReasoningStrippedIds(args.db, args.sessionId)) {
|
|
9578
9908
|
if (decision === "binding_mismatch_order:end" || decision === TOOL_SWEEP_SCOPED_MARKER)
|
|
@@ -9580,7 +9910,7 @@ function prepareLatestThinkingRecovery(args) {
|
|
|
9580
9910
|
const id = decodeMergedReasoningParts(decision)?.[0] ?? (decision.startsWith("binding_mismatch:") ? decision.slice("binding_mismatch:".length) : decision);
|
|
9581
9911
|
const index = ids.get(id);
|
|
9582
9912
|
if (index === undefined || index >= start && !args.parts(args.messages[index]).some(replayableOriginal))
|
|
9583
|
-
throw contextRefusalError(LATEST_THINKING_UNSAFE
|
|
9913
|
+
throw contextRefusalError(`${LATEST_THINKING_UNSAFE} [missing-original:${id}]`);
|
|
9584
9914
|
}
|
|
9585
9915
|
return { restore: true, ended: false };
|
|
9586
9916
|
}
|
|
@@ -9613,964 +9943,6 @@ function armLatestThinkingRecoveryFromError(args) {
|
|
|
9613
9943
|
return true;
|
|
9614
9944
|
}
|
|
9615
9945
|
|
|
9616
|
-
// src/hooks/magic-context/lkg-measured-request.ts
|
|
9617
|
-
import { createHash as createHash3 } from "node:crypto";
|
|
9618
|
-
|
|
9619
|
-
// src/shared/provider-response-completion.ts
|
|
9620
|
-
function providerResponseFailed(input) {
|
|
9621
|
-
if (input.error !== undefined && input.error !== null && input.error !== "")
|
|
9622
|
-
return true;
|
|
9623
|
-
const finish = typeof input.finish === "string" ? input.finish.trim().toLowerCase() : "";
|
|
9624
|
-
return ["error", "failed", "abort", "aborted", "interrupted", "cancelled", "canceled"].includes(finish);
|
|
9625
|
-
}
|
|
9626
|
-
function isSuccessfulProviderCompletion(input) {
|
|
9627
|
-
if (providerResponseFailed(input))
|
|
9628
|
-
return false;
|
|
9629
|
-
return typeof input.completedAt === "number" && Number.isFinite(input.completedAt) && input.completedAt > 0 || typeof input.finish === "string" && input.finish.trim().length > 0;
|
|
9630
|
-
}
|
|
9631
|
-
|
|
9632
|
-
// src/hooks/magic-context/lkg-measured-request.ts
|
|
9633
|
-
var requests = new BoundedSessionMap(1000);
|
|
9634
|
-
var claimedRequests = new WeakSet;
|
|
9635
|
-
var captures = new BoundedSessionMap(1000);
|
|
9636
|
-
function lkgProviderInputTotal(tokens) {
|
|
9637
|
-
const counts = [tokens?.input ?? 0, tokens?.cache?.read ?? 0, tokens?.cache?.write ?? 0];
|
|
9638
|
-
return counts.every((count) => Number.isSafeInteger(count) && count >= 0) ? counts.reduce((sum, count) => sum + count, 0) : Number.NaN;
|
|
9639
|
-
}
|
|
9640
|
-
function identity(slot) {
|
|
9641
|
-
return createHash3("sha256").update(JSON.stringify([
|
|
9642
|
-
slot.capturedAt,
|
|
9643
|
-
slot.captureSequence,
|
|
9644
|
-
slot.rowVersion,
|
|
9645
|
-
slot.modelKey,
|
|
9646
|
-
slot.providerKey,
|
|
9647
|
-
slot.inputIdSeq,
|
|
9648
|
-
slot.inputContentDigests
|
|
9649
|
-
])).update(slot.jsonPrefix).digest("hex");
|
|
9650
|
-
}
|
|
9651
|
-
function envelope(modelKey, systemPromptTokens, agentName) {
|
|
9652
|
-
const slash = modelKey.indexOf("/");
|
|
9653
|
-
return JSON.stringify([
|
|
9654
|
-
modelKey,
|
|
9655
|
-
systemPromptTokens,
|
|
9656
|
-
agentName,
|
|
9657
|
-
getMeasuredToolDefinitionTokens(modelKey.slice(0, slash), modelKey.slice(slash + 1), agentName)
|
|
9658
|
-
]);
|
|
9659
|
-
}
|
|
9660
|
-
function beginV2LkgRequest(sessionId, modelKey, previousResponseId) {
|
|
9661
|
-
requests.set(sessionId, { kind: "v2", previousResponseId, startedAt: Date.now(), modelKey });
|
|
9662
|
-
}
|
|
9663
|
-
function claimLkgRequestIdentity(sessionId) {
|
|
9664
|
-
const request = requests.get(sessionId);
|
|
9665
|
-
if (!request || claimedRequests.has(request))
|
|
9666
|
-
return;
|
|
9667
|
-
claimedRequests.add(request);
|
|
9668
|
-
return request;
|
|
9669
|
-
}
|
|
9670
|
-
function noteCapturedLkgRequest(args) {
|
|
9671
|
-
const request = args.request;
|
|
9672
|
-
if (!request || request.modelKey !== args.slot.modelKey) {
|
|
9673
|
-
captures.delete(args.sessionId);
|
|
9674
|
-
return;
|
|
9675
|
-
}
|
|
9676
|
-
captures.set(args.sessionId, {
|
|
9677
|
-
request,
|
|
9678
|
-
slot: identity(args.slot),
|
|
9679
|
-
prefixCount: JSON.parse(args.slot.jsonPrefix).length,
|
|
9680
|
-
envelope: envelope(request.modelKey, args.systemPromptTokens, args.agentName)
|
|
9681
|
-
});
|
|
9682
|
-
}
|
|
9683
|
-
function noteLkgProviderResponse(args) {
|
|
9684
|
-
if (!args.responseId || !args.modelKey)
|
|
9685
|
-
return;
|
|
9686
|
-
if (!args.v2 && args.inputTokens === 0 && !args.completedAt && !args.finish && !args.error) {
|
|
9687
|
-
const previous = requests.get(args.sessionId);
|
|
9688
|
-
if (previous?.kind === "v1" && previous.responseId === args.responseId && previous.modelKey === args.modelKey)
|
|
9689
|
-
return;
|
|
9690
|
-
requests.set(args.sessionId, {
|
|
9691
|
-
kind: "v1",
|
|
9692
|
-
responseId: args.responseId,
|
|
9693
|
-
modelKey: args.modelKey
|
|
9694
|
-
});
|
|
9695
|
-
return;
|
|
9696
|
-
}
|
|
9697
|
-
const capture = captures.get(args.sessionId);
|
|
9698
|
-
if (!capture || capture.usage || capture.request.modelKey !== args.modelKey || !Number.isSafeInteger(args.inputTokens) || args.inputTokens <= 0 || providerResponseFailed(args) || !args.completedAt && !args.finish)
|
|
9699
|
-
return;
|
|
9700
|
-
const request = capture.request;
|
|
9701
|
-
if (request.kind === "v1") {
|
|
9702
|
-
if (args.v2 || request.responseId !== args.responseId)
|
|
9703
|
-
return;
|
|
9704
|
-
} else if (!args.v2 || requests.get(args.sessionId) !== request || request.previousResponseId === args.responseId || args.createdAt === undefined || args.createdAt < request.startedAt)
|
|
9705
|
-
return;
|
|
9706
|
-
capture.usage = { responseId: args.responseId, inputTokens: args.inputTokens };
|
|
9707
|
-
}
|
|
9708
|
-
|
|
9709
|
-
// src/hooks/magic-context/lkg-persist.ts
|
|
9710
|
-
import { createHash as createHash4 } from "node:crypto";
|
|
9711
|
-
function parseStringArray(value) {
|
|
9712
|
-
if (typeof value !== "string")
|
|
9713
|
-
return null;
|
|
9714
|
-
let parsed;
|
|
9715
|
-
try {
|
|
9716
|
-
parsed = JSON.parse(value);
|
|
9717
|
-
} catch {
|
|
9718
|
-
return null;
|
|
9719
|
-
}
|
|
9720
|
-
if (!Array.isArray(parsed))
|
|
9721
|
-
return null;
|
|
9722
|
-
const result = [];
|
|
9723
|
-
for (const entry of parsed) {
|
|
9724
|
-
if (typeof entry !== "string" || entry.length === 0)
|
|
9725
|
-
return null;
|
|
9726
|
-
result.push(entry);
|
|
9727
|
-
}
|
|
9728
|
-
return result;
|
|
9729
|
-
}
|
|
9730
|
-
function parseNullableString(value) {
|
|
9731
|
-
if (value === null || value === undefined)
|
|
9732
|
-
return null;
|
|
9733
|
-
return typeof value === "string" ? value : undefined;
|
|
9734
|
-
}
|
|
9735
|
-
function parseNullableInteger(value) {
|
|
9736
|
-
if (value === null || value === undefined)
|
|
9737
|
-
return;
|
|
9738
|
-
return typeof value === "number" && Number.isSafeInteger(value) ? value : undefined;
|
|
9739
|
-
}
|
|
9740
|
-
function parsePersistedLkgSlot(row) {
|
|
9741
|
-
if (!row || typeof row !== "object")
|
|
9742
|
-
return;
|
|
9743
|
-
const record = row;
|
|
9744
|
-
const jsonPrefix = record.json_prefix;
|
|
9745
|
-
const lastInputMessageId = record.last_input_message_id;
|
|
9746
|
-
const capturedAt = record.captured_at;
|
|
9747
|
-
let inputIdsRaw = record.input_id_seq;
|
|
9748
|
-
let piOutputEntryIds;
|
|
9749
|
-
if (typeof inputIdsRaw === "string") {
|
|
9750
|
-
try {
|
|
9751
|
-
const metadata = JSON.parse(inputIdsRaw);
|
|
9752
|
-
if (metadata && !Array.isArray(metadata) && metadata.version === 1 && Array.isArray(metadata.piOutputEntryIds)) {
|
|
9753
|
-
if (!metadata.piOutputEntryIds.every((id) => id === null || typeof id === "string" && id.length > 0))
|
|
9754
|
-
return;
|
|
9755
|
-
piOutputEntryIds = metadata.piOutputEntryIds;
|
|
9756
|
-
inputIdsRaw = JSON.stringify(metadata.inputIds);
|
|
9757
|
-
}
|
|
9758
|
-
} catch {
|
|
9759
|
-
return;
|
|
9760
|
-
}
|
|
9761
|
-
}
|
|
9762
|
-
const inputIdSeq = parseStringArray(inputIdsRaw);
|
|
9763
|
-
const inputContentDigests = parseStringArray(record.input_content_digests);
|
|
9764
|
-
const modelKey = parseNullableString(record.model_key);
|
|
9765
|
-
const providerKey = parseNullableString(record.provider_key);
|
|
9766
|
-
if (typeof jsonPrefix !== "string" || typeof lastInputMessageId !== "string" || lastInputMessageId.length === 0 || typeof capturedAt !== "number" || !Number.isFinite(capturedAt) || inputIdSeq === null || inputContentDigests === null || inputContentDigests.length !== inputIdSeq.length || modelKey === undefined || providerKey === undefined) {
|
|
9767
|
-
return;
|
|
9768
|
-
}
|
|
9769
|
-
if (piOutputEntryIds) {
|
|
9770
|
-
try {
|
|
9771
|
-
const output = JSON.parse(jsonPrefix);
|
|
9772
|
-
const inputs = new Set(inputIdSeq);
|
|
9773
|
-
if (!Array.isArray(output) || output.length !== piOutputEntryIds.length || piOutputEntryIds.some((id) => id !== null && !inputs.has(id)))
|
|
9774
|
-
return;
|
|
9775
|
-
} catch {
|
|
9776
|
-
return;
|
|
9777
|
-
}
|
|
9778
|
-
}
|
|
9779
|
-
let inputContentSignatures;
|
|
9780
|
-
if (record.input_content_signatures !== null && record.input_content_signatures !== undefined) {
|
|
9781
|
-
const parsed = parseStringArray(record.input_content_signatures);
|
|
9782
|
-
if (parsed === null || parsed.length !== inputIdSeq.length)
|
|
9783
|
-
return;
|
|
9784
|
-
inputContentSignatures = parsed;
|
|
9785
|
-
}
|
|
9786
|
-
const slot = {
|
|
9787
|
-
jsonPrefix,
|
|
9788
|
-
inputIdSeq,
|
|
9789
|
-
inputContentDigests,
|
|
9790
|
-
lastInputMessageId,
|
|
9791
|
-
modelKey,
|
|
9792
|
-
providerKey,
|
|
9793
|
-
capturedAt
|
|
9794
|
-
};
|
|
9795
|
-
if (inputContentSignatures)
|
|
9796
|
-
slot.inputContentSignatures = inputContentSignatures;
|
|
9797
|
-
if (piOutputEntryIds)
|
|
9798
|
-
slot.piOutputEntryIds = piOutputEntryIds;
|
|
9799
|
-
const rowVersion = parseNullableInteger(record.row_version);
|
|
9800
|
-
if (rowVersion !== undefined)
|
|
9801
|
-
slot.rowVersion = rowVersion;
|
|
9802
|
-
const captureSequence = parseNullableInteger(record.capture_sequence);
|
|
9803
|
-
if (captureSequence !== undefined)
|
|
9804
|
-
slot.captureSequence = captureSequence;
|
|
9805
|
-
return slot;
|
|
9806
|
-
}
|
|
9807
|
-
var persistedFingerprints = new WeakMap;
|
|
9808
|
-
var PERSISTED_FINGERPRINT_MAX_SESSIONS = 1000;
|
|
9809
|
-
function rememberFingerprint(db, sessionId, fingerprint) {
|
|
9810
|
-
let saved = persistedFingerprints.get(db);
|
|
9811
|
-
if (!saved) {
|
|
9812
|
-
saved = new Map;
|
|
9813
|
-
persistedFingerprints.set(db, saved);
|
|
9814
|
-
}
|
|
9815
|
-
saved.delete(sessionId);
|
|
9816
|
-
if (saved.size >= PERSISTED_FINGERPRINT_MAX_SESSIONS) {
|
|
9817
|
-
const oldest = saved.keys().next().value;
|
|
9818
|
-
if (oldest !== undefined)
|
|
9819
|
-
saved.delete(oldest);
|
|
9820
|
-
}
|
|
9821
|
-
saved.set(sessionId, fingerprint);
|
|
9822
|
-
}
|
|
9823
|
-
function slotFingerprint(slot) {
|
|
9824
|
-
return createHash4("sha256").update(JSON.stringify([
|
|
9825
|
-
slot.jsonPrefix,
|
|
9826
|
-
slot.inputIdSeq,
|
|
9827
|
-
slot.inputContentDigests,
|
|
9828
|
-
slot.inputContentSignatures,
|
|
9829
|
-
slot.piOutputEntryIds,
|
|
9830
|
-
slot.lastInputMessageId,
|
|
9831
|
-
slot.modelKey,
|
|
9832
|
-
slot.providerKey,
|
|
9833
|
-
slot.rowVersion,
|
|
9834
|
-
slot.captureSequence
|
|
9835
|
-
])).digest("hex");
|
|
9836
|
-
}
|
|
9837
|
-
function saveLkgSlotToDb(db, sessionId, slot) {
|
|
9838
|
-
const fingerprint = slotFingerprint(slot);
|
|
9839
|
-
if (persistedFingerprints.get(db)?.get(sessionId) === fingerprint)
|
|
9840
|
-
return true;
|
|
9841
|
-
const layout = layoutLkgPrefix(slot.jsonPrefix);
|
|
9842
|
-
try {
|
|
9843
|
-
db.transaction(() => {
|
|
9844
|
-
const storedHashes = new Map;
|
|
9845
|
-
for (const row of db.prepare("SELECT chunk, hash FROM lkg_slot_chunks WHERE session_id = ?").all(sessionId)) {
|
|
9846
|
-
storedHashes.set(row.chunk, row.hash);
|
|
9847
|
-
}
|
|
9848
|
-
const upsertChunk = db.prepare(`INSERT INTO lkg_slot_chunks (session_id, chunk, hash, body) VALUES (?, ?, ?, ?)
|
|
9849
|
-
ON CONFLICT(session_id, chunk) DO UPDATE SET hash = excluded.hash, body = excluded.body`);
|
|
9850
|
-
for (let index = 0;index < layout.chunks.length; index += 1) {
|
|
9851
|
-
if (storedHashes.get(index) === layout.chunkHashes[index])
|
|
9852
|
-
continue;
|
|
9853
|
-
upsertChunk.run(sessionId, index, layout.chunkHashes[index], layout.chunks[index]);
|
|
9854
|
-
}
|
|
9855
|
-
db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ? AND chunk >= ?").run(sessionId, layout.chunks.length);
|
|
9856
|
-
db.prepare(`INSERT INTO lkg_slots (
|
|
9857
|
-
session_id, json_prefix_chars, json_prefix_chunks, json_prefix_hash,
|
|
9858
|
-
input_id_seq, input_content_digests, input_content_signatures,
|
|
9859
|
-
last_input_message_id, model_key, provider_key,
|
|
9860
|
-
captured_at, row_version, capture_sequence
|
|
9861
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
9862
|
-
ON CONFLICT(session_id) DO UPDATE SET
|
|
9863
|
-
json_prefix_chars = excluded.json_prefix_chars,
|
|
9864
|
-
json_prefix_chunks = excluded.json_prefix_chunks,
|
|
9865
|
-
json_prefix_hash = excluded.json_prefix_hash,
|
|
9866
|
-
input_id_seq = excluded.input_id_seq,
|
|
9867
|
-
input_content_digests = excluded.input_content_digests,
|
|
9868
|
-
input_content_signatures = excluded.input_content_signatures,
|
|
9869
|
-
last_input_message_id = excluded.last_input_message_id,
|
|
9870
|
-
model_key = excluded.model_key,
|
|
9871
|
-
provider_key = excluded.provider_key,
|
|
9872
|
-
captured_at = excluded.captured_at,
|
|
9873
|
-
row_version = excluded.row_version,
|
|
9874
|
-
capture_sequence = excluded.capture_sequence`).run(sessionId, layout.chars, layout.chunks.length, layout.hash, JSON.stringify(slot.piOutputEntryIds ? {
|
|
9875
|
-
version: 1,
|
|
9876
|
-
inputIds: slot.inputIdSeq,
|
|
9877
|
-
piOutputEntryIds: slot.piOutputEntryIds
|
|
9878
|
-
} : slot.inputIdSeq), JSON.stringify(slot.inputContentDigests), slot.inputContentSignatures ? JSON.stringify(slot.inputContentSignatures) : null, slot.lastInputMessageId, slot.modelKey, slot.providerKey, slot.capturedAt, slot.rowVersion ?? null, slot.captureSequence ?? null);
|
|
9879
|
-
}).immediate();
|
|
9880
|
-
rememberFingerprint(db, sessionId, fingerprint);
|
|
9881
|
-
return true;
|
|
9882
|
-
} catch (error) {
|
|
9883
|
-
sessionLog(sessionId, "LKG snapshot persistence failed (in-memory slot retained):", error);
|
|
9884
|
-
return false;
|
|
9885
|
-
}
|
|
9886
|
-
}
|
|
9887
|
-
function clearPersistedLkgSlot(db, sessionId) {
|
|
9888
|
-
try {
|
|
9889
|
-
db.transaction(() => {
|
|
9890
|
-
db.prepare("DELETE FROM lkg_slot_chunks WHERE session_id = ?").run(sessionId);
|
|
9891
|
-
db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
|
|
9892
|
-
}).immediate();
|
|
9893
|
-
persistedFingerprints.get(db)?.delete(sessionId);
|
|
9894
|
-
} catch (error) {
|
|
9895
|
-
sessionLog(sessionId, "LKG snapshot durable clear failed:", error);
|
|
9896
|
-
}
|
|
9897
|
-
}
|
|
9898
|
-
function loadPersistedLkgSlot(db, sessionId) {
|
|
9899
|
-
let row;
|
|
9900
|
-
let chunkRows;
|
|
9901
|
-
try {
|
|
9902
|
-
({ row, chunkRows } = db.transaction(() => {
|
|
9903
|
-
const slotRow = db.prepare("SELECT * FROM lkg_slots WHERE session_id = ?").get(sessionId);
|
|
9904
|
-
if (!slotRow)
|
|
9905
|
-
return { row: undefined, chunkRows: [] };
|
|
9906
|
-
const slices = db.prepare("SELECT chunk, hash, body FROM lkg_slot_chunks WHERE session_id = ? ORDER BY chunk").all(sessionId);
|
|
9907
|
-
return { row: slotRow, chunkRows: slices };
|
|
9908
|
-
}).deferred());
|
|
9909
|
-
} catch (error) {
|
|
9910
|
-
sessionLog(sessionId, "LKG snapshot durable load failed:", error);
|
|
9911
|
-
return;
|
|
9912
|
-
}
|
|
9913
|
-
if (!row)
|
|
9914
|
-
return;
|
|
9915
|
-
const prefix = assembleLkgPrefix({
|
|
9916
|
-
chars: row.json_prefix_chars,
|
|
9917
|
-
chunks: row.json_prefix_chunks,
|
|
9918
|
-
hash: row.json_prefix_hash
|
|
9919
|
-
}, chunkRows);
|
|
9920
|
-
const slot = prefix ? parsePersistedLkgSlot({ ...row, json_prefix: prefix.jsonPrefix }) : undefined;
|
|
9921
|
-
if (!prefix || !slot) {
|
|
9922
|
-
if (!prefix)
|
|
9923
|
-
sessionLog(sessionId, "LKG snapshot slices failed verification; slot cleared");
|
|
9924
|
-
clearPersistedLkgSlot(db, sessionId);
|
|
9925
|
-
return;
|
|
9926
|
-
}
|
|
9927
|
-
return slot;
|
|
9928
|
-
}
|
|
9929
|
-
function pruneStaleLkgSlotsBatch(db, now) {
|
|
9930
|
-
const previousTimeout = db.prepare("PRAGMA busy_timeout").get();
|
|
9931
|
-
const cutoff = now - 7 * 24 * 60 * 60 * 1000;
|
|
9932
|
-
const stale = `captured_at < ? AND NOT EXISTS (
|
|
9933
|
-
SELECT 1 FROM session_projects sp
|
|
9934
|
-
WHERE sp.session_id = lkg_slots.session_id AND sp.updated_at >= ?
|
|
9935
|
-
)`;
|
|
9936
|
-
const slot = db.prepare(`SELECT session_id FROM lkg_slots WHERE ${stale} LIMIT 1`).get(cutoff, cutoff);
|
|
9937
|
-
const chunks = db.prepare(`SELECT rowid FROM lkg_slot_chunks c WHERE
|
|
9938
|
-
session_id = ? OR NOT EXISTS (SELECT 1 FROM lkg_slots s WHERE s.session_id = c.session_id)
|
|
9939
|
-
LIMIT 25`).all(slot?.session_id ?? "");
|
|
9940
|
-
if (!slot && chunks.length === 0)
|
|
9941
|
-
return { slots: 0, chunks: 0 };
|
|
9942
|
-
try {
|
|
9943
|
-
db.exec("PRAGMA busy_timeout = 0");
|
|
9944
|
-
let transactionStartedAt = 0;
|
|
9945
|
-
const changes = db.transaction(() => {
|
|
9946
|
-
transactionStartedAt = performance.now();
|
|
9947
|
-
const removed = slot ? db.prepare(`DELETE FROM lkg_slots WHERE session_id = ? AND ${stale}`).run(slot.session_id, cutoff, cutoff).changes : 0;
|
|
9948
|
-
const removeChunk = db.prepare(`DELETE FROM lkg_slot_chunks WHERE rowid = ? AND NOT EXISTS (
|
|
9949
|
-
SELECT 1 FROM lkg_slots s WHERE s.session_id = lkg_slot_chunks.session_id
|
|
9950
|
-
)`);
|
|
9951
|
-
let removedChunks = 0;
|
|
9952
|
-
for (const { rowid } of chunks)
|
|
9953
|
-
removedChunks += removeChunk.run(rowid).changes;
|
|
9954
|
-
return { slots: removed, chunks: removedChunks };
|
|
9955
|
-
}).immediate();
|
|
9956
|
-
logSlowWriteTransaction("lkg_stale_gc", transactionStartedAt);
|
|
9957
|
-
if (changes.slots && slot)
|
|
9958
|
-
persistedFingerprints.get(db)?.delete(slot.session_id);
|
|
9959
|
-
return changes;
|
|
9960
|
-
} finally {
|
|
9961
|
-
db.exec(`PRAGMA busy_timeout = ${Number(previousTimeout.timeout) || 0}`);
|
|
9962
|
-
}
|
|
9963
|
-
}
|
|
9964
|
-
function pruneStaleLkgSlots(db, now = Date.now()) {
|
|
9965
|
-
return pruneStaleLkgSlotsBatch(db, now).slots;
|
|
9966
|
-
}
|
|
9967
|
-
|
|
9968
|
-
// src/hooks/magic-context/openai-compat-adjacency.ts
|
|
9969
|
-
function assertOpenAiCompatAdjacency(messages) {
|
|
9970
|
-
const violations = [];
|
|
9971
|
-
for (let i = 0;i < messages.length; i++) {
|
|
9972
|
-
const msg = messages[i];
|
|
9973
|
-
if (msg.role !== "assistant" || !msg.tool_calls || msg.tool_calls.length === 0) {
|
|
9974
|
-
continue;
|
|
9975
|
-
}
|
|
9976
|
-
const expectedIds = msg.tool_calls.map((tc) => tc.id);
|
|
9977
|
-
const expectedSet = new Set(expectedIds);
|
|
9978
|
-
const collected = new Map;
|
|
9979
|
-
let j = i + 1;
|
|
9980
|
-
while (j < messages.length && messages[j].role === "tool") {
|
|
9981
|
-
const toolMsg = messages[j];
|
|
9982
|
-
const id = toolMsg.tool_call_id;
|
|
9983
|
-
if (!id) {
|
|
9984
|
-
violations.push({
|
|
9985
|
-
index: i,
|
|
9986
|
-
kind: "unmatched_tool_call_id",
|
|
9987
|
-
detail: `tool message at index ${j} missing tool_call_id`
|
|
9988
|
-
});
|
|
9989
|
-
} else if (!expectedSet.has(id)) {
|
|
9990
|
-
violations.push({
|
|
9991
|
-
index: i,
|
|
9992
|
-
kind: "unmatched_tool_call_id",
|
|
9993
|
-
toolCallId: id,
|
|
9994
|
-
assistantToolCallIds: expectedIds,
|
|
9995
|
-
detail: `tool message at index ${j} references unexpected id ${id}`
|
|
9996
|
-
});
|
|
9997
|
-
} else {
|
|
9998
|
-
collected.set(id, j);
|
|
9999
|
-
}
|
|
10000
|
-
j++;
|
|
10001
|
-
}
|
|
10002
|
-
const followingRoles = messages.slice(i + 1, Math.min(messages.length, i + 4)).map((m) => m.role);
|
|
10003
|
-
const missing = expectedIds.filter((id) => !collected.has(id));
|
|
10004
|
-
if (missing.length > 0) {
|
|
10005
|
-
violations.push({
|
|
10006
|
-
index: i,
|
|
10007
|
-
kind: "missing_tool_messages",
|
|
10008
|
-
assistantToolCallIds: expectedIds,
|
|
10009
|
-
followingRoles,
|
|
10010
|
-
detail: missing.length === expectedIds.length ? `assistant at index ${i} has tool_calls but next messages are not contiguous tool role (following: ${followingRoles.join(", ") || "none"})` : `assistant at index ${i} missing tool results for: ${missing.join(", ")}`
|
|
10011
|
-
});
|
|
10012
|
-
if (j < messages.length && messages[j].role !== "tool") {
|
|
10013
|
-
const last = violations[violations.length - 1];
|
|
10014
|
-
last.detail += `; blocked by ${messages.slice(i + 1, j + 1).map((m, off) => `${m.role}[${i + 1 + off}]`).join(", ")}`;
|
|
10015
|
-
}
|
|
10016
|
-
}
|
|
10017
|
-
}
|
|
10018
|
-
for (let i = 0;i < messages.length; i++) {
|
|
10019
|
-
if (messages[i].role !== "tool")
|
|
10020
|
-
continue;
|
|
10021
|
-
const id = messages[i].tool_call_id ?? "";
|
|
10022
|
-
if (!id)
|
|
10023
|
-
continue;
|
|
10024
|
-
let found = false;
|
|
10025
|
-
for (let k = i - 1;k >= 0; k--) {
|
|
10026
|
-
const prev = messages[k];
|
|
10027
|
-
if (prev.role === "assistant" && prev.tool_calls?.some((tc) => tc.id === id)) {
|
|
10028
|
-
const between = messages.slice(k + 1, i);
|
|
10029
|
-
if (between.every((m) => m.role === "tool")) {
|
|
10030
|
-
found = true;
|
|
10031
|
-
}
|
|
10032
|
-
break;
|
|
10033
|
-
}
|
|
10034
|
-
if (prev.role === "assistant" || prev.role === "user")
|
|
10035
|
-
break;
|
|
10036
|
-
}
|
|
10037
|
-
if (!found) {
|
|
10038
|
-
violations.push({
|
|
10039
|
-
index: i,
|
|
10040
|
-
kind: "orphan_tool_message",
|
|
10041
|
-
toolCallId: id,
|
|
10042
|
-
detail: `tool message at index ${i} is not immediately after its assistant tool_calls`
|
|
10043
|
-
});
|
|
10044
|
-
}
|
|
10045
|
-
}
|
|
10046
|
-
return { ok: violations.length === 0, violations };
|
|
10047
|
-
}
|
|
10048
|
-
|
|
10049
|
-
// src/hooks/magic-context/lkg-replay.ts
|
|
10050
|
-
function canonicalLkgModelKeys(modelKey, providerKey) {
|
|
10051
|
-
const canonicalModelKey = modelKey ? piModelRefToCanonical(modelKey) : null;
|
|
10052
|
-
const slash = canonicalModelKey?.indexOf("/") ?? -1;
|
|
10053
|
-
return {
|
|
10054
|
-
modelKey: canonicalModelKey,
|
|
10055
|
-
providerKey: slash > 0 && canonicalModelKey ? canonicalModelKey.slice(0, slash) : providerKey
|
|
10056
|
-
};
|
|
10057
|
-
}
|
|
10058
|
-
function resolveLkgModelKeys(messages) {
|
|
10059
|
-
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
10060
|
-
const info = messages[index]?.info;
|
|
10061
|
-
const nested = info?.model;
|
|
10062
|
-
if (nested && typeof nested === "object") {
|
|
10063
|
-
const provider = nested.providerID;
|
|
10064
|
-
const model = nested.modelID;
|
|
10065
|
-
if (typeof provider === "string" && typeof model === "string") {
|
|
10066
|
-
return canonicalLkgModelKeys(`${provider}/${model}`, provider);
|
|
10067
|
-
}
|
|
10068
|
-
}
|
|
10069
|
-
const provider = info?.providerID;
|
|
10070
|
-
const model = info?.modelID;
|
|
10071
|
-
if (typeof provider === "string" && typeof model === "string") {
|
|
10072
|
-
return canonicalLkgModelKeys(`${provider}/${model}`, provider);
|
|
10073
|
-
}
|
|
10074
|
-
}
|
|
10075
|
-
return { modelKey: null, providerKey: null };
|
|
10076
|
-
}
|
|
10077
|
-
function projectLkgEntry(messages) {
|
|
10078
|
-
return projectEntryWithDigests(messages, messages.map(lkgContentDigest));
|
|
10079
|
-
}
|
|
10080
|
-
function createLkgEntryProjector(options = {}) {
|
|
10081
|
-
const priors = new Map;
|
|
10082
|
-
const maxBytes = options.maxBytes ?? 64 * 1024 * 1024;
|
|
10083
|
-
let bytes = 0;
|
|
10084
|
-
return (sessionId, messages) => {
|
|
10085
|
-
const prior = priors.get(sessionId);
|
|
10086
|
-
const snapshots = messages.map((message) => ({
|
|
10087
|
-
id: typeof message.info?.id === "string" ? message.info.id : "",
|
|
10088
|
-
fields: lkgContentFields(message)
|
|
10089
|
-
}));
|
|
10090
|
-
let reused = 0;
|
|
10091
|
-
const digests = snapshots.map((snapshot) => {
|
|
10092
|
-
const cached = prior?.entries.get(snapshot.id);
|
|
10093
|
-
if (snapshot.fields && cached && exactReusablePrefix([snapshot], [cached.snapshot]) === 1) {
|
|
10094
|
-
reused += 1;
|
|
10095
|
-
return cached.digest;
|
|
10096
|
-
}
|
|
10097
|
-
if (!snapshot.fields)
|
|
10098
|
-
return null;
|
|
10099
|
-
return options.maxBytes === undefined ? memoizedLkgContentDigestFromFields(snapshot.id, snapshot.fields) : lkgContentDigestFromFields(snapshot.fields);
|
|
10100
|
-
});
|
|
10101
|
-
if (prior) {
|
|
10102
|
-
bytes -= prior.bytes;
|
|
10103
|
-
priors.delete(sessionId);
|
|
10104
|
-
}
|
|
10105
|
-
let size = 0;
|
|
10106
|
-
let retainedCount = 0;
|
|
10107
|
-
const retained = new Map;
|
|
10108
|
-
snapshots.forEach((snapshot, index) => {
|
|
10109
|
-
const entrySize = snapshot.id.length * 2 + (snapshot.fields?.reduce((sum, field) => sum + 16 + (typeof field === "string" ? field.length * 2 : 0), 0) ?? 0) + 80 + 86;
|
|
10110
|
-
if (!snapshot.fields || retained.has(snapshot.id) || size + entrySize > maxBytes)
|
|
10111
|
-
return;
|
|
10112
|
-
size += entrySize;
|
|
10113
|
-
retainedCount += 1;
|
|
10114
|
-
retained.set(snapshot.id, {
|
|
10115
|
-
snapshot,
|
|
10116
|
-
digest: digests[index] ?? null
|
|
10117
|
-
});
|
|
10118
|
-
});
|
|
10119
|
-
if (size <= maxBytes && retainedCount > 0) {
|
|
10120
|
-
while (priors.size >= 16 || bytes + size > maxBytes) {
|
|
10121
|
-
const oldest = priors.entries().next().value;
|
|
10122
|
-
if (!oldest)
|
|
10123
|
-
break;
|
|
10124
|
-
bytes -= oldest[1].bytes;
|
|
10125
|
-
priors.delete(oldest[0]);
|
|
10126
|
-
}
|
|
10127
|
-
priors.set(sessionId, {
|
|
10128
|
-
entries: retained,
|
|
10129
|
-
bytes: size
|
|
10130
|
-
});
|
|
10131
|
-
bytes += size;
|
|
10132
|
-
}
|
|
10133
|
-
options.onReuse?.({ reused, retained: retainedCount, retainedBytes: size });
|
|
10134
|
-
return projectEntryWithDigests(messages, digests);
|
|
10135
|
-
};
|
|
10136
|
-
}
|
|
10137
|
-
function projectEntryWithDigests(messages, digests) {
|
|
10138
|
-
return messages.map((message, index) => {
|
|
10139
|
-
const info = messageInfo(message);
|
|
10140
|
-
const time = info.time;
|
|
10141
|
-
const timeRecord = time && typeof time === "object" ? time : null;
|
|
10142
|
-
const timeCandidates = [
|
|
10143
|
-
timeRecord?.created,
|
|
10144
|
-
info.timeCreated,
|
|
10145
|
-
info.time_created,
|
|
10146
|
-
info.createdAt,
|
|
10147
|
-
info.created_at
|
|
10148
|
-
];
|
|
10149
|
-
let timeCreated = null;
|
|
10150
|
-
for (const value of timeCandidates) {
|
|
10151
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
10152
|
-
timeCreated = value;
|
|
10153
|
-
break;
|
|
10154
|
-
}
|
|
10155
|
-
}
|
|
10156
|
-
let hasIncompleteTool = false;
|
|
10157
|
-
for (const rawPart of messageParts(message)) {
|
|
10158
|
-
if (!rawPart || typeof rawPart !== "object")
|
|
10159
|
-
continue;
|
|
10160
|
-
const part = rawPart;
|
|
10161
|
-
if (part.type !== "tool" || part.providerExecuted === true)
|
|
10162
|
-
continue;
|
|
10163
|
-
const state = part.state;
|
|
10164
|
-
const status = state && typeof state === "object" ? state.status : undefined;
|
|
10165
|
-
if (status !== "completed") {
|
|
10166
|
-
hasIncompleteTool = true;
|
|
10167
|
-
break;
|
|
10168
|
-
}
|
|
10169
|
-
}
|
|
10170
|
-
const id = info.id;
|
|
10171
|
-
const projection = {
|
|
10172
|
-
id: typeof id === "string" && id.length > 0 ? id : null,
|
|
10173
|
-
role: typeof info.role === "string" ? info.role : undefined,
|
|
10174
|
-
synthetic: info.synthetic === true,
|
|
10175
|
-
timeCreated,
|
|
10176
|
-
finish: info.finish,
|
|
10177
|
-
hasIncompleteTool
|
|
10178
|
-
};
|
|
10179
|
-
const contentDigest = digests[index] ?? null;
|
|
10180
|
-
Object.defineProperty(projection, "contentDigest", {
|
|
10181
|
-
value: () => contentDigest,
|
|
10182
|
-
enumerable: false
|
|
10183
|
-
});
|
|
10184
|
-
return projection;
|
|
10185
|
-
});
|
|
10186
|
-
}
|
|
10187
|
-
function recordValue(info, key) {
|
|
10188
|
-
return info && typeof info === "object" ? info[key] : undefined;
|
|
10189
|
-
}
|
|
10190
|
-
function messageInfo(message) {
|
|
10191
|
-
if (message.info && typeof message.info === "object")
|
|
10192
|
-
return message.info;
|
|
10193
|
-
return message;
|
|
10194
|
-
}
|
|
10195
|
-
function messageParts(message) {
|
|
10196
|
-
return Array.isArray(message.parts) ? message.parts : [];
|
|
10197
|
-
}
|
|
10198
|
-
function isSynthetic(message) {
|
|
10199
|
-
return recordValue(messageInfo(message), "synthetic") === true;
|
|
10200
|
-
}
|
|
10201
|
-
function hasSyntheticParts(message) {
|
|
10202
|
-
const parts = messageParts(message);
|
|
10203
|
-
return parts.length > 0 && parts.every((part) => {
|
|
10204
|
-
return Boolean(part && typeof part === "object" && part.synthetic === true);
|
|
10205
|
-
});
|
|
10206
|
-
}
|
|
10207
|
-
function isSyntheticOutput(message) {
|
|
10208
|
-
return isSynthetic(message) || hasSyntheticParts(message);
|
|
10209
|
-
}
|
|
10210
|
-
function messageRole(message) {
|
|
10211
|
-
const infoRole = recordValue(messageInfo(message), "role");
|
|
10212
|
-
if (typeof infoRole === "string")
|
|
10213
|
-
return infoRole;
|
|
10214
|
-
const role = recordValue(message, "role");
|
|
10215
|
-
return typeof role === "string" ? role : undefined;
|
|
10216
|
-
}
|
|
10217
|
-
function messageId(message) {
|
|
10218
|
-
const id = recordValue(messageInfo(message), "id") ?? recordValue(message, "id");
|
|
10219
|
-
return typeof id === "string" && id.length > 0 ? id : null;
|
|
10220
|
-
}
|
|
10221
|
-
function latestAssistant(messages) {
|
|
10222
|
-
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
10223
|
-
if (messages[index].role === "assistant")
|
|
10224
|
-
return messages[index];
|
|
10225
|
-
}
|
|
10226
|
-
return null;
|
|
10227
|
-
}
|
|
10228
|
-
function isRealUser(message) {
|
|
10229
|
-
return message.role === "user" && !message.synthetic && message.id !== null;
|
|
10230
|
-
}
|
|
10231
|
-
function assistantIsActive(message) {
|
|
10232
|
-
return message.finish === "tool-calls" || message.hasIncompleteTool;
|
|
10233
|
-
}
|
|
10234
|
-
function findLkgAnchor(messages) {
|
|
10235
|
-
const assistant = latestAssistant(messages);
|
|
10236
|
-
const assistantTime = assistant?.timeCreated ?? null;
|
|
10237
|
-
if (assistant && assistantTime === null)
|
|
10238
|
-
return null;
|
|
10239
|
-
let anchor = -1;
|
|
10240
|
-
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
10241
|
-
const message = messages[index];
|
|
10242
|
-
if (!isRealUser(message))
|
|
10243
|
-
continue;
|
|
10244
|
-
if (assistant && assistantIsActive(assistant)) {
|
|
10245
|
-
if (assistantTime === null || message.timeCreated === null || message.timeCreated <= assistantTime) {
|
|
10246
|
-
continue;
|
|
10247
|
-
}
|
|
10248
|
-
}
|
|
10249
|
-
anchor = index;
|
|
10250
|
-
break;
|
|
10251
|
-
}
|
|
10252
|
-
return anchor >= 0 ? anchor : null;
|
|
10253
|
-
}
|
|
10254
|
-
function asEntryProjection(input) {
|
|
10255
|
-
if (input.length === 0 || "hasIncompleteTool" in input[0]) {
|
|
10256
|
-
return input;
|
|
10257
|
-
}
|
|
10258
|
-
return projectLkgEntry(input);
|
|
10259
|
-
}
|
|
10260
|
-
function outputMessageIsPostAnchor(message, inputIndexById, anchorIndex) {
|
|
10261
|
-
const id = messageId(message);
|
|
10262
|
-
if (id !== null) {
|
|
10263
|
-
const inputIndex = inputIndexById.get(id);
|
|
10264
|
-
if (inputIndex !== undefined)
|
|
10265
|
-
return inputIndex > anchorIndex;
|
|
10266
|
-
if (!isSyntheticOutput(message))
|
|
10267
|
-
return null;
|
|
10268
|
-
const linked = ["sourceMessageId", "ownerMessageId", "anchorMessageId", "messageId"].map((key) => recordValue(messageInfo(message), key)).find((value) => typeof value === "string");
|
|
10269
|
-
if (typeof linked === "string") {
|
|
10270
|
-
const linkedIndex = inputIndexById.get(linked);
|
|
10271
|
-
if (linkedIndex === undefined)
|
|
10272
|
-
return null;
|
|
10273
|
-
return linkedIndex > anchorIndex;
|
|
10274
|
-
}
|
|
10275
|
-
return false;
|
|
10276
|
-
}
|
|
10277
|
-
if (!isSyntheticOutput(message))
|
|
10278
|
-
return null;
|
|
10279
|
-
const linked = ["sourceMessageId", "ownerMessageId", "anchorMessageId"].map((key) => recordValue(message.info, key)).find((value) => typeof value === "string");
|
|
10280
|
-
if (typeof linked !== "string")
|
|
10281
|
-
return false;
|
|
10282
|
-
const linkedIndex = inputIndexById.get(linked);
|
|
10283
|
-
return linkedIndex === undefined ? null : linkedIndex > anchorIndex;
|
|
10284
|
-
}
|
|
10285
|
-
function buildLkgPrefix(input, output) {
|
|
10286
|
-
const projected = asEntryProjection(input);
|
|
10287
|
-
const anchorIndex = findLkgAnchor(projected);
|
|
10288
|
-
if (anchorIndex === null)
|
|
10289
|
-
return null;
|
|
10290
|
-
const ids = projected.map((message) => message.id);
|
|
10291
|
-
if (ids.some((id) => id === null))
|
|
10292
|
-
return null;
|
|
10293
|
-
const validIds = ids;
|
|
10294
|
-
if (new Set(validIds).size !== validIds.length)
|
|
10295
|
-
return null;
|
|
10296
|
-
const anchorMessageId = validIds[anchorIndex];
|
|
10297
|
-
const inputContentDigests = projected.slice(0, anchorIndex + 1).map((message) => message.contentDigest?.() ?? null);
|
|
10298
|
-
if (inputContentDigests.some((digest) => digest === null))
|
|
10299
|
-
return null;
|
|
10300
|
-
const inputIndexById = new Map(validIds.map((id, index) => [id, index]));
|
|
10301
|
-
const prefix = [];
|
|
10302
|
-
for (const message of output) {
|
|
10303
|
-
const postAnchor = outputMessageIsPostAnchor(message, inputIndexById, anchorIndex);
|
|
10304
|
-
if (postAnchor === null)
|
|
10305
|
-
return null;
|
|
10306
|
-
if (!postAnchor)
|
|
10307
|
-
prefix.push(message);
|
|
10308
|
-
}
|
|
10309
|
-
let jsonPrefix;
|
|
10310
|
-
try {
|
|
10311
|
-
jsonPrefix = JSON.stringify(prefix);
|
|
10312
|
-
if (typeof jsonPrefix !== "string")
|
|
10313
|
-
return null;
|
|
10314
|
-
} catch {
|
|
10315
|
-
return null;
|
|
10316
|
-
}
|
|
10317
|
-
return {
|
|
10318
|
-
anchorIndex,
|
|
10319
|
-
anchorMessageId,
|
|
10320
|
-
inputIdSeq: validIds.slice(0, anchorIndex + 1),
|
|
10321
|
-
inputContentDigests,
|
|
10322
|
-
jsonPrefix
|
|
10323
|
-
};
|
|
10324
|
-
}
|
|
10325
|
-
function captureLkgSlot(args) {
|
|
10326
|
-
const built = buildLkgPrefix(args.input, args.output);
|
|
10327
|
-
if (!built)
|
|
10328
|
-
return false;
|
|
10329
|
-
const modelKeys = canonicalLkgModelKeys(args.modelKey, args.providerKey);
|
|
10330
|
-
const slot = {
|
|
10331
|
-
jsonPrefix: built.jsonPrefix,
|
|
10332
|
-
inputIdSeq: built.inputIdSeq,
|
|
10333
|
-
inputContentDigests: built.inputContentDigests,
|
|
10334
|
-
lastInputMessageId: built.anchorMessageId,
|
|
10335
|
-
modelKey: modelKeys.modelKey,
|
|
10336
|
-
providerKey: modelKeys.providerKey,
|
|
10337
|
-
capturedAt: args.capturedAt ?? Date.now()
|
|
10338
|
-
};
|
|
10339
|
-
const captured = captureSlot(args.sessionId, slot);
|
|
10340
|
-
if (captured)
|
|
10341
|
-
noteCapturedLkgRequest({
|
|
10342
|
-
sessionId: args.sessionId,
|
|
10343
|
-
slot,
|
|
10344
|
-
request: built.anchorIndex === args.input.length - 1 ? claimLkgRequestIdentity(args.sessionId) : undefined,
|
|
10345
|
-
systemPromptTokens: args.systemPromptTokens ?? 0,
|
|
10346
|
-
agentName: args.agentName
|
|
10347
|
-
});
|
|
10348
|
-
return captured;
|
|
10349
|
-
}
|
|
10350
|
-
function entryIdsAreValid(slot, entryIds) {
|
|
10351
|
-
if (slot.inputIdSeq.length === 0 || entryIds.length < slot.inputIdSeq.length)
|
|
10352
|
-
return false;
|
|
10353
|
-
if (slot.inputIdSeq[slot.inputIdSeq.length - 1] !== slot.lastInputMessageId)
|
|
10354
|
-
return false;
|
|
10355
|
-
const seen = new Set;
|
|
10356
|
-
for (const id of entryIds) {
|
|
10357
|
-
if (!id || seen.has(id))
|
|
10358
|
-
return false;
|
|
10359
|
-
seen.add(id);
|
|
10360
|
-
}
|
|
10361
|
-
if (entryIds.indexOf(slot.lastInputMessageId) !== slot.inputIdSeq.length - 1)
|
|
10362
|
-
return false;
|
|
10363
|
-
for (let index = 0;index < slot.inputIdSeq.length; index += 1) {
|
|
10364
|
-
if (entryIds[index] !== slot.inputIdSeq[index])
|
|
10365
|
-
return false;
|
|
10366
|
-
}
|
|
10367
|
-
return true;
|
|
10368
|
-
}
|
|
10369
|
-
function entryContentIsValid(slot, entryDigests) {
|
|
10370
|
-
return entryDigests.length >= slot.inputContentDigests.length && slot.inputContentDigests.every((digest, index) => entryDigests[index] === digest);
|
|
10371
|
-
}
|
|
10372
|
-
function partCallIds(message) {
|
|
10373
|
-
const ids = [];
|
|
10374
|
-
for (const rawPart of messageParts(message)) {
|
|
10375
|
-
if (!rawPart || typeof rawPart !== "object")
|
|
10376
|
-
continue;
|
|
10377
|
-
const part = rawPart;
|
|
10378
|
-
if (part.type !== "tool" && part.type !== "tool_use")
|
|
10379
|
-
continue;
|
|
10380
|
-
const callId = part.callID ?? part.callId ?? part.id;
|
|
10381
|
-
if (typeof callId === "string" && callId.length > 0)
|
|
10382
|
-
ids.push(callId);
|
|
10383
|
-
}
|
|
10384
|
-
return ids;
|
|
10385
|
-
}
|
|
10386
|
-
function partResultIds(message) {
|
|
10387
|
-
const ids = [];
|
|
10388
|
-
for (const rawPart of messageParts(message)) {
|
|
10389
|
-
if (!rawPart || typeof rawPart !== "object")
|
|
10390
|
-
continue;
|
|
10391
|
-
const part = rawPart;
|
|
10392
|
-
if (part.type !== "tool_result" && part.type !== "tool-result")
|
|
10393
|
-
continue;
|
|
10394
|
-
const callId = part.tool_call_id ?? part.tool_use_id ?? part.callID ?? part.callId;
|
|
10395
|
-
if (typeof callId === "string" && callId.length > 0)
|
|
10396
|
-
ids.push(callId);
|
|
10397
|
-
}
|
|
10398
|
-
return ids;
|
|
10399
|
-
}
|
|
10400
|
-
function partIsReasoning(part) {
|
|
10401
|
-
return Boolean(part && typeof part === "object" && part.type === "reasoning");
|
|
10402
|
-
}
|
|
10403
|
-
function partIsAnthropicThinking(part) {
|
|
10404
|
-
if (!part || typeof part !== "object")
|
|
10405
|
-
return false;
|
|
10406
|
-
const type = part.type;
|
|
10407
|
-
return type === "thinking" || type === "reasoning" || type === "redacted_thinking";
|
|
10408
|
-
}
|
|
10409
|
-
function partEndsAnthropicAssistantRun(part) {
|
|
10410
|
-
if (!part || typeof part !== "object")
|
|
10411
|
-
return false;
|
|
10412
|
-
const value = part;
|
|
10413
|
-
if (value.type !== "tool" || value.providerExecuted === true || !value.state || typeof value.state !== "object") {
|
|
10414
|
-
return false;
|
|
10415
|
-
}
|
|
10416
|
-
const status = value.state.status;
|
|
10417
|
-
return status === "completed" || status === "error";
|
|
10418
|
-
}
|
|
10419
|
-
function partIsOpenCodeStepMetadata(part) {
|
|
10420
|
-
if (!part || typeof part !== "object")
|
|
10421
|
-
return false;
|
|
10422
|
-
const type = part.type;
|
|
10423
|
-
return type === "step-start" || type === "step-finish";
|
|
10424
|
-
}
|
|
10425
|
-
function validateAnthropicReasoningRuns(messages) {
|
|
10426
|
-
let index = 0;
|
|
10427
|
-
while (index < messages.length) {
|
|
10428
|
-
if (messageRole(messages[index]) !== "assistant") {
|
|
10429
|
-
index += 1;
|
|
10430
|
-
continue;
|
|
10431
|
-
}
|
|
10432
|
-
let firstMessageInRun = null;
|
|
10433
|
-
let sawOtherContent = false;
|
|
10434
|
-
while (index < messages.length && messageRole(messages[index]) === "assistant") {
|
|
10435
|
-
for (const part of messageParts(messages[index])) {
|
|
10436
|
-
if (partEndsAnthropicAssistantRun(part)) {
|
|
10437
|
-
firstMessageInRun = null;
|
|
10438
|
-
sawOtherContent = false;
|
|
10439
|
-
} else if (!partIsOpenCodeStepMetadata(part)) {
|
|
10440
|
-
if (firstMessageInRun === null)
|
|
10441
|
-
firstMessageInRun = index;
|
|
10442
|
-
if (partIsAnthropicThinking(part)) {
|
|
10443
|
-
if (sawOtherContent || index !== firstMessageInRun)
|
|
10444
|
-
return false;
|
|
10445
|
-
} else {
|
|
10446
|
-
sawOtherContent = true;
|
|
10447
|
-
}
|
|
10448
|
-
}
|
|
10449
|
-
}
|
|
10450
|
-
index += 1;
|
|
10451
|
-
}
|
|
10452
|
-
}
|
|
10453
|
-
return true;
|
|
10454
|
-
}
|
|
10455
|
-
function validateLkgSeamBoundary(prefix, tail) {
|
|
10456
|
-
const last = prefix[prefix.length - 1];
|
|
10457
|
-
const first = tail[0];
|
|
10458
|
-
if (!last || !first)
|
|
10459
|
-
return true;
|
|
10460
|
-
const lastCalls = partCallIds(last);
|
|
10461
|
-
if (lastCalls.length === 0)
|
|
10462
|
-
return true;
|
|
10463
|
-
const firstCalls = new Set([...partCallIds(first), ...partResultIds(first)]);
|
|
10464
|
-
if (messageRole(first) === "tool" || lastCalls.some((callId) => firstCalls.has(callId)))
|
|
10465
|
-
return false;
|
|
10466
|
-
return !messageParts(last).some((part) => {
|
|
10467
|
-
if (!part || typeof part !== "object")
|
|
10468
|
-
return false;
|
|
10469
|
-
const value = part;
|
|
10470
|
-
if (value.type !== "tool")
|
|
10471
|
-
return false;
|
|
10472
|
-
const state = value.state;
|
|
10473
|
-
return !state || typeof state !== "object" || state.status !== "completed";
|
|
10474
|
-
});
|
|
10475
|
-
}
|
|
10476
|
-
function validateLkgSeam(prefix, tail, providerKey) {
|
|
10477
|
-
const all = [...prefix, ...tail];
|
|
10478
|
-
const ids = new Set;
|
|
10479
|
-
const calls = new Set;
|
|
10480
|
-
const results = new Set;
|
|
10481
|
-
for (const message of all) {
|
|
10482
|
-
const id = messageId(message);
|
|
10483
|
-
if (id !== null) {
|
|
10484
|
-
if (ids.has(id))
|
|
10485
|
-
return false;
|
|
10486
|
-
ids.add(id);
|
|
10487
|
-
}
|
|
10488
|
-
for (const callId of partCallIds(message)) {
|
|
10489
|
-
if (calls.has(callId))
|
|
10490
|
-
return false;
|
|
10491
|
-
calls.add(callId);
|
|
10492
|
-
}
|
|
10493
|
-
for (const callId of partResultIds(message)) {
|
|
10494
|
-
if (results.has(callId))
|
|
10495
|
-
return false;
|
|
10496
|
-
results.add(callId);
|
|
10497
|
-
}
|
|
10498
|
-
if (messageRole(message) !== "assistant" && messageParts(message).some(partIsReasoning))
|
|
10499
|
-
return false;
|
|
10500
|
-
if (providerKey !== "anthropic" && messageParts(message).some((part) => {
|
|
10501
|
-
if (!part || typeof part !== "object")
|
|
10502
|
-
return false;
|
|
10503
|
-
const value = part;
|
|
10504
|
-
return (value.type === "text" || value.type === "reasoning") && value.text === "";
|
|
10505
|
-
}))
|
|
10506
|
-
return false;
|
|
10507
|
-
}
|
|
10508
|
-
if (!validateLkgSeamBoundary(prefix, tail))
|
|
10509
|
-
return false;
|
|
10510
|
-
const wireCandidates = all.map((message) => message);
|
|
10511
|
-
if (wireCandidates.every((message) => typeof message.role === "string")) {
|
|
10512
|
-
const adjacency = assertOpenAiCompatAdjacency(wireCandidates);
|
|
10513
|
-
if (!adjacency.ok)
|
|
10514
|
-
return false;
|
|
10515
|
-
const wireCallIds = new Set;
|
|
10516
|
-
for (const wireMessage of wireCandidates) {
|
|
10517
|
-
for (const call of wireMessage.tool_calls ?? []) {
|
|
10518
|
-
if (wireCallIds.has(call.id))
|
|
10519
|
-
return false;
|
|
10520
|
-
wireCallIds.add(call.id);
|
|
10521
|
-
}
|
|
10522
|
-
}
|
|
10523
|
-
}
|
|
10524
|
-
return true;
|
|
10525
|
-
}
|
|
10526
|
-
function replayLkg(args) {
|
|
10527
|
-
const slot = getSlot(args.sessionId);
|
|
10528
|
-
if (!slot)
|
|
10529
|
-
return { ok: false, reason: "lkg_invalidated_reshape" };
|
|
10530
|
-
const requestedModelKeys = canonicalLkgModelKeys(args.modelKey, args.providerKey);
|
|
10531
|
-
const capturedModelKeys = canonicalLkgModelKeys(slot.modelKey, slot.providerKey);
|
|
10532
|
-
if (capturedModelKeys.modelKey !== requestedModelKeys.modelKey || capturedModelKeys.providerKey !== requestedModelKeys.providerKey) {
|
|
10533
|
-
dropSlot(args.sessionId, "lkg_model_mismatch");
|
|
10534
|
-
return { ok: false, reason: "lkg_model_mismatch" };
|
|
10535
|
-
}
|
|
10536
|
-
const entry = args.entry ?? noteEntry(args.sessionId, args.messages);
|
|
10537
|
-
if (!entry || entry.anchorIndex !== slot.inputIdSeq.length - 1 || !entryIdsAreValid(slot, entry.entryInputIds)) {
|
|
10538
|
-
dropSlot(args.sessionId, "lkg_invalidated_reshape");
|
|
10539
|
-
return { ok: false, reason: "lkg_invalidated_reshape" };
|
|
10540
|
-
}
|
|
10541
|
-
if (!entryContentIsValid(slot, entry.entryContentDigests)) {
|
|
10542
|
-
dropSlot(args.sessionId, "lkg_content_mismatch");
|
|
10543
|
-
return { ok: false, reason: "lkg_content_mismatch" };
|
|
10544
|
-
}
|
|
10545
|
-
let prefix;
|
|
10546
|
-
try {
|
|
10547
|
-
const parsed = JSON.parse(slot.jsonPrefix);
|
|
10548
|
-
if (!Array.isArray(parsed))
|
|
10549
|
-
throw new Error("prefix is not an array");
|
|
10550
|
-
prefix = parsed;
|
|
10551
|
-
} catch {
|
|
10552
|
-
dropSlot(args.sessionId, "lkg_seam_invalid");
|
|
10553
|
-
return { ok: false, reason: "lkg_seam_invalid" };
|
|
10554
|
-
}
|
|
10555
|
-
const replayed = [...prefix, ...entry.pristineTail];
|
|
10556
|
-
args.prepareReplay?.(replayed);
|
|
10557
|
-
if (!args.skipSeamValidation) {
|
|
10558
|
-
if (!validateLkgSeamBoundary(prefix, entry.pristineTail)) {
|
|
10559
|
-
dropSlot(args.sessionId, "lkg_unsafe_seam");
|
|
10560
|
-
return { ok: false, reason: "lkg_unsafe_seam" };
|
|
10561
|
-
}
|
|
10562
|
-
if (!validateLkgSeam(prefix, entry.pristineTail, requestedModelKeys.providerKey)) {
|
|
10563
|
-
dropSlot(args.sessionId, "lkg_seam_invalid");
|
|
10564
|
-
return { ok: false, reason: "lkg_seam_invalid" };
|
|
10565
|
-
}
|
|
10566
|
-
}
|
|
10567
|
-
if (requestedModelKeys.providerKey === "anthropic" && !validateAnthropicReasoningRuns(replayed)) {
|
|
10568
|
-
dropSlot(args.sessionId, "lkg_anthropic_reasoning_run_invalid");
|
|
10569
|
-
return { ok: false, reason: "lkg_anthropic_reasoning_run_invalid" };
|
|
10570
|
-
}
|
|
10571
|
-
return { ok: true, messages: replayed };
|
|
10572
|
-
}
|
|
10573
|
-
|
|
10574
9946
|
// src/hooks/magic-context/lkg-replay-fit.ts
|
|
10575
9947
|
var RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN = 4;
|
|
10576
9948
|
function lkgReplayLimit(args) {
|
|
@@ -10637,7 +10009,7 @@ class StorageBusyRefusalError extends Error {
|
|
|
10637
10009
|
}
|
|
10638
10010
|
|
|
10639
10011
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
10640
|
-
import { createHash as
|
|
10012
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
10641
10013
|
|
|
10642
10014
|
// src/agents/magic-context-prompt.ts
|
|
10643
10015
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -10780,8 +10152,160 @@ ${BASE_INTRO(memoryEnabled, temporalAwarenessEnabled)}${cavemanWarning}
|
|
|
10780
10152
|
${SELF_TAG_GUIDANCE}${languageGuidance}`;
|
|
10781
10153
|
}
|
|
10782
10154
|
|
|
10155
|
+
// src/hooks/magic-context/system-prompt-dates.ts
|
|
10156
|
+
function replaceHostDates(prompt, replace) {
|
|
10157
|
+
const fields = /<(plugin-env|environment|env)>[\s\S]*?<\/\1>|Today's date: [^\r\n<]+/g;
|
|
10158
|
+
return prompt.replace(fields, (block) => block.replace(/(^[\t ]*(?:Date|Today's date):[\t ]*)([^\r\n<]+)/gm, (_line, label, date) => `${label}${replace(date)}`));
|
|
10159
|
+
}
|
|
10160
|
+
function systemPromptDates(prompt, sticky) {
|
|
10161
|
+
const values = [];
|
|
10162
|
+
replaceHostDates(prompt, (date) => {
|
|
10163
|
+
values.push(date);
|
|
10164
|
+
return date;
|
|
10165
|
+
});
|
|
10166
|
+
const prior = sticky ? JSON.parse(sticky) : [];
|
|
10167
|
+
let index = 0;
|
|
10168
|
+
const stable = replaceHostDates(prompt, (date) => prior[index++] ?? date);
|
|
10169
|
+
return { live: values.length ? JSON.stringify(values) : undefined, stable };
|
|
10170
|
+
}
|
|
10171
|
+
|
|
10172
|
+
// src/hooks/magic-context/system-date-refresh.ts
|
|
10173
|
+
var channels = new WeakMap;
|
|
10174
|
+
var outputUpdates = new WeakMap;
|
|
10175
|
+
var outputIdentities = new WeakMap;
|
|
10176
|
+
var outputRequests = new WeakMap;
|
|
10177
|
+
function systemDateTurnId(messages) {
|
|
10178
|
+
const start = activeAnthropicTurnStart(messages, true);
|
|
10179
|
+
if (start === undefined)
|
|
10180
|
+
return;
|
|
10181
|
+
const message = messages[start - 1];
|
|
10182
|
+
const id = message.info?.id ?? message.id;
|
|
10183
|
+
return typeof id === "string" && id.length > 0 ? id : undefined;
|
|
10184
|
+
}
|
|
10185
|
+
function bindSystemDateRequestIdentity(output, identity) {
|
|
10186
|
+
outputIdentities.set(output, identity);
|
|
10187
|
+
}
|
|
10188
|
+
function systemDateRequestIdentity(output) {
|
|
10189
|
+
return outputIdentities.get(output);
|
|
10190
|
+
}
|
|
10191
|
+
function bindSystemDateRequest(output, request) {
|
|
10192
|
+
if (request)
|
|
10193
|
+
outputRequests.set(output, request);
|
|
10194
|
+
}
|
|
10195
|
+
function systemDateRequestForOutput(history, output) {
|
|
10196
|
+
const request = outputRequests.get(output);
|
|
10197
|
+
return state(history, request);
|
|
10198
|
+
}
|
|
10199
|
+
function bindSystemDateOutput(system, update) {
|
|
10200
|
+
outputUpdates.set(system, update);
|
|
10201
|
+
}
|
|
10202
|
+
function publishSystemDateOutput(system) {
|
|
10203
|
+
outputUpdates.get(system)?.();
|
|
10204
|
+
outputUpdates.delete(system);
|
|
10205
|
+
}
|
|
10206
|
+
function registerSystemDateRefresh(history) {
|
|
10207
|
+
if (!channels.has(history))
|
|
10208
|
+
channels.set(history, new Map);
|
|
10209
|
+
}
|
|
10210
|
+
function hasSystemDateRefresh(history) {
|
|
10211
|
+
return channels.has(history);
|
|
10212
|
+
}
|
|
10213
|
+
function beginSystemDateRequest(history, sessionId, stage, turnId, identity) {
|
|
10214
|
+
const channel = channels.get(history);
|
|
10215
|
+
if (!channel)
|
|
10216
|
+
return;
|
|
10217
|
+
let requests = channel.get(sessionId);
|
|
10218
|
+
if (!requests)
|
|
10219
|
+
channel.set(sessionId, requests = new Map);
|
|
10220
|
+
let request = identity === undefined ? undefined : requests.get(identity);
|
|
10221
|
+
if (identity === undefined) {
|
|
10222
|
+
const candidates = [...requests.values()].filter((candidate) => !candidate.explicit && !(candidate.systemSeen && candidate.messagesSeen) && (stage === "system-after-messages" || candidate.turnId === turnId));
|
|
10223
|
+
const matching = candidates.filter((candidate) => !candidate.ambiguous && (stage === "messages" ? candidate.systemSeen && !candidate.messagesSeen : candidate.messagesSeen && !candidate.systemSeen));
|
|
10224
|
+
if (turnId !== undefined && candidates.length === 1 && matching.length === 1) {
|
|
10225
|
+
request = matching[0];
|
|
10226
|
+
} else if (candidates.length > 0) {
|
|
10227
|
+
for (const candidate of candidates)
|
|
10228
|
+
candidate.ambiguous = true;
|
|
10229
|
+
}
|
|
10230
|
+
}
|
|
10231
|
+
if (!request) {
|
|
10232
|
+
const sameTurn = [...requests.values()].some((candidate) => !candidate.explicit && !(candidate.systemSeen && candidate.messagesSeen) && (stage === "system-after-messages" || candidate.turnId === turnId));
|
|
10233
|
+
request = {
|
|
10234
|
+
sessionId,
|
|
10235
|
+
identity: identity ?? {},
|
|
10236
|
+
turnId,
|
|
10237
|
+
explicit: identity !== undefined,
|
|
10238
|
+
systemSeen: false,
|
|
10239
|
+
systemDone: false,
|
|
10240
|
+
messagesSeen: false,
|
|
10241
|
+
permitted: undefined,
|
|
10242
|
+
ambiguous: identity === undefined && (turnId === undefined || sameTurn)
|
|
10243
|
+
};
|
|
10244
|
+
const blocked = [...requests.values()].filter((candidate) => !candidate.explicit && candidate.ambiguous && !(candidate.systemSeen && candidate.messagesSeen) && candidate.turnId === turnId).length;
|
|
10245
|
+
if (request.explicit || !request.ambiguous || blocked < 2)
|
|
10246
|
+
requests.set(request.identity, request);
|
|
10247
|
+
}
|
|
10248
|
+
if (stage === "messages")
|
|
10249
|
+
request.messagesSeen = true;
|
|
10250
|
+
else
|
|
10251
|
+
request.systemSeen = true;
|
|
10252
|
+
return request;
|
|
10253
|
+
}
|
|
10254
|
+
function state(history, request) {
|
|
10255
|
+
if (!request)
|
|
10256
|
+
return;
|
|
10257
|
+
const current = channels.get(history)?.get(request.sessionId)?.get(request.identity);
|
|
10258
|
+
return current === request ? current : undefined;
|
|
10259
|
+
}
|
|
10260
|
+
function systemDateRefreshPermission(history, request) {
|
|
10261
|
+
const current = state(history, request);
|
|
10262
|
+
return current?.ambiguous ? undefined : current?.permitted;
|
|
10263
|
+
}
|
|
10264
|
+
function waitForSystemDateRefresh(history, request, apply) {
|
|
10265
|
+
const current = state(history, request);
|
|
10266
|
+
if (!current)
|
|
10267
|
+
return false;
|
|
10268
|
+
current.waiting = apply;
|
|
10269
|
+
return true;
|
|
10270
|
+
}
|
|
10271
|
+
function retire(history, current) {
|
|
10272
|
+
const unpairable = !current.explicit && current.turnId === undefined;
|
|
10273
|
+
if (!unpairable && (!current.systemDone || current.permitted === undefined))
|
|
10274
|
+
return;
|
|
10275
|
+
if (unpairable) {
|
|
10276
|
+
const apply = current.waiting;
|
|
10277
|
+
current.waiting = undefined;
|
|
10278
|
+
apply?.(false);
|
|
10279
|
+
}
|
|
10280
|
+
const channel = channels.get(history);
|
|
10281
|
+
const requests = channel?.get(current.sessionId);
|
|
10282
|
+
requests?.delete(current.identity);
|
|
10283
|
+
if (requests?.size === 0)
|
|
10284
|
+
channel?.delete(current.sessionId);
|
|
10285
|
+
}
|
|
10286
|
+
function finishSystemDateRefresh(history, request, permitted) {
|
|
10287
|
+
const current = state(history, request);
|
|
10288
|
+
if (!current)
|
|
10289
|
+
return;
|
|
10290
|
+
current.permitted = current.ambiguous ? false : permitted;
|
|
10291
|
+
const apply = current.waiting;
|
|
10292
|
+
current.waiting = undefined;
|
|
10293
|
+
apply?.(current.permitted);
|
|
10294
|
+
retire(history, current);
|
|
10295
|
+
}
|
|
10296
|
+
function finishSystemDateHook(history, request) {
|
|
10297
|
+
const current = state(history, request);
|
|
10298
|
+
if (!current)
|
|
10299
|
+
return;
|
|
10300
|
+
current.systemDone = true;
|
|
10301
|
+
retire(history, current);
|
|
10302
|
+
}
|
|
10303
|
+
function clearSystemDateRefresh(history, sessionId) {
|
|
10304
|
+
channels.get(history)?.delete(sessionId);
|
|
10305
|
+
}
|
|
10306
|
+
|
|
10783
10307
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
10784
|
-
var
|
|
10308
|
+
var MAGIC_CONTEXT_MARKER = "## Magic Context";
|
|
10785
10309
|
var SYSTEM_PROMPT_GUIDANCE_SEPARATOR = `
|
|
10786
10310
|
|
|
10787
10311
|
`;
|
|
@@ -10793,16 +10317,16 @@ function isInternalOpenCodeAgent(systemPromptContent) {
|
|
|
10793
10317
|
return systemPromptContent.includes("You are a title generator. You output ONLY a thread title.") || systemPromptContent.includes("Summarize what was done in this conversation. Write like a pull request description.") || systemPromptContent.includes("You are an anchored context summarization assistant for coding sessions.") || systemPromptContent.includes("You are a context summarization agent. You are given a conversation between a user and an agent.");
|
|
10794
10318
|
}
|
|
10795
10319
|
function isMagicContextInternalAgent(systemPromptContent) {
|
|
10796
|
-
return systemPromptContent.includes("You are Historian — the hippocampus of a long-running coding agent.");
|
|
10320
|
+
return systemPromptContent.includes("You are Historian — the hippocampus of a long-running coding agent.") || systemPromptContent.includes("for the magic-context system");
|
|
10797
10321
|
}
|
|
10798
10322
|
function createSystemPromptHashHandler(deps) {
|
|
10799
10323
|
const promptSurfaceRuntime = deps.promptSurfaceRuntime ?? createPromptSurfaceRuntime({
|
|
10800
10324
|
userConfigDirectory: process.cwd(),
|
|
10801
|
-
warn: (message) =>
|
|
10325
|
+
warn: (message) => log(`[magic-context] config warning: ${message}`)
|
|
10802
10326
|
});
|
|
10803
10327
|
const guidanceEpochs = createPromptSurfaceGuidanceEpochCache(promptSurfaceRuntime);
|
|
10804
10328
|
const stickyDateBySession = new Map;
|
|
10805
|
-
const
|
|
10329
|
+
const processSystemPrompt = async (input, output) => {
|
|
10806
10330
|
const sessionId = input.sessionID;
|
|
10807
10331
|
if (!sessionId)
|
|
10808
10332
|
return;
|
|
@@ -10826,6 +10350,10 @@ function createSystemPromptHashHandler(deps) {
|
|
|
10826
10350
|
sessionLog(sessionId, "system-prompt-hash skipped (matched system_prompt_injection.skip_signatures)");
|
|
10827
10351
|
return;
|
|
10828
10352
|
}
|
|
10353
|
+
const messagesPrepared = deps.consumeMessagesPrepared?.(sessionId) ?? false;
|
|
10354
|
+
const dateRequest = beginSystemDateRequest(deps.historyRefreshSessions, sessionId, messagesPrepared ? "system-after-messages" : "system", input.dateRefreshRequest === undefined && hasSystemDateRefresh(deps.historyRefreshSessions) ? (deps.resolveDateTurnId ?? latestRealUserTurnIdFromOpenCodeDb)(sessionId) : undefined, input.dateRefreshRequest);
|
|
10355
|
+
bindSystemDateRequest(output, dateRequest);
|
|
10356
|
+
const requestMessagesFinal = messagesPrepared || systemDateRefreshPermission(deps.historyRefreshSessions, dateRequest) !== undefined;
|
|
10829
10357
|
let sessionMetaEarly;
|
|
10830
10358
|
try {
|
|
10831
10359
|
sessionMetaEarly = getOrCreateSessionMeta(deps.db, sessionId);
|
|
@@ -10850,15 +10378,14 @@ function createSystemPromptHashHandler(deps) {
|
|
|
10850
10378
|
const promptSurface = guidanceEpochs.resolve(sessionId, deps.promptSurface, modelKey);
|
|
10851
10379
|
const fullPrompt = output.system.join(`
|
|
10852
10380
|
`);
|
|
10853
|
-
if (fullPrompt.length > 0 && !fullPrompt.includes(
|
|
10381
|
+
if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
|
|
10854
10382
|
const guidance = buildMagicContextSection(null, 0, effectiveCtxReduceEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false, promptSurface.preset, promptSurface.primaryOverride);
|
|
10855
10383
|
output.system[0] = `${output.system[0]}${SYSTEM_PROMPT_GUIDANCE_SEPARATOR}${guidance}`;
|
|
10856
10384
|
sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession}, subagentReduceMode=${subagentReduceMode})`);
|
|
10857
10385
|
}
|
|
10858
10386
|
const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
|
|
10859
10387
|
const idleCacheExpired = sessionMetaEarly !== undefined && computeHardCacheExpired(sessionMetaEarly.cacheTtl, sessionMetaEarly.lastResponseTime, Date.now());
|
|
10860
|
-
const
|
|
10861
|
-
const DATE_PATTERN_ALL = /Today's date: .+/g;
|
|
10388
|
+
const adoptSystemChange = idleCacheExpired || requestMessagesFinal && !isHeldHeadForRequest(sessionId, currentLkgRequestIdentity(sessionId));
|
|
10862
10389
|
const liveSystemContent = output.system.join(`
|
|
10863
10390
|
`);
|
|
10864
10391
|
if (liveSystemContent.length === 0)
|
|
@@ -10867,29 +10394,56 @@ function createSystemPromptHashHandler(deps) {
|
|
|
10867
10394
|
const hasPersistedHash = previousHash !== "" && previousHash !== "0";
|
|
10868
10395
|
if (!hasPersistedHash)
|
|
10869
10396
|
stickyDateBySession.delete(sessionId);
|
|
10870
|
-
const dateElementIndexes = [];
|
|
10871
|
-
let currentDate;
|
|
10872
|
-
for (let i = 0;i < output.system.length; i++) {
|
|
10873
|
-
const match = output.system[i].match(DATE_PATTERN);
|
|
10874
|
-
if (!match)
|
|
10875
|
-
continue;
|
|
10876
|
-
dateElementIndexes.push(i);
|
|
10877
|
-
currentDate ??= match[0];
|
|
10878
|
-
}
|
|
10879
10397
|
const stickyDate = stickyDateBySession.get(sessionId);
|
|
10880
|
-
const
|
|
10881
|
-
const
|
|
10398
|
+
const dates = systemPromptDates(liveSystemContent, stickyDate);
|
|
10399
|
+
const currentDate = dates.live;
|
|
10400
|
+
const stableCandidate = dates.stable;
|
|
10401
|
+
const stableCandidateHash = createHash3("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
|
|
10882
10402
|
const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
|
|
10883
|
-
const
|
|
10403
|
+
const rewritePermission = systemDateRefreshPermission(deps.historyRefreshSessions, dateRequest);
|
|
10404
|
+
let deferredDateRefresh = false;
|
|
10405
|
+
if (currentDate && stickyDate && currentDate !== stickyDate && isCacheBusting && !idleCacheExpired && !contentOrPresetChanged && !requestMessagesFinal) {
|
|
10406
|
+
const liveElements = [...output.system];
|
|
10407
|
+
deferredDateRefresh = waitForSystemDateRefresh(deps.historyRefreshSessions, dateRequest, (permitted) => {
|
|
10408
|
+
if (!permitted) {
|
|
10409
|
+
deps.systemPromptRefreshSessions.add(sessionId);
|
|
10410
|
+
return;
|
|
10411
|
+
}
|
|
10412
|
+
try {
|
|
10413
|
+
const content = liveElements.join(`
|
|
10414
|
+
`);
|
|
10415
|
+
const hash = createHash3("md5").update(promptSurfaceHashMaterial(content, promptSurface.preset)).digest("hex");
|
|
10416
|
+
updateSessionMeta(deps.db, sessionId, {
|
|
10417
|
+
systemPromptHash: hash,
|
|
10418
|
+
cachedM0SystemHash: hash,
|
|
10419
|
+
systemPromptTokens: estimateTokens(content)
|
|
10420
|
+
});
|
|
10421
|
+
stickyDateBySession.set(sessionId, currentDate);
|
|
10422
|
+
output.system.splice(0, output.system.length, ...liveElements);
|
|
10423
|
+
publishSystemDateOutput(output.system);
|
|
10424
|
+
deps.systemPromptRefreshSessions.delete(sessionId);
|
|
10425
|
+
sessionLog(sessionId, `system prompt date updated after prefix rewrite: ${stickyDate} → ${currentDate}`);
|
|
10426
|
+
} catch (error) {
|
|
10427
|
+
deps.systemPromptRefreshSessions.add(sessionId);
|
|
10428
|
+
sessionLog(sessionId, "system prompt date refresh failed (keeping frozen date):", error);
|
|
10429
|
+
}
|
|
10430
|
+
});
|
|
10431
|
+
}
|
|
10432
|
+
const dateMayAdvance = idleCacheExpired || contentOrPresetChanged || isCacheBusting && !deferredDateRefresh && (dateRequest ? rewritePermission === true : rewritePermission !== false);
|
|
10884
10433
|
if (currentDate && !stickyDate) {
|
|
10885
10434
|
stickyDateBySession.set(sessionId, currentDate);
|
|
10886
10435
|
} else if (currentDate && stickyDate && currentDate !== stickyDate) {
|
|
10887
10436
|
if (dateMayAdvance) {
|
|
10888
10437
|
stickyDateBySession.set(sessionId, currentDate);
|
|
10889
10438
|
sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${currentDate} (cache-busting pass)`);
|
|
10890
|
-
} else
|
|
10891
|
-
|
|
10892
|
-
|
|
10439
|
+
} else {
|
|
10440
|
+
let offset = 0;
|
|
10441
|
+
const prior = JSON.parse(stickyDate);
|
|
10442
|
+
for (let index = 0;index < output.system.length; index++) {
|
|
10443
|
+
const element = systemPromptDates(output.system[index]);
|
|
10444
|
+
const count = element.live ? JSON.parse(element.live).length : 0;
|
|
10445
|
+
output.system[index] = systemPromptDates(output.system[index], JSON.stringify(prior.slice(offset, offset + count))).stable;
|
|
10446
|
+
offset += count;
|
|
10893
10447
|
}
|
|
10894
10448
|
sessionLog(sessionId, `system prompt date frozen: real=${currentDate}, using=${stickyDate} (defer pass)`);
|
|
10895
10449
|
}
|
|
@@ -10898,17 +10452,20 @@ function createSystemPromptHashHandler(deps) {
|
|
|
10898
10452
|
`);
|
|
10899
10453
|
if (!availability.frozen || !modelKey)
|
|
10900
10454
|
return;
|
|
10901
|
-
const currentHash =
|
|
10455
|
+
const currentHash = createHash3("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
|
|
10456
|
+
recordSystemPromptForRequest(sessionId, currentLkgRequestIdentity(sessionId), currentHash, deps.db, previousHash !== currentHash ? !deps.historyRefreshSessions.has(sessionId) : undefined, deps.historyRefreshSessions, deps.pendingMaterializationSessions);
|
|
10902
10457
|
if (!sessionMetaEarly) {
|
|
10903
10458
|
return;
|
|
10904
10459
|
}
|
|
10905
10460
|
const sessionMeta = sessionMetaEarly;
|
|
10906
10461
|
if (previousHash !== "" && previousHash !== "0" && previousHash !== currentHash) {
|
|
10907
|
-
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${systemContent.length}), ${idleCacheExpired ? "adopting on idle-expired request" : "triggering flush"}`);
|
|
10908
|
-
if (!
|
|
10462
|
+
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${systemContent.length}), ${idleCacheExpired ? "adopting on idle-expired request" : requestMessagesFinal ? "adopting on the request whose messages are already final" : "triggering flush"}`);
|
|
10463
|
+
if (!adoptSystemChange) {
|
|
10909
10464
|
deps.historyRefreshSessions.add(sessionId);
|
|
10910
10465
|
deps.systemPromptRefreshSessions.add(sessionId);
|
|
10911
|
-
deps.pendingMaterializationSessions.
|
|
10466
|
+
if (!deps.pendingMaterializationSessions.has(sessionId)) {
|
|
10467
|
+
requestPendingMaterialization(deps.pendingMaterializationSessions, sessionId, "system_hash");
|
|
10468
|
+
}
|
|
10912
10469
|
deps.lastHeuristicsTurnId.delete(sessionId);
|
|
10913
10470
|
}
|
|
10914
10471
|
} else if (previousHash === "" || previousHash === "0") {
|
|
@@ -10925,19 +10482,27 @@ function createSystemPromptHashHandler(deps) {
|
|
|
10925
10482
|
updateSessionMeta(deps.db, sessionId, {
|
|
10926
10483
|
systemPromptHash: currentHash,
|
|
10927
10484
|
systemPromptTokens,
|
|
10928
|
-
cachedM0SystemHash: !hasPersistedHash ||
|
|
10485
|
+
cachedM0SystemHash: !hasPersistedHash || adoptSystemChange ? currentHash : undefined
|
|
10929
10486
|
});
|
|
10930
10487
|
} catch (error) {
|
|
10931
10488
|
sessionLog(sessionId, "system prompt meta persist failed (fail-open):", error);
|
|
10932
10489
|
}
|
|
10933
10490
|
}
|
|
10934
|
-
if (isCacheBusting) {
|
|
10491
|
+
if (isCacheBusting && !deferredDateRefresh && (contentOrPresetChanged || !currentDate || currentDate === stickyDate || !dateRequest || rewritePermission === true)) {
|
|
10935
10492
|
deps.systemPromptRefreshSessions.delete(sessionId);
|
|
10936
10493
|
}
|
|
10937
10494
|
};
|
|
10495
|
+
const handler = async (input, output) => {
|
|
10496
|
+
try {
|
|
10497
|
+
await processSystemPrompt(input, output);
|
|
10498
|
+
} finally {
|
|
10499
|
+
finishSystemDateHook(deps.historyRefreshSessions, systemDateRequestForOutput(deps.historyRefreshSessions, output));
|
|
10500
|
+
}
|
|
10501
|
+
};
|
|
10938
10502
|
return {
|
|
10939
10503
|
handler,
|
|
10940
10504
|
clearSession: (sessionId) => {
|
|
10505
|
+
clearSystemDateRefresh(deps.historyRefreshSessions, sessionId);
|
|
10941
10506
|
guidanceEpochs.clear(sessionId);
|
|
10942
10507
|
clearSystemPromptHashSession(sessionId, {
|
|
10943
10508
|
stickyDateBySession,
|
|
@@ -11657,12 +11222,8 @@ function markDropLeavesReasoning(db, sessionId) {
|
|
|
11657
11222
|
|
|
11658
11223
|
// src/hooks/magic-context/reasoning-budget.ts
|
|
11659
11224
|
function projectOpencodeReasoningBudgetCutoff(db, sessionId, messages, budget, watermark, proseRatio) {
|
|
11660
|
-
const
|
|
11661
|
-
|
|
11662
|
-
const id = tag.type === "tool" ? tag.toolOwnerMessageId : contentTagOwnerMessageId(tag.messageId);
|
|
11663
|
-
if (id)
|
|
11664
|
-
maxTags.set(id, Math.max(maxTags.get(id) ?? 0, tag.tagNumber));
|
|
11665
|
-
}
|
|
11225
|
+
const textEstimateByMessageId = getReasoningTokenEstimatesByMessage(db, sessionId, proseRatio);
|
|
11226
|
+
const maxTags = getMaxTagNumberByOwnerMessage(db, sessionId);
|
|
11666
11227
|
const messageTags = new Map;
|
|
11667
11228
|
const gone = new Set(getReasoningRemovalState(db, sessionId).messageIds);
|
|
11668
11229
|
for (const message of messages) {
|
|
@@ -11673,15 +11234,16 @@ function projectOpencodeReasoningBudgetCutoff(db, sessionId, messages, budget, w
|
|
|
11673
11234
|
if (tag > 0 && tag <= watermark)
|
|
11674
11235
|
gone.add(message.info.id);
|
|
11675
11236
|
}
|
|
11237
|
+
const frozenMergedIds = getMergedReasoningStrippedIds(db, sessionId);
|
|
11676
11238
|
return opencodeReasoningBudgetCutoff({
|
|
11677
11239
|
messages,
|
|
11678
11240
|
messageTagNumbers: messageTags,
|
|
11679
11241
|
budget,
|
|
11680
11242
|
alreadyRemoved: gone,
|
|
11681
|
-
textEstimateByMessageId
|
|
11243
|
+
textEstimateByMessageId,
|
|
11682
11244
|
proseRatio,
|
|
11683
|
-
frozenMergedIds
|
|
11684
|
-
alsoGone: new Set([...
|
|
11245
|
+
frozenMergedIds,
|
|
11246
|
+
alsoGone: new Set([...frozenMergedIds].filter((id) => id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)).map((id) => id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length)))
|
|
11685
11247
|
});
|
|
11686
11248
|
}
|
|
11687
11249
|
var DEFAULT_KEEP_REASONING_TOKENS = 1e4;
|
|
@@ -11769,14 +11331,25 @@ function opencodeReasoningBudgetCutoff(args) {
|
|
|
11769
11331
|
const assistants = args.messages.filter((message) => message.info.role === "assistant");
|
|
11770
11332
|
const newest = assistants.at(-1);
|
|
11771
11333
|
const exempt = findLatestAssistantReasoningMutationExemptMessage(args.messages);
|
|
11334
|
+
const anthropic = args.anthropic ?? hasAnthropicReasoning(args.messages);
|
|
11335
|
+
const indexOfMessage = new Map;
|
|
11336
|
+
args.messages.forEach((message, index) => {
|
|
11337
|
+
if (!indexOfMessage.has(message))
|
|
11338
|
+
indexOfMessage.set(message, index);
|
|
11339
|
+
});
|
|
11340
|
+
const frozenParts = args.frozenMergedIds ? readFrozenMergedReasoningParts(args.frozenMergedIds) : undefined;
|
|
11341
|
+
const frozenPartMessageIds = frozenParts ? new Set(frozenParts.keys()) : undefined;
|
|
11772
11342
|
return reasoningBudgetCutoff(assistants.map((message) => ({
|
|
11773
11343
|
tag: args.messageTagNumbers.get(message) ?? 0,
|
|
11774
|
-
exempt: message === newest || message === exempt || isInActiveAnthropicTurn(args.messages,
|
|
11344
|
+
exempt: message === newest || message === exempt || isInActiveAnthropicTurn(args.messages, indexOfMessage.get(message) ?? -1, anthropic),
|
|
11775
11345
|
cost: () => {
|
|
11776
11346
|
const costMessage = { ...message, parts: [...message.parts] };
|
|
11777
|
-
|
|
11347
|
+
const id = message.info.id ?? "";
|
|
11348
|
+
if (args.frozenMergedIds && (frozenParts?.has(id) || args.frozenMergedIds.has(id)))
|
|
11778
11349
|
stripReasoningFromMergedAssistants([costMessage], "anthropic", {
|
|
11779
|
-
frozenMessageIds: args.frozenMergedIds
|
|
11350
|
+
frozenMessageIds: args.frozenMergedIds,
|
|
11351
|
+
frozenParts,
|
|
11352
|
+
frozenPartMessageIds
|
|
11780
11353
|
});
|
|
11781
11354
|
const visible = reasoningTextAndOpaque(args.countNeutralized ? costMessage.parts.map(neutralizedReasoningSource) : costMessage.parts);
|
|
11782
11355
|
if (!visible.hasReasoning && !visible.inlineText)
|
|
@@ -12151,6 +11724,7 @@ var PASS_DEGRADATION_EFFECTS = {
|
|
|
12151
11724
|
"auto-search-timeout": "served",
|
|
12152
11725
|
"auto-search-search-failure": "served",
|
|
12153
11726
|
"auto-search-cas-exhaustion": "served",
|
|
11727
|
+
"auto-search-storage-busy": "served",
|
|
12154
11728
|
"auto-search-internal-failure": "served",
|
|
12155
11729
|
"thinking-binding-recovery-persistence-failure": "changes-request",
|
|
12156
11730
|
"merged-reasoning-strip-persistence-failure": "changes-request",
|
|
@@ -12609,15 +12183,22 @@ function buildReplacementContent(tagId) {
|
|
|
12609
12183
|
return `[dropped §${tagId}§]`;
|
|
12610
12184
|
}
|
|
12611
12185
|
function applyNewToolDrop(target, options) {
|
|
12612
|
-
if (
|
|
12186
|
+
if (options.persist && (target?.prepareDrop?.() ?? target?.canDrop?.()) === false) {
|
|
12187
|
+
return { result: "incomplete", mode: "full" };
|
|
12188
|
+
}
|
|
12189
|
+
if (!target) {
|
|
12190
|
+
options.persist?.("full");
|
|
12613
12191
|
return { result: "absent", mode: "full" };
|
|
12614
|
-
|
|
12192
|
+
}
|
|
12193
|
+
if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true || target.wouldStrandConversationEnd?.() === true) {
|
|
12615
12194
|
const strip = target.hasAttachments?.() === true;
|
|
12195
|
+
options.persist?.(strip ? "skeleton_stripped" : "skeleton_real");
|
|
12616
12196
|
return {
|
|
12617
12197
|
result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
|
|
12618
12198
|
mode: strip ? "skeleton_stripped" : "skeleton_real"
|
|
12619
12199
|
};
|
|
12620
12200
|
}
|
|
12201
|
+
options.persist?.("full");
|
|
12621
12202
|
const result = target.drop?.() ?? "absent";
|
|
12622
12203
|
if (result === "truncated" && target.hasAttachments?.() === true) {
|
|
12623
12204
|
return { result: target.skeletonStripped?.() ?? "absent", mode: "skeleton_stripped" };
|
|
@@ -12628,6 +12209,18 @@ function hasSmallToolInput(target) {
|
|
|
12628
12209
|
const bytes = target?.inputStringBytes?.() ?? null;
|
|
12629
12210
|
return bytes !== null && bytes <= SKELETON_REAL_INPUT_MAX_BYTES;
|
|
12630
12211
|
}
|
|
12212
|
+
function applyPersistedToolDrop(db, sessionId, tagNumber, target, options, afterWrite) {
|
|
12213
|
+
return applyNewToolDrop(target, {
|
|
12214
|
+
...options,
|
|
12215
|
+
persist: (mode) => {
|
|
12216
|
+
db.transaction(() => {
|
|
12217
|
+
updateTagDropMode(db, sessionId, tagNumber, mode);
|
|
12218
|
+
updateTagStatus(db, sessionId, tagNumber, "dropped");
|
|
12219
|
+
afterWrite?.();
|
|
12220
|
+
}).immediate();
|
|
12221
|
+
}
|
|
12222
|
+
});
|
|
12223
|
+
}
|
|
12631
12224
|
var CACHE_LOSING_FOLD_REASONS = new Set([
|
|
12632
12225
|
"model_change",
|
|
12633
12226
|
"system_hash",
|
|
@@ -12701,11 +12294,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
12701
12294
|
diagnostics.reasons[reason] = (diagnostics.reasons[reason] ?? 0) + 1;
|
|
12702
12295
|
};
|
|
12703
12296
|
let admitted = false;
|
|
12704
|
-
let startedAt = 0;
|
|
12705
12297
|
try {
|
|
12706
12298
|
db.transaction(() => {
|
|
12707
12299
|
admitted = true;
|
|
12708
|
-
|
|
12300
|
+
}).immediate();
|
|
12301
|
+
{
|
|
12709
12302
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
12710
12303
|
const neededTagNumbers = new Set(pendingOps.map((op) => op.tagId));
|
|
12711
12304
|
for (const op of syntheticPendingOps)
|
|
@@ -12764,9 +12357,30 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
12764
12357
|
}
|
|
12765
12358
|
}
|
|
12766
12359
|
let shouldPersistDrop = false;
|
|
12360
|
+
const persistDrop = (mode) => {
|
|
12361
|
+
let startedAt = 0;
|
|
12362
|
+
try {
|
|
12363
|
+
db.transaction(() => {
|
|
12364
|
+
startedAt = performance.now();
|
|
12365
|
+
if (mode)
|
|
12366
|
+
updateTagDropMode(db, sessionId, pendingOp.tagId, mode);
|
|
12367
|
+
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
12368
|
+
if (!synthetic)
|
|
12369
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
12370
|
+
}).immediate();
|
|
12371
|
+
} finally {
|
|
12372
|
+
if (startedAt)
|
|
12373
|
+
logSlowWriteTransaction("apply_pending_operation", startedAt);
|
|
12374
|
+
}
|
|
12375
|
+
};
|
|
12767
12376
|
if (isToolTag) {
|
|
12768
12377
|
if (editMarkerTagIds.has(pendingOp.tagId)) {
|
|
12769
12378
|
const strip = target?.hasAttachments?.() === true;
|
|
12379
|
+
if (target?.canDrop?.() === false || target?.prepareDrop?.() === false || !target) {
|
|
12380
|
+
reject("edit_marker_incomplete");
|
|
12381
|
+
continue;
|
|
12382
|
+
}
|
|
12383
|
+
persistDrop(strip ? "edit_marker_stripped" : "edit_marker");
|
|
12770
12384
|
const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
|
|
12771
12385
|
if (markResult === "incomplete" || markResult === "absent") {
|
|
12772
12386
|
reject(`edit_marker_${markResult}`);
|
|
@@ -12775,11 +12389,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
12775
12389
|
didMutateMessage = true;
|
|
12776
12390
|
operationMutated = true;
|
|
12777
12391
|
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
|
|
12778
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, strip ? "edit_marker_stripped" : "edit_marker");
|
|
12779
12392
|
shouldPersistDrop = true;
|
|
12780
12393
|
} else {
|
|
12781
12394
|
const { result: dropResult, mode: appliedMode } = applyNewToolDrop(target, {
|
|
12782
|
-
inWindow: skeletonWindow.has(pendingOp.tagId)
|
|
12395
|
+
inWindow: skeletonWindow.has(pendingOp.tagId),
|
|
12396
|
+
persist: persistDrop
|
|
12783
12397
|
});
|
|
12784
12398
|
if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
|
|
12785
12399
|
reject(`drop_${dropResult}`);
|
|
@@ -12795,12 +12409,12 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
12795
12409
|
} else {
|
|
12796
12410
|
reject(`drop_${dropResult}`);
|
|
12797
12411
|
}
|
|
12798
|
-
updateTagDropMode(db, sessionId, pendingOp.tagId, appliedMode);
|
|
12799
12412
|
shouldPersistDrop = true;
|
|
12800
12413
|
}
|
|
12801
12414
|
} else if (target) {
|
|
12802
12415
|
const replacement = buildReplacementContent(pendingOp.tagId);
|
|
12803
12416
|
const priorContent = target.getContent?.();
|
|
12417
|
+
persistDrop();
|
|
12804
12418
|
const changed = target.setContent(replacement);
|
|
12805
12419
|
if (changed) {
|
|
12806
12420
|
didMutateMessage = true;
|
|
@@ -12817,30 +12431,25 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
12817
12431
|
shouldPersistDrop = true;
|
|
12818
12432
|
} else if (!synthetic) {
|
|
12819
12433
|
reject("target_absent");
|
|
12434
|
+
persistDrop();
|
|
12820
12435
|
shouldPersistDrop = true;
|
|
12821
12436
|
}
|
|
12822
12437
|
if (!shouldPersistDrop) {
|
|
12823
12438
|
reject("not_persisted");
|
|
12824
12439
|
continue;
|
|
12825
12440
|
}
|
|
12826
|
-
updateTagStatus(db, sessionId, pendingOp.tagId, "dropped");
|
|
12827
|
-
if (!synthetic)
|
|
12828
|
-
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
12829
12441
|
if (operationMutated)
|
|
12830
12442
|
diagnostics.mutated += 1;
|
|
12831
12443
|
else
|
|
12832
12444
|
diagnostics.persistedWithoutMutation += 1;
|
|
12833
12445
|
}
|
|
12834
|
-
}
|
|
12446
|
+
}
|
|
12835
12447
|
} catch (error) {
|
|
12836
12448
|
if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
|
|
12837
12449
|
sessionLog(sessionId, "pending operations write admission busy; retaining prior bytes for retry");
|
|
12838
12450
|
return false;
|
|
12839
12451
|
}
|
|
12840
12452
|
throw error;
|
|
12841
|
-
} finally {
|
|
12842
|
-
if (admitted)
|
|
12843
|
-
logSlowWriteTransaction("apply_pending_operations", startedAt);
|
|
12844
12453
|
}
|
|
12845
12454
|
if (diagnostics) {
|
|
12846
12455
|
onBatchComplete?.(diagnostics);
|
|
@@ -13088,6 +12697,7 @@ function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)
|
|
|
13088
12697
|
const messageIds = messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []);
|
|
13089
12698
|
const ownersKey = JSON.stringify(messageIds);
|
|
13090
12699
|
const tagsVersion = tagger.getLoadedTagsVersion?.(sessionId, db);
|
|
12700
|
+
const identityRevision = tagger.getLoadedTagIdentityRevision?.(sessionId, db);
|
|
13091
12701
|
if (tagsVersion === undefined)
|
|
13092
12702
|
return getInertWhitespaceAssistantTags(db, sessionId, messageIds);
|
|
13093
12703
|
let bySession = inertWhitespaceCache.get(db);
|
|
@@ -13096,10 +12706,10 @@ function getCachedInertWhitespaceAssistantTags(db, sessionId, tagger, messages)
|
|
|
13096
12706
|
inertWhitespaceCache.set(db, bySession);
|
|
13097
12707
|
}
|
|
13098
12708
|
const cached = bySession.get(sessionId);
|
|
13099
|
-
if (cached?.tagsVersion === tagsVersion && cached.ownersKey === ownersKey)
|
|
12709
|
+
if (cached?.tagsVersion === tagsVersion && cached.identityRevision === identityRevision && cached.ownersKey === ownersKey)
|
|
13100
12710
|
return cached.tags;
|
|
13101
12711
|
const tags = getInertWhitespaceAssistantTags(db, sessionId, messageIds);
|
|
13102
|
-
bySession.set(sessionId, { tagsVersion, ownersKey, tags });
|
|
12712
|
+
bySession.set(sessionId, { tagsVersion, identityRevision, ownersKey, tags });
|
|
13103
12713
|
return tags;
|
|
13104
12714
|
}
|
|
13105
12715
|
function makeToolOwnerCacheKey(sessionId, callId) {
|
|
@@ -13256,8 +12866,19 @@ function hasRecentAssistantCommit(messages) {
|
|
|
13256
12866
|
}
|
|
13257
12867
|
return false;
|
|
13258
12868
|
}
|
|
13259
|
-
function
|
|
13260
|
-
|
|
12869
|
+
function isVolatileOmoSyntheticTextPart(part) {
|
|
12870
|
+
if (!isTextPart(part) || !isRecord(part))
|
|
12871
|
+
return false;
|
|
12872
|
+
if (part.synthetic !== true)
|
|
12873
|
+
return false;
|
|
12874
|
+
const metadata = part.metadata;
|
|
12875
|
+
if (!isRecord(metadata))
|
|
12876
|
+
return false;
|
|
12877
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
12878
|
+
if (key.startsWith("oh-my-opencode-slim.") && value === true)
|
|
12879
|
+
return true;
|
|
12880
|
+
}
|
|
12881
|
+
return false;
|
|
13261
12882
|
}
|
|
13262
12883
|
function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
13263
12884
|
const protectedThinkingParts = new Set([...options.protectedThinkingMessages ?? []].flatMap((message) => message.parts));
|
|
@@ -13315,9 +12936,16 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
13315
12936
|
if (message.info.role === "user") {
|
|
13316
12937
|
precedingThinkingParts = [];
|
|
13317
12938
|
}
|
|
13318
|
-
if (message.info.role === "user" && message.parts.length === 1 &&
|
|
12939
|
+
if (message.info.role === "user" && message.parts.length === 1 && isVolatileOmoSyntheticTextPart(message.parts[0])) {
|
|
13319
12940
|
continue;
|
|
13320
12941
|
}
|
|
12942
|
+
if (message.info.role === "user" && messageId !== null) {
|
|
12943
|
+
for (let index = 0;index < message.parts.length; index += 1) {
|
|
12944
|
+
if (isVolatileOmoSyntheticTextPart(message.parts[index])) {
|
|
12945
|
+
tagger.unbindTag(sessionId, `${messageId}:p${index}`);
|
|
12946
|
+
}
|
|
12947
|
+
}
|
|
12948
|
+
}
|
|
13321
12949
|
const messageThinkingParts = message.parts.filter(isThinkingPart);
|
|
13322
12950
|
if (messageThinkingParts.length > 0) {
|
|
13323
12951
|
reasoningByMessage.set(message, messageThinkingParts);
|
|
@@ -13379,6 +13007,10 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
13379
13007
|
ownerByPartKey.set(part, { ownerMsgId, callId: toolObservation.callId });
|
|
13380
13008
|
}
|
|
13381
13009
|
if (messageId && isTextPart(part)) {
|
|
13010
|
+
if (message.info.role === "user" && isVolatileOmoSyntheticTextPart(part)) {
|
|
13011
|
+
textOrdinal += 1;
|
|
13012
|
+
continue;
|
|
13013
|
+
}
|
|
13382
13014
|
const textPart = part;
|
|
13383
13015
|
const thinkingParts = messageThinkingParts;
|
|
13384
13016
|
const contentId = `${messageId}:p${partIndex}`;
|
|
@@ -13434,7 +13066,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
|
|
|
13434
13066
|
accAssignTag += performance.now() - _tAssignText;
|
|
13435
13067
|
const persistedSource = sourceContents.get(tagId);
|
|
13436
13068
|
if (persistedSource !== undefined) {
|
|
13437
|
-
textPart.text = persistedSource;
|
|
13069
|
+
textPart.text = options.normalizeRestoredAssistantText && message.info.role === "assistant" ? options.normalizeRestoredAssistantText(persistedSource) : persistedSource;
|
|
13438
13070
|
} else {
|
|
13439
13071
|
const sourceContent = stripTagPrefix(textPart.text);
|
|
13440
13072
|
if (sourceContent.trim().length > 0) {
|
|
@@ -13724,31 +13356,27 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
13724
13356
|
if (plan.shouldDrop) {
|
|
13725
13357
|
const toDrop = new Set(plan.tagNumbers);
|
|
13726
13358
|
const newestEmergencyTags = recentTags;
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13359
|
+
for (const tag of tags) {
|
|
13360
|
+
if (!toDrop.has(tag.tagNumber))
|
|
13361
|
+
continue;
|
|
13362
|
+
if (tag.status !== "active" || tag.type !== "tool")
|
|
13363
|
+
continue;
|
|
13364
|
+
const target = targets.get(tag.tagNumber);
|
|
13365
|
+
const recent = (emergency.usagePercentage ?? 0) < 95 && newestEmergencyTags.has(tag.tagNumber);
|
|
13366
|
+
const { result } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
|
|
13367
|
+
inWindow: recent,
|
|
13368
|
+
keepSkeleton: target?.requiresToolArcSkeleton === true
|
|
13369
|
+
});
|
|
13370
|
+
if (result === "removed" || result === "truncated") {
|
|
13371
|
+
droppedTools++;
|
|
13372
|
+
emergencyDroppedTools++;
|
|
13373
|
+
droppedTokenReductions.push({
|
|
13374
|
+
tagNumber: tag.tagNumber,
|
|
13375
|
+
mode: result === "removed" ? "full" : "truncated"
|
|
13738
13376
|
});
|
|
13739
|
-
|
|
13740
|
-
updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
|
|
13741
|
-
updateTagDropMode(db, sessionId, tag.tagNumber, mode);
|
|
13742
|
-
droppedTools++;
|
|
13743
|
-
emergencyDroppedTools++;
|
|
13744
|
-
droppedTokenReductions.push({
|
|
13745
|
-
tagNumber: tag.tagNumber,
|
|
13746
|
-
mode: result === "removed" ? "full" : "truncated"
|
|
13747
|
-
});
|
|
13748
|
-
emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(measuredByTag.get(tag.tagNumber) ?? tag);
|
|
13749
|
-
}
|
|
13377
|
+
emergencyReclaimedTokens += estimateEmergencyDropReclaimTokens(measuredByTag.get(tag.tagNumber) ?? tag);
|
|
13750
13378
|
}
|
|
13751
|
-
}
|
|
13379
|
+
}
|
|
13752
13380
|
sessionLog(sessionId, `emergency tiered drop: ${plan.reason}`);
|
|
13753
13381
|
} else {
|
|
13754
13382
|
sessionLog(sessionId, `emergency tiered drop skipped: ${plan.reason}`);
|
|
@@ -13829,35 +13457,33 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
|
|
|
13829
13457
|
group.push(tag);
|
|
13830
13458
|
fingerprintGroups.set(fingerprint, group);
|
|
13831
13459
|
}
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13460
|
+
for (const [, group] of fingerprintGroups) {
|
|
13461
|
+
if (group.length <= 1)
|
|
13462
|
+
continue;
|
|
13463
|
+
group.sort((a, b) => a.tagNumber - b.tagNumber);
|
|
13464
|
+
for (let i = 0;i < group.length - 1; i++) {
|
|
13465
|
+
const tag = group[i];
|
|
13466
|
+
if (config.protectedTagNumbers.has(tag.tagNumber))
|
|
13835
13467
|
continue;
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
|
|
13843
|
-
|
|
13844
|
-
|
|
13845
|
-
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
deduplicatedTools++;
|
|
13853
|
-
droppedTokenReductions.push({
|
|
13854
|
-
tagNumber: tag.tagNumber,
|
|
13855
|
-
mode: result === "removed" ? "full" : "truncated"
|
|
13856
|
-
});
|
|
13857
|
-
}
|
|
13468
|
+
const target = targets.get(tag.tagNumber);
|
|
13469
|
+
if (protectedTools.has(tag.tagNumber))
|
|
13470
|
+
continue;
|
|
13471
|
+
if (target?.canDrop?.() === false)
|
|
13472
|
+
continue;
|
|
13473
|
+
const { result } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
|
|
13474
|
+
inWindow: false
|
|
13475
|
+
});
|
|
13476
|
+
if (result === "incomplete")
|
|
13477
|
+
continue;
|
|
13478
|
+
if (result === "removed" || result === "truncated") {
|
|
13479
|
+
deduplicatedTools++;
|
|
13480
|
+
droppedTokenReductions.push({
|
|
13481
|
+
tagNumber: tag.tagNumber,
|
|
13482
|
+
mode: result === "removed" ? "full" : "truncated"
|
|
13483
|
+
});
|
|
13858
13484
|
}
|
|
13859
13485
|
}
|
|
13860
|
-
}
|
|
13486
|
+
}
|
|
13861
13487
|
}
|
|
13862
13488
|
if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0) {
|
|
13863
13489
|
sessionLog(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
@@ -13988,6 +13614,7 @@ function postprocessReplaySnapshot(db, sessionId) {
|
|
|
13988
13614
|
...replay,
|
|
13989
13615
|
staleReduceStrippedIds: new Set(replay.staleReduceStrippedIds),
|
|
13990
13616
|
processedImageStrippedIds: new Set(replay.processedImageStrippedIds),
|
|
13617
|
+
processedImageMarkers: new Map(replay.processedImageMarkers),
|
|
13991
13618
|
strippedPlaceholderIds: new Set(replay.strippedPlaceholderIds),
|
|
13992
13619
|
hiddenSeamPlaceholderIds: new Set(replay.hiddenSeamPlaceholderIds),
|
|
13993
13620
|
mergedReasoningStrippedIds: new Set(replay.mergedReasoningStrippedIds),
|
|
@@ -14044,6 +13671,39 @@ function captureOpencodeReasoningBudgetStatus(sessionId, messages, budget, prefi
|
|
|
14044
13671
|
sources.delete(sources.keys().next().value);
|
|
14045
13672
|
}
|
|
14046
13673
|
|
|
13674
|
+
// src/hooks/magic-context/strict-thinking-prefix.ts
|
|
13675
|
+
function servedPrefixMatches(args) {
|
|
13676
|
+
const heads = args.messages?.slice(0, 2);
|
|
13677
|
+
if (heads?.length !== 2 || args.m0Text == null || args.m1Text == null)
|
|
13678
|
+
return false;
|
|
13679
|
+
const text = (message) => {
|
|
13680
|
+
if (!isRecord(message))
|
|
13681
|
+
return;
|
|
13682
|
+
if (typeof message.content === "string")
|
|
13683
|
+
return message.content;
|
|
13684
|
+
const parts = Array.isArray(message.parts) ? message.parts : message.content;
|
|
13685
|
+
if (!Array.isArray(parts))
|
|
13686
|
+
return;
|
|
13687
|
+
return parts.filter(isRecord).filter((part) => part.type === "text").map((part) => String(part.text ?? "")).join("");
|
|
13688
|
+
};
|
|
13689
|
+
if (text(heads[0]) !== args.m0Text || text(heads[1]) !== args.m1Text)
|
|
13690
|
+
return false;
|
|
13691
|
+
const head = heads[0];
|
|
13692
|
+
if (!isRecord(head))
|
|
13693
|
+
return false;
|
|
13694
|
+
const parts = Array.isArray(head.parts) ? head.parts : head.content;
|
|
13695
|
+
if (!Array.isArray(parts))
|
|
13696
|
+
return !args.muralDataUrl;
|
|
13697
|
+
const images = parts.filter(isRecord).filter((part) => part.type === "image" || part.type === "file");
|
|
13698
|
+
if (!args.muralDataUrl)
|
|
13699
|
+
return images.length === 0;
|
|
13700
|
+
if (images.length !== 1)
|
|
13701
|
+
return false;
|
|
13702
|
+
const image = images[0];
|
|
13703
|
+
const url = typeof image.url === "string" ? image.url : typeof image.data === "string" && typeof image.mimeType === "string" ? `data:${image.mimeType};base64,${image.data}` : undefined;
|
|
13704
|
+
return url === args.muralDataUrl;
|
|
13705
|
+
}
|
|
13706
|
+
|
|
14047
13707
|
// src/hooks/magic-context/supersession-reclaim.ts
|
|
14048
13708
|
var SUPERSESSION_RECENT_MESSAGE_WINDOW = 20;
|
|
14049
13709
|
function recentSupersessionOwnerMessageIds(db, sessionId) {
|
|
@@ -14147,6 +13807,21 @@ function readFilePath(target) {
|
|
|
14147
13807
|
return null;
|
|
14148
13808
|
}
|
|
14149
13809
|
|
|
13810
|
+
// src/hooks/magic-context/tag-owner-warmup.ts
|
|
13811
|
+
function prewarmTagOwners(db, sessionId, ratio) {
|
|
13812
|
+
if (isTagOwnerSummaryReady(db, sessionId, ratio))
|
|
13813
|
+
return Promise.resolve(true);
|
|
13814
|
+
try {
|
|
13815
|
+
scanTagOwnerSummary(db, sessionId, ratio);
|
|
13816
|
+
return Promise.resolve(true);
|
|
13817
|
+
} catch {
|
|
13818
|
+
return Promise.resolve(false);
|
|
13819
|
+
}
|
|
13820
|
+
}
|
|
13821
|
+
async function waitForTagOwners(db, sessionId, ratio, _waitMs = 250) {
|
|
13822
|
+
return prewarmTagOwners(db, sessionId, ratio);
|
|
13823
|
+
}
|
|
13824
|
+
|
|
14150
13825
|
// src/hooks/magic-context/tool-reclaim.ts
|
|
14151
13826
|
function buildSyntheticToolReclaimOps(input) {
|
|
14152
13827
|
const watermark = Math.max(0, input.watermark);
|
|
@@ -14515,6 +14190,9 @@ function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
|
|
|
14515
14190
|
async function runPostTransformPhase(args) {
|
|
14516
14191
|
const tPostprocessSetup = performance.now();
|
|
14517
14192
|
const compactionOff = args.compactionOff === true;
|
|
14193
|
+
if (!compactionOff && !tryGetReasoningTokenEstimatesByMessage(args.db, args.sessionId, sessionDecisionCalibration(args.db, args.sessionId).proseRatio)) {
|
|
14194
|
+
await waitForTagOwners(args.db, args.sessionId, sessionDecisionCalibration(args.db, args.sessionId).proseRatio);
|
|
14195
|
+
}
|
|
14518
14196
|
const failPass = (site, error = new Error(`Could not complete ${site}`), kind) => {
|
|
14519
14197
|
args.passOutcome?.record(site, kind);
|
|
14520
14198
|
if (!compactionOff) {
|
|
@@ -14533,8 +14211,9 @@ async function runPostTransformPhase(args) {
|
|
|
14533
14211
|
}
|
|
14534
14212
|
const reasoningMutationExemptMessage = findLatestAssistantReasoningMutationExemptMessage(args.messages);
|
|
14535
14213
|
const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
|
|
14214
|
+
const pendingOrigin = pendingMaterializationOrigin(args.pendingMaterializationSessions, args.sessionId);
|
|
14536
14215
|
const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
|
|
14537
|
-
|
|
14216
|
+
let isExplicitFlush = pendingMaterializationAtPassStart;
|
|
14538
14217
|
const deferredMaterializationWasPending = deferredMaterializationAtPassStart;
|
|
14539
14218
|
const alreadyRanThisTurn = args.currentTurnId !== null && args.lastHeuristicsTurnId.get(args.sessionId) === args.currentTurnId;
|
|
14540
14219
|
const forceMaterialization = args.fullFeatureMode && !compactionOff && args.contextUsage.percentage >= args.forceMaterializationPercentage;
|
|
@@ -14551,8 +14230,8 @@ async function runPostTransformPhase(args) {
|
|
|
14551
14230
|
}
|
|
14552
14231
|
const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
|
|
14553
14232
|
const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
|
|
14554
|
-
|
|
14555
|
-
|
|
14233
|
+
let deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
14234
|
+
let materializationRequested = isExplicitFlush || deferredMaterialize;
|
|
14556
14235
|
const m0M1EnabledForFold = args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory) && (args.fullFeatureMode || compactionOff);
|
|
14557
14236
|
const frozenThinking = new Set(args.activeThinkingTurn ? getMergedReasoningStrippedIds(args.db, args.sessionId) : []);
|
|
14558
14237
|
const bindingThinking = new Set([...frozenThinking].filter((id) => id.startsWith(THINKING_BINDING_RECOVERY_FROZEN_PREFIX)).map((id) => id.slice(THINKING_BINDING_RECOVERY_FROZEN_PREFIX.length)));
|
|
@@ -14564,9 +14243,9 @@ async function runPostTransformPhase(args) {
|
|
|
14564
14243
|
bindingIds: bindingThinking,
|
|
14565
14244
|
removedIds: getReasoningRemovalState(args.db, args.sessionId).messageIds
|
|
14566
14245
|
}) : new Set;
|
|
14567
|
-
|
|
14246
|
+
let activeThinkingTurn = retainedThinking.size > 0;
|
|
14568
14247
|
const protectedThinkingMessages = new Set(args.messages.filter((message) => message.parts.some((part) => retainedThinking.has(part))));
|
|
14569
|
-
|
|
14248
|
+
let newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
|
|
14570
14249
|
let maxReasoningTag = 0;
|
|
14571
14250
|
for (const tag of args.messageTagNumbers.values())
|
|
14572
14251
|
maxReasoningTag = Math.max(maxReasoningTag, tag);
|
|
@@ -14576,7 +14255,28 @@ async function runPostTransformPhase(args) {
|
|
|
14576
14255
|
if (tag && tag > 0)
|
|
14577
14256
|
safeReasoningCutoff = Math.min(safeReasoningCutoff, tag - 1);
|
|
14578
14257
|
}
|
|
14579
|
-
|
|
14258
|
+
let activeThinkingPrefixHold = args.activeThinkingPrefixHold === true || activeThinkingTurn && args.thinkingBindingRecoveryEnabledForModel === true;
|
|
14259
|
+
let freezeM0M1 = args.freezeM0M1 === true || activeThinkingPrefixHold;
|
|
14260
|
+
let rewritingSignedPrefix = false;
|
|
14261
|
+
let thinkingReleasedForFit = false;
|
|
14262
|
+
const releaseThinkingForRewrite = (forFit = false) => {
|
|
14263
|
+
const stripped = freezeReasoningOnBustingPass({
|
|
14264
|
+
db: args.db,
|
|
14265
|
+
sessionId: args.sessionId,
|
|
14266
|
+
messages: args.messages,
|
|
14267
|
+
alreadyFrozen: bindingThinking
|
|
14268
|
+
});
|
|
14269
|
+
if (stripped.persistenceFailed)
|
|
14270
|
+
throw new Error("Cannot persist signed thinking omission before prefix rewrite");
|
|
14271
|
+
retainedThinking.clear();
|
|
14272
|
+
protectedThinkingMessages.clear();
|
|
14273
|
+
activeThinkingTurn = false;
|
|
14274
|
+
activeThinkingPrefixHold = false;
|
|
14275
|
+
freezeM0M1 = args.directoryPrefixHold === true;
|
|
14276
|
+
newTargets = args.targets;
|
|
14277
|
+
rewritingSignedPrefix = true;
|
|
14278
|
+
thinkingReleasedForFit ||= forFit;
|
|
14279
|
+
};
|
|
14580
14280
|
const foldDueDecision = m0M1EnabledForFold && args.m0M1 && !freezeM0M1 ? mustMaterialize({
|
|
14581
14281
|
db: args.db,
|
|
14582
14282
|
sessionId: args.sessionId,
|
|
@@ -14594,6 +14294,7 @@ async function runPostTransformPhase(args) {
|
|
|
14594
14294
|
const cachedPrefixBeforePreflight = shouldCaptureCachedPrefix ? prepareCachedM0M1Replay(args.db, args.sessionId) : undefined;
|
|
14595
14295
|
const completeCachedPrefixAvailable = args.sessionMeta.cachedM0Bytes != null && args.sessionMeta.cachedM1Bytes != null || cachedPrefixBeforePreflight !== undefined || m0M1EnabledForFold && !shouldCaptureCachedPrefix && hasCompleteCachedM0M1(args.db, args.sessionId);
|
|
14596
14296
|
const firstRenderBust = m0M1EnabledForFold && !completeCachedPrefixAvailable;
|
|
14297
|
+
const servedBeforeFirstRender = firstRenderBust ? args.readLastServedMessages?.() : null;
|
|
14597
14298
|
let foldExecutedThisPass = false;
|
|
14598
14299
|
let foldBustsServedPrefixThisPass = false;
|
|
14599
14300
|
let publishedM1RefreshedThisPass = false;
|
|
@@ -14609,7 +14310,7 @@ async function runPostTransformPhase(args) {
|
|
|
14609
14310
|
m0Bytes: args.sessionMeta.cachedM0Bytes ?? null,
|
|
14610
14311
|
m1Bytes: args.sessionMeta.cachedM1Bytes ?? null
|
|
14611
14312
|
};
|
|
14612
|
-
if ((foldDueDecision.value || softRefreshOpportunity) && m0M1EnabledForFold && args.m0M1) {
|
|
14313
|
+
if ((foldDueDecision.value || softRefreshOpportunity || firstRenderBust && activeThinkingPrefixHold) && m0M1EnabledForFold && args.m0M1) {
|
|
14613
14314
|
let committedFoldBustsServedPrefix;
|
|
14614
14315
|
try {
|
|
14615
14316
|
const previousM1 = args.sessionMeta.cachedM1Bytes?.toString("utf8");
|
|
@@ -14632,7 +14333,11 @@ async function runPostTransformPhase(args) {
|
|
|
14632
14333
|
onFoldPrepare: () => {
|
|
14633
14334
|
const conversions = prepareLegacyToolSkeletonConversions(args.db, args.sessionId, args.targets);
|
|
14634
14335
|
return (db, rendered) => {
|
|
14635
|
-
const bustsPrefix =
|
|
14336
|
+
const bustsPrefix = activeThinkingPrefixHold ? !servedPrefixMatches({
|
|
14337
|
+
messages: servedBeforeFirstRender,
|
|
14338
|
+
m0Text: rendered.m0Bytes.toString(),
|
|
14339
|
+
m1Text: rendered.m1Bytes.toString()
|
|
14340
|
+
}) : foldBustsServedPrefix(foldDueDecision.reason, servedPrefixBeforeFold, rendered);
|
|
14636
14341
|
if (bustsPrefix) {
|
|
14637
14342
|
if (!conversions.isCurrent(db)) {
|
|
14638
14343
|
throw new MaterializeContentionError({
|
|
@@ -14649,6 +14354,9 @@ async function runPostTransformPhase(args) {
|
|
|
14649
14354
|
}
|
|
14650
14355
|
});
|
|
14651
14356
|
preparedPrefix = foldResult;
|
|
14357
|
+
if (activeThinkingPrefixHold && firstRenderBust && committedFoldBustsServedPrefix) {
|
|
14358
|
+
releaseThinkingForRewrite();
|
|
14359
|
+
}
|
|
14652
14360
|
prefixPreflightFailed = foldResult.materializationContentionRetryExhausted === true;
|
|
14653
14361
|
foldExecutedThisPass = foldExecutesThisPass(foldDueDecision.value || softRefreshOpportunity, foldResult.m0RematerializedThisPass);
|
|
14654
14362
|
foldBustsServedPrefixThisPass = foldExecutedThisPass && (committedFoldBustsServedPrefix ?? true);
|
|
@@ -14682,18 +14390,33 @@ async function runPostTransformPhase(args) {
|
|
|
14682
14390
|
}
|
|
14683
14391
|
sessionLog(args.sessionId, `m[0] HARD fold decision: reason=${m0MaterializeReason ?? foldDueDecision.reason ?? (foldExecutedThisPass ? "drift" : "soft_refresh")} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
|
|
14684
14392
|
}
|
|
14393
|
+
if (args.normalizeRecoveryTail && (foldBustsServedPrefixThisPass || firstRenderBust)) {
|
|
14394
|
+
args.normalizeRecoveryTail();
|
|
14395
|
+
args.tags = getTagsBySession(args.db, args.sessionId);
|
|
14396
|
+
newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
|
|
14397
|
+
}
|
|
14685
14398
|
logTransformTiming(args.sessionId, "pp.prefixPreflight", tPostprocessSetup, `foldExecuted=${foldExecutedThisPass} m1Refreshed=${publishedM1RefreshedThisPass}`);
|
|
14686
14399
|
const tPassDecisions = performance.now();
|
|
14400
|
+
const frontToolCandidates = args.tags.filter((tag) => tag.type === "tool" && tag.status === "active" && args.targets.get(tag.tagNumber)?.canDrop?.());
|
|
14401
|
+
if (activeThinkingPrefixHold && (args.forceSignedRebuildForFit || args.contextUsage.percentage >= 95 && frontToolCandidates.length > 0 && frontToolCandidates.every((tag) => newTargets.get(tag.tagNumber)?.thinkingRewriteProtected === true))) {
|
|
14402
|
+
releaseThinkingForRewrite(true);
|
|
14403
|
+
}
|
|
14404
|
+
if (activeThinkingPrefixHold) {
|
|
14405
|
+
isExplicitFlush = false;
|
|
14406
|
+
deferredMaterialize = false;
|
|
14407
|
+
materializationRequested = false;
|
|
14408
|
+
}
|
|
14687
14409
|
const shouldReadPendingOps = !compactionOff && (materializationRequested || publishedM1RefreshedThisPass || args.schedulerDecision === "execute" || forceMaterialization || foldExecutedThisPass || firstRenderBust || compartmentRunning);
|
|
14688
14410
|
const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
|
|
14689
14411
|
const hasPendingUserOps = pendingOps.length > 0;
|
|
14690
14412
|
if (args.schedulerDecision === "execute" && pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected))
|
|
14691
|
-
args.pendingMaterializationSessions
|
|
14413
|
+
requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "thinking_hold");
|
|
14692
14414
|
const formatPendingOpsDepth = () => {
|
|
14693
14415
|
const depth = getPendingOpsCount(args.db, args.sessionId);
|
|
14694
14416
|
return depth === null ? "not loaded (deferred pass)" : String(depth);
|
|
14695
14417
|
};
|
|
14696
|
-
const
|
|
14418
|
+
const heldIdleExpiryRebuild = activeThinkingPrefixHold && args.m0M1?.hardSignals?.cacheExpired === true;
|
|
14419
|
+
const idleExpiryRebuild = (!freezeM0M1 || activeThinkingPrefixHold) && args.m0M1?.hardSignals?.cacheExpired === true;
|
|
14697
14420
|
const rideSignals = {
|
|
14698
14421
|
subagentExecute: !args.fullFeatureMode && args.schedulerDecision === "execute",
|
|
14699
14422
|
hardFold: foldBustsServedPrefixThisPass || firstRenderBust || idleExpiryRebuild,
|
|
@@ -14701,15 +14424,16 @@ async function runPostTransformPhase(args) {
|
|
|
14701
14424
|
explicitFlush: isExplicitFlush || deferredMaterialize && !prefixPreflightFailed,
|
|
14702
14425
|
publishedHistory: publishedM1RefreshedThisPass || !m0M1EnabledForFold && (args.pendingCompartmentInjection?.compartmentCount ?? 0) > 0 && (args.historyRebuiltThisPass || args.rebuiltHistoryFromInitialPrepare || args.canConsumeDeferredLate && args.deferredHistoryWasPendingAtPassStart)
|
|
14703
14426
|
};
|
|
14704
|
-
const publishedWorkDrainAllowed = !compactionOff && hasReclaimRide(rideSignals);
|
|
14427
|
+
const publishedWorkDrainAllowed = !compactionOff && (!activeThinkingPrefixHold || firstRenderBust || idleExpiryRebuild || emergencyDropEligible) && hasReclaimRide(rideSignals);
|
|
14705
14428
|
const shouldApplyPendingOps = publishedWorkDrainAllowed;
|
|
14706
|
-
const shouldRunHeuristics = !compactionOff &&
|
|
14429
|
+
const shouldRunHeuristics = !compactionOff && publishedWorkDrainAllowed && (rideSignals.publishedHistory || materializationRequested || forceMaterialization || foldBustsServedPrefixThisPass || firstRenderBust || heldIdleExpiryRebuild || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
|
|
14707
14430
|
const isCacheBustingPass = publishedWorkDrainAllowed;
|
|
14431
|
+
const canEditWholePrefix = isCacheBustingPass && !activeThinkingPrefixHold;
|
|
14708
14432
|
const previousTemporalDecisions = args.temporalCandidates && !compactionOff ? new Map([
|
|
14709
14433
|
...args.temporalObservedDecisions ?? [],
|
|
14710
14434
|
...getTemporalDecisions(args.db, args.sessionId, args.temporalReplayIds ?? args.temporalCandidates.keys())
|
|
14711
14435
|
]) : undefined;
|
|
14712
|
-
const temporalDecisions = args.temporalCandidates && !compactionOff ?
|
|
14436
|
+
const temporalDecisions = args.temporalCandidates && !compactionOff ? canEditWholePrefix ? new Map([
|
|
14713
14437
|
...previousTemporalDecisions ?? [],
|
|
14714
14438
|
...freezeTemporalDecisions(args.db, args.sessionId, args.temporalCandidates)
|
|
14715
14439
|
]) : previousTemporalDecisions : undefined;
|
|
@@ -14725,6 +14449,43 @@ async function runPostTransformPhase(args) {
|
|
|
14725
14449
|
const removedReasoningIds = new Set;
|
|
14726
14450
|
let dropLeavesReasoning = false;
|
|
14727
14451
|
let reasoningRemovalReadable = false;
|
|
14452
|
+
const refreshReasoningRemovalUnion = () => {
|
|
14453
|
+
if (compactionOff)
|
|
14454
|
+
return;
|
|
14455
|
+
try {
|
|
14456
|
+
if (reasoningRemovalEnabled) {
|
|
14457
|
+
const committed = getReasoningRemovalState(args.db, args.sessionId);
|
|
14458
|
+
for (const id of committed.messageIds)
|
|
14459
|
+
removedReasoningIds.add(id);
|
|
14460
|
+
dropLeavesReasoning = committed.dropLeavesReasoning;
|
|
14461
|
+
}
|
|
14462
|
+
const committedWatermark = args.db.prepare("SELECT cleared_reasoning_through_tag AS watermark, last_observed_model_key AS modelKey FROM session_meta WHERE session_id=?").get(args.sessionId);
|
|
14463
|
+
if (committedWatermark && committedWatermark.modelKey === args.sessionMeta.lastObservedModelKey) {
|
|
14464
|
+
args.sessionMeta.clearedReasoningThroughTag = Math.max(args.sessionMeta.clearedReasoningThroughTag, committedWatermark.watermark);
|
|
14465
|
+
if (!prefixBoundModel) {
|
|
14466
|
+
if (canUseEmptySentinels)
|
|
14467
|
+
replayClearedReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.sessionMeta.clearedReasoningThroughTag);
|
|
14468
|
+
replayStrippedInlineThinking(args.messages, args.messageTagNumbers, args.sessionMeta.clearedReasoningThroughTag);
|
|
14469
|
+
}
|
|
14470
|
+
}
|
|
14471
|
+
} catch (error) {
|
|
14472
|
+
failPass("reasoning-removal-read-failure", error);
|
|
14473
|
+
throw new EmergencyFailClosedError("Saved reasoning removals could not be refreshed", {
|
|
14474
|
+
cause: error
|
|
14475
|
+
});
|
|
14476
|
+
}
|
|
14477
|
+
};
|
|
14478
|
+
const replayCommittedVisibleDrops = () => {
|
|
14479
|
+
if (compactionOff)
|
|
14480
|
+
return false;
|
|
14481
|
+
const visible = new Set(args.messages);
|
|
14482
|
+
const targets = new Map([...args.targets].filter(([, target]) => {
|
|
14483
|
+
if (target.mutationParts)
|
|
14484
|
+
return target.mutationParts.some(({ message, part }) => visible.has(message) && message.info.syntheticHead !== true && message.parts.includes(part) && (!isRecord(part) || part.synthetic !== true));
|
|
14485
|
+
return target.message !== undefined && visible.has(target.message) && target.message.info.syntheticHead !== true;
|
|
14486
|
+
}));
|
|
14487
|
+
return applyFlushedStatuses(args.sessionId, args.db, targets);
|
|
14488
|
+
};
|
|
14728
14489
|
if (reasoningRemovalEnabled) {
|
|
14729
14490
|
try {
|
|
14730
14491
|
const state = getReasoningRemovalState(args.db, args.sessionId);
|
|
@@ -14740,7 +14501,7 @@ async function runPostTransformPhase(args) {
|
|
|
14740
14501
|
}
|
|
14741
14502
|
if (shouldRunHeuristics) {
|
|
14742
14503
|
const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
|
|
14743
|
-
const reason = isExplicitFlush ?
|
|
14504
|
+
const reason = isExplicitFlush ? `pending_materialization origin=${pendingOrigin}` : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `${reclaimRideLabel(rideSignals)} subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
|
|
14744
14505
|
sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
|
|
14745
14506
|
} else if (args.schedulerDeferReason !== undefined && args.schedulerDeferReason !== null) {
|
|
14746
14507
|
sessionLog(args.sessionId, `heuristics WILL NOT RUN — reason=${args.schedulerDeferReason}`);
|
|
@@ -14803,7 +14564,7 @@ async function runPostTransformPhase(args) {
|
|
|
14803
14564
|
logTransformTiming(args.sessionId, "pp.passDecisions", tPassDecisions, `pendingOps=${pendingOps.length}`);
|
|
14804
14565
|
try {
|
|
14805
14566
|
if (shouldApplyPendingOps) {
|
|
14806
|
-
const applyReason = isExplicitFlush ?
|
|
14567
|
+
const applyReason = isExplicitFlush ? `pending_materialization origin=${pendingOrigin}` : deferredMaterialize ? "deferred_materialization" : foldBustsServedPrefixThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `${reclaimRideLabel(rideSignals)} (scheduler=${args.schedulerDecision})`;
|
|
14807
14568
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${formatPendingOpsDepth()}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
14808
14569
|
const tApply = performance.now();
|
|
14809
14570
|
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, new Set([
|
|
@@ -14830,7 +14591,7 @@ async function runPostTransformPhase(args) {
|
|
|
14830
14591
|
wordRules: args.cavemanTextCompression.wordRules
|
|
14831
14592
|
} : undefined;
|
|
14832
14593
|
const heuristicTags = shouldApplyPendingOps ? getActiveTagsBySession(args.db, args.sessionId) : args.tags;
|
|
14833
|
-
const emergencyRewriteAlreadyPriced = pendingOpsDidMutate || foldBustsServedPrefixThisPass || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
|
|
14594
|
+
const emergencyRewriteAlreadyPriced = pendingOpsDidMutate || foldBustsServedPrefixThisPass || firstRenderBust || heldIdleExpiryRebuild || args.historyRebuiltThisPass || args.compartmentInjectionRebuiltFromDb || args.rebuiltHistoryFromInitialPrepare;
|
|
14834
14595
|
if (emergencyDropEligible && emergencyRewriteAlreadyPriced && getEmergencyInputSample(args.db, args.sessionId) > 0) {
|
|
14835
14596
|
clearEmergencyDropSample(args.db, args.sessionId);
|
|
14836
14597
|
}
|
|
@@ -14892,7 +14653,8 @@ async function runPostTransformPhase(args) {
|
|
|
14892
14653
|
bindingStrippedIds.add(messageId);
|
|
14893
14654
|
}
|
|
14894
14655
|
}
|
|
14895
|
-
const
|
|
14656
|
+
const reasoningEstimates = tryGetReasoningTokenEstimatesByMessage(args.db, args.sessionId, sessionDecisionCalibration(args.db, args.sessionId).proseRatio);
|
|
14657
|
+
const budgetCutoff = routineCleanupApplied && !activeThinkingPrefixHold && reasoningEstimates ? Math.min(safeReasoningCutoff, opencodeReasoningBudgetCutoff({
|
|
14896
14658
|
messages: args.messages,
|
|
14897
14659
|
messageTagNumbers: args.messageTagNumbers,
|
|
14898
14660
|
budget: args.keepReasoningTokens ?? DEFAULT_KEEP_REASONING_TOKENS,
|
|
@@ -14902,7 +14664,7 @@ async function runPostTransformPhase(args) {
|
|
|
14902
14664
|
proseRatio: sessionDecisionCalibration(args.db, args.sessionId).proseRatio,
|
|
14903
14665
|
frozenMergedIds: getMergedReasoningStrippedIds(args.db, args.sessionId),
|
|
14904
14666
|
anthropic: canUseEmptySentinels || prefixBoundModel || hasAnthropicReasoning(args.messages),
|
|
14905
|
-
textEstimateByMessageId:
|
|
14667
|
+
textEstimateByMessageId: reasoningEstimates
|
|
14906
14668
|
})) : 0;
|
|
14907
14669
|
const clearedReasoning = routineCleanupApplied && canUseEmptySentinels && ageLaneAllowed ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, budgetCutoff) : 0;
|
|
14908
14670
|
if (routineCleanupApplied && canUseEmptySentinels) {
|
|
@@ -14914,7 +14676,7 @@ async function runPostTransformPhase(args) {
|
|
|
14914
14676
|
replayStrippedInlineThinking(args.messages, args.messageTagNumbers, persistedInlineWatermark);
|
|
14915
14677
|
}
|
|
14916
14678
|
let removedReasoningMessages = 0;
|
|
14917
|
-
if (routineCleanupApplied && reasoningRemovalSelectable && reasoningRemovalReadable) {
|
|
14679
|
+
if (routineCleanupApplied && !prefixBoundModel && reasoningRemovalSelectable && reasoningRemovalReadable) {
|
|
14918
14680
|
const newIds = selectReasoningRemovals({
|
|
14919
14681
|
messages: args.messages,
|
|
14920
14682
|
messageTagNumbers: args.messageTagNumbers,
|
|
@@ -14969,7 +14731,7 @@ async function runPostTransformPhase(args) {
|
|
|
14969
14731
|
heuristicOrReasoningEditBesidesTrim = heuristicMutationCount + clearedReasoning + strippedInline > 0;
|
|
14970
14732
|
droppedCount += clearedReasoning + strippedInline + removedReasoningMessages;
|
|
14971
14733
|
if (pendingMaterializationAtPassStart && !freezeM0M1 && !pendingOps.some((op) => newTargets.get(op.tagId)?.thinkingDropProtected)) {
|
|
14972
|
-
args.pendingMaterializationSessions
|
|
14734
|
+
clearPendingMaterialization(args.pendingMaterializationSessions, args.sessionId);
|
|
14973
14735
|
}
|
|
14974
14736
|
if (args.currentTurnId) {
|
|
14975
14737
|
args.lastHeuristicsTurnId.set(args.sessionId, args.currentTurnId);
|
|
@@ -15031,7 +14793,7 @@ async function runPostTransformPhase(args) {
|
|
|
15031
14793
|
logTransformTiming(args.sessionId, "toolReclaim.select", tReclaimSelect, `targets=${autoReclaimTargetCount}`);
|
|
15032
14794
|
if (syntheticPendingOps.length > 0) {
|
|
15033
14795
|
const tReclaimApply = performance.now();
|
|
15034
|
-
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db,
|
|
14796
|
+
autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, newTargets, args.protectedTagIds, undefined, [], syntheticPendingOps, editMarkerTagIds, (reduction) => droppedTokenReductions.push(reduction));
|
|
15035
14797
|
logTransformTiming(args.sessionId, "toolReclaim.apply", tReclaimApply);
|
|
15036
14798
|
if (autoReclaimDidMutate) {
|
|
15037
14799
|
droppedCount += syntheticPendingOps.length;
|
|
@@ -15084,7 +14846,7 @@ async function runPostTransformPhase(args) {
|
|
|
15084
14846
|
const t8 = performance.now();
|
|
15085
14847
|
const frozenStaleReduceIds = replaySnapshot.staleReduceStrippedIds;
|
|
15086
14848
|
const staleReduceResult = dropStaleReduceCalls(args.messages, frozenStaleReduceIds, {
|
|
15087
|
-
detect:
|
|
14849
|
+
detect: canEditWholePrefix,
|
|
15088
14850
|
protectedCount: args.protectedCount,
|
|
15089
14851
|
protectedCallIds: new Set(args.tags.filter((tag) => protectedToolTags.has(tag.tagNumber)).map((tag) => tag.messageId)),
|
|
15090
14852
|
onFirstApplication: recordFirstApplicationAt
|
|
@@ -15098,19 +14860,34 @@ async function runPostTransformPhase(args) {
|
|
|
15098
14860
|
sessionLog(args.sessionId, "transform failed dropping stale mmc_reduce calls:", error);
|
|
15099
14861
|
}
|
|
15100
14862
|
}
|
|
15101
|
-
if (
|
|
14863
|
+
if (!compactionOff && replaySnapshot) {
|
|
15102
14864
|
try {
|
|
15103
14865
|
const tImg = performance.now();
|
|
14866
|
+
const imageWatermark = canEditWholePrefix ? Math.max(args.watermark, getMaxDroppedTagNumber(args.db, args.sessionId)) : args.watermark;
|
|
15104
14867
|
const frozenImageIds = replaySnapshot.processedImageStrippedIds;
|
|
15105
|
-
const
|
|
15106
|
-
|
|
15107
|
-
|
|
14868
|
+
const frozenMarkers = replaySnapshot.processedImageMarkers;
|
|
14869
|
+
const replacementText = canUseEmptySentinels ? "" : "[image stripped]";
|
|
14870
|
+
stripProcessedImages(args.messages, frozenImageIds, {
|
|
14871
|
+
detect: canEditWholePrefix && imageWatermark > 0,
|
|
14872
|
+
watermark: imageWatermark,
|
|
15108
14873
|
messageTagNumbers: args.messageTagNumbers,
|
|
14874
|
+
protectedCutoff: args.protectedCutoff,
|
|
14875
|
+
contextPercentage: args.contextUsage.percentage,
|
|
14876
|
+
replacementText,
|
|
14877
|
+
frozenMarkers,
|
|
14878
|
+
protectedMessageIds: new Set([
|
|
14879
|
+
...args.tags.filter((tag) => protectedToolTags.has(tag.tagNumber)).map((tag) => tag.toolOwnerMessageId ?? tag.messageId)
|
|
14880
|
+
]),
|
|
14881
|
+
persistNewIds: (ids, markers) => {
|
|
14882
|
+
if (!addProcessedImageStrippedIds(args.db, args.sessionId, ids, markers))
|
|
14883
|
+
return false;
|
|
14884
|
+
const committed = getProcessedImageMarkers(args.db, args.sessionId);
|
|
14885
|
+
for (const id of ids)
|
|
14886
|
+
frozenMarkers.set(id, committed.get(id) ?? replacementText);
|
|
14887
|
+
return true;
|
|
14888
|
+
},
|
|
15109
14889
|
onFirstApplication: recordFirstApplicationAt
|
|
15110
14890
|
});
|
|
15111
|
-
if (isCacheBustingPass && imageResult.newlyStrippedIds.length > 0) {
|
|
15112
|
-
addProcessedImageStrippedIds(args.db, args.sessionId, imageResult.newlyStrippedIds);
|
|
15113
|
-
}
|
|
15114
14891
|
logTransformTiming(args.sessionId, "stripProcessedImages", tImg);
|
|
15115
14892
|
} catch (error) {
|
|
15116
14893
|
failPass("image-strip-exception", error);
|
|
@@ -15316,7 +15093,7 @@ async function runPostTransformPhase(args) {
|
|
|
15316
15093
|
messages: args.messages,
|
|
15317
15094
|
fullFeatureMode: args.fullFeatureMode,
|
|
15318
15095
|
compactionOff,
|
|
15319
|
-
isCacheBustingPass,
|
|
15096
|
+
isCacheBustingPass: canEditWholePrefix,
|
|
15320
15097
|
sessionMeta: args.sessionMeta,
|
|
15321
15098
|
todowriteAvailability: args.todowriteAvailability,
|
|
15322
15099
|
client: args.client,
|
|
@@ -15382,23 +15159,22 @@ async function runPostTransformPhase(args) {
|
|
|
15382
15159
|
autoSearchHintAppendedThisPass = autoSearchCompletedThisPass && countAutoSearchHints(args.db, args.sessionId) !== autoSearchHintsBefore;
|
|
15383
15160
|
logTransformTiming(args.sessionId, "pp.autoSearchHint", tAutoSearch);
|
|
15384
15161
|
}
|
|
15385
|
-
if (args.fullFeatureMode &&
|
|
15162
|
+
if (args.fullFeatureMode && canEditWholePrefix) {
|
|
15386
15163
|
const visibleIds = new Set;
|
|
15387
15164
|
for (const message of args.messages) {
|
|
15388
15165
|
if (typeof message.info?.id === "string") {
|
|
15389
15166
|
visibleIds.add(message.info.id);
|
|
15390
15167
|
}
|
|
15391
15168
|
}
|
|
15392
|
-
|
|
15393
|
-
if (prunedDecisions > 0) {
|
|
15394
|
-
sessionLog(args.sessionId, `sticky-injection GC: pruned ${prunedDecisions} auto-search decision(s)`);
|
|
15395
|
-
}
|
|
15169
|
+
flushAutoSearchHintDecisionRetirement(args.db, args.sessionId, visibleIds);
|
|
15396
15170
|
}
|
|
15397
|
-
const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ?
|
|
15171
|
+
const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? pendingOrigin : null);
|
|
15398
15172
|
const materialized = m0RematerializedThisPass || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully;
|
|
15173
|
+
refreshReasoningRemovalUnion();
|
|
15174
|
+
replayCommittedVisibleDrops();
|
|
15399
15175
|
const dropModeSwitchesThisPass = !canUseEmptySentinels && !dropLeavesReasoning && typeof args.resolvedProviderID === "string" && isCacheBustingPass && reasoningRemovalReadable && args.messages.some((message) => message.info.role === "assistant" && message.parts.some((part) => isNeutralizedReasoningPart(part)));
|
|
15400
15176
|
let bustedThisPass = firstApplicationEdits.any || firstRenderBust || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass;
|
|
15401
|
-
const proactiveThinkingStripPermitted = isCacheBustingPass;
|
|
15177
|
+
const proactiveThinkingStripPermitted = isCacheBustingPass && !activeThinkingPrefixHold;
|
|
15402
15178
|
const tFrozenDecisions = performance.now();
|
|
15403
15179
|
if (reasoningMutationTargetUnknown) {
|
|
15404
15180
|
const reasoningCandidates = args.reasoningByMessage.size > 0 ? args.reasoningByMessage.keys() : args.messages;
|
|
@@ -15450,7 +15226,7 @@ async function runPostTransformPhase(args) {
|
|
|
15450
15226
|
sessionLog(args.sessionId, "thinking binding recovery: persistence failed; leaving the bound blocks intact");
|
|
15451
15227
|
}
|
|
15452
15228
|
}
|
|
15453
|
-
if (canUseEmptySentinels &&
|
|
15229
|
+
if (canUseEmptySentinels && canEditWholePrefix) {
|
|
15454
15230
|
const candidates = findMergedReasoningStripDecisions(args.messages, args.resolvedProviderID, mergedReasoningStrippedIds, {
|
|
15455
15231
|
mutationExemptMessage: reasoningMutationExemptMessage,
|
|
15456
15232
|
protectedMessages: args.protectedThinkingMessages
|
|
@@ -15497,7 +15273,7 @@ async function runPostTransformPhase(args) {
|
|
|
15497
15273
|
}
|
|
15498
15274
|
};
|
|
15499
15275
|
const newestAssistantId = typeof trailingBlankNewestAssistant?.info.id === "string" ? trailingBlankNewestAssistant.info.id : undefined;
|
|
15500
|
-
if (
|
|
15276
|
+
if (canEditWholePrefix && trailingBlankDecisions.size > 0) {
|
|
15501
15277
|
const visibleMessageIds = new Set(args.messages.flatMap((message) => typeof message.info.id === "string" ? [message.info.id] : []));
|
|
15502
15278
|
const poisonedKeepIds = [];
|
|
15503
15279
|
for (const [id, decision] of trailingBlankDecisions) {
|
|
@@ -15586,7 +15362,7 @@ async function runPostTransformPhase(args) {
|
|
|
15586
15362
|
}
|
|
15587
15363
|
}
|
|
15588
15364
|
}
|
|
15589
|
-
const prefixEditBesidesReasoningTrim = firstRenderBust || materializationRequested || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || foldBustsServedPrefixThisPass || publishedM1RefreshedThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass || pendingOpsDidMutate || heuristicOrReasoningEditBesidesTrim || emergency || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || dropModeSwitchesThisPass || deferredClearedMarkerRetires || autoSearchHintAppendedThisPass || todoAnchorMovedThisPass || firstApplicationEdits.beforeNewerThinking;
|
|
15365
|
+
const prefixEditBesidesReasoningTrim = firstRenderBust || heldIdleExpiryRebuild || materializationRequested || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully || foldBustsServedPrefixThisPass || publishedM1RefreshedThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass || pendingOpsDidMutate || heuristicOrReasoningEditBesidesTrim || emergency || autoReclaimDidMutateThisPass || convertedToolSkeletonsDidMutate || dropModeSwitchesThisPass || deferredClearedMarkerRetires || autoSearchHintAppendedThisPass || todoAnchorMovedThisPass || firstApplicationEdits.beforeNewerThinking;
|
|
15590
15366
|
if (!compactionOff && args.thinkingBindingRecoveryEnabledForModel === true && proactiveThinkingStripPermitted && prefixEditBesidesReasoningTrim) {
|
|
15591
15367
|
const outcome = freezeReasoningOnBustingPass({
|
|
15592
15368
|
db: args.db,
|
|
@@ -15626,7 +15402,7 @@ async function runPostTransformPhase(args) {
|
|
|
15626
15402
|
const tFinalRepresentation = performance.now();
|
|
15627
15403
|
if (temporalDecisions)
|
|
15628
15404
|
injectTemporalMarkers(args.messages, temporalDecisions);
|
|
15629
|
-
const
|
|
15405
|
+
const finalizeOptions = {
|
|
15630
15406
|
prependedMessageCount,
|
|
15631
15407
|
reasoningMutatedMessages,
|
|
15632
15408
|
reasoningMutationExemptMessage,
|
|
@@ -15637,10 +15413,21 @@ async function runPostTransformPhase(args) {
|
|
|
15637
15413
|
trailingBlankDecisions,
|
|
15638
15414
|
skipMergedReasoningStrip: compactionOff,
|
|
15639
15415
|
skipTrailingWhitespaceStrip: compactionOff
|
|
15640
|
-
}
|
|
15416
|
+
};
|
|
15417
|
+
const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, finalizeOptions);
|
|
15641
15418
|
const removedReasoningParts = reasoningRemovalEnabled ? removeReasoningParts(args.messages, removedReasoningIds, args.resolvedProviderID) : 0;
|
|
15642
15419
|
const reasoningStatusRatio = sessionDecisionCalibration(args.db, args.sessionId).proseRatio;
|
|
15643
15420
|
captureOpencodeReasoningBudgetStatus(args.sessionId, args.messages, args.keepReasoningTokens ?? DEFAULT_KEEP_REASONING_TOKENS, prefixBoundModel, reasoningStatusRatio);
|
|
15421
|
+
if (!rewritingSignedPrefix)
|
|
15422
|
+
args.restoreLatestTurnOriginals?.();
|
|
15423
|
+
if (!rewritingSignedPrefix && args.restoreLatestTurnOriginals) {
|
|
15424
|
+
refreshReasoningRemovalUnion();
|
|
15425
|
+
if (replayCommittedVisibleDrops()) {
|
|
15426
|
+
finalizeMessageRepresentation(args.messages, args.resolvedProviderID, finalizeOptions);
|
|
15427
|
+
}
|
|
15428
|
+
if (reasoningRemovalEnabled)
|
|
15429
|
+
removeReasoningParts(args.messages, removedReasoningIds, args.resolvedProviderID);
|
|
15430
|
+
}
|
|
15644
15431
|
sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts} removedReasoningParts=${removedReasoningParts} settledDroppedReasoning=${settledDroppedReasoning}`);
|
|
15645
15432
|
logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
|
|
15646
15433
|
const tTailBaseline = performance.now();
|
|
@@ -15739,6 +15526,7 @@ async function runPostTransformPhase(args) {
|
|
|
15739
15526
|
logTransformTiming(args.sessionId, "pp.tailGuard", tTailGuard);
|
|
15740
15527
|
args.restoreLatestTurnOriginals?.();
|
|
15741
15528
|
return {
|
|
15529
|
+
thinkingReleasedForFit,
|
|
15742
15530
|
explicitMaterializedSuccessfully,
|
|
15743
15531
|
deferredMaterializedSuccessfully,
|
|
15744
15532
|
materialized,
|
|
@@ -15764,7 +15552,7 @@ function checkM0MutationDriftAndSignal(args) {
|
|
|
15764
15552
|
const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
|
|
15765
15553
|
const cachedMaxMutationId = args.cachedM0MaxMutationId ?? 0;
|
|
15766
15554
|
if (currentMaxMutationId !== cachedMaxMutationId) {
|
|
15767
|
-
args.pendingMaterializationSessions
|
|
15555
|
+
requestPendingMaterialization(args.pendingMaterializationSessions, args.sessionId, "mutation_drift");
|
|
15768
15556
|
args.historyRefreshSessions?.add(args.sessionId);
|
|
15769
15557
|
sessionLog(args.sessionId, `m[0] drift watcher: mutation id changed ${cachedMaxMutationId} → ${currentMaxMutationId}; scheduling next-pass materialization`);
|
|
15770
15558
|
return true;
|
|
@@ -15808,7 +15596,6 @@ class UnresolvedHistoryBoundaryError extends Error {
|
|
|
15808
15596
|
this.name = "UnresolvedHistoryBoundaryError";
|
|
15809
15597
|
}
|
|
15810
15598
|
}
|
|
15811
|
-
|
|
15812
15599
|
// src/hooks/magic-context/transform.ts
|
|
15813
15600
|
var MESSAGE_TOKENS_CACHE_MAX = 100;
|
|
15814
15601
|
var messageTokensBySession = new BoundedSessionMap(MESSAGE_TOKENS_CACHE_MAX);
|
|
@@ -15881,6 +15668,7 @@ function resolveTransformHostSeams(deps) {
|
|
|
15881
15668
|
return {
|
|
15882
15669
|
hostRawMessages: deps.hostRawMessages ?? readRawSessionMessages2,
|
|
15883
15670
|
hostMessageReconciliationSource: deps.hostMessageReconciliationSource ?? readRawSessionMessages2,
|
|
15671
|
+
hostPrepareRawOrdinals: deps.hostPrepareRawOrdinals ?? prepareRawSessionOrdinals2,
|
|
15884
15672
|
hostProtectedTailBoundary: deps.hostProtectedTailBoundary ?? resolveOpenCodeProtectedTailBoundary,
|
|
15885
15673
|
hostModelFallback: deps.hostModelFallback ?? findLastAssistantModelFromOpenCodeDb,
|
|
15886
15674
|
hostRefusalNotice: deps.hostRefusalNotice ?? sendEmergencyRefusalNotice,
|
|
@@ -15888,12 +15676,18 @@ function resolveTransformHostSeams(deps) {
|
|
|
15888
15676
|
};
|
|
15889
15677
|
}
|
|
15890
15678
|
function createTransform(deps) {
|
|
15679
|
+
registerSystemDateRefresh(deps.historyRefreshSessions);
|
|
15891
15680
|
const finalWireUsage = createFinalWireUsageTracker();
|
|
15892
15681
|
const host = resolveTransformHostSeams(deps);
|
|
15893
15682
|
const loadedSessions = new Set;
|
|
15683
|
+
const prefixHoldLogTurnIds = new Map;
|
|
15684
|
+
const thinkingFitRetries = new Set;
|
|
15685
|
+
const clearSessionLogState = (sessionId) => {
|
|
15686
|
+
prefixHoldLogTurnIds.delete(sessionId);
|
|
15687
|
+
};
|
|
15894
15688
|
const unmanagedOverWindowSessions = new Set;
|
|
15895
|
-
const deferredHistoryRefreshSessions = deps.deferredHistoryRefreshSessions
|
|
15896
|
-
const deferredMaterializationSessions = deps.deferredMaterializationSessions
|
|
15689
|
+
const deferredHistoryRefreshSessions = deps.deferredHistoryRefreshSessions ??= new Set;
|
|
15690
|
+
const deferredMaterializationSessions = deps.deferredMaterializationSessions ??= new Set;
|
|
15897
15691
|
const maintenanceTail = createMaintenanceTailLauncher({
|
|
15898
15692
|
db: deps.db,
|
|
15899
15693
|
getMaintenanceConfig: deps.maintenanceConfig,
|
|
@@ -15909,17 +15703,22 @@ function createTransform(deps) {
|
|
|
15909
15703
|
const startTime = performance.now();
|
|
15910
15704
|
const historianRun = deps.resolveHistorianRun?.();
|
|
15911
15705
|
const messages = output.messages;
|
|
15706
|
+
const originalForThinkingFit = messages.some((message) => message.parts.some((part) => isRecord(part) && ["reasoning", "thinking", "redacted_thinking"].includes(String(part.type)))) ? structuredClone(messages) : null;
|
|
15912
15707
|
const passOutcome = createPassOutcome();
|
|
15913
15708
|
const tSessionId = performance.now();
|
|
15914
15709
|
const sessionId = findSessionId(messages);
|
|
15915
15710
|
if (!sessionId) {
|
|
15916
15711
|
return;
|
|
15917
15712
|
}
|
|
15713
|
+
deps.onMessagesPassStarted?.(sessionId, messages);
|
|
15714
|
+
const dateRequest = systemDateRequestForOutput(deps.historyRefreshSessions, output) ?? beginSystemDateRequest(deps.historyRefreshSessions, sessionId, "messages", systemDateTurnId(messages), systemDateRequestIdentity(output));
|
|
15715
|
+
bindSystemDateRequest(output, dateRequest);
|
|
15918
15716
|
const temporalCandidates = deps.experimentalTemporalAwareness ? collectTemporalCandidates(messages) : undefined;
|
|
15919
15717
|
const temporalReplayIds = temporalCandidates ? messages.flatMap((message) => message.info.id ? [message.info.id] : []) : undefined;
|
|
15920
15718
|
logTransformTiming(sessionId, "findSessionId", tSessionId, `messages=${messages.length}`);
|
|
15921
15719
|
const tLkgEntry = performance.now();
|
|
15922
15720
|
const lkgInput = projectEntry(sessionId, messages);
|
|
15721
|
+
const recovery = deps.compactionOff ? {} : readLkgRecoveryPrefix(sessionId, lkgInput, messages, deps.db);
|
|
15923
15722
|
logTransformTiming(sessionId, "lkg.entryProjection", tLkgEntry, entryReuse ? `reused=${entryReuse.reused} retained=${entryReuse.retained} retainedBytes=${entryReuse.retainedBytes}` : undefined);
|
|
15924
15723
|
const resolvedSessionId = sessionId;
|
|
15925
15724
|
const runNotificationParams = (sid) => {
|
|
@@ -15929,6 +15728,13 @@ function createTransform(deps) {
|
|
|
15929
15728
|
beginLkgPass(sessionId);
|
|
15930
15729
|
clearOpenCodePendingTransformDecision(sessionId);
|
|
15931
15730
|
const db = deps.db;
|
|
15731
|
+
try {
|
|
15732
|
+
const tPrepare = performance.now();
|
|
15733
|
+
const ready = await host.hostPrepareRawOrdinals(sessionId);
|
|
15734
|
+
logTransformTiming(sessionId, "rawOrdinals.prepare", tPrepare, `ready=${ready}`);
|
|
15735
|
+
} catch (error) {
|
|
15736
|
+
sessionLog(sessionId, "transform: canonical ordinal warm-up threw:", error);
|
|
15737
|
+
}
|
|
15932
15738
|
const failPass = (site, error, kind) => {
|
|
15933
15739
|
passOutcome.record(site, kind);
|
|
15934
15740
|
if (deps.compactionOff === true)
|
|
@@ -16070,20 +15876,30 @@ function createTransform(deps) {
|
|
|
16070
15876
|
let restoreLatestTurnOriginals;
|
|
16071
15877
|
const activeThinkingModel = findLastAssistantModel(messages) ?? deps.liveModelBySession?.get(sessionId);
|
|
16072
15878
|
let activeThinkingTurn = hasActiveAnthropicThinkingTurn(messages, activeThinkingModel?.providerID, activeThinkingModel?.modelID);
|
|
16073
|
-
|
|
15879
|
+
const unresolvedDirectoryHold = sessionDirectoryFellBack && sessionMeta.cachedM0Bytes != null && sessionMeta.cachedM1Bytes != null && (() => {
|
|
16074
15880
|
try {
|
|
16075
15881
|
return hasRecordedSessionProjectIdentity(db, sessionId);
|
|
16076
15882
|
} catch {
|
|
16077
15883
|
return true;
|
|
16078
15884
|
}
|
|
16079
15885
|
})();
|
|
16080
|
-
|
|
16081
|
-
|
|
15886
|
+
let activeThinkingPrefixHold = activeThinkingTurn && isPrefixBoundThinkingModel(activeThinkingModel?.providerID, activeThinkingModel?.modelID);
|
|
15887
|
+
let freezeM0M1 = unresolvedDirectoryHold || activeThinkingPrefixHold;
|
|
15888
|
+
if (freezeM0M1 && prefixHoldLogTurnIds.get(sessionId) !== currentTurnId) {
|
|
15889
|
+
prefixHoldLogTurnIds.set(sessionId, currentTurnId);
|
|
15890
|
+
const reason = activeThinkingPrefixHold ? "active thinking turn (prefix-bound model)" : "session directory unresolved";
|
|
15891
|
+
sessionLog(sessionId, `m[0]/m[1] frozen: ${reason}; replaying the frozen prefix and deferring any rebuild`);
|
|
16082
15892
|
}
|
|
16083
15893
|
const compartmentDirectory = sessionDirectory;
|
|
16084
15894
|
const historianRunnable = deps.historianRunnable !== false;
|
|
16085
15895
|
const canRunCompartments = fullFeatureMode && !compactionOff && historianRunnable && (deps.client !== undefined || deps.hiddenCompletionExecutor !== undefined) && compartmentDirectory.length > 0;
|
|
16086
15896
|
const fallbackModelId = deps.getFallbackModelId?.(sessionId);
|
|
15897
|
+
if (fullFeatureMode && !compactionOff && historianRunnable) {
|
|
15898
|
+
const tOwners = performance.now();
|
|
15899
|
+
await waitForTagOwners(db, sessionId, sessionDecisionCalibration(db, sessionId).proseRatio);
|
|
15900
|
+
sessionMeta = getOrCreateSessionMeta(db, sessionId);
|
|
15901
|
+
logTransformTiming(sessionId, "tagOwners.prepare", tOwners);
|
|
15902
|
+
}
|
|
16087
15903
|
const tModelDetect = performance.now();
|
|
16088
15904
|
const persistedUsageBeforeResets = contextUsagePassSnapshot(sessionMeta).persistedUsage;
|
|
16089
15905
|
if (deps.liveModelBySession) {
|
|
@@ -16201,7 +16017,13 @@ function createTransform(deps) {
|
|
|
16201
16017
|
}
|
|
16202
16018
|
const resolvedProviderID = modelForBudget?.providerID;
|
|
16203
16019
|
activeThinkingTurn ||= hasActiveAnthropicThinkingTurn(messages, resolvedProviderID, modelForBudget?.modelID);
|
|
16204
|
-
|
|
16020
|
+
activeThinkingPrefixHold ||= activeThinkingTurn && isPrefixBoundThinkingModel(resolvedProviderID, modelForBudget?.modelID);
|
|
16021
|
+
freezeM0M1 ||= activeThinkingPrefixHold;
|
|
16022
|
+
if (freezeM0M1 && prefixHoldLogTurnIds.get(sessionId) !== currentTurnId) {
|
|
16023
|
+
prefixHoldLogTurnIds.set(sessionId, currentTurnId);
|
|
16024
|
+
const reason = activeThinkingPrefixHold ? "active thinking turn (prefix-bound model)" : "session directory unresolved";
|
|
16025
|
+
sessionLog(sessionId, `m[0]/m[1] frozen: ${reason}; replaying the frozen prefix and deferring any rebuild`);
|
|
16026
|
+
}
|
|
16205
16027
|
const protectedThinkingMessagesForPass = activeThinkingTurn || isAnthropicFamilyRoute(resolvedProviderID, modelForBudget?.modelID) ? latestAssistantTurnMessages(messages) : new Set;
|
|
16206
16028
|
const canUseEmptySentinels = modelAcceptsEmptyContent(resolvedProviderID);
|
|
16207
16029
|
const resolvedContextLimit = modelForBudget ? resolveTrustedContextLimit(modelForBudget.providerID, modelForBudget.modelID, {
|
|
@@ -16267,7 +16089,7 @@ function createTransform(deps) {
|
|
|
16267
16089
|
const schedulerDeferReason = schedulerDecision === "defer" ? "scheduler_defer" : null;
|
|
16268
16090
|
const historyRefreshExplicitBeforePrepare = !freezeM0M1 && deps.historyRefreshSessions.has(sessionId);
|
|
16269
16091
|
const deferredHistoryWasPendingAtPassStart = !freezeM0M1 && deferredHistoryRefreshSessions.has(sessionId);
|
|
16270
|
-
const prefixTrimSourceOrder =
|
|
16092
|
+
const prefixTrimSourceOrder = capturePrefixTrimSourceOrder(messages);
|
|
16271
16093
|
const earlyActiveRunBlocksMaterialization = (getActiveCompartmentRun(sessionId) !== undefined || sessionMeta.compartmentInProgress) && contextUsageEarly.percentage < forceMaterializationPercentage;
|
|
16272
16094
|
const canConsumeDeferredEarly = canConsumeDeferredOnThisPass({
|
|
16273
16095
|
schedulerDecision,
|
|
@@ -16411,8 +16233,11 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16411
16233
|
if (!compactionOff && taggerFloor === 0 && messages.length > 0) {
|
|
16412
16234
|
sessionLog(sessionId, `tag floor: 0 (full-scan fallback) — no leading wire message resolved a tag across ${messages.length} msgs`);
|
|
16413
16235
|
}
|
|
16236
|
+
const ownerRatio = sessionDecisionCalibration(db, sessionId).proseRatio;
|
|
16237
|
+
prewarmTagOwners(db, sessionId, ownerRatio);
|
|
16238
|
+
const tagOwnersReady = isTagOwnerSummaryReady(db, sessionId, ownerRatio);
|
|
16414
16239
|
let triggerBoundarySnapshot;
|
|
16415
|
-
if (fullFeatureMode && !compactionOff && historianRunnable && !sessionMeta.compartmentInProgress) {
|
|
16240
|
+
if (fullFeatureMode && !compactionOff && historianRunnable && tagOwnersReady && !sessionMeta.compartmentInProgress) {
|
|
16416
16241
|
const tTrigger = performance.now();
|
|
16417
16242
|
try {
|
|
16418
16243
|
const inMemoryTail = buildTriggerInMemoryTail(db, sessionId, extractInMemoryMessageViews(messages));
|
|
@@ -16474,6 +16299,26 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16474
16299
|
logTransformTiming(sessionId, "injectTemporalMarkers", tTemporal);
|
|
16475
16300
|
}
|
|
16476
16301
|
let taggingSucceeded = false;
|
|
16302
|
+
let recoveryBatch = null;
|
|
16303
|
+
let recoveryNormalized = false;
|
|
16304
|
+
const normalizeRecoveryTail = recovery.prefix ? () => {
|
|
16305
|
+
if (recoveryNormalized)
|
|
16306
|
+
return;
|
|
16307
|
+
const tail = messages.filter((message) => recovery.prefix?.untaggedInputIds.has(message.info.id ?? ""));
|
|
16308
|
+
const tagged = tagMessages(sessionId, tail, deps.tagger, db, {
|
|
16309
|
+
skipPrefixInjection: !ctxReduceCallable,
|
|
16310
|
+
servedMessages: messages,
|
|
16311
|
+
normalizeRestoredAssistantText: deps.normalizeRestoredAssistantText
|
|
16312
|
+
});
|
|
16313
|
+
for (const [number, target] of tagged.targets)
|
|
16314
|
+
targets.set(number, target);
|
|
16315
|
+
for (const [message, parts] of tagged.reasoningByMessage)
|
|
16316
|
+
reasoningByMessage.set(message, parts);
|
|
16317
|
+
for (const [message, number] of tagged.messageTagNumbers)
|
|
16318
|
+
messageTagNumbers.set(message, number);
|
|
16319
|
+
recoveryBatch = tagged.batch;
|
|
16320
|
+
recoveryNormalized = true;
|
|
16321
|
+
} : undefined;
|
|
16477
16322
|
if (!compactionOff) {
|
|
16478
16323
|
try {
|
|
16479
16324
|
const t0 = performance.now();
|
|
@@ -16484,18 +16329,24 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16484
16329
|
const messagesForTagging = messagesBeforeInitialPrepare && hiddenMessagesAtCompactionSeam.length > 0 ? messagesBeforeInitialPrepare : messages;
|
|
16485
16330
|
const canAdoptScopedToolSweep = isCacheBusting || canConsumeDeferredEarly;
|
|
16486
16331
|
const scopedToolSweep = useScopedToolSweep(db, sessionId, canAdoptScopedToolSweep) ? true : createPreAdoptionToolSweepResolver(db, sessionId);
|
|
16487
|
-
const result = tagMessages(sessionId, messagesForTagging, deps.tagger, db, {
|
|
16332
|
+
const result = tagMessages(sessionId, recovery.prefix ? messagesForTagging.filter((message) => !recovery.prefix?.untaggedInputIds.has(message.info.id ?? "")) : messagesForTagging, deps.tagger, db, {
|
|
16488
16333
|
skipPrefixInjection,
|
|
16489
16334
|
scopedToolSweep,
|
|
16490
16335
|
servedMessages: messages,
|
|
16491
|
-
protectedThinkingMessages: protectedThinkingMessagesForPass
|
|
16336
|
+
protectedThinkingMessages: protectedThinkingMessagesForPass,
|
|
16337
|
+
normalizeRestoredAssistantText: deps.normalizeRestoredAssistantText
|
|
16492
16338
|
});
|
|
16493
16339
|
targets = result.targets;
|
|
16494
16340
|
if (thinkingRecovery.restore)
|
|
16495
16341
|
restoreLatestTurnOriginals = captureLatestTurnOriginals(messages);
|
|
16496
16342
|
reasoningByMessage = result.reasoningByMessage;
|
|
16497
16343
|
messageTagNumbers = result.messageTagNumbers;
|
|
16498
|
-
batch =
|
|
16344
|
+
batch = {
|
|
16345
|
+
finalize: () => {
|
|
16346
|
+
result.batch?.finalize();
|
|
16347
|
+
recoveryBatch?.finalize();
|
|
16348
|
+
}
|
|
16349
|
+
};
|
|
16499
16350
|
if (resolvedProviderID && !isAnthropicFamilyRoute(resolvedProviderID, modelForBudget?.modelID)) {
|
|
16500
16351
|
for (const target of targets.values()) {
|
|
16501
16352
|
if (target.requiresToolArcSkeleton)
|
|
@@ -16614,7 +16465,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16614
16465
|
sessionMeta = { ...sessionMeta, compartmentInProgress };
|
|
16615
16466
|
logTransformTiming(sessionId, "compartmentPhase", tCompartmentPhase);
|
|
16616
16467
|
if (pendingCompartmentInjection?.needsFreshMaterialization) {
|
|
16617
|
-
deps.pendingMaterializationSessions
|
|
16468
|
+
requestPendingMaterialization(deps.pendingMaterializationSessions, sessionId, "boundary_repair");
|
|
16618
16469
|
deferredMaterializationSessions.add(sessionId);
|
|
16619
16470
|
}
|
|
16620
16471
|
const hardModel = deps.liveModelBySession?.get(sessionId);
|
|
@@ -16708,6 +16559,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16708
16559
|
const protectedCutoff = protectionWindow.cutoff;
|
|
16709
16560
|
const tPostProcess = performance.now();
|
|
16710
16561
|
const postTransformResult = await runPostTransformPhase({
|
|
16562
|
+
normalizeRecoveryTail,
|
|
16711
16563
|
compactionMarkerStrategy: deps.compactionMarkerStrategy ?? defaultCompactionMarkerStrategy,
|
|
16712
16564
|
sessionId,
|
|
16713
16565
|
db,
|
|
@@ -16726,7 +16578,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16726
16578
|
client: deps.client,
|
|
16727
16579
|
activeAgent,
|
|
16728
16580
|
batch,
|
|
16729
|
-
contextUsage,
|
|
16581
|
+
contextUsage: thinkingFitRetries.has(sessionId) ? { ...contextUsage, percentage: Math.max(95, contextUsage.percentage) } : contextUsage,
|
|
16730
16582
|
usableWindow: resolvedContextLimit ?? 0,
|
|
16731
16583
|
schedulerDecision,
|
|
16732
16584
|
schedulerDeferReason,
|
|
@@ -16738,6 +16590,17 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16738
16590
|
compartmentInProgress,
|
|
16739
16591
|
historyRefreshExplicitBeforePrepare,
|
|
16740
16592
|
freezeM0M1,
|
|
16593
|
+
activeThinkingPrefixHold,
|
|
16594
|
+
directoryPrefixHold: unresolvedDirectoryHold,
|
|
16595
|
+
forceSignedRebuildForFit: thinkingFitRetries.has(sessionId) || !!recovery.rebuildReason,
|
|
16596
|
+
readLastServedMessages: () => {
|
|
16597
|
+
const slot = getInMemorySlot(sessionId) ?? loadPersistedLkgSlot(db, sessionId);
|
|
16598
|
+
try {
|
|
16599
|
+
return slot ? JSON.parse(slot.jsonPrefix) : null;
|
|
16600
|
+
} catch {
|
|
16601
|
+
return null;
|
|
16602
|
+
}
|
|
16603
|
+
},
|
|
16741
16604
|
deferredHistoryWasPendingAtPassStart,
|
|
16742
16605
|
compartmentInjectionRebuiltFromDb: pendingCompartmentInjection?.rebuiltFromDb === true,
|
|
16743
16606
|
rebuiltHistoryFromInitialPrepare,
|
|
@@ -16789,6 +16652,15 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16789
16652
|
hardSignals: m0HardSignals
|
|
16790
16653
|
}
|
|
16791
16654
|
});
|
|
16655
|
+
if (recovery.prefix && !recoveryNormalized) {
|
|
16656
|
+
const priorIds = new Set(recovery.prefix.inputs.map((input) => input.id));
|
|
16657
|
+
const newIds = new Set(lkgInput.flatMap((input) => input.id && !priorIds.has(input.id) ? [input.id] : []));
|
|
16658
|
+
const suffix = messages.filter((message) => message.info.id && newIds.has(message.info.id));
|
|
16659
|
+
messages.splice(0, messages.length, ...JSON.parse(recovery.prefix.json), ...suffix);
|
|
16660
|
+
}
|
|
16661
|
+
const recoveryReleaseReason = recovery.rebuildReason ?? (recoveryNormalized ? "recovery_tail_normalized" : undefined);
|
|
16662
|
+
if (recoveryReleaseReason)
|
|
16663
|
+
postTransformResult.bustedThisPass = true;
|
|
16792
16664
|
passOutcome.markFinalized();
|
|
16793
16665
|
const finalWireTail = describeFinalWireTail(messages);
|
|
16794
16666
|
let finalWireEstimate;
|
|
@@ -16819,6 +16691,21 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16819
16691
|
if (finalWireEstimate) {
|
|
16820
16692
|
sessionLog(sessionId, `transform: final-wire telemetry estimate=${finalWireEstimate.tokens} trusted=${finalWireEstimate.trusted} conversation=${finalWireEstimate.messageTokens.conversation} tools=${finalWireEstimate.messageTokens.toolCall} system=${finalWireEstimate.systemTokens} toolDefinitions=${finalWireEstimate.toolDefinitionTokens ?? "unknown"} tail=${finalWireTail}`);
|
|
16821
16693
|
}
|
|
16694
|
+
if ((finalWireEstimate?.refusalGrade || finalWireEstimate?.refusalBasis === "byte-bound" && finalWireEstimate.refusalTokens !== undefined) && boundaryContextLimit > 0 && (finalWireEstimate.refusalTokens ?? finalWireEstimate.tokens) > boundaryContextLimit) {
|
|
16695
|
+
if (!thinkingFitRetries.has(sessionId) && activeThinkingPrefixHold && originalForThinkingFit && hasActiveAnthropicThinkingTurn(messages, resolvedProviderID, modelForBudget?.modelID)) {
|
|
16696
|
+
thinkingFitRetries.add(sessionId);
|
|
16697
|
+
requestPendingMaterialization(deps.pendingMaterializationSessions, sessionId, "fit_retry");
|
|
16698
|
+
messages.splice(0, messages.length, ...originalForThinkingFit);
|
|
16699
|
+
try {
|
|
16700
|
+
await transform({}, output);
|
|
16701
|
+
} finally {
|
|
16702
|
+
thinkingFitRetries.delete(sessionId);
|
|
16703
|
+
}
|
|
16704
|
+
return;
|
|
16705
|
+
}
|
|
16706
|
+
if (thinkingFitRetries.has(sessionId) || postTransformResult.thinkingReleasedForFit)
|
|
16707
|
+
throw contextRefusalError("The request remains over the model window after stripping signed thinking and reclaiming context");
|
|
16708
|
+
}
|
|
16822
16709
|
if (postTransformResult.prefixTrimStatus === "refused") {
|
|
16823
16710
|
const untrimmed = finalWireEstimate ?? estimateFinalWireInputTokens({
|
|
16824
16711
|
messages,
|
|
@@ -16933,11 +16820,16 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16933
16820
|
if (!finalWireEstimate) {
|
|
16934
16821
|
sessionLog(sessionId, `transform: final-wire telemetry estimate=unavailable trusted=false conversation=unknown tools=unknown system=unknown toolDefinitions=unknown tail=${finalWireTail}`);
|
|
16935
16822
|
}
|
|
16936
|
-
|
|
16823
|
+
finishSystemDateRefresh(deps.historyRefreshSessions, dateRequest, postTransformResult.bustedThisPass && !activeThinkingPrefixHold || postTransformResult.thinkingReleasedForFit === true);
|
|
16824
|
+
if (activeThinkingPrefixHold && !postTransformResult.thinkingReleasedForFit && sessionMeta.cachedM0Bytes != null && sessionMeta.cachedM1Bytes != null) {
|
|
16825
|
+
recordHeldHeadForRequest(sessionId, currentLkgRequestIdentity(sessionId), (ownsHistory) => deferDeliveredSystemRefresh(deps, sessionId, ownsHistory));
|
|
16826
|
+
}
|
|
16827
|
+
if (passOutcome.captureEligible || recovery.prefix || recoveryReleaseReason) {
|
|
16937
16828
|
const keys = resolveLkgModelKeys(messages);
|
|
16938
16829
|
const modelKey = modelForBudget ? `${modelForBudget.providerID}/${modelForBudget.modelID}` : keys.modelKey;
|
|
16939
16830
|
const providerKey = modelForBudget?.providerID ?? keys.providerKey;
|
|
16940
16831
|
const captured = captureLkgSlot({
|
|
16832
|
+
completeOutput: !!recovery.prefix || !!recoveryReleaseReason || isPrefixBoundThinkingModel(resolvedProviderID, modelForBudget?.modelID),
|
|
16941
16833
|
sessionId,
|
|
16942
16834
|
input: lkgInput,
|
|
16943
16835
|
output: messages,
|
|
@@ -16949,13 +16841,37 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16949
16841
|
if (captured) {
|
|
16950
16842
|
const capturedSlot = getInMemorySlot(sessionId);
|
|
16951
16843
|
if (capturedSlot) {
|
|
16952
|
-
|
|
16844
|
+
const revision = lkgDirtyRevision(sessionId) ?? dirtyLkgRecoveryRevision(sessionId, capturedSlot);
|
|
16845
|
+
const fence = {
|
|
16846
|
+
ownDirtyRevision: revision,
|
|
16847
|
+
requiredRevision: revision && ownsLkgDirtyFence(sessionId, revision) ? revision : undefined,
|
|
16848
|
+
rebuild: !!recoveryReleaseReason,
|
|
16849
|
+
retainDirtyRevision: recovery.prefix && !recoveryReleaseReason ? revision : undefined
|
|
16850
|
+
};
|
|
16851
|
+
withoutSqliteTransformPass(() => setImmediate(() => {
|
|
16852
|
+
if (fence.requiredRevision) {
|
|
16853
|
+
const latest = getInMemorySlot(sessionId);
|
|
16854
|
+
if (!latest || latest.capturedAt !== capturedSlot.capturedAt || latest.jsonPrefix !== capturedSlot.jsonPrefix || latest.lastInputMessageId !== capturedSlot.lastInputMessageId || latest.modelKey !== capturedSlot.modelKey || latest.providerKey !== capturedSlot.providerKey)
|
|
16855
|
+
return;
|
|
16856
|
+
}
|
|
16857
|
+
try {
|
|
16858
|
+
saveLkgSlotToDb(db, sessionId, capturedSlot, undefined, fence);
|
|
16859
|
+
} catch (error) {
|
|
16860
|
+
sessionLog(sessionId, "Last-good deferred publication remains uncertified:", error);
|
|
16861
|
+
}
|
|
16862
|
+
}));
|
|
16953
16863
|
}
|
|
16864
|
+
noteLkgHealthyPrefix(sessionId, lkgInput, messages, !!recoveryReleaseReason);
|
|
16954
16865
|
}
|
|
16955
|
-
if (
|
|
16956
|
-
|
|
16866
|
+
if (!captured) {
|
|
16867
|
+
if (postTransformResult.bustedThisPass)
|
|
16868
|
+
dropSlot(sessionId, "lkg_refresh_declined");
|
|
16869
|
+
noteUncertifiedNormalLkg(sessionId, invalidateCleanLkgRecoveryFence(sessionId, () => loadPersistedLkgSlot(db, sessionId, true), lkgDirtyRevision(sessionId)));
|
|
16957
16870
|
}
|
|
16958
16871
|
} else if (passOutcome.degradations.length > 0) {
|
|
16872
|
+
if (compactionOff) {
|
|
16873
|
+
noteUncertifiedNormalLkg(sessionId, invalidateCleanLkgRecoveryFence(sessionId, () => loadPersistedLkgSlot(db, sessionId, true), lkgDirtyRevision(sessionId)));
|
|
16874
|
+
}
|
|
16959
16875
|
sessionLog(sessionId, `lkg_capture_declined degradations=${passOutcome.degradations.map((item) => item.site).join(",")}`);
|
|
16960
16876
|
}
|
|
16961
16877
|
if (postTransformResult.bustedThisPass || hardCacheExpired) {
|
|
@@ -16974,7 +16890,8 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
16974
16890
|
droppedTokens: postTransformResult.droppedTokens,
|
|
16975
16891
|
droppedCount: postTransformResult.droppedCount,
|
|
16976
16892
|
inputTokens: contextUsage.inputTokens,
|
|
16977
|
-
bustedThisPass: true
|
|
16893
|
+
bustedThisPass: true,
|
|
16894
|
+
lkgFrozenReleaseReason: recoveryReleaseReason
|
|
16978
16895
|
});
|
|
16979
16896
|
}
|
|
16980
16897
|
logTransformTiming(sessionId, "postTransformPhase", tPostProcess);
|
|
@@ -17093,7 +17010,11 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
|
|
|
17093
17010
|
sessionLog(sessionId, "memory maintenance launch probe failed (ignored):", error);
|
|
17094
17011
|
}
|
|
17095
17012
|
};
|
|
17096
|
-
return transform
|
|
17013
|
+
return Object.assign(transform, {
|
|
17014
|
+
clearSessionLogState(sessionId) {
|
|
17015
|
+
clearSessionLogState(sessionId);
|
|
17016
|
+
}
|
|
17017
|
+
});
|
|
17097
17018
|
}
|
|
17098
17019
|
var HIDDEN_CHILD_AGENT_IDS = new Set([
|
|
17099
17020
|
HISTORIAN_AGENT,
|
|
@@ -18339,7 +18260,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
18339
18260
|
return detail;
|
|
18340
18261
|
});
|
|
18341
18262
|
const buildManagedCtx = async (db) => {
|
|
18342
|
-
const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-
|
|
18263
|
+
const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-s1p37t2g.js");
|
|
18343
18264
|
const { resolveHistorianModel } = await import("./model-resolution-wazv26n0.js");
|
|
18344
18265
|
const DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
|
|
18345
18266
|
const runConfig = historianRunConfig(config, currentPluginConfigReader(directory)?.poll().effective ?? config);
|
|
@@ -18369,8 +18290,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
18369
18290
|
const db = readDatabase();
|
|
18370
18291
|
if (!db)
|
|
18371
18292
|
return { ok: false, error: "db unavailable" };
|
|
18372
|
-
const { runManagedRecomp } = await import("./recomp-orchestrator-
|
|
18373
|
-
const { sendIgnoredMessage } = await import("./send-session-notification-
|
|
18293
|
+
const { runManagedRecomp } = await import("./recomp-orchestrator-wrjy3qym.js");
|
|
18294
|
+
const { sendIgnoredMessage } = await import("./send-session-notification-cz6ev088.js");
|
|
18374
18295
|
log(`[rpc] recomp requested for session ${sessionId}`);
|
|
18375
18296
|
if (!args.client && !args.hiddenCompletionExecutor) {
|
|
18376
18297
|
return {
|
|
@@ -18405,7 +18326,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
18405
18326
|
const message = executeFlush(db, sessionId);
|
|
18406
18327
|
liveSessionState.historyRefreshSessions.add(sessionId);
|
|
18407
18328
|
liveSessionState.systemPromptRefreshSessions.add(sessionId);
|
|
18408
|
-
liveSessionState.pendingMaterializationSessions
|
|
18329
|
+
requestPendingMaterialization(liveSessionState.pendingMaterializationSessions, sessionId, "user_flush");
|
|
18409
18330
|
return { ok: true, message };
|
|
18410
18331
|
});
|
|
18411
18332
|
rpcServer.handle("wrapup", async (params) => {
|
|
@@ -18419,7 +18340,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
18419
18340
|
const db = readDatabase();
|
|
18420
18341
|
if (!db)
|
|
18421
18342
|
return { ok: false, error: "db unavailable" };
|
|
18422
|
-
const { runManagedWrapup } = await import("./wrapup-orchestrator-
|
|
18343
|
+
const { runManagedWrapup } = await import("./wrapup-orchestrator-bmybc5p5.js");
|
|
18423
18344
|
const model = liveSessionState.liveModelBySession.get(sessionId);
|
|
18424
18345
|
const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
18425
18346
|
const ctx = {
|
|
@@ -19232,8 +19153,8 @@ var v2CompactionMarkerStrategy = {
|
|
|
19232
19153
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
19233
19154
|
|
|
19234
19155
|
// src/v2/fold/owner.ts
|
|
19235
|
-
import { createHash as
|
|
19236
|
-
var foldDigest = (value) =>
|
|
19156
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
19157
|
+
var foldDigest = (value) => createHash4("sha256").update(value).digest("hex");
|
|
19237
19158
|
|
|
19238
19159
|
class FoldOwner {
|
|
19239
19160
|
storage;
|
|
@@ -19540,6 +19461,11 @@ function toolStateContent(state) {
|
|
|
19540
19461
|
`);
|
|
19541
19462
|
}
|
|
19542
19463
|
|
|
19464
|
+
// src/v2/hooks/copied-tag-notation.ts
|
|
19465
|
+
function stripCopiedTagNotation(text) {
|
|
19466
|
+
return text.includes("§") ? stripPersistedAssistantText(text) : text;
|
|
19467
|
+
}
|
|
19468
|
+
|
|
19543
19469
|
// src/v2/hooks/payload.ts
|
|
19544
19470
|
var HEAD_IDS = ["__magic_context_v2_m0__", "__magic_context_v2_m1__"];
|
|
19545
19471
|
var HOST_CONTENT_TYPES = new Set([
|
|
@@ -19559,6 +19485,35 @@ function rejectContentPart(message, part, reason) {
|
|
|
19559
19485
|
else
|
|
19560
19486
|
log(text);
|
|
19561
19487
|
}
|
|
19488
|
+
var emptyTextOmissionLogged = new Set;
|
|
19489
|
+
function placeCacheHint(content, hint) {
|
|
19490
|
+
if (content.length === 0 || content.some((part) => part.cache !== undefined))
|
|
19491
|
+
return;
|
|
19492
|
+
let lastText = content.length - 1;
|
|
19493
|
+
while (lastText >= 0 && content[lastText]?.type !== "text")
|
|
19494
|
+
lastText -= 1;
|
|
19495
|
+
const index = lastText >= 0 ? lastText : content.length - 1;
|
|
19496
|
+
content[index] = { ...content[index], cache: hint };
|
|
19497
|
+
}
|
|
19498
|
+
function removeEmptyTextParts(content, rendered, mayRemove) {
|
|
19499
|
+
let hint;
|
|
19500
|
+
let removed = 0;
|
|
19501
|
+
for (let index = content.length - 1;index >= 0; index -= 1) {
|
|
19502
|
+
const part = content[index];
|
|
19503
|
+
if (part?.type !== "text" || part.text !== "" || !mayRemove(part))
|
|
19504
|
+
continue;
|
|
19505
|
+
if (hint === undefined)
|
|
19506
|
+
hint = part.cache;
|
|
19507
|
+
content.splice(index, 1);
|
|
19508
|
+
removed += 1;
|
|
19509
|
+
}
|
|
19510
|
+
if (hint !== undefined) {
|
|
19511
|
+
const target = content.length > 0 ? content : rendered.at(-1)?.content;
|
|
19512
|
+
if (target)
|
|
19513
|
+
placeCacheHint(target, hint);
|
|
19514
|
+
}
|
|
19515
|
+
return removed;
|
|
19516
|
+
}
|
|
19562
19517
|
function isHostInstance(value) {
|
|
19563
19518
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
19564
19519
|
return false;
|
|
@@ -19621,12 +19576,14 @@ function contentValueAttachments(value) {
|
|
|
19621
19576
|
...typeof item.name === "string" ? { filename: item.name } : {}
|
|
19622
19577
|
}));
|
|
19623
19578
|
}
|
|
19624
|
-
function rebuildFileContent(value, output) {
|
|
19579
|
+
function rebuildFileContent(value, output, attachments) {
|
|
19625
19580
|
if (isDroppedToolOutput(output))
|
|
19626
19581
|
return { type: "text", value: output };
|
|
19627
19582
|
const rebuilt = [];
|
|
19628
19583
|
let placed = false;
|
|
19629
19584
|
for (const item of value) {
|
|
19585
|
+
if (item?.type === "file" && Array.isArray(attachments) && !attachments.some((attachment) => attachment?.url === item.uri && attachment?.mime === item.mime))
|
|
19586
|
+
continue;
|
|
19630
19587
|
if (item?.type !== "text") {
|
|
19631
19588
|
rebuilt.push(item);
|
|
19632
19589
|
continue;
|
|
@@ -19727,6 +19684,8 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19727
19684
|
if (paired.has(content))
|
|
19728
19685
|
continue;
|
|
19729
19686
|
const part = callParts.get(content) ?? (content.type === "tool-result" ? nativeTool(undefined, { part: content, message }) : clonePreservingInstances(content));
|
|
19687
|
+
if (message.role === "assistant" && part.type === "text" && typeof part.text === "string")
|
|
19688
|
+
part.text = stripCopiedTagNotation(part.text);
|
|
19730
19689
|
if (message.id && admittedIDs.has(message.id))
|
|
19731
19690
|
part.synthetic = true;
|
|
19732
19691
|
parts.push(part);
|
|
@@ -19766,12 +19725,17 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19766
19725
|
commit() {
|
|
19767
19726
|
let head = 0;
|
|
19768
19727
|
const rendered = [];
|
|
19728
|
+
const emptyTextGuard = modelAcceptsEmptyContent(draft.model.providerID);
|
|
19729
|
+
const imageOmissions = getEmptyImageParts(messages);
|
|
19730
|
+
let omitted = 0;
|
|
19731
|
+
let emptyTextParts = 0;
|
|
19769
19732
|
for (const message of messages) {
|
|
19770
19733
|
const original = originals.get(message) ?? (typeof message.info.id === "string" ? originalsByID.get(message.info.id) : undefined);
|
|
19771
19734
|
const id = message.info.syntheticHead ? HEAD_IDS[head++] : original?.id;
|
|
19772
19735
|
const content = [];
|
|
19736
|
+
const emptyImages = new Set;
|
|
19773
19737
|
const following = [];
|
|
19774
|
-
for (const candidate of message.parts) {
|
|
19738
|
+
for (const [partIndex, candidate] of message.parts.entries()) {
|
|
19775
19739
|
const part = candidate;
|
|
19776
19740
|
const bridge = bridges.get(part) ?? (part.type === "tool" && typeof part.callID === "string" ? bridgesFor(message)?.get(part.callID) : undefined);
|
|
19777
19741
|
if (!bridge) {
|
|
@@ -19827,7 +19791,10 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19827
19791
|
}
|
|
19828
19792
|
const { synthetic: _synthetic, ...clean } = part;
|
|
19829
19793
|
const original = hostPartTypes.has(clean.type) && !containsHostInstance(clean) ? hostParts.get(contentKey(clean)) : undefined;
|
|
19830
|
-
|
|
19794
|
+
const projected = original ?? clean;
|
|
19795
|
+
if (imageOmissions.get(message.info.id ?? "")?.has(partIndex))
|
|
19796
|
+
emptyImages.add(projected);
|
|
19797
|
+
content.push(projected);
|
|
19831
19798
|
continue;
|
|
19832
19799
|
}
|
|
19833
19800
|
const state = part.state;
|
|
@@ -19859,7 +19826,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19859
19826
|
if (bridge.result && bridge.resultMessage) {
|
|
19860
19827
|
const result = {
|
|
19861
19828
|
...bridge.result,
|
|
19862
|
-
result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output) : {
|
|
19829
|
+
result: state.output === bridge.output ? bridge.result.result : bridge.files && typeof state.output === "string" ? rebuildFileContent(bridge.files, state.output, state.attachments) : {
|
|
19863
19830
|
type: state.status === "error" ? "error" : "text",
|
|
19864
19831
|
value: state.output
|
|
19865
19832
|
}
|
|
@@ -19870,7 +19837,8 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19870
19837
|
following.push({ ...bridge.resultMessage, content: [result] });
|
|
19871
19838
|
}
|
|
19872
19839
|
}
|
|
19873
|
-
|
|
19840
|
+
const guarded = removeEmptyTextParts(content, rendered, (part) => emptyTextGuard || emptyImages.has(part));
|
|
19841
|
+
if (content.length || !original?.content.length && guarded === 0) {
|
|
19874
19842
|
const value = {
|
|
19875
19843
|
...original,
|
|
19876
19844
|
id,
|
|
@@ -19879,9 +19847,16 @@ function adaptPayload(draft, admittedIDs = new Set) {
|
|
|
19879
19847
|
};
|
|
19880
19848
|
const existing = id ? existingHeads.get(id) : undefined;
|
|
19881
19849
|
rendered.push(existing ? Object.assign(existing, { content }) : value);
|
|
19850
|
+
} else if (emptyTextGuard || guarded > 0) {
|
|
19851
|
+
omitted += 1;
|
|
19882
19852
|
}
|
|
19853
|
+
emptyTextParts += guarded;
|
|
19883
19854
|
rendered.push(...following);
|
|
19884
19855
|
}
|
|
19856
|
+
if (omitted + emptyTextParts > 0 && !emptyTextOmissionLogged.has(draft.sessionID)) {
|
|
19857
|
+
emptyTextOmissionLogged.add(draft.sessionID);
|
|
19858
|
+
sessionLog(draft.sessionID, `v2 payload: left out ${omitted} emptied messages and ${emptyTextParts} empty text parts, ${emptyTextGuard ? "because Anthropic rejects an empty text block" : "to replay frozen image omissions"} (logged once per session)`);
|
|
19859
|
+
}
|
|
19885
19860
|
draft.messages.splice(0, draft.messages.length, ...rendered);
|
|
19886
19861
|
}
|
|
19887
19862
|
};
|
|
@@ -21545,13 +21520,28 @@ class DeletedSessionTombstones {
|
|
|
21545
21520
|
}
|
|
21546
21521
|
|
|
21547
21522
|
// src/v2/hooks/generate.ts
|
|
21523
|
+
function generateReplayAnchor(messages) {
|
|
21524
|
+
let index = messages.length - 1;
|
|
21525
|
+
while (index >= 0 && !messages[index]?.id)
|
|
21526
|
+
index--;
|
|
21527
|
+
if (index < 0)
|
|
21528
|
+
return;
|
|
21529
|
+
const id = messages.at(index)?.id;
|
|
21530
|
+
if (!id)
|
|
21531
|
+
return;
|
|
21532
|
+
return { id, tail: clonePreservingInstances(messages.slice(index + 1)) };
|
|
21533
|
+
}
|
|
21534
|
+
|
|
21548
21535
|
class V2GenerateReplay {
|
|
21549
21536
|
prefixes = new Map;
|
|
21550
21537
|
capture(draft, anchor) {
|
|
21551
|
-
if (!anchor)
|
|
21538
|
+
if (!anchor) {
|
|
21539
|
+
this.prefixes.delete(draft.sessionID);
|
|
21540
|
+
sessionLog(draft.sessionID, "generate replay capture skipped: no-anchor");
|
|
21552
21541
|
return;
|
|
21542
|
+
}
|
|
21553
21543
|
this.prefixes.set(draft.sessionID, {
|
|
21554
|
-
anchor,
|
|
21544
|
+
anchor: clonePreservingInstances(anchor),
|
|
21555
21545
|
model: `${draft.model.providerID}/${draft.model.id}`,
|
|
21556
21546
|
agent: draft.agent,
|
|
21557
21547
|
system: clonePreservingInstances(draft.system),
|
|
@@ -21564,12 +21554,23 @@ class V2GenerateReplay {
|
|
|
21564
21554
|
}
|
|
21565
21555
|
apply(draft) {
|
|
21566
21556
|
const prefix = this.prefixes.get(draft.sessionID);
|
|
21567
|
-
|
|
21557
|
+
const skip = (reason) => {
|
|
21558
|
+
sessionLog(draft.sessionID, `generate replay apply skipped: ${reason}`);
|
|
21568
21559
|
return false;
|
|
21569
|
-
|
|
21560
|
+
};
|
|
21561
|
+
if (!prefix)
|
|
21562
|
+
return skip("no-prefix");
|
|
21563
|
+
if (prefix.model !== `${draft.model.providerID}/${draft.model.id}`)
|
|
21564
|
+
return skip("model-mismatch");
|
|
21565
|
+
if (prefix.agent !== draft.agent)
|
|
21566
|
+
return skip("agent-mismatch");
|
|
21567
|
+
const index = draft.messages.findIndex((message) => message.id === prefix.anchor.id);
|
|
21570
21568
|
if (index < 0)
|
|
21571
|
-
return
|
|
21572
|
-
const
|
|
21569
|
+
return skip("anchor-not-found");
|
|
21570
|
+
const end = index + 1 + prefix.anchor.tail.length;
|
|
21571
|
+
if (JSON.stringify(draft.messages.slice(index + 1, end)) !== JSON.stringify(prefix.anchor.tail))
|
|
21572
|
+
return skip("anchor-tail-mismatch");
|
|
21573
|
+
const tail = draft.messages.slice(end);
|
|
21573
21574
|
draft.messages.splice(0, draft.messages.length, ...clonePreservingInstances(prefix.messages), ...tail);
|
|
21574
21575
|
draft.system.splice(0, draft.system.length, ...clonePreservingInstances(prefix.system));
|
|
21575
21576
|
draft.tools = clonePreservingInstances(prefix.tools);
|
|
@@ -21587,9 +21588,9 @@ function hiddenTerminalError(event) {
|
|
|
21587
21588
|
}
|
|
21588
21589
|
|
|
21589
21590
|
// src/v2/hooks/lkg-system.ts
|
|
21590
|
-
import { createHash as
|
|
21591
|
-
function
|
|
21592
|
-
return
|
|
21591
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
21592
|
+
function identity(slot) {
|
|
21593
|
+
return createHash5("sha256").update(JSON.stringify({
|
|
21593
21594
|
capturedAt: slot.capturedAt,
|
|
21594
21595
|
captureSequence: slot.captureSequence,
|
|
21595
21596
|
rowVersion: slot.rowVersion,
|
|
@@ -21604,14 +21605,14 @@ class V2LkgSystemReplay {
|
|
|
21604
21605
|
systems = new BoundedSessionMap(1000);
|
|
21605
21606
|
capture(sessionId, slot, input, served) {
|
|
21606
21607
|
this.systems.set(sessionId, {
|
|
21607
|
-
slot:
|
|
21608
|
+
slot: identity(slot),
|
|
21608
21609
|
input: JSON.stringify(input),
|
|
21609
21610
|
served: structuredClone(served)
|
|
21610
21611
|
});
|
|
21611
21612
|
}
|
|
21612
21613
|
restore(sessionId, slot, input, target) {
|
|
21613
21614
|
const saved = this.systems.get(sessionId);
|
|
21614
|
-
if (!slot || !saved || saved.slot !==
|
|
21615
|
+
if (!slot || !saved || saved.slot !== identity(slot) || saved.input !== JSON.stringify(input))
|
|
21615
21616
|
return false;
|
|
21616
21617
|
target.splice(0, target.length, ...structuredClone(saved.served));
|
|
21617
21618
|
return true;
|
|
@@ -22389,6 +22390,24 @@ function createV2RawMessageProvider(reader, sessionID) {
|
|
|
22389
22390
|
};
|
|
22390
22391
|
}
|
|
22391
22392
|
|
|
22393
|
+
// src/v2/hooks/system-prompt-response.ts
|
|
22394
|
+
function bindV2SystemPromptResponse(sessionId, reader) {
|
|
22395
|
+
const request = currentLkgRequestIdentity(sessionId);
|
|
22396
|
+
if (request?.kind !== "v2" || request.responseAfterSequence === undefined)
|
|
22397
|
+
return;
|
|
22398
|
+
const first = reader.assistantSince(sessionId, request.responseAfterSequence)[0];
|
|
22399
|
+
if (!first)
|
|
22400
|
+
return;
|
|
22401
|
+
const createdAt = first.data.time?.created ?? first.time_created;
|
|
22402
|
+
if (typeof createdAt !== "number")
|
|
22403
|
+
return;
|
|
22404
|
+
bindSystemPromptResponse(sessionId, request, {
|
|
22405
|
+
responseId: first.id,
|
|
22406
|
+
createdAt,
|
|
22407
|
+
modelKey: first.data.model?.providerID && first.data.model?.id ? `${first.data.model.providerID}/${first.data.model.id}` : undefined
|
|
22408
|
+
});
|
|
22409
|
+
}
|
|
22410
|
+
|
|
22392
22411
|
// src/v2/hooks/tools.ts
|
|
22393
22412
|
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
22394
22413
|
|
|
@@ -22534,7 +22553,7 @@ function resolveCtxExpandMode(args, domain) {
|
|
|
22534
22553
|
}
|
|
22535
22554
|
|
|
22536
22555
|
// src/tools/ctx-expand/render.ts
|
|
22537
|
-
import { createHash as
|
|
22556
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
22538
22557
|
function isRecord4(value) {
|
|
22539
22558
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
22540
22559
|
}
|
|
@@ -22758,7 +22777,7 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
|
|
|
22758
22777
|
const index = scoped ? Number(scoped[2]) : 0;
|
|
22759
22778
|
const piText = message.parts.filter((part) => isRecord4(part) && part.type === "text");
|
|
22760
22779
|
const part = message.parts[index];
|
|
22761
|
-
const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" &&
|
|
22780
|
+
const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" && createHash6("sha256").update(part.text).digest("hex") === derived[3]) : [];
|
|
22762
22781
|
const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
|
|
22763
22782
|
if (!selected)
|
|
22764
22783
|
return `Tag ${number}'s original text part is no longer in stored history.`;
|
|
@@ -22766,6 +22785,56 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
|
|
|
22766
22785
|
return renderedPart !== null ? renderedPart : `Tag ${number}'s stored text part has no renderable content (empty or structural-only); the requested content was not recovered.`;
|
|
22767
22786
|
}
|
|
22768
22787
|
|
|
22788
|
+
// src/tools/ctx-expand/search-archive.ts
|
|
22789
|
+
function renderSearchArchive(db, sessionId, start, end, tokenBudget, archiveOnly = false) {
|
|
22790
|
+
return withMessageFtsSessionFilter(db, sessionId, (sessionFirst) => {
|
|
22791
|
+
let rawIds;
|
|
22792
|
+
const rows = db.prepare(sessionFirst ? `SELECT f.message_ordinal AS ordinal, f.message_id AS id, f.role, f.content
|
|
22793
|
+
FROM message_fts_rowid_map AS m
|
|
22794
|
+
JOIN message_history_fts AS f ON f.rowid = m.fts_rowid
|
|
22795
|
+
WHERE m.session_id = ?1 AND m.message_ordinal BETWEEN ?2 AND ?3
|
|
22796
|
+
AND f.session_id = ?1 AND f.message_ordinal BETWEEN ?2 AND ?3
|
|
22797
|
+
ORDER BY m.message_ordinal` : `SELECT message_ordinal AS ordinal, message_id AS id, role, content
|
|
22798
|
+
FROM message_history_fts
|
|
22799
|
+
WHERE session_id = ?1 AND message_ordinal BETWEEN ?2 AND ?3
|
|
22800
|
+
ORDER BY CAST(message_ordinal AS INTEGER)`);
|
|
22801
|
+
const blocks = [];
|
|
22802
|
+
let tokens = 0;
|
|
22803
|
+
let lastOrdinal = start - 1;
|
|
22804
|
+
let truncated = false;
|
|
22805
|
+
for (const row of rows.iterate(sessionId, start, end)) {
|
|
22806
|
+
if (!row.content)
|
|
22807
|
+
continue;
|
|
22808
|
+
if (!archiveOnly) {
|
|
22809
|
+
rawIds ??= readRawSessionMessageIdOrdinalsForRange2(sessionId, start, end);
|
|
22810
|
+
if (rawIds.get(row.id) === row.ordinal)
|
|
22811
|
+
continue;
|
|
22812
|
+
}
|
|
22813
|
+
const block = `[${row.ordinal}] ${row.role === "user" ? "U" : "A"}: ${row.content}`;
|
|
22814
|
+
const cost = estimateTokens(block);
|
|
22815
|
+
if (blocks.length > 0 && tokens + cost > tokenBudget) {
|
|
22816
|
+
truncated = true;
|
|
22817
|
+
break;
|
|
22818
|
+
}
|
|
22819
|
+
blocks.push(block);
|
|
22820
|
+
tokens += cost;
|
|
22821
|
+
lastOrdinal = row.ordinal;
|
|
22822
|
+
}
|
|
22823
|
+
if (blocks.length === 0)
|
|
22824
|
+
return null;
|
|
22825
|
+
const text = [
|
|
22826
|
+
"From the search archive: indexed text only; no surrounding messages or tool output.",
|
|
22827
|
+
"",
|
|
22828
|
+
...blocks
|
|
22829
|
+
];
|
|
22830
|
+
if (truncated) {
|
|
22831
|
+
text.push("", `Truncated at message ${lastOrdinal} (budget: ~${tokenBudget} tokens). Call mmc_expand(start=${lastOrdinal + 1}, end=${end}) for more archived text.`);
|
|
22832
|
+
}
|
|
22833
|
+
return text.join(`
|
|
22834
|
+
`);
|
|
22835
|
+
});
|
|
22836
|
+
}
|
|
22837
|
+
|
|
22769
22838
|
// src/tools/ctx-expand/tools.ts
|
|
22770
22839
|
var ctxExpandArgsShape = {
|
|
22771
22840
|
tag: tool.schema.union([tool.schema.number(), tool.schema.string()]).optional().describe("Tag number from a §N§ tag or a [dropped §N§] placeholder, not a message ordinal. Returns that one item in full. Use alone."),
|
|
@@ -22789,6 +22858,8 @@ function createCtxExpandTool(deps) {
|
|
|
22789
22858
|
message: "number"
|
|
22790
22859
|
});
|
|
22791
22860
|
const sessionId = toolContext.sessionID;
|
|
22861
|
+
if (!await prepareRawSessionOrdinals2(sessionId))
|
|
22862
|
+
return "Session ordinals are warming in the background. Retry mmc_expand shortly; no approximate ordinal was served.";
|
|
22792
22863
|
try {
|
|
22793
22864
|
const mode = resolveCtxExpandMode(args, "positive");
|
|
22794
22865
|
if (mode.kind === "error") {
|
|
@@ -22798,7 +22869,7 @@ function createCtxExpandTool(deps) {
|
|
|
22798
22869
|
return renderItemByTag(deps.db, sessionId, mode.tag);
|
|
22799
22870
|
}
|
|
22800
22871
|
if (mode.kind === "message") {
|
|
22801
|
-
return renderMessageByOrdinal(sessionId, mode.message);
|
|
22872
|
+
return renderSearchArchive(deps.db, sessionId, mode.message, mode.message, CTX_EXPAND_TOKEN_BUDGET) ?? renderMessageByOrdinal(sessionId, mode.message);
|
|
22802
22873
|
}
|
|
22803
22874
|
const { start, end, verbose } = mode;
|
|
22804
22875
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
@@ -22806,6 +22877,9 @@ function createCtxExpandTool(deps) {
|
|
|
22806
22877
|
return `Range ${start}-${end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`;
|
|
22807
22878
|
}
|
|
22808
22879
|
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(end, lastCompartmentEnd) : end;
|
|
22880
|
+
const archived = renderSearchArchive(deps.db, sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
|
|
22881
|
+
if (archived)
|
|
22882
|
+
return archived;
|
|
22809
22883
|
if (verbose) {
|
|
22810
22884
|
const v = renderVerboseRange(sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET, deps.expandTools);
|
|
22811
22885
|
if (!v.text) {
|
|
@@ -23596,9 +23670,15 @@ Stamp: file reads, search results and tool outputs the work ahead no longer need
|
|
|
23596
23670
|
Keep: user messages (never stamp one for its directive), your own conversation text, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may still matter.
|
|
23597
23671
|
|
|
23598
23672
|
Look at each tag before stamping it; never blanket-stamp a range like "1-50". Many small targeted stamps beat one sweep. \`drop\` accepts "3-5", "1,2,9", "1-5,8,12-15".`;
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23673
|
+
function formatCtxReduceReply(stampedCount, selfStampCount = 0) {
|
|
23674
|
+
const parts = [];
|
|
23675
|
+
if (stampedCount > 0) {
|
|
23676
|
+
parts.push(`${stampedCount} tag${stampedCount === 1 ? "" : "s"} stamped.`);
|
|
23677
|
+
}
|
|
23678
|
+
if (selfStampCount > 0) {
|
|
23679
|
+
parts.push(selfStampCount === 1 ? "1 was a ctx_reduce call; leave those alone, they are cleaned up automatically." : `${selfStampCount} were ctx_reduce calls; leave those alone, they are cleaned up automatically.`);
|
|
23680
|
+
}
|
|
23681
|
+
return parts.join(" ");
|
|
23602
23682
|
}
|
|
23603
23683
|
// src/tools/ctx-reduce/tools.ts
|
|
23604
23684
|
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
@@ -23681,22 +23761,10 @@ function createCtxReduceTool(deps) {
|
|
|
23681
23761
|
return `Error: Unknown tag(s) ${formatIds(unknownIds)}. Check available tags in conversation.`;
|
|
23682
23762
|
}
|
|
23683
23763
|
const ctxReduceSelfStampIds = new Set(allTags.filter((tag) => tag.toolName?.toLowerCase() === "mmc_reduce").map((tag) => tag.tagNumber));
|
|
23684
|
-
const
|
|
23764
|
+
const ctxReduceSelfStampCount = new Set(dropIds.filter((id) => ctxReduceSelfStampIds.has(id))).size;
|
|
23685
23765
|
dropIds = dropIds.filter((id) => !ctxReduceSelfStampIds.has(id));
|
|
23686
|
-
let protectedSet;
|
|
23687
|
-
if (deps.protectedSet) {
|
|
23688
|
-
protectedSet = typeof deps.protectedSet === "function" ? deps.protectedSet(sessionId) : deps.protectedSet;
|
|
23689
|
-
} else if (deps.getProtectionWindow) {
|
|
23690
|
-
protectedSet = deps.getProtectionWindow(sessionId).protectedTagNumbers;
|
|
23691
|
-
} else {
|
|
23692
|
-
protectedSet = getProtectionWindowForSession(deps.db, sessionId, deps.floor).protectedTagNumbers;
|
|
23693
|
-
}
|
|
23694
23766
|
const tagStatusMap = new Map(allTags.map((tag) => [tag.tagNumber, tag.status]));
|
|
23695
|
-
|
|
23696
|
-
...protectedSet,
|
|
23697
|
-
...protectedToolTagNumbers(getActiveTagsBySession(deps.db, sessionId), deps.protectedTools)
|
|
23698
|
-
]);
|
|
23699
|
-
const inertWhitespaceTagNumbers = new Set(getInertWhitespaceAssistantTags(deps.db, sessionId).map((tag) => tag.tagNumber));
|
|
23767
|
+
const inertWhitespaceTagNumbers = new Set(getInertWhitespaceAssistantTagsByNumbers(deps.db, sessionId, dropIds).map((tag) => tag.tagNumber));
|
|
23700
23768
|
const inertDropIds = [
|
|
23701
23769
|
...new Set(dropIds.filter((id) => inertWhitespaceTagNumbers.has(id)))
|
|
23702
23770
|
];
|
|
@@ -23712,15 +23780,15 @@ function createCtxReduceTool(deps) {
|
|
|
23712
23780
|
if (conflicts.length > 0) {
|
|
23713
23781
|
return `Error: Conflicting operations — ${conflicts.join("; ")}.`;
|
|
23714
23782
|
}
|
|
23715
|
-
const
|
|
23783
|
+
const stampedCount = new Set(dropIds.filter((id) => !inertWhitespaceTagNumbers.has(id))).size;
|
|
23716
23784
|
dropIds = dropIds.filter((id) => !inertWhitespaceTagNumbers.has(id) && tagStatusMap.get(id) !== "dropped" && pendingMap.get(id) !== "drop");
|
|
23717
|
-
const skippedCount = preFilterDropCount - dropIds.length;
|
|
23718
23785
|
if (dropIds.length === 0) {
|
|
23719
|
-
const
|
|
23720
|
-
if (
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23786
|
+
const reply = formatCtxReduceReply(stampedCount, ctxReduceSelfStampCount);
|
|
23787
|
+
if (reply)
|
|
23788
|
+
return `${reply}${inertNote ? ` ${inertNote}` : ""}`;
|
|
23789
|
+
if (inertNote)
|
|
23790
|
+
return inertNote;
|
|
23791
|
+
return "All requested tags were already queued or processed. No new action is needed.";
|
|
23724
23792
|
}
|
|
23725
23793
|
try {
|
|
23726
23794
|
deps.db.transaction(() => {
|
|
@@ -23735,25 +23803,8 @@ function createCtxReduceTool(deps) {
|
|
|
23735
23803
|
}
|
|
23736
23804
|
const currentInputTokens = deps.getSessionTokens?.(sessionId) ?? getOrCreateSessionMeta(deps.db, sessionId).lastInputTokens;
|
|
23737
23805
|
updateSessionMeta(deps.db, sessionId, { lastNudgeTokens: currentInputTokens });
|
|
23738
|
-
const
|
|
23739
|
-
|
|
23740
|
-
const skippedNote = skippedCount > 0 ? ` ${skippedCount} requested tag${skippedCount === 1 ? " was" : "s were"} already queued and need no action.` : "";
|
|
23741
|
-
let heldSentence = "";
|
|
23742
|
-
if (deferredDropIds.length === 1) {
|
|
23743
|
-
heldSentence = `Held: §${deferredDropIds[0]} is inside the protected working set; it applies once newer work displaces it.`;
|
|
23744
|
-
} else if (deferredDropIds.length > 1) {
|
|
23745
|
-
heldSentence = `Held: ${deferredDropIds.map((id) => `§${id}`).join(", ")} are inside the protected working set; they apply once newer work displaces them.`;
|
|
23746
|
-
}
|
|
23747
|
-
if (immediateDropIds.length > 0 && heldSentence.length > 0) {
|
|
23748
|
-
return `Queued: drop ${formatIds(immediateDropIds)}.${skippedNote}${inertNote ? ` ${inertNote}` : ""} ${heldSentence}${ctxReduceSelfStampNote ? ` ${ctxReduceSelfStampNote}` : ""}`;
|
|
23749
|
-
}
|
|
23750
|
-
if (immediateDropIds.length > 0) {
|
|
23751
|
-
return `Queued: drop ${formatIds(immediateDropIds)}.${skippedNote}${inertNote ? ` ${inertNote}` : ""}${ctxReduceSelfStampNote ? ` ${ctxReduceSelfStampNote}` : ""}`;
|
|
23752
|
-
}
|
|
23753
|
-
if (heldSentence.length > 0) {
|
|
23754
|
-
return `${heldSentence}${skippedNote}${inertNote ? ` ${inertNote}` : ""}${ctxReduceSelfStampNote ? ` ${ctxReduceSelfStampNote}` : ""}`;
|
|
23755
|
-
}
|
|
23756
|
-
return `Queued: drop ${formatIds(dropIds)}.${skippedNote}${inertNote ? ` ${inertNote}` : ""}${ctxReduceSelfStampNote ? ` ${ctxReduceSelfStampNote}` : ""}`;
|
|
23806
|
+
const reply = formatCtxReduceReply(stampedCount, ctxReduceSelfStampCount);
|
|
23807
|
+
return `${reply}${inertNote ? ` ${inertNote}` : ""}`;
|
|
23757
23808
|
}
|
|
23758
23809
|
});
|
|
23759
23810
|
}
|
|
@@ -24126,8 +24177,16 @@ async function applyV2SystemPrompt(systemPrompt, draft) {
|
|
|
24126
24177
|
}
|
|
24127
24178
|
})));
|
|
24128
24179
|
const system = { system: draft.system.map((part) => String(part.text ?? "")) };
|
|
24180
|
+
bindSystemDateOutput(system.system, () => {
|
|
24181
|
+
draft.system.splice(0, draft.system.length, ...system.system.map((text, index) => ({
|
|
24182
|
+
...draft.system[index],
|
|
24183
|
+
type: "text",
|
|
24184
|
+
text
|
|
24185
|
+
})));
|
|
24186
|
+
});
|
|
24129
24187
|
await systemPrompt.handler({
|
|
24130
24188
|
sessionID: draft.sessionID,
|
|
24189
|
+
dateRefreshRequest: draft,
|
|
24131
24190
|
model: { providerID: draft.model.providerID, modelID: draft.model.id }
|
|
24132
24191
|
}, system);
|
|
24133
24192
|
const originals = [...draft.system];
|
|
@@ -24147,6 +24206,7 @@ function createHostSeams(context, readAllForConversion, reconciliationSource, li
|
|
|
24147
24206
|
return {
|
|
24148
24207
|
hostRawMessages: readAllForConversion,
|
|
24149
24208
|
hostMessageReconciliationSource: reconciliationSource,
|
|
24209
|
+
hostPrepareRawOrdinals: async () => true,
|
|
24150
24210
|
hostProtectedTailBoundary: (args) => resolveOpenCodeProtectedTailBoundary({
|
|
24151
24211
|
...args,
|
|
24152
24212
|
cacheNamespace: `opencode2:${args.sessionId}`
|
|
@@ -24445,6 +24505,7 @@ async function registerContext(context) {
|
|
|
24445
24505
|
const sessionDirectories = new Map;
|
|
24446
24506
|
const forkSeedSettled = new Set;
|
|
24447
24507
|
const historyRefreshSessions = new Set;
|
|
24508
|
+
registerSystemDateRefresh(historyRefreshSessions);
|
|
24448
24509
|
const pendingMaterializationSessions = new Set;
|
|
24449
24510
|
const lastHeuristicsTurnId = new Map;
|
|
24450
24511
|
const restoredRows = new RestoredRowCache;
|
|
@@ -24529,6 +24590,11 @@ async function registerContext(context) {
|
|
|
24529
24590
|
try {
|
|
24530
24591
|
const latest = reader.latestAssistant(draft.sessionID);
|
|
24531
24592
|
latestLkgResponseIds.set(draft.sessionID, latest?.id);
|
|
24593
|
+
try {
|
|
24594
|
+
bindV2SystemPromptResponse(draft.sessionID, reader);
|
|
24595
|
+
} catch (error) {
|
|
24596
|
+
sessionLog(draft.sessionID, "v2 response ownership unavailable; keeping system identity pending", error);
|
|
24597
|
+
}
|
|
24532
24598
|
if (latest)
|
|
24533
24599
|
noteLkgProviderResponse({
|
|
24534
24600
|
sessionId: draft.sessionID,
|
|
@@ -24621,6 +24687,10 @@ async function registerContext(context) {
|
|
|
24621
24687
|
nativeFoldReplay?.onEvent(event);
|
|
24622
24688
|
restoredRows.forget(sessionID);
|
|
24623
24689
|
}
|
|
24690
|
+
if (event.type?.startsWith("session.revert.") && db) {
|
|
24691
|
+
const database = db;
|
|
24692
|
+
withoutSqliteTransformPass(() => scheduleClearAndReindex(database, sessionID, pagedRead));
|
|
24693
|
+
}
|
|
24624
24694
|
if (event.type === "session.error" || event.type === "session.execution.failed") {
|
|
24625
24695
|
const error = hiddenTerminalError(event);
|
|
24626
24696
|
if (error !== undefined)
|
|
@@ -24642,7 +24712,9 @@ async function registerContext(context) {
|
|
|
24642
24712
|
continue;
|
|
24643
24713
|
}
|
|
24644
24714
|
if (event.type === "session.deleted") {
|
|
24715
|
+
clearLkgMeasuredRequest(sessionID);
|
|
24645
24716
|
deletedSessions.add(sessionID);
|
|
24717
|
+
transform?.clearSessionLogState(sessionID);
|
|
24646
24718
|
if (db) {
|
|
24647
24719
|
markSessionCleanupPending(db, sessionID);
|
|
24648
24720
|
clearSession(db, sessionID);
|
|
@@ -24657,7 +24729,7 @@ async function registerContext(context) {
|
|
|
24657
24729
|
agents.delete(sessionID);
|
|
24658
24730
|
channel1.delete(sessionID);
|
|
24659
24731
|
historyRefreshSessions.delete(sessionID);
|
|
24660
|
-
pendingMaterializationSessions
|
|
24732
|
+
clearPendingMaterialization(pendingMaterializationSessions, sessionID);
|
|
24661
24733
|
lastHeuristicsTurnId.delete(sessionID);
|
|
24662
24734
|
restoredRows.forget(sessionID);
|
|
24663
24735
|
await nativeFoldReplay?.forget(sessionID);
|
|
@@ -24766,6 +24838,7 @@ async function registerContext(context) {
|
|
|
24766
24838
|
const systemAtEntry = structuredClone(draft.system);
|
|
24767
24839
|
const slotAtEntry = getSlot(draft.sessionID);
|
|
24768
24840
|
const restoreLkgSystem = () => {
|
|
24841
|
+
retirePendingSystemPromptDelivery(draft.sessionID);
|
|
24769
24842
|
if (!lkgSystems.restore(draft.sessionID, getSlot(draft.sessionID), systemAtEntry, draft.system)) {
|
|
24770
24843
|
sessionLog(draft.sessionID, "lkg_system_state_mismatch");
|
|
24771
24844
|
throw new Error("LKG system identity is unavailable or changed");
|
|
@@ -24917,6 +24990,18 @@ async function registerContext(context) {
|
|
|
24917
24990
|
injectionEnabled: config.system_prompt_injection.enabled,
|
|
24918
24991
|
injectionSkipSignatures: config.system_prompt_injection.skip_signatures
|
|
24919
24992
|
});
|
|
24993
|
+
let responseAfterSequence;
|
|
24994
|
+
try {
|
|
24995
|
+
const responseReader = openStoreReader();
|
|
24996
|
+
try {
|
|
24997
|
+
responseAfterSequence = responseReader.latestSequence(draft.sessionID);
|
|
24998
|
+
} finally {
|
|
24999
|
+
responseReader.close();
|
|
25000
|
+
}
|
|
25001
|
+
} catch (error) {
|
|
25002
|
+
sessionLog(draft.sessionID, "v2 response boundary unavailable; no system delivery acknowledgement", error);
|
|
25003
|
+
}
|
|
25004
|
+
beginV2LkgRequest(draft.sessionID, `${draft.model.providerID}/${draft.model.id}`, latestLkgResponseIds.get(draft.sessionID), responseAfterSequence);
|
|
24920
25005
|
const system = await applyV2SystemPrompt(systemPrompt, draft);
|
|
24921
25006
|
noteMaintenanceSystemSnapshot(draft.sessionID, system.join(`
|
|
24922
25007
|
`));
|
|
@@ -24941,6 +25026,16 @@ async function registerContext(context) {
|
|
|
24941
25026
|
await cacheV2SessionDirectory(context.session, draft.sessionID, sessionDirectories);
|
|
24942
25027
|
if (!rawProviders.has(draft.sessionID))
|
|
24943
25028
|
rawProviders.set(draft.sessionID, setBoundedRawMessageProvider2(draft.sessionID, createV2RawMessageProvider(pagedRead, draft.sessionID)));
|
|
25029
|
+
const indexDatabase = db;
|
|
25030
|
+
if (indexDatabase) {
|
|
25031
|
+
withoutSqliteTransformPass(() => {
|
|
25032
|
+
try {
|
|
25033
|
+
scheduleReconciliationCatchup(indexDatabase, draft.sessionID, pagedRead);
|
|
25034
|
+
} catch (error) {
|
|
25035
|
+
sessionLog(draft.sessionID, "message index catchup scheduling failed:", error);
|
|
25036
|
+
}
|
|
25037
|
+
});
|
|
25038
|
+
}
|
|
24944
25039
|
transform ??= createTransform({
|
|
24945
25040
|
cacheTtlConfig: config.cache_ttl,
|
|
24946
25041
|
cacheTtlConfigured: config.cacheTtlConfigured,
|
|
@@ -24951,6 +25046,7 @@ async function registerContext(context) {
|
|
|
24951
25046
|
contextUsageMap: usage,
|
|
24952
25047
|
compactionOff,
|
|
24953
25048
|
storeGeneration: "v2",
|
|
25049
|
+
normalizeRestoredAssistantText: stripCopiedTagNotation,
|
|
24954
25050
|
hostCleanupCompactionMarkers: () => ({
|
|
24955
25051
|
verified: true,
|
|
24956
25052
|
removedLineages: 0,
|
|
@@ -25009,7 +25105,7 @@ async function registerContext(context) {
|
|
|
25009
25105
|
const boundaryRepair = db && !compactionOff ? checkHistoryBoundary(db, reader, draft.sessionID) : undefined;
|
|
25010
25106
|
if (boundaryRepair?.kind === "repaired" || boundaryRepair?.kind === "baseline-reset") {
|
|
25011
25107
|
historyRefreshSessions.add(draft.sessionID);
|
|
25012
|
-
pendingMaterializationSessions
|
|
25108
|
+
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "boundary_repair");
|
|
25013
25109
|
}
|
|
25014
25110
|
const incoming = cut && draft.messages.find((message) => message.id === cut.id);
|
|
25015
25111
|
postFold = cut !== undefined;
|
|
@@ -25027,7 +25123,7 @@ async function registerContext(context) {
|
|
|
25027
25123
|
}
|
|
25028
25124
|
if (nativeRestored && nativeFoldReplay?.sourceChanged(draft.sessionID)) {
|
|
25029
25125
|
historyRefreshSessions.add(draft.sessionID);
|
|
25030
|
-
pendingMaterializationSessions
|
|
25126
|
+
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "host_history_change");
|
|
25031
25127
|
}
|
|
25032
25128
|
if (cut && incoming && nativeRestored) {
|
|
25033
25129
|
const present = new Set(draft.messages.flatMap((message) => message.id ? [message.id] : []));
|
|
@@ -25045,7 +25141,7 @@ async function registerContext(context) {
|
|
|
25045
25141
|
onHard: (reason) => {
|
|
25046
25142
|
log(`[magic-context] HARD reason=${reason} session=${draft.sessionID}`);
|
|
25047
25143
|
materialize(draft);
|
|
25048
|
-
pendingMaterializationSessions
|
|
25144
|
+
requestPendingMaterialization(pendingMaterializationSessions, draft.sessionID, "host_compaction");
|
|
25049
25145
|
}
|
|
25050
25146
|
});
|
|
25051
25147
|
checkpoint = structuredClone(identity.rendered ?? incoming);
|
|
@@ -25072,7 +25168,7 @@ async function registerContext(context) {
|
|
|
25072
25168
|
}
|
|
25073
25169
|
}
|
|
25074
25170
|
const mapped = adaptPayload(draft, admitted);
|
|
25075
|
-
|
|
25171
|
+
bindSystemDateRequestIdentity(mapped, draft);
|
|
25076
25172
|
await transform({}, mapped);
|
|
25077
25173
|
mapped.commit();
|
|
25078
25174
|
if (db) {
|
|
@@ -25235,10 +25331,12 @@ ${baseline}
|
|
|
25235
25331
|
throw new V2ContextRefusal(STORAGE_BUSY_MESSAGE, { cause: refusal });
|
|
25236
25332
|
}
|
|
25237
25333
|
}
|
|
25238
|
-
const anchor = draft.messages
|
|
25334
|
+
const anchor = generateReplayAnchor(draft.messages);
|
|
25239
25335
|
await runManagedContext(draft);
|
|
25240
|
-
if (!compactionOff
|
|
25336
|
+
if (!compactionOff)
|
|
25241
25337
|
generateReplay.capture(draft, anchor);
|
|
25338
|
+
else
|
|
25339
|
+
sessionLog(draft.sessionID, "generate replay capture skipped: compaction-disabled");
|
|
25242
25340
|
}));
|
|
25243
25341
|
await context.session.hook("generate", async (draft) => {
|
|
25244
25342
|
if (!compactionOff && !deletedSessions.has(draft.sessionID))
|