@cortexkit/pi-magic-context 0.49.26 → 0.49.28
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 +4 -4
- package/dist/chunk-embedding-write-worker.js +8 -9
- package/dist/{compartment-chunk-embedding-vt6afvdm.js → compartment-chunk-embedding-pkk5beqp.js} +3 -3
- package/dist/{embedding-backfill-jc5fqt5s.js → embedding-backfill-25fp3b8w.js} +7 -7
- package/dist/{index-0dr64gsy.js → index-0s14xaca.js} +2 -2
- package/dist/{index-n8e5e9fp.js → index-0x1c054v.js} +1 -1
- package/dist/{index-hxp6q5f8.js → index-48twbev2.js} +50 -36
- package/dist/{index-j3pz3a1b.js → index-4zemngt7.js} +1 -1
- package/dist/{index-r1hvaza0.js → index-5d506f7y.js} +719 -23
- package/dist/{index-z24d75tz.js → index-6981g1xv.js} +0 -2
- package/dist/{index-zpmz6x24.js → index-bkcwcghx.js} +1308 -104
- package/dist/{index-g0d51qzc.js → index-bvpar0bg.js} +2 -5
- package/dist/{index-w1avzkdt.js → index-g026ztby.js} +1 -1
- package/dist/{index-rjnc6kkf.js → index-kagezf2h.js} +3 -3
- package/dist/{index-dnadppqx.js → index-kmk3xpf9.js} +1 -1
- package/dist/{index-zz7dnyh6.js → index-sdsnb5b6.js} +8 -8
- package/dist/index-v0ht940m.js +488 -0
- package/dist/{index-kbswhkc8.js → index-vea2d9ka.js} +1 -1
- package/dist/{index-w5v0ntbw.js → index-wjbqw6r1.js} +1 -1
- package/dist/{index-z6k6jsmh.js → index-xa90f88m.js} +3 -3
- package/dist/{index-wpy2rzb2.js → index-xw070axm.js} +3 -3
- package/dist/index.js +499 -440
- package/dist/{message-fts-rowid-map-xe3ss2g3.js → message-fts-rowid-map-3mbvdgn9.js} +2 -4
- package/dist/{message-index-bounded-2zffszp9.js → message-index-bounded-avbaa7wa.js} +19 -22
- package/dist/migration-worker.js +7 -8
- package/dist/{project-embedding-registry-bn9ts1h0.js → project-embedding-registry-hc4ahjdt.js} +6 -6
- package/dist/raw-ordinal-warmup-worker.js +7 -30
- package/dist/{read-session-chunk-p0cexvvs.js → read-session-chunk-1rfprgc1.js} +4 -4
- package/dist/{read-session-raw-mq03ws9v.js → read-session-raw-g9b1zdn5.js} +1 -1
- package/dist/{search-archive-jw2wm4tw.js → search-archive-mpjeecwj.js} +5 -5
- package/dist/{search-vmcbbwm5.js → search-vkkfg27q.js} +13 -14
- package/dist/{storage-tags-r48vxthe.js → storage-tags-9qaasrky.js} +2 -2
- package/dist/subagent-entry.js +17 -18
- package/dist/tag-snapshot-worker-pi.js +9 -10
- package/package.json +1 -1
- package/dist/index-87xm7z44.js +0 -2100
- package/dist/index-n4wyxcgr.js +0 -712
- package/dist/index-wrr9rp9a.js +0 -16
- package/dist/message-index-jv1m3g8d.js +0 -58
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
harnessOwnsOpenCodeStore2
|
|
5
5
|
} from "./index-0h2mkab2.js";
|
|
6
6
|
import {
|
|
7
|
-
getDataDir,
|
|
8
7
|
ensureCortexKitArtifactGitignore,
|
|
9
8
|
getProjectMagicContextHistorianDir,
|
|
10
9
|
getMagicContextStorageDir,
|
|
@@ -46,11 +45,21 @@ import {
|
|
|
46
45
|
cortexKitProjectConfigBasePath,
|
|
47
46
|
migrateMagicContextConfigLocations,
|
|
48
47
|
getProtectedTokensTierOverrides,
|
|
48
|
+
LkgRecoveryFenceError,
|
|
49
|
+
clearLkgFenceProcessState,
|
|
50
|
+
lkgFenceRequiresRebuild,
|
|
51
|
+
lkgRecoveryFenceUnclean,
|
|
52
|
+
ownsLkgDirtyFence,
|
|
53
|
+
invalidateCleanLkgRecoveryFence,
|
|
54
|
+
markLkgRecoveryDirty,
|
|
49
55
|
rememberUnpublishedAutoSearchNoHint,
|
|
50
56
|
getUnpublishedAutoSearchNoHint,
|
|
51
57
|
forgetUnpublishedAutoSearchNoHint,
|
|
52
58
|
registerAutoSearchWork,
|
|
53
59
|
cancelAutoSearchWork,
|
|
60
|
+
readSessionActivity,
|
|
61
|
+
observeSessionActivity,
|
|
62
|
+
backfillSessionActivity,
|
|
54
63
|
readSessionMeta,
|
|
55
64
|
getOrCreateSessionMeta,
|
|
56
65
|
updateSessionMeta,
|
|
@@ -251,7 +260,7 @@ import {
|
|
|
251
260
|
registerTodoStateLifecycle,
|
|
252
261
|
syncCtxMemoryToolEnabled,
|
|
253
262
|
registerMagicContextTools
|
|
254
|
-
} from "./index-
|
|
263
|
+
} from "./index-bkcwcghx.js";
|
|
255
264
|
import"./index-4knyh1kt.js";
|
|
256
265
|
import {
|
|
257
266
|
canonicalModelIdentity,
|
|
@@ -277,6 +286,7 @@ import {
|
|
|
277
286
|
isFailClosedBlockingError,
|
|
278
287
|
shouldBypassFailClosedBlock,
|
|
279
288
|
createFailClosedController,
|
|
289
|
+
piHarnessKindFromExecutable,
|
|
280
290
|
getErrorMessage,
|
|
281
291
|
describeError,
|
|
282
292
|
startBootDeadline,
|
|
@@ -292,8 +302,9 @@ import {
|
|
|
292
302
|
openCurrentDatabase,
|
|
293
303
|
openDatabaseAsync,
|
|
294
304
|
closeDatabase
|
|
295
|
-
} from "./index-
|
|
305
|
+
} from "./index-5d506f7y.js";
|
|
296
306
|
import {
|
|
307
|
+
sameProjectDirectory,
|
|
297
308
|
pruneMissingProjectIdentities,
|
|
298
309
|
setHomeProjectPermission,
|
|
299
310
|
ProjectIdentityError,
|
|
@@ -304,7 +315,7 @@ import {
|
|
|
304
315
|
resolveProjectIdentityForSession,
|
|
305
316
|
beginBootQuietPeriod,
|
|
306
317
|
scheduleAfterBootQuiet
|
|
307
|
-
} from "./index-
|
|
318
|
+
} from "./index-48twbev2.js";
|
|
308
319
|
import {
|
|
309
320
|
detectThinkingBindingMismatch,
|
|
310
321
|
detectLatestTurnThinkingMismatch,
|
|
@@ -462,11 +473,12 @@ import {
|
|
|
462
473
|
getCachedAbsoluteMessageCount2,
|
|
463
474
|
primeInMemoryTailRawMessageCache2,
|
|
464
475
|
readRawSessionMessageIdOrdinalsForRange2,
|
|
476
|
+
compareRawSessionMessageOrder2,
|
|
465
477
|
getRawSessionMessageCount2,
|
|
466
478
|
getRawSessionTagKeysThrough2,
|
|
467
479
|
getLegacyProtectedTailStartOrdinal2,
|
|
468
480
|
readSessionChunk2
|
|
469
|
-
} from "./index-
|
|
481
|
+
} from "./index-kagezf2h.js";
|
|
470
482
|
import {
|
|
471
483
|
UNKNOWN_FIT_RATIO,
|
|
472
484
|
hasMeasuredDecisionCalibration,
|
|
@@ -553,7 +565,7 @@ import {
|
|
|
553
565
|
getToolTagNumberByOwner2,
|
|
554
566
|
getNullOwnerToolTag2,
|
|
555
567
|
adoptNullOwnerToolTag2
|
|
556
|
-
} from "./index-
|
|
568
|
+
} from "./index-0x1c054v.js";
|
|
557
569
|
import {
|
|
558
570
|
textMentionsRecentCommit,
|
|
559
571
|
hasMeaningfulUserText2,
|
|
@@ -587,36 +599,7 @@ import {
|
|
|
587
599
|
observeTemporalDecisions,
|
|
588
600
|
freezeTemporalDecisions,
|
|
589
601
|
tagIdentityRevisionKey
|
|
590
|
-
} from "./index-
|
|
591
|
-
import {
|
|
592
|
-
piHarnessKindFromExecutable
|
|
593
|
-
} from "./index-n4wyxcgr.js";
|
|
594
|
-
import {
|
|
595
|
-
LkgRecoveryFenceError,
|
|
596
|
-
clearLkgFenceProcessState,
|
|
597
|
-
takeLkgRecoveryLockSweepPage,
|
|
598
|
-
lkgFenceRequiresRebuild,
|
|
599
|
-
lkgRecoveryFenceUnclean,
|
|
600
|
-
ownsLkgDirtyFence,
|
|
601
|
-
invalidateCleanLkgRecoveryFence,
|
|
602
|
-
markLkgRecoveryDirty,
|
|
603
|
-
gaDatabasePath,
|
|
604
|
-
readSessionActivity,
|
|
605
|
-
observeSessionActivity,
|
|
606
|
-
backfillSessionActivity,
|
|
607
|
-
clearCompressionDepth,
|
|
608
|
-
clearCompressionDepthRange,
|
|
609
|
-
cleanSearchText,
|
|
610
|
-
matchedSearchSnippet,
|
|
611
|
-
getMessageIndexSourceIdentity2,
|
|
612
|
-
isMessageIndexSourceCurrent2,
|
|
613
|
-
getLastIndexedOrdinal2,
|
|
614
|
-
getMessageIndexReconciliationStartOrdinal2,
|
|
615
|
-
isMessageIndexReconciledThrough2,
|
|
616
|
-
indexSingleMessage2,
|
|
617
|
-
indexMessagesAfterOrdinal2,
|
|
618
|
-
sweepOrphanedOpenCodeMessageIndexesCooperatively2
|
|
619
|
-
} from "./index-87xm7z44.js";
|
|
602
|
+
} from "./index-g026ztby.js";
|
|
620
603
|
import {
|
|
621
604
|
BoundedSessionMap,
|
|
622
605
|
resolveOpenCodeDbPath,
|
|
@@ -633,11 +616,11 @@ import {
|
|
|
633
616
|
import {
|
|
634
617
|
runSessionWarmupWorker,
|
|
635
618
|
RAW_SUMMARY_TEXT_MAX_CHARS2
|
|
636
|
-
} from "./index-
|
|
619
|
+
} from "./index-6981g1xv.js";
|
|
637
620
|
import {
|
|
638
621
|
formatSynapseLaneDescriptor
|
|
639
622
|
} from "./index-gwxaz0z5.js";
|
|
640
|
-
import"./index-
|
|
623
|
+
import"./index-bvpar0bg.js";
|
|
641
624
|
import {
|
|
642
625
|
buildCanonicalChunkTextFromFts2,
|
|
643
626
|
buildCompartmentSummaryFallbackText2,
|
|
@@ -647,7 +630,7 @@ import {
|
|
|
647
630
|
replaceCompartmentChunkEmbeddings2,
|
|
648
631
|
deleteChunkEmbedBackoffForSession2,
|
|
649
632
|
chunkWindowSourceKey2
|
|
650
|
-
} from "./index-
|
|
633
|
+
} from "./index-kmk3xpf9.js";
|
|
651
634
|
import {
|
|
652
635
|
recordSessionProjectIdentity,
|
|
653
636
|
GIT_SWEEP_LEASE_RENEWAL_MS,
|
|
@@ -656,7 +639,7 @@ import {
|
|
|
656
639
|
markGitSweepSuccessAndRelease,
|
|
657
640
|
parkGitSweepNonIndexable,
|
|
658
641
|
releaseGitSweepLease
|
|
659
|
-
} from "./index-
|
|
642
|
+
} from "./index-4zemngt7.js";
|
|
660
643
|
import {
|
|
661
644
|
embedPauseBySession,
|
|
662
645
|
embedRunStateBySession,
|
|
@@ -682,7 +665,20 @@ import {
|
|
|
682
665
|
embedSessionCompartmentChunks2,
|
|
683
666
|
getEmbeddingCoverageStatus2,
|
|
684
667
|
getAutoEmbeddingSessionCoverage2
|
|
685
|
-
} from "./index-
|
|
668
|
+
} from "./index-xa90f88m.js";
|
|
669
|
+
import {
|
|
670
|
+
clearCompressionDepth,
|
|
671
|
+
clearCompressionDepthRange,
|
|
672
|
+
cleanSearchText,
|
|
673
|
+
matchedSearchSnippet,
|
|
674
|
+
getMessageIndexSourceIdentity,
|
|
675
|
+
isMessageIndexSourceCurrent,
|
|
676
|
+
getLastIndexedOrdinal,
|
|
677
|
+
getMessageIndexReconciliationStartOrdinal,
|
|
678
|
+
isMessageIndexReconciledThrough,
|
|
679
|
+
indexSingleMessage,
|
|
680
|
+
indexMessagesAfterOrdinal
|
|
681
|
+
} from "./index-v0ht940m.js";
|
|
686
682
|
import {
|
|
687
683
|
rememberV1HiddenRun
|
|
688
684
|
} from "./index-6x556c2q.js";
|
|
@@ -697,7 +693,7 @@ import {
|
|
|
697
693
|
expandWorkspaceIdentitySetWithAliases,
|
|
698
694
|
sourceNameForMemory,
|
|
699
695
|
computeWorkspaceEpochFingerprint
|
|
700
|
-
} from "./index-
|
|
696
|
+
} from "./index-0s14xaca.js";
|
|
701
697
|
import {
|
|
702
698
|
configureContextDatabasePragmas2
|
|
703
699
|
} from "./index-fapenpch.js";
|
|
@@ -747,7 +743,7 @@ import {
|
|
|
747
743
|
normalizeVerificationFiles,
|
|
748
744
|
indexCommitsForProject,
|
|
749
745
|
embedUnembeddedCommits
|
|
750
|
-
} from "./index-
|
|
746
|
+
} from "./index-sdsnb5b6.js";
|
|
751
747
|
import {
|
|
752
748
|
setEmbeddingSessionBusy2,
|
|
753
749
|
isEmbeddingHostBusy2
|
|
@@ -783,7 +779,7 @@ import {
|
|
|
783
779
|
} from "./index-wqpjhx1p.js";
|
|
784
780
|
import {
|
|
785
781
|
cosineSimilarity
|
|
786
|
-
} from "./index-
|
|
782
|
+
} from "./index-wjbqw6r1.js";
|
|
787
783
|
import"./index-6wdwv3a6.js";
|
|
788
784
|
import {
|
|
789
785
|
DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS,
|
|
@@ -811,10 +807,10 @@ import {
|
|
|
811
807
|
drainPiTagSnapshotSession,
|
|
812
808
|
assertPiTagSnapshotReady,
|
|
813
809
|
ensurePiTagSnapshotReady
|
|
814
|
-
} from "./index-
|
|
810
|
+
} from "./index-xw070axm.js";
|
|
815
811
|
import"./index-jn44h81p.js";
|
|
816
812
|
import"./index-1cvyaw9a.js";
|
|
817
|
-
import"./index-
|
|
813
|
+
import"./index-vea2d9ka.js";
|
|
818
814
|
import {
|
|
819
815
|
__toESM
|
|
820
816
|
} from "./index-22jkk6wg.js";
|
|
@@ -824,9 +820,6 @@ import {
|
|
|
824
820
|
import {
|
|
825
821
|
normalizeProtectedToolName
|
|
826
822
|
} from "./index-674f6qs2.js";
|
|
827
|
-
import {
|
|
828
|
-
sameProjectDirectory
|
|
829
|
-
} from "./index-wrr9rp9a.js";
|
|
830
823
|
import {
|
|
831
824
|
logSlowWriteTransaction,
|
|
832
825
|
WriteTransactionSteps
|
|
@@ -3556,7 +3549,7 @@ function startHostStallProfilerSwitch() {
|
|
|
3556
3549
|
// package.json
|
|
3557
3550
|
var package_default = {
|
|
3558
3551
|
name: "@cortexkit/pi-magic-context",
|
|
3559
|
-
version: "0.49.
|
|
3552
|
+
version: "0.49.28",
|
|
3560
3553
|
type: "module",
|
|
3561
3554
|
description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
|
|
3562
3555
|
main: "dist/index.js",
|
|
@@ -14934,8 +14927,8 @@ async function mapMemories(args) {
|
|
|
14934
14927
|
result.failureStage = outcome.failure.stage;
|
|
14935
14928
|
}
|
|
14936
14929
|
const committed = outcome.mapped + outcome.independent;
|
|
14930
|
+
const committedIds = new Set(outcome.committedIds);
|
|
14937
14931
|
runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
|
|
14938
|
-
const committedIds = new Set(outcome.committedIds);
|
|
14939
14932
|
for (const memory of batch.inputs) {
|
|
14940
14933
|
if (committedIds.has(memory.id)) {
|
|
14941
14934
|
delete retries[memory.id];
|
|
@@ -14970,7 +14963,22 @@ async function mapMemories(args) {
|
|
|
14970
14963
|
log2(`[dreamer] map-memories: targeted retry still omitted ${outcome.requeue.length} id(s); leaving them unmapped for the next run`);
|
|
14971
14964
|
}
|
|
14972
14965
|
}
|
|
14973
|
-
if (outcome.failure?.class === "timeout" &&
|
|
14966
|
+
if (outcome.failure?.class === "timeout" && batch.inputs.length > 1) {
|
|
14967
|
+
const unmapped = batch.inputs.filter((memory) => !committedIds.has(memory.id));
|
|
14968
|
+
const splitSize = Math.floor(batch.inputs.length / 2);
|
|
14969
|
+
const splits = [];
|
|
14970
|
+
for (let offset = 0;offset < unmapped.length; offset += splitSize) {
|
|
14971
|
+
splits.push({
|
|
14972
|
+
inputs: unmapped.slice(offset, offset + splitSize),
|
|
14973
|
+
isOmissionRetry: batch.isOmissionRetry
|
|
14974
|
+
});
|
|
14975
|
+
}
|
|
14976
|
+
if (splits.length > 0) {
|
|
14977
|
+
batches.splice(i + 1, 0, ...splits);
|
|
14978
|
+
log2(`[dreamer] map-memories: splitting batch [${batch.inputs.map((memory) => memory.id).join(",")}] into ${splits.map((split) => split.inputs.length).join("+")} after timeout; retrying ${unmapped.length} uncommitted mapping(s)`);
|
|
14979
|
+
}
|
|
14980
|
+
}
|
|
14981
|
+
if (outcome.failure?.class === "timeout" && batch.inputs.length === 1 && committed === 0) {
|
|
14974
14982
|
consecutiveTimeouts += 1;
|
|
14975
14983
|
timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
|
|
14976
14984
|
if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT2) {
|
|
@@ -14978,7 +14986,7 @@ async function mapMemories(args) {
|
|
|
14978
14986
|
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`);
|
|
14979
14987
|
break;
|
|
14980
14988
|
}
|
|
14981
|
-
} else {
|
|
14989
|
+
} else if (committed > 0 || outcome.failure?.class !== "timeout") {
|
|
14982
14990
|
consecutiveTimeouts = 0;
|
|
14983
14991
|
timeoutStreakElapsedMs = [];
|
|
14984
14992
|
}
|
|
@@ -16930,6 +16938,21 @@ function verifyAssistantText(messages) {
|
|
|
16930
16938
|
const start = text.lastIndexOf("<verify>");
|
|
16931
16939
|
return start >= 0 ? text.slice(start) : text;
|
|
16932
16940
|
}
|
|
16941
|
+
function validateVerifyCompletion(messages, text, expectedIds, responseText = text) {
|
|
16942
|
+
let parsed;
|
|
16943
|
+
try {
|
|
16944
|
+
parsed = validateVerifyManifest(text, expectedIds);
|
|
16945
|
+
} catch (error) {
|
|
16946
|
+
throw providerOutputFailureFromInvalidManifest(messages, responseText) ?? error;
|
|
16947
|
+
}
|
|
16948
|
+
const ids = [...parsed.verified, ...parsed.updated, ...parsed.archived, ...parsed.skipped].map((entry) => entry.id);
|
|
16949
|
+
if (ids.length !== expectedIds.size || ids.some((id) => !expectedIds.has(id))) {
|
|
16950
|
+
const providerFailure = providerOutputFailureFromInvalidManifest(messages, responseText);
|
|
16951
|
+
if (providerFailure)
|
|
16952
|
+
throw providerFailure;
|
|
16953
|
+
}
|
|
16954
|
+
return parsed;
|
|
16955
|
+
}
|
|
16933
16956
|
var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
|
|
16934
16957
|
var VERIFY_BATCH_FLOOR_MS = 30000;
|
|
16935
16958
|
function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
|
|
@@ -17088,6 +17111,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
17088
17111
|
const timer = setTimeout(() => batchController.abort(new Error(`verify slice timed out after ${sliceMs}ms`)), sliceMs);
|
|
17089
17112
|
const batchSignal = batchController.signal;
|
|
17090
17113
|
const tokenBudget = verifyBatchTokenBudget(batch.length, args.tokenBudget);
|
|
17114
|
+
const expectedIds = new Set(batch.map((memory) => memory.id));
|
|
17091
17115
|
let agentSessionId = null;
|
|
17092
17116
|
let hiddenSessionId = null;
|
|
17093
17117
|
let promptSettled = false;
|
|
@@ -17140,13 +17164,10 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
17140
17164
|
onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId });
|
|
17141
17165
|
},
|
|
17142
17166
|
parse: (text, completion) => {
|
|
17143
|
-
const providerFailure = providerOutputFailureFromInvalidManifest(completion.messages ?? [], text);
|
|
17144
|
-
if (providerFailure)
|
|
17145
|
-
throw providerFailure;
|
|
17146
17167
|
const manifest = verifyAssistantText(completion.messages ?? []) ?? (text.trim() ? text : null);
|
|
17147
17168
|
if (!manifest)
|
|
17148
17169
|
throw new Error("verify returned no output");
|
|
17149
|
-
return
|
|
17170
|
+
return validateVerifyCompletion(completion.messages ?? [], manifest, expectedIds, text);
|
|
17150
17171
|
}
|
|
17151
17172
|
});
|
|
17152
17173
|
recordInvocation4(args, startedAt, {
|
|
@@ -17208,10 +17229,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
17208
17229
|
const text = verifyAssistantText(messages);
|
|
17209
17230
|
if (!text)
|
|
17210
17231
|
throw new Error("verify returned no output");
|
|
17211
|
-
|
|
17212
|
-
if (providerFailure)
|
|
17213
|
-
throw providerFailure;
|
|
17214
|
-
return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
|
|
17232
|
+
return validateVerifyCompletion(messages, text, expectedIds);
|
|
17215
17233
|
}
|
|
17216
17234
|
});
|
|
17217
17235
|
promptSettled = true;
|
|
@@ -19481,390 +19499,70 @@ function clearDreamerTickFailure(db) {
|
|
|
19481
19499
|
db.prepare("DELETE FROM schema_migrations_meta WHERE key = ?").run(DREAMER_TICK_FAILURE_KEY);
|
|
19482
19500
|
}
|
|
19483
19501
|
|
|
19484
|
-
// ../plugin/src/
|
|
19485
|
-
var
|
|
19486
|
-
var
|
|
19487
|
-
var
|
|
19488
|
-
|
|
19489
|
-
|
|
19502
|
+
// ../plugin/src/plugin/dream-timer.ts
|
|
19503
|
+
var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
|
|
19504
|
+
var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
|
|
19505
|
+
var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
|
|
19506
|
+
var activeTimer = null;
|
|
19507
|
+
var tickInFlight = false;
|
|
19508
|
+
var startupTickTimer = null;
|
|
19509
|
+
var startupTimers = new Map;
|
|
19510
|
+
var startupJitters = new Map;
|
|
19511
|
+
var nextStartupJitterSlot = 0;
|
|
19512
|
+
function directoryStillExists(directory) {
|
|
19513
|
+
try {
|
|
19514
|
+
return statSync3(directory).isDirectory();
|
|
19515
|
+
} catch {
|
|
19490
19516
|
return false;
|
|
19491
|
-
const e = error;
|
|
19492
|
-
if (typeof e.code === "string") {
|
|
19493
|
-
if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
|
|
19494
|
-
return true;
|
|
19495
|
-
}
|
|
19496
|
-
if (typeof e.message === "string") {
|
|
19497
|
-
if (/database is locked/i.test(e.message))
|
|
19498
|
-
return true;
|
|
19499
|
-
if (/sqlite_(busy|locked)/i.test(e.message))
|
|
19500
|
-
return true;
|
|
19501
19517
|
}
|
|
19502
|
-
return false;
|
|
19503
|
-
}
|
|
19504
|
-
var INCREMENTAL_DEBOUNCE_MS = 100;
|
|
19505
|
-
var RECONCILIATION_BATCH_SIZE = 100;
|
|
19506
|
-
|
|
19507
|
-
class MagicContextMessageIndexHeapHolder {
|
|
19508
|
-
reconciledSessions = new Set;
|
|
19509
|
-
reconciledSnapshots = new Map;
|
|
19510
|
-
stalledSessions = new Set;
|
|
19511
|
-
reconciliationScheduledSessions = new Set;
|
|
19512
|
-
clearAndReindexScheduledSessions = new Map;
|
|
19513
|
-
sessionLocks = new Map;
|
|
19514
|
-
incrementalTimers = new Map;
|
|
19515
|
-
pendingIncrementalKeys = new Set;
|
|
19516
|
-
completedIncrementalKeys = new Set;
|
|
19517
|
-
activeReconcilerBuffers = new Map;
|
|
19518
|
-
}
|
|
19519
|
-
var heapHolder = new MagicContextMessageIndexHeapHolder;
|
|
19520
|
-
var PREPARE_RETRY_MS = 60000;
|
|
19521
|
-
async function sourceReady(source, sessionId) {
|
|
19522
|
-
const prepare = source?.prepare;
|
|
19523
|
-
return typeof prepare === "function" ? prepare(sessionId) : true;
|
|
19524
19518
|
}
|
|
19525
|
-
function
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
|
|
19529
|
-
|
|
19519
|
+
function openTimerDatabaseOrNull(context) {
|
|
19520
|
+
let db;
|
|
19521
|
+
try {
|
|
19522
|
+
db = openCurrentDatabase();
|
|
19523
|
+
} catch (error) {
|
|
19524
|
+
log2(`[dreamer] storage fatal; skipping ${context}: ${getErrorMessage(error)}`);
|
|
19525
|
+
return null;
|
|
19530
19526
|
}
|
|
19531
|
-
|
|
19532
|
-
}
|
|
19533
|
-
|
|
19534
|
-
|
|
19527
|
+
if (!db) {
|
|
19528
|
+
log2(`[dreamer] storage unavailable; skipping ${context} (the cache schema is newer than this binary supports — restart/upgrade OpenCode/Pi/Magic Context to recover)`);
|
|
19529
|
+
return null;
|
|
19530
|
+
}
|
|
19531
|
+
return db;
|
|
19535
19532
|
}
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
|
|
19539
|
-
return;
|
|
19540
|
-
}).then(async () => {
|
|
19541
|
-
await operation();
|
|
19542
|
-
});
|
|
19543
|
-
heapHolder.sessionLocks.set(sessionId, run);
|
|
19544
|
-
run.finally(() => {
|
|
19545
|
-
if (heapHolder.sessionLocks.get(sessionId) === run) {
|
|
19546
|
-
heapHolder.sessionLocks.delete(sessionId);
|
|
19547
|
-
}
|
|
19548
|
-
}).catch(() => {
|
|
19533
|
+
var refusedEmptyIdentityDirectories = new Set;
|
|
19534
|
+
function logEmptyIdentityRefusalOnce(directory) {
|
|
19535
|
+
if (refusedEmptyIdentityDirectories.has(directory))
|
|
19549
19536
|
return;
|
|
19550
|
-
|
|
19551
|
-
|
|
19537
|
+
refusedEmptyIdentityDirectories.add(directory);
|
|
19538
|
+
log2(`[dreamer] not registering ${directory}: it has no project identity, so no project-scoped work runs for it`);
|
|
19552
19539
|
}
|
|
19553
|
-
|
|
19554
|
-
|
|
19555
|
-
|
|
19540
|
+
var registeredProjects = new Map;
|
|
19541
|
+
function stopDreamScheduleTimerIfIdle() {
|
|
19542
|
+
if (registeredProjects.size !== 0)
|
|
19556
19543
|
return;
|
|
19544
|
+
const stopped = activeTimer !== null || startupTickTimer !== null;
|
|
19545
|
+
if (activeTimer) {
|
|
19546
|
+
clearInterval(activeTimer);
|
|
19547
|
+
activeTimer = null;
|
|
19557
19548
|
}
|
|
19558
|
-
|
|
19559
|
-
|
|
19560
|
-
|
|
19561
|
-
function logReconciliationStall(sessionId, reason) {
|
|
19562
|
-
if (heapHolder.stalledSessions.has(sessionId))
|
|
19563
|
-
return;
|
|
19564
|
-
heapHolder.stalledSessions.add(sessionId);
|
|
19565
|
-
sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
|
|
19566
|
-
}
|
|
19567
|
-
async function reconcileSessionIndex(db, sessionId, readMessages) {
|
|
19568
|
-
if (!await sourceReady(readMessages, sessionId)) {
|
|
19569
|
-
logReconciliationStall(sessionId, "raw message reader is not ready");
|
|
19570
|
-
return false;
|
|
19549
|
+
if (startupTickTimer) {
|
|
19550
|
+
clearTimeout(startupTickTimer);
|
|
19551
|
+
startupTickTimer = null;
|
|
19571
19552
|
}
|
|
19572
|
-
|
|
19573
|
-
|
|
19574
|
-
|
|
19575
|
-
|
|
19576
|
-
try {
|
|
19577
|
-
const fullReader = typeof readMessages === "function" ? readMessages : null;
|
|
19578
|
-
const revision = readMessages.getRevision?.(sessionId);
|
|
19579
|
-
const previous = heapHolder.reconciledSnapshots.get(sessionId);
|
|
19580
|
-
const finalWatermark = previous && revision === previous.revision ? previous.count : revision !== undefined && readMessages.getCountAfterRevision ? previous && revision > previous.revision ? previous.count + readMessages.getCountAfterRevision(sessionId, previous.revision, revision) : readMessages.getCountAfterRevision(sessionId, -1, revision) : readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
|
|
19581
|
-
let cursor = getMessageIndexReconciliationStartOrdinal2(db, sessionId);
|
|
19582
|
-
let after = cursor === previous?.count ? previous.after : undefined;
|
|
19583
|
-
while (cursor < finalWatermark) {
|
|
19584
|
-
const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
|
|
19585
|
-
const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
|
|
19586
|
-
const retainedMessages = fallbackSnapshot ?? messages;
|
|
19587
|
-
heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
|
|
19588
|
-
withSqliteBackgroundWriter2(() => indexMessagesAfterOrdinal2(db, sessionId, messages, cursor, pageEnd));
|
|
19589
|
-
const nextCursor = getMessageIndexReconciliationStartOrdinal2(db, sessionId);
|
|
19590
|
-
if (nextCursor <= cursor)
|
|
19591
|
-
break;
|
|
19592
|
-
cursor = nextCursor;
|
|
19593
|
-
const last = messages.at(-1);
|
|
19594
|
-
after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
|
|
19595
|
-
if (cursor < finalWatermark) {
|
|
19596
|
-
await yieldToEventLoop();
|
|
19597
|
-
}
|
|
19598
|
-
}
|
|
19599
|
-
if (isMessageIndexReconciledThrough2(db, sessionId, finalWatermark)) {
|
|
19600
|
-
heapHolder.reconciledSessions.add(sessionId);
|
|
19601
|
-
if (revision !== undefined) {
|
|
19602
|
-
if (!after && finalWatermark > 0 && readMessages.readPage) {
|
|
19603
|
-
const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
|
|
19604
|
-
if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
|
|
19605
|
-
after = { timeCreated: last.createdAt, id: last.id };
|
|
19606
|
-
}
|
|
19607
|
-
heapHolder.reconciledSnapshots.set(sessionId, {
|
|
19608
|
-
revision,
|
|
19609
|
-
count: finalWatermark,
|
|
19610
|
-
after
|
|
19611
|
-
});
|
|
19612
|
-
}
|
|
19613
|
-
} else {
|
|
19614
|
-
logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
|
|
19615
|
-
}
|
|
19616
|
-
} finally {
|
|
19617
|
-
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
19618
|
-
}
|
|
19619
|
-
});
|
|
19620
|
-
return true;
|
|
19553
|
+
startupJitters.clear();
|
|
19554
|
+
nextStartupJitterSlot = 0;
|
|
19555
|
+
if (stopped)
|
|
19556
|
+
log2("[dreamer] stopped dream schedule timer (no projects left)");
|
|
19621
19557
|
}
|
|
19622
|
-
function
|
|
19623
|
-
if (!
|
|
19558
|
+
async function startDreamScheduleTimer(args) {
|
|
19559
|
+
if (!isUsableProjectIdentity(args.projectIdentity)) {
|
|
19560
|
+
logEmptyIdentityRefusalOnce(args.directory);
|
|
19624
19561
|
return;
|
|
19625
19562
|
}
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
let appendedDuringReconciliation = false;
|
|
19630
|
-
const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
|
|
19631
|
-
reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
|
|
19632
|
-
if (ran) {
|
|
19633
|
-
const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
|
|
19634
|
-
appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
|
|
19635
|
-
return;
|
|
19636
|
-
}
|
|
19637
|
-
inRootAsyncContext2(() => setTimeout(() => {
|
|
19638
|
-
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
19639
|
-
scheduleReconciliation(db, sessionId, readMessages);
|
|
19640
|
-
}, PREPARE_RETRY_MS)).unref?.();
|
|
19641
|
-
}).catch((error) => {
|
|
19642
|
-
logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
|
|
19643
|
-
if (isDatabaseLockedError(error))
|
|
19644
|
-
inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
|
|
19645
|
-
}).finally(() => {
|
|
19646
|
-
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
19647
|
-
if (appendedDuringReconciliation)
|
|
19648
|
-
scheduleReconciliation(db, sessionId, readMessages);
|
|
19649
|
-
});
|
|
19650
|
-
});
|
|
19651
|
-
});
|
|
19652
|
-
}
|
|
19653
|
-
function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
19654
|
-
const schedulingKey = `${sessionId}\x00${messageId}`;
|
|
19655
|
-
const epoch = sessionEpochs.get(sessionId) ?? 0;
|
|
19656
|
-
if (heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
19657
|
-
return;
|
|
19658
|
-
const activeTimer = heapHolder.incrementalTimers.get(schedulingKey);
|
|
19659
|
-
if (activeTimer)
|
|
19660
|
-
clearTimeout(activeTimer);
|
|
19661
|
-
const timer = inRootAsyncContext2(() => setTimeout(() => {
|
|
19662
|
-
heapHolder.incrementalTimers.delete(schedulingKey);
|
|
19663
|
-
heapHolder.pendingIncrementalKeys.add(schedulingKey);
|
|
19664
|
-
const indexMessage = async () => {
|
|
19665
|
-
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
19666
|
-
return;
|
|
19667
|
-
const message = typeof messageSource === "function" ? messageSource(sessionId, messageId) : messageSource;
|
|
19668
|
-
if (!message)
|
|
19669
|
-
return;
|
|
19670
|
-
const revisionKey = `${schedulingKey}\x00${getMessageIndexSourceIdentity2(message)}`;
|
|
19671
|
-
if (heapHolder.completedIncrementalKeys.has(revisionKey))
|
|
19672
|
-
return;
|
|
19673
|
-
const currentWatermark = getLastIndexedOrdinal2(db, sessionId);
|
|
19674
|
-
if (message.ordinal <= currentWatermark && isMessageIndexSourceCurrent2(db, sessionId, message)) {
|
|
19675
|
-
heapHolder.completedIncrementalKeys.add(revisionKey);
|
|
19676
|
-
return;
|
|
19677
|
-
}
|
|
19678
|
-
const wasReconciled = heapHolder.reconciledSessions.delete(sessionId);
|
|
19679
|
-
await indexSingleMessageOffThread(db, sessionId, message);
|
|
19680
|
-
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
19681
|
-
return;
|
|
19682
|
-
const finalWatermark = getLastIndexedOrdinal2(db, sessionId);
|
|
19683
|
-
if (wasReconciled && isMessageIndexReconciledThrough2(db, sessionId, finalWatermark)) {
|
|
19684
|
-
heapHolder.reconciledSessions.add(sessionId);
|
|
19685
|
-
}
|
|
19686
|
-
heapHolder.completedIncrementalKeys.add(revisionKey);
|
|
19687
|
-
};
|
|
19688
|
-
sourceReady(messageSource, sessionId).then((ready) => {
|
|
19689
|
-
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
|
|
19690
|
-
return;
|
|
19691
|
-
if (ready)
|
|
19692
|
-
return runWithSessionLock(sessionId, indexMessage);
|
|
19693
|
-
setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), PREPARE_RETRY_MS).unref?.();
|
|
19694
|
-
}).catch((error) => {
|
|
19695
|
-
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
|
|
19696
|
-
return;
|
|
19697
|
-
heapHolder.reconciledSessions.delete(sessionId);
|
|
19698
|
-
logIndexingError(sessionId, `incremental index for ${messageId}`, error);
|
|
19699
|
-
if (isDatabaseLockedError(error))
|
|
19700
|
-
setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), 1000).unref();
|
|
19701
|
-
}).finally(() => {
|
|
19702
|
-
if ((sessionEpochs.get(sessionId) ?? 0) === epoch)
|
|
19703
|
-
heapHolder.pendingIncrementalKeys.delete(schedulingKey);
|
|
19704
|
-
});
|
|
19705
|
-
}, INCREMENTAL_DEBOUNCE_MS));
|
|
19706
|
-
heapHolder.incrementalTimers.set(schedulingKey, timer);
|
|
19707
|
-
}
|
|
19708
|
-
async function indexSingleMessageOffThread(db, sessionId, message) {
|
|
19709
|
-
const path = getSqliteDatabasePath2(db);
|
|
19710
|
-
if (!path)
|
|
19711
|
-
return withSqliteBackgroundWriter2(() => indexSingleMessage2(db, sessionId, message));
|
|
19712
|
-
const cancellation = new Int32Array(new SharedArrayBuffer(4));
|
|
19713
|
-
const active = indexCancellations.get(sessionId) ?? new Set;
|
|
19714
|
-
active.add(cancellation);
|
|
19715
|
-
indexCancellations.set(sessionId, active);
|
|
19716
|
-
const result = await runSessionWarmupWorker({
|
|
19717
|
-
path,
|
|
19718
|
-
sessionId,
|
|
19719
|
-
indexMessage: message,
|
|
19720
|
-
harness: getHarness2(),
|
|
19721
|
-
indexCancellation: cancellation.buffer,
|
|
19722
|
-
...indexCoordinationInput2()
|
|
19723
|
-
}, {}).finally(() => {
|
|
19724
|
-
active.delete(cancellation);
|
|
19725
|
-
if (active.size === 0)
|
|
19726
|
-
indexCancellations.delete(sessionId);
|
|
19727
|
-
});
|
|
19728
|
-
if (!("inserted" in result))
|
|
19729
|
-
throw new Error("failure" in result ? result.detail : "unexpected indexing worker reply");
|
|
19730
|
-
if (result.measurements) {
|
|
19731
|
-
const sessions = workerMeasurements.get(db) ?? new Map;
|
|
19732
|
-
sessions.set(sessionId, result.measurements);
|
|
19733
|
-
workerMeasurements.set(db, sessions);
|
|
19734
|
-
if (result.measurements.skipped)
|
|
19735
|
-
log2(`[magic-context] incremental FTS skipped oversized source ${message.id} (${result.measurements.sourceBytes} bytes); identity and progress persisted`);
|
|
19736
|
-
}
|
|
19737
|
-
return result.inserted;
|
|
19738
|
-
}
|
|
19739
|
-
async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, options = {}) {
|
|
19740
|
-
if (getHarness2() === "opencode" || getHarness2() === "opencode2")
|
|
19741
|
-
options = {
|
|
19742
|
-
...options,
|
|
19743
|
-
fenceLockNames: options.fenceLockNames ?? takeLkgRecoveryLockSweepPage()
|
|
19744
|
-
};
|
|
19745
|
-
if (getHarness2() === "opencode2")
|
|
19746
|
-
openSource = () => new Database2(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"), {
|
|
19747
|
-
readonly: true,
|
|
19748
|
-
fileMustExist: true
|
|
19749
|
-
});
|
|
19750
|
-
const path = getSqliteDatabasePath2(db);
|
|
19751
|
-
if (!path || getHarness2() !== "opencode" && getHarness2() !== "opencode2")
|
|
19752
|
-
return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, openSource, options);
|
|
19753
|
-
let source = null;
|
|
19754
|
-
let sourcePath = null;
|
|
19755
|
-
try {
|
|
19756
|
-
source = openSource();
|
|
19757
|
-
if (source)
|
|
19758
|
-
sourcePath = getSqliteDatabasePath2(source);
|
|
19759
|
-
} catch {} finally {
|
|
19760
|
-
if (sourcePath)
|
|
19761
|
-
source?.close();
|
|
19762
|
-
}
|
|
19763
|
-
if (!sourcePath)
|
|
19764
|
-
return sweepOrphanedOpenCodeMessageIndexesCooperatively2(db, () => source, options);
|
|
19765
|
-
const reply = await runSessionWarmupWorker({
|
|
19766
|
-
path,
|
|
19767
|
-
sessionId: "",
|
|
19768
|
-
harness: getHarness2(),
|
|
19769
|
-
orphanSweep: { sourcePath, options }
|
|
19770
|
-
}, {});
|
|
19771
|
-
if (!("orphanSweep" in reply))
|
|
19772
|
-
throw new Error("message history orphan sweep worker failed");
|
|
19773
|
-
return reply.orphanSweep;
|
|
19774
|
-
}
|
|
19775
|
-
function clearSessionTracking(sessionId) {
|
|
19776
|
-
sessionEpochs.set(sessionId, (sessionEpochs.get(sessionId) ?? 0) + 1);
|
|
19777
|
-
for (const cancellation of indexCancellations.get(sessionId) ?? [])
|
|
19778
|
-
Atomics.store(cancellation, 0, 1);
|
|
19779
|
-
heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
|
|
19780
|
-
heapHolder.reconciledSessions.delete(sessionId);
|
|
19781
|
-
heapHolder.reconciledSnapshots.delete(sessionId);
|
|
19782
|
-
heapHolder.stalledSessions.delete(sessionId);
|
|
19783
|
-
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
19784
|
-
heapHolder.sessionLocks.delete(sessionId);
|
|
19785
|
-
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
19786
|
-
const prefix = `${sessionId}\x00`;
|
|
19787
|
-
for (const [key, timer] of heapHolder.incrementalTimers) {
|
|
19788
|
-
if (key.startsWith(prefix)) {
|
|
19789
|
-
clearTimeout(timer);
|
|
19790
|
-
heapHolder.incrementalTimers.delete(key);
|
|
19791
|
-
}
|
|
19792
|
-
}
|
|
19793
|
-
for (const key of heapHolder.pendingIncrementalKeys) {
|
|
19794
|
-
if (key.startsWith(prefix)) {
|
|
19795
|
-
heapHolder.pendingIncrementalKeys.delete(key);
|
|
19796
|
-
}
|
|
19797
|
-
}
|
|
19798
|
-
for (const key of heapHolder.completedIncrementalKeys) {
|
|
19799
|
-
if (key.startsWith(prefix))
|
|
19800
|
-
heapHolder.completedIncrementalKeys.delete(key);
|
|
19801
|
-
}
|
|
19802
|
-
}
|
|
19803
|
-
|
|
19804
|
-
// ../plugin/src/plugin/dream-timer.ts
|
|
19805
|
-
var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
|
|
19806
|
-
var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
|
|
19807
|
-
var BOOT_PROJECT_JITTER_SLOT_MS = 1000;
|
|
19808
|
-
var activeTimer = null;
|
|
19809
|
-
var tickInFlight = false;
|
|
19810
|
-
var startupTickTimer = null;
|
|
19811
|
-
var startupTimers = new Map;
|
|
19812
|
-
var startupJitters = new Map;
|
|
19813
|
-
var nextStartupJitterSlot = 0;
|
|
19814
|
-
function directoryStillExists(directory) {
|
|
19815
|
-
try {
|
|
19816
|
-
return statSync3(directory).isDirectory();
|
|
19817
|
-
} catch {
|
|
19818
|
-
return false;
|
|
19819
|
-
}
|
|
19820
|
-
}
|
|
19821
|
-
function openTimerDatabaseOrNull(context) {
|
|
19822
|
-
let db;
|
|
19823
|
-
try {
|
|
19824
|
-
db = openCurrentDatabase();
|
|
19825
|
-
} catch (error) {
|
|
19826
|
-
log2(`[dreamer] storage fatal; skipping ${context}: ${getErrorMessage(error)}`);
|
|
19827
|
-
return null;
|
|
19828
|
-
}
|
|
19829
|
-
if (!db) {
|
|
19830
|
-
log2(`[dreamer] storage unavailable; skipping ${context} (the cache schema is newer than this binary supports — restart/upgrade OpenCode/Pi/Magic Context to recover)`);
|
|
19831
|
-
return null;
|
|
19832
|
-
}
|
|
19833
|
-
return db;
|
|
19834
|
-
}
|
|
19835
|
-
var refusedEmptyIdentityDirectories = new Set;
|
|
19836
|
-
function logEmptyIdentityRefusalOnce(directory) {
|
|
19837
|
-
if (refusedEmptyIdentityDirectories.has(directory))
|
|
19838
|
-
return;
|
|
19839
|
-
refusedEmptyIdentityDirectories.add(directory);
|
|
19840
|
-
log2(`[dreamer] not registering ${directory}: it has no project identity, so no project-scoped work runs for it`);
|
|
19841
|
-
}
|
|
19842
|
-
var registeredProjects = new Map;
|
|
19843
|
-
function stopDreamScheduleTimerIfIdle() {
|
|
19844
|
-
if (registeredProjects.size !== 0)
|
|
19845
|
-
return;
|
|
19846
|
-
const stopped = activeTimer !== null || startupTickTimer !== null;
|
|
19847
|
-
if (activeTimer) {
|
|
19848
|
-
clearInterval(activeTimer);
|
|
19849
|
-
activeTimer = null;
|
|
19850
|
-
}
|
|
19851
|
-
if (startupTickTimer) {
|
|
19852
|
-
clearTimeout(startupTickTimer);
|
|
19853
|
-
startupTickTimer = null;
|
|
19854
|
-
}
|
|
19855
|
-
startupJitters.clear();
|
|
19856
|
-
nextStartupJitterSlot = 0;
|
|
19857
|
-
if (stopped)
|
|
19858
|
-
log2("[dreamer] stopped dream schedule timer (no projects left)");
|
|
19859
|
-
}
|
|
19860
|
-
async function startDreamScheduleTimer(args) {
|
|
19861
|
-
if (!isUsableProjectIdentity(args.projectIdentity)) {
|
|
19862
|
-
logEmptyIdentityRefusalOnce(args.directory);
|
|
19863
|
-
return;
|
|
19864
|
-
}
|
|
19865
|
-
beginBootQuietPeriod();
|
|
19866
|
-
const db = openTimerDatabaseOrNull("schedule timer registration");
|
|
19867
|
-
if (!db)
|
|
19563
|
+
beginBootQuietPeriod();
|
|
19564
|
+
const db = openTimerDatabaseOrNull("schedule timer registration");
|
|
19565
|
+
if (!db)
|
|
19868
19566
|
return;
|
|
19869
19567
|
const dreamingEnabled = Boolean(args.dreamerConfig && args.dreamerConfig.disable !== true);
|
|
19870
19568
|
const embeddingSweepEnabled = args.memoryEnabled === true;
|
|
@@ -19996,12 +19694,6 @@ async function runMessageHistoryMaintenance(db) {
|
|
|
19996
19694
|
log2(`[message-index] pending Rust session cleanup: cleared=${rustCleanup.cleared} failed=${rustCleanup.failedSessionIds.length}`);
|
|
19997
19695
|
}
|
|
19998
19696
|
}
|
|
19999
|
-
const sweep = await sweepOrphanedOpenCodeMessageIndexesOffThread(db, openOpenCodeDb);
|
|
20000
|
-
if (sweep.reason)
|
|
20001
|
-
log2(`[message-index] orphan sweep parked: ${sweep.reason}`);
|
|
20002
|
-
if (sweep.deleted > 0) {
|
|
20003
|
-
log2(`[message-index] orphan sweep: scanned=${sweep.scanned} deleted=${sweep.deleted} cursor=${sweep.cursor || "<complete>"}`);
|
|
20004
|
-
}
|
|
20005
19697
|
}
|
|
20006
19698
|
function startupJitterMs(directory) {
|
|
20007
19699
|
const existing = startupJitters.get(directory);
|
|
@@ -22953,6 +22645,8 @@ async function awaitInFlightDreamers(registrationOwner) {
|
|
|
22953
22645
|
return;
|
|
22954
22646
|
await Promise.allSettled(runs);
|
|
22955
22647
|
}
|
|
22648
|
+
var RUNNER_TIMEOUT_HEADROOM_MINUTES = 5;
|
|
22649
|
+
var UNKNOWN_TASK_TIMEOUT_MINUTES = 30;
|
|
22956
22650
|
function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRefreshNeeded, isRegistrationOwnerActive = () => true, getMaxOutputTokens = () => opts.config.maxTokens, getDreamerConfig = () => opts.config) {
|
|
22957
22651
|
const runner = piSubagentRunnerFactory();
|
|
22958
22652
|
const budgetStates = new Map;
|
|
@@ -23006,7 +22700,7 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
|
|
|
23006
22700
|
userMessage,
|
|
23007
22701
|
model: perTaskModel,
|
|
23008
22702
|
fallbackModels: undefined,
|
|
23009
|
-
timeoutMs:
|
|
22703
|
+
timeoutMs: ((taskConfig?.timeoutMinutes ?? UNKNOWN_TASK_TIMEOUT_MINUTES) + RUNNER_TIMEOUT_HEADROOM_MINUTES) * 60 * 1000,
|
|
23010
22704
|
cwd: dreamSession.directory,
|
|
23011
22705
|
signal: args.signal ? AbortSignal.any([args.signal, controller.signal]) : controller.signal,
|
|
23012
22706
|
thinkingLevel: extractBodyVariant(args),
|
|
@@ -23115,7 +22809,11 @@ function accountingTaskFromTitle(title) {
|
|
|
23115
22809
|
const task = title.slice("magic-context-dream-".length);
|
|
23116
22810
|
if (!title.startsWith("magic-context-dream-") || task.length === 0)
|
|
23117
22811
|
return null;
|
|
23118
|
-
|
|
22812
|
+
if (task === "classify")
|
|
22813
|
+
return "classify-memories";
|
|
22814
|
+
if (task === "user-memories")
|
|
22815
|
+
return "review-user-memories";
|
|
22816
|
+
return task;
|
|
23119
22817
|
}
|
|
23120
22818
|
function readSessionTitle(args) {
|
|
23121
22819
|
const body = args.body;
|
|
@@ -23934,6 +23632,290 @@ function commitPiCompactionModeRecord(db, sessionId, record) {
|
|
|
23934
23632
|
// src/context-handler.ts
|
|
23935
23633
|
import * as crypto3 from "node:crypto";
|
|
23936
23634
|
|
|
23635
|
+
// ../plugin/src/features/magic-context/message-index-async.ts
|
|
23636
|
+
var indexCancellations = new Map;
|
|
23637
|
+
var sessionEpochs = new Map;
|
|
23638
|
+
var workerMeasurements = new WeakMap;
|
|
23639
|
+
function isDatabaseLockedError(error) {
|
|
23640
|
+
if (!error || typeof error !== "object")
|
|
23641
|
+
return false;
|
|
23642
|
+
const e = error;
|
|
23643
|
+
if (typeof e.code === "string") {
|
|
23644
|
+
if (e.code === "SQLITE_BUSY" || e.code === "SQLITE_LOCKED")
|
|
23645
|
+
return true;
|
|
23646
|
+
}
|
|
23647
|
+
if (typeof e.message === "string") {
|
|
23648
|
+
if (/database is locked/i.test(e.message))
|
|
23649
|
+
return true;
|
|
23650
|
+
if (/sqlite_(busy|locked)/i.test(e.message))
|
|
23651
|
+
return true;
|
|
23652
|
+
}
|
|
23653
|
+
return false;
|
|
23654
|
+
}
|
|
23655
|
+
var INCREMENTAL_DEBOUNCE_MS = 100;
|
|
23656
|
+
var RECONCILIATION_BATCH_SIZE = 100;
|
|
23657
|
+
|
|
23658
|
+
class MagicContextMessageIndexHeapHolder {
|
|
23659
|
+
reconciledSessions = new Set;
|
|
23660
|
+
reconciledSnapshots = new Map;
|
|
23661
|
+
stalledSessions = new Set;
|
|
23662
|
+
reconciliationScheduledSessions = new Set;
|
|
23663
|
+
clearAndReindexScheduledSessions = new Map;
|
|
23664
|
+
sessionLocks = new Map;
|
|
23665
|
+
incrementalTimers = new Map;
|
|
23666
|
+
pendingIncrementalKeys = new Set;
|
|
23667
|
+
completedIncrementalKeys = new Set;
|
|
23668
|
+
activeReconcilerBuffers = new Map;
|
|
23669
|
+
}
|
|
23670
|
+
var heapHolder = new MagicContextMessageIndexHeapHolder;
|
|
23671
|
+
var PREPARE_RETRY_MS = 60000;
|
|
23672
|
+
async function sourceReady(source, sessionId) {
|
|
23673
|
+
const prepare = source?.prepare;
|
|
23674
|
+
return typeof prepare === "function" ? prepare(sessionId) : true;
|
|
23675
|
+
}
|
|
23676
|
+
function defer(fn) {
|
|
23677
|
+
const immediate = globalThis.setImmediate;
|
|
23678
|
+
if (typeof immediate === "function") {
|
|
23679
|
+
inRootAsyncContext2(() => immediate(fn));
|
|
23680
|
+
return;
|
|
23681
|
+
}
|
|
23682
|
+
inRootAsyncContext2(() => setTimeout(fn, 0));
|
|
23683
|
+
}
|
|
23684
|
+
function yieldToEventLoop() {
|
|
23685
|
+
return new Promise((resolve) => defer(resolve));
|
|
23686
|
+
}
|
|
23687
|
+
function runWithSessionLock(sessionId, operation) {
|
|
23688
|
+
const previous = heapHolder.sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
23689
|
+
const run = previous.catch(() => {
|
|
23690
|
+
return;
|
|
23691
|
+
}).then(async () => {
|
|
23692
|
+
await operation();
|
|
23693
|
+
});
|
|
23694
|
+
heapHolder.sessionLocks.set(sessionId, run);
|
|
23695
|
+
run.finally(() => {
|
|
23696
|
+
if (heapHolder.sessionLocks.get(sessionId) === run) {
|
|
23697
|
+
heapHolder.sessionLocks.delete(sessionId);
|
|
23698
|
+
}
|
|
23699
|
+
}).catch(() => {
|
|
23700
|
+
return;
|
|
23701
|
+
});
|
|
23702
|
+
return run;
|
|
23703
|
+
}
|
|
23704
|
+
function logIndexingError(sessionId, action, error) {
|
|
23705
|
+
if (isDatabaseLockedError(error)) {
|
|
23706
|
+
sessionLog2(sessionId, `message FTS async ${action} skipped (database busy; will retry on next reconciliation)`);
|
|
23707
|
+
return;
|
|
23708
|
+
}
|
|
23709
|
+
sessionLog2(sessionId, `message FTS async ${action} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
23710
|
+
log2(`[message-index-async] ${action} failed for ${sessionId}:`, error);
|
|
23711
|
+
}
|
|
23712
|
+
function logReconciliationStall(sessionId, reason) {
|
|
23713
|
+
if (heapHolder.stalledSessions.has(sessionId))
|
|
23714
|
+
return;
|
|
23715
|
+
heapHolder.stalledSessions.add(sessionId);
|
|
23716
|
+
sessionLog2(sessionId, `message FTS reconciliation stalled: ${reason}; will retry`);
|
|
23717
|
+
}
|
|
23718
|
+
async function reconcileSessionIndex(db, sessionId, readMessages) {
|
|
23719
|
+
if (!await sourceReady(readMessages, sessionId)) {
|
|
23720
|
+
logReconciliationStall(sessionId, "raw message reader is not ready");
|
|
23721
|
+
return false;
|
|
23722
|
+
}
|
|
23723
|
+
await runWithSessionLock(sessionId, async () => {
|
|
23724
|
+
if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId))
|
|
23725
|
+
return;
|
|
23726
|
+
let fallbackSnapshot = null;
|
|
23727
|
+
try {
|
|
23728
|
+
const fullReader = typeof readMessages === "function" ? readMessages : null;
|
|
23729
|
+
const revision = readMessages.getRevision?.(sessionId);
|
|
23730
|
+
const previous = heapHolder.reconciledSnapshots.get(sessionId);
|
|
23731
|
+
const finalWatermark = previous && revision === previous.revision ? previous.count : revision !== undefined && readMessages.getCountAfterRevision ? previous && revision > previous.revision ? previous.count + readMessages.getCountAfterRevision(sessionId, previous.revision, revision) : readMessages.getCountAfterRevision(sessionId, -1, revision) : readMessages.getCount ? readMessages.getCount(sessionId) : (fallbackSnapshot = fullReader?.(sessionId) ?? []).length;
|
|
23732
|
+
let cursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
23733
|
+
let after = cursor === previous?.count ? previous.after : undefined;
|
|
23734
|
+
while (cursor < finalWatermark) {
|
|
23735
|
+
const pageEnd = Math.min(finalWatermark, cursor + RECONCILIATION_BATCH_SIZE);
|
|
23736
|
+
const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark, after) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
|
|
23737
|
+
const retainedMessages = fallbackSnapshot ?? messages;
|
|
23738
|
+
heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
|
|
23739
|
+
withSqliteBackgroundWriter2(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd));
|
|
23740
|
+
const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
|
|
23741
|
+
if (nextCursor <= cursor)
|
|
23742
|
+
break;
|
|
23743
|
+
cursor = nextCursor;
|
|
23744
|
+
const last = messages.at(-1);
|
|
23745
|
+
after = last?.ordinal === cursor && typeof last.createdAt === "number" ? { timeCreated: last.createdAt, id: last.id } : undefined;
|
|
23746
|
+
if (cursor < finalWatermark) {
|
|
23747
|
+
await yieldToEventLoop();
|
|
23748
|
+
}
|
|
23749
|
+
}
|
|
23750
|
+
if (isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
|
|
23751
|
+
heapHolder.reconciledSessions.add(sessionId);
|
|
23752
|
+
if (revision !== undefined) {
|
|
23753
|
+
if (!after && finalWatermark > 0 && readMessages.readPage) {
|
|
23754
|
+
const last = readMessages.readPage(sessionId, finalWatermark - 1, 1, finalWatermark).at(-1);
|
|
23755
|
+
if (last?.ordinal === finalWatermark && typeof last.createdAt === "number")
|
|
23756
|
+
after = { timeCreated: last.createdAt, id: last.id };
|
|
23757
|
+
}
|
|
23758
|
+
heapHolder.reconciledSnapshots.set(sessionId, {
|
|
23759
|
+
revision,
|
|
23760
|
+
count: finalWatermark,
|
|
23761
|
+
after
|
|
23762
|
+
});
|
|
23763
|
+
}
|
|
23764
|
+
} else {
|
|
23765
|
+
logReconciliationStall(sessionId, `gap after ordinal ${cursor} (store count ${finalWatermark})`);
|
|
23766
|
+
}
|
|
23767
|
+
} finally {
|
|
23768
|
+
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
23769
|
+
}
|
|
23770
|
+
});
|
|
23771
|
+
return true;
|
|
23772
|
+
}
|
|
23773
|
+
function scheduleReconciliation(db, sessionId, readMessages) {
|
|
23774
|
+
if (!readMessages.getRevision && heapHolder.reconciledSessions.has(sessionId) || heapHolder.reconciliationScheduledSessions.has(sessionId)) {
|
|
23775
|
+
return;
|
|
23776
|
+
}
|
|
23777
|
+
heapHolder.reconciliationScheduledSessions.add(sessionId);
|
|
23778
|
+
scheduleAfterBootQuiet(() => {
|
|
23779
|
+
defer(() => {
|
|
23780
|
+
let appendedDuringReconciliation = false;
|
|
23781
|
+
const previousSnapshot = heapHolder.reconciledSnapshots.get(sessionId);
|
|
23782
|
+
reconcileSessionIndex(db, sessionId, readMessages).then((ran) => {
|
|
23783
|
+
if (ran) {
|
|
23784
|
+
const snapshot = heapHolder.reconciledSnapshots.get(sessionId);
|
|
23785
|
+
appendedDuringReconciliation = snapshot !== undefined && snapshot !== previousSnapshot && readMessages.getRevision !== undefined && readMessages.getRevision(sessionId) !== snapshot.revision;
|
|
23786
|
+
return;
|
|
23787
|
+
}
|
|
23788
|
+
inRootAsyncContext2(() => setTimeout(() => {
|
|
23789
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
23790
|
+
scheduleReconciliation(db, sessionId, readMessages);
|
|
23791
|
+
}, PREPARE_RETRY_MS)).unref?.();
|
|
23792
|
+
}).catch((error) => {
|
|
23793
|
+
logReconciliationStall(sessionId, error instanceof Error ? error.message : String(error));
|
|
23794
|
+
if (isDatabaseLockedError(error))
|
|
23795
|
+
inRootAsyncContext2(() => setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000)).unref();
|
|
23796
|
+
}).finally(() => {
|
|
23797
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
23798
|
+
if (appendedDuringReconciliation)
|
|
23799
|
+
scheduleReconciliation(db, sessionId, readMessages);
|
|
23800
|
+
});
|
|
23801
|
+
});
|
|
23802
|
+
});
|
|
23803
|
+
}
|
|
23804
|
+
function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
23805
|
+
const schedulingKey = `${sessionId}\x00${messageId}`;
|
|
23806
|
+
const epoch = sessionEpochs.get(sessionId) ?? 0;
|
|
23807
|
+
if (heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
23808
|
+
return;
|
|
23809
|
+
const activeTimer = heapHolder.incrementalTimers.get(schedulingKey);
|
|
23810
|
+
if (activeTimer)
|
|
23811
|
+
clearTimeout(activeTimer);
|
|
23812
|
+
const timer = inRootAsyncContext2(() => setTimeout(() => {
|
|
23813
|
+
heapHolder.incrementalTimers.delete(schedulingKey);
|
|
23814
|
+
heapHolder.pendingIncrementalKeys.add(schedulingKey);
|
|
23815
|
+
const indexMessage = async () => {
|
|
23816
|
+
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
23817
|
+
return;
|
|
23818
|
+
const message = typeof messageSource === "function" ? messageSource(sessionId, messageId) : messageSource;
|
|
23819
|
+
if (!message)
|
|
23820
|
+
return;
|
|
23821
|
+
const revisionKey = `${schedulingKey}\x00${getMessageIndexSourceIdentity(message)}`;
|
|
23822
|
+
if (heapHolder.completedIncrementalKeys.has(revisionKey))
|
|
23823
|
+
return;
|
|
23824
|
+
const currentWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
23825
|
+
if (message.ordinal <= currentWatermark && isMessageIndexSourceCurrent(db, sessionId, message)) {
|
|
23826
|
+
heapHolder.completedIncrementalKeys.add(revisionKey);
|
|
23827
|
+
return;
|
|
23828
|
+
}
|
|
23829
|
+
const wasReconciled = heapHolder.reconciledSessions.delete(sessionId);
|
|
23830
|
+
await indexSingleMessageOffThread(db, sessionId, message);
|
|
23831
|
+
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch || !heapHolder.pendingIncrementalKeys.has(schedulingKey))
|
|
23832
|
+
return;
|
|
23833
|
+
const finalWatermark = getLastIndexedOrdinal(db, sessionId);
|
|
23834
|
+
if (wasReconciled && isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
|
|
23835
|
+
heapHolder.reconciledSessions.add(sessionId);
|
|
23836
|
+
}
|
|
23837
|
+
heapHolder.completedIncrementalKeys.add(revisionKey);
|
|
23838
|
+
};
|
|
23839
|
+
sourceReady(messageSource, sessionId).then((ready) => {
|
|
23840
|
+
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
|
|
23841
|
+
return;
|
|
23842
|
+
if (ready)
|
|
23843
|
+
return runWithSessionLock(sessionId, indexMessage);
|
|
23844
|
+
setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), PREPARE_RETRY_MS).unref?.();
|
|
23845
|
+
}).catch((error) => {
|
|
23846
|
+
if ((sessionEpochs.get(sessionId) ?? 0) !== epoch)
|
|
23847
|
+
return;
|
|
23848
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
23849
|
+
logIndexingError(sessionId, `incremental index for ${messageId}`, error);
|
|
23850
|
+
if (isDatabaseLockedError(error))
|
|
23851
|
+
setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), 1000).unref();
|
|
23852
|
+
}).finally(() => {
|
|
23853
|
+
if ((sessionEpochs.get(sessionId) ?? 0) === epoch)
|
|
23854
|
+
heapHolder.pendingIncrementalKeys.delete(schedulingKey);
|
|
23855
|
+
});
|
|
23856
|
+
}, INCREMENTAL_DEBOUNCE_MS));
|
|
23857
|
+
heapHolder.incrementalTimers.set(schedulingKey, timer);
|
|
23858
|
+
}
|
|
23859
|
+
async function indexSingleMessageOffThread(db, sessionId, message) {
|
|
23860
|
+
const path = getSqliteDatabasePath2(db);
|
|
23861
|
+
if (!path)
|
|
23862
|
+
return withSqliteBackgroundWriter2(() => indexSingleMessage(db, sessionId, message));
|
|
23863
|
+
const cancellation = new Int32Array(new SharedArrayBuffer(4));
|
|
23864
|
+
const active = indexCancellations.get(sessionId) ?? new Set;
|
|
23865
|
+
active.add(cancellation);
|
|
23866
|
+
indexCancellations.set(sessionId, active);
|
|
23867
|
+
const result = await runSessionWarmupWorker({
|
|
23868
|
+
path,
|
|
23869
|
+
sessionId,
|
|
23870
|
+
indexMessage: message,
|
|
23871
|
+
harness: getHarness2(),
|
|
23872
|
+
indexCancellation: cancellation.buffer,
|
|
23873
|
+
...indexCoordinationInput2()
|
|
23874
|
+
}, {}).finally(() => {
|
|
23875
|
+
active.delete(cancellation);
|
|
23876
|
+
if (active.size === 0)
|
|
23877
|
+
indexCancellations.delete(sessionId);
|
|
23878
|
+
});
|
|
23879
|
+
if (!("inserted" in result))
|
|
23880
|
+
throw new Error("failure" in result ? result.detail : "unexpected indexing worker reply");
|
|
23881
|
+
if (result.measurements) {
|
|
23882
|
+
const sessions = workerMeasurements.get(db) ?? new Map;
|
|
23883
|
+
sessions.set(sessionId, result.measurements);
|
|
23884
|
+
workerMeasurements.set(db, sessions);
|
|
23885
|
+
if (result.measurements.skipped)
|
|
23886
|
+
log2(`[magic-context] incremental FTS skipped oversized source ${message.id} (${result.measurements.sourceBytes} bytes); identity and progress persisted`);
|
|
23887
|
+
}
|
|
23888
|
+
return result.inserted;
|
|
23889
|
+
}
|
|
23890
|
+
function clearSessionTracking(sessionId) {
|
|
23891
|
+
sessionEpochs.set(sessionId, (sessionEpochs.get(sessionId) ?? 0) + 1);
|
|
23892
|
+
for (const cancellation of indexCancellations.get(sessionId) ?? [])
|
|
23893
|
+
Atomics.store(cancellation, 0, 1);
|
|
23894
|
+
heapHolder.clearAndReindexScheduledSessions.delete(sessionId);
|
|
23895
|
+
heapHolder.reconciledSessions.delete(sessionId);
|
|
23896
|
+
heapHolder.reconciledSnapshots.delete(sessionId);
|
|
23897
|
+
heapHolder.stalledSessions.delete(sessionId);
|
|
23898
|
+
heapHolder.reconciliationScheduledSessions.delete(sessionId);
|
|
23899
|
+
heapHolder.sessionLocks.delete(sessionId);
|
|
23900
|
+
heapHolder.activeReconcilerBuffers.delete(sessionId);
|
|
23901
|
+
const prefix = `${sessionId}\x00`;
|
|
23902
|
+
for (const [key, timer] of heapHolder.incrementalTimers) {
|
|
23903
|
+
if (key.startsWith(prefix)) {
|
|
23904
|
+
clearTimeout(timer);
|
|
23905
|
+
heapHolder.incrementalTimers.delete(key);
|
|
23906
|
+
}
|
|
23907
|
+
}
|
|
23908
|
+
for (const key of heapHolder.pendingIncrementalKeys) {
|
|
23909
|
+
if (key.startsWith(prefix)) {
|
|
23910
|
+
heapHolder.pendingIncrementalKeys.delete(key);
|
|
23911
|
+
}
|
|
23912
|
+
}
|
|
23913
|
+
for (const key of heapHolder.completedIncrementalKeys) {
|
|
23914
|
+
if (key.startsWith(prefix))
|
|
23915
|
+
heapHolder.completedIncrementalKeys.delete(key);
|
|
23916
|
+
}
|
|
23917
|
+
}
|
|
23918
|
+
|
|
23937
23919
|
// ../plugin/src/hooks/magic-context/event-resolvers.ts
|
|
23938
23920
|
var DEFAULT_CONTEXT_LIMIT = 200000;
|
|
23939
23921
|
var clampWarnSeen = new Set;
|
|
@@ -26380,6 +26362,60 @@ function isHistorianDrainBudgetSpent(args) {
|
|
|
26380
26362
|
return true;
|
|
26381
26363
|
}
|
|
26382
26364
|
|
|
26365
|
+
// ../plugin/src/hooks/magic-context/historian-history-wait.ts
|
|
26366
|
+
var historyWaits = new Map;
|
|
26367
|
+
function newestMessageId(snapshot) {
|
|
26368
|
+
try {
|
|
26369
|
+
const count = getRawSessionMessageOrdinalCount2(snapshot.sessionId);
|
|
26370
|
+
const ids = readRawSessionMessageIdOrdinalsForRange2(snapshot.sessionId, count, count);
|
|
26371
|
+
const newest = ids.keys().next().value;
|
|
26372
|
+
if (newest)
|
|
26373
|
+
return newest;
|
|
26374
|
+
} catch {}
|
|
26375
|
+
return snapshot.rawLastMessageIdAtTrigger;
|
|
26376
|
+
}
|
|
26377
|
+
function recoveryWindow(snapshot, percentage) {
|
|
26378
|
+
return percentage >= escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage || snapshot.emergencyTailScale !== undefined;
|
|
26379
|
+
}
|
|
26380
|
+
function clearHistorianHistoryWait(sessionId) {
|
|
26381
|
+
historyWaits.delete(sessionId);
|
|
26382
|
+
}
|
|
26383
|
+
function recordHistorianNoProgress(snapshot, emergency = false) {
|
|
26384
|
+
const newest = newestMessageId(snapshot);
|
|
26385
|
+
if (!newest)
|
|
26386
|
+
return;
|
|
26387
|
+
const previous = historyWaits.get(snapshot.sessionId);
|
|
26388
|
+
const sameHistory = previous?.newestMessageId === newest;
|
|
26389
|
+
historyWaits.set(snapshot.sessionId, {
|
|
26390
|
+
newestMessageId: newest,
|
|
26391
|
+
recoveryAttempted: sameHistory && previous.recoveryAttempted || emergency || recoveryWindow(snapshot, snapshot.usagePercentage),
|
|
26392
|
+
floorLiftAttempted: sameHistory && previous.floorLiftAttempted || snapshot.liftLivePromptFloor === true
|
|
26393
|
+
});
|
|
26394
|
+
}
|
|
26395
|
+
function shouldWaitForNewHistorianHistory(snapshot, options = {}) {
|
|
26396
|
+
const wait = historyWaits.get(snapshot.sessionId);
|
|
26397
|
+
if (!wait)
|
|
26398
|
+
return false;
|
|
26399
|
+
const newest = newestMessageId(snapshot);
|
|
26400
|
+
if (newest && newest !== wait.newestMessageId) {
|
|
26401
|
+
try {
|
|
26402
|
+
const order = compareRawSessionMessageOrder2(snapshot.sessionId, newest, wait.newestMessageId);
|
|
26403
|
+
if (order === null || order > 0)
|
|
26404
|
+
return false;
|
|
26405
|
+
} catch {}
|
|
26406
|
+
}
|
|
26407
|
+
const recovery = options.emergency || recoveryWindow(snapshot, options.usagePercentage ?? snapshot.usagePercentage);
|
|
26408
|
+
const floorLift = snapshot.liftLivePromptFloor === true;
|
|
26409
|
+
if (recovery && !wait.recoveryAttempted || floorLift && !wait.floorLiftAttempted) {
|
|
26410
|
+
if (options.claim) {
|
|
26411
|
+
wait.recoveryAttempted ||= recovery;
|
|
26412
|
+
wait.floorLiftAttempted ||= floorLift;
|
|
26413
|
+
}
|
|
26414
|
+
return false;
|
|
26415
|
+
}
|
|
26416
|
+
return true;
|
|
26417
|
+
}
|
|
26418
|
+
|
|
26383
26419
|
// ../plugin/src/hooks/magic-context/compartment-trigger.ts
|
|
26384
26420
|
var PROACTIVE_TRIGGER_OFFSET_PERCENTAGE = 2;
|
|
26385
26421
|
var POST_DROP_TARGET_RATIO = 0.75;
|
|
@@ -26638,6 +26674,13 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
26638
26674
|
}
|
|
26639
26675
|
return { shouldFire: false };
|
|
26640
26676
|
}
|
|
26677
|
+
if (tailInfo.boundarySnapshot && shouldWaitForNewHistorianHistory(tailInfo.boundarySnapshot, {
|
|
26678
|
+
usagePercentage: usage.percentage,
|
|
26679
|
+
emergency: getOverflowState(db, sessionId).needsEmergencyRecovery
|
|
26680
|
+
})) {
|
|
26681
|
+
sessionLog2(sessionId, "compartment trigger: waiting for new history after no forward progress");
|
|
26682
|
+
return { shouldFire: false };
|
|
26683
|
+
}
|
|
26641
26684
|
const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
|
|
26642
26685
|
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession2(db, sessionId), keepReasoningTokens, sessionMeta.clearedReasoningThroughTag, canClearReasoning, reasoningProjection?.budgetCutoff, eligiblePendingDropTagIds);
|
|
26643
26686
|
const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
|
|
@@ -30030,6 +30073,14 @@ async function runPiHistorian(deps) {
|
|
|
30030
30073
|
return;
|
|
30031
30074
|
}
|
|
30032
30075
|
const protectedTailStart = boundarySnapshot.protectedTailStart;
|
|
30076
|
+
if (!forceDrainQuota && shouldWaitForNewHistorianHistory(boundarySnapshot, {
|
|
30077
|
+
emergency: getOverflowState(db, sessionId).needsEmergencyRecovery
|
|
30078
|
+
})) {
|
|
30079
|
+
telemetry.status = "noop";
|
|
30080
|
+
telemetry.failureReason = "waiting for new history after no forward progress";
|
|
30081
|
+
sessionLog2(sessionId, "historian no-op: waiting for new history after no forward progress");
|
|
30082
|
+
return;
|
|
30083
|
+
}
|
|
30033
30084
|
const eligibleEndOrdinal = Math.min(boundarySnapshot.eligibleEndOrdinal, protectedTailStart);
|
|
30034
30085
|
if (protectedTailStart <= offset || eligibleEndOrdinal <= offset) {
|
|
30035
30086
|
telemetry.status = "noop";
|
|
@@ -30230,6 +30281,12 @@ ${chunkText}`,
|
|
|
30230
30281
|
};
|
|
30231
30282
|
retainDrainReservationForRetryThrottle = true;
|
|
30232
30283
|
const historianEditorSystemPrompt = withContentLanguageDirective(HISTORIAN_EDITOR_SYSTEM_PROMPT, deps.language, { preserveUserQuotes: true });
|
|
30284
|
+
if (!forceDrainQuota) {
|
|
30285
|
+
shouldWaitForNewHistorianHistory(boundarySnapshot, {
|
|
30286
|
+
emergency: getOverflowState(db, sessionId).needsEmergencyRecovery,
|
|
30287
|
+
claim: true
|
|
30288
|
+
});
|
|
30289
|
+
}
|
|
30233
30290
|
const firstResult = await runHistorianSubagentWithTransientRetries({
|
|
30234
30291
|
runner,
|
|
30235
30292
|
sessionId,
|
|
@@ -30393,6 +30450,7 @@ ${chunkText}`,
|
|
|
30393
30450
|
const failCount = incrementHistorianFailure(db, sessionId, errorMsg);
|
|
30394
30451
|
await notify(buildHistorianFailureNotice(failCount, errorMsg));
|
|
30395
30452
|
}
|
|
30453
|
+
recordHistorianNoProgress(boundarySnapshot, inEmergency);
|
|
30396
30454
|
rollbackDrainReservation();
|
|
30397
30455
|
return;
|
|
30398
30456
|
}
|
|
@@ -30488,6 +30546,7 @@ ${chunkText}`,
|
|
|
30488
30546
|
}
|
|
30489
30547
|
db.exec("COMMIT");
|
|
30490
30548
|
published = true;
|
|
30549
|
+
clearHistorianHistoryWait(sessionId);
|
|
30491
30550
|
logSlowWriteTransaction("pi_historian_publish", transactionStartedAt);
|
|
30492
30551
|
} finally {
|
|
30493
30552
|
if (!published) {
|