@cortexkit/pi-magic-context 0.49.6 → 0.49.8
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-9w5g66at.js → compaction-marker-candidates-n4dphyz4.js} +3 -3
- package/dist/compaction-marker-candidates-worker.js +2 -2
- package/dist/embedding-backfill-chva00z3.js +20 -0
- package/dist/embedding-worker-process.js +6 -2
- package/dist/embedding-worker.js +6 -5
- package/dist/historian-calibration-extension.js +1 -1
- package/dist/{index-j7pa3t4s.js → index-18qe4gs1.js} +113 -27
- package/dist/{index-0j0zqb4t.js → index-3veejgp8.js} +1 -1
- package/dist/{index-0vrkp1jq.js → index-43zqh10z.js} +1 -1
- package/dist/{index-r56xgha8.js → index-4pxydwvg.js} +1 -1
- package/dist/{index-5rc9kvrk.js → index-4vj37yw9.js} +4 -3
- package/dist/{index-fcacf11g.js → index-54r5vs9w.js} +4 -4
- package/dist/{index-cd6bjrj4.js → index-6e3yv1jt.js} +4 -4
- package/dist/{index-swab4319.js → index-729kkhmf.js} +4 -3
- package/dist/{index-gc2749rx.js → index-8yjhda46.js} +9 -6
- package/dist/{index-8vbh4tzw.js → index-asrxgdt4.js} +63 -19
- package/dist/{index-wf7mwdnf.js → index-fdxzpnbj.js} +2 -2
- package/dist/{index-kamhcj15.js → index-gqxsds3q.js} +6 -3
- package/dist/{index-x3dcnxh0.js → index-gycf3sp7.js} +5 -1
- package/dist/{index-kxxdyjfs.js → index-hy44m6jc.js} +1 -1
- package/dist/{index-0p9gemc6.js → index-jsyjxgfy.js} +172 -36
- package/dist/{index-290tzwp1.js → index-kh3jt7t9.js} +1 -1
- package/dist/{index-hfnjfk4d.js → index-pdhbj18g.js} +71 -70
- package/dist/{index-fx0r5485.js → index-qc8e13wc.js} +22 -22
- package/dist/{index-9mn34fnx.js → index-r8cy8hmq.js} +5 -5
- package/dist/{index-57mvvbbh.js → index-rggtvnbg.js} +40 -29
- package/dist/{index-21v1kfs7.js → index-szh001qb.js} +6 -3
- package/dist/{index-cyrnv16r.js → index-ta0ed2nc.js} +2 -0
- package/dist/{index-5z1h0qsa.js → index-tdhppxwd.js} +9 -9
- package/dist/{index-p4matwj0.js → index-v26j81w6.js} +5 -5
- package/dist/{index-mcgehvgw.js → index-zzn7qbps.js} +1 -1
- package/dist/index.js +1071 -390
- package/dist/{logger-j6tecd1h.js → logger-qg51hmp7.js} +1 -1
- package/dist/{message-index-m6snq0fh.js → message-index-1wta074c.js} +14 -14
- package/dist/{message-index-bounded-8a94k72f.js → message-index-bounded-ss3ctdwb.js} +14 -14
- package/dist/{message-time-backfill-xqwg3hg1.js → message-time-backfill-q9s88zdv.js} +3 -3
- package/dist/migration-worker.js +10 -10
- package/dist/{project-embedding-registry-3x6nmszv.js → project-embedding-registry-bxawck58.js} +11 -11
- package/dist/raw-ordinal-warmup-worker.js +17 -15
- package/dist/{read-session-chunk-49e1ayzs.js → read-session-chunk-1jagnq05.js} +11 -9
- package/dist/{read-session-raw-545mgtjz.js → read-session-raw-hm7ptnrh.js} +3 -3
- package/dist/{safe-notification-target-vn9kpmv4.js → safe-notification-target-62ty6rvp.js} +2 -2
- package/dist/{search-q76dp7w9.js → search-x7cachq0.js} +21 -21
- package/dist/{sqlite-wp7wddw3.js → sqlite-adjpy399.js} +3 -1
- package/dist/{storage-memory-7417pbm9.js → storage-memory-axnsk5t1.js} +2 -2
- package/dist/{storage-tags-cvjsrbqh.js → storage-tags-6j5s2q49.js} +5 -5
- package/dist/subagent-entry.js +24 -24
- package/package.json +1 -1
- package/dist/embedding-backfill-809pgwvb.js +0 -20
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
log2,
|
|
16
16
|
sessionLog2,
|
|
17
17
|
flushLogger2
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-gycf3sp7.js";
|
|
19
19
|
import {
|
|
20
20
|
COMPACTION_ENABLED_PATH,
|
|
21
21
|
isDreamerRunnable,
|
|
@@ -168,6 +168,7 @@ import {
|
|
|
168
168
|
readPiSessionMessagePage,
|
|
169
169
|
findRestartModelSeedFromBranch,
|
|
170
170
|
iterateEntriesToRawMessageRange,
|
|
171
|
+
iterateAsyncEntriesToRawMessageRange,
|
|
171
172
|
convertEntriesToRawMessages,
|
|
172
173
|
convertPiAssistantEntryById,
|
|
173
174
|
convertEntriesToRawMessagePage,
|
|
@@ -249,7 +250,7 @@ import {
|
|
|
249
250
|
registerTodoStateLifecycle,
|
|
250
251
|
syncCtxMemoryToolEnabled,
|
|
251
252
|
registerMagicContextTools
|
|
252
|
-
} from "./index-
|
|
253
|
+
} from "./index-jsyjxgfy.js";
|
|
253
254
|
import {
|
|
254
255
|
canonicalModelIdentity,
|
|
255
256
|
piModelRefToCanonical,
|
|
@@ -266,7 +267,7 @@ import {
|
|
|
266
267
|
DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
267
268
|
DREAM_TASK_PROMOTION_DEFAULTS,
|
|
268
269
|
LIVE_RELOAD_CONFIG_PATHS
|
|
269
|
-
} from "./index-
|
|
270
|
+
} from "./index-ta0ed2nc.js";
|
|
270
271
|
import {
|
|
271
272
|
FAIL_CLOSED_DOCTOR_COMMAND,
|
|
272
273
|
formatFailClosedBlockingMessage,
|
|
@@ -289,7 +290,7 @@ import {
|
|
|
289
290
|
openCurrentDatabase,
|
|
290
291
|
openDatabaseAsync,
|
|
291
292
|
closeDatabase
|
|
292
|
-
} from "./index-
|
|
293
|
+
} from "./index-rggtvnbg.js";
|
|
293
294
|
import {
|
|
294
295
|
setHomeProjectPermission,
|
|
295
296
|
ProjectIdentityError,
|
|
@@ -300,7 +301,7 @@ import {
|
|
|
300
301
|
resolveProjectIdentityForSession,
|
|
301
302
|
beginBootQuietPeriod,
|
|
302
303
|
scheduleAfterBootQuiet
|
|
303
|
-
} from "./index-
|
|
304
|
+
} from "./index-gqxsds3q.js";
|
|
304
305
|
import {
|
|
305
306
|
detectThinkingBindingMismatch,
|
|
306
307
|
detectLatestTurnThinkingMismatch,
|
|
@@ -398,6 +399,7 @@ import {
|
|
|
398
399
|
getPendingPiCompactionMarkerState,
|
|
399
400
|
setPendingPiCompactionMarkerState,
|
|
400
401
|
clearPendingPiCompactionMarkerStateIf,
|
|
402
|
+
logPiCompactionMarkerClear,
|
|
401
403
|
getSessionsWithPendingPiMarker,
|
|
402
404
|
setSessionWorkMetrics,
|
|
403
405
|
getSessionWorkMetrics,
|
|
@@ -438,6 +440,7 @@ import {
|
|
|
438
440
|
opaqueThinkingCost,
|
|
439
441
|
SKELETON_REAL_INPUT_MAX_BYTES,
|
|
440
442
|
toolInputStringBytes,
|
|
443
|
+
hasRawMessageProvider2,
|
|
441
444
|
setRawMessageProvider2,
|
|
442
445
|
withRawMessageProvider2,
|
|
443
446
|
cleanUserText2,
|
|
@@ -445,6 +448,7 @@ import {
|
|
|
445
448
|
readRawSessionMessages2,
|
|
446
449
|
getRawSessionMessageOrdinalCount2,
|
|
447
450
|
visitRawSessionMessages2,
|
|
451
|
+
visitRawSessionMessagesAsync2,
|
|
448
452
|
readRawSessionMessageRange2,
|
|
449
453
|
prepareRawSessionOrdinals2,
|
|
450
454
|
primeTailRawMessageCache2,
|
|
@@ -455,7 +459,7 @@ import {
|
|
|
455
459
|
getRawSessionTagKeysThrough2,
|
|
456
460
|
getLegacyProtectedTailStartOrdinal2,
|
|
457
461
|
readSessionChunk2
|
|
458
|
-
} from "./index-
|
|
462
|
+
} from "./index-18qe4gs1.js";
|
|
459
463
|
import {
|
|
460
464
|
UNKNOWN_FIT_RATIO,
|
|
461
465
|
hasMeasuredDecisionCalibration,
|
|
@@ -538,7 +542,7 @@ import {
|
|
|
538
542
|
getToolTagNumberByOwner2,
|
|
539
543
|
getNullOwnerToolTag2,
|
|
540
544
|
adoptNullOwnerToolTag2
|
|
541
|
-
} from "./index-
|
|
545
|
+
} from "./index-54r5vs9w.js";
|
|
542
546
|
import {
|
|
543
547
|
textMentionsRecentCommit,
|
|
544
548
|
hasMeaningfulUserText2,
|
|
@@ -550,8 +554,9 @@ import {
|
|
|
550
554
|
estimateTokens,
|
|
551
555
|
estimateFixedPromptTokens,
|
|
552
556
|
normalizeText
|
|
553
|
-
} from "./index-
|
|
557
|
+
} from "./index-4pxydwvg.js";
|
|
554
558
|
import {
|
|
559
|
+
inRootAsyncContext2,
|
|
555
560
|
Database2,
|
|
556
561
|
getSqliteDatabasePath2,
|
|
557
562
|
withSqliteBackgroundWriter2,
|
|
@@ -562,7 +567,7 @@ import {
|
|
|
562
567
|
isTransientSqliteError2,
|
|
563
568
|
withAsyncPrivilegedWriter2,
|
|
564
569
|
indexCoordinationInput2
|
|
565
|
-
} from "./index-
|
|
570
|
+
} from "./index-asrxgdt4.js";
|
|
566
571
|
import {
|
|
567
572
|
stableStringify,
|
|
568
573
|
closeQuietly,
|
|
@@ -574,7 +579,7 @@ import {
|
|
|
574
579
|
tagRevisionKey,
|
|
575
580
|
tagIdentityRevisionKey,
|
|
576
581
|
TAG_INSERT_CONFLICT_ROWS
|
|
577
|
-
} from "./index-
|
|
582
|
+
} from "./index-zzn7qbps.js";
|
|
578
583
|
import {
|
|
579
584
|
resolveOpenCodeDbPath,
|
|
580
585
|
assertOpenCodeStoreGeneration,
|
|
@@ -587,10 +592,10 @@ import"./index-399p688g.js";
|
|
|
587
592
|
import {
|
|
588
593
|
runSessionWarmupWorker,
|
|
589
594
|
RAW_SUMMARY_TEXT_MAX_CHARS2
|
|
590
|
-
} from "./index-
|
|
595
|
+
} from "./index-4vj37yw9.js";
|
|
591
596
|
import {
|
|
592
597
|
piHarnessKindFromExecutable
|
|
593
|
-
} from "./index-
|
|
598
|
+
} from "./index-3veejgp8.js";
|
|
594
599
|
import {
|
|
595
600
|
BoundedSessionMap,
|
|
596
601
|
LkgRecoveryFenceError,
|
|
@@ -613,13 +618,13 @@ import {
|
|
|
613
618
|
indexSingleMessage2,
|
|
614
619
|
indexMessagesAfterOrdinal2,
|
|
615
620
|
sweepOrphanedOpenCodeMessageIndexes2
|
|
616
|
-
} from "./index-
|
|
621
|
+
} from "./index-tdhppxwd.js";
|
|
617
622
|
import {
|
|
618
623
|
formatSynapseLaneDescriptor
|
|
619
|
-
} from "./index-
|
|
624
|
+
} from "./index-szh001qb.js";
|
|
620
625
|
import {
|
|
621
626
|
sameProjectDirectory
|
|
622
|
-
} from "./index-
|
|
627
|
+
} from "./index-fdxzpnbj.js";
|
|
623
628
|
import {
|
|
624
629
|
buildCanonicalChunkTextFromFts,
|
|
625
630
|
buildCompartmentSummaryFallbackText,
|
|
@@ -629,7 +634,7 @@ import {
|
|
|
629
634
|
replaceCompartmentChunkEmbeddings,
|
|
630
635
|
deleteChunkEmbedBackoffForSession,
|
|
631
636
|
chunkWindowSourceKey
|
|
632
|
-
} from "./index-
|
|
637
|
+
} from "./index-6e3yv1jt.js";
|
|
633
638
|
import {
|
|
634
639
|
recordSessionProjectIdentity,
|
|
635
640
|
GIT_SWEEP_LEASE_RENEWAL_MS,
|
|
@@ -654,7 +659,7 @@ import {
|
|
|
654
659
|
embedSessionCompartmentChunks2,
|
|
655
660
|
getEmbeddingCoverageStatus2,
|
|
656
661
|
getAutoEmbeddingSessionCoverage2
|
|
657
|
-
} from "./index-
|
|
662
|
+
} from "./index-qc8e13wc.js";
|
|
658
663
|
import {
|
|
659
664
|
V2_MEMORY_CATEGORIES
|
|
660
665
|
} from "./index-135e8hvg.js";
|
|
@@ -666,7 +671,7 @@ import {
|
|
|
666
671
|
expandWorkspaceIdentitySetWithAliases,
|
|
667
672
|
sourceNameForMemory,
|
|
668
673
|
computeWorkspaceEpochFingerprint
|
|
669
|
-
} from "./index-
|
|
674
|
+
} from "./index-r8cy8hmq.js";
|
|
670
675
|
import {
|
|
671
676
|
configureContextDatabasePragmas2
|
|
672
677
|
} from "./index-fapenpch.js";
|
|
@@ -716,7 +721,7 @@ import {
|
|
|
716
721
|
normalizeVerificationFiles,
|
|
717
722
|
indexCommitsForProject,
|
|
718
723
|
embedUnembeddedCommits
|
|
719
|
-
} from "./index-
|
|
724
|
+
} from "./index-pdhbj18g.js";
|
|
720
725
|
import {
|
|
721
726
|
setEmbeddingSessionBusy2,
|
|
722
727
|
isEmbeddingHostBusy2
|
|
@@ -740,18 +745,18 @@ import {
|
|
|
740
745
|
setMemoryClassification2,
|
|
741
746
|
archiveMemory2,
|
|
742
747
|
getMemoryCountsByStatus2
|
|
743
|
-
} from "./index-
|
|
748
|
+
} from "./index-hy44m6jc.js";
|
|
744
749
|
import {
|
|
745
750
|
invalidateMemory2
|
|
746
751
|
} from "./index-yhzhdp3m.js";
|
|
747
752
|
import {
|
|
748
753
|
pushNotification2
|
|
749
754
|
} from "./index-q1yc6bs0.js";
|
|
750
|
-
import"./index-
|
|
755
|
+
import"./index-8yjhda46.js";
|
|
751
756
|
import {
|
|
752
757
|
cosineSimilarity
|
|
753
|
-
} from "./index-
|
|
754
|
-
import"./index-
|
|
758
|
+
} from "./index-v26j81w6.js";
|
|
759
|
+
import"./index-729kkhmf.js";
|
|
755
760
|
import {
|
|
756
761
|
buildHiddenAgentRegistrations,
|
|
757
762
|
logTemperatureDecision,
|
|
@@ -759,7 +764,7 @@ import {
|
|
|
759
764
|
SubagentTelemetry,
|
|
760
765
|
readHostSystemPrompt
|
|
761
766
|
} from "./index-zh1jw8qp.js";
|
|
762
|
-
import"./index-
|
|
767
|
+
import"./index-kh3jt7t9.js";
|
|
763
768
|
import {
|
|
764
769
|
__toESM
|
|
765
770
|
} from "./index-22jkk6wg.js";
|
|
@@ -772,7 +777,7 @@ import {
|
|
|
772
777
|
import {
|
|
773
778
|
logSlowWriteTransaction,
|
|
774
779
|
WriteTransactionSteps
|
|
775
|
-
} from "./index-
|
|
780
|
+
} from "./index-43zqh10z.js";
|
|
776
781
|
import {
|
|
777
782
|
setStoragePrivatePermissionEnforcement,
|
|
778
783
|
ensureStorageDirectorySync,
|
|
@@ -2367,7 +2372,7 @@ function observeNoteNudgeServe(args) {
|
|
|
2367
2372
|
sessions.set(args.sessionId, seen);
|
|
2368
2373
|
return {
|
|
2369
2374
|
isFirstServe: warm && args.isLiveTail && firstServe,
|
|
2370
|
-
|
|
2375
|
+
prefixRewriteCoversAnchor: args.anchorMessageId !== null && args.prefixRewriteCoversAnchor
|
|
2371
2376
|
};
|
|
2372
2377
|
}
|
|
2373
2378
|
var NOTE_NUDGE_COOLDOWN_MS = 15 * 60 * 1000;
|
|
@@ -2406,7 +2411,7 @@ function peekNoteNudgeText(db, sessionId, currentUserMessageId, projectIdentity,
|
|
|
2406
2411
|
const state = getPersistedNoteNudge(db, sessionId);
|
|
2407
2412
|
if (!state.triggerPending)
|
|
2408
2413
|
return null;
|
|
2409
|
-
if (eligibility && !eligibility.isFirstServe && !eligibility.
|
|
2414
|
+
if (eligibility && !eligibility.isFirstServe && !eligibility.prefixRewriteCoversAnchor) {
|
|
2410
2415
|
sessionLog2(sessionId, "note-nudge: deferring — user already served or first serve unproven");
|
|
2411
2416
|
return null;
|
|
2412
2417
|
}
|
|
@@ -3327,7 +3332,7 @@ function createNodeHostStallProfiler(deps) {
|
|
|
3327
3332
|
if (stopped || !existsSync5(enablePath))
|
|
3328
3333
|
return;
|
|
3329
3334
|
session = api;
|
|
3330
|
-
api.connect();
|
|
3335
|
+
inRootAsyncContext2(() => api.connect());
|
|
3331
3336
|
await post(api, "Profiler.enable");
|
|
3332
3337
|
await post(api, "Profiler.setSamplingInterval", {
|
|
3333
3338
|
interval: Math.round(options.sampleIntervalMs * 1000)
|
|
@@ -3377,7 +3382,6 @@ function createNodeHostStallProfiler(deps) {
|
|
|
3377
3382
|
isUnavailable: () => unavailable
|
|
3378
3383
|
};
|
|
3379
3384
|
}
|
|
3380
|
-
|
|
3381
3385
|
// ../plugin/src/shared/host-stall-profiler.ts
|
|
3382
3386
|
function hostStallProfilerDir() {
|
|
3383
3387
|
return path7.join(getMagicContextStorageDir(), HOST_PROFILER_DIRNAME);
|
|
@@ -3394,7 +3398,7 @@ function startHostStallProfilerSwitch() {
|
|
|
3394
3398
|
now: () => performance.now(),
|
|
3395
3399
|
wallNow: () => Date.now(),
|
|
3396
3400
|
setInterval: (callback, ms) => {
|
|
3397
|
-
const handle = setInterval(callback, ms);
|
|
3401
|
+
const handle = inRootAsyncContext2(() => setInterval(callback, ms));
|
|
3398
3402
|
handle.unref?.();
|
|
3399
3403
|
return handle;
|
|
3400
3404
|
},
|
|
@@ -3421,7 +3425,7 @@ function startHostStallProfilerSwitch() {
|
|
|
3421
3425
|
// package.json
|
|
3422
3426
|
var package_default = {
|
|
3423
3427
|
name: "@cortexkit/pi-magic-context",
|
|
3424
|
-
version: "0.49.
|
|
3428
|
+
version: "0.49.8",
|
|
3425
3429
|
type: "module",
|
|
3426
3430
|
description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
|
|
3427
3431
|
main: "dist/index.js",
|
|
@@ -9694,7 +9698,7 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisiti
|
|
|
9694
9698
|
}
|
|
9695
9699
|
};
|
|
9696
9700
|
beat();
|
|
9697
|
-
const timer = lost ? undefined : setInterval(() => withSqliteBackgroundWriter2(beat), intervalMs);
|
|
9701
|
+
const timer = lost ? undefined : inRootAsyncContext2(() => setInterval(() => withSqliteBackgroundWriter2(beat), intervalMs));
|
|
9698
9702
|
return {
|
|
9699
9703
|
stop: () => {
|
|
9700
9704
|
if (timer)
|
|
@@ -10320,6 +10324,25 @@ async function runHiddenSingleShotPrompt(args) {
|
|
|
10320
10324
|
});
|
|
10321
10325
|
promptSettled = true;
|
|
10322
10326
|
return { validated: run.validated, completion: run.output, childSessionId: handle.id };
|
|
10327
|
+
} catch (error) {
|
|
10328
|
+
if (args.onFailureOutput) {
|
|
10329
|
+
let timer;
|
|
10330
|
+
try {
|
|
10331
|
+
const completion = await Promise.race([
|
|
10332
|
+
args.executor.collect(handle, 200),
|
|
10333
|
+
new Promise((resolve) => {
|
|
10334
|
+
timer = setTimeout(() => resolve(null), 5000);
|
|
10335
|
+
})
|
|
10336
|
+
]);
|
|
10337
|
+
if (completion)
|
|
10338
|
+
args.onFailureOutput(completion);
|
|
10339
|
+
} catch (readError) {
|
|
10340
|
+
log2(`${args.callContext}: failed to collect interrupted output: ${String(readError)}`);
|
|
10341
|
+
} finally {
|
|
10342
|
+
clearTimeout(timer);
|
|
10343
|
+
}
|
|
10344
|
+
}
|
|
10345
|
+
throw error;
|
|
10323
10346
|
} finally {
|
|
10324
10347
|
await args.executor.close(handle, {
|
|
10325
10348
|
promptSettled,
|
|
@@ -13906,31 +13929,33 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
13906
13929
|
import { createHash as createHash8 } from "node:crypto";
|
|
13907
13930
|
|
|
13908
13931
|
// ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
13932
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
13909
13933
|
import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
|
|
13910
13934
|
import path10 from "node:path";
|
|
13935
|
+
import { promisify as promisify2 } from "node:util";
|
|
13911
13936
|
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.
|
|
13912
13937
|
|
|
13913
13938
|
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.
|
|
13914
13939
|
|
|
13915
|
-
Tools (read-only): read, grep, glob.
|
|
13940
|
+
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.
|
|
13916
13941
|
|
|
13917
13942
|
For each memory decide ONE of:
|
|
13918
|
-
- Backing files found → the
|
|
13943
|
+
- Backing files found → the specific repo-relative paths whose code the memory is about; do not chase every caller or related implementation.
|
|
13919
13944
|
- 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.
|
|
13920
13945
|
|
|
13921
|
-
Output ONE XML manifest
|
|
13946
|
+
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:
|
|
13922
13947
|
<mappings>
|
|
13923
13948
|
<memory id="N" files="path/a.ts,path/b.ts"/>
|
|
13924
13949
|
<memory id="M" independent="true"/>
|
|
13925
13950
|
</mappings>
|
|
13926
13951
|
|
|
13927
13952
|
Rules:
|
|
13928
|
-
- Every input memory id MUST appear exactly once.
|
|
13953
|
+
- Every decided input memory id MUST appear exactly once. Omit uncertain ids rather than inventing backing files or declaring them independent.
|
|
13929
13954
|
- files: repo-relative, comma-separated, no spaces inside a path. Only files that actually exist and genuinely back the memory.
|
|
13930
13955
|
- 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".
|
|
13931
13956
|
- 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.
|
|
13932
13957
|
- Prefer the most specific file(s); do not pad with tangential files. Most memories map to one file; some to a few.
|
|
13933
|
-
-
|
|
13958
|
+
- Mark independent="true" only for the file-independent cases above; an investigation that runs out of calls stays unmapped.`;
|
|
13934
13959
|
var MAX_SEED_PATHS_PER_MEMORY = 3;
|
|
13935
13960
|
var PATH_PATTERN = "`?((?:[\\w.-]+\\/)+[\\w.-]+\\.(?:ts|tsx|js|jsx|mjs|cjs|rs|go|py|json|jsonc|sql|toml|sh))`?";
|
|
13936
13961
|
function extractMemoryCandidatePaths(content, repoDir) {
|
|
@@ -13952,10 +13977,65 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
13952
13977
|
}
|
|
13953
13978
|
return [...found];
|
|
13954
13979
|
}
|
|
13980
|
+
var execFileAsync2 = promisify2(execFile2);
|
|
13981
|
+
async function seedIdentifierCandidates(memories, repoDir) {
|
|
13982
|
+
const identifiers = new Map(memories.filter((memory) => memory.candidates.length === 0).map((memory) => [
|
|
13983
|
+
memory.id,
|
|
13984
|
+
[
|
|
13985
|
+
...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) ?? [])
|
|
13986
|
+
].slice(0, 3)
|
|
13987
|
+
]));
|
|
13988
|
+
const terms = [...new Set([...identifiers.values()].flat())];
|
|
13989
|
+
if (terms.length === 0)
|
|
13990
|
+
return memories;
|
|
13991
|
+
let stdout;
|
|
13992
|
+
try {
|
|
13993
|
+
const result = await execFileAsync2("git", [
|
|
13994
|
+
"-c",
|
|
13995
|
+
"core.quotePath=false",
|
|
13996
|
+
"grep",
|
|
13997
|
+
"--no-color",
|
|
13998
|
+
"-n",
|
|
13999
|
+
"-I",
|
|
14000
|
+
"-F",
|
|
14001
|
+
...terms.flatMap((term) => ["-e", term]),
|
|
14002
|
+
"--",
|
|
14003
|
+
...["ts", "tsx", "js", "jsx", "mjs", "cjs", "rs", "go", "py", "sql", "sh"].map((extension) => `*.${extension}`)
|
|
14004
|
+
], {
|
|
14005
|
+
cwd: repoDir,
|
|
14006
|
+
encoding: "utf8",
|
|
14007
|
+
timeout: 2000,
|
|
14008
|
+
maxBuffer: 256 * 1024,
|
|
14009
|
+
windowsHide: true,
|
|
14010
|
+
killSignal: "SIGKILL"
|
|
14011
|
+
});
|
|
14012
|
+
stdout = result.stdout;
|
|
14013
|
+
} catch {
|
|
14014
|
+
return memories;
|
|
14015
|
+
}
|
|
14016
|
+
const matches = stdout.split(`
|
|
14017
|
+
`).flatMap((line) => {
|
|
14018
|
+
const match = line.match(/^([^:]+):\d+:(.*)$/);
|
|
14019
|
+
return match ? [{ file: match[1], text: match[2] }] : [];
|
|
14020
|
+
});
|
|
14021
|
+
return memories.map((memory) => {
|
|
14022
|
+
const names = identifiers.get(memory.id);
|
|
14023
|
+
if (!names?.length)
|
|
14024
|
+
return memory;
|
|
14025
|
+
const files = new Map;
|
|
14026
|
+
for (const match of matches) {
|
|
14027
|
+
const score = names.filter((name) => match.text.includes(name)).length;
|
|
14028
|
+
if (score)
|
|
14029
|
+
files.set(match.file, Math.max(files.get(match.file) ?? 0, score));
|
|
14030
|
+
}
|
|
14031
|
+
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);
|
|
14032
|
+
return candidates.length ? { ...memory, candidates } : memory;
|
|
14033
|
+
});
|
|
14034
|
+
}
|
|
13955
14035
|
function buildMapMemoriesPrompt(projectPath, memories) {
|
|
13956
14036
|
const list = memories.map((m) => {
|
|
13957
14037
|
const seed = m.candidates.length ? `
|
|
13958
|
-
Likely files (
|
|
14038
|
+
Likely files (candidate paths, confirmed to exist): ${m.candidates.join(", ")}` : "";
|
|
13959
14039
|
return `[${m.id}] ${m.category}
|
|
13960
14040
|
${m.content}${seed}`;
|
|
13961
14041
|
}).join(`
|
|
@@ -13965,13 +14045,13 @@ ${m.content}${seed}`;
|
|
|
13965
14045
|
|
|
13966
14046
|
Project: ${projectPath}
|
|
13967
14047
|
|
|
13968
|
-
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
|
|
14048
|
+
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.
|
|
13969
14049
|
|
|
13970
14050
|
<memories>
|
|
13971
14051
|
${list}
|
|
13972
14052
|
</memories>`;
|
|
13973
14053
|
}
|
|
13974
|
-
var MEMORY_ELEMENT_PATTERN = "<memory\\b([
|
|
14054
|
+
var MEMORY_ELEMENT_PATTERN = "<memory\\b([^<>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
|
|
13975
14055
|
var NESTED_FILE_PATTERN = "<file\\b([^>]*)\\/?>";
|
|
13976
14056
|
function extractNestedFilePaths(inner) {
|
|
13977
14057
|
const files = [];
|
|
@@ -14029,12 +14109,78 @@ function validateMapMemoriesManifest(text, expectedIds) {
|
|
|
14029
14109
|
assertNoDuplicateManifestIds(parsed.filter((entry) => expectedIds.has(entry.id)).map((entry) => entry.id), "mappings");
|
|
14030
14110
|
return parsed;
|
|
14031
14111
|
}
|
|
14112
|
+
function parsePartialMapMemoriesManifest(text, expectedIds) {
|
|
14113
|
+
const start = text.indexOf("<mappings>");
|
|
14114
|
+
if (start < 0)
|
|
14115
|
+
return [];
|
|
14116
|
+
const entries = new Map;
|
|
14117
|
+
const conflicts = new Set;
|
|
14118
|
+
for (const match of text.slice(start).matchAll(new RegExp(MEMORY_ELEMENT_PATTERN, "gi"))) {
|
|
14119
|
+
try {
|
|
14120
|
+
const entry = parseMapMemoriesManifest(`<mappings>${match[0]}</mappings>`)[0];
|
|
14121
|
+
if (!entry || !expectedIds.has(entry.id) || conflicts.has(entry.id))
|
|
14122
|
+
continue;
|
|
14123
|
+
const previous = entries.get(entry.id);
|
|
14124
|
+
if (previous && JSON.stringify(previous) !== JSON.stringify(entry)) {
|
|
14125
|
+
entries.delete(entry.id);
|
|
14126
|
+
conflicts.add(entry.id);
|
|
14127
|
+
} else {
|
|
14128
|
+
entries.set(entry.id, entry);
|
|
14129
|
+
}
|
|
14130
|
+
} catch {}
|
|
14131
|
+
}
|
|
14132
|
+
return [...entries.values()];
|
|
14133
|
+
}
|
|
14032
14134
|
|
|
14033
14135
|
// ../plugin/src/features/magic-context/dreamer/map-memories.ts
|
|
14034
|
-
var MAP_BATCH_SIZE =
|
|
14136
|
+
var MAP_BATCH_SIZE = 5;
|
|
14035
14137
|
var MAP_BATCH_FLOOR_MS = 240000;
|
|
14036
14138
|
var CONSECUTIVE_TIMEOUT_LIMIT2 = 2;
|
|
14037
14139
|
var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
|
|
14140
|
+
function retryKey(project) {
|
|
14141
|
+
return `map-memories:retry:${project}`;
|
|
14142
|
+
}
|
|
14143
|
+
function readRetries(db, project) {
|
|
14144
|
+
try {
|
|
14145
|
+
const parsed = JSON.parse(getDreamState(db, retryKey(project)) ?? "{}");
|
|
14146
|
+
if (!isRecord(parsed))
|
|
14147
|
+
return {};
|
|
14148
|
+
const retries = {};
|
|
14149
|
+
for (const [id, value] of Object.entries(parsed)) {
|
|
14150
|
+
if (isRecord(value) && typeof value.content === "string" && typeof value.failures === "number" && typeof value.deferUntil === "number") {
|
|
14151
|
+
retries[id] = {
|
|
14152
|
+
content: value.content,
|
|
14153
|
+
failures: value.failures,
|
|
14154
|
+
deferUntil: value.deferUntil
|
|
14155
|
+
};
|
|
14156
|
+
}
|
|
14157
|
+
}
|
|
14158
|
+
return retries;
|
|
14159
|
+
} catch {
|
|
14160
|
+
return {};
|
|
14161
|
+
}
|
|
14162
|
+
}
|
|
14163
|
+
function contentKey(memory) {
|
|
14164
|
+
return createHash8("sha256").update(`${memory.category}
|
|
14165
|
+
${memory.content}`).digest("hex");
|
|
14166
|
+
}
|
|
14167
|
+
function isDeferred(memory, retries) {
|
|
14168
|
+
const retry = retries[memory.id];
|
|
14169
|
+
return !!retry && retry.content === contentKey(memory) && retry.deferUntil > Date.now();
|
|
14170
|
+
}
|
|
14171
|
+
function assistantText(messages) {
|
|
14172
|
+
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(`
|
|
14173
|
+
`) : "")).join(`
|
|
14174
|
+
`);
|
|
14175
|
+
}
|
|
14176
|
+
function currentManifest(text) {
|
|
14177
|
+
const start = text.lastIndexOf("<mappings>");
|
|
14178
|
+
return start < 0 ? text : text.slice(start);
|
|
14179
|
+
}
|
|
14180
|
+
function logBatchUsage(messages, committed, startedAt) {
|
|
14181
|
+
const steps = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).length;
|
|
14182
|
+
log2(`[dreamer] map-memories batch: steps=${steps} committed=${committed} steps_per_memory=${committed ? (steps / committed).toFixed(2) : "n/a"} elapsed_ms=${Date.now() - startedAt}`);
|
|
14183
|
+
}
|
|
14038
14184
|
function computeMapBatchSliceMs(remainingMs, batchesRemaining) {
|
|
14039
14185
|
return Math.min(remainingMs, Math.max(MAP_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
|
|
14040
14186
|
}
|
|
@@ -14056,7 +14202,7 @@ function toMapInput(memory, repoDir) {
|
|
|
14056
14202
|
candidates: extractMemoryCandidatePaths(memory.content, repoDir)
|
|
14057
14203
|
};
|
|
14058
14204
|
}
|
|
14059
|
-
function selectMapMemoryInputs(db, projectIdentity, repoDir) {
|
|
14205
|
+
function selectMapMemoryInputs(db, projectIdentity, repoDir, includeDeferred = false) {
|
|
14060
14206
|
const active = getMemoriesByProject2(db, projectIdentity);
|
|
14061
14207
|
const activeIds = active.map((m) => m.id);
|
|
14062
14208
|
const unmapped = new Set(getUnmappedMemoryIds(db, activeIds));
|
|
@@ -14075,7 +14221,8 @@ function selectMapMemoryInputs(db, projectIdentity, repoDir) {
|
|
|
14075
14221
|
if (requeue.length >= MAX_INDEPENDENT_REQUEUE_PER_RUN)
|
|
14076
14222
|
break;
|
|
14077
14223
|
}
|
|
14078
|
-
|
|
14224
|
+
const retries = readRetries(db, projectIdentity);
|
|
14225
|
+
return [...unmappedInputs, ...requeue].filter((memory) => includeDeferred || !isDeferred(memory, retries));
|
|
14079
14226
|
}
|
|
14080
14227
|
async function mapMemories(args) {
|
|
14081
14228
|
const result = {
|
|
@@ -14085,14 +14232,21 @@ async function mapMemories(args) {
|
|
|
14085
14232
|
remaining: 0,
|
|
14086
14233
|
complete: true
|
|
14087
14234
|
};
|
|
14088
|
-
const
|
|
14235
|
+
const allInputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory, true);
|
|
14236
|
+
const retries = readRetries(args.db, args.projectIdentity);
|
|
14237
|
+
const activeIds = new Set(allInputs.map((memory) => String(memory.id)));
|
|
14238
|
+
for (const id of Object.keys(retries))
|
|
14239
|
+
if (!activeIds.has(id))
|
|
14240
|
+
delete retries[id];
|
|
14241
|
+
const inputs = allInputs.filter((memory) => !isDeferred(memory, retries));
|
|
14242
|
+
result.remaining = allInputs.length;
|
|
14243
|
+
result.complete = result.remaining === 0;
|
|
14089
14244
|
if (inputs.length === 0)
|
|
14090
14245
|
return result;
|
|
14091
14246
|
const batches = [];
|
|
14092
14247
|
for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
|
|
14093
14248
|
batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
|
|
14094
14249
|
}
|
|
14095
|
-
result.remaining = inputs.length;
|
|
14096
14250
|
const abortController = new AbortController;
|
|
14097
14251
|
const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, (reason) => abortController.abort(new Error(reason)), args.leaseAcquisition);
|
|
14098
14252
|
try {
|
|
@@ -14115,6 +14269,24 @@ async function mapMemories(args) {
|
|
|
14115
14269
|
break;
|
|
14116
14270
|
const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
|
|
14117
14271
|
const committed = outcome.mapped + outcome.independent;
|
|
14272
|
+
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
14273
|
+
const committedIds = new Set(outcome.committedIds);
|
|
14274
|
+
for (const memory of batch.inputs) {
|
|
14275
|
+
if (committedIds.has(memory.id)) {
|
|
14276
|
+
delete retries[memory.id];
|
|
14277
|
+
continue;
|
|
14278
|
+
}
|
|
14279
|
+
const content = contentKey(memory);
|
|
14280
|
+
const prior = retries[memory.id];
|
|
14281
|
+
const failures = (prior?.content === content ? prior.failures : 0) + 1;
|
|
14282
|
+
retries[memory.id] = {
|
|
14283
|
+
content,
|
|
14284
|
+
failures,
|
|
14285
|
+
deferUntil: failures < 2 ? 0 : Date.now() + Math.min(24, 2 ** (failures - 2)) * 3600000
|
|
14286
|
+
};
|
|
14287
|
+
}
|
|
14288
|
+
setDreamState(args.db, retryKey(args.projectIdentity), JSON.stringify(retries));
|
|
14289
|
+
});
|
|
14118
14290
|
result.mapped += outcome.mapped;
|
|
14119
14291
|
result.independent += outcome.independent;
|
|
14120
14292
|
result.remaining -= committed;
|
|
@@ -14124,8 +14296,8 @@ async function mapMemories(args) {
|
|
|
14124
14296
|
}
|
|
14125
14297
|
if (outcome.requeue?.length) {
|
|
14126
14298
|
if (!batch.isOmissionRetry) {
|
|
14127
|
-
batches.
|
|
14128
|
-
inputs: outcome.requeue,
|
|
14299
|
+
batches.push({
|
|
14300
|
+
inputs: outcome.requeue.filter((memory) => !isDeferred(memory, retries)),
|
|
14129
14301
|
isOmissionRetry: true
|
|
14130
14302
|
});
|
|
14131
14303
|
log2(`[dreamer] map-memories: committed ${committed}/${batch.inputs.length} mapping(s); requeueing ${outcome.requeue.length} omitted id(s) in a targeted retry`);
|
|
@@ -14133,12 +14305,12 @@ async function mapMemories(args) {
|
|
|
14133
14305
|
log2(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
|
|
14134
14306
|
}
|
|
14135
14307
|
}
|
|
14136
|
-
if (outcome.failure?.class === "timeout") {
|
|
14308
|
+
if (outcome.failure?.class === "timeout" && committed === 0) {
|
|
14137
14309
|
consecutiveTimeouts += 1;
|
|
14138
14310
|
timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
|
|
14139
14311
|
if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
|
|
14140
14312
|
result.stopReason = "timeout-circuit-breaker";
|
|
14141
|
-
log2(`[dreamer] map-memories starvation: circuit breaker tripped after ${consecutiveTimeouts} consecutive batch timeouts
|
|
14313
|
+
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`);
|
|
14142
14314
|
break;
|
|
14143
14315
|
}
|
|
14144
14316
|
} else {
|
|
@@ -14158,12 +14330,13 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14158
14330
|
let promptSettled = false;
|
|
14159
14331
|
const startedAt = Date.now();
|
|
14160
14332
|
let budgetFinalized = false;
|
|
14333
|
+
let failedCompletion;
|
|
14161
14334
|
const onBudgetUpdate = (state) => {
|
|
14162
14335
|
budgetFinalized ||= state.finalizeFired;
|
|
14163
14336
|
args.onBudgetUpdate?.(state);
|
|
14164
14337
|
};
|
|
14165
14338
|
try {
|
|
14166
|
-
const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
|
|
14339
|
+
const prompt = buildMapMemoriesPrompt(args.projectIdentity, await seedIdentifierCandidates(batch, args.sessionDirectory));
|
|
14167
14340
|
if (args.hiddenCompletionExecutor) {
|
|
14168
14341
|
const run = await runHiddenSingleShotPrompt({
|
|
14169
14342
|
executor: args.hiddenCompletionExecutor,
|
|
@@ -14179,14 +14352,18 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14179
14352
|
fallbackModels: args.fallbackModels,
|
|
14180
14353
|
timeoutMs: sliceMs,
|
|
14181
14354
|
signal,
|
|
14182
|
-
|
|
14355
|
+
onFailureOutput: (completion) => {
|
|
14356
|
+
failedCompletion = completion;
|
|
14357
|
+
},
|
|
14358
|
+
parse: (text, completion) => validateMapMemoriesManifest(currentManifest(assistantText(completion.messages ?? []) || text), new Set(batch.map((memory) => memory.id)))
|
|
14183
14359
|
});
|
|
14184
14360
|
recordInvocation2(args, startedAt, {
|
|
14185
14361
|
status: "completed",
|
|
14186
14362
|
messages: run.completion.messages ?? []
|
|
14187
14363
|
});
|
|
14188
|
-
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
|
|
14189
|
-
|
|
14364
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
|
|
14365
|
+
logBatchUsage(run.completion.messages ?? [], outcome.mapped + outcome.independent, startedAt);
|
|
14366
|
+
const returnedIds = new Set(outcome.committedIds);
|
|
14190
14367
|
return {
|
|
14191
14368
|
...outcome,
|
|
14192
14369
|
requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
|
|
@@ -14229,7 +14406,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14229
14406
|
fetchOutput: async () => {
|
|
14230
14407
|
const messagesResponse = await client.session.messages({
|
|
14231
14408
|
path: { id: agentSessionId },
|
|
14232
|
-
query: { directory: args.sessionDirectory, limit:
|
|
14409
|
+
query: { directory: args.sessionDirectory, limit: 200 }
|
|
14233
14410
|
});
|
|
14234
14411
|
return normalizeSDKResponse(messagesResponse, [], {
|
|
14235
14412
|
preferResponseOnMissingData: true
|
|
@@ -14239,7 +14416,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14239
14416
|
if (hasLengthCappedOutput(messages)) {
|
|
14240
14417
|
throw new Error("map-memories returned length-capped output");
|
|
14241
14418
|
}
|
|
14242
|
-
const text =
|
|
14419
|
+
const text = currentManifest(assistantText(messages));
|
|
14243
14420
|
if (!text)
|
|
14244
14421
|
throw new Error("map-memories returned no output");
|
|
14245
14422
|
return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
@@ -14247,8 +14424,9 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14247
14424
|
});
|
|
14248
14425
|
promptSettled = true;
|
|
14249
14426
|
recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
|
|
14250
|
-
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
|
|
14251
|
-
|
|
14427
|
+
const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
|
|
14428
|
+
logBatchUsage(run.output, outcome.mapped + outcome.independent, startedAt);
|
|
14429
|
+
const returnedIds = new Set(outcome.committedIds);
|
|
14252
14430
|
return {
|
|
14253
14431
|
...outcome,
|
|
14254
14432
|
requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
|
|
@@ -14256,18 +14434,23 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14256
14434
|
} catch (error) {
|
|
14257
14435
|
const desc = describeError(error);
|
|
14258
14436
|
log2(`[dreamer] map-memories batch failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
14437
|
+
const messages = failedCompletion?.messages ?? await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory) ?? [];
|
|
14259
14438
|
recordInvocation2(args, startedAt, {
|
|
14260
14439
|
status: failedInvocationStatus(error),
|
|
14261
14440
|
error,
|
|
14262
|
-
messages
|
|
14441
|
+
messages
|
|
14263
14442
|
});
|
|
14264
|
-
if (error instanceof DreamerModuleFailureError
|
|
14443
|
+
if (error instanceof DreamerModuleFailureError)
|
|
14265
14444
|
throw error;
|
|
14266
14445
|
if (signal.aborted)
|
|
14267
14446
|
throw error;
|
|
14447
|
+
const recovered = parsePartialMapMemoriesManifest(assistantText(messages) || failedCompletion?.text || "", new Set(batch.map((memory) => memory.id)));
|
|
14448
|
+
const outcome = await applyParsedBatchMappings(args, batch, recovered, budgetFinalized, true);
|
|
14449
|
+
logBatchUsage(messages, outcome.mapped + outcome.independent, startedAt);
|
|
14450
|
+
if (error instanceof DreamTokenBudgetExceeded)
|
|
14451
|
+
throw error;
|
|
14268
14452
|
return {
|
|
14269
|
-
|
|
14270
|
-
independent: 0,
|
|
14453
|
+
...outcome,
|
|
14271
14454
|
failure: {
|
|
14272
14455
|
class: isTimeoutClassError2(error) ? "timeout" : "other",
|
|
14273
14456
|
elapsedMs: Date.now() - startedAt
|
|
@@ -14286,7 +14469,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
14286
14469
|
});
|
|
14287
14470
|
}
|
|
14288
14471
|
}
|
|
14289
|
-
async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false) {
|
|
14472
|
+
async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false, allowPartial = false) {
|
|
14290
14473
|
const batchIds = new Set(batch.map((memory) => memory.id));
|
|
14291
14474
|
const valid = parsed.filter((entry) => batchIds.has(entry.id));
|
|
14292
14475
|
const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
|
|
@@ -14294,14 +14477,14 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
14294
14477
|
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(", ")})`);
|
|
14295
14478
|
}
|
|
14296
14479
|
assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
|
|
14297
|
-
if (!budgetFinalized && valid.length * 2 < batch.length) {
|
|
14480
|
+
if (!allowPartial && !budgetFinalized && valid.length * 2 < batch.length) {
|
|
14298
14481
|
throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
|
|
14299
14482
|
}
|
|
14300
14483
|
if (budgetFinalized && valid.length < batch.length) {
|
|
14301
14484
|
log2(`[dreamer] map-memories: accepted partial manifest after token budget: ${valid.length}/${batch.length}`);
|
|
14302
14485
|
}
|
|
14303
14486
|
if (valid.length === 0)
|
|
14304
|
-
return { mapped: 0, independent: 0 };
|
|
14487
|
+
return { mapped: 0, independent: 0, committedIds: [] };
|
|
14305
14488
|
const planned = [];
|
|
14306
14489
|
const batchById = new Map(batch.map((memory) => [memory.id, memory]));
|
|
14307
14490
|
for (const p of valid) {
|
|
@@ -14350,9 +14533,10 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
14350
14533
|
});
|
|
14351
14534
|
}
|
|
14352
14535
|
if (planned.length === 0)
|
|
14353
|
-
return { mapped: 0, independent: 0 };
|
|
14536
|
+
return { mapped: 0, independent: 0, committedIds: [] };
|
|
14354
14537
|
let mapped = 0;
|
|
14355
14538
|
let independent = 0;
|
|
14539
|
+
const committedIds = [];
|
|
14356
14540
|
if (args.moduleRoute) {
|
|
14357
14541
|
const identities = getModuleMemoryIdentities(args.db, args.projectIdentity, planned.map((item) => item.id));
|
|
14358
14542
|
const rows = planned.map((item) => {
|
|
@@ -14390,19 +14574,22 @@ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = f
|
|
|
14390
14574
|
const accepted = new Set(result.accepted.filter((id) => typeof id === "number"));
|
|
14391
14575
|
for (const item of planned) {
|
|
14392
14576
|
const identity = identities.get(item.id);
|
|
14393
|
-
if (identity && accepted.has(identity.moduleId))
|
|
14577
|
+
if (identity && accepted.has(identity.moduleId)) {
|
|
14394
14578
|
item.independent ? independent += 1 : mapped += 1;
|
|
14579
|
+
committedIds.push(item.id);
|
|
14580
|
+
}
|
|
14395
14581
|
}
|
|
14396
|
-
return { mapped, independent };
|
|
14582
|
+
return { mapped, independent, committedIds };
|
|
14397
14583
|
}
|
|
14398
14584
|
const now = Date.now();
|
|
14399
14585
|
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
14400
14586
|
for (const item of planned) {
|
|
14401
14587
|
recordMemoryMapping(args.db, item.id, item.files, now, item.mappingOrigin);
|
|
14402
14588
|
item.independent ? independent += 1 : mapped += 1;
|
|
14589
|
+
committedIds.push(item.id);
|
|
14403
14590
|
}
|
|
14404
14591
|
});
|
|
14405
|
-
return { mapped, independent };
|
|
14592
|
+
return { mapped, independent, committedIds };
|
|
14406
14593
|
}
|
|
14407
14594
|
function recordInvocation2(args, startedAt, params) {
|
|
14408
14595
|
if (!args.parentSessionId)
|
|
@@ -14670,32 +14857,41 @@ async function promotePrimers(args) {
|
|
|
14670
14857
|
// ../plugin/src/features/magic-context/dreamer/primer-seed.ts
|
|
14671
14858
|
var PRIMER_SEED_CAP_TOKENS = 4000;
|
|
14672
14859
|
function renderUserAndToolOrientation(sessionId, startOrdinal, endOrdinal, capTokens) {
|
|
14860
|
+
const renderer = orientationRenderer(capTokens);
|
|
14861
|
+
visitRawSessionMessages2(sessionId, startOrdinal, endOrdinal, renderer.visit, {
|
|
14862
|
+
summary: true
|
|
14863
|
+
});
|
|
14864
|
+
return renderer.result();
|
|
14865
|
+
}
|
|
14866
|
+
function orientationRenderer(capTokens) {
|
|
14673
14867
|
const lines = [];
|
|
14674
14868
|
let tokens = 0;
|
|
14675
14869
|
let sawMessage = false;
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
|
|
14682
|
-
|
|
14683
|
-
|
|
14684
|
-
|
|
14685
|
-
|
|
14686
|
-
|
|
14687
|
-
const
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
14870
|
+
return {
|
|
14871
|
+
visit: (msg) => {
|
|
14872
|
+
sawMessage = true;
|
|
14873
|
+
const out = [];
|
|
14874
|
+
if (msg.role === "user" && hasMeaningfulUserText2(msg.parts)) {
|
|
14875
|
+
const text = extractTexts2(msg.parts).map((t) => cleanUserText2(t)).map(normalizeText).filter((t) => t.length > 0).join(" / ");
|
|
14876
|
+
if (text)
|
|
14877
|
+
out.push(`U: ${text}`);
|
|
14878
|
+
}
|
|
14879
|
+
for (const tc of extractToolCallSummaries(msg.parts))
|
|
14880
|
+
out.push(tc);
|
|
14881
|
+
for (const line of out) {
|
|
14882
|
+
const lineTokens = estimateTokens(line);
|
|
14883
|
+
if (tokens + lineTokens > capTokens && lines.length > 0) {
|
|
14884
|
+
lines.push("… (orientation truncated; investigate the current source directly)");
|
|
14885
|
+
return false;
|
|
14886
|
+
}
|
|
14887
|
+
lines.push(line);
|
|
14888
|
+
tokens += lineTokens;
|
|
14691
14889
|
}
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
}
|
|
14697
|
-
return sawMessage ? lines.join(`
|
|
14698
|
-
`) : null;
|
|
14890
|
+
return true;
|
|
14891
|
+
},
|
|
14892
|
+
result: () => sawMessage ? lines.join(`
|
|
14893
|
+
`) : null
|
|
14894
|
+
};
|
|
14699
14895
|
}
|
|
14700
14896
|
function selectPrimerOriginCandidate(db, primer) {
|
|
14701
14897
|
return getPrimerCandidatesByIds(db, primer.sourceCandidateIds).filter((candidate) => candidate.projectPath === primer.projectPath).sort((a, b) => b.sourceMessageTime - a.sourceMessageTime || b.id - a.id)[0];
|
|
@@ -14729,16 +14925,37 @@ function closedBookOriginP1(db, sessionId, originStartMessage) {
|
|
|
14729
14925
|
return { orientation, sessionId };
|
|
14730
14926
|
}
|
|
14731
14927
|
function buildPrimerSeed(db, primer) {
|
|
14928
|
+
return buildPrimerSeedUsing(db, selectPrimerOriginCandidate(db, primer), renderUserAndToolOrientation);
|
|
14929
|
+
}
|
|
14930
|
+
async function buildPrimerSeedAsync(db, primer) {
|
|
14732
14931
|
const mostRecent = selectPrimerOriginCandidate(db, primer);
|
|
14932
|
+
let orientation = null;
|
|
14933
|
+
if (mostRecent && typeof mostRecent.sourceCompartmentStart === "number" && typeof mostRecent.sourceCompartmentEnd === "number") {
|
|
14934
|
+
try {
|
|
14935
|
+
const renderer = orientationRenderer(PRIMER_SEED_CAP_TOKENS);
|
|
14936
|
+
await visitRawSessionMessagesAsync2(mostRecent.sessionId, mostRecent.sourceCompartmentStart, mostRecent.sourceCompartmentEnd, renderer.visit, { summary: true });
|
|
14937
|
+
orientation = renderer.result();
|
|
14938
|
+
} catch {
|
|
14939
|
+
orientation = null;
|
|
14940
|
+
}
|
|
14941
|
+
}
|
|
14942
|
+
return buildPrimerSeedUsing(db, mostRecent, () => orientation);
|
|
14943
|
+
}
|
|
14944
|
+
function buildPrimerSeedUsing(db, mostRecent, render) {
|
|
14733
14945
|
if (!mostRecent || typeof mostRecent.sourceCompartmentStart !== "number" || typeof mostRecent.sourceCompartmentEnd !== "number") {
|
|
14734
|
-
return {
|
|
14946
|
+
return {
|
|
14947
|
+
kind: "closed-book",
|
|
14948
|
+
orientation: "",
|
|
14949
|
+
prePost: "",
|
|
14950
|
+
sessionId: null
|
|
14951
|
+
};
|
|
14735
14952
|
}
|
|
14736
14953
|
const sessionId = mostRecent.sessionId;
|
|
14737
14954
|
const start = mostRecent.sourceCompartmentStart;
|
|
14738
14955
|
const end = mostRecent.sourceCompartmentEnd;
|
|
14739
14956
|
let orientation = null;
|
|
14740
14957
|
try {
|
|
14741
|
-
orientation =
|
|
14958
|
+
orientation = render(sessionId, start, end, PRIMER_SEED_CAP_TOKENS);
|
|
14742
14959
|
} catch {
|
|
14743
14960
|
orientation = null;
|
|
14744
14961
|
}
|
|
@@ -14869,14 +15086,14 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
14869
15086
|
provider = null;
|
|
14870
15087
|
}
|
|
14871
15088
|
}
|
|
14872
|
-
const seed =
|
|
15089
|
+
const seed = await (async () => {
|
|
14873
15090
|
const unregister = provider && originSessionId ? setRawMessageProvider2(originSessionId, provider) : null;
|
|
14874
15091
|
try {
|
|
14875
|
-
return buildPrimerSeed(args.db, primer);
|
|
15092
|
+
return provider?.iterateMessageRangeAsync ? await buildPrimerSeedAsync(args.db, primer) : withRawSessionMessageCache2(() => buildPrimerSeed(args.db, primer));
|
|
14876
15093
|
} finally {
|
|
14877
15094
|
unregister?.();
|
|
14878
15095
|
}
|
|
14879
|
-
});
|
|
15096
|
+
})();
|
|
14880
15097
|
let agentSessionId = null;
|
|
14881
15098
|
let promptSettled = false;
|
|
14882
15099
|
const startedAt = Date.now();
|
|
@@ -14892,7 +15109,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
14892
15109
|
prompt,
|
|
14893
15110
|
title: "magic-context-dream-refresh-primers",
|
|
14894
15111
|
callContext: "dreamer:refresh-primers",
|
|
14895
|
-
metadata: {
|
|
15112
|
+
metadata: {
|
|
15113
|
+
tokenBudget: args.tokenBudget,
|
|
15114
|
+
onBudgetUpdate: args.onBudgetUpdate
|
|
15115
|
+
},
|
|
14896
15116
|
model: args.model,
|
|
14897
15117
|
fallbackModels: args.fallbackModels,
|
|
14898
15118
|
language: args.language,
|
|
@@ -14958,7 +15178,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
14958
15178
|
validateOutput: (messages) => parseAnswer(messages, primer.answer)
|
|
14959
15179
|
});
|
|
14960
15180
|
promptSettled = true;
|
|
14961
|
-
recordInvocation3(args, startedAt, {
|
|
15181
|
+
recordInvocation3(args, startedAt, {
|
|
15182
|
+
status: "completed",
|
|
15183
|
+
messages: run.output
|
|
15184
|
+
});
|
|
14962
15185
|
const answer = run.validated.trim();
|
|
14963
15186
|
if (!answer)
|
|
14964
15187
|
return false;
|
|
@@ -14973,7 +15196,10 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
14973
15196
|
} catch (error) {
|
|
14974
15197
|
const desc = describeError(error);
|
|
14975
15198
|
log2(`[dreamer] refresh-primers failed (primer #${primer.id}): ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
|
|
14976
|
-
recordInvocation3(args, startedAt, {
|
|
15199
|
+
recordInvocation3(args, startedAt, {
|
|
15200
|
+
status: failedInvocationStatus(error),
|
|
15201
|
+
error
|
|
15202
|
+
});
|
|
14977
15203
|
throw error;
|
|
14978
15204
|
} finally {
|
|
14979
15205
|
if (agentSessionId && args.client)
|
|
@@ -15587,9 +15813,9 @@ function insertDreamRun(db, run) {
|
|
|
15587
15813
|
import { createHash as createHash9 } from "node:crypto";
|
|
15588
15814
|
|
|
15589
15815
|
// ../plugin/src/features/magic-context/dreamer/verify-diff.ts
|
|
15590
|
-
import { execFile as
|
|
15591
|
-
import { promisify as
|
|
15592
|
-
var exec =
|
|
15816
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
15817
|
+
import { promisify as promisify3 } from "node:util";
|
|
15818
|
+
var exec = promisify3(execFile3);
|
|
15593
15819
|
var VERIFY_DIFF_BUDGET_TOKENS = 12000;
|
|
15594
15820
|
var MAX_DIFF_BYTES = 4 * 1024 * 1024;
|
|
15595
15821
|
async function git2(root, args) {
|
|
@@ -18401,10 +18627,10 @@ async function sourceReady(source, sessionId) {
|
|
|
18401
18627
|
function defer(fn) {
|
|
18402
18628
|
const immediate = globalThis.setImmediate;
|
|
18403
18629
|
if (typeof immediate === "function") {
|
|
18404
|
-
immediate(fn);
|
|
18630
|
+
inRootAsyncContext2(() => immediate(fn));
|
|
18405
18631
|
return;
|
|
18406
18632
|
}
|
|
18407
|
-
setTimeout(fn, 0);
|
|
18633
|
+
inRootAsyncContext2(() => setTimeout(fn, 0));
|
|
18408
18634
|
}
|
|
18409
18635
|
function yieldToEventLoop() {
|
|
18410
18636
|
return new Promise((resolve) => defer(resolve));
|
|
@@ -18481,14 +18707,14 @@ function scheduleReconciliation(db, sessionId, readMessages) {
|
|
|
18481
18707
|
reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
|
|
18482
18708
|
if (ran)
|
|
18483
18709
|
return;
|
|
18484
|
-
setTimeout(() => {
|
|
18710
|
+
inRootAsyncContext2(() => setTimeout(() => {
|
|
18485
18711
|
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
18486
18712
|
scheduleReconciliation(db, sessionId, readMessages);
|
|
18487
|
-
}, PREPARE_RETRY_MS).unref?.();
|
|
18713
|
+
}, PREPARE_RETRY_MS)).unref?.();
|
|
18488
18714
|
}).catch((error) => {
|
|
18489
18715
|
logIndexingError(sessionId, "reconciliation", error);
|
|
18490
18716
|
if (isDatabaseLockedError(error))
|
|
18491
|
-
setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000).unref();
|
|
18717
|
+
inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
|
|
18492
18718
|
}).finally(() => {
|
|
18493
18719
|
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
18494
18720
|
});
|
|
@@ -18503,7 +18729,7 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
|
18503
18729
|
const activeTimer = heapHolder.incrementalTimers.get(schedulingKey);
|
|
18504
18730
|
if (activeTimer)
|
|
18505
18731
|
clearTimeout(activeTimer);
|
|
18506
|
-
const timer = setTimeout(() => {
|
|
18732
|
+
const timer = inRootAsyncContext2(() => setTimeout(() => {
|
|
18507
18733
|
heapHolder.incrementalTimers.delete(schedulingKey);
|
|
18508
18734
|
heapHolder.pendingIncrementalKeys.add(schedulingKey);
|
|
18509
18735
|
const indexMessage = async () => {
|
|
@@ -18547,7 +18773,7 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
|
18547
18773
|
if ((sessionEpochs.get(sessionId) ?? 0) === epoch)
|
|
18548
18774
|
heapHolder.pendingIncrementalKeys.delete(schedulingKey);
|
|
18549
18775
|
});
|
|
18550
|
-
}, INCREMENTAL_DEBOUNCE_MS);
|
|
18776
|
+
}, INCREMENTAL_DEBOUNCE_MS));
|
|
18551
18777
|
heapHolder.incrementalTimers.set(schedulingKey, timer);
|
|
18552
18778
|
}
|
|
18553
18779
|
async function indexSingleMessageOffThread(db, sessionId, message) {
|
|
@@ -18721,7 +18947,7 @@ async function startDreamScheduleTimer(args) {
|
|
|
18721
18947
|
startupTickTimer = null;
|
|
18722
18948
|
runTick("startup");
|
|
18723
18949
|
});
|
|
18724
|
-
const timer = setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS);
|
|
18950
|
+
const timer = inRootAsyncContext2(() => setInterval(() => runTick("interval"), DREAM_TIMER_INTERVAL_MS));
|
|
18725
18951
|
if (typeof timer === "object" && "unref" in timer) {
|
|
18726
18952
|
timer.unref();
|
|
18727
18953
|
}
|
|
@@ -19017,7 +19243,7 @@ async function runCompiledSmartNoteSweep(reg, db) {
|
|
|
19017
19243
|
}
|
|
19018
19244
|
}
|
|
19019
19245
|
function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
|
|
19020
|
-
const timer = setInterval(() => {
|
|
19246
|
+
const timer = inRootAsyncContext2(() => setInterval(() => {
|
|
19021
19247
|
try {
|
|
19022
19248
|
if (!renewGitSweepLease(db, projectIdentity, holderId)) {
|
|
19023
19249
|
log2(`[git-commits] sweep lease renewal failed for ${projectIdentity}`);
|
|
@@ -19025,7 +19251,7 @@ function startGitSweepLeaseRenewal(db, projectIdentity, holderId) {
|
|
|
19025
19251
|
} catch (error) {
|
|
19026
19252
|
log2(`[git-commits] sweep lease renewal errored for ${projectIdentity}: ${error instanceof Error ? error.message : String(error)}`);
|
|
19027
19253
|
}
|
|
19028
|
-
}, GIT_SWEEP_LEASE_RENEWAL_MS);
|
|
19254
|
+
}, GIT_SWEEP_LEASE_RENEWAL_MS));
|
|
19029
19255
|
timer.unref?.();
|
|
19030
19256
|
return () => clearInterval(timer);
|
|
19031
19257
|
}
|
|
@@ -19906,11 +20132,19 @@ class PiSubagentRunner {
|
|
|
19906
20132
|
});
|
|
19907
20133
|
return new Promise((resolve) => {
|
|
19908
20134
|
let accountingMessages = [];
|
|
20135
|
+
let mappingMessages = [];
|
|
20136
|
+
const isMemoryMapper = options.agent.replace(/^magic-context-/, "") === "dreamer-memory-mapper";
|
|
19909
20137
|
let settled = false;
|
|
19910
20138
|
const settle = (result) => {
|
|
19911
20139
|
if (settled)
|
|
19912
20140
|
return;
|
|
19913
20141
|
settled = true;
|
|
20142
|
+
if (isMemoryMapper) {
|
|
20143
|
+
result = {
|
|
20144
|
+
...result,
|
|
20145
|
+
meta: { ...result.meta, mappingMessages: [...mappingMessages] }
|
|
20146
|
+
};
|
|
20147
|
+
}
|
|
19914
20148
|
if (accountingMessages.length > 0 && /historian|dreamer|classify/i.test(options.agent)) {
|
|
19915
20149
|
const last = [...accountingMessages].reverse().find((message) => message !== null && typeof message === "object" && message.role === "assistant");
|
|
19916
20150
|
const responseChars = result.ok ? result.assistantText.length : last?.content?.filter((part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string").reduce((sum, part) => sum + part.text.length, 0) ?? 0;
|
|
@@ -19943,7 +20177,7 @@ class PiSubagentRunner {
|
|
|
19943
20177
|
const parentEnv = { ...process.env };
|
|
19944
20178
|
delete parentEnv.MAGIC_CONTEXT_HISTORIAN_TEMPERATURE;
|
|
19945
20179
|
try {
|
|
19946
|
-
child = this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...this.extraArgs, ...args], {
|
|
20180
|
+
child = inRootAsyncContext2(() => this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...this.extraArgs, ...args], {
|
|
19947
20181
|
windowsHide: true,
|
|
19948
20182
|
cwd: options.cwd,
|
|
19949
20183
|
env: {
|
|
@@ -19964,7 +20198,7 @@ class PiSubagentRunner {
|
|
|
19964
20198
|
"pipe",
|
|
19965
20199
|
"pipe"
|
|
19966
20200
|
]
|
|
19967
|
-
});
|
|
20201
|
+
}));
|
|
19968
20202
|
} catch (error) {
|
|
19969
20203
|
cleanupSystemPromptFile();
|
|
19970
20204
|
settle({
|
|
@@ -20103,6 +20337,12 @@ class PiSubagentRunner {
|
|
|
20103
20337
|
if (typeof event !== "object" || event === null)
|
|
20104
20338
|
return;
|
|
20105
20339
|
const e = event;
|
|
20340
|
+
if (isMemoryMapper) {
|
|
20341
|
+
if (e.type === "message_end" && e.message)
|
|
20342
|
+
mappingMessages.push(e.message);
|
|
20343
|
+
if (e.type === "agent_end" && Array.isArray(e.messages))
|
|
20344
|
+
mappingMessages = e.messages;
|
|
20345
|
+
}
|
|
20106
20346
|
if (rpcBudget && e.type === "response" && event.success === false) {
|
|
20107
20347
|
const reply = event;
|
|
20108
20348
|
if (reply.command === "prompt" || reply.command === "steer" && !sawAgentEnd) {
|
|
@@ -20722,7 +20962,9 @@ import { join as join13 } from "node:path";
|
|
|
20722
20962
|
|
|
20723
20963
|
// src/dreamer/bounded-session-reader.ts
|
|
20724
20964
|
import { closeSync, opendirSync, openSync, readSync } from "node:fs";
|
|
20965
|
+
import { open as open4, opendir } from "node:fs/promises";
|
|
20725
20966
|
import { join as join11 } from "node:path";
|
|
20967
|
+
import { setImmediate as yieldToHost } from "node:timers/promises";
|
|
20726
20968
|
var MAX_ENTRY_BYTES = 1024 * 1024;
|
|
20727
20969
|
var OVERSIZED_HEAD_BYTES = 64 * 1024;
|
|
20728
20970
|
var OVERSIZED_TAIL_BYTES = 4 * 1024;
|
|
@@ -20793,86 +21035,107 @@ function lastMatch(text, pattern) {
|
|
|
20793
21035
|
last = match[1];
|
|
20794
21036
|
return last;
|
|
20795
21037
|
}
|
|
21038
|
+
|
|
21039
|
+
class LineDecoder {
|
|
21040
|
+
pending = Buffer.alloc(0);
|
|
21041
|
+
oversized = null;
|
|
21042
|
+
*append(buffer) {
|
|
21043
|
+
const bytes = buffer.length;
|
|
21044
|
+
let start = 0;
|
|
21045
|
+
for (let i = 0;i < bytes; i++) {
|
|
21046
|
+
if (buffer[i] !== 10)
|
|
21047
|
+
continue;
|
|
21048
|
+
const piece = buffer.subarray(start, i);
|
|
21049
|
+
if (this.oversized) {
|
|
21050
|
+
yield this.oversized.append(piece).stub();
|
|
21051
|
+
this.oversized = null;
|
|
21052
|
+
} else if (this.pending.length + piece.length > MAX_ENTRY_BYTES) {
|
|
21053
|
+
yield new OversizedLine().append(this.pending).append(piece).stub();
|
|
21054
|
+
} else {
|
|
21055
|
+
yield Buffer.concat([this.pending, piece]).toString("utf8");
|
|
21056
|
+
}
|
|
21057
|
+
this.pending = Buffer.alloc(0);
|
|
21058
|
+
start = i + 1;
|
|
21059
|
+
}
|
|
21060
|
+
const rest = buffer.subarray(start, bytes);
|
|
21061
|
+
if (this.oversized) {
|
|
21062
|
+
this.oversized.append(rest);
|
|
21063
|
+
} else if (this.pending.length + rest.length > MAX_ENTRY_BYTES) {
|
|
21064
|
+
this.oversized = new OversizedLine().append(this.pending).append(rest);
|
|
21065
|
+
this.pending = Buffer.alloc(0);
|
|
21066
|
+
} else {
|
|
21067
|
+
this.pending = Buffer.concat([this.pending, rest]);
|
|
21068
|
+
}
|
|
21069
|
+
}
|
|
21070
|
+
*finish() {
|
|
21071
|
+
if (this.oversized)
|
|
21072
|
+
yield this.oversized.stub();
|
|
21073
|
+
else if (this.pending.length)
|
|
21074
|
+
yield this.pending.toString("utf8");
|
|
21075
|
+
}
|
|
21076
|
+
}
|
|
20796
21077
|
function* lines(path) {
|
|
20797
21078
|
const fd = openSync(path, "r");
|
|
20798
21079
|
const buffer = Buffer.alloc(64 * 1024);
|
|
20799
|
-
|
|
20800
|
-
let oversized = null;
|
|
21080
|
+
const decoder = new LineDecoder;
|
|
20801
21081
|
try {
|
|
20802
21082
|
while (true) {
|
|
20803
21083
|
const bytes = readSync(fd, buffer, 0, buffer.length, null);
|
|
20804
21084
|
if (bytes === 0)
|
|
20805
21085
|
break;
|
|
20806
|
-
|
|
20807
|
-
for (let i = 0;i < bytes; i++) {
|
|
20808
|
-
if (buffer[i] !== 10)
|
|
20809
|
-
continue;
|
|
20810
|
-
const piece = buffer.subarray(start, i);
|
|
20811
|
-
if (oversized) {
|
|
20812
|
-
yield oversized.append(piece).stub();
|
|
20813
|
-
oversized = null;
|
|
20814
|
-
} else if (pending.length + piece.length > MAX_ENTRY_BYTES) {
|
|
20815
|
-
yield new OversizedLine().append(pending).append(piece).stub();
|
|
20816
|
-
} else {
|
|
20817
|
-
yield Buffer.concat([pending, piece]).toString("utf8");
|
|
20818
|
-
}
|
|
20819
|
-
pending = Buffer.alloc(0);
|
|
20820
|
-
start = i + 1;
|
|
20821
|
-
}
|
|
20822
|
-
const rest = buffer.subarray(start, bytes);
|
|
20823
|
-
if (oversized) {
|
|
20824
|
-
oversized.append(rest);
|
|
20825
|
-
} else if (pending.length + rest.length > MAX_ENTRY_BYTES) {
|
|
20826
|
-
oversized = new OversizedLine().append(pending).append(rest);
|
|
20827
|
-
pending = Buffer.alloc(0);
|
|
20828
|
-
} else {
|
|
20829
|
-
pending = Buffer.concat([pending, rest]);
|
|
20830
|
-
}
|
|
21086
|
+
yield* decoder.append(buffer.subarray(0, bytes));
|
|
20831
21087
|
}
|
|
20832
|
-
|
|
20833
|
-
yield oversized.stub();
|
|
20834
|
-
else if (pending.length)
|
|
20835
|
-
yield pending.toString("utf8");
|
|
21088
|
+
yield* decoder.finish();
|
|
20836
21089
|
} finally {
|
|
20837
21090
|
closeSync(fd);
|
|
20838
21091
|
}
|
|
20839
21092
|
}
|
|
21093
|
+
async function* asyncLines(path) {
|
|
21094
|
+
const file = await open4(path, "r");
|
|
21095
|
+
const buffer = Buffer.alloc(64 * 1024);
|
|
21096
|
+
const decoder = new LineDecoder;
|
|
21097
|
+
try {
|
|
21098
|
+
while (true) {
|
|
21099
|
+
const { bytesRead } = await file.read(buffer, 0, buffer.length, null);
|
|
21100
|
+
if (bytesRead === 0)
|
|
21101
|
+
break;
|
|
21102
|
+
yield* decoder.append(buffer.subarray(0, bytesRead));
|
|
21103
|
+
await yieldToHost();
|
|
21104
|
+
}
|
|
21105
|
+
yield* decoder.finish();
|
|
21106
|
+
} finally {
|
|
21107
|
+
await file.close();
|
|
21108
|
+
}
|
|
21109
|
+
}
|
|
20840
21110
|
function record(value) {
|
|
20841
21111
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
20842
21112
|
}
|
|
20843
|
-
function*
|
|
21113
|
+
async function* asyncSessionEntries(path) {
|
|
21114
|
+
for await (const line of asyncLines(path)) {
|
|
21115
|
+
try {
|
|
21116
|
+
yield JSON.parse(line);
|
|
21117
|
+
} catch {}
|
|
21118
|
+
}
|
|
21119
|
+
}
|
|
21120
|
+
async function* asyncSessionFiles(directory, nested) {
|
|
20844
21121
|
let dir;
|
|
20845
21122
|
try {
|
|
20846
|
-
dir =
|
|
21123
|
+
dir = await opendir(directory);
|
|
20847
21124
|
} catch {
|
|
20848
21125
|
return;
|
|
20849
21126
|
}
|
|
20850
|
-
|
|
20851
|
-
|
|
20852
|
-
|
|
20853
|
-
|
|
20854
|
-
|
|
20855
|
-
|
|
20856
|
-
if (entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
20857
|
-
yield path;
|
|
20858
|
-
else if (nested && entry.isDirectory())
|
|
20859
|
-
yield* sessionFiles(path, false);
|
|
20860
|
-
}
|
|
20861
|
-
} finally {
|
|
20862
|
-
dir.closeSync();
|
|
20863
|
-
}
|
|
20864
|
-
}
|
|
20865
|
-
function findSession(directory, nested, sessionId) {
|
|
20866
|
-
for (const header of sessionHeaders(directory, nested)) {
|
|
20867
|
-
if (header.id === sessionId)
|
|
20868
|
-
return header.path;
|
|
21127
|
+
for await (const entry of dir) {
|
|
21128
|
+
const path = join11(directory, entry.name);
|
|
21129
|
+
if (entry.isFile() && entry.name.endsWith(".jsonl"))
|
|
21130
|
+
yield path;
|
|
21131
|
+
else if (nested && entry.isDirectory())
|
|
21132
|
+
yield* asyncSessionFiles(path, false);
|
|
20869
21133
|
}
|
|
20870
|
-
return null;
|
|
20871
21134
|
}
|
|
20872
|
-
function*
|
|
20873
|
-
for (const path of
|
|
21135
|
+
async function* asyncSessionHeaders(directory, nested) {
|
|
21136
|
+
for await (const path of asyncSessionFiles(directory, nested)) {
|
|
20874
21137
|
try {
|
|
20875
|
-
for (const line of
|
|
21138
|
+
for await (const line of asyncLines(path)) {
|
|
20876
21139
|
const header = record(JSON.parse(line));
|
|
20877
21140
|
if (header.type === "session")
|
|
20878
21141
|
yield { ...header, path };
|
|
@@ -20881,13 +21144,6 @@ function* sessionHeaders(directory, nested) {
|
|
|
20881
21144
|
} catch {}
|
|
20882
21145
|
}
|
|
20883
21146
|
}
|
|
20884
|
-
function* sessionEntries(path) {
|
|
20885
|
-
for (const line of lines(path)) {
|
|
20886
|
-
try {
|
|
20887
|
-
yield JSON.parse(line);
|
|
20888
|
-
} catch {}
|
|
20889
|
-
}
|
|
20890
|
-
}
|
|
20891
21147
|
|
|
20892
21148
|
// src/dreamer/pi-session-api.ts
|
|
20893
21149
|
import { existsSync as existsSync11, readFileSync as readFileSync10, realpathSync as realpathSync4, statSync as statSync5 } from "node:fs";
|
|
@@ -21154,15 +21410,9 @@ function projectEntry(value) {
|
|
|
21154
21410
|
}
|
|
21155
21411
|
};
|
|
21156
21412
|
}
|
|
21157
|
-
function
|
|
21413
|
+
function summaryProjector() {
|
|
21158
21414
|
let pendingResults = 0;
|
|
21159
|
-
|
|
21160
|
-
let parsed;
|
|
21161
|
-
try {
|
|
21162
|
-
parsed = JSON.parse(line);
|
|
21163
|
-
} catch {
|
|
21164
|
-
continue;
|
|
21165
|
-
}
|
|
21415
|
+
return (parsed) => {
|
|
21166
21416
|
const entry = projectEntry(parsed);
|
|
21167
21417
|
const e = record2(entry);
|
|
21168
21418
|
if (e.type === "message") {
|
|
@@ -21173,7 +21423,30 @@ function* summaryEntries(path) {
|
|
|
21173
21423
|
} else if (m.role === "user" || m.role === "assistant")
|
|
21174
21424
|
pendingResults = 0;
|
|
21175
21425
|
}
|
|
21176
|
-
|
|
21426
|
+
return entry;
|
|
21427
|
+
};
|
|
21428
|
+
}
|
|
21429
|
+
function* summaryEntries(path) {
|
|
21430
|
+
const project = summaryProjector();
|
|
21431
|
+
for (const line of lines(path)) {
|
|
21432
|
+
let entry;
|
|
21433
|
+
try {
|
|
21434
|
+
entry = JSON.parse(line);
|
|
21435
|
+
} catch {}
|
|
21436
|
+
if (entry !== undefined)
|
|
21437
|
+
yield project(entry);
|
|
21438
|
+
}
|
|
21439
|
+
}
|
|
21440
|
+
async function* asyncSummaryEntries(path) {
|
|
21441
|
+
const project = summaryProjector();
|
|
21442
|
+
for await (const line of asyncLines(path)) {
|
|
21443
|
+
let entry;
|
|
21444
|
+
try {
|
|
21445
|
+
entry = JSON.parse(line);
|
|
21446
|
+
} catch {
|
|
21447
|
+
continue;
|
|
21448
|
+
}
|
|
21449
|
+
yield project(entry);
|
|
21177
21450
|
}
|
|
21178
21451
|
}
|
|
21179
21452
|
function createPiPrimerRawProviderFactory(deps = {}) {
|
|
@@ -21186,13 +21459,23 @@ function createPiPrimerRawProviderFactory(deps = {}) {
|
|
|
21186
21459
|
return null;
|
|
21187
21460
|
directory = join13(mod.getAgentDir(), "sessions");
|
|
21188
21461
|
}
|
|
21189
|
-
|
|
21462
|
+
let path = null;
|
|
21463
|
+
for await (const header of asyncSessionHeaders(directory, !deps.sessionDir)) {
|
|
21464
|
+
if (header.id === sessionId) {
|
|
21465
|
+
path = header.path;
|
|
21466
|
+
break;
|
|
21467
|
+
}
|
|
21468
|
+
}
|
|
21190
21469
|
if (!path)
|
|
21191
21470
|
return null;
|
|
21471
|
+
const sessionPath = path;
|
|
21192
21472
|
return {
|
|
21193
21473
|
readMessages() {
|
|
21194
21474
|
throw new Error("Pi primer history requires bounded pages");
|
|
21195
21475
|
},
|
|
21476
|
+
iterateMessageRangeAsync(from, to) {
|
|
21477
|
+
return iterateAsyncEntriesToRawMessageRange(asyncSummaryEntries(sessionPath), from - 1, Number.MAX_SAFE_INTEGER, to);
|
|
21478
|
+
},
|
|
21196
21479
|
iterateMessageRange(from, to) {
|
|
21197
21480
|
return iterateEntriesToRawMessageRange(summaryEntries(path), from - 1, Number.MAX_SAFE_INTEGER, to);
|
|
21198
21481
|
},
|
|
@@ -21207,6 +21490,7 @@ function createPiPrimerRawProviderFactory(deps = {}) {
|
|
|
21207
21490
|
}
|
|
21208
21491
|
|
|
21209
21492
|
// src/dreamer/retrospective-raw-provider-pi.ts
|
|
21493
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
21210
21494
|
import { join as join14 } from "node:path";
|
|
21211
21495
|
class PiRetrospectiveRawProvider {
|
|
21212
21496
|
deps;
|
|
@@ -21222,11 +21506,11 @@ class PiRetrospectiveRawProvider {
|
|
|
21222
21506
|
return [];
|
|
21223
21507
|
directory = join14(mod.getAgentDir(), "sessions");
|
|
21224
21508
|
}
|
|
21225
|
-
const sessions = this.deps.listSessions ? await this.deps.listSessions(directory) : directory ?
|
|
21509
|
+
const sessions = this.deps.listSessions ? await this.deps.listSessions(directory) : directory ? asyncSessionHeaders(directory, !this.deps.sessionDir) : [];
|
|
21226
21510
|
const projectCwd = this.deps.projectCwd;
|
|
21227
21511
|
const result = [];
|
|
21228
21512
|
this.sessionPathById.clear();
|
|
21229
|
-
for (const raw of sessions) {
|
|
21513
|
+
for await (const raw of sessions) {
|
|
21230
21514
|
const info = raw;
|
|
21231
21515
|
if (!info || typeof info !== "object")
|
|
21232
21516
|
continue;
|
|
@@ -21248,7 +21532,7 @@ class PiRetrospectiveRawProvider {
|
|
|
21248
21532
|
}
|
|
21249
21533
|
async readUserMessagesSince(sessionId, sinceMs, capPerSession) {
|
|
21250
21534
|
const limit = Math.max(1, Math.floor(capPerSession));
|
|
21251
|
-
const messages = await this.selectUserEntries(sessionId, (ts) => ts > sinceMs, limit + 1, false);
|
|
21535
|
+
const messages = await this.selectUserEntries(sessionId, (ts) => ts > sinceMs, limit + 1, false, sinceMs);
|
|
21252
21536
|
return {
|
|
21253
21537
|
messages: messages.slice(0, limit),
|
|
21254
21538
|
truncated: messages.length > limit
|
|
@@ -21257,7 +21541,7 @@ class PiRetrospectiveRawProvider {
|
|
|
21257
21541
|
async readOldestMessageTimesSince(sessionIds, sinceMs) {
|
|
21258
21542
|
const out = new Map;
|
|
21259
21543
|
for (const sessionId of sessionIds) {
|
|
21260
|
-
const [oldest] = await this.selectUserEntries(sessionId, (ts) => ts > sinceMs, 1, false);
|
|
21544
|
+
const [oldest] = await this.selectUserEntries(sessionId, (ts) => ts > sinceMs, 1, false, sinceMs);
|
|
21261
21545
|
if (oldest)
|
|
21262
21546
|
out.set(sessionId, oldest.ts);
|
|
21263
21547
|
}
|
|
@@ -21266,15 +21550,19 @@ class PiRetrospectiveRawProvider {
|
|
|
21266
21550
|
async readUserMessagesBefore(sessionId, beforeMs, count) {
|
|
21267
21551
|
return this.selectUserEntries(sessionId, (ts) => ts <= beforeMs, Math.max(1, Math.floor(count)), true);
|
|
21268
21552
|
}
|
|
21269
|
-
async selectUserEntries(sessionId, eligible, limit, newest) {
|
|
21553
|
+
async selectUserEntries(sessionId, eligible, limit, newest, sinceMs) {
|
|
21270
21554
|
const filePath = this.sessionPathById.get(sessionId);
|
|
21271
21555
|
if (!filePath)
|
|
21272
21556
|
return [];
|
|
21273
21557
|
const kept = [];
|
|
21274
21558
|
try {
|
|
21275
|
-
|
|
21559
|
+
if (sinceMs !== undefined && !this.deps.loadEntriesFromFile) {
|
|
21560
|
+
if ((await stat2(filePath)).mtimeMs < sinceMs)
|
|
21561
|
+
return [];
|
|
21562
|
+
}
|
|
21563
|
+
const entries = this.deps.loadEntriesFromFile ? await this.deps.loadEntriesFromFile(filePath) : asyncSessionEntries(filePath);
|
|
21276
21564
|
let ordinal = 0;
|
|
21277
|
-
for (const entry of entries) {
|
|
21565
|
+
for await (const entry of entries) {
|
|
21278
21566
|
const row = normalizePiUserEntry(entry, sessionId, ++ordinal);
|
|
21279
21567
|
if (!row || !eligible(row.ts))
|
|
21280
21568
|
continue;
|
|
@@ -21622,6 +21910,10 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
|
|
|
21622
21910
|
});
|
|
21623
21911
|
}
|
|
21624
21912
|
assertRegistrationOwnerActive();
|
|
21913
|
+
const mappingMessages = result.meta?.mappingMessages;
|
|
21914
|
+
if (budgetTask === "map-memories" && Array.isArray(mappingMessages)) {
|
|
21915
|
+
dreamSession.messages = mappingMessages.filter(isRecord).filter((message) => message.role === "assistant").map((message) => makeMessage("assistant", Array.isArray(message.content) ? message.content.filter(isRecord).flatMap((part) => part.type === "text" && typeof part.text === "string" ? [{ type: "text", text: part.text }] : part.type === "toolCall" ? syntheticToolParts(1) : []) : []));
|
|
21916
|
+
}
|
|
21625
21917
|
if (!result.ok) {
|
|
21626
21918
|
if (result.reason === "token_budget") {
|
|
21627
21919
|
throw new DreamTokenBudgetExceeded(dreamSession.id, Number(result.meta?.tokenBudget?.spent ?? 0));
|
|
@@ -21635,13 +21927,14 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
|
|
|
21635
21927
|
}
|
|
21636
21928
|
throw error;
|
|
21637
21929
|
}
|
|
21638
|
-
|
|
21639
|
-
|
|
21640
|
-
|
|
21641
|
-
|
|
21642
|
-
|
|
21643
|
-
|
|
21644
|
-
|
|
21930
|
+
if (!(budgetTask === "map-memories" && Array.isArray(mappingMessages)))
|
|
21931
|
+
dreamSession.messages = [
|
|
21932
|
+
makeMessage("user", [{ type: "text", text: userMessage }]),
|
|
21933
|
+
makeMessage("assistant", [
|
|
21934
|
+
...syntheticToolParts(result.toolCallCount ?? 0, result.completedToolCalls),
|
|
21935
|
+
...result.assistantText ? [{ type: "text", text: result.assistantText }] : []
|
|
21936
|
+
])
|
|
21937
|
+
];
|
|
21645
21938
|
onAdjunctsRefreshNeeded?.(opts.projectIdentity);
|
|
21646
21939
|
} finally {
|
|
21647
21940
|
inFlightDreams.delete(runPromise);
|
|
@@ -22389,7 +22682,7 @@ function reconcilePiCompactionMode(args) {
|
|
|
22389
22682
|
return NO_TRANSITION;
|
|
22390
22683
|
let clearedSomething = false;
|
|
22391
22684
|
if (getPendingPiCompactionMarkerState(args.db, args.sessionId) !== null) {
|
|
22392
|
-
setPendingPiCompactionMarkerState(args.db, args.sessionId, null);
|
|
22685
|
+
setPendingPiCompactionMarkerState(args.db, args.sessionId, null, "compaction-disabled");
|
|
22393
22686
|
clearedSomething = true;
|
|
22394
22687
|
}
|
|
22395
22688
|
if (getOverflowState(args.db, args.sessionId).needsEmergencyRecovery) {
|
|
@@ -23110,7 +23403,7 @@ function schedulePiTransformDecisionResolve(args) {
|
|
|
23110
23403
|
return false;
|
|
23111
23404
|
pendingPiDecisionBySession.delete(args.sessionId);
|
|
23112
23405
|
const token = addScheduledWriteToken(args.sessionId);
|
|
23113
|
-
setTimeout(() => {
|
|
23406
|
+
inRootAsyncContext2(() => setTimeout(() => {
|
|
23114
23407
|
try {
|
|
23115
23408
|
if (!hasScheduledWriteToken(args.sessionId, token))
|
|
23116
23409
|
return;
|
|
@@ -23130,7 +23423,7 @@ function schedulePiTransformDecisionResolve(args) {
|
|
|
23130
23423
|
} finally {
|
|
23131
23424
|
deleteScheduledWriteToken(args.sessionId, token);
|
|
23132
23425
|
}
|
|
23133
|
-
}, 0);
|
|
23426
|
+
}, 0));
|
|
23134
23427
|
return true;
|
|
23135
23428
|
}
|
|
23136
23429
|
function addScheduledWriteToken(sessionId) {
|
|
@@ -23286,21 +23579,40 @@ function buildReplacementContent(tagId) {
|
|
|
23286
23579
|
return `[dropped §${tagId}§]`;
|
|
23287
23580
|
}
|
|
23288
23581
|
function applyNewToolDrop(target, options) {
|
|
23289
|
-
if (
|
|
23582
|
+
if (options.persist && (target?.prepareDrop?.() ?? target?.canDrop?.()) === false) {
|
|
23583
|
+
return { result: "incomplete", mode: "full" };
|
|
23584
|
+
}
|
|
23585
|
+
if (!target) {
|
|
23586
|
+
options.persist?.("full");
|
|
23290
23587
|
return { result: "absent", mode: "full" };
|
|
23291
|
-
|
|
23588
|
+
}
|
|
23589
|
+
if (options.inWindow && hasSmallToolInput(target) || options.keepSkeleton === true || target.cannotRemove?.() === true || target.wouldStrandConversationEnd?.() === true) {
|
|
23292
23590
|
const strip = target.hasAttachments?.() === true;
|
|
23591
|
+
options.persist?.(strip ? "skeleton_stripped" : "skeleton_real");
|
|
23293
23592
|
return {
|
|
23294
23593
|
result: (strip ? target.skeletonStripped?.() : target.skeletonReal?.()) ?? "absent",
|
|
23295
23594
|
mode: strip ? "skeleton_stripped" : "skeleton_real"
|
|
23296
23595
|
};
|
|
23297
23596
|
}
|
|
23597
|
+
options.persist?.("full");
|
|
23298
23598
|
const result = target.drop?.() ?? "absent";
|
|
23299
23599
|
if (result === "truncated" && target.hasAttachments?.() === true) {
|
|
23300
23600
|
return { result: target.skeletonStripped?.() ?? "absent", mode: "skeleton_stripped" };
|
|
23301
23601
|
}
|
|
23302
23602
|
return { result, mode: result === "truncated" ? "skeleton_real" : "full" };
|
|
23303
23603
|
}
|
|
23604
|
+
function applyPersistedToolDrop(db, sessionId, tagNumber, target, options, afterWrite) {
|
|
23605
|
+
return applyNewToolDrop(target, {
|
|
23606
|
+
...options,
|
|
23607
|
+
persist: (mode) => {
|
|
23608
|
+
db.transaction(() => {
|
|
23609
|
+
updateTagDropMode2(db, sessionId, tagNumber, mode);
|
|
23610
|
+
updateTagStatus2(db, sessionId, tagNumber, "dropped");
|
|
23611
|
+
afterWrite?.();
|
|
23612
|
+
}).immediate();
|
|
23613
|
+
}
|
|
23614
|
+
});
|
|
23615
|
+
}
|
|
23304
23616
|
function hasSmallToolInput(target) {
|
|
23305
23617
|
const bytes = target?.inputStringBytes?.() ?? null;
|
|
23306
23618
|
return bytes !== null && bytes <= SKELETON_REAL_INPUT_MAX_BYTES;
|
|
@@ -23375,11 +23687,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
23375
23687
|
diagnostics.reasons[reason] = (diagnostics.reasons[reason] ?? 0) + 1;
|
|
23376
23688
|
};
|
|
23377
23689
|
let admitted = false;
|
|
23378
|
-
let startedAt = 0;
|
|
23379
23690
|
try {
|
|
23380
23691
|
db.transaction(() => {
|
|
23381
23692
|
admitted = true;
|
|
23382
|
-
|
|
23693
|
+
}).immediate();
|
|
23694
|
+
{
|
|
23383
23695
|
const pendingOps = preloadedPendingOps ?? getPendingOps(db, sessionId);
|
|
23384
23696
|
const tags = preloadedTags ?? getTagsByNumbers2(db, sessionId, [
|
|
23385
23697
|
...new Set([
|
|
@@ -23431,10 +23743,31 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
23431
23743
|
continue;
|
|
23432
23744
|
}
|
|
23433
23745
|
}
|
|
23746
|
+
const persistDrop = (mode) => {
|
|
23747
|
+
let startedAt = 0;
|
|
23748
|
+
try {
|
|
23749
|
+
db.transaction(() => {
|
|
23750
|
+
startedAt = performance.now();
|
|
23751
|
+
if (mode)
|
|
23752
|
+
updateTagDropMode2(db, sessionId, pendingOp.tagId, mode);
|
|
23753
|
+
updateTagStatus2(db, sessionId, pendingOp.tagId, "dropped");
|
|
23754
|
+
if (!synthetic)
|
|
23755
|
+
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
23756
|
+
}).immediate();
|
|
23757
|
+
} finally {
|
|
23758
|
+
if (startedAt)
|
|
23759
|
+
logSlowWriteTransaction("apply_pending_operation", startedAt);
|
|
23760
|
+
}
|
|
23761
|
+
};
|
|
23434
23762
|
let shouldPersistDrop = false;
|
|
23435
23763
|
if (isToolTag) {
|
|
23436
23764
|
if (editMarkerTagIds.has(pendingOp.tagId)) {
|
|
23437
23765
|
const strip = target?.hasAttachments?.() === true;
|
|
23766
|
+
if (target?.canDrop?.() === false || target?.prepareDrop?.() === false || !target) {
|
|
23767
|
+
reject("edit_marker_incomplete");
|
|
23768
|
+
continue;
|
|
23769
|
+
}
|
|
23770
|
+
persistDrop(strip ? "edit_marker_stripped" : "edit_marker");
|
|
23438
23771
|
const markResult = (strip ? target?.editMarkerStripped?.() : target?.editMarker?.()) ?? "absent";
|
|
23439
23772
|
if (markResult === "incomplete" || markResult === "absent") {
|
|
23440
23773
|
reject(`edit_marker_${markResult}`);
|
|
@@ -23443,11 +23776,11 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
23443
23776
|
didMutateMessage = true;
|
|
23444
23777
|
operationMutated = true;
|
|
23445
23778
|
onTagReduced?.({ tagNumber: pendingOp.tagId, mode: "edit_marker" });
|
|
23446
|
-
updateTagDropMode2(db, sessionId, pendingOp.tagId, strip ? "edit_marker_stripped" : "edit_marker");
|
|
23447
23779
|
shouldPersistDrop = true;
|
|
23448
23780
|
} else {
|
|
23449
23781
|
const { result: dropResult, mode: appliedMode } = applyNewToolDrop(target, {
|
|
23450
|
-
inWindow: skeletonWindow.has(pendingOp.tagId)
|
|
23782
|
+
inWindow: skeletonWindow.has(pendingOp.tagId),
|
|
23783
|
+
persist: persistDrop
|
|
23451
23784
|
});
|
|
23452
23785
|
if (dropResult === "incomplete" || synthetic && dropResult !== "removed" && dropResult !== "truncated") {
|
|
23453
23786
|
reject(`drop_${dropResult}`);
|
|
@@ -23463,12 +23796,12 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
23463
23796
|
} else {
|
|
23464
23797
|
reject(`drop_${dropResult}`);
|
|
23465
23798
|
}
|
|
23466
|
-
updateTagDropMode2(db, sessionId, pendingOp.tagId, appliedMode);
|
|
23467
23799
|
shouldPersistDrop = true;
|
|
23468
23800
|
}
|
|
23469
23801
|
} else if (target) {
|
|
23470
23802
|
const replacement = buildReplacementContent(pendingOp.tagId);
|
|
23471
23803
|
const priorContent = target.getContent?.();
|
|
23804
|
+
persistDrop();
|
|
23472
23805
|
const changed = target.setContent(replacement);
|
|
23473
23806
|
if (changed) {
|
|
23474
23807
|
didMutateMessage = true;
|
|
@@ -23485,30 +23818,25 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
|
|
|
23485
23818
|
shouldPersistDrop = true;
|
|
23486
23819
|
} else if (!synthetic) {
|
|
23487
23820
|
reject("target_absent");
|
|
23821
|
+
persistDrop();
|
|
23488
23822
|
shouldPersistDrop = true;
|
|
23489
23823
|
}
|
|
23490
23824
|
if (!shouldPersistDrop) {
|
|
23491
23825
|
reject("not_persisted");
|
|
23492
23826
|
continue;
|
|
23493
23827
|
}
|
|
23494
|
-
updateTagStatus2(db, sessionId, pendingOp.tagId, "dropped");
|
|
23495
|
-
if (!synthetic)
|
|
23496
|
-
removePendingOp(db, sessionId, pendingOp.tagId);
|
|
23497
23828
|
if (operationMutated)
|
|
23498
23829
|
diagnostics.mutated += 1;
|
|
23499
23830
|
else
|
|
23500
23831
|
diagnostics.persistedWithoutMutation += 1;
|
|
23501
23832
|
}
|
|
23502
|
-
}
|
|
23833
|
+
}
|
|
23503
23834
|
} catch (error) {
|
|
23504
23835
|
if (!admitted && /database (?:table )?is locked|sqlite_(busy|locked)/i.test(String(error))) {
|
|
23505
23836
|
sessionLog2(sessionId, "pending operations write admission busy; retaining prior bytes for retry");
|
|
23506
23837
|
return false;
|
|
23507
23838
|
}
|
|
23508
23839
|
throw error;
|
|
23509
|
-
} finally {
|
|
23510
|
-
if (admitted)
|
|
23511
|
-
logSlowWriteTransaction("apply_pending_operations", startedAt);
|
|
23512
23840
|
}
|
|
23513
23841
|
if (diagnostics) {
|
|
23514
23842
|
onBatchComplete?.(diagnostics);
|
|
@@ -24880,6 +25208,24 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
24880
25208
|
};
|
|
24881
25209
|
}
|
|
24882
25210
|
|
|
25211
|
+
// ../plugin/src/hooks/magic-context/degraded-pass-refusal.ts
|
|
25212
|
+
class DegradedPassRefusalError extends Error {
|
|
25213
|
+
site;
|
|
25214
|
+
code = "DEGRADED_PASS_REFUSAL";
|
|
25215
|
+
recoverable = true;
|
|
25216
|
+
estimatedTokens;
|
|
25217
|
+
contextLimitTokens;
|
|
25218
|
+
constructor(site, options) {
|
|
25219
|
+
super(renderUserFacingFailure("transform_pass_degraded", "plain"), {
|
|
25220
|
+
cause: options?.cause
|
|
25221
|
+
});
|
|
25222
|
+
this.site = site;
|
|
25223
|
+
this.name = "DegradedPassRefusalError";
|
|
25224
|
+
this.estimatedTokens = options?.estimatedTokens;
|
|
25225
|
+
this.contextLimitTokens = options?.contextLimitTokens;
|
|
25226
|
+
}
|
|
25227
|
+
}
|
|
25228
|
+
|
|
24883
25229
|
// ../plugin/src/hooks/magic-context/dropped-token-estimate.ts
|
|
24884
25230
|
var TAG_QUERY_CHUNK_SIZE = 900;
|
|
24885
25231
|
var ESTIMATED_CHARACTERS_PER_TOKEN = 3.5;
|
|
@@ -25500,8 +25846,110 @@ function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
|
|
|
25500
25846
|
return maxTagNumber;
|
|
25501
25847
|
}
|
|
25502
25848
|
|
|
25849
|
+
// ../plugin/src/shared/recovery-reasoning-prefix.ts
|
|
25850
|
+
function recoveryReasoningPrefixes(messages, partsKey) {
|
|
25851
|
+
const prefixes = [];
|
|
25852
|
+
for (let index = 0;index < messages.length; index++) {
|
|
25853
|
+
const message = messages[index];
|
|
25854
|
+
const parts = message?.[partsKey];
|
|
25855
|
+
if (!Array.isArray(parts))
|
|
25856
|
+
continue;
|
|
25857
|
+
for (let p = 0;p < parts.length; p++) {
|
|
25858
|
+
const type = parts[p]?.type;
|
|
25859
|
+
if (type !== "thinking" && type !== "reasoning" && type !== "redactedThinking" && type !== "redacted_thinking")
|
|
25860
|
+
continue;
|
|
25861
|
+
prefixes.push(JSON.stringify([
|
|
25862
|
+
...messages.slice(0, index),
|
|
25863
|
+
{ ...message, [partsKey]: parts.slice(0, p + 1) }
|
|
25864
|
+
]));
|
|
25865
|
+
}
|
|
25866
|
+
}
|
|
25867
|
+
return prefixes;
|
|
25868
|
+
}
|
|
25869
|
+
|
|
25503
25870
|
// ../plugin/src/shared/tag-transcript.ts
|
|
25504
25871
|
import { createHash as createHash11 } from "node:crypto";
|
|
25872
|
+
function buildPersistedDropTargets(transcript, tags, options = {}) {
|
|
25873
|
+
const targets = new Map;
|
|
25874
|
+
const tools = new Map(tags.filter((tag) => tag.type === "tool").map((tag) => [makeToolCompositeKey(tag.toolOwnerMessageId ?? "", tag.messageId), tag]));
|
|
25875
|
+
const textTags = new Map(tags.filter((tag) => tag.type !== "tool").map((tag) => [tag.messageId, tag]));
|
|
25876
|
+
const byNumber = new Map(tags.map((tag) => [tag.tagNumber, tag]));
|
|
25877
|
+
const aggregates = new Map;
|
|
25878
|
+
const pending = new Map;
|
|
25879
|
+
const resolved = new Map;
|
|
25880
|
+
const ambiguousCalls = new Set;
|
|
25881
|
+
const end = new ConversationEndGuard(transcript.messages);
|
|
25882
|
+
for (const message of transcript.messages) {
|
|
25883
|
+
let ordinal = 0;
|
|
25884
|
+
let resultRun;
|
|
25885
|
+
const parts = message.parts;
|
|
25886
|
+
const reasoning = message.requiresToolArcSkeleton ?? (message.info.role === "assistant" && parts.some((part) => part.kind === "thinking"));
|
|
25887
|
+
for (const part of parts) {
|
|
25888
|
+
if (part.kind !== "tool_result")
|
|
25889
|
+
resultRun = undefined;
|
|
25890
|
+
if (part.kind === "text") {
|
|
25891
|
+
const prefix = /^§(\d+)§\s/.exec(part.getText() ?? "");
|
|
25892
|
+
const tag = (prefix ? byNumber.get(Number(prefix[1])) : undefined) ?? textTags.get(`${message.info.id}:p${ordinal}`);
|
|
25893
|
+
ordinal++;
|
|
25894
|
+
if (tag && tag.type !== "tool")
|
|
25895
|
+
targets.set(tag.tagNumber, buildTextTarget(part, message, ""));
|
|
25896
|
+
} else if ((part.kind === "tool_use" || part.kind === "tool_result") && part.id) {
|
|
25897
|
+
const open = pending.get(part.id) ?? [];
|
|
25898
|
+
if (open.length > 1)
|
|
25899
|
+
ambiguousCalls.add(part.id);
|
|
25900
|
+
const key = (part.kind === "tool_result" ? resultRun?.callId === part.id ? resultRun.key : open.at(-1) ?? resolved.get(part.id) : undefined) ?? makeToolCompositeKey(message.info.id ?? "", part.id);
|
|
25901
|
+
if (part.kind === "tool_use")
|
|
25902
|
+
open.push(key);
|
|
25903
|
+
else {
|
|
25904
|
+
const position = open.lastIndexOf(key);
|
|
25905
|
+
if (position >= 0)
|
|
25906
|
+
open.splice(position, 1);
|
|
25907
|
+
resultRun = { callId: part.id, key };
|
|
25908
|
+
resolved.set(part.id, key);
|
|
25909
|
+
}
|
|
25910
|
+
pending.set(part.id, open);
|
|
25911
|
+
let aggregate = aggregates.get(key);
|
|
25912
|
+
if (!aggregate) {
|
|
25913
|
+
aggregate = {
|
|
25914
|
+
tag: tools.get(key),
|
|
25915
|
+
occurrences: [],
|
|
25916
|
+
reasoning: false
|
|
25917
|
+
};
|
|
25918
|
+
aggregates.set(key, aggregate);
|
|
25919
|
+
}
|
|
25920
|
+
aggregate.occurrences.push({ message, part, kind: part.kind });
|
|
25921
|
+
aggregate.reasoning ||= reasoning;
|
|
25922
|
+
}
|
|
25923
|
+
}
|
|
25924
|
+
}
|
|
25925
|
+
const arcsByCall = new Map;
|
|
25926
|
+
for (const { occurrences } of aggregates.values()) {
|
|
25927
|
+
const callId = occurrences[0]?.part.id ?? "";
|
|
25928
|
+
arcsByCall.set(callId, (arcsByCall.get(callId) ?? 0) + 1);
|
|
25929
|
+
}
|
|
25930
|
+
for (const aggregate of aggregates.values()) {
|
|
25931
|
+
const { occurrences, reasoning } = aggregate;
|
|
25932
|
+
const callId = occurrences[0]?.part.id ?? "";
|
|
25933
|
+
if (ambiguousCalls.has(callId))
|
|
25934
|
+
continue;
|
|
25935
|
+
const tag = aggregate.tag ?? (arcsByCall.get(callId) === 1 ? tools.get(makeToolCompositeKey("", callId)) : undefined);
|
|
25936
|
+
if (tag)
|
|
25937
|
+
targets.set(tag.tagNumber, buildAggregateTarget(tag.tagNumber, occurrences, reasoning, end));
|
|
25938
|
+
}
|
|
25939
|
+
if (!options.allowReasoningPrefixRewrite) {
|
|
25940
|
+
let lastThinking = -1;
|
|
25941
|
+
transcript.messages.forEach((message, index) => {
|
|
25942
|
+
if (message.parts.some((part) => part.kind === "thinking"))
|
|
25943
|
+
lastThinking = index;
|
|
25944
|
+
});
|
|
25945
|
+
const protectedIds = new Set(transcript.messages.slice(0, lastThinking + 1).map((message) => message.info.id));
|
|
25946
|
+
for (const [number, target] of targets) {
|
|
25947
|
+
if (target.mutationParts?.some(({ message }) => protectedIds.has(message.info.id)))
|
|
25948
|
+
targets.delete(number);
|
|
25949
|
+
}
|
|
25950
|
+
}
|
|
25951
|
+
return targets;
|
|
25952
|
+
}
|
|
25505
25953
|
function textIdentityDigest(value) {
|
|
25506
25954
|
return createHash11("sha256").update(value).digest("hex");
|
|
25507
25955
|
}
|
|
@@ -26196,6 +26644,7 @@ function buildAggregateTarget(tagId, occurrences, requiresToolArcSkeleton, conve
|
|
|
26196
26644
|
}
|
|
26197
26645
|
return any ? "truncated" : "absent";
|
|
26198
26646
|
},
|
|
26647
|
+
prepareDrop: () => !occurrences.some((occ) => occ.part.canRemove?.() === "defer"),
|
|
26199
26648
|
canDrop: () => complete() && !occurrences.some((occ) => occ.part.hasUserAnswer?.()),
|
|
26200
26649
|
requiresToolArcSkeleton,
|
|
26201
26650
|
readInput() {
|
|
@@ -26546,7 +26995,7 @@ function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
|
|
|
26546
26995
|
pending.delete(key);
|
|
26547
26996
|
resolve();
|
|
26548
26997
|
};
|
|
26549
|
-
const queued = setTimeout(() => {
|
|
26998
|
+
const queued = inRootAsyncContext2(() => setTimeout(() => {
|
|
26550
26999
|
lifecycle.signal.removeEventListener("abort", cancel);
|
|
26551
27000
|
if (lifecycle.signal.aborted)
|
|
26552
27001
|
return done();
|
|
@@ -26557,7 +27006,7 @@ function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
|
|
|
26557
27006
|
clearTimeout(timeout);
|
|
26558
27007
|
done();
|
|
26559
27008
|
});
|
|
26560
|
-
}, 0);
|
|
27009
|
+
}, 0));
|
|
26561
27010
|
const cancel = () => {
|
|
26562
27011
|
clearTimeout(queued);
|
|
26563
27012
|
done();
|
|
@@ -26604,7 +27053,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
|
|
|
26604
27053
|
deadlineUnixMs: autoSearchDeadlineUnixMs(deadlineSignal)
|
|
26605
27054
|
};
|
|
26606
27055
|
return new Promise((resolve, reject) => {
|
|
26607
|
-
const worker = new Worker(entry, { workerData: input });
|
|
27056
|
+
const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: input }));
|
|
26608
27057
|
let settled = false;
|
|
26609
27058
|
const finish = (results, error) => {
|
|
26610
27059
|
if (settled)
|
|
@@ -28225,18 +28674,27 @@ function buildPiCompactionSummary(compartments) {
|
|
|
28225
28674
|
return `Magic Context compacted ${titles.length} segments: ${shown}; …and ${titles.length - MAX_SUMMARY_TITLES} more`;
|
|
28226
28675
|
}
|
|
28227
28676
|
function findFirstKeptEntryId(entries, lastCompactedOrdinal, ordinalOffset = 0) {
|
|
28677
|
+
const boundary = resolvePiFirstKeptEntry(entries, lastCompactedOrdinal, ordinalOffset);
|
|
28678
|
+
return boundary.kind === "resolved" ? boundary.entryId : null;
|
|
28679
|
+
}
|
|
28680
|
+
function resolvePiFirstKeptEntry(entries, lastCompactedOrdinal, ordinalOffset = 0) {
|
|
28228
28681
|
const target = lastCompactedOrdinal + 1;
|
|
28229
28682
|
const afterOrdinal = Number.isNaN(lastCompactedOrdinal) ? 0 : Math.max(0, lastCompactedOrdinal);
|
|
28683
|
+
let syntheticKeptId;
|
|
28230
28684
|
for (const message of iterateEntriesToRawMessageRange(entries, afterOrdinal, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, ordinalOffset)) {
|
|
28231
28685
|
if (message.ordinal < target || isPiSystemEntry(message))
|
|
28232
28686
|
continue;
|
|
28233
|
-
if (
|
|
28234
|
-
return
|
|
28687
|
+
if (syntheticKeptId)
|
|
28688
|
+
return { kind: "unplaceable", rawId: syntheticKeptId };
|
|
28689
|
+
if (message.id.startsWith(SYNTH_USER_ID_PREFIX)) {
|
|
28690
|
+
syntheticKeptId = message.id;
|
|
28691
|
+
continue;
|
|
28692
|
+
}
|
|
28235
28693
|
if (message.id.length === 0)
|
|
28236
28694
|
continue;
|
|
28237
|
-
return message.id;
|
|
28695
|
+
return { kind: "resolved", entryId: message.id };
|
|
28238
28696
|
}
|
|
28239
|
-
return
|
|
28697
|
+
return { kind: "waiting" };
|
|
28240
28698
|
}
|
|
28241
28699
|
|
|
28242
28700
|
// src/compaction-marker-manager-pi.ts
|
|
@@ -28257,6 +28715,7 @@ function logPiCompactionMarkerDrainGateOnce(sessionId, pending, gate, fields = {
|
|
|
28257
28715
|
`endMessageId=${pending.endMessageId}`,
|
|
28258
28716
|
`ordinal=${pending.ordinal}`,
|
|
28259
28717
|
`firstKeptEntryId=${firstKeptEntryId ?? "<none>"}`,
|
|
28718
|
+
`boundaryKind=${pending.endMessageId.startsWith(SYNTH_USER_ID_PREFIX) ? "folded-tool-result" : "session-entry"}`,
|
|
28260
28719
|
`renderedCoverageOrdinal=${fields.renderedCoverageOrdinal ?? "<none>"}`
|
|
28261
28720
|
];
|
|
28262
28721
|
if (fields.renderedCoverageEndMessageId !== undefined)
|
|
@@ -28269,6 +28728,17 @@ function logPiCompactionMarkerDrainGateOnce(sessionId, pending, gate, fields = {
|
|
|
28269
28728
|
parts.push(`matchCount=${fields.matchCount}`);
|
|
28270
28729
|
if (fields.alignment !== undefined)
|
|
28271
28730
|
parts.push(`alignment=${fields.alignment}`);
|
|
28731
|
+
if (fields.alignmentReason !== undefined)
|
|
28732
|
+
parts.push(`alignmentReason=${fields.alignmentReason}`);
|
|
28733
|
+
for (const key of [
|
|
28734
|
+
"historyConsumed",
|
|
28735
|
+
"materializationSatisfied",
|
|
28736
|
+
"drainSuppressed",
|
|
28737
|
+
"casLost"
|
|
28738
|
+
]) {
|
|
28739
|
+
if (fields[key] !== undefined)
|
|
28740
|
+
parts.push(`${key}=${fields[key]}`);
|
|
28741
|
+
}
|
|
28272
28742
|
if (fields.foldingOnlyTools !== undefined)
|
|
28273
28743
|
parts.push(`foldingOnlyTools=${JSON.stringify(fields.foldingOnlyTools)}`);
|
|
28274
28744
|
if (fields.persistedOnlyTools !== undefined)
|
|
@@ -28318,10 +28788,20 @@ function applyDeferredPiCompactionMarker(deps, sessionId, pending) {
|
|
|
28318
28788
|
if (!firstKeptEntryId) {
|
|
28319
28789
|
const alignment = resolvePiOrdinalAlignment(deps.db, sessionId, branchEntries);
|
|
28320
28790
|
if (isPiOrdinalAlignmentUnanchored(alignment)) {
|
|
28321
|
-
|
|
28791
|
+
if (alignment.kind === "unanchored" && alignment.reason === "anchor-missing" && hasMergedSyntheticBoundary(branchEntries, pending.endMessageId)) {
|
|
28792
|
+
return { kind: "stale-skip", reason: "synthetic-boundary-merged" };
|
|
28793
|
+
}
|
|
28794
|
+
logPiCompactionMarkerDrainGateOnce(sessionId, pending, "ordinal-alignment-unavailable", {
|
|
28795
|
+
alignment: alignment.kind,
|
|
28796
|
+
...alignment.kind === "unanchored" ? { alignmentReason: alignment.reason } : {}
|
|
28797
|
+
});
|
|
28322
28798
|
return { kind: "waiting-for-entry" };
|
|
28323
28799
|
}
|
|
28324
|
-
|
|
28800
|
+
const boundary = resolvePiFirstKeptEntry(branchEntries, pending.ordinal, alignment.offset);
|
|
28801
|
+
if (boundary.kind === "unplaceable") {
|
|
28802
|
+
return { kind: "stale-skip", reason: "synthetic-kept-entry" };
|
|
28803
|
+
}
|
|
28804
|
+
firstKeptEntryId = boundary.kind === "resolved" ? boundary.entryId : null;
|
|
28325
28805
|
}
|
|
28326
28806
|
if (!firstKeptEntryId) {
|
|
28327
28807
|
logPiCompactionMarkerDrainGateOnce(sessionId, pending, "no-replay-safe-kept-entry", { firstKeptEntryId: null });
|
|
@@ -28376,6 +28856,27 @@ function applyDeferredPiCompactionMarker(deps, sessionId, pending) {
|
|
|
28376
28856
|
return { kind: "retryable-failure", error };
|
|
28377
28857
|
}
|
|
28378
28858
|
}
|
|
28859
|
+
function hasMergedSyntheticBoundary(entries, endMessageId) {
|
|
28860
|
+
if (!endMessageId.startsWith(SYNTH_USER_ID_PREFIX))
|
|
28861
|
+
return false;
|
|
28862
|
+
const resultId = endMessageId.slice(SYNTH_USER_ID_PREFIX.length);
|
|
28863
|
+
let foundResult = false;
|
|
28864
|
+
for (const entry of entries) {
|
|
28865
|
+
const row = entry;
|
|
28866
|
+
if (row?.type !== "message")
|
|
28867
|
+
continue;
|
|
28868
|
+
const message = row.message;
|
|
28869
|
+
if (!foundResult) {
|
|
28870
|
+
foundResult = row.id === resultId && message?.role === "toolResult" && typeof message.toolCallId === "string" && message.toolCallId.length > 0;
|
|
28871
|
+
continue;
|
|
28872
|
+
}
|
|
28873
|
+
if (message?.role === "user")
|
|
28874
|
+
return true;
|
|
28875
|
+
if (message?.role === "assistant")
|
|
28876
|
+
return false;
|
|
28877
|
+
}
|
|
28878
|
+
return false;
|
|
28879
|
+
}
|
|
28379
28880
|
function findLatestCompaction(branchEntries) {
|
|
28380
28881
|
for (let i = branchEntries.length - 1;i >= 0; i--) {
|
|
28381
28882
|
const entry = branchEntries[i];
|
|
@@ -29729,30 +30230,26 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
29729
30230
|
const tPersist = performance.now();
|
|
29730
30231
|
const toDrop = new Set(plan.tagNumbers);
|
|
29731
30232
|
const newestEmergencyTags = recentTags;
|
|
29732
|
-
|
|
29733
|
-
|
|
29734
|
-
|
|
29735
|
-
|
|
29736
|
-
|
|
29737
|
-
|
|
29738
|
-
|
|
29739
|
-
|
|
29740
|
-
|
|
29741
|
-
|
|
29742
|
-
|
|
30233
|
+
for (const tag of tags) {
|
|
30234
|
+
if (!toDrop.has(tag.tagNumber))
|
|
30235
|
+
continue;
|
|
30236
|
+
if (tag.status !== "active" || tag.type !== "tool")
|
|
30237
|
+
continue;
|
|
30238
|
+
const target = targets.get(tag.tagNumber);
|
|
30239
|
+
const recent = (emergency.usagePercentage ?? 0) < 95 && newestEmergencyTags.has(tag.tagNumber);
|
|
30240
|
+
const { result, mode } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
|
|
30241
|
+
inWindow: recent,
|
|
30242
|
+
keepSkeleton: target?.requiresToolArcSkeleton === true
|
|
30243
|
+
});
|
|
30244
|
+
if (result === "removed" || result === "truncated") {
|
|
30245
|
+
droppedTools++;
|
|
30246
|
+
emergencyDroppedTools++;
|
|
30247
|
+
droppedTokenReductions.push({
|
|
30248
|
+
tagNumber: tag.tagNumber,
|
|
30249
|
+
mode: mode === "full" ? "full" : "truncated"
|
|
29743
30250
|
});
|
|
29744
|
-
if (result === "removed" || result === "truncated") {
|
|
29745
|
-
updateTagStatus2(db, sessionId, tag.tagNumber, "dropped");
|
|
29746
|
-
updateTagDropMode2(db, sessionId, tag.tagNumber, mode);
|
|
29747
|
-
droppedTools++;
|
|
29748
|
-
emergencyDroppedTools++;
|
|
29749
|
-
droppedTokenReductions.push({
|
|
29750
|
-
tagNumber: tag.tagNumber,
|
|
29751
|
-
mode: mode === "full" ? "full" : "truncated"
|
|
29752
|
-
});
|
|
29753
|
-
}
|
|
29754
30251
|
}
|
|
29755
|
-
}
|
|
30252
|
+
}
|
|
29756
30253
|
logStep("applyEmergencyDrops", tPersist, `dropped=${emergencyDroppedTools}`);
|
|
29757
30254
|
sessionLog2(sessionId, `emergency tiered drop: ${plan.reason}`);
|
|
29758
30255
|
} else {
|
|
@@ -29761,33 +30258,29 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
29761
30258
|
}
|
|
29762
30259
|
const staleReduce = routine && config.staleReduceStripEnabled ? collectStaleReduceCallIds(piMessages, buildMessageIdToMaxTagFromTargets(targets), buildCtxReduceTagNumbers(tags), toolAgeCutoff, resolveStableId) : { composite: new Set, bareCallIds: new Set };
|
|
29763
30260
|
if (routine && config.staleReduceStripEnabled && (staleReduce.composite.size > 0 || staleReduce.bareCallIds.size > 0)) {
|
|
29764
|
-
|
|
29765
|
-
|
|
29766
|
-
|
|
29767
|
-
|
|
29768
|
-
|
|
29769
|
-
|
|
29770
|
-
|
|
29771
|
-
|
|
29772
|
-
|
|
29773
|
-
|
|
29774
|
-
|
|
29775
|
-
|
|
29776
|
-
|
|
29777
|
-
|
|
29778
|
-
|
|
29779
|
-
|
|
29780
|
-
|
|
29781
|
-
|
|
29782
|
-
|
|
29783
|
-
|
|
29784
|
-
|
|
29785
|
-
if (result === "removed" || result === "truncated") {
|
|
29786
|
-
droppedStaleReduceCalls++;
|
|
29787
|
-
config.onStaleReduceEdit?.(tag);
|
|
29788
|
-
}
|
|
30261
|
+
for (const tag of tags) {
|
|
30262
|
+
if (tag.status !== "active")
|
|
30263
|
+
continue;
|
|
30264
|
+
if (tag.type !== "tool")
|
|
30265
|
+
continue;
|
|
30266
|
+
if (protectedTools.has(tag.tagNumber))
|
|
30267
|
+
continue;
|
|
30268
|
+
if (!tag.messageId)
|
|
30269
|
+
continue;
|
|
30270
|
+
const matched = tag.toolOwnerMessageId ? staleReduce.composite.has(`${tag.toolOwnerMessageId}\x00${tag.messageId}`) : staleReduce.bareCallIds.has(tag.messageId);
|
|
30271
|
+
if (!matched)
|
|
30272
|
+
continue;
|
|
30273
|
+
const target = targets.get(tag.tagNumber);
|
|
30274
|
+
if (target?.canDrop?.() === false)
|
|
30275
|
+
continue;
|
|
30276
|
+
const { result } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, { inWindow: false });
|
|
30277
|
+
if (result === "incomplete")
|
|
30278
|
+
continue;
|
|
30279
|
+
if (result === "removed" || result === "truncated") {
|
|
30280
|
+
droppedStaleReduceCalls++;
|
|
30281
|
+
config.onStaleReduceEdit?.(tag);
|
|
29789
30282
|
}
|
|
29790
|
-
}
|
|
30283
|
+
}
|
|
29791
30284
|
}
|
|
29792
30285
|
if (routine) {
|
|
29793
30286
|
db.transaction(() => {
|
|
@@ -29856,37 +30349,33 @@ function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config, pre
|
|
|
29856
30349
|
group.push(tag);
|
|
29857
30350
|
fingerprintGroups.set(fingerprint, group);
|
|
29858
30351
|
}
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
30352
|
+
for (const [, group] of fingerprintGroups) {
|
|
30353
|
+
if (group.length <= 1)
|
|
30354
|
+
continue;
|
|
30355
|
+
group.sort((a, b) => a.tagNumber - b.tagNumber);
|
|
30356
|
+
for (let i = 0;i < group.length - 1; i++) {
|
|
30357
|
+
const tag = group[i];
|
|
30358
|
+
if (tag.tagNumber > protectedCutoff)
|
|
29862
30359
|
continue;
|
|
29863
|
-
|
|
29864
|
-
|
|
29865
|
-
|
|
29866
|
-
|
|
29867
|
-
|
|
29868
|
-
|
|
29869
|
-
|
|
29870
|
-
|
|
29871
|
-
|
|
29872
|
-
|
|
29873
|
-
|
|
29874
|
-
|
|
30360
|
+
const target = targets.get(tag.tagNumber);
|
|
30361
|
+
if (protectedTools.has(tag.tagNumber))
|
|
30362
|
+
continue;
|
|
30363
|
+
if (target?.canDrop?.() === false)
|
|
30364
|
+
continue;
|
|
30365
|
+
const { result, mode } = applyPersistedToolDrop(db, sessionId, tag.tagNumber, target, {
|
|
30366
|
+
inWindow: false
|
|
30367
|
+
});
|
|
30368
|
+
if (result === "incomplete")
|
|
30369
|
+
continue;
|
|
30370
|
+
if (result === "removed" || result === "truncated") {
|
|
30371
|
+
deduplicatedTools++;
|
|
30372
|
+
droppedTokenReductions.push({
|
|
30373
|
+
tagNumber: tag.tagNumber,
|
|
30374
|
+
mode: mode === "full" ? "full" : "truncated"
|
|
29875
30375
|
});
|
|
29876
|
-
if (result === "incomplete")
|
|
29877
|
-
continue;
|
|
29878
|
-
updateTagDropMode2(db, sessionId, tag.tagNumber, mode);
|
|
29879
|
-
updateTagStatus2(db, sessionId, tag.tagNumber, "dropped");
|
|
29880
|
-
if (result === "removed" || result === "truncated") {
|
|
29881
|
-
deduplicatedTools++;
|
|
29882
|
-
droppedTokenReductions.push({
|
|
29883
|
-
tagNumber: tag.tagNumber,
|
|
29884
|
-
mode: mode === "full" ? "full" : "truncated"
|
|
29885
|
-
});
|
|
29886
|
-
}
|
|
29887
30376
|
}
|
|
29888
30377
|
}
|
|
29889
|
-
}
|
|
30378
|
+
}
|
|
29890
30379
|
}
|
|
29891
30380
|
if (droppedTools > 0 || deduplicatedTools > 0 || droppedInjections > 0 || droppedStaleReduceCalls > 0) {
|
|
29892
30381
|
sessionLog2(sessionId, `heuristic cleanup: dropped ${droppedTools} tool tags, stale ctx_reduce=${droppedStaleReduceCalls}, deduplicated ${deduplicatedTools} tool calls, dropped ${droppedInjections} system injections`);
|
|
@@ -30300,6 +30789,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
30300
30789
|
sequenceOffset: candidateCompartments.length,
|
|
30301
30790
|
dumpLabelBase: `recomp-${sessionId}-${chunk.startIndex}-${chunk.endIndex}-pass-${passCount + 1}`,
|
|
30302
30791
|
timeoutMs: historianTimeoutMs,
|
|
30792
|
+
maxOutputTokens: deps.historianMaxOutputTokens,
|
|
30303
30793
|
model: deps.model,
|
|
30304
30794
|
fallbackModelId: deps.fallbackModelId,
|
|
30305
30795
|
fallbackModels: deps.fallbackModels,
|
|
@@ -30814,7 +31304,6 @@ ${renderUserFacingFailure("recomp_unavailable")}`;
|
|
|
30814
31304
|
}
|
|
30815
31305
|
}
|
|
30816
31306
|
}
|
|
30817
|
-
|
|
30818
31307
|
// ../plugin/src/hooks/magic-context/compartment-runner.ts
|
|
30819
31308
|
var activeRuns = new Map;
|
|
30820
31309
|
function getActiveCompartmentRun(sessionId) {
|
|
@@ -30835,7 +31324,7 @@ function withPublishedCallback(deps) {
|
|
|
30835
31324
|
};
|
|
30836
31325
|
}
|
|
30837
31326
|
function startLeaseRenewal(deps, holderId) {
|
|
30838
|
-
return setInterval(() => {
|
|
31327
|
+
return inRootAsyncContext2(() => setInterval(() => {
|
|
30839
31328
|
try {
|
|
30840
31329
|
if (!renewCompartmentLease(deps.db, deps.sessionId, holderId)) {
|
|
30841
31330
|
sessionLog2(deps.sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
@@ -30843,7 +31332,7 @@ function startLeaseRenewal(deps, holderId) {
|
|
|
30843
31332
|
} catch (err) {
|
|
30844
31333
|
sessionLog2(deps.sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
30845
31334
|
}
|
|
30846
|
-
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
31335
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS));
|
|
30847
31336
|
}
|
|
30848
31337
|
async function executeContextRecompWithResult(deps, options = {}) {
|
|
30849
31338
|
const { sessionId } = deps;
|
|
@@ -30933,6 +31422,7 @@ function forgetCachedPrefix(sessionId) {
|
|
|
30933
31422
|
function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = false, onRetire) {
|
|
30934
31423
|
db.exec("BEGIN IMMEDIATE");
|
|
30935
31424
|
let finished = false;
|
|
31425
|
+
let clearedMarker = null;
|
|
30936
31426
|
try {
|
|
30937
31427
|
if (!isCompartmentLeaseHeld(db, sessionId, holderId)) {
|
|
30938
31428
|
db.exec("ROLLBACK");
|
|
@@ -30949,14 +31439,16 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
|
|
|
30949
31439
|
if (activeBranch) {
|
|
30950
31440
|
db.prepare("UPDATE session_meta SET prior_boundary_ordinal = ? WHERE session_id = ?").run((anchor?.endMessage ?? 0) + 1, sessionId);
|
|
30951
31441
|
const marker = getPendingPiCompactionMarkerState(db, sessionId);
|
|
30952
|
-
if (marker)
|
|
30953
|
-
|
|
31442
|
+
if (marker && clearPendingPiCompactionMarkerStateIf(db, sessionId, marker, null))
|
|
31443
|
+
clearedMarker = marker;
|
|
30954
31444
|
}
|
|
30955
31445
|
deleteChunkEmbedBackoffForSession(db, sessionId);
|
|
30956
31446
|
queueM0Mutation(db, { sessionId, mutationType: "recomp_boundary_change" });
|
|
30957
31447
|
clearCachedM0M1(db, sessionId);
|
|
30958
31448
|
db.exec("COMMIT");
|
|
30959
31449
|
finished = true;
|
|
31450
|
+
if (clearedMarker)
|
|
31451
|
+
logPiCompactionMarkerClear(sessionId, clearedMarker, "active-branch-retired");
|
|
30960
31452
|
return dropped.map((row) => row.sequence);
|
|
30961
31453
|
} finally {
|
|
30962
31454
|
if (!finished) {
|
|
@@ -31072,6 +31564,29 @@ function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId, trimMut
|
|
|
31072
31564
|
break;
|
|
31073
31565
|
}
|
|
31074
31566
|
}
|
|
31567
|
+
if (cutoffIndex < 0 && sessionId && hasRawMessageProvider2(sessionId)) {
|
|
31568
|
+
try {
|
|
31569
|
+
const branch = readRawSessionMessages2(sessionId);
|
|
31570
|
+
const positions = new Map(branch.map((message, index) => [message.id, index]));
|
|
31571
|
+
const boundaryPosition = positions.get(cutoffMessageId);
|
|
31572
|
+
if (boundaryPosition === undefined)
|
|
31573
|
+
return 0;
|
|
31574
|
+
let previous = -1;
|
|
31575
|
+
for (const [index, message] of piMessages.entries()) {
|
|
31576
|
+
if (isPiSystemEntry(message))
|
|
31577
|
+
continue;
|
|
31578
|
+
const id = resolveStableId(message, index, entryIds);
|
|
31579
|
+
const position = positions.get(id) ?? positions.get(`${SYNTH_USER_ID_PREFIX}${id}`);
|
|
31580
|
+
if (position === undefined || position <= previous)
|
|
31581
|
+
return 0;
|
|
31582
|
+
previous = position;
|
|
31583
|
+
if (position <= boundaryPosition)
|
|
31584
|
+
cutoffIndex = index;
|
|
31585
|
+
}
|
|
31586
|
+
} catch {
|
|
31587
|
+
return 0;
|
|
31588
|
+
}
|
|
31589
|
+
}
|
|
31075
31590
|
if (cutoffIndex < 0)
|
|
31076
31591
|
return 0;
|
|
31077
31592
|
const remove = new Set;
|
|
@@ -32575,6 +33090,54 @@ function rewriteNativeToolInput(message, toolCallId, input) {
|
|
|
32575
33090
|
items[match.index] = { ...match.item, [field]: nextValue };
|
|
32576
33091
|
envelope.message.providerPayload = { ...envelope.payload, items };
|
|
32577
33092
|
}
|
|
33093
|
+
function textIdentity(part) {
|
|
33094
|
+
if (!isRecord(part) || part.type !== "text" || typeof part.textSignature !== "string")
|
|
33095
|
+
return;
|
|
33096
|
+
try {
|
|
33097
|
+
const signature = JSON.parse(part.textSignature);
|
|
33098
|
+
if (isRecord(signature) && signature.v === 1 && typeof signature.id === "string" && signature.id.length > 0 && (signature.phase === undefined || signature.phase === "commentary" || signature.phase === "final_answer")) {
|
|
33099
|
+
return { id: signature.id, phase: signature.phase };
|
|
33100
|
+
}
|
|
33101
|
+
} catch {}
|
|
33102
|
+
return;
|
|
33103
|
+
}
|
|
33104
|
+
function rewriteNativeAssistantTexts(message, previous, sessionId) {
|
|
33105
|
+
const envelope = getNativeEnvelope(message);
|
|
33106
|
+
if (envelope?.message.role !== "assistant" || !isRecord(previous) || !Array.isArray(previous.content) || !Array.isArray(envelope.message.content))
|
|
33107
|
+
return;
|
|
33108
|
+
const content = envelope.message.content;
|
|
33109
|
+
for (let index = 0;index < content.length; index++) {
|
|
33110
|
+
const part = content[index];
|
|
33111
|
+
const before = previous.content[index];
|
|
33112
|
+
if (!isRecord(part) || part.type !== "text" || typeof part.text !== "string" || !isRecord(before) || before.type !== "text" || typeof before.text !== "string")
|
|
33113
|
+
continue;
|
|
33114
|
+
if (part.text.replace(/^§\d+§ /u, "") === before.text.replace(/^§\d+§ /u, ""))
|
|
33115
|
+
continue;
|
|
33116
|
+
const identity = textIdentity(part);
|
|
33117
|
+
const sameIdentity = (value) => {
|
|
33118
|
+
const other = textIdentity(value);
|
|
33119
|
+
return identity !== undefined && other?.id === identity.id && other.phase === identity.phase;
|
|
33120
|
+
};
|
|
33121
|
+
const matches = envelope.items.flatMap((item, itemIndex) => isRecord(item) && item.type === "message" && item.role === "assistant" && identity !== undefined && item.id === identity.id && item.phase === identity.phase ? [{ item, itemIndex }] : []);
|
|
33122
|
+
const match = matches[0];
|
|
33123
|
+
const outputs = match && Array.isArray(match.item.content) ? match.item.content.flatMap((output, outputIndex) => isRecord(output) && output.type === "output_text" && typeof output.text === "string" ? [{ output, outputIndex }] : []) : [];
|
|
33124
|
+
if (!identity || content.filter(sameIdentity).length !== 1 || previous.content.filter(sameIdentity).length !== 1 || matches.length !== 1 || outputs.length !== 1) {
|
|
33125
|
+
if (sessionId)
|
|
33126
|
+
sessionLog2(sessionId, `native assistant text replay skipped: missing or ambiguous id/phase match at part ${index} (items=${matches.length}, outputs=${outputs.length}); retaining native history for dispatch validation`);
|
|
33127
|
+
continue;
|
|
33128
|
+
}
|
|
33129
|
+
const { output, outputIndex } = outputs[0];
|
|
33130
|
+
if (output.text === part.text)
|
|
33131
|
+
continue;
|
|
33132
|
+
const nextContent = match.item.content.slice();
|
|
33133
|
+
nextContent[outputIndex] = { ...output, text: part.text };
|
|
33134
|
+
const items = envelope.items.slice();
|
|
33135
|
+
items[match.itemIndex] = { ...match.item, content: nextContent };
|
|
33136
|
+
envelope.items = items;
|
|
33137
|
+
envelope.payload = { ...envelope.payload, items };
|
|
33138
|
+
envelope.message.providerPayload = envelope.payload;
|
|
33139
|
+
}
|
|
33140
|
+
}
|
|
32578
33141
|
function hasRedactedThinkingContent(message) {
|
|
32579
33142
|
if (!Array.isArray(message.content))
|
|
32580
33143
|
return false;
|
|
@@ -32886,9 +33449,9 @@ class PiContextBudget {
|
|
|
32886
33449
|
elapsed() {
|
|
32887
33450
|
return this.now() - this.startedAt;
|
|
32888
33451
|
}
|
|
32889
|
-
remainingWork() {
|
|
33452
|
+
remainingWork = () => {
|
|
32890
33453
|
return Math.max(0, PI_CONTEXT_BUDGET.workMs - this.elapsed());
|
|
32891
|
-
}
|
|
33454
|
+
};
|
|
32892
33455
|
remainingOutcome = () => Math.max(0, PI_CONTEXT_BUDGET.outcomeMs - this.elapsed());
|
|
32893
33456
|
writerAllowance() {
|
|
32894
33457
|
return Math.max(0, Math.min(PI_CONTEXT_BUDGET.writerMs, this.remainingWork() - PI_CONTEXT_BUDGET.completionReserveMs));
|
|
@@ -33670,7 +34233,7 @@ function object4(value) {
|
|
|
33670
34233
|
function wellFormed(text) {
|
|
33671
34234
|
return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "�");
|
|
33672
34235
|
}
|
|
33673
|
-
function
|
|
34236
|
+
function textIdentity2(text, phase) {
|
|
33674
34237
|
return JSON.stringify([
|
|
33675
34238
|
text,
|
|
33676
34239
|
phase === "commentary" || phase === "final_answer" ? phase : null
|
|
@@ -33728,7 +34291,7 @@ function piResponsesAssistantTexts(value, model) {
|
|
|
33728
34291
|
units += text.length;
|
|
33729
34292
|
if (units > MAX_TEXT_UNITS)
|
|
33730
34293
|
return;
|
|
33731
|
-
texts.push(
|
|
34294
|
+
texts.push(textIdentity2(text, undefined));
|
|
33732
34295
|
continue;
|
|
33733
34296
|
}
|
|
33734
34297
|
if (block?.type !== "text" || typeof block.text !== "string")
|
|
@@ -33736,7 +34299,7 @@ function piResponsesAssistantTexts(value, model) {
|
|
|
33736
34299
|
units += block.text.length;
|
|
33737
34300
|
if (units > MAX_TEXT_UNITS)
|
|
33738
34301
|
return;
|
|
33739
|
-
texts.push(
|
|
34302
|
+
texts.push(textIdentity2(wellFormed(block.text), sameModel ? signaturePhase(block) : undefined));
|
|
33740
34303
|
blocks.push(block);
|
|
33741
34304
|
}
|
|
33742
34305
|
const payload = object4(message.providerPayload);
|
|
@@ -33761,7 +34324,7 @@ function piResponsesAssistantTexts(value, model) {
|
|
|
33761
34324
|
}
|
|
33762
34325
|
if (signature?.v !== 1 || typeof signature.id !== "string" || item.id !== signature.id || item.phase !== signature.phase || part.text !== block.text.replace(/^§\d+§ /u, ""))
|
|
33763
34326
|
return texts;
|
|
33764
|
-
replay.push(
|
|
34327
|
+
replay.push(textIdentity2(wellFormed(part.text), item.phase));
|
|
33765
34328
|
}
|
|
33766
34329
|
}
|
|
33767
34330
|
return replay.length === texts.length ? replay : texts;
|
|
@@ -33770,7 +34333,7 @@ function piResponsesWireTexts(value, phase) {
|
|
|
33770
34333
|
if (phase !== undefined && phase !== null && phase !== "commentary" && phase !== "final_answer")
|
|
33771
34334
|
return;
|
|
33772
34335
|
if (typeof value === "string")
|
|
33773
|
-
return [
|
|
34336
|
+
return [textIdentity2(value, phase)];
|
|
33774
34337
|
if (!Array.isArray(value))
|
|
33775
34338
|
return;
|
|
33776
34339
|
const texts = [];
|
|
@@ -33782,7 +34345,7 @@ function piResponsesWireTexts(value, phase) {
|
|
|
33782
34345
|
units += part.text.length;
|
|
33783
34346
|
if (units > MAX_TEXT_UNITS)
|
|
33784
34347
|
return;
|
|
33785
|
-
texts.push(
|
|
34348
|
+
texts.push(textIdentity2(part.text, phase));
|
|
33786
34349
|
}
|
|
33787
34350
|
return texts;
|
|
33788
34351
|
}
|
|
@@ -35775,17 +36338,26 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
35775
36338
|
return { rebuildReason: "lkg_recovery_input_rebuild" };
|
|
35776
36339
|
return { prefix };
|
|
35777
36340
|
};
|
|
35778
|
-
const
|
|
35779
|
-
const state = stateFor(snapshot.sessionId);
|
|
36341
|
+
const recoveryEntryIds = (snapshot) => {
|
|
35780
36342
|
const anchor = snapshot.replayAnchorInputIndex;
|
|
35781
36343
|
const slot = getSlot(snapshot.sessionId);
|
|
35782
36344
|
if (snapshot.preparationFailure || anchor === null || !slot?.piOutputEntryIds)
|
|
35783
36345
|
throw new PiLkgUncapturable("lkg_output_mapping_unavailable", "Cannot retain recovered output ownership");
|
|
35784
36346
|
const surviving = new Set(snapshot.inputs.map((input) => input.id));
|
|
35785
|
-
|
|
36347
|
+
return [
|
|
35786
36348
|
...slot.piOutputEntryIds.filter((id) => id === null || surviving.has(id)),
|
|
35787
36349
|
...snapshot.inputs.slice(anchor + 1).map((input) => input.id)
|
|
35788
36350
|
];
|
|
36351
|
+
};
|
|
36352
|
+
const noteRecovery = (snapshot, messages, entryIds) => {
|
|
36353
|
+
const state = stateFor(snapshot.sessionId);
|
|
36354
|
+
const slot = getSlot(snapshot.sessionId);
|
|
36355
|
+
if (!slot)
|
|
36356
|
+
throw new PiLkgUncapturable("lkg_miss", "Cannot retain recovery without a saved request");
|
|
36357
|
+
const anchor = snapshot.replayAnchorInputIndex;
|
|
36358
|
+
if (anchor === null)
|
|
36359
|
+
throw new PiLkgUncapturable("lkg_miss", "Cannot retain recovery without an input anchor");
|
|
36360
|
+
const outputEntryIds = entryIds ?? recoveryEntryIds(snapshot);
|
|
35789
36361
|
if (outputEntryIds.length !== messages.length)
|
|
35790
36362
|
throw new PiLkgUncapturable("lkg_output_mapping_unavailable", "Recovered output ownership does not match the served array");
|
|
35791
36363
|
state.recoveryPrefix = {
|
|
@@ -36202,6 +36774,7 @@ function createPiLkgCoordinator(db, scheduleCapture = (capture) => setImmediate(
|
|
|
36202
36774
|
};
|
|
36203
36775
|
return {
|
|
36204
36776
|
noteRecovery,
|
|
36777
|
+
recoveryEntryIds,
|
|
36205
36778
|
recoveryFor,
|
|
36206
36779
|
beginPass(args) {
|
|
36207
36780
|
return {
|
|
@@ -36603,7 +37176,7 @@ function flushPiServedArrayLedger() {
|
|
|
36603
37176
|
function scheduleFlush() {
|
|
36604
37177
|
if (flushTimer)
|
|
36605
37178
|
return;
|
|
36606
|
-
flushTimer = setTimeout(flushPiServedArrayLedger, FLUSH_DELAY_MS);
|
|
37179
|
+
flushTimer = inRootAsyncContext2(() => setTimeout(flushPiServedArrayLedger, FLUSH_DELAY_MS));
|
|
36607
37180
|
flushTimer.unref?.();
|
|
36608
37181
|
}
|
|
36609
37182
|
function enqueue(filePath, line, assertCurrentPass) {
|
|
@@ -38557,31 +39130,61 @@ function isLargeImagePart(value) {
|
|
|
38557
39130
|
const part = value;
|
|
38558
39131
|
return part.type === "image" && typeof part.mimeType === "string" && part.mimeType.startsWith("image/") && typeof part.data === "string" && part.data.length > 200;
|
|
38559
39132
|
}
|
|
38560
|
-
function
|
|
38561
|
-
|
|
38562
|
-
|
|
38563
|
-
|
|
38564
|
-
|
|
38565
|
-
|
|
38566
|
-
|
|
38567
|
-
|
|
38568
|
-
|
|
38569
|
-
|
|
38570
|
-
|
|
38571
|
-
|
|
38572
|
-
|
|
39133
|
+
function planPiProcessedImageIds(args, frozenIds) {
|
|
39134
|
+
if (!args.detect || args.watermark <= 0)
|
|
39135
|
+
return [];
|
|
39136
|
+
const ids = args.messages.map(args.stableId);
|
|
39137
|
+
const ownTags = ids.map((id) => id ? args.messageIdToMaxTag.get(id) ?? 0 : 0);
|
|
39138
|
+
const completeToolResults = new Set;
|
|
39139
|
+
const openCalls = new Map;
|
|
39140
|
+
for (let i = 0;i < args.messages.length; i++) {
|
|
39141
|
+
const message = args.messages[i];
|
|
39142
|
+
if (!message || typeof message !== "object")
|
|
39143
|
+
continue;
|
|
39144
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
39145
|
+
for (const part of message.content) {
|
|
39146
|
+
if (part?.type === "toolCall" && typeof part.id === "string") {
|
|
39147
|
+
openCalls.set(part.id, `${ids[i] ?? ""}\x00${part.id}`);
|
|
39148
|
+
}
|
|
38573
39149
|
}
|
|
38574
|
-
|
|
38575
|
-
|
|
39150
|
+
} else if (message.role === "toolResult" && message.toolCallId) {
|
|
39151
|
+
const key = openCalls.get(message.toolCallId);
|
|
39152
|
+
if (key !== undefined && !args.protectedToolKeys?.has(key) && !args.protectedToolKeys?.has(message.toolCallId)) {
|
|
39153
|
+
completeToolResults.add(i);
|
|
38576
39154
|
}
|
|
38577
|
-
|
|
38578
|
-
if (!id || frozenIds.has(id))
|
|
38579
|
-
continue;
|
|
38580
|
-
const maxTag = args.messageIdToMaxTag.get(id) ?? 0;
|
|
38581
|
-
if (maxTag <= args.watermark)
|
|
38582
|
-
newlyStrippedIds.push(id);
|
|
39155
|
+
openCalls.delete(message.toolCallId);
|
|
38583
39156
|
}
|
|
38584
39157
|
}
|
|
39158
|
+
const selected = [];
|
|
39159
|
+
let hasAssistantResponse = false;
|
|
39160
|
+
let nextTag;
|
|
39161
|
+
for (let i = args.messages.length - 1;i >= 0; i--) {
|
|
39162
|
+
const ownTag = ownTags[i];
|
|
39163
|
+
const positionTag = ownTag > 0 ? ownTag : nextTag;
|
|
39164
|
+
if (ownTag > 0)
|
|
39165
|
+
nextTag = ownTag;
|
|
39166
|
+
const raw = args.messages[i];
|
|
39167
|
+
if (!raw || typeof raw !== "object")
|
|
39168
|
+
continue;
|
|
39169
|
+
const message = raw;
|
|
39170
|
+
if (message.role === "assistant") {
|
|
39171
|
+
hasAssistantResponse = true;
|
|
39172
|
+
continue;
|
|
39173
|
+
}
|
|
39174
|
+
if (message.role !== "user" && message.role !== "toolResult" || message.role === "toolResult" && !completeToolResults.has(i) || !hasAssistantResponse || !Array.isArray(message.content) || !message.content.some(isLargeImagePart))
|
|
39175
|
+
continue;
|
|
39176
|
+
const id = ids[i];
|
|
39177
|
+
if (!id || frozenIds.has(id) || positionTag === undefined || positionTag > args.watermark)
|
|
39178
|
+
continue;
|
|
39179
|
+
if ((args.usagePercentage ?? 0) < 95 && positionTag >= (args.protectedCutoff ?? Infinity))
|
|
39180
|
+
continue;
|
|
39181
|
+
selected.push(id);
|
|
39182
|
+
}
|
|
39183
|
+
return selected;
|
|
39184
|
+
}
|
|
39185
|
+
function stripPiProcessedImages(args) {
|
|
39186
|
+
const frozenIds = getProcessedImageStrippedIds(args.db, args.sessionId);
|
|
39187
|
+
const newlyStrippedIds = planPiProcessedImageIds(args, frozenIds);
|
|
38585
39188
|
if (newlyStrippedIds.length > 0) {
|
|
38586
39189
|
const persisted = (args.addIds ?? addProcessedImageStrippedIds)(args.db, args.sessionId, newlyStrippedIds);
|
|
38587
39190
|
if (persisted) {
|
|
@@ -38833,6 +39436,9 @@ function createPiTranscript(source, sessionId, entryIds, options = {}) {
|
|
|
38833
39436
|
if (committed)
|
|
38834
39437
|
return;
|
|
38835
39438
|
committed = true;
|
|
39439
|
+
for (const index of dirtyMessages) {
|
|
39440
|
+
rewriteNativeAssistantTexts(working[index], source[index], sessionId);
|
|
39441
|
+
}
|
|
38836
39442
|
for (const [index, parts] of removals) {
|
|
38837
39443
|
const message = working[index];
|
|
38838
39444
|
if (message.role !== "assistant" && message.role !== "toolResult" || !Array.isArray(message.content))
|
|
@@ -39225,6 +39831,8 @@ function createPiAssistantPart(working, messageIndex, partIndex, markDirty) {
|
|
|
39225
39831
|
...existing,
|
|
39226
39832
|
arguments: { dropped: sentinelText }
|
|
39227
39833
|
};
|
|
39834
|
+
} else if (existing?.type === "text") {
|
|
39835
|
+
newContent[partIndex] = { ...existing, text: sentinelText };
|
|
39228
39836
|
} else {
|
|
39229
39837
|
newContent[partIndex] = { type: "text", text: sentinelText };
|
|
39230
39838
|
}
|
|
@@ -41043,7 +41651,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
41043
41651
|
const passGuard = { assert: assertCurrentPass, wait: guardAwait };
|
|
41044
41652
|
guardSqliteTransformPass2({
|
|
41045
41653
|
assert: assertCurrentPass,
|
|
41046
|
-
remainingMs:
|
|
41654
|
+
remainingMs: budget.remainingWork
|
|
41047
41655
|
});
|
|
41048
41656
|
budget.stage = "schema";
|
|
41049
41657
|
const toolWireSchema = await guardAwait(loadPiToolWireSchema());
|
|
@@ -41053,6 +41661,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
41053
41661
|
let sessionIdForError;
|
|
41054
41662
|
let lkgPassSnapshot;
|
|
41055
41663
|
let lkgCompactionOff = baseOptions.compactionOff === true;
|
|
41664
|
+
let lkgOptions = baseOptions;
|
|
41056
41665
|
let lkgEmergencyRecoveryArmed = false;
|
|
41057
41666
|
const captureServedEvidence = (...args) => {
|
|
41058
41667
|
try {
|
|
@@ -41083,6 +41692,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
41083
41692
|
rawMessageCount = event.messages.length;
|
|
41084
41693
|
const fullWireMessageCount = rawMessageCount;
|
|
41085
41694
|
const options = baseOptions.resolveForProject?.(projectDirectory) ?? baseOptions;
|
|
41695
|
+
lkgOptions = options;
|
|
41086
41696
|
const deliveryModelKey = resolvePiContextModelKey(ctx);
|
|
41087
41697
|
if (!budget.sideTurn && deliveryModelKey) {
|
|
41088
41698
|
const parentId = ctx.sessionManager.getLeafId?.();
|
|
@@ -41682,7 +42292,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
41682
42292
|
if (historian && !options.compactionOff && budget.remainingWork() > 0) {
|
|
41683
42293
|
guardSqliteTransformPass2({
|
|
41684
42294
|
assert: budget.assert,
|
|
41685
|
-
remainingMs:
|
|
42295
|
+
remainingMs: budget.remainingWork
|
|
41686
42296
|
});
|
|
41687
42297
|
try {
|
|
41688
42298
|
budget.assert();
|
|
@@ -41762,7 +42372,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
41762
42372
|
if (options.autoSearch?.enabled && !options.compactionOff && result.prefixMutationAllowed && budget.remainingWork() > PI_CONTEXT_BUDGET.searchMs) {
|
|
41763
42373
|
guardSqliteTransformPass2({
|
|
41764
42374
|
assert: budget.assert,
|
|
41765
|
-
remainingMs:
|
|
42375
|
+
remainingMs: budget.remainingWork
|
|
41766
42376
|
});
|
|
41767
42377
|
try {
|
|
41768
42378
|
outputMessages = await guardAwait(runAutoSearchHintForPi({
|
|
@@ -42172,7 +42782,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
42172
42782
|
budget.assertOutcome();
|
|
42173
42783
|
guardSqliteTransformPass2({
|
|
42174
42784
|
assert: budget.assertOutcome,
|
|
42175
|
-
remainingMs:
|
|
42785
|
+
remainingMs: budget.remainingOutcome
|
|
42176
42786
|
});
|
|
42177
42787
|
if (!budget.sideTurn && !lkgCompactionOff && lkgPassSnapshot && (rawMessageCount > 0 || result.servedTagNumbers?.size)) {
|
|
42178
42788
|
let hostEnvelopeSignature;
|
|
@@ -42301,14 +42911,38 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
42301
42911
|
reason: lkgPassSnapshot.replayFailure ?? "lkg_recovery_unproven"
|
|
42302
42912
|
} : lkgCoordinator.replay(lkgPassSnapshot, (id) => ctx.sessionManager.getEntry?.(id)?.parentId);
|
|
42303
42913
|
if (replay.ok) {
|
|
42914
|
+
const reasoningPrefixes = recoveryReasoningPrefixes(replay.messages, "content");
|
|
42915
|
+
const entryIds = lkgCoordinator.recoveryEntryIds(lkgPassSnapshot);
|
|
42916
|
+
const recoverySessionId = sessionIdForError;
|
|
42917
|
+
const recoveryTranscript = createPiTranscript(replay.messages, sessionIdForError, entryIds.map((id) => id ?? undefined), {
|
|
42918
|
+
preserveReasoningToolArcs: ctx.model?.api !== "openai-codex-responses" && ctx.model?.api !== "openai-responses",
|
|
42919
|
+
authorizeToolRemoval: (callId) => authorizePiToolRemoval({
|
|
42920
|
+
db: lkgOptions.db,
|
|
42921
|
+
sessionId: recoverySessionId,
|
|
42922
|
+
callId,
|
|
42923
|
+
saved: getNativeReplayState(lkgOptions.db, recoverySessionId).toolInputs,
|
|
42924
|
+
canApply: false
|
|
42925
|
+
})
|
|
42926
|
+
});
|
|
42927
|
+
const drops = getTagsBySession2(lkgOptions.db, sessionIdForError).filter((tag) => tag.status === "dropped");
|
|
42928
|
+
const changed = applyFlushedStatuses(sessionIdForError, lkgOptions.db, buildPersistedDropTargets(recoveryTranscript, drops, {
|
|
42929
|
+
allowReasoningPrefixRewrite: true
|
|
42930
|
+
}), drops);
|
|
42931
|
+
const working = recoveryTranscript.getWorkingMessages();
|
|
42932
|
+
recoveryTranscript.commit();
|
|
42933
|
+
const idsByOutput = new Map(working.map((message, index) => [message, entryIds[index]]));
|
|
42934
|
+
recoveryTranscript.finalizeToolRemovals();
|
|
42935
|
+
if (JSON.stringify(recoveryReasoningPrefixes(replay.messages, "content")) !== JSON.stringify(reasoningPrefixes))
|
|
42936
|
+
throw new DegradedPassRefusalError("lkg-reasoning-prefix-changed", { cause: err });
|
|
42937
|
+
const recoveryIds = replay.messages.map((message) => idsByOutput.get(message) ?? null);
|
|
42304
42938
|
assertPiRawFallbackFits(replay.messages, rawFallbackLimit, (line) => {
|
|
42305
42939
|
if (sessionIdForError)
|
|
42306
42940
|
logPiLkgRecovery(sessionIdForError, line);
|
|
42307
|
-
}, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError), toolWireSchema), replay.measuredPrefix);
|
|
42941
|
+
}, err, readPiLkgFitEnvelope(ctx, pi, resolvePiContextModelKey(ctx), sessionDecisionCalibration(baseOptions.db, sessionIdForError), toolWireSchema), changed ? undefined : replay.measuredPrefix);
|
|
42308
42942
|
const reason = piStorageErrorReason(err);
|
|
42309
42943
|
logPiLkgRecovery(sessionIdForError, `${failureLabel} ${reason}: LKG replay served ${replay.messages.length} messages instead of raw ${rawMessageCount}`);
|
|
42310
42944
|
budget.assertOutcome();
|
|
42311
|
-
lkgCoordinator.noteRecovery(lkgPassSnapshot, replay.messages);
|
|
42945
|
+
lkgCoordinator.noteRecovery(lkgPassSnapshot, replay.messages, recoveryIds);
|
|
42312
42946
|
if (!budget.sideTurn)
|
|
42313
42947
|
captureServedEvidence(sessionIdForError, replay.messages, {
|
|
42314
42948
|
recoveryWithoutTagState: true,
|
|
@@ -42321,6 +42955,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
42321
42955
|
logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG unavailable (${replay.reason}); refusing unreduced ${rawMessageCount}-message input`);
|
|
42322
42956
|
} catch (replayError) {
|
|
42323
42957
|
budget.assertOutcome();
|
|
42958
|
+
if (replayError instanceof DegradedPassRefusalError)
|
|
42959
|
+
throw replayError;
|
|
42324
42960
|
if (replayError instanceof PiStorageBusyError)
|
|
42325
42961
|
throw replayError;
|
|
42326
42962
|
logPiLkgRecovery(sessionIdForError, `${failureLabel} ${piStorageErrorReason(err)}: LKG replay unavailable (${replayError instanceof Error ? replayError.message : String(replayError)}); refusing unreduced ${rawMessageCount}-message input`);
|
|
@@ -42415,7 +43051,7 @@ function resolveHistoryBudgetTokensForPi(args) {
|
|
|
42415
43051
|
}) / 100) * historyBudgetPercentage);
|
|
42416
43052
|
}
|
|
42417
43053
|
function startPiCompartmentLeaseRenewal(db, sessionId, holderId) {
|
|
42418
|
-
return setInterval(() => {
|
|
43054
|
+
return inRootAsyncContext2(() => setInterval(() => {
|
|
42419
43055
|
try {
|
|
42420
43056
|
if (!renewCompartmentLease(db, sessionId, holderId)) {
|
|
42421
43057
|
sessionLog2(sessionId, "compartment lease renewal failed; publish will be skipped if holder is stale");
|
|
@@ -42423,7 +43059,7 @@ function startPiCompartmentLeaseRenewal(db, sessionId, holderId) {
|
|
|
42423
43059
|
} catch (err) {
|
|
42424
43060
|
sessionLog2(sessionId, `compartment lease renewal threw; publish will be skipped if holder is stale (${err instanceof Error ? err.message : String(err)})`);
|
|
42425
43061
|
}
|
|
42426
|
-
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
43062
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS));
|
|
42427
43063
|
}
|
|
42428
43064
|
function ensureRunnablePiBoundaryForTests(snapshot) {
|
|
42429
43065
|
if (true) {
|
|
@@ -42483,7 +43119,7 @@ function spawnPiHistorianRun(args) {
|
|
|
42483
43119
|
const holderId = crypto3.randomUUID();
|
|
42484
43120
|
const controller = new AbortController;
|
|
42485
43121
|
historianAbortControllers.set(sessionId, controller);
|
|
42486
|
-
const runPromise =
|
|
43122
|
+
const runPromise = inRootAsyncContext2(() => (async () => {
|
|
42487
43123
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
42488
43124
|
if (controller.signal.aborted)
|
|
42489
43125
|
return;
|
|
@@ -43638,7 +44274,7 @@ async function runPipeline(args) {
|
|
|
43638
44274
|
protectedToolTags,
|
|
43639
44275
|
protectedCutoff: usesTokenProtection ? protectionWindowForPass.cutoff : undefined,
|
|
43640
44276
|
routine: routineCleanupApplied,
|
|
43641
|
-
staleReduceStripEnabled:
|
|
44277
|
+
staleReduceStripEnabled: true,
|
|
43642
44278
|
onStaleReduceEdit: recordStaleReduceEdit,
|
|
43643
44279
|
emergency: args.forceMaterialization === true && args.emergencyCeilingTokens !== undefined && args.emergencyCeilingTokens > 0 ? {
|
|
43644
44280
|
currentTotalInputTokens: args.contextUsage.inputTokens,
|
|
@@ -43654,7 +44290,7 @@ async function runPipeline(args) {
|
|
|
43654
44290
|
protectedToolTags,
|
|
43655
44291
|
protectedCutoff: usesTokenProtection ? protectionWindowForPass.cutoff : undefined,
|
|
43656
44292
|
routine: true,
|
|
43657
|
-
staleReduceStripEnabled:
|
|
44293
|
+
staleReduceStripEnabled: true,
|
|
43658
44294
|
onStaleReduceEdit: recordStaleReduceEdit,
|
|
43659
44295
|
caveman: args.isSubagent ? undefined : args.heuristics.caveman
|
|
43660
44296
|
}, getActiveTagsBySession2(args.db, args.sessionId), stableIdResolver);
|
|
@@ -43840,16 +44476,50 @@ async function runPipeline(args) {
|
|
|
43840
44476
|
}
|
|
43841
44477
|
}
|
|
43842
44478
|
}
|
|
43843
|
-
|
|
44479
|
+
{
|
|
43844
44480
|
const tProcessedImages = performance.now();
|
|
43845
44481
|
try {
|
|
44482
|
+
const imagePositionTags = new Map;
|
|
44483
|
+
const noteImagePosition = (id, tag) => {
|
|
44484
|
+
if (id && tag > (imagePositionTags.get(id) ?? 0))
|
|
44485
|
+
imagePositionTags.set(id, tag);
|
|
44486
|
+
};
|
|
44487
|
+
for (const [tagNumber, target] of targets) {
|
|
44488
|
+
for (const { message, part } of target.mutationParts ?? []) {
|
|
44489
|
+
if (typeof part === "object" && part !== null && "kind" in part && part.kind === "text")
|
|
44490
|
+
noteImagePosition(message.info.id, tagNumber);
|
|
44491
|
+
}
|
|
44492
|
+
}
|
|
44493
|
+
const imageToolTags = new Map(allTagsForPass.filter((tag) => tag.type === "tool").map((tag) => [
|
|
44494
|
+
`${tag.toolOwnerMessageId ?? ""}\x00${tag.messageId}`,
|
|
44495
|
+
tag.tagNumber
|
|
44496
|
+
]));
|
|
44497
|
+
const imageToolOwners = new Map;
|
|
44498
|
+
for (let index = 0;index < workingMessages.length; index++) {
|
|
44499
|
+
const message = workingMessages[index];
|
|
44500
|
+
const id = stableIdResolver(message, index);
|
|
44501
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
44502
|
+
for (const part of message.content) {
|
|
44503
|
+
if (part.type !== "toolCall")
|
|
44504
|
+
continue;
|
|
44505
|
+
imageToolOwners.set(part.id, id ?? "");
|
|
44506
|
+
noteImagePosition(id, imageToolTags.get(`${id ?? ""}\x00${part.id}`) ?? 0);
|
|
44507
|
+
}
|
|
44508
|
+
} else if (message.role === "toolResult") {
|
|
44509
|
+
noteImagePosition(id, imageToolTags.get(`${imageToolOwners.get(message.toolCallId) ?? ""}\x00${message.toolCallId}`) ?? 0);
|
|
44510
|
+
}
|
|
44511
|
+
}
|
|
44512
|
+
const protectedImageToolKeys = new Set(activeTags.filter((tag) => tag.type === "tool" && protectedToolTags.has(tag.tagNumber)).map((tag) => tag.toolOwnerMessageId ? `${tag.toolOwnerMessageId}\x00${tag.messageId}` : tag.messageId));
|
|
43846
44513
|
const imageResult = stripPiProcessedImages({
|
|
43847
44514
|
db: args.db,
|
|
43848
44515
|
sessionId: args.sessionId,
|
|
43849
44516
|
messages: workingMessages,
|
|
43850
44517
|
detect: isCacheBustingPass && !protectedSignedPrefix,
|
|
43851
44518
|
watermark: getMaxDroppedTagNumber2(args.db, args.sessionId),
|
|
43852
|
-
messageIdToMaxTag,
|
|
44519
|
+
messageIdToMaxTag: imagePositionTags,
|
|
44520
|
+
protectedCutoff: usesTokenProtection ? protectionWindowForPass.cutoff : protectedTagNumbersForPass.size > 0 ? Math.min(...protectedTagNumbersForPass) : null,
|
|
44521
|
+
usagePercentage: args.contextUsage.percentage,
|
|
44522
|
+
protectedToolKeys: protectedImageToolKeys,
|
|
43853
44523
|
stableId: stableIdResolver,
|
|
43854
44524
|
onFirstApplication: recordFirstApplicationAt
|
|
43855
44525
|
});
|
|
@@ -43999,6 +44669,18 @@ async function runPipeline(args) {
|
|
|
43999
44669
|
const deferredHistoryDrainEligible = historyWasConsumedThisPass && materializationSatisfiedThisPass && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal) && !suppressDeferredHistoryDrain && !casLost;
|
|
44000
44670
|
let preserveDeferredMaterializationForMarkerDrain = false;
|
|
44001
44671
|
let pendingForDrain = null;
|
|
44672
|
+
if (!deferredHistoryDrainEligible && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal)) {
|
|
44673
|
+
try {
|
|
44674
|
+
const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
|
|
44675
|
+
if (pending)
|
|
44676
|
+
logPiCompactionMarkerDrainGateOnce(args.sessionId, pending, "drain-not-eligible", {
|
|
44677
|
+
historyConsumed: historyWasConsumedThisPass,
|
|
44678
|
+
materializationSatisfied: materializationSatisfiedThisPass,
|
|
44679
|
+
drainSuppressed: suppressDeferredHistoryDrain,
|
|
44680
|
+
casLost
|
|
44681
|
+
});
|
|
44682
|
+
} catch {}
|
|
44683
|
+
}
|
|
44002
44684
|
if (deferredHistoryDrainEligible) {
|
|
44003
44685
|
try {
|
|
44004
44686
|
args.assertCurrentPass?.();
|
|
@@ -44073,7 +44755,7 @@ async function runPipeline(args) {
|
|
|
44073
44755
|
if (outcome.kind === "waiting-for-entry") {
|
|
44074
44756
|
suppressDeferredHistoryDrain = true;
|
|
44075
44757
|
preserveDeferredMaterializationForMarkerDrain = true;
|
|
44076
|
-
} else if (outcome.kind === "retryable-failure") {} else if (markerEquivalent && clearPendingPiCompactionMarkerStateIf(args.db, args.sessionId, pending)) {
|
|
44758
|
+
} else if (outcome.kind === "retryable-failure") {} else if (markerEquivalent && clearPendingPiCompactionMarkerStateIf(args.db, args.sessionId, pending, outcome.kind === "stale-skip" ? outcome.reason : outcome.kind)) {
|
|
44077
44759
|
consumeDeferredHistoryRefresh(args.sessionId);
|
|
44078
44760
|
} else if (markerEquivalent) {
|
|
44079
44761
|
casLost = true;
|
|
@@ -44291,12 +44973,6 @@ function applyNoteNudges(args) {
|
|
|
44291
44973
|
for (const anchor of noteAnchors) {
|
|
44292
44974
|
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, anchor.messageId, anchor.text);
|
|
44293
44975
|
}
|
|
44294
|
-
const autoSearchDecisions = args.postTransformSnapshot?.autoSearchDecisions ?? getAutoSearchHintDecisions(db, sessionId);
|
|
44295
|
-
for (const decision of autoSearchDecisions) {
|
|
44296
|
-
if (decision.decision === "hint" && getUnpublishedAutoSearchNoHint(sessionId, decision.messageId) === undefined) {
|
|
44297
|
-
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, decision.messageId, decision.text);
|
|
44298
|
-
}
|
|
44299
|
-
}
|
|
44300
44976
|
logTransformTiming(sessionId, "stickyReplayDecisions", tStickyReplay);
|
|
44301
44977
|
const latestUser = findLatestUserMessageIdPi(messages, messageIdByIndex);
|
|
44302
44978
|
const latestUserId = latestUser?.messageId ?? null;
|
|
@@ -44306,7 +44982,7 @@ function applyNoteNudges(args) {
|
|
|
44306
44982
|
userMessageIds: [...messageIdByIndex].filter(([index]) => messages[index]?.role === "user").map(([, id]) => id),
|
|
44307
44983
|
anchorMessageId: latestUserId,
|
|
44308
44984
|
isLiveTail: latestUser?.index === messages.length - 1,
|
|
44309
|
-
|
|
44985
|
+
prefixRewriteCoversAnchor: false
|
|
44310
44986
|
});
|
|
44311
44987
|
const noteReadStillVisible = hasVisibleNoteReadCallPi(messages);
|
|
44312
44988
|
const deferredNoteText = args.postTransformSnapshot?.noteTriggerPending === false ? null : peekNoteNudgeText(db, sessionId, latestUserId, projectIdentity, noteReadStillVisible, eligibility);
|
|
@@ -44330,6 +45006,12 @@ function applyNoteNudges(args) {
|
|
|
44330
45006
|
sessionLog2(sessionId, `Pi note-nudge delivery skipped wire append: ${outcome.kind}`);
|
|
44331
45007
|
}
|
|
44332
45008
|
}
|
|
45009
|
+
const autoSearchDecisions = args.postTransformSnapshot?.autoSearchDecisions ?? getAutoSearchHintDecisions(db, sessionId);
|
|
45010
|
+
for (const decision of autoSearchDecisions) {
|
|
45011
|
+
if (decision.decision === "hint" && getUnpublishedAutoSearchNoHint(sessionId, decision.messageId) === undefined) {
|
|
45012
|
+
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, decision.messageId, decision.text);
|
|
45013
|
+
}
|
|
45014
|
+
}
|
|
44333
45015
|
if (args.isCacheBusting) {
|
|
44334
45016
|
const visibleIds = new Set(messageIdByIndex.values());
|
|
44335
45017
|
const realMessageCount = Math.max(0, messages.length - (args.syntheticLeadingCount ?? 0));
|
|
@@ -44588,6 +45270,7 @@ function createPiHistorianClient(args) {
|
|
|
44588
45270
|
model: modelOverride?.model ?? args.model,
|
|
44589
45271
|
fallbackModels: modelOverride ? undefined : args.fallbackModels,
|
|
44590
45272
|
timeoutMs: args.timeoutMs,
|
|
45273
|
+
maxOutputTokens: args.maxOutputTokens,
|
|
44591
45274
|
cwd: args.directory,
|
|
44592
45275
|
thinkingLevel: modelOverride ? modelOverride.qualifier : args.thinkingLevel,
|
|
44593
45276
|
accountingSessionId: args.accountingSessionId,
|
|
@@ -45002,6 +45685,7 @@ Recomp started. Rebuilding the compressed history from raw session history now;
|
|
|
45002
45685
|
systemPrompt: withContentLanguageDirective(COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT, currentDeps.language, { preserveUserQuotes: true }),
|
|
45003
45686
|
fallbackModels: currentDeps.historianFallbacks,
|
|
45004
45687
|
timeoutMs: currentDeps.historianTimeoutMs,
|
|
45688
|
+
maxOutputTokens: currentDeps.historianMaxOutputTokens,
|
|
45005
45689
|
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
45006
45690
|
directory: cwd,
|
|
45007
45691
|
accountingSessionId: sessionId,
|
|
@@ -46227,14 +46911,14 @@ class StatusDialogComponent {
|
|
|
46227
46911
|
this.detailRefresh = new PiStatusDetailRefresh(props.pi, props.ctx, props.deps, props.sessionId);
|
|
46228
46912
|
this.detail = this.detailRefresh.refresh();
|
|
46229
46913
|
openStatusDialogs.add(this);
|
|
46230
|
-
this.refreshTimer = setInterval(() => {
|
|
46914
|
+
this.refreshTimer = inRootAsyncContext2(() => setInterval(() => {
|
|
46231
46915
|
if (this.closed)
|
|
46232
46916
|
return;
|
|
46233
46917
|
try {
|
|
46234
46918
|
this.detail = this.detailRefresh.refresh();
|
|
46235
46919
|
this.props.tui.requestRender();
|
|
46236
46920
|
} catch {}
|
|
46237
|
-
}, REFRESH_INTERVAL_MS);
|
|
46921
|
+
}, REFRESH_INTERVAL_MS));
|
|
46238
46922
|
}
|
|
46239
46923
|
handleInput(data) {
|
|
46240
46924
|
if (this.closed)
|
|
@@ -47149,7 +47833,7 @@ No runnable wrapup boundary is available yet; wrapped up 0 messages into 0 compa
|
|
|
47149
47833
|
}
|
|
47150
47834
|
return true;
|
|
47151
47835
|
};
|
|
47152
|
-
const renewal = setInterval(() => {
|
|
47836
|
+
const renewal = inRootAsyncContext2(() => setInterval(() => {
|
|
47153
47837
|
try {
|
|
47154
47838
|
renewWrapupMarker({
|
|
47155
47839
|
lastCompartmentEnd: getLastCompartmentEndMessage(deps.db, sessionId)
|
|
@@ -47157,7 +47841,7 @@ No runnable wrapup boundary is available yet; wrapped up 0 messages into 0 compa
|
|
|
47157
47841
|
} catch (err) {
|
|
47158
47842
|
sessionLog2(sessionId, `[pi] /ctx-wrapup marker renewal failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
47159
47843
|
}
|
|
47160
|
-
}, 60000);
|
|
47844
|
+
}, 60000));
|
|
47161
47845
|
const stopRenewal = () => clearInterval(renewal);
|
|
47162
47846
|
deps.shutdownSignal?.addEventListener("abort", stopRenewal, { once: true });
|
|
47163
47847
|
try {
|
|
@@ -47232,13 +47916,13 @@ Chunk ${chunkIndex}: wrapping messages ${plan.snapshot.offset}-${plan.snapshot.e
|
|
|
47232
47916
|
break;
|
|
47233
47917
|
}
|
|
47234
47918
|
const leaseHolder = leaseResult.holderId;
|
|
47235
|
-
const leaseRenewal = setInterval(() => {
|
|
47919
|
+
const leaseRenewal = inRootAsyncContext2(() => setInterval(() => {
|
|
47236
47920
|
try {
|
|
47237
47921
|
renewCompartmentLease(deps.db, sessionId, leaseHolder);
|
|
47238
47922
|
} catch (err) {
|
|
47239
47923
|
sessionLog2(sessionId, `[pi] /ctx-wrapup compartment lease renewal failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
47240
47924
|
}
|
|
47241
|
-
}, COMPARTMENT_LEASE_RENEWAL_MS);
|
|
47925
|
+
}, COMPARTMENT_LEASE_RENEWAL_MS));
|
|
47242
47926
|
const stopLeaseRenewal = () => clearInterval(leaseRenewal);
|
|
47243
47927
|
deps.shutdownSignal?.addEventListener("abort", stopLeaseRenewal, {
|
|
47244
47928
|
once: true
|
|
@@ -47272,6 +47956,7 @@ Chunk ${chunkIndex}: wrapping messages ${plan.snapshot.offset}-${plan.snapshot.e
|
|
|
47272
47956
|
}).snapshot,
|
|
47273
47957
|
currentContextLimit: contextLimit,
|
|
47274
47958
|
historianTimeoutMs: deps.historianTimeoutMs,
|
|
47959
|
+
maxOutputTokens: deps.historianMaxOutputTokens,
|
|
47275
47960
|
thinkingLevel: deps.historianThinkingLevel,
|
|
47276
47961
|
memoryEnabled: deps.memoryEnabled,
|
|
47277
47962
|
autoPromote: deps.autoPromote,
|
|
@@ -47403,9 +48088,9 @@ function readPiWrapupBranchEntries(ctx) {
|
|
|
47403
48088
|
function observePiMessageActivity(db, sessionId, timestamp) {
|
|
47404
48089
|
observeSessionActivity(db, sessionId, timestamp);
|
|
47405
48090
|
}
|
|
47406
|
-
function latestPiMessageTime(path) {
|
|
48091
|
+
async function latestPiMessageTime(path) {
|
|
47407
48092
|
let latest = 0;
|
|
47408
|
-
for (const entry of
|
|
48093
|
+
for await (const entry of asyncSessionEntries(path)) {
|
|
47409
48094
|
const row = entry;
|
|
47410
48095
|
if (row.type === "message" && typeof row.message?.timestamp === "number")
|
|
47411
48096
|
latest = Math.max(latest, row.message.timestamp);
|
|
@@ -47413,12 +48098,12 @@ function latestPiMessageTime(path) {
|
|
|
47413
48098
|
return latest || undefined;
|
|
47414
48099
|
}
|
|
47415
48100
|
async function backfillPiSessionActivity(db, harness, paths) {
|
|
47416
|
-
await backfillSessionActivity(db, harness, (sessionId) => {
|
|
48101
|
+
await backfillSessionActivity(db, harness, async (sessionId) => {
|
|
47417
48102
|
const path = paths.get(sessionId);
|
|
47418
48103
|
if (!path)
|
|
47419
48104
|
return;
|
|
47420
48105
|
try {
|
|
47421
|
-
return latestPiMessageTime(path);
|
|
48106
|
+
return await latestPiMessageTime(path);
|
|
47422
48107
|
} catch {
|
|
47423
48108
|
return;
|
|
47424
48109
|
}
|
|
@@ -47625,6 +48310,18 @@ async function bootPiRuntimeWithDeadline(args) {
|
|
|
47625
48310
|
return { status: "timed_out", lateAdoption };
|
|
47626
48311
|
}
|
|
47627
48312
|
|
|
48313
|
+
// src/pi-historian-command-options.ts
|
|
48314
|
+
function buildPiHistorianCommandOptions(historian, config) {
|
|
48315
|
+
return {
|
|
48316
|
+
historianModel: historian?.model,
|
|
48317
|
+
historianChunkTokens: historian?.historianChunkTokens ?? deriveHistorianChunkTokens(resolveHistorianContextLimit(historian?.model)),
|
|
48318
|
+
historianFallbacks: historian?.fallbackModels,
|
|
48319
|
+
historianTimeoutMs: historian?.timeoutMs ?? config.historian_timeout_ms,
|
|
48320
|
+
historianMaxOutputTokens: historian?.maxOutputTokens,
|
|
48321
|
+
historianThinkingLevel: historian?.thinkingLevel
|
|
48322
|
+
};
|
|
48323
|
+
}
|
|
48324
|
+
|
|
47628
48325
|
// src/stale-build-notice.ts
|
|
47629
48326
|
function bindStaleBuildNotice(ctx, moduleUrl) {
|
|
47630
48327
|
registerStalePluginBuildHost({
|
|
@@ -48754,11 +49451,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
48754
49451
|
registerCtxRecompCommand(pi, {
|
|
48755
49452
|
db,
|
|
48756
49453
|
runner: recompRunner,
|
|
48757
|
-
|
|
48758
|
-
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(bootProjectDeps.historianConfig?.model)),
|
|
48759
|
-
historianFallbacks: bootProjectDeps.historianConfig?.fallbackModels,
|
|
48760
|
-
historianTimeoutMs: bootProjectDeps.config.historian_timeout_ms,
|
|
48761
|
-
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
49454
|
+
...buildPiHistorianCommandOptions(bootProjectDeps.historianConfig, bootProjectDeps.config),
|
|
48762
49455
|
language: bootProjectDeps.config.language,
|
|
48763
49456
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
48764
49457
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
@@ -48770,11 +49463,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
48770
49463
|
return {
|
|
48771
49464
|
db,
|
|
48772
49465
|
runner: recompRunner,
|
|
48773
|
-
|
|
48774
|
-
historianChunkTokens: historian?.historianChunkTokens ?? deriveHistorianChunkTokens(resolveHistorianContextLimit(historian?.model)),
|
|
48775
|
-
historianFallbacks: historian?.fallbackModels,
|
|
48776
|
-
historianTimeoutMs: historian?.timeoutMs ?? current.config.historian_timeout_ms,
|
|
48777
|
-
historianThinkingLevel: historian?.thinkingLevel,
|
|
49466
|
+
...buildPiHistorianCommandOptions(historian, current.config),
|
|
48778
49467
|
language: current.config.language,
|
|
48779
49468
|
memoryEnabled: current.config.memory.enabled,
|
|
48780
49469
|
autoPromote: fresh.memory.auto_promote,
|
|
@@ -48787,11 +49476,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
48787
49476
|
shutdownSignal: commandLifecycleController.signal,
|
|
48788
49477
|
db,
|
|
48789
49478
|
runner: wrapupRunner,
|
|
48790
|
-
|
|
48791
|
-
historianChunkTokens: deriveHistorianChunkTokens(resolveHistorianContextLimit(bootProjectDeps.historianConfig?.model)),
|
|
48792
|
-
historianFallbacks: bootProjectDeps.historianConfig?.fallbackModels,
|
|
48793
|
-
historianTimeoutMs: bootProjectDeps.config.historian_timeout_ms,
|
|
48794
|
-
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
49479
|
+
...buildPiHistorianCommandOptions(bootProjectDeps.historianConfig, bootProjectDeps.config),
|
|
48795
49480
|
language: bootProjectDeps.config.language,
|
|
48796
49481
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
48797
49482
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
@@ -48806,11 +49491,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
48806
49491
|
return {
|
|
48807
49492
|
db,
|
|
48808
49493
|
runner: wrapupRunner,
|
|
48809
|
-
|
|
48810
|
-
historianChunkTokens: historian?.historianChunkTokens ?? deriveHistorianChunkTokens(resolveHistorianContextLimit(historian?.model)),
|
|
48811
|
-
historianFallbacks: historian?.fallbackModels,
|
|
48812
|
-
historianTimeoutMs: historian?.timeoutMs ?? current.config.historian_timeout_ms,
|
|
48813
|
-
historianThinkingLevel: historian?.thinkingLevel,
|
|
49494
|
+
...buildPiHistorianCommandOptions(historian, current.config),
|
|
48814
49495
|
language: current.config.language,
|
|
48815
49496
|
memoryEnabled: current.config.memory.enabled,
|
|
48816
49497
|
autoPromote: fresh.memory.auto_promote,
|