@cortexkit/opencode-magic-context 0.49.5 → 0.49.7
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/auto-search-worker.js +10 -7
- package/dist/{compaction-marker-candidates-dd638ypn.js → compaction-marker-candidates-a0edbqrr.js} +2 -2
- package/dist/compaction-marker-candidates-worker.js +2 -2
- package/dist/{conflict-warning-hook-ae8nmv7c.js → conflict-warning-hook-myk5hbt9.js} +5 -5
- package/dist/{context-yg023c5r.js → context-ffr7e0g7.js} +46 -34
- package/dist/{embedding-backfill-aj488s8x.js → embedding-backfill-re16xncd.js} +6 -6
- package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +6 -3
- package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +7 -1
- package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -2
- package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/primer-seed.d.ts +2 -0
- package/dist/features/magic-context/dreamer/primer-seed.d.ts.map +1 -1
- package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -2
- package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-persisted.d.ts +10 -3
- package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
- package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
- package/dist/features/magic-context/storage-replay-document.d.ts +4 -0
- package/dist/features/magic-context/storage-replay-document.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/heuristic-cleanup.d.ts.map +1 -1
- package/dist/hooks/magic-context/history-boundary-repair.d.ts.map +1 -1
- package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
- package/dist/hooks/magic-context/note-nudger.d.ts +5 -3
- package/dist/hooks/magic-context/note-nudger.d.ts.map +1 -1
- package/dist/hooks/magic-context/postprocess-read-cache.d.ts.map +1 -1
- package/dist/hooks/magic-context/read-session-chunk.d.ts +7 -0
- package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
- package/dist/hooks/magic-context/replay-committed-drops.d.ts +9 -0
- package/dist/hooks/magic-context/replay-committed-drops.d.ts.map +1 -0
- package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts +2 -2
- package/dist/hooks/magic-context/rust-lkg-freeze-registry.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-mode-transform.d.ts +3 -0
- package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
- package/dist/hooks/magic-context/rust-served-raw.d.ts +29 -0
- package/dist/hooks/magic-context/rust-served-raw.d.ts.map +1 -0
- package/dist/hooks/magic-context/strip-content.d.ts +23 -24
- package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
- package/dist/hooks/magic-context/tag-messages.d.ts +2 -0
- package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/{index-m4p77myp.js → index-0gyq3djm.js} +1 -1
- package/dist/{index-jpm52v9x.js → index-37q80veb.js} +1 -1
- package/dist/{index-znzgze2v.js → index-4btknbqh.js} +9 -8
- package/dist/{index-v4bqjy56.js → index-5tbvdff4.js} +59 -28
- package/dist/{index-7jzrrxap.js → index-9yyqq3mm.js} +1 -1
- package/dist/{index-qvr78ej6.js → index-a8acx4gc.js} +2 -2
- package/dist/{index-gcdb3rqw.js → index-ax2jhztn.js} +1 -1
- package/dist/{index-2mqps3c1.js → index-ebnngykq.js} +145 -94
- package/dist/{index-41gqa557.js → index-g8qbdb03.js} +1 -1
- package/dist/{index-fst3t0d9.js → index-j58gqrn2.js} +65 -65
- package/dist/{index-xfbfrngb.js → index-j5hce1ab.js} +2 -2
- package/dist/{index-kb9nn0a0.js → index-j8epsc0g.js} +35 -14
- package/dist/{index-7zg9dvx0.js → index-n5a170gs.js} +227 -38
- package/dist/{index-fjtgekd4.js → index-n7kwfw2r.js} +4 -4
- package/dist/{index-dd18gej8.js → index-rwmpkss5.js} +3 -3
- package/dist/{index-7w18gg78.js → index-rzmjkdd6.js} +1 -1
- package/dist/{index-c0b01zrc.js → index-sf94at64.js} +3 -3
- package/dist/{index-yxawqmdd.js → index-sh91t19a.js} +1 -1
- package/dist/{index-x3y1np1h.js → index-tagss15p.js} +857 -125
- package/dist/{index-yqps2zsv.js → index-tmtty2x5.js} +1 -1
- package/dist/{index-bhk710rw.js → index-vt4sf4ep.js} +1 -1
- package/dist/{index-6m7rdv7y.js → index-w4mw92w3.js} +1 -1
- package/dist/{index-7ndnvw7a.js → index-w6bd03dc.js} +1 -1
- package/dist/{index-p2hs3rps.js → index-w6vr754t.js} +4 -4
- package/dist/{index-3wckxwfp.js → index-wq16ahsn.js} +5 -5
- package/dist/index.js +36 -36
- package/dist/{message-index-bounded-pv6ct15d.js → message-index-bounded-04rycpx4.js} +9 -9
- package/dist/{message-index-jqa7qd0s.js → message-index-rqtse28y.js} +9 -9
- package/dist/{message-time-backfill-8x06r9kx.js → message-time-backfill-a5ytnp53.js} +1 -1
- package/dist/migration-worker.js +6 -6
- package/dist/plugin/messages-transform.d.ts.map +1 -1
- package/dist/{project-embedding-registry-fcmszatg.js → project-embedding-registry-k0sd9k7v.js} +5 -5
- package/dist/raw-ordinal-warmup-worker.js +17 -15
- package/dist/{read-session-chunk-cwgjwjd0.js → read-session-chunk-h1btx938.js} +7 -5
- package/dist/{read-session-raw-z38cn0as.js → read-session-raw-vdf4wh78.js} +2 -2
- package/dist/{recomp-orchestrator-xw9wt5bm.js → recomp-orchestrator-trcgmm23.js} +20 -20
- package/dist/{search-v1t47s2q.js → search-3rbdx6hw.js} +16 -16
- package/dist/{send-session-notification-yp9m5g4p.js → send-session-notification-2tp44tfa.js} +4 -4
- package/dist/shared/processed-image-eligibility.d.ts +22 -0
- package/dist/shared/processed-image-eligibility.d.ts.map +1 -0
- 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 +1 -1
- package/dist/shared/sqlite.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/{sqlite-mhjkerzq.js → sqlite-j3tvg8r0.js} +1 -1
- package/dist/{storage-memory-07fx57k6.js → storage-memory-8168bgef.js} +2 -2
- package/dist/{storage-tags-0ssbmzg9.js → storage-tags-61z5j2f9.js} +2 -2
- 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/{transform-postprocess-phase-ttra554y.js → transform-postprocess-phase-7qts7h54.js} +20 -20
- package/dist/v2/auto-search-worker.js +10 -7
- package/dist/v2/{compaction-marker-candidates-1s21e2fz.js → compaction-marker-candidates-6nypjkpf.js} +2 -2
- package/dist/v2/compaction-marker-candidates-worker.js +2 -2
- package/dist/v2/{context-6en6a8ar.js → context-xq4rtywr.js} +1019 -233
- package/dist/v2/{embedding-backfill-9hbkfvnz.js → embedding-backfill-xd9ygzgd.js} +6 -6
- package/dist/v2/hooks/payload.d.ts.map +1 -1
- package/dist/v2/{message-index-h8ssgq3q.js → message-index-8e5z2xx8.js} +9 -9
- package/dist/v2/{message-index-bounded-c0810p5w.js → message-index-bounded-5vh1h2g7.js} +9 -9
- package/dist/v2/{message-time-backfill-cje68egj.js → message-time-backfill-2z365239.js} +1 -1
- package/dist/v2/migration-worker.js +6 -6
- package/dist/v2/{project-embedding-registry-42th7k1z.js → project-embedding-registry-b77awytr.js} +5 -5
- package/dist/v2/raw-ordinal-warmup-worker.js +17 -15
- package/dist/v2/{read-session-chunk-n86v9xfg.js → read-session-chunk-4sat83cx.js} +7 -5
- package/dist/v2/{read-session-raw-3b3ehga4.js → read-session-raw-a3hw9jsp.js} +2 -2
- package/dist/v2/{recomp-orchestrator-krvsbnds.js → recomp-orchestrator-n11zv1f1.js} +19 -19
- package/dist/v2/{search-048v8y02.js → search-mvgqtkkz.js} +16 -16
- package/dist/v2/{send-session-notification-a4h2azxa.js → send-session-notification-ppgc8qdz.js} +4 -4
- package/dist/v2/{server-cvgn49tr.js → server-1rfgbjfn.js} +1 -1
- package/dist/v2/{server-3bc6k4k4.js → server-7srtwsa4.js} +5 -5
- package/dist/v2/{server-7jzrrxap.js → server-9yyqq3mm.js} +1 -1
- package/dist/v2/{server-2htmbqbv.js → server-brhj8qtd.js} +1 -1
- package/dist/v2/{server-3dqjhchy.js → server-dd0nja67.js} +1 -1
- package/dist/v2/{server-8wcf79fe.js → server-fpqe39as.js} +1 -1
- package/dist/v2/{server-cjz51jm2.js → server-fw31krgq.js} +3 -3
- package/dist/v2/{server-4n2tknpc.js → server-gtv9wbhq.js} +227 -38
- package/dist/v2/{server-8pqnnmf9.js → server-hcvcxzx7.js} +2 -2
- package/dist/v2/{server-kb9nn0a0.js → server-j8epsc0g.js} +35 -14
- package/dist/v2/{server-rygvffsf.js → server-jdwd03ep.js} +4 -4
- package/dist/v2/{server-q6j5dasr.js → server-kdrezdy0.js} +1 -1
- package/dist/v2/{server-e2v4m8xe.js → server-mv1w7t6z.js} +61 -30
- package/dist/v2/{server-hetyb88z.js → server-nfan6zb6.js} +65 -65
- package/dist/v2/{server-4enr7s6x.js → server-qcw43339.js} +1 -1
- package/dist/v2/{server-5zrpr764.js → server-sy4b1sra.js} +1 -1
- package/dist/v2/{server-9a6v0wth.js → server-v4fwha43.js} +9 -8
- package/dist/v2/{server-pcygfdbs.js → server-w3zeywp1.js} +1 -1
- package/dist/v2/{server-czb2rkpk.js → server-wkdgjjch.js} +1 -1
- package/dist/v2/{server-9290a1mb.js → server-x08d1xf3.js} +1 -1
- package/dist/v2/server.js +4 -4
- package/dist/v2/{sqlite-mhjkerzq.js → sqlite-j3tvg8r0.js} +1 -1
- package/dist/v2/{storage-memory-07fx57k6.js → storage-memory-8168bgef.js} +2 -2
- package/dist/v2/{storage-tags-3a4cavqb.js → storage-tags-j2fzq3sw.js} +2 -2
- package/dist/v2/{wrapup-orchestrator-r2v7kgy3.js → wrapup-orchestrator-s92ebfzv.js} +19 -19
- package/dist/{wrapup-orchestrator-z7agncp8.js → wrapup-orchestrator-df61jmz9.js} +21 -21
- package/package.json +3 -3
- 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/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 +140 -0
- package/src/shared/sqlite-pass-scope.test.ts +4 -4
- package/src/shared/sqlite-writer-diagnostics.test.ts +31 -0
- package/src/shared/sqlite.ts +64 -23
- package/src/shared/tag-transcript.ts +118 -0
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
SqliteAcquisitionBusyError2,
|
|
39
39
|
withAsyncPrivilegedWriter2,
|
|
40
40
|
indexCoordinationInput2
|
|
41
|
-
} from "./index-
|
|
41
|
+
} from "./index-j8epsc0g.js";
|
|
42
42
|
import {
|
|
43
43
|
shouldSkipHomeProjectMemory,
|
|
44
44
|
ProjectIdentityError,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
storedPathBelongsToIdentity,
|
|
54
54
|
beginBootQuietPeriod,
|
|
55
55
|
scheduleAfterBootQuiet
|
|
56
|
-
} from "./index-
|
|
56
|
+
} from "./index-g8qbdb03.js";
|
|
57
57
|
import {
|
|
58
58
|
recordSessionProjectIdentity,
|
|
59
59
|
hasRecordedSessionProjectIdentity,
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
drainCommitBacklogForProject2,
|
|
81
81
|
embedSessionCompartmentChunks2,
|
|
82
82
|
getEmbeddingCoverageStatus2
|
|
83
|
-
} from "./index-
|
|
83
|
+
} from "./index-sf94at64.js";
|
|
84
84
|
import {
|
|
85
85
|
hasTrustedAbsoluteWall,
|
|
86
86
|
applyProvenInputFloor,
|
|
@@ -110,6 +110,7 @@ import {
|
|
|
110
110
|
import {
|
|
111
111
|
protectedToolTokenCount,
|
|
112
112
|
peelLeadingMcTagNotation,
|
|
113
|
+
isThinkingPart,
|
|
113
114
|
isRecord,
|
|
114
115
|
contentTagOwnerMessageId,
|
|
115
116
|
normalizeTodoStateJson,
|
|
@@ -142,9 +143,10 @@ import {
|
|
|
142
143
|
getDroppedTagsByNumbers2,
|
|
143
144
|
getMaxDroppedTagNumber2,
|
|
144
145
|
getTagById2
|
|
145
|
-
} from "./index-
|
|
146
|
+
} from "./index-tmtty2x5.js";
|
|
146
147
|
import {
|
|
147
|
-
observeTemporalDecisions
|
|
148
|
+
observeTemporalDecisions,
|
|
149
|
+
stableStringify
|
|
148
150
|
} from "./index-1bt88epp.js";
|
|
149
151
|
import {
|
|
150
152
|
withContentLanguageDirective,
|
|
@@ -164,7 +166,7 @@ import {
|
|
|
164
166
|
extractInMemoryMessageViews2,
|
|
165
167
|
buildInMemoryTailRawMessages2,
|
|
166
168
|
runSessionWarmupWorker
|
|
167
|
-
} from "./index-
|
|
169
|
+
} from "./index-37q80veb.js";
|
|
168
170
|
import {
|
|
169
171
|
openCodeDbExists,
|
|
170
172
|
withReadOnlySessionDb,
|
|
@@ -172,10 +174,11 @@ import {
|
|
|
172
174
|
latestPersistedMessageForRecovery,
|
|
173
175
|
latestRealUserTurnIdFromOpenCodeDb,
|
|
174
176
|
findLastAssistantModelFromOpenCodeDb
|
|
175
|
-
} from "./index-
|
|
177
|
+
} from "./index-a8acx4gc.js";
|
|
176
178
|
import {
|
|
177
179
|
expandToolPart,
|
|
178
180
|
estimateTrueRawMessageTokens,
|
|
181
|
+
isTextPart,
|
|
179
182
|
toolPartHasUserAnswer,
|
|
180
183
|
DreamTokenBudgetExceeded,
|
|
181
184
|
isEditTool,
|
|
@@ -185,6 +188,8 @@ import {
|
|
|
185
188
|
sessionDecisionCalibration,
|
|
186
189
|
getProtectionWindowForSession,
|
|
187
190
|
ensureSessionMetaRow,
|
|
191
|
+
withReplayEnvelopeSnapshot,
|
|
192
|
+
invalidateReplayEnvelopeSnapshot,
|
|
188
193
|
isRustMarkerAdmissionFenced,
|
|
189
194
|
setRustMarkerAdmissionFence,
|
|
190
195
|
readReplayEnvelope,
|
|
@@ -268,11 +273,16 @@ import {
|
|
|
268
273
|
createFinalWireUsageTracker,
|
|
269
274
|
estimateFinalWireInputTokens,
|
|
270
275
|
estimateAppendedWireTokens,
|
|
276
|
+
partHasCompletedResult,
|
|
277
|
+
extractToolCallObservation,
|
|
278
|
+
ToolMutationBatch,
|
|
279
|
+
createToolDropTarget,
|
|
271
280
|
setRawMessageProvider2,
|
|
272
281
|
cleanUserText2,
|
|
273
282
|
withRawSessionMessageCache2,
|
|
274
283
|
readRawSessionMessages2,
|
|
275
284
|
visitRawSessionMessages2,
|
|
285
|
+
visitRawSessionMessagesAsync2,
|
|
276
286
|
prepareRawSessionOrdinals2,
|
|
277
287
|
primeTailRawMessageCache2,
|
|
278
288
|
primeInMemoryTailRawMessageCache2,
|
|
@@ -284,7 +294,7 @@ import {
|
|
|
284
294
|
readRawSessionMessageById2,
|
|
285
295
|
readSessionChunk2,
|
|
286
296
|
readRawSessionSeedTail2
|
|
287
|
-
} from "./index-
|
|
297
|
+
} from "./index-n5a170gs.js";
|
|
288
298
|
import {
|
|
289
299
|
getMeasuredToolDefinitionTokens
|
|
290
300
|
} from "./index-h2wc01qk.js";
|
|
@@ -315,20 +325,20 @@ import {
|
|
|
315
325
|
runSqliteOptimize,
|
|
316
326
|
openDatabase,
|
|
317
327
|
openCurrentDatabase
|
|
318
|
-
} from "./index-
|
|
328
|
+
} from "./index-4btknbqh.js";
|
|
319
329
|
import {
|
|
320
330
|
registerOwnRpcServerInstance,
|
|
321
331
|
rpcPortDir,
|
|
322
332
|
rpcPortFilePath,
|
|
323
333
|
parseRpcPortFile,
|
|
324
334
|
inspectProcessesAsync
|
|
325
|
-
} from "./index-
|
|
335
|
+
} from "./index-w4mw92w3.js";
|
|
326
336
|
import {
|
|
327
337
|
configureContextDatabasePragmas2
|
|
328
338
|
} from "./index-fb3zxn06.js";
|
|
329
339
|
import {
|
|
330
340
|
canonicalProjectDirectory
|
|
331
|
-
} from "./index-
|
|
341
|
+
} from "./index-rzmjkdd6.js";
|
|
332
342
|
import {
|
|
333
343
|
unescapeXml,
|
|
334
344
|
resolveWorkspaceShareCategories,
|
|
@@ -337,7 +347,7 @@ import {
|
|
|
337
347
|
resolveStoredPathWorkspaceIdentity,
|
|
338
348
|
storedPathBelongsToWorkspace,
|
|
339
349
|
computeWorkspaceEpochFingerprint
|
|
340
|
-
} from "./index-
|
|
350
|
+
} from "./index-j5hce1ab.js";
|
|
341
351
|
import {
|
|
342
352
|
V2_MEMORY_CATEGORIES,
|
|
343
353
|
CATEGORY_PRIORITY
|
|
@@ -394,6 +404,8 @@ import {
|
|
|
394
404
|
resolveLkgModelKeys,
|
|
395
405
|
createLkgEntryProjector,
|
|
396
406
|
captureLkgSlot,
|
|
407
|
+
validateAnthropicReasoningRuns,
|
|
408
|
+
validateLkgSeam,
|
|
397
409
|
replayLkg,
|
|
398
410
|
coldStartRawServedIndex,
|
|
399
411
|
coldStartUncapturedReplay,
|
|
@@ -509,7 +521,7 @@ import {
|
|
|
509
521
|
snapRangeToCompartments,
|
|
510
522
|
getActiveCompartmentRun,
|
|
511
523
|
startCompartmentAgent
|
|
512
|
-
} from "./index-
|
|
524
|
+
} from "./index-5tbvdff4.js";
|
|
513
525
|
import {
|
|
514
526
|
SubcClient,
|
|
515
527
|
connectionFileExists,
|
|
@@ -538,7 +550,7 @@ import {
|
|
|
538
550
|
indexSingleMessage2,
|
|
539
551
|
indexMessagesAfterOrdinal2,
|
|
540
552
|
sweepOrphanedOpenCodeMessageIndexes2
|
|
541
|
-
} from "./index-
|
|
553
|
+
} from "./index-wq16ahsn.js";
|
|
542
554
|
import {
|
|
543
555
|
renderUserFacingFailure,
|
|
544
556
|
userFacingFailureCode,
|
|
@@ -582,7 +594,7 @@ import {
|
|
|
582
594
|
readGitFileChangeTimesSince,
|
|
583
595
|
verificationFileExists,
|
|
584
596
|
normalizeVerificationFiles
|
|
585
|
-
} from "./index-
|
|
597
|
+
} from "./index-n7kwfw2r.js";
|
|
586
598
|
import {
|
|
587
599
|
registerNotificationSink2,
|
|
588
600
|
pushNotification2,
|
|
@@ -600,7 +612,7 @@ import {
|
|
|
600
612
|
} from "./index-4dhv7mqz.js";
|
|
601
613
|
import {
|
|
602
614
|
cosineSimilarity
|
|
603
|
-
} from "./index-
|
|
615
|
+
} from "./index-w6bd03dc.js";
|
|
604
616
|
import {
|
|
605
617
|
computeCueContentHash,
|
|
606
618
|
hasMuralCueColumns,
|
|
@@ -625,7 +637,7 @@ import {
|
|
|
625
637
|
mergeMemoryStats2,
|
|
626
638
|
archiveMemory2,
|
|
627
639
|
getMemoryCountsByStatus2
|
|
628
|
-
} from "./index-
|
|
640
|
+
} from "./index-9yyqq3mm.js";
|
|
629
641
|
import {
|
|
630
642
|
renderSingleStoreMigrationRequiredRefusal,
|
|
631
643
|
SingleStoreMigrationRequiredError,
|
|
@@ -641,23 +653,25 @@ import {
|
|
|
641
653
|
SubcModuleTransport,
|
|
642
654
|
indexCommitsForProject,
|
|
643
655
|
embedUnembeddedCommits,
|
|
656
|
+
withMessageFtsSessionFilter,
|
|
644
657
|
createUnifiedSearchDiagnostics2,
|
|
645
658
|
parseIdShapedQuery2,
|
|
646
659
|
resolveMemoriesByIdsForSearch2,
|
|
647
660
|
unifiedSearch2,
|
|
648
661
|
formatSearchResults2
|
|
649
|
-
} from "./index-
|
|
662
|
+
} from "./index-j58gqrn2.js";
|
|
650
663
|
import {
|
|
651
664
|
flushIgnoredMessages2,
|
|
652
665
|
clearIgnoredMessages2,
|
|
653
666
|
observeIgnoredNotificationEvent2,
|
|
654
667
|
sendStatusNotification2
|
|
655
|
-
} from "./index-
|
|
668
|
+
} from "./index-vt4sf4ep.js";
|
|
656
669
|
import {
|
|
657
670
|
setRecompStarting2,
|
|
658
671
|
setRecompTerminal2
|
|
659
|
-
} from "./index-
|
|
672
|
+
} from "./index-rwmpkss5.js";
|
|
660
673
|
import {
|
|
674
|
+
makeToolCompositeKey,
|
|
661
675
|
searchMessageHistoryOffThread,
|
|
662
676
|
findSessionId,
|
|
663
677
|
findLastUserMessageId,
|
|
@@ -706,7 +720,7 @@ import {
|
|
|
706
720
|
abortSessionFailClosed2,
|
|
707
721
|
evaluateEmergencyFailClosed2,
|
|
708
722
|
runPostTransformPhase2
|
|
709
|
-
} from "./index-
|
|
723
|
+
} from "./index-ebnngykq.js";
|
|
710
724
|
import {
|
|
711
725
|
ANNOUNCEMENT_VERSION2,
|
|
712
726
|
ANNOUNCEMENT_FEATURES2,
|
|
@@ -2797,6 +2811,25 @@ async function runHiddenSingleShotPrompt(args) {
|
|
|
2797
2811
|
});
|
|
2798
2812
|
promptSettled = true;
|
|
2799
2813
|
return { validated: run.validated, completion: run.output, childSessionId: handle.id };
|
|
2814
|
+
} catch (error) {
|
|
2815
|
+
if (args.onFailureOutput) {
|
|
2816
|
+
let timer;
|
|
2817
|
+
try {
|
|
2818
|
+
const completion = await Promise.race([
|
|
2819
|
+
args.executor.collect(handle, 200),
|
|
2820
|
+
new Promise((resolve) => {
|
|
2821
|
+
timer = setTimeout(() => resolve(null), 5000);
|
|
2822
|
+
})
|
|
2823
|
+
]);
|
|
2824
|
+
if (completion)
|
|
2825
|
+
args.onFailureOutput(completion);
|
|
2826
|
+
} catch (readError) {
|
|
2827
|
+
log2(`${args.callContext}: failed to collect interrupted output: ${String(readError)}`);
|
|
2828
|
+
} finally {
|
|
2829
|
+
clearTimeout(timer);
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
throw error;
|
|
2800
2833
|
} finally {
|
|
2801
2834
|
await args.executor.close(handle, {
|
|
2802
2835
|
promptSettled,
|
|
@@ -6626,31 +6659,33 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
6626
6659
|
import { createHash as createHash5 } from "node:crypto";
|
|
6627
6660
|
|
|
6628
6661
|
// src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
6662
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
6629
6663
|
import { existsSync as existsSync4, statSync } from "node:fs";
|
|
6630
6664
|
import path3 from "node:path";
|
|
6665
|
+
import { promisify as promisify2 } from "node:util";
|
|
6631
6666
|
var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
|
|
6632
6667
|
|
|
6633
6668
|
A memory's BACKING FILES are the file(s) whose code the memory makes a claim about — the files you would open to check whether the memory is accurate. You do NOT judge accuracy, rewrite, or remove anything. You only LOCATE backing files.
|
|
6634
6669
|
|
|
6635
|
-
Tools (read-only): read, grep, glob.
|
|
6670
|
+
Tools (read-only): read, grep, glob. Use at most 3 tool calls per memory, including searches and reads. Never read the same file twice in a batch; reuse what you already learned. Never repeat an identical search or use broad searches such as "fn " or ".*". Request one useful line range, not repeated slices. Each memory may come with "Likely files" from paths it names or a literal identifier search, confirmed to exist — confirm those FIRST (cheap) instead of searching. Use search/grep to FIND code only when no likely files are given. Do not guess — confirm a file exists and genuinely backs the memory before listing it. You are locating code, not exhaustively verifying the claim. If the call budget runs out before you can decide, leave that id unmapped and move on; uncertainty is not evidence of file-independence.
|
|
6636
6671
|
|
|
6637
6672
|
For each memory decide ONE of:
|
|
6638
|
-
- Backing files found → the
|
|
6673
|
+
- Backing files found → the specific repo-relative paths whose code the memory is about; do not chase every caller or related implementation.
|
|
6639
6674
|
- File-independent → the memory describes EXTERNAL behavior (a provider / API / platform / protocol limit, e.g. "Anthropic returns 400 on empty content"), or a pure process / workflow / philosophy rule, with NO specific local file that backs it. A BEHAVIORAL claim (when to act, how to work, who decides, or tool-usage discipline) is file-independent even when it cites file paths or commands as examples: a named file is not the file backing the rule.
|
|
6640
6675
|
|
|
6641
|
-
Output ONE XML manifest
|
|
6676
|
+
Output ONE XML manifest and NOTHING else — no narration, no per-memory commentary, no reasoning. Open <mappings> before investigating. Emit each <memory> element as soon as you decide its mapping, before investigating the next memory, so an interruption cannot lose completed work. Close </mappings> when finished:
|
|
6642
6677
|
<mappings>
|
|
6643
6678
|
<memory id="N" files="path/a.ts,path/b.ts"/>
|
|
6644
6679
|
<memory id="M" independent="true"/>
|
|
6645
6680
|
</mappings>
|
|
6646
6681
|
|
|
6647
6682
|
Rules:
|
|
6648
|
-
- Every input memory id MUST appear exactly once.
|
|
6683
|
+
- Every decided input memory id MUST appear exactly once. Omit uncertain ids rather than inventing backing files or declaring them independent.
|
|
6649
6684
|
- files: repo-relative, comma-separated, no spaces inside a path. Only files that actually exist and genuinely back the memory.
|
|
6650
6685
|
- A BACKING FILE is CODE that implements or handles the claim — not a file that merely mentions it. A path named inside a process directive is an action target or example, not evidence that the file backs the directive. A markdown doc (.md), a PARITY/notes file, or a test that only DESCRIBES an external fact is NOT a backing file. If the only place a memory's fact appears is prose/docs/a test (no code implements or handles it), mark it independent="true".
|
|
6651
6686
|
- Many CONSTRAINTS are HYBRID: "external system does X, and OUR code handles it here." Map those to the HANDLING code (you can verify the handling, even though you can't verify the external behavior). Only mark independent when there is NO local code that implements or handles the fact.
|
|
6652
6687
|
- Prefer the most specific file(s); do not pad with tangential files. Most memories map to one file; some to a few.
|
|
6653
|
-
-
|
|
6688
|
+
- Mark independent="true" only for the file-independent cases above; an investigation that runs out of calls stays unmapped.`;
|
|
6654
6689
|
var MAX_SEED_PATHS_PER_MEMORY = 3;
|
|
6655
6690
|
var PATH_PATTERN = "`?((?:[\\w.-]+\\/)+[\\w.-]+\\.(?:ts|tsx|js|jsx|mjs|cjs|rs|go|py|json|jsonc|sql|toml|sh))`?";
|
|
6656
6691
|
function extractMemoryCandidatePaths(content, repoDir) {
|
|
@@ -6672,10 +6707,65 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
6672
6707
|
}
|
|
6673
6708
|
return [...found];
|
|
6674
6709
|
}
|
|
6710
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
6711
|
+
async function seedIdentifierCandidates(memories, repoDir) {
|
|
6712
|
+
const identifiers = new Map(memories.filter((memory) => memory.candidates.length === 0).map((memory) => [
|
|
6713
|
+
memory.id,
|
|
6714
|
+
[
|
|
6715
|
+
...new Set(memory.content.match(/\b(?:[A-Z][A-Za-z0-9_]{3,}|[a-z][a-z0-9]*[A-Z][A-Za-z0-9_]*|[a-z][a-z0-9]*_[A-Za-z0-9_]{2,})\b/g) ?? [])
|
|
6716
|
+
].slice(0, 3)
|
|
6717
|
+
]));
|
|
6718
|
+
const terms = [...new Set([...identifiers.values()].flat())];
|
|
6719
|
+
if (terms.length === 0)
|
|
6720
|
+
return memories;
|
|
6721
|
+
let stdout;
|
|
6722
|
+
try {
|
|
6723
|
+
const result = await execFileAsync2("git", [
|
|
6724
|
+
"-c",
|
|
6725
|
+
"core.quotePath=false",
|
|
6726
|
+
"grep",
|
|
6727
|
+
"--no-color",
|
|
6728
|
+
"-n",
|
|
6729
|
+
"-I",
|
|
6730
|
+
"-F",
|
|
6731
|
+
...terms.flatMap((term) => ["-e", term]),
|
|
6732
|
+
"--",
|
|
6733
|
+
...["ts", "tsx", "js", "jsx", "mjs", "cjs", "rs", "go", "py", "sql", "sh"].map((extension) => `*.${extension}`)
|
|
6734
|
+
], {
|
|
6735
|
+
cwd: repoDir,
|
|
6736
|
+
encoding: "utf8",
|
|
6737
|
+
timeout: 2000,
|
|
6738
|
+
maxBuffer: 256 * 1024,
|
|
6739
|
+
windowsHide: true,
|
|
6740
|
+
killSignal: "SIGKILL"
|
|
6741
|
+
});
|
|
6742
|
+
stdout = result.stdout;
|
|
6743
|
+
} catch {
|
|
6744
|
+
return memories;
|
|
6745
|
+
}
|
|
6746
|
+
const matches = stdout.split(`
|
|
6747
|
+
`).flatMap((line) => {
|
|
6748
|
+
const match = line.match(/^([^:]+):\d+:(.*)$/);
|
|
6749
|
+
return match ? [{ file: match[1], text: match[2] }] : [];
|
|
6750
|
+
});
|
|
6751
|
+
return memories.map((memory) => {
|
|
6752
|
+
const names = identifiers.get(memory.id);
|
|
6753
|
+
if (!names?.length)
|
|
6754
|
+
return memory;
|
|
6755
|
+
const files = new Map;
|
|
6756
|
+
for (const match of matches) {
|
|
6757
|
+
const score = names.filter((name) => match.text.includes(name)).length;
|
|
6758
|
+
if (score)
|
|
6759
|
+
files.set(match.file, Math.max(files.get(match.file) ?? 0, score));
|
|
6760
|
+
}
|
|
6761
|
+
const candidates = [...files].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_SEED_PATHS_PER_MEMORY).map(([file]) => file);
|
|
6762
|
+
return candidates.length ? { ...memory, candidates } : memory;
|
|
6763
|
+
});
|
|
6764
|
+
}
|
|
6675
6765
|
function buildMapMemoriesPrompt(projectPath, memories) {
|
|
6676
6766
|
const list = memories.map((m) => {
|
|
6677
6767
|
const seed = m.candidates.length ? `
|
|
6678
|
-
Likely files (
|
|
6768
|
+
Likely files (candidate paths, confirmed to exist): ${m.candidates.join(", ")}` : "";
|
|
6679
6769
|
return `[${m.id}] ${m.category}
|
|
6680
6770
|
${m.content}${seed}`;
|
|
6681
6771
|
}).join(`
|
|
@@ -6685,13 +6775,13 @@ ${m.content}${seed}`;
|
|
|
6685
6775
|
|
|
6686
6776
|
Project: ${projectPath}
|
|
6687
6777
|
|
|
6688
|
-
For each memory below, find the repo file(s) it makes a claim about, or mark it file-independent. Behavioral process/workflow directives stay file-independent even when they name files. When "Likely files" are listed, those paths
|
|
6778
|
+
For each memory below, find the repo file(s) it makes a claim about, or mark it file-independent. Behavioral process/workflow directives stay file-independent even when they name files. When "Likely files" are listed, those paths either occur in the memory or match its identifiers in a bounded literal source search — START there only for code claims: confirm each actually backs the claim (a quick read/outline), drop any that don't, add others only if genuinely needed. Search from scratch only when no likely files are given. Use at most 3 tool calls per memory, reuse prior reads, and emit each decided mapping immediately in ONE <mappings> manifest. Leave uncertain ids unmapped and move on.
|
|
6689
6779
|
|
|
6690
6780
|
<memories>
|
|
6691
6781
|
${list}
|
|
6692
6782
|
</memories>`;
|
|
6693
6783
|
}
|
|
6694
|
-
var MEMORY_ELEMENT_PATTERN = "<memory\\b([
|
|
6784
|
+
var MEMORY_ELEMENT_PATTERN = "<memory\\b([^<>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
|
|
6695
6785
|
var NESTED_FILE_PATTERN = "<file\\b([^>]*)\\/?>";
|
|
6696
6786
|
function extractNestedFilePaths(inner) {
|
|
6697
6787
|
const files = [];
|
|
@@ -6749,12 +6839,78 @@ function validateMapMemoriesManifest(text, expectedIds) {
|
|
|
6749
6839
|
assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
|
|
6750
6840
|
return parsed;
|
|
6751
6841
|
}
|
|
6842
|
+
function parsePartialMapMemoriesManifest(text, expectedIds) {
|
|
6843
|
+
const start = text.indexOf("<mappings>");
|
|
6844
|
+
if (start < 0)
|
|
6845
|
+
return [];
|
|
6846
|
+
const entries = new Map;
|
|
6847
|
+
const conflicts = new Set;
|
|
6848
|
+
for (const match of text.slice(start).matchAll(new RegExp(MEMORY_ELEMENT_PATTERN, "gi"))) {
|
|
6849
|
+
try {
|
|
6850
|
+
const entry = parseMapMemoriesManifest(`<mappings>${match[0]}</mappings>`)[0];
|
|
6851
|
+
if (!entry || !expectedIds.has(entry.id) || conflicts.has(entry.id))
|
|
6852
|
+
continue;
|
|
6853
|
+
const previous = entries.get(entry.id);
|
|
6854
|
+
if (previous && JSON.stringify(previous) !== JSON.stringify(entry)) {
|
|
6855
|
+
entries.delete(entry.id);
|
|
6856
|
+
conflicts.add(entry.id);
|
|
6857
|
+
} else {
|
|
6858
|
+
entries.set(entry.id, entry);
|
|
6859
|
+
}
|
|
6860
|
+
} catch {}
|
|
6861
|
+
}
|
|
6862
|
+
return [...entries.values()];
|
|
6863
|
+
}
|
|
6752
6864
|
|
|
6753
6865
|
// src/features/magic-context/dreamer/map-memories.ts
|
|
6754
|
-
var MAP_BATCH_SIZE =
|
|
6866
|
+
var MAP_BATCH_SIZE = 5;
|
|
6755
6867
|
var MAP_BATCH_FLOOR_MS = 240000;
|
|
6756
6868
|
var CONSECUTIVE_TIMEOUT_LIMIT2 = 2;
|
|
6757
6869
|
var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
|
|
6870
|
+
function retryKey(project) {
|
|
6871
|
+
return `map-memories:retry:${project}`;
|
|
6872
|
+
}
|
|
6873
|
+
function readRetries(db, project) {
|
|
6874
|
+
try {
|
|
6875
|
+
const parsed = JSON.parse(getDreamState(db, retryKey(project)) ?? "{}");
|
|
6876
|
+
if (!isRecord(parsed))
|
|
6877
|
+
return {};
|
|
6878
|
+
const retries = {};
|
|
6879
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
6880
|
+
if (isRecord(value) && typeof value.content === "string" && typeof value.failures === "number" && typeof value.deferUntil === "number") {
|
|
6881
|
+
retries[id] = {
|
|
6882
|
+
content: value.content,
|
|
6883
|
+
failures: value.failures,
|
|
6884
|
+
deferUntil: value.deferUntil
|
|
6885
|
+
};
|
|
6886
|
+
}
|
|
6887
|
+
}
|
|
6888
|
+
return retries;
|
|
6889
|
+
} catch {
|
|
6890
|
+
return {};
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
function contentKey(memory) {
|
|
6894
|
+
return createHash5("sha256").update(`${memory.category}
|
|
6895
|
+
${memory.content}`).digest("hex");
|
|
6896
|
+
}
|
|
6897
|
+
function isDeferred(memory, retries) {
|
|
6898
|
+
const retry = retries[memory.id];
|
|
6899
|
+
return !!retry && retry.content === contentKey(memory) && retry.deferUntil > Date.now();
|
|
6900
|
+
}
|
|
6901
|
+
function assistantText(messages) {
|
|
6902
|
+
return messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).map((message) => extractLatestAssistantText([message]) ?? (isRecord(message) && Array.isArray(message.content) ? message.content.filter(isRecord).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join(`
|
|
6903
|
+
`) : "")).join(`
|
|
6904
|
+
`);
|
|
6905
|
+
}
|
|
6906
|
+
function currentManifest(text) {
|
|
6907
|
+
const start = text.lastIndexOf("<mappings>");
|
|
6908
|
+
return start < 0 ? text : text.slice(start);
|
|
6909
|
+
}
|
|
6910
|
+
function logBatchUsage(messages, committed, startedAt) {
|
|
6911
|
+
const steps = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).length;
|
|
6912
|
+
log2(`[dreamer] map-memories batch: steps=${steps} committed=${committed} steps_per_memory=${committed ? (steps / committed).toFixed(2) : "n/a"} elapsed_ms=${Date.now() - startedAt}`);
|
|
6913
|
+
}
|
|
6758
6914
|
function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
|
|
6759
6915
|
return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
|
|
6760
6916
|
}
|
|
@@ -6776,7 +6932,7 @@ function toMapInput(memory, repoDir) {
|
|
|
6776
6932
|
candidates: extractMemoryCandidatePaths(memory.content, repoDir)
|
|
6777
6933
|
};
|
|
6778
6934
|
}
|
|
6779
|
-
function selectMapMemoryInputs(db, projectIdentity, repoDir) {
|
|
6935
|
+
function selectMapMemoryInputs(db, projectIdentity, repoDir, includeDeferred = false) {
|
|
6780
6936
|
const active = getMemoriesByProject2(db, projectIdentity);
|
|
6781
6937
|
const activeIds = active.map((m) => m.id);
|
|
6782
6938
|
const unmapped = new Set(getUnmappedMemoryIds(db, activeIds));
|
|
@@ -6795,7 +6951,8 @@ function selectMapMemoryInputs(db, projectIdentity, repoDir) {
|
|
|
6795
6951
|
if (requeue.length >= MAX_INDEPENDENT_REQUEUE_PER_RUN)
|
|
6796
6952
|
break;
|
|
6797
6953
|
}
|
|
6798
|
-
|
|
6954
|
+
const retries = readRetries(db, projectIdentity);
|
|
6955
|
+
return [...unmappedInputs, ...requeue].filter((memory) => includeDeferred || !isDeferred(memory, retries));
|
|
6799
6956
|
}
|
|
6800
6957
|
async function mapMemories(args) {
|
|
6801
6958
|
const result = {
|
|
@@ -6805,14 +6962,21 @@ async function mapMemories(args) {
|
|
|
6805
6962
|
remaining: 0,
|
|
6806
6963
|
complete: true
|
|
6807
6964
|
};
|
|
6808
|
-
const
|
|
6965
|
+
const allInputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory, true);
|
|
6966
|
+
const retries = readRetries(args.db, args.projectIdentity);
|
|
6967
|
+
const activeIds = new Set(allInputs.map((memory) => String(memory.id)));
|
|
6968
|
+
for (const id of Object.keys(retries))
|
|
6969
|
+
if (!activeIds.has(id))
|
|
6970
|
+
delete retries[id];
|
|
6971
|
+
const inputs = allInputs.filter((memory) => !isDeferred(memory, retries));
|
|
6972
|
+
result.remaining = allInputs.length;
|
|
6973
|
+
result.complete = result.remaining === 0;
|
|
6809
6974
|
if (inputs.length === 0)
|
|
6810
6975
|
return result;
|
|
6811
6976
|
const batches = [];
|
|
6812
6977
|
for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
|
|
6813
6978
|
batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
|
|
6814
6979
|
}
|
|
6815
|
-
result.remaining = inputs.length;
|
|
6816
6980
|
const abortController = new AbortController;
|
|
6817
6981
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
|
|
6818
6982
|
try {
|
|
@@ -6835,6 +6999,24 @@ async function mapMemories(args) {
|
|
|
6835
6999
|
break;
|
|
6836
7000
|
const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
|
|
6837
7001
|
const committed = outcome.mapped + outcome.independent;
|
|
7002
|
+
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
7003
|
+
const committedIds = new Set(outcome.committedIds);
|
|
7004
|
+
for (const memory of batch.inputs) {
|
|
7005
|
+
if (committedIds.has(memory.id)) {
|
|
7006
|
+
delete retries[memory.id];
|
|
7007
|
+
continue;
|
|
7008
|
+
}
|
|
7009
|
+
const content = contentKey(memory);
|
|
7010
|
+
const prior = retries[memory.id];
|
|
7011
|
+
const failures = (prior?.content === content ? prior.failures : 0) + 1;
|
|
7012
|
+
retries[memory.id] = {
|
|
7013
|
+
content,
|
|
7014
|
+
failures,
|
|
7015
|
+
deferUntil: failures < 2 ? 0 : Date.now() + Math.min(24, 2 ** (failures - 2)) * 3600000
|
|
7016
|
+
};
|
|
7017
|
+
}
|
|
7018
|
+
setDreamState(args.db, retryKey(args.projectIdentity), JSON.stringify(retries));
|
|
7019
|
+
});
|
|
6838
7020
|
result.mapped += outcome.mapped;
|
|
6839
7021
|
result.independent += outcome.independent;
|
|
6840
7022
|
result.remaining -= committed;
|
|
@@ -6844,8 +7026,8 @@ async function mapMemories(args) {
|
|
|
6844
7026
|
}
|
|
6845
7027
|
if (outcome.requeue?.length) {
|
|
6846
7028
|
if (!batch.isOmissionRetry) {
|
|
6847
|
-
batches.
|
|
6848
|
-
inputs: outcome.requeue,
|
|
7029
|
+
batches.push({
|
|
7030
|
+
inputs: outcome.requeue.filter((memory) => !isDeferred(memory, retries)),
|
|
6849
7031
|
isOmissionRetry: true
|
|
6850
7032
|
});
|
|
6851
7033
|
log2(`[dreamer] map-memories: committed ${committed}/${batch.inputs.length} mapping(s); requeueing ${outcome.requeue.length} omitted id(s) in a targeted retry`);
|
|
@@ -6853,12 +7035,12 @@ async function mapMemories(args) {
|
|
|
6853
7035
|
log2(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
|
|
6854
7036
|
}
|
|
6855
7037
|
}
|
|
6856
|
-
if (outcome.failure?.class === "timeout") {
|
|
7038
|
+
if (outcome.failure?.class === "timeout" && committed === 0) {
|
|
6857
7039
|
consecutiveTimeouts += 1;
|
|
6858
7040
|
timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
|
|
6859
7041
|
if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
|
|
6860
7042
|
result.stopReason = "timeout-circuit-breaker";
|
|
6861
|
-
log2(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts
|
|
7043
|
+
log2(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts with no committed mappings (investigation made no durable progress); per-batch elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping with ${result.remaining} mapping(s) remaining`);
|
|
6862
7044
|
break;
|
|
6863
7045
|
}
|
|
6864
7046
|
} else {
|
|
@@ -6878,12 +7060,13 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6878
7060
|
let promptSettled = false;
|
|
6879
7061
|
const startedAt = Date.now();
|
|
6880
7062
|
let budgetFinalized = false;
|
|
7063
|
+
let failedCompletion;
|
|
6881
7064
|
const onBudgetUpdate = (state) => {
|
|
6882
7065
|
budgetFinalized ||= state.finalizeFired;
|
|
6883
7066
|
args.onBudgetUpdate?.(state);
|
|
6884
7067
|
};
|
|
6885
7068
|
try {
|
|
6886
|
-
const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
|
|
7069
|
+
const prompt = buildMapMemoriesPrompt(args.projectIdentity, await seedIdentifierCandidates(batch, args.sessionDirectory));
|
|
6887
7070
|
if (args.hiddenCompletionExecutor) {
|
|
6888
7071
|
const run = await runHiddenSingleShotPrompt({
|
|
6889
7072
|
executor: args.hiddenCompletionExecutor,
|
|
@@ -6899,14 +7082,18 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6899
7082
|
fallbackModels: args.fallbackModels,
|
|
6900
7083
|
timeoutMs: sliceMs,
|
|
6901
7084
|
signal,
|
|
6902
|
-
|
|
7085
|
+
onFailureOutput: (completion) => {
|
|
7086
|
+
failedCompletion = completion;
|
|
7087
|
+
},
|
|
7088
|
+
parse: (text, completion) => validateMapMemoriesManifest(currentManifest(assistantText(completion.messages ?? []) || text), new Set(batch.map((memory) => memory.id)))
|
|
6903
7089
|
});
|
|
6904
7090
|
recordInvocation2(args, startedAt, {
|
|
6905
7091
|
status: "completed",
|
|
6906
7092
|
messages: run.completion.messages ?? []
|
|
6907
7093
|
});
|
|
6908
|
-
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
|
|
6909
|
-
|
|
7094
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
|
|
7095
|
+
logBatchUsage(run.completion.messages ?? [], outcome.mapped + outcome.independent, startedAt);
|
|
7096
|
+
const returnedIds = new Set(outcome.committedIds);
|
|
6910
7097
|
return {
|
|
6911
7098
|
...outcome,
|
|
6912
7099
|
requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
|
|
@@ -6949,7 +7136,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6949
7136
|
fetchOutput: async () => {
|
|
6950
7137
|
const messagesResponse = await client.session.messages({
|
|
6951
7138
|
path: { id: agentSessionId },
|
|
6952
|
-
query: { directory: args.sessionDirectory, limit:
|
|
7139
|
+
query: { directory: args.sessionDirectory, limit: 200 }
|
|
6953
7140
|
});
|
|
6954
7141
|
return normalizeSDKResponse(messagesResponse, [], {
|
|
6955
7142
|
preferResponseOnMissingData: true
|
|
@@ -6959,7 +7146,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6959
7146
|
if (hasLengthCappedOutput(messages)) {
|
|
6960
7147
|
throw new Error("map-memories returned length-capped output");
|
|
6961
7148
|
}
|
|
6962
|
-
const text =
|
|
7149
|
+
const text = currentManifest(assistantText(messages));
|
|
6963
7150
|
if (!text)
|
|
6964
7151
|
throw new Error("map-memories returned no output");
|
|
6965
7152
|
return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
@@ -6967,8 +7154,9 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6967
7154
|
});
|
|
6968
7155
|
promptSettled = true;
|
|
6969
7156
|
recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
|
|
6970
|
-
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
|
|
6971
|
-
|
|
7157
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
|
|
7158
|
+
logBatchUsage(run.output, outcome.mapped + outcome.independent, startedAt);
|
|
7159
|
+
const returnedIds = new Set(outcome.committedIds);
|
|
6972
7160
|
return {
|
|
6973
7161
|
...outcome,
|
|
6974
7162
|
requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
|
|
@@ -6976,18 +7164,23 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
6976
7164
|
} catch (error) {
|
|
6977
7165
|
const desc = describeError(error);
|
|
6978
7166
|
log2(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
7167
|
+
const messages = failedCompletion?.messages ?? await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory) ?? [];
|
|
6979
7168
|
recordInvocation2(args, startedAt, {
|
|
6980
7169
|
status: failedInvocationStatus(error),
|
|
6981
7170
|
error,
|
|
6982
|
-
messages
|
|
7171
|
+
messages
|
|
6983
7172
|
});
|
|
6984
|
-
if (error instanceof DreamerModuleFailureError
|
|
7173
|
+
if (error instanceof DreamerModuleFailureError)
|
|
6985
7174
|
throw error;
|
|
6986
7175
|
if (signal.aborted)
|
|
6987
7176
|
throw error;
|
|
7177
|
+
const recovered = parsePartialMapMemoriesManifest(assistantText(messages) || failedCompletion?.text || "", new Set(batch.map((memory) => memory.id)));
|
|
7178
|
+
const outcome = await applyParsedBatchMappings(args, batch, recovered, budgetFinalized, true);
|
|
7179
|
+
logBatchUsage(messages, outcome.mapped + outcome.independent, startedAt);
|
|
7180
|
+
if (error instanceof DreamTokenBudgetExceeded)
|
|
7181
|
+
throw error;
|
|
6988
7182
|
return {
|
|
6989
|
-
|
|
6990
|
-
independent: 0,
|
|
7183
|
+
...outcome,
|
|
6991
7184
|
failure: {
|
|
6992
7185
|
class: isTimeoutClassError2(error) ? "timeout" : "other",
|
|
6993
7186
|
elapsedMs: Date.now() - startedAt
|
|
@@ -7006,7 +7199,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
7006
7199
|
});
|
|
7007
7200
|
}
|
|
7008
7201
|
}
|
|
7009
|
-
async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false) {
|
|
7202
|
+
async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false, allowPartial = false) {
|
|
7010
7203
|
const batchIds = new Set(batch.map((memory) => memory.id));
|
|
7011
7204
|
const valid = parsed.filter((entry) => batchIds.has(entry.id));
|
|
7012
7205
|
const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
|
|
@@ -7014,14 +7207,14 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
7014
7207
|
log2(`[dreamer] map-memories warning: dropping ${unknown.length} unknown mapping entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
|
|
7015
7208
|
}
|
|
7016
7209
|
assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
|
|
7017
|
-
if (!budgetFinalized && valid.length * 2 < batch.length) {
|
|
7210
|
+
if (!allowPartial && !budgetFinalized && valid.length * 2 < batch.length) {
|
|
7018
7211
|
throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
|
|
7019
7212
|
}
|
|
7020
7213
|
if (budgetFinalized && valid.length < batch.length) {
|
|
7021
7214
|
log2(`[dreamer] map-memories: accepted partial manifest after token budget: ${valid.length}/${batch.length}`);
|
|
7022
7215
|
}
|
|
7023
7216
|
if (valid.length === 0)
|
|
7024
|
-
return { mapped: 0, independent: 0 };
|
|
7217
|
+
return { mapped: 0, independent: 0, committedIds: [] };
|
|
7025
7218
|
const planned = [];
|
|
7026
7219
|
const batchById = new Map(batch.map((memory) => [memory.id, memory]));
|
|
7027
7220
|
for (const p of valid) {
|
|
@@ -7070,9 +7263,10 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
7070
7263
|
});
|
|
7071
7264
|
}
|
|
7072
7265
|
if (planned.length === 0)
|
|
7073
|
-
return { mapped: 0, independent: 0 };
|
|
7266
|
+
return { mapped: 0, independent: 0, committedIds: [] };
|
|
7074
7267
|
let mapped = 0;
|
|
7075
7268
|
let independent = 0;
|
|
7269
|
+
const committedIds = [];
|
|
7076
7270
|
if (args.moduleRoute) {
|
|
7077
7271
|
const identities = getModuleMemoryIdentities(args.db, args.projectIdentity, planned.map((item) => item.id));
|
|
7078
7272
|
const rows = planned.map((item) => {
|
|
@@ -7110,19 +7304,22 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
7110
7304
|
const accepted = new Set(result.accepted.filter((id) => typeof id === "number"));
|
|
7111
7305
|
for (const item of planned) {
|
|
7112
7306
|
const identity = identities.get(item.id);
|
|
7113
|
-
if (identity && accepted.has(identity.moduleId))
|
|
7307
|
+
if (identity && accepted.has(identity.moduleId)) {
|
|
7114
7308
|
item.independent ? independent += 1 : mapped += 1;
|
|
7309
|
+
committedIds.push(item.id);
|
|
7310
|
+
}
|
|
7115
7311
|
}
|
|
7116
|
-
return { mapped, independent };
|
|
7312
|
+
return { mapped, independent, committedIds };
|
|
7117
7313
|
}
|
|
7118
7314
|
const now = Date.now();
|
|
7119
7315
|
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
7120
7316
|
for (const item of planned) {
|
|
7121
7317
|
recordMemoryMapping(args.db, item.id, item.files, now, item.mappingOrigin);
|
|
7122
7318
|
item.independent ? independent += 1 : mapped += 1;
|
|
7319
|
+
committedIds.push(item.id);
|
|
7123
7320
|
}
|
|
7124
7321
|
});
|
|
7125
|
-
return { mapped, independent };
|
|
7322
|
+
return { mapped, independent, committedIds };
|
|
7126
7323
|
}
|
|
7127
7324
|
function recordInvocation2(args, startedAt, params) {
|
|
7128
7325
|
if (!args.parentSessionId)
|
|
@@ -7390,32 +7587,41 @@ async function promotePrimers(args) {
|
|
|
7390
7587
|
// src/features/magic-context/dreamer/primer-seed.ts
|
|
7391
7588
|
var PRIMER_SEED_CAP_TOKENS = 4000;
|
|
7392
7589
|
function renderUserAndToolOrientation(sessionId, startOrdinal, endOrdinal, capTokens) {
|
|
7590
|
+
const renderer = orientationRenderer(capTokens);
|
|
7591
|
+
visitRawSessionMessages2(sessionId, startOrdinal, endOrdinal, renderer.visit, {
|
|
7592
|
+
summary: true
|
|
7593
|
+
});
|
|
7594
|
+
return renderer.result();
|
|
7595
|
+
}
|
|
7596
|
+
function orientationRenderer(capTokens) {
|
|
7393
7597
|
const lines = [];
|
|
7394
7598
|
let tokens = 0;
|
|
7395
7599
|
let sawMessage = false;
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
const
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7600
|
+
return {
|
|
7601
|
+
visit: (msg) => {
|
|
7602
|
+
sawMessage = true;
|
|
7603
|
+
const out = [];
|
|
7604
|
+
if (msg.role === "user" && hasMeaningfulUserText2(msg.parts)) {
|
|
7605
|
+
const text = extractTexts2(msg.parts).map((t) => cleanUserText2(t)).map(normalizeText).filter((t) => t.length > 0).join(" / ");
|
|
7606
|
+
if (text)
|
|
7607
|
+
out.push(`U: ${text}`);
|
|
7608
|
+
}
|
|
7609
|
+
for (const tc of extractToolCallSummaries(msg.parts))
|
|
7610
|
+
out.push(tc);
|
|
7611
|
+
for (const line of out) {
|
|
7612
|
+
const lineTokens = estimateTokens(line);
|
|
7613
|
+
if (tokens + lineTokens > capTokens && lines.length > 0) {
|
|
7614
|
+
lines.push("… (orientation truncated; investigate the current source directly)");
|
|
7615
|
+
return false;
|
|
7616
|
+
}
|
|
7617
|
+
lines.push(line);
|
|
7618
|
+
tokens += lineTokens;
|
|
7411
7619
|
}
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
}
|
|
7417
|
-
return sawMessage ? lines.join(`
|
|
7418
|
-
`) : null;
|
|
7620
|
+
return true;
|
|
7621
|
+
},
|
|
7622
|
+
result: () => sawMessage ? lines.join(`
|
|
7623
|
+
`) : null
|
|
7624
|
+
};
|
|
7419
7625
|
}
|
|
7420
7626
|
function selectPrimerOriginCandidate(db, primer) {
|
|
7421
7627
|
return getPrimerCandidatesByIds(db, primer.sourceCandidateIds).filter((candidate) => candidate.projectPath === primer.projectPath).sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
|
|
@@ -7449,16 +7655,37 @@ function closedBookOriginP1(db, sessionId, originStartMessage) {
|
|
|
7449
7655
|
return { orientation, sessionId };
|
|
7450
7656
|
}
|
|
7451
7657
|
function buildPrimerSeed(db, primer) {
|
|
7658
|
+
return buildPrimerSeedUsing(db, selectPrimerOriginCandidate(db, primer), renderUserAndToolOrientation);
|
|
7659
|
+
}
|
|
7660
|
+
async function buildPrimerSeedAsync(db, primer) {
|
|
7452
7661
|
const mostRecent = selectPrimerOriginCandidate(db, primer);
|
|
7662
|
+
let orientation = null;
|
|
7663
|
+
if (mostRecent && typeof mostRecent.sourceCompartmentStart === "number" && typeof mostRecent.sourceCompartmentEnd === "number") {
|
|
7664
|
+
try {
|
|
7665
|
+
const renderer = orientationRenderer(PRIMER_SEED_CAP_TOKENS);
|
|
7666
|
+
await visitRawSessionMessagesAsync2(mostRecent.sessionId, mostRecent.sourceCompartmentStart, mostRecent.sourceCompartmentEnd, renderer.visit, { summary: true });
|
|
7667
|
+
orientation = renderer.result();
|
|
7668
|
+
} catch {
|
|
7669
|
+
orientation = null;
|
|
7670
|
+
}
|
|
7671
|
+
}
|
|
7672
|
+
return buildPrimerSeedUsing(db, mostRecent, () => orientation);
|
|
7673
|
+
}
|
|
7674
|
+
function buildPrimerSeedUsing(db, mostRecent, render) {
|
|
7453
7675
|
if (!mostRecent || typeof mostRecent.sourceCompartmentStart !== "number" || typeof mostRecent.sourceCompartmentEnd !== "number") {
|
|
7454
|
-
return {
|
|
7676
|
+
return {
|
|
7677
|
+
kind: "closed-book",
|
|
7678
|
+
orientation: "",
|
|
7679
|
+
prePost: "",
|
|
7680
|
+
sessionId: null
|
|
7681
|
+
};
|
|
7455
7682
|
}
|
|
7456
7683
|
const sessionId = mostRecent.sessionId;
|
|
7457
7684
|
const start = mostRecent.sourceCompartmentStart;
|
|
7458
7685
|
const end = mostRecent.sourceCompartmentEnd;
|
|
7459
7686
|
let orientation = null;
|
|
7460
7687
|
try {
|
|
7461
|
-
orientation =
|
|
7688
|
+
orientation = render(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
|
|
7462
7689
|
} catch {
|
|
7463
7690
|
orientation = null;
|
|
7464
7691
|
}
|
|
@@ -7589,14 +7816,14 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7589
7816
|
provider = null;
|
|
7590
7817
|
}
|
|
7591
7818
|
}
|
|
7592
|
-
const seed =
|
|
7819
|
+
const seed = await (async () => {
|
|
7593
7820
|
const unregister = provider && originSessionId ? setRawMessageProvider2(originSessionId, provider) : null;
|
|
7594
7821
|
try {
|
|
7595
|
-
return buildPrimerSeed(args.db, primer);
|
|
7822
|
+
return provider?.iterateMessageRangeAsync ? await buildPrimerSeedAsync(args.db, primer) : withRawSessionMessageCache2(() => buildPrimerSeed(args.db, primer));
|
|
7596
7823
|
} finally {
|
|
7597
7824
|
unregister?.();
|
|
7598
7825
|
}
|
|
7599
|
-
});
|
|
7826
|
+
})();
|
|
7600
7827
|
let agentSessionId = null;
|
|
7601
7828
|
let promptSettled = false;
|
|
7602
7829
|
const startedAt = Date.now();
|
|
@@ -7612,7 +7839,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7612
7839
|
prompt,
|
|
7613
7840
|
title: "magic-context-dream-refresh-primers",
|
|
7614
7841
|
callContext: "dreamer:refresh-primers",
|
|
7615
|
-
metadata: {
|
|
7842
|
+
metadata: {
|
|
7843
|
+
tokenBudget: args.tokenBudget,
|
|
7844
|
+
onBudgetUpdate: args.onBudgetUpdate
|
|
7845
|
+
},
|
|
7616
7846
|
model: args.model,
|
|
7617
7847
|
fallbackModels: args.fallbackModels,
|
|
7618
7848
|
language: args.language,
|
|
@@ -7678,7 +7908,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7678
7908
|
validateOutput: (messages) => parseAnswer(messages, primer.answer)
|
|
7679
7909
|
});
|
|
7680
7910
|
promptSettled = true;
|
|
7681
|
-
recordInvocation3(args, startedAt, {
|
|
7911
|
+
recordInvocation3(args, startedAt, {
|
|
7912
|
+
status: "completed",
|
|
7913
|
+
messages: run.output
|
|
7914
|
+
});
|
|
7682
7915
|
const answer = run.validated.trim();
|
|
7683
7916
|
if (!answer)
|
|
7684
7917
|
return false;
|
|
@@ -7693,7 +7926,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7693
7926
|
} catch (error) {
|
|
7694
7927
|
const desc = describeError(error);
|
|
7695
7928
|
log2(`[dreamer] refresh-primers failed (primer #${primer.id}): ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
7696
|
-
recordInvocation3(args, startedAt, {
|
|
7929
|
+
recordInvocation3(args, startedAt, {
|
|
7930
|
+
status: failedInvocationStatus(error),
|
|
7931
|
+
error
|
|
7932
|
+
});
|
|
7697
7933
|
throw error;
|
|
7698
7934
|
} finally {
|
|
7699
7935
|
if (agentSessionId && args.client)
|
|
@@ -8210,9 +8446,9 @@ function evaluateTaskGate(task, ctx) {
|
|
|
8210
8446
|
import { createHash as createHash6 } from "node:crypto";
|
|
8211
8447
|
|
|
8212
8448
|
// src/features/magic-context/dreamer/verify-diff.ts
|
|
8213
|
-
import { execFile as
|
|
8214
|
-
import { promisify as
|
|
8215
|
-
var exec =
|
|
8449
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
8450
|
+
import { promisify as promisify3 } from "node:util";
|
|
8451
|
+
var exec = promisify3(execFile3);
|
|
8216
8452
|
var VERIFY_DIFF_BUDGET_TOKENS = 12000;
|
|
8217
8453
|
var MAX_DIFF_BYTES = 4 * 1024 * 1024;
|
|
8218
8454
|
async function git2(root, args) {
|
|
@@ -15706,8 +15942,8 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
15706
15942
|
const db = readDatabase();
|
|
15707
15943
|
if (!db)
|
|
15708
15944
|
return { ok: false, error: "db unavailable" };
|
|
15709
|
-
const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-
|
|
15710
|
-
const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-
|
|
15945
|
+
const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-trcgmm23.js"));
|
|
15946
|
+
const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-2tp44tfa.js"));
|
|
15711
15947
|
log2(`[rpc] recomp requested for session ${sessionId}`);
|
|
15712
15948
|
if (!args.client && !args.hiddenCompletionExecutor) {
|
|
15713
15949
|
return {
|
|
@@ -15776,7 +16012,7 @@ function registerRpcHandlers(rpcServer, args) {
|
|
|
15776
16012
|
const db = readDatabase();
|
|
15777
16013
|
if (!db)
|
|
15778
16014
|
return { ok: false, error: "db unavailable" };
|
|
15779
|
-
const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-
|
|
16015
|
+
const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-df61jmz9.js"));
|
|
15780
16016
|
const model = liveSessionState.liveModelBySession.get(sessionId);
|
|
15781
16017
|
const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
|
|
15782
16018
|
const ctx = {
|
|
@@ -16215,11 +16451,11 @@ function clone(value) {
|
|
|
16215
16451
|
return value;
|
|
16216
16452
|
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, clone(item)]));
|
|
16217
16453
|
}
|
|
16218
|
-
function
|
|
16454
|
+
function isThinkingPart2(part) {
|
|
16219
16455
|
return isRecord(part) && ["thinking", "reasoning", "redacted_thinking"].includes(String(part.type));
|
|
16220
16456
|
}
|
|
16221
16457
|
function replayableOriginal(part) {
|
|
16222
|
-
if (!
|
|
16458
|
+
if (!isThinkingPart2(part) || !isRecord(part))
|
|
16223
16459
|
return false;
|
|
16224
16460
|
const metadata = isRecord(part.metadata) && isRecord(part.metadata.anthropic) ? part.metadata.anthropic : {};
|
|
16225
16461
|
const signature = part.signature ?? part.thinkingSignature ?? metadata.signature ?? part.data ?? metadata.redactedData;
|
|
@@ -16527,7 +16763,7 @@ function createPassOutcome() {
|
|
|
16527
16763
|
}
|
|
16528
16764
|
|
|
16529
16765
|
// src/hooks/magic-context/rust-mode-transform.ts
|
|
16530
|
-
import { createHash as
|
|
16766
|
+
import { createHash as createHash12, randomUUID as randomUUID6 } from "node:crypto";
|
|
16531
16767
|
|
|
16532
16768
|
// src/features/magic-context/memory/single-store-embedding-drain.ts
|
|
16533
16769
|
function isWatermarkRow(row) {
|
|
@@ -19059,13 +19295,235 @@ function resolveRustLkgReplayParticipant(sessionId) {
|
|
|
19059
19295
|
return latest;
|
|
19060
19296
|
return alive.length === 1 ? alive[0] : undefined;
|
|
19061
19297
|
}
|
|
19062
|
-
function noteExternalLkgReplay(participant, sessionId,
|
|
19298
|
+
function noteExternalLkgReplay(participant, sessionId, inputMessages, servedMessages) {
|
|
19063
19299
|
if (!participant)
|
|
19064
19300
|
return;
|
|
19065
|
-
participant.enterFreezeFromExternalServe(sessionId,
|
|
19301
|
+
participant.enterFreezeFromExternalServe(sessionId, inputMessages, servedMessages);
|
|
19066
19302
|
sessionLog2(sessionId, "lkg_external_replay_froze_rust_adapter");
|
|
19067
19303
|
}
|
|
19068
19304
|
|
|
19305
|
+
// src/hooks/magic-context/rust-served-raw.ts
|
|
19306
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
19307
|
+
class RustServedRawConflict extends EmergencyFailClosedError {
|
|
19308
|
+
reason;
|
|
19309
|
+
messageIds;
|
|
19310
|
+
firstBlockId;
|
|
19311
|
+
constructor(reason, messageIds, firstBlockId) {
|
|
19312
|
+
super(`Rust served-raw conflict: ${reason} at ${firstBlockId}`);
|
|
19313
|
+
this.reason = reason;
|
|
19314
|
+
this.messageIds = messageIds;
|
|
19315
|
+
this.firstBlockId = firstBlockId;
|
|
19316
|
+
}
|
|
19317
|
+
}
|
|
19318
|
+
function partDigest(part) {
|
|
19319
|
+
const serialized = JSON.stringify(part);
|
|
19320
|
+
return createHash11("sha256").update(stableStringify(serialized === undefined ? undefined : JSON.parse(serialized))).digest("hex");
|
|
19321
|
+
}
|
|
19322
|
+
function records(doc) {
|
|
19323
|
+
if (doc.rustServedRaw === undefined)
|
|
19324
|
+
return [];
|
|
19325
|
+
if (!Array.isArray(doc.rustServedRaw))
|
|
19326
|
+
throw new EmergencyFailClosedError("Invalid Rust served-raw evidence");
|
|
19327
|
+
for (const row of doc.rustServedRaw) {
|
|
19328
|
+
if (!row || typeof row.messageId !== "string" || !Number.isSafeInteger(row.index) || row.index < 0 || row.partId !== undefined && typeof row.partId !== "string" || typeof row.digest !== "string" || !/^[a-f0-9]{64}$/.test(row.digest) || !Array.isArray(row.blockIds) || !row.blockIds.every((id) => typeof id === "string")) {
|
|
19329
|
+
throw new EmergencyFailClosedError("Invalid Rust served-raw part");
|
|
19330
|
+
}
|
|
19331
|
+
}
|
|
19332
|
+
return doc.rustServedRaw;
|
|
19333
|
+
}
|
|
19334
|
+
function rustRawRebuild(db, sessionId) {
|
|
19335
|
+
const value = readReplayEnvelope(db, sessionId).rustRawRebuild;
|
|
19336
|
+
if (value === undefined)
|
|
19337
|
+
return;
|
|
19338
|
+
if (!value || typeof value.identity !== "string" || !/^[a-f0-9]{64}$/.test(value.identity) || !["source_removed", "source_changed", "candidate_loss", "candidate_conflict"].includes(value.reason) || !Array.isArray(value.messageIds) || !value.messageIds.every((id) => typeof id === "string") || typeof value.firstBlockId !== "string" || typeof value.pending !== "boolean") {
|
|
19339
|
+
throw new EmergencyFailClosedError("Invalid Rust raw-rebuild request");
|
|
19340
|
+
}
|
|
19341
|
+
return value;
|
|
19342
|
+
}
|
|
19343
|
+
function servedRawBlockIds(db, sessionId) {
|
|
19344
|
+
return records(readReplayEnvelope(db, sessionId)).flatMap((row) => row.blockIds);
|
|
19345
|
+
}
|
|
19346
|
+
function sourcePart(row, message) {
|
|
19347
|
+
return row.partId === undefined ? message?.parts[row.index] : message?.parts.find((part) => part?.id === row.partId);
|
|
19348
|
+
}
|
|
19349
|
+
function conflict(row, reason) {
|
|
19350
|
+
return new RustServedRawConflict(reason, [row.messageId], row.blockIds[0] ?? `${row.messageId}#0`);
|
|
19351
|
+
}
|
|
19352
|
+
function checkRustServedRawIngress(db, sessionId, input) {
|
|
19353
|
+
const rows = records(readReplayEnvelope(db, sessionId));
|
|
19354
|
+
if (!rows.length)
|
|
19355
|
+
return;
|
|
19356
|
+
const byId = new Map(input.map((message) => [message.info.id, message]));
|
|
19357
|
+
const changed = rows.filter((row) => partDigest(sourcePart(row, byId.get(row.messageId))) !== row.digest);
|
|
19358
|
+
const first = changed[0];
|
|
19359
|
+
if (!first)
|
|
19360
|
+
return;
|
|
19361
|
+
throw new RustServedRawConflict(sourcePart(first, byId.get(first.messageId)) === undefined ? "source_removed" : "source_changed", [...new Set(changed.map((row) => row.messageId))], first.blockIds[0] ?? `${first.messageId}#0`);
|
|
19362
|
+
}
|
|
19363
|
+
function requestRustRawRebuild(db, sessionId, error) {
|
|
19364
|
+
if (!updateReplayDocument(db, sessionId, (doc) => {
|
|
19365
|
+
const previous = doc.rustRawRebuild;
|
|
19366
|
+
if (previous?.pending && previous.reason === error.reason && previous.firstBlockId === error.firstBlockId && error.messageIds.every((id) => previous.messageIds.includes(id)))
|
|
19367
|
+
return false;
|
|
19368
|
+
const messageIds = [
|
|
19369
|
+
...new Set([
|
|
19370
|
+
...previous?.pending ? previous.messageIds : [],
|
|
19371
|
+
...error.messageIds
|
|
19372
|
+
])
|
|
19373
|
+
];
|
|
19374
|
+
const identity = partDigest([
|
|
19375
|
+
previous?.identity ?? "",
|
|
19376
|
+
error.reason,
|
|
19377
|
+
messageIds,
|
|
19378
|
+
error.firstBlockId
|
|
19379
|
+
]);
|
|
19380
|
+
doc.version = 2;
|
|
19381
|
+
doc.rustRawRebuild = {
|
|
19382
|
+
identity,
|
|
19383
|
+
reason: error.reason,
|
|
19384
|
+
messageIds,
|
|
19385
|
+
firstBlockId: error.firstBlockId,
|
|
19386
|
+
pending: true
|
|
19387
|
+
};
|
|
19388
|
+
return true;
|
|
19389
|
+
}))
|
|
19390
|
+
throw new EmergencyFailClosedError("Cannot persist Rust raw-rebuild request");
|
|
19391
|
+
}
|
|
19392
|
+
function noteRustServedRaw(db, sessionId, input, served) {
|
|
19393
|
+
const additions = [];
|
|
19394
|
+
const byId = new Map(served.filter((message) => typeof message?.info?.id === "string").map((message) => [message.info.id, message]));
|
|
19395
|
+
for (const message of input) {
|
|
19396
|
+
const visible = byId.get(message.info.id);
|
|
19397
|
+
if (!visible)
|
|
19398
|
+
continue;
|
|
19399
|
+
let offset = 0;
|
|
19400
|
+
for (const [index, value] of message.parts.entries()) {
|
|
19401
|
+
if (!value || typeof value !== "object")
|
|
19402
|
+
continue;
|
|
19403
|
+
const part = value;
|
|
19404
|
+
const count = encodeOpenCodeMessagesToCk([{ ...message, parts: [part] }])[0].ck.content.length;
|
|
19405
|
+
const actual = typeof part.id === "string" ? visible.parts.find((candidate) => candidate?.id === part.id) : visible.parts[index];
|
|
19406
|
+
const status = part.state?.status;
|
|
19407
|
+
const reachesProvider = !(part.type === "text" && part.ignored === true) && ![
|
|
19408
|
+
"compaction",
|
|
19409
|
+
"step-start",
|
|
19410
|
+
"step-finish",
|
|
19411
|
+
"snapshot",
|
|
19412
|
+
"patch",
|
|
19413
|
+
"agent",
|
|
19414
|
+
"retry"
|
|
19415
|
+
].includes(String(part.type)) && (part.type !== "tool" || status === "completed" || status === "error");
|
|
19416
|
+
if (reachesProvider && count > 0) {
|
|
19417
|
+
const digest = partDigest(part);
|
|
19418
|
+
if (actual === part || partDigest(actual) === digest) {
|
|
19419
|
+
additions.push({
|
|
19420
|
+
messageId: message.info.id,
|
|
19421
|
+
index,
|
|
19422
|
+
...typeof part.id === "string" ? { partId: part.id } : {},
|
|
19423
|
+
digest,
|
|
19424
|
+
blockIds: Array.from({ length: count }, (_, i) => `${message.info.id}#${offset + i}`)
|
|
19425
|
+
});
|
|
19426
|
+
}
|
|
19427
|
+
}
|
|
19428
|
+
offset += count;
|
|
19429
|
+
}
|
|
19430
|
+
}
|
|
19431
|
+
if (!additions.length)
|
|
19432
|
+
return;
|
|
19433
|
+
if (!updateReplayDocument(db, sessionId, (doc) => {
|
|
19434
|
+
const rows = records(doc);
|
|
19435
|
+
const key = (row) => stableStringify([row.messageId, row.partId ?? row.index]);
|
|
19436
|
+
const merged = new Map(rows.map((row) => [key(row), row]));
|
|
19437
|
+
for (const row of additions)
|
|
19438
|
+
merged.set(key(row), row);
|
|
19439
|
+
const next = [...merged.values()];
|
|
19440
|
+
if (stableStringify(rows) === stableStringify(next))
|
|
19441
|
+
return false;
|
|
19442
|
+
doc.version = 2;
|
|
19443
|
+
doc.rustServedRaw = next;
|
|
19444
|
+
return true;
|
|
19445
|
+
}))
|
|
19446
|
+
throw new EmergencyFailClosedError("Cannot persist Rust served-raw evidence");
|
|
19447
|
+
}
|
|
19448
|
+
function preserveRustServedRaw(db, sessionId, output, input = output, reconstruct = new Set, covered = new Set) {
|
|
19449
|
+
const rows = records(readReplayEnvelope(db, sessionId));
|
|
19450
|
+
if (!rows.length)
|
|
19451
|
+
return false;
|
|
19452
|
+
const sources = new Map(input.map((message) => [message.info.id, message]));
|
|
19453
|
+
const byId = new Map(output.map((message) => [message.info.id, message]));
|
|
19454
|
+
let repaired = false;
|
|
19455
|
+
for (const row of rows) {
|
|
19456
|
+
if (covered.has(row.messageId))
|
|
19457
|
+
continue;
|
|
19458
|
+
const original = sources.get(row.messageId);
|
|
19459
|
+
const source = sourcePart(row, original);
|
|
19460
|
+
if (!original || !source)
|
|
19461
|
+
throw conflict(row, "source_removed");
|
|
19462
|
+
if (partDigest(source) !== row.digest)
|
|
19463
|
+
throw conflict(row, "source_changed");
|
|
19464
|
+
let message = byId.get(row.messageId);
|
|
19465
|
+
if (!message) {
|
|
19466
|
+
if (!reconstruct.has(row.messageId))
|
|
19467
|
+
throw conflict(row, "candidate_loss");
|
|
19468
|
+
const sourceIndex = input.indexOf(original);
|
|
19469
|
+
const next = output.findIndex((candidate) => input.findIndex((entry) => entry.info.id === candidate.info.id) > sourceIndex);
|
|
19470
|
+
message = structuredClone(original);
|
|
19471
|
+
output.splice(next < 0 ? output.length : next, 0, message);
|
|
19472
|
+
byId.set(row.messageId, message);
|
|
19473
|
+
repaired = true;
|
|
19474
|
+
}
|
|
19475
|
+
const parts = message.parts;
|
|
19476
|
+
if (row.partId === undefined) {
|
|
19477
|
+
const candidate = parts[row.index];
|
|
19478
|
+
if (partDigest(candidate) === row.digest)
|
|
19479
|
+
continue;
|
|
19480
|
+
const reversibleTag = source.type === "text" && typeof source.text === "string" && typeof candidate?.text === "string" && /^§\d+§ /.test(candidate.text) && candidate.text.replace(/^§\d+§ /, "") === source.text && partDigest({ ...candidate, text: source.text }) === row.digest;
|
|
19481
|
+
if (!reversibleTag) {
|
|
19482
|
+
if (!reconstruct.has(row.messageId))
|
|
19483
|
+
throw conflict(row, "candidate_conflict");
|
|
19484
|
+
message.parts = structuredClone(original.parts);
|
|
19485
|
+
repaired = true;
|
|
19486
|
+
continue;
|
|
19487
|
+
}
|
|
19488
|
+
parts[row.index] = structuredClone(source);
|
|
19489
|
+
continue;
|
|
19490
|
+
}
|
|
19491
|
+
const matches = parts.flatMap((part, i) => part.id === row.partId ? [i] : []);
|
|
19492
|
+
if (matches.length > 1)
|
|
19493
|
+
throw conflict(row, "candidate_conflict");
|
|
19494
|
+
const index = matches[0];
|
|
19495
|
+
if (index !== undefined) {
|
|
19496
|
+
if (partDigest(parts[index]) !== row.digest)
|
|
19497
|
+
parts[index] = structuredClone(source);
|
|
19498
|
+
} else if (["reasoning", "thinking", "redacted_thinking"].includes(String(source.type)) || reconstruct.has(row.messageId)) {
|
|
19499
|
+
parts.splice(row.index, 0, structuredClone(source));
|
|
19500
|
+
repaired = true;
|
|
19501
|
+
} else
|
|
19502
|
+
throw conflict(row, "candidate_loss");
|
|
19503
|
+
}
|
|
19504
|
+
return repaired;
|
|
19505
|
+
}
|
|
19506
|
+
function releaseRustServedRaw(db, sessionId, output, rebuiltIdentity) {
|
|
19507
|
+
const snapshot = readReplayEnvelope(db, sessionId);
|
|
19508
|
+
if (!records(snapshot).length && !snapshot.rustRawRebuild?.pending)
|
|
19509
|
+
return;
|
|
19510
|
+
const byId = new Map(output.map((message) => [message.info.id, message]));
|
|
19511
|
+
if (!updateReplayDocument(db, sessionId, (doc) => {
|
|
19512
|
+
const rows = records(doc);
|
|
19513
|
+
const kept = rows.filter((row) => partDigest(sourcePart(row, byId.get(row.messageId))) === row.digest);
|
|
19514
|
+
const recovery = doc.rustRawRebuild;
|
|
19515
|
+
const acknowledged = recovery?.pending && recovery.identity === rebuiltIdentity;
|
|
19516
|
+
if (kept.length === rows.length && !acknowledged)
|
|
19517
|
+
return false;
|
|
19518
|
+
doc.version = 2;
|
|
19519
|
+
doc.rustServedRaw = kept;
|
|
19520
|
+
if (acknowledged)
|
|
19521
|
+
doc.rustRawRebuild = { ...recovery, pending: false };
|
|
19522
|
+
return true;
|
|
19523
|
+
}))
|
|
19524
|
+
throw new EmergencyFailClosedError("Cannot release Rust served-raw evidence");
|
|
19525
|
+
}
|
|
19526
|
+
|
|
19069
19527
|
// src/hooks/magic-context/storage-busy-refusal.ts
|
|
19070
19528
|
var STORAGE_BUSY_MESSAGE = "Magic Context's database is busy (another process held it too long); send your message again.";
|
|
19071
19529
|
function describeStorageBusyCause(cause) {
|
|
@@ -19505,10 +19963,10 @@ function messageCacheSignature(message) {
|
|
|
19505
19963
|
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
19506
19964
|
const serializedParts = JSON.stringify(parts) ?? "null";
|
|
19507
19965
|
const serializedMessage = JSON.stringify(message) ?? "null";
|
|
19508
|
-
return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${
|
|
19966
|
+
return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash12("sha256").update(serializedMessage).digest("hex")}`;
|
|
19509
19967
|
}
|
|
19510
19968
|
function advanceWireFingerprint(previous, encoded) {
|
|
19511
|
-
return
|
|
19969
|
+
return createHash12("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
|
|
19512
19970
|
}
|
|
19513
19971
|
function buildWireFingerprint(encoded) {
|
|
19514
19972
|
let fingerprint = "rust-wire-v1";
|
|
@@ -20048,7 +20506,8 @@ function buildTransformBody(args) {
|
|
|
20048
20506
|
args.providerId ? `provider:${args.providerId}` : "",
|
|
20049
20507
|
args.modelKey ? `model:${args.modelKey}` : "",
|
|
20050
20508
|
args.variant ? `variant:${args.variant}` : "",
|
|
20051
|
-
args.systemPromptHash ? `system:${args.systemPromptHash}` : ""
|
|
20509
|
+
args.systemPromptHash ? `system:${args.systemPromptHash}` : "",
|
|
20510
|
+
args.rawRebuild ? `raw_replay:${args.rawRebuild.identity}` : ""
|
|
20052
20511
|
].filter(Boolean).join("|"),
|
|
20053
20512
|
system_prompt_hash: args.systemPromptHash,
|
|
20054
20513
|
adopted_system_prompt_hash: args.passInputs.adopted_system_prompt_hash,
|
|
@@ -20056,6 +20515,14 @@ function buildTransformBody(args) {
|
|
|
20056
20515
|
is_subagent: args.passInputs.is_subagent === true,
|
|
20057
20516
|
messages: args.input,
|
|
20058
20517
|
native_messages: args.nativeMessages,
|
|
20518
|
+
served_raw_block_ids: args.servedRawBlockIds ?? [],
|
|
20519
|
+
...args.rawRebuild?.pending ? {
|
|
20520
|
+
raw_replay_rebuild: {
|
|
20521
|
+
identity: args.rawRebuild.identity,
|
|
20522
|
+
reason: args.rawRebuild.reason,
|
|
20523
|
+
message_ids: args.rawRebuild.messageIds
|
|
20524
|
+
}
|
|
20525
|
+
} : {},
|
|
20059
20526
|
tool_input_key_orders: args.toolInputKeyOrders ?? toolInputKeyOrders(args.input),
|
|
20060
20527
|
...args.fullArrayFingerprint ? { full_array_fingerprint: args.fullArrayFingerprint } : {},
|
|
20061
20528
|
...args.tailDelta ? {
|
|
@@ -20246,6 +20713,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20246
20713
|
throw error;
|
|
20247
20714
|
} finally {
|
|
20248
20715
|
clock.clearTimeout(timer);
|
|
20716
|
+
invalidateReplayEnvelopeSnapshot(deps.db, args.sessionId);
|
|
20249
20717
|
}
|
|
20250
20718
|
};
|
|
20251
20719
|
const callTransformWithStallProbe = async (args, attemptTimeoutMs) => {
|
|
@@ -20354,6 +20822,24 @@ function createRustModeTransform(deps, options) {
|
|
|
20354
20822
|
logTransformTiming(sessionId, "rust.ordinal_rebuild", startedAt, detail);
|
|
20355
20823
|
}
|
|
20356
20824
|
};
|
|
20825
|
+
const recordRawConflict = (sessionId, error) => {
|
|
20826
|
+
requestRustRawRebuild(deps.db, sessionId, error);
|
|
20827
|
+
dropSlot(sessionId, `raw_replay_${error.reason}`);
|
|
20828
|
+
const state = ensureState(states, sessionId);
|
|
20829
|
+
state.forceFullWire = true;
|
|
20830
|
+
state.parked = false;
|
|
20831
|
+
sessionLog2(sessionId, `raw_replay_rebuild_requested reason=${error.reason} first_changed=${error.firstBlockId}`);
|
|
20832
|
+
};
|
|
20833
|
+
const observeRawReplay = (sessionId, input, served) => {
|
|
20834
|
+
try {
|
|
20835
|
+
checkRustServedRawIngress(deps.db, sessionId, input);
|
|
20836
|
+
noteRustServedRaw(deps.db, sessionId, input, served);
|
|
20837
|
+
} catch (error) {
|
|
20838
|
+
if (error instanceof RustServedRawConflict)
|
|
20839
|
+
recordRawConflict(sessionId, error);
|
|
20840
|
+
throw error;
|
|
20841
|
+
}
|
|
20842
|
+
};
|
|
20357
20843
|
const replayLastGood = (sessionId, currentMessages, output, systemPromptTokens) => {
|
|
20358
20844
|
try {
|
|
20359
20845
|
if (states.get(sessionId)?.markerAdmissionFenced || isRustMarkerAdmissionFenced(deps.db, sessionId))
|
|
@@ -20440,6 +20926,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20440
20926
|
ownDirtyRevision: lkgDirtyRevision(sessionId)
|
|
20441
20927
|
}));
|
|
20442
20928
|
const replayInputCount = currentMessages.length;
|
|
20929
|
+
observeRawReplay(sessionId, currentMessages, replay.messages);
|
|
20443
20930
|
replaceMessagesInPlace(output, replay.messages);
|
|
20444
20931
|
ensureState(states, sessionId).lkgLatestServedDigest = lkgServedArrayDigest(JSON.stringify(replay.messages));
|
|
20445
20932
|
enterLkgReplayFreeze(ensureState(states, sessionId), replayInputCount);
|
|
@@ -20503,7 +20990,10 @@ function createRustModeTransform(deps, options) {
|
|
|
20503
20990
|
const passStampBySession = new Map;
|
|
20504
20991
|
const replayParticipant = {
|
|
20505
20992
|
lastPassStamp: (sessionId) => states.has(sessionId) ? passStampBySession.get(sessionId) : undefined,
|
|
20506
|
-
enterFreezeFromExternalServe: (sessionId,
|
|
20993
|
+
enterFreezeFromExternalServe: (sessionId, inputMessages, servedMessages) => {
|
|
20994
|
+
observeRawReplay(sessionId, inputMessages, servedMessages);
|
|
20995
|
+
enterLkgReplayFreeze(ensureState(states, sessionId), inputMessages.length);
|
|
20996
|
+
},
|
|
20507
20997
|
replayFits: (sessionId, messages, inputMessages) => {
|
|
20508
20998
|
try {
|
|
20509
20999
|
const fit = lkgReplayFits({
|
|
@@ -20649,6 +21139,24 @@ function createRustModeTransform(deps, options) {
|
|
|
20649
21139
|
bindSystemDateRequest(output, dateRequest);
|
|
20650
21140
|
const passObservedAtMs = Date.now();
|
|
20651
21141
|
const state = ensureState(states, sessionId);
|
|
21142
|
+
let rawRebuild;
|
|
21143
|
+
let rawReadError;
|
|
21144
|
+
try {
|
|
21145
|
+
rawRebuild = rustRawRebuild(deps.db, sessionId);
|
|
21146
|
+
try {
|
|
21147
|
+
checkRustServedRawIngress(deps.db, sessionId, messages);
|
|
21148
|
+
} catch (error) {
|
|
21149
|
+
if (!(error instanceof RustServedRawConflict) || !rawRebuild?.pending)
|
|
21150
|
+
throw error;
|
|
21151
|
+
requestRustRawRebuild(deps.db, sessionId, error);
|
|
21152
|
+
rawRebuild = rustRawRebuild(deps.db, sessionId);
|
|
21153
|
+
}
|
|
21154
|
+
} catch (error) {
|
|
21155
|
+
if (error instanceof RustServedRawConflict)
|
|
21156
|
+
throw error;
|
|
21157
|
+
rawReadError = error;
|
|
21158
|
+
}
|
|
21159
|
+
const reconstructRaw = new Set(rawRebuild?.messageIds ?? []);
|
|
20652
21160
|
let entrySlot = getSlot(sessionId);
|
|
20653
21161
|
try {
|
|
20654
21162
|
entrySlot = loadPersistedLkgSlot(deps.db, sessionId, true) ?? entrySlot;
|
|
@@ -20687,6 +21195,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20687
21195
|
let decision = "error";
|
|
20688
21196
|
let materializeReason = "none";
|
|
20689
21197
|
let frozenReleaseReason = null;
|
|
21198
|
+
let frozenReleaseFirstChanged = "unknown";
|
|
20690
21199
|
let schedulerDecision;
|
|
20691
21200
|
let responseCommitted;
|
|
20692
21201
|
let responsePrefixBustPermitted;
|
|
@@ -20712,7 +21221,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20712
21221
|
let recoveryProjectRoot = options.projectRoot ?? deps.directory ?? "";
|
|
20713
21222
|
const passUsageSnapshot = loadContextUsage(deps.contextUsageMap, deps.db, sessionId);
|
|
20714
21223
|
requestInputTokens = Math.max(0, Math.floor(passUsageSnapshot.inputTokens));
|
|
20715
|
-
let preflightError;
|
|
21224
|
+
let preflightError = rawReadError;
|
|
20716
21225
|
let markerAdmissionRecovery = state.markerAdmissionFenced;
|
|
20717
21226
|
try {
|
|
20718
21227
|
markerAdmissionRecovery ||= isRustMarkerAdmissionFenced(deps.db, sessionId);
|
|
@@ -20906,7 +21415,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20906
21415
|
decision,
|
|
20907
21416
|
committed: responseCommitted,
|
|
20908
21417
|
prefixBustPermitted: responsePrefixBustPermitted,
|
|
20909
|
-
reason: materializeReason,
|
|
21418
|
+
reason: applied && served && frozenReleaseReason ? `lkg_frozen_release:${frozenReleaseReason};first_changed=${frozenReleaseFirstChanged};materialize_reason=${materializeReason}` : materializeReason,
|
|
20910
21419
|
schedulerDecision,
|
|
20911
21420
|
schedulerDeferReason,
|
|
20912
21421
|
historianNoFire,
|
|
@@ -20928,7 +21437,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20928
21437
|
materializeReason: materializeReason === "none" ? null : materializeReason,
|
|
20929
21438
|
inputTokens: requestInputTokens,
|
|
20930
21439
|
tsMs: passObservedAtMs,
|
|
20931
|
-
lkgFrozenReleaseReason: applied && served
|
|
21440
|
+
lkgFrozenReleaseReason: applied && served && frozenReleaseReason ? `${frozenReleaseReason};first_changed=${frozenReleaseFirstChanged}` : undefined
|
|
20932
21441
|
});
|
|
20933
21442
|
}
|
|
20934
21443
|
};
|
|
@@ -20963,7 +21472,7 @@ function createRustModeTransform(deps, options) {
|
|
|
20963
21472
|
sessionLog2(sessionId, `rust module stages (slow pass): ${detail}`);
|
|
20964
21473
|
}
|
|
20965
21474
|
};
|
|
20966
|
-
if (state.parked) {
|
|
21475
|
+
if (state.parked && !preflightError) {
|
|
20967
21476
|
state.passesSincePark += 1;
|
|
20968
21477
|
if (!emergencyFailClosed && passUsageSnapshot.percentage < RUST_PARK_PROBE_PRESSURE_BYPASS_PCT && state.passCount % RUST_PARK_RETRY_INTERVAL !== 0) {
|
|
20969
21478
|
decision = "parked";
|
|
@@ -21248,7 +21757,7 @@ function createRustModeTransform(deps, options) {
|
|
|
21248
21757
|
const id = messageIdOf(message) ?? `index:${todoStart + offset}`;
|
|
21249
21758
|
const parts = message.parts?.filter((part) => isRecord3(part) && part.type === "tool" && part.tool === "todowrite");
|
|
21250
21759
|
if (parts?.length) {
|
|
21251
|
-
todoCalls.set(id,
|
|
21760
|
+
todoCalls.set(id, createHash12("sha256").update(JSON.stringify(parts)).digest("hex"));
|
|
21252
21761
|
} else {
|
|
21253
21762
|
todoCalls.delete(id);
|
|
21254
21763
|
}
|
|
@@ -21394,6 +21903,8 @@ function createRustModeTransform(deps, options) {
|
|
|
21394
21903
|
};
|
|
21395
21904
|
let body = buildTransformBody({
|
|
21396
21905
|
sessionId,
|
|
21906
|
+
rawRebuild,
|
|
21907
|
+
servedRawBlockIds: servedRawBlockIds(deps.db, sessionId),
|
|
21397
21908
|
input: encodedInput,
|
|
21398
21909
|
nativeMessages: wireDelta ? messages.slice(wireDelta.rawStart) : messages,
|
|
21399
21910
|
toolInputKeyOrders: toolInputKeyOrders(encodedInput),
|
|
@@ -21593,6 +22104,8 @@ function createRustModeTransform(deps, options) {
|
|
|
21593
22104
|
const retryWireBuildStartedAt = performance.now();
|
|
21594
22105
|
body = buildTransformBody({
|
|
21595
22106
|
sessionId,
|
|
22107
|
+
rawRebuild,
|
|
22108
|
+
servedRawBlockIds: servedRawBlockIds(deps.db, sessionId),
|
|
21596
22109
|
input: retryEncodedInput,
|
|
21597
22110
|
nativeMessages: messages,
|
|
21598
22111
|
toolInputKeyOrders: toolInputKeyOrders(retryEncodedInput),
|
|
@@ -21652,6 +22165,13 @@ function createRustModeTransform(deps, options) {
|
|
|
21652
22165
|
sessionLog2(sessionId, `signed thinking reset fence: ${fenced.length} assistant(s) [${fenced.join(",")}]`);
|
|
21653
22166
|
}
|
|
21654
22167
|
const cacheBustingPass = moduleDecisionBusts;
|
|
22168
|
+
if (rawRebuild?.pending && !moduleDecisionBusts) {
|
|
22169
|
+
throw new EmergencyFailClosedError("Rust raw-rebuild request was not authorized by the module");
|
|
22170
|
+
}
|
|
22171
|
+
if (rawRebuild?.pending) {
|
|
22172
|
+
frozenReleaseReason = `raw_replay_${rawRebuild.reason}`;
|
|
22173
|
+
frozenReleaseFirstChanged = rawRebuild.firstBlockId;
|
|
22174
|
+
}
|
|
21655
22175
|
let frozenReplayReleased = false;
|
|
21656
22176
|
if (markerAdmissionRecovery && !moduleDecisionBusts)
|
|
21657
22177
|
throw new RustTransformProtocolError("rust marker admission recovery: supported prefix_bust_permitted=true required; upgrade ck-mc if unsupported");
|
|
@@ -21683,6 +22203,7 @@ function createRustModeTransform(deps, options) {
|
|
|
21683
22203
|
let appliedMessages = moduleMessages;
|
|
21684
22204
|
let markerStrategyFailure;
|
|
21685
22205
|
let replayedFrozenRepresentation = false;
|
|
22206
|
+
let reconstructedRaw = false;
|
|
21686
22207
|
const boundaryId = response.boundary_id;
|
|
21687
22208
|
if (typeof boundaryId === "string" && boundaryId.length > 0) {
|
|
21688
22209
|
assertNativeBoundary(moduleMessages, sessionId, boundaryId);
|
|
@@ -21727,7 +22248,7 @@ function createRustModeTransform(deps, options) {
|
|
|
21727
22248
|
}
|
|
21728
22249
|
if (recoveryFenceRebuild) {
|
|
21729
22250
|
frozenReplayReleased = true;
|
|
21730
|
-
frozenReleaseReason
|
|
22251
|
+
frozenReleaseReason ??= "lkg_recovery_fence_unproven";
|
|
21731
22252
|
frozenReleaseLastServed = { messages: null, proven: false };
|
|
21732
22253
|
}
|
|
21733
22254
|
if (state.lkgRepresentationFrozen && !shouldAdoptModuleAfterFreeze(moduleDecisionBusts, frozenReplayReleased)) {
|
|
@@ -21792,6 +22313,10 @@ function createRustModeTransform(deps, options) {
|
|
|
21792
22313
|
if (!replayedFrozenRepresentation) {
|
|
21793
22314
|
const outputCloneStartedAt = performance.now();
|
|
21794
22315
|
appliedMessages = cloneModuleNativeOutput(moduleMessages);
|
|
22316
|
+
if (!moduleDecisionBusts || rawRebuild?.pending && rawRebuild.reason.startsWith("candidate")) {
|
|
22317
|
+
const covered = moduleDecisionBusts && typeof response.coverage_ordinal === "number" ? new Set([...state.idOrdinalMemo].filter(([, ordinal]) => ordinal <= Number(response.coverage_ordinal)).map(([id]) => id)) : new Set;
|
|
22318
|
+
reconstructedRaw = preserveRustServedRaw(deps.db, sessionId, appliedMessages, messages, reconstructRaw, covered);
|
|
22319
|
+
}
|
|
21795
22320
|
timings.outputClone += performance.now() - outputCloneStartedAt;
|
|
21796
22321
|
}
|
|
21797
22322
|
pendingWireCache.nativeOutput = moduleMessages;
|
|
@@ -21850,7 +22375,7 @@ function createRustModeTransform(deps, options) {
|
|
|
21850
22375
|
prefixPermissionSupported: permissionSupported,
|
|
21851
22376
|
moduleReasoningTrimOnly: response.reasoning_trim_only === true,
|
|
21852
22377
|
moduleSignedThinkingReset: response.signed_thinking_reset === true,
|
|
21853
|
-
...
|
|
22378
|
+
...moduleDecisionBusts && (passStartedFrozen || frozenReleaseReason || coldStartLastServed) ? { frozenReleaseLastServed } : {},
|
|
21854
22379
|
trailingBlankSourceDecisions,
|
|
21855
22380
|
trailingBlankNewestAssistantId: typeof trailingBlankNewestAssistantId === "string" ? trailingBlankNewestAssistantId : undefined,
|
|
21856
22381
|
tagger: deps.tagger,
|
|
@@ -21861,6 +22386,23 @@ function createRustModeTransform(deps, options) {
|
|
|
21861
22386
|
if (markerStrategyFailure)
|
|
21862
22387
|
throw markerStrategyFailure;
|
|
21863
22388
|
}
|
|
22389
|
+
if (!moduleDecisionBusts && !replayedFrozenRepresentation) {
|
|
22390
|
+
reconstructedRaw = preserveRustServedRaw(deps.db, sessionId, appliedMessages, messages, reconstructRaw) || reconstructedRaw;
|
|
22391
|
+
replayRustModeBindingMismatchStrips2({
|
|
22392
|
+
db: deps.db,
|
|
22393
|
+
sessionId,
|
|
22394
|
+
messages: appliedMessages,
|
|
22395
|
+
resolvedProviderID: model?.providerID
|
|
22396
|
+
});
|
|
22397
|
+
if (servedRawBlockIds(deps.db, sessionId).length > 0 && (!validateLkgSeam([], appliedMessages, model?.providerID ?? null) || model?.providerID === "anthropic" && !validateAnthropicReasoningRuns(appliedMessages.map((message) => ({
|
|
22398
|
+
...message,
|
|
22399
|
+
parts: message.parts.filter((part) => !isRecord3(part) || !["text", "reasoning"].includes(String(part.type)) || part.text !== "")
|
|
22400
|
+
}))))) {
|
|
22401
|
+
throw new RustServedRawConflict("candidate_conflict", [
|
|
22402
|
+
...new Set(servedRawBlockIds(deps.db, sessionId).map((id) => id.replace(/#\d+$/, "")))
|
|
22403
|
+
], servedRawBlockIds(deps.db, sessionId)[0] ?? "unknown");
|
|
22404
|
+
}
|
|
22405
|
+
}
|
|
21864
22406
|
if (typeof boundaryId === "string" && boundaryId.length > 0) {
|
|
21865
22407
|
assertNativeBoundary(appliedMessages, sessionId, boundaryId);
|
|
21866
22408
|
}
|
|
@@ -21896,6 +22438,24 @@ function createRustModeTransform(deps, options) {
|
|
|
21896
22438
|
}
|
|
21897
22439
|
}
|
|
21898
22440
|
logStage(sessionId, "apply", applyStartedAt, timings);
|
|
22441
|
+
if (frozenReleaseReason && frozenReleaseLastServed.messages && [...frozenReleaseLastServed.messages, ...appliedMessages].every((message) => isRecord3(message) && isRecord3(message.info) && Array.isArray(message.parts))) {
|
|
22442
|
+
frozenReleaseFirstChanged = "none";
|
|
22443
|
+
const byId = new Map(appliedMessages.map((message) => [message.info.id, message]));
|
|
22444
|
+
for (const before of frozenReleaseLastServed.messages) {
|
|
22445
|
+
const after = byId.get(before.info.id);
|
|
22446
|
+
const index = before.parts.findIndex((part, i) => JSON.stringify(part) !== JSON.stringify(after?.parts[i]));
|
|
22447
|
+
if (!after || index >= 0) {
|
|
22448
|
+
const blockIndex = index > 0 ? encodeOpenCodeMessagesToCk([
|
|
22449
|
+
{ ...before, parts: before.parts.slice(0, index) }
|
|
22450
|
+
])[0].ck.content.length : 0;
|
|
22451
|
+
frozenReleaseFirstChanged = `${before.info.id}#${blockIndex}`;
|
|
22452
|
+
break;
|
|
22453
|
+
}
|
|
22454
|
+
}
|
|
22455
|
+
}
|
|
22456
|
+
if (replayedFrozenRepresentation || reconstructedRaw) {
|
|
22457
|
+
noteRustServedRaw(deps.db, sessionId, messages, appliedMessages);
|
|
22458
|
+
}
|
|
21899
22459
|
const lkgInputIds = messages.map((message) => message.info.id);
|
|
21900
22460
|
const lkgInputKeys = resolveLkgModelKeys(messages);
|
|
21901
22461
|
const applyReplaceStartedAt = performance.now();
|
|
@@ -22153,6 +22713,9 @@ function createRustModeTransform(deps, options) {
|
|
|
22153
22713
|
}
|
|
22154
22714
|
}
|
|
22155
22715
|
}
|
|
22716
|
+
if (moduleDecisionBusts) {
|
|
22717
|
+
releaseRustServedRaw(deps.db, sessionId, output.messages, rawRebuild?.identity);
|
|
22718
|
+
}
|
|
22156
22719
|
} catch (error) {
|
|
22157
22720
|
if (markerDefinitelyNoCut) {
|
|
22158
22721
|
try {
|
|
@@ -22290,7 +22853,12 @@ function createRustModeTransform(deps, options) {
|
|
|
22290
22853
|
const adapter = {
|
|
22291
22854
|
run: async (sessionId, messages, output, sessionMeta) => {
|
|
22292
22855
|
try {
|
|
22293
|
-
await withSqliteTransformPass2(() => run(sessionId, messages, output, sessionMeta));
|
|
22856
|
+
await withReplayEnvelopeSnapshot(deps.db, sessionId, () => withSqliteTransformPass2(() => run(sessionId, messages, output, sessionMeta)));
|
|
22857
|
+
} catch (error) {
|
|
22858
|
+
if (error instanceof RustServedRawConflict) {
|
|
22859
|
+
recordRawConflict(sessionId, error);
|
|
22860
|
+
}
|
|
22861
|
+
throw error;
|
|
22294
22862
|
} finally {
|
|
22295
22863
|
try {
|
|
22296
22864
|
withoutSqliteTransformPass2(() => resolveHostRunner()?.pump(sessionId));
|
|
@@ -24394,7 +24962,7 @@ function createRustRefusalRecovery(options) {
|
|
|
24394
24962
|
}
|
|
24395
24963
|
|
|
24396
24964
|
// src/hooks/magic-context/system-prompt-hash.ts
|
|
24397
|
-
import { createHash as
|
|
24965
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
24398
24966
|
|
|
24399
24967
|
// src/hooks/magic-context/system-prompt-dates.ts
|
|
24400
24968
|
function replaceHostDates(prompt, replace) {
|
|
@@ -24507,7 +25075,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
24507
25075
|
const dates = systemPromptDates(liveSystemContent, stickyDate);
|
|
24508
25076
|
const currentDate = dates.live;
|
|
24509
25077
|
const stableCandidate = dates.stable;
|
|
24510
|
-
const stableCandidateHash =
|
|
25078
|
+
const stableCandidateHash = createHash13("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
|
|
24511
25079
|
const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
|
|
24512
25080
|
const rewritePermission = systemDateRefreshPermission(deps.historyRefreshSessions, dateRequest);
|
|
24513
25081
|
let deferredDateRefresh = false;
|
|
@@ -24521,7 +25089,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
24521
25089
|
try {
|
|
24522
25090
|
const content = liveElements.join(`
|
|
24523
25091
|
`);
|
|
24524
|
-
const hash =
|
|
25092
|
+
const hash = createHash13("md5").update(promptSurfaceHashMaterial(content, promptSurface.preset)).digest("hex");
|
|
24525
25093
|
updateSessionMeta(deps.db, sessionId, {
|
|
24526
25094
|
systemPromptHash: hash,
|
|
24527
25095
|
cachedM0SystemHash: hash,
|
|
@@ -24561,7 +25129,7 @@ function createSystemPromptHashHandler(deps) {
|
|
|
24561
25129
|
`);
|
|
24562
25130
|
if (!availability.frozen || !modelKey)
|
|
24563
25131
|
return;
|
|
24564
|
-
const currentHash =
|
|
25132
|
+
const currentHash = createHash13("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
|
|
24565
25133
|
recordSystemPromptForRequest(sessionId, currentLkgRequestIdentity(sessionId), currentHash, deps.db, previousHash !== currentHash ? !deps.historyRefreshSessions.has(sessionId) : undefined, deps.historyRefreshSessions, deps.pendingMaterializationSessions);
|
|
24566
25134
|
if (!sessionMetaEarly) {
|
|
24567
25135
|
return;
|
|
@@ -24621,6 +25189,114 @@ function createSystemPromptHashHandler(deps) {
|
|
|
24621
25189
|
};
|
|
24622
25190
|
}
|
|
24623
25191
|
|
|
25192
|
+
// src/shared/recovery-reasoning-prefix.ts
|
|
25193
|
+
function recoveryReasoningPrefixes(messages, partsKey) {
|
|
25194
|
+
const prefixes = [];
|
|
25195
|
+
for (let index = 0;index < messages.length; index++) {
|
|
25196
|
+
const message = messages[index];
|
|
25197
|
+
const parts = message?.[partsKey];
|
|
25198
|
+
if (!Array.isArray(parts))
|
|
25199
|
+
continue;
|
|
25200
|
+
for (let p = 0;p < parts.length; p++) {
|
|
25201
|
+
const type = parts[p]?.type;
|
|
25202
|
+
if (type !== "thinking" && type !== "reasoning" && type !== "redactedThinking" && type !== "redacted_thinking")
|
|
25203
|
+
continue;
|
|
25204
|
+
prefixes.push(JSON.stringify([
|
|
25205
|
+
...messages.slice(0, index),
|
|
25206
|
+
{ ...message, [partsKey]: parts.slice(0, p + 1) }
|
|
25207
|
+
]));
|
|
25208
|
+
}
|
|
25209
|
+
}
|
|
25210
|
+
return prefixes;
|
|
25211
|
+
}
|
|
25212
|
+
|
|
25213
|
+
// src/hooks/magic-context/replay-committed-drops.ts
|
|
25214
|
+
function replayCommittedDrops(db, sessionId, messages) {
|
|
25215
|
+
const original = messages;
|
|
25216
|
+
const reasoningPrefixes = recoveryReasoningPrefixes(messages, "parts");
|
|
25217
|
+
if (reasoningPrefixes.length)
|
|
25218
|
+
messages = structuredClone(messages);
|
|
25219
|
+
const tags = getTagsBySession2(db, sessionId).filter((tag) => tag.status === "dropped");
|
|
25220
|
+
const toolTags = new Map(tags.filter((tag) => tag.type === "tool").map((tag) => [makeToolCompositeKey(tag.toolOwnerMessageId ?? "", tag.messageId), tag]));
|
|
25221
|
+
const textTags = new Map(tags.filter((tag) => tag.type !== "tool").map((tag) => [tag.messageId, tag]));
|
|
25222
|
+
const byNumber = new Map(tags.map((tag) => [tag.tagNumber, tag]));
|
|
25223
|
+
const index = new Map;
|
|
25224
|
+
const owners = new Map;
|
|
25225
|
+
const resolvedOwners = new Map;
|
|
25226
|
+
const ambiguousCalls = new Set;
|
|
25227
|
+
const targets = new Map;
|
|
25228
|
+
let precedingThinking = [];
|
|
25229
|
+
const toolThinking = new Map;
|
|
25230
|
+
const batch = new ToolMutationBatch(messages);
|
|
25231
|
+
for (const message of messages) {
|
|
25232
|
+
if (message.info.role === "user")
|
|
25233
|
+
precedingThinking = [];
|
|
25234
|
+
const thinking = message.parts.filter(isThinkingPart);
|
|
25235
|
+
for (let p = 0;p < message.parts.length; p++) {
|
|
25236
|
+
const part = message.parts[p];
|
|
25237
|
+
const observation = extractToolCallObservation(part);
|
|
25238
|
+
if (observation) {
|
|
25239
|
+
const { callId, kind } = observation;
|
|
25240
|
+
const pending = owners.get(callId) ?? [];
|
|
25241
|
+
if (pending.length > 1)
|
|
25242
|
+
ambiguousCalls.add(callId);
|
|
25243
|
+
const hostingKey = makeToolCompositeKey(message.info.id ?? "", callId);
|
|
25244
|
+
const owner = kind === "invocation" || part.type === "tool" || toolTags.has(hostingKey) ? message.info.id ?? "" : pending.shift() ?? resolvedOwners.get(callId) ?? message.info.id ?? "";
|
|
25245
|
+
if (kind === "invocation")
|
|
25246
|
+
pending.push(owner);
|
|
25247
|
+
else
|
|
25248
|
+
resolvedOwners.set(callId, owner);
|
|
25249
|
+
owners.set(callId, pending);
|
|
25250
|
+
const key = makeToolCompositeKey(owner, callId);
|
|
25251
|
+
if (message.info.role === "tool" && !toolThinking.has(key))
|
|
25252
|
+
toolThinking.set(key, precedingThinking);
|
|
25253
|
+
const entry = index.get(key) ?? { occurrences: [], hasResult: false };
|
|
25254
|
+
entry.occurrences.push({ message, part, kind });
|
|
25255
|
+
entry.hasResult ||= kind === "result" && partHasCompletedResult(part);
|
|
25256
|
+
index.set(key, entry);
|
|
25257
|
+
} else {
|
|
25258
|
+
const prefix = isTextPart(part) ? /^§(\d+)§\s/.exec(part.text) : null;
|
|
25259
|
+
const tag = (prefix ? byNumber.get(Number(prefix[1])) : undefined) ?? textTags.get(`${message.info.id}:p${p}`) ?? textTags.get(`${message.info.id}:file${p}`);
|
|
25260
|
+
if (tag && tag.type !== "tool")
|
|
25261
|
+
targets.set(tag.tagNumber, {
|
|
25262
|
+
message,
|
|
25263
|
+
setContent(content) {
|
|
25264
|
+
if (isTextPart(part)) {
|
|
25265
|
+
if (part.text === content)
|
|
25266
|
+
return false;
|
|
25267
|
+
part.text = content;
|
|
25268
|
+
} else
|
|
25269
|
+
message.parts[p] = { type: "text", text: content };
|
|
25270
|
+
return true;
|
|
25271
|
+
}
|
|
25272
|
+
});
|
|
25273
|
+
}
|
|
25274
|
+
}
|
|
25275
|
+
if (message.info.role === "assistant" && !message.parts.some(isTextPart))
|
|
25276
|
+
precedingThinking = thinking;
|
|
25277
|
+
}
|
|
25278
|
+
const arcsByCall = new Map;
|
|
25279
|
+
for (const entry of index.values()) {
|
|
25280
|
+
const callId = extractToolCallObservation(entry.occurrences[0]?.part)?.callId ?? "";
|
|
25281
|
+
arcsByCall.set(callId, (arcsByCall.get(callId) ?? 0) + 1);
|
|
25282
|
+
}
|
|
25283
|
+
for (const [key, entry] of index) {
|
|
25284
|
+
const callId = extractToolCallObservation(entry.occurrences[0]?.part)?.callId ?? "";
|
|
25285
|
+
if (ambiguousCalls.has(callId))
|
|
25286
|
+
continue;
|
|
25287
|
+
const tag = toolTags.get(key) ?? (arcsByCall.get(callId) === 1 ? toolTags.get(makeToolCompositeKey("", callId)) : undefined);
|
|
25288
|
+
if (tag)
|
|
25289
|
+
targets.set(tag.tagNumber, createToolDropTarget(key, toolThinking.get(key) ?? [], index, batch, tag.tagNumber));
|
|
25290
|
+
}
|
|
25291
|
+
applyFlushedStatuses(sessionId, db, targets, tags);
|
|
25292
|
+
batch.finalize();
|
|
25293
|
+
if (JSON.stringify(recoveryReasoningPrefixes(messages, "parts")) !== JSON.stringify(reasoningPrefixes))
|
|
25294
|
+
return false;
|
|
25295
|
+
if (messages !== original)
|
|
25296
|
+
original.splice(0, original.length, ...messages);
|
|
25297
|
+
return true;
|
|
25298
|
+
}
|
|
25299
|
+
|
|
24624
25300
|
// src/plugin/messages-transform.ts
|
|
24625
25301
|
var ASSISTANT_TERMINAL_RETRY_MESSAGE = "The conversation ends with a completed assistant response and cannot be resubmitted as-is — send a new message to continue.";
|
|
24626
25302
|
|
|
@@ -24763,7 +25439,6 @@ function tryMessagesTransformLkgReplay(args) {
|
|
|
24763
25439
|
sessionLog2(sessionId, "lkg_emergency_armed");
|
|
24764
25440
|
} else {
|
|
24765
25441
|
const inputMessages = output.messages;
|
|
24766
|
-
const inputCount = inputMessages.length;
|
|
24767
25442
|
const keys = resolveLkgModelKeys(inputMessages);
|
|
24768
25443
|
const replay = replayLkg({
|
|
24769
25444
|
sessionId,
|
|
@@ -24782,6 +25457,10 @@ function tryMessagesTransformLkgReplay(args) {
|
|
|
24782
25457
|
sessionLog2(sessionId, "lkg_restart_rebuild_required");
|
|
24783
25458
|
return false;
|
|
24784
25459
|
}
|
|
25460
|
+
if (replay.ok && !rust && !replayCommittedDrops(db, sessionId, replay.messages)) {
|
|
25461
|
+
sessionLog2(sessionId, "lkg_reasoning_prefix_changed");
|
|
25462
|
+
return false;
|
|
25463
|
+
}
|
|
24785
25464
|
let tsFit = true;
|
|
24786
25465
|
if (replay.ok && !rust && keys.providerKey && keys.modelKey) {
|
|
24787
25466
|
const model = {
|
|
@@ -24831,8 +25510,8 @@ function tryMessagesTransformLkgReplay(args) {
|
|
|
24831
25510
|
return false;
|
|
24832
25511
|
retirePendingSystemPromptDelivery(sessionId);
|
|
24833
25512
|
args.onLkgReplay?.();
|
|
25513
|
+
noteExternalLkgReplay(rust, sessionId, inputMessages, replay.messages);
|
|
24834
25514
|
replaceMessagesInPlace2(output, replay.messages);
|
|
24835
|
-
noteExternalLkgReplay(rust, sessionId, inputCount);
|
|
24836
25515
|
sessionLog2(sessionId, "lkg_replay_served");
|
|
24837
25516
|
return true;
|
|
24838
25517
|
} else {
|
|
@@ -25228,7 +25907,7 @@ function resolveCtxExpandMode(args, domain) {
|
|
|
25228
25907
|
}
|
|
25229
25908
|
|
|
25230
25909
|
// src/tools/ctx-expand/render.ts
|
|
25231
|
-
import { createHash as
|
|
25910
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
25232
25911
|
function isRecord4(value) {
|
|
25233
25912
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
25234
25913
|
}
|
|
@@ -25452,11 +26131,61 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
|
|
|
25452
26131
|
const index = scoped ? Number(scoped[2]) : 0;
|
|
25453
26132
|
const piText = message.parts.filter((part) => isRecord4(part) && part.type === "text");
|
|
25454
26133
|
const part = message.parts[index];
|
|
25455
|
-
const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" &&
|
|
26134
|
+
const matching = derived ? piText.filter((part) => isRecord4(part) && typeof part.text === "string" && createHash14("sha256").update(part.text).digest("hex") === derived[3]) : [];
|
|
25456
26135
|
const selected = derived ? matching[Number(derived[4])] : textIndexDomain === "text" ? piText[index] : part;
|
|
25457
26136
|
return selected ? renderPartFull(selected) ?? "" : `Tag ${number}'s original text part is no longer in stored history.`;
|
|
25458
26137
|
}
|
|
25459
26138
|
|
|
26139
|
+
// src/tools/ctx-expand/search-archive.ts
|
|
26140
|
+
function renderSearchArchive(db, sessionId, start, end, tokenBudget, archiveOnly = false) {
|
|
26141
|
+
return withMessageFtsSessionFilter(db, sessionId, (sessionFirst) => {
|
|
26142
|
+
let rawIds;
|
|
26143
|
+
const rows = db.prepare(sessionFirst ? `SELECT f.message_ordinal AS ordinal, f.message_id AS id, f.role, f.content
|
|
26144
|
+
FROM message_fts_rowid_map AS m
|
|
26145
|
+
JOIN message_history_fts AS f ON f.rowid = m.fts_rowid
|
|
26146
|
+
WHERE m.session_id = ?1 AND m.message_ordinal BETWEEN ?2 AND ?3
|
|
26147
|
+
AND f.session_id = ?1 AND f.message_ordinal BETWEEN ?2 AND ?3
|
|
26148
|
+
ORDER BY m.message_ordinal` : `SELECT message_ordinal AS ordinal, message_id AS id, role, content
|
|
26149
|
+
FROM message_history_fts
|
|
26150
|
+
WHERE session_id = ?1 AND message_ordinal BETWEEN ?2 AND ?3
|
|
26151
|
+
ORDER BY CAST(message_ordinal AS INTEGER)`);
|
|
26152
|
+
const blocks = [];
|
|
26153
|
+
let tokens = 0;
|
|
26154
|
+
let lastOrdinal = start - 1;
|
|
26155
|
+
let truncated = false;
|
|
26156
|
+
for (const row of rows.iterate(sessionId, start, end)) {
|
|
26157
|
+
if (!row.content)
|
|
26158
|
+
continue;
|
|
26159
|
+
if (!archiveOnly) {
|
|
26160
|
+
rawIds ??= readRawSessionMessageIdOrdinalsForRange2(sessionId, start, end);
|
|
26161
|
+
if (rawIds.get(row.id) === row.ordinal)
|
|
26162
|
+
continue;
|
|
26163
|
+
}
|
|
26164
|
+
const block = `[${row.ordinal}] ${row.role === "user" ? "U" : "A"}: ${row.content}`;
|
|
26165
|
+
const cost = estimateTokens(block);
|
|
26166
|
+
if (blocks.length > 0 && tokens + cost > tokenBudget) {
|
|
26167
|
+
truncated = true;
|
|
26168
|
+
break;
|
|
26169
|
+
}
|
|
26170
|
+
blocks.push(block);
|
|
26171
|
+
tokens += cost;
|
|
26172
|
+
lastOrdinal = row.ordinal;
|
|
26173
|
+
}
|
|
26174
|
+
if (blocks.length === 0)
|
|
26175
|
+
return null;
|
|
26176
|
+
const text = [
|
|
26177
|
+
"From the search archive: indexed text only; no surrounding messages or tool output.",
|
|
26178
|
+
"",
|
|
26179
|
+
...blocks
|
|
26180
|
+
];
|
|
26181
|
+
if (truncated) {
|
|
26182
|
+
text.push("", `Truncated at message ${lastOrdinal} (budget: ~${tokenBudget} tokens). Call ctx_expand(start=${lastOrdinal + 1}, end=${end}) for more archived text.`);
|
|
26183
|
+
}
|
|
26184
|
+
return text.join(`
|
|
26185
|
+
`);
|
|
26186
|
+
});
|
|
26187
|
+
}
|
|
26188
|
+
|
|
25460
26189
|
// src/tools/ctx-expand/tools.ts
|
|
25461
26190
|
var ctxExpandArgsShape = {
|
|
25462
26191
|
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."),
|
|
@@ -25490,7 +26219,7 @@ function createCtxExpandTool(deps) {
|
|
|
25490
26219
|
return renderItemByTag(deps.db, sessionId, mode.tag);
|
|
25491
26220
|
}
|
|
25492
26221
|
if (mode.kind === "message") {
|
|
25493
|
-
return renderMessageByOrdinal(sessionId, mode.message);
|
|
26222
|
+
return renderSearchArchive(deps.db, sessionId, mode.message, mode.message, CTX_EXPAND_TOKEN_BUDGET) ?? renderMessageByOrdinal(sessionId, mode.message);
|
|
25494
26223
|
}
|
|
25495
26224
|
const { start, end, verbose } = mode;
|
|
25496
26225
|
const lastCompartmentEnd = getLastCompartmentEndMessage(deps.db, sessionId);
|
|
@@ -25498,6 +26227,9 @@ function createCtxExpandTool(deps) {
|
|
|
25498
26227
|
return `Range ${start}-${end} is entirely within the live tail (after the last compacted message ${lastCompartmentEnd}); those messages are already visible in context.`;
|
|
25499
26228
|
}
|
|
25500
26229
|
const effectiveEnd = lastCompartmentEnd >= 0 ? Math.min(end, lastCompartmentEnd) : end;
|
|
26230
|
+
const archived = renderSearchArchive(deps.db, sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET);
|
|
26231
|
+
if (archived)
|
|
26232
|
+
return archived;
|
|
25501
26233
|
if (verbose) {
|
|
25502
26234
|
const v = renderVerboseRange(sessionId, start, effectiveEnd, CTX_EXPAND_TOKEN_BUDGET, deps.expandTools);
|
|
25503
26235
|
if (!v.text) {
|
|
@@ -26353,9 +27085,9 @@ function isMissingError(error) {
|
|
|
26353
27085
|
}
|
|
26354
27086
|
|
|
26355
27087
|
// ../retina-local-fs/src/provider.ts
|
|
26356
|
-
import { execFile as
|
|
26357
|
-
import { promisify as
|
|
26358
|
-
var
|
|
27088
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
27089
|
+
import { promisify as promisify4 } from "node:util";
|
|
27090
|
+
var execFileAsync3 = promisify4(execFile4);
|
|
26359
27091
|
function parseSemver(value) {
|
|
26360
27092
|
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
|
|
26361
27093
|
if (!match) {
|
|
@@ -27004,7 +27736,7 @@ function formatCtxReduceReply(stampedCount, selfStampCount = 0) {
|
|
|
27004
27736
|
return parts.join(" ");
|
|
27005
27737
|
}
|
|
27006
27738
|
// src/tools/ctx-reduce/tools.ts
|
|
27007
|
-
import { createHash as
|
|
27739
|
+
import { createHash as createHash15 } from "node:crypto";
|
|
27008
27740
|
import { tool as tool4 } from "@opencode-ai/plugin";
|
|
27009
27741
|
|
|
27010
27742
|
// src/features/magic-context/range-parser.ts
|
|
@@ -27068,11 +27800,11 @@ function createCtxReduceTool(deps) {
|
|
|
27068
27800
|
const stableId = `oc-${sessionId}-${callId}`;
|
|
27069
27801
|
if (Buffer.byteLength(stableId) <= 128)
|
|
27070
27802
|
return stableId;
|
|
27071
|
-
return `oc-${
|
|
27803
|
+
return `oc-${createHash15("sha256").update(stableId).digest("hex")}`;
|
|
27072
27804
|
}
|
|
27073
27805
|
fallbackCommandSequence += 1;
|
|
27074
27806
|
const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
|
|
27075
|
-
return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${
|
|
27807
|
+
return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash15("sha256").update(monotonicId).digest("hex")}`;
|
|
27076
27808
|
};
|
|
27077
27809
|
return tool4({
|
|
27078
27810
|
description: CTX_REDUCE_DESCRIPTION,
|