@cortexkit/pi-magic-context 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-f3jfb2ed.js → index-0k3j1tc3.js} +1394 -262
- package/dist/{rpc-notifications-td0amw6w.js → index-hw34xmzk.js} +2 -10
- package/dist/index.js +1240 -1091
- package/dist/rpc-notifications-s2rw51c6.js +17 -0
- package/dist/subagent-entry.js +8 -4
- package/package.json +69 -69
- /package/dist/{index-v7fmc1s2.js → index-3pnd4qh9.js} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGE_RECLAIM_MIN_TOKENS,
|
|
3
|
-
|
|
3
|
+
BoundedSessionMap,
|
|
4
|
+
COMPACTION_ENABLED_PATH,
|
|
4
5
|
COMPARTMENT_LEASE_RENEWAL_MS,
|
|
5
6
|
COMPARTMENT_RENDER_EPOCH,
|
|
6
7
|
DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
@@ -11,6 +12,8 @@ import {
|
|
|
11
12
|
Database,
|
|
12
13
|
GIT_SWEEP_LEASE_RENEWAL_MS,
|
|
13
14
|
GLOBAL_USER_PROFILE_PROJECT_PATH,
|
|
15
|
+
LATEST_SUPPORTED_VERSION,
|
|
16
|
+
MAX_EXECUTE_THRESHOLD,
|
|
14
17
|
PRIMER_CANDIDATE_MAX_AGE_MS,
|
|
15
18
|
PRIMER_CANDIDATE_TTL_MS,
|
|
16
19
|
ProjectIdentityError,
|
|
@@ -58,12 +61,12 @@ import {
|
|
|
58
61
|
clearInjectionCache,
|
|
59
62
|
clearMemoryVerifications,
|
|
60
63
|
clearPendingCompactionMarkerStateIf,
|
|
64
|
+
clearPendingOps,
|
|
61
65
|
clearPendingPiCompactionMarkerStateIf,
|
|
62
66
|
clearPersistedReasoningWatermark,
|
|
63
67
|
clearPersistedTodoSyntheticAnchor,
|
|
64
68
|
clearRecompStaging,
|
|
65
69
|
closeQuietly,
|
|
66
|
-
compareTaskOrder,
|
|
67
70
|
computeCueContentHash,
|
|
68
71
|
computeNormalizedHash,
|
|
69
72
|
computeWorkspaceEpochFingerprint,
|
|
@@ -91,6 +94,7 @@ import {
|
|
|
91
94
|
encodeCachedM0UpgradeIdentity,
|
|
92
95
|
enqueueShadowEmbeddingItems,
|
|
93
96
|
ensureProjectRegisteredFromPiDirectory,
|
|
97
|
+
escalationBands,
|
|
94
98
|
escapeXmlAttr,
|
|
95
99
|
escapeXmlContent,
|
|
96
100
|
estimateTokens,
|
|
@@ -111,6 +115,7 @@ import {
|
|
|
111
115
|
getAutoSearchHintDecisions,
|
|
112
116
|
getCachedAbsoluteMessageCount,
|
|
113
117
|
getChannel2NudgeState,
|
|
118
|
+
getCompactionModeRecord,
|
|
114
119
|
getCompartments,
|
|
115
120
|
getCompartmentsByEndMessageId,
|
|
116
121
|
getContextStoreUuid,
|
|
@@ -143,6 +148,7 @@ import {
|
|
|
143
148
|
getMemoryVerifications,
|
|
144
149
|
getMessageIndexReconciliationStartOrdinal,
|
|
145
150
|
getMessageIndexSourceIdentity,
|
|
151
|
+
getMigrationOnOpenRefusal,
|
|
146
152
|
getModuleNoteEvaluationBridge,
|
|
147
153
|
getMuralCueState,
|
|
148
154
|
getNoteLastReadAt,
|
|
@@ -150,14 +156,15 @@ import {
|
|
|
150
156
|
getNotes,
|
|
151
157
|
getNullOwnerToolTag,
|
|
152
158
|
getOldestActiveUnprotectedToolTags,
|
|
159
|
+
getOpenCodeDbPath,
|
|
153
160
|
getOrCreateSessionMeta,
|
|
154
161
|
getOverflowState,
|
|
155
162
|
getPendingCompactionMarkerState,
|
|
156
163
|
getPendingOps,
|
|
157
164
|
getPendingPiCompactionMarkerState,
|
|
158
165
|
getPendingSmartNotes,
|
|
159
|
-
getPersistedCompactionMarkerState,
|
|
160
166
|
getPersistedNoteNudge,
|
|
167
|
+
getPersistedSchemaVersion,
|
|
161
168
|
getPersistedTodoSyntheticAnchor,
|
|
162
169
|
getPersistedToolTagAccounting,
|
|
163
170
|
getPrimerCandidatesByIds,
|
|
@@ -205,18 +212,17 @@ import {
|
|
|
205
212
|
insertUserMemory,
|
|
206
213
|
insertUserMemoryCandidates,
|
|
207
214
|
invalidateMemory,
|
|
208
|
-
|
|
215
|
+
isCompactionEnabled,
|
|
209
216
|
isCompartmentLeaseHeld,
|
|
210
217
|
isDreamerRunnable,
|
|
211
218
|
isEditTool,
|
|
212
219
|
isMessageIndexReconciledThrough,
|
|
213
220
|
isMessageIndexSourceCurrent,
|
|
221
|
+
isMidTurn,
|
|
214
222
|
isMidTurnPi,
|
|
215
223
|
isRecord,
|
|
216
224
|
isSaneLimit,
|
|
217
225
|
isWrapupInProgress,
|
|
218
|
-
leaseKeyFor,
|
|
219
|
-
leaseKindFor,
|
|
220
226
|
loadPiConfig,
|
|
221
227
|
loadProtectedTailMeta,
|
|
222
228
|
markGitSweepSuccessAndRelease,
|
|
@@ -233,6 +239,7 @@ import {
|
|
|
233
239
|
openDatabase,
|
|
234
240
|
openDatabaseAsync,
|
|
235
241
|
parkGitSweepNonIndexable,
|
|
242
|
+
parseCompartmentOutput,
|
|
236
243
|
parseCron,
|
|
237
244
|
parseTodos,
|
|
238
245
|
peekDeferredExecutePending,
|
|
@@ -286,7 +293,9 @@ import {
|
|
|
286
293
|
reserveProtectedTailDrainTokens,
|
|
287
294
|
resetLastNudgeCycle,
|
|
288
295
|
resetLastNudgeCycleIfTailShrank,
|
|
296
|
+
resolveCompactionModeRecord,
|
|
289
297
|
resolveGitTopLevel,
|
|
298
|
+
resolveLimit,
|
|
290
299
|
resolveModelRefForPi,
|
|
291
300
|
resolveMuralWire,
|
|
292
301
|
resolvePiStableId,
|
|
@@ -302,6 +311,7 @@ import {
|
|
|
302
311
|
saveSourceContent,
|
|
303
312
|
scheduleAfterBootQuiet,
|
|
304
313
|
setChannel2NudgeState,
|
|
314
|
+
setCompactionModeRecord,
|
|
305
315
|
setDeferredExecutePendingIfAbsent,
|
|
306
316
|
setEmergencyDropSample,
|
|
307
317
|
setLastNudgeLevel,
|
|
@@ -309,7 +319,6 @@ import {
|
|
|
309
319
|
setMemoryClassification,
|
|
310
320
|
setMuralCue,
|
|
311
321
|
setPendingPiCompactionMarkerState,
|
|
312
|
-
setPersistedCompactionMarkerState,
|
|
313
322
|
setPersistedNoteNudgeTrigger,
|
|
314
323
|
setPersistedNoteNudgeTriggerMessageId,
|
|
315
324
|
setPersistedTodoSyntheticAnchor,
|
|
@@ -317,6 +326,7 @@ import {
|
|
|
317
326
|
setRecompPartialRange,
|
|
318
327
|
setSessionWorkMetrics,
|
|
319
328
|
setSqlitePragmaConfig,
|
|
329
|
+
setStoragePrivatePermissionEnforcement,
|
|
320
330
|
setTodoSnapshot,
|
|
321
331
|
sourceNameForMemory,
|
|
322
332
|
stableStringify,
|
|
@@ -333,6 +343,7 @@ import {
|
|
|
333
343
|
trimWorkspaceMemoriesToBudgetV2,
|
|
334
344
|
unifiedSearch,
|
|
335
345
|
updateCavemanDepth,
|
|
346
|
+
updateCompactionMarkerAfterPublication,
|
|
336
347
|
updatePrimerAnswer,
|
|
337
348
|
updatePrimerCandidateEmbedding,
|
|
338
349
|
updatePrimerSupport,
|
|
@@ -350,10 +361,12 @@ import {
|
|
|
350
361
|
withMigrationLanguageDirective,
|
|
351
362
|
withRawMessageProvider,
|
|
352
363
|
withRawSessionMessageCache
|
|
353
|
-
} from "./index-
|
|
364
|
+
} from "./index-0k3j1tc3.js";
|
|
365
|
+
import {
|
|
366
|
+
pushNotification
|
|
367
|
+
} from "./index-hw34xmzk.js";
|
|
354
368
|
import {
|
|
355
369
|
ensureCortexKitArtifactGitignore,
|
|
356
|
-
getDataDir,
|
|
357
370
|
getHarness,
|
|
358
371
|
getMagicContextStorageDir,
|
|
359
372
|
getProjectMagicContextHistorianDir,
|
|
@@ -368,7 +381,7 @@ import {
|
|
|
368
381
|
|
|
369
382
|
// src/index.ts
|
|
370
383
|
import { createRequire as createRequire3 } from "node:module";
|
|
371
|
-
import { join as
|
|
384
|
+
import { join as join5, resolve as resolve2 } from "node:path";
|
|
372
385
|
|
|
373
386
|
// ../plugin/src/shared/resolve-fallbacks.ts
|
|
374
387
|
function resolveFallbackChain(userFallbacks) {
|
|
@@ -415,6 +428,61 @@ function modelBodyField(spec) {
|
|
|
415
428
|
return parsed ? { model: parsed } : {};
|
|
416
429
|
}
|
|
417
430
|
|
|
431
|
+
// ../plugin/src/features/magic-context/dreamer/task-registry.ts
|
|
432
|
+
var CANONICAL_DREAM_TASKS = [
|
|
433
|
+
"map-memories",
|
|
434
|
+
"verify",
|
|
435
|
+
"verify-broad",
|
|
436
|
+
"curate",
|
|
437
|
+
"compress-cues",
|
|
438
|
+
"classify-memories",
|
|
439
|
+
"retrospective",
|
|
440
|
+
"maintain-docs",
|
|
441
|
+
"evaluate-smart-notes",
|
|
442
|
+
"review-user-memories",
|
|
443
|
+
"promote-primers",
|
|
444
|
+
"refresh-primers"
|
|
445
|
+
];
|
|
446
|
+
var MEMORY_DOMAIN_TASKS = [
|
|
447
|
+
"map-memories",
|
|
448
|
+
"verify",
|
|
449
|
+
"verify-broad",
|
|
450
|
+
"curate",
|
|
451
|
+
"compress-cues",
|
|
452
|
+
"classify-memories",
|
|
453
|
+
"retrospective",
|
|
454
|
+
"promote-primers",
|
|
455
|
+
"refresh-primers"
|
|
456
|
+
];
|
|
457
|
+
var MEMORY_DOMAIN_SET = new Set(MEMORY_DOMAIN_TASKS);
|
|
458
|
+
function leaseKindFor(task) {
|
|
459
|
+
if (MEMORY_DOMAIN_SET.has(task))
|
|
460
|
+
return "memory";
|
|
461
|
+
switch (task) {
|
|
462
|
+
case "review-user-memories":
|
|
463
|
+
return "user-memories";
|
|
464
|
+
case "promote-primers":
|
|
465
|
+
case "refresh-primers":
|
|
466
|
+
return "memory";
|
|
467
|
+
case "maintain-docs":
|
|
468
|
+
return "maintain-docs";
|
|
469
|
+
case "evaluate-smart-notes":
|
|
470
|
+
return "evaluate-smart-notes";
|
|
471
|
+
default:
|
|
472
|
+
return "memory";
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function leaseKeyFor(task, projectIdentity) {
|
|
476
|
+
const kind = leaseKindFor(task);
|
|
477
|
+
return kind === "user-memories" ? "user-memories" : `${kind}:${projectIdentity}`;
|
|
478
|
+
}
|
|
479
|
+
function isCanonicalDreamTask(value) {
|
|
480
|
+
return CANONICAL_DREAM_TASKS.includes(value);
|
|
481
|
+
}
|
|
482
|
+
function compareTaskOrder(a, b) {
|
|
483
|
+
return CANONICAL_DREAM_TASKS.indexOf(a) - CANONICAL_DREAM_TASKS.indexOf(b);
|
|
484
|
+
}
|
|
485
|
+
|
|
418
486
|
// ../plugin/src/features/magic-context/dreamer/task-config.ts
|
|
419
487
|
function buildDreamTaskRuntimeConfigs(dreamer, language) {
|
|
420
488
|
const tasks = dreamer.tasks ?? {};
|
|
@@ -478,14 +546,41 @@ function isMagicContextHiddenAgentName(agent) {
|
|
|
478
546
|
return true;
|
|
479
547
|
return false;
|
|
480
548
|
}
|
|
549
|
+
var MAX_FORMATTED_BLOCKING_PROCESSES = 8;
|
|
550
|
+
function formatFailClosedBlockingProcesses(processes) {
|
|
551
|
+
const uniqueProcesses = new Map;
|
|
552
|
+
for (const process2 of processes) {
|
|
553
|
+
if (!process2.harness.trim() || !Number.isInteger(process2.pid) || process2.pid <= 0)
|
|
554
|
+
continue;
|
|
555
|
+
uniqueProcesses.set(`${process2.harness}\x00${process2.pid}`, {
|
|
556
|
+
harness: process2.harness.trim(),
|
|
557
|
+
pid: process2.pid
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
const entries = [...uniqueProcesses.values()];
|
|
561
|
+
const visible = entries.slice(0, MAX_FORMATTED_BLOCKING_PROCESSES);
|
|
562
|
+
const rendered = visible.map(({ harness, pid }) => `${harness} (PID ${pid})`);
|
|
563
|
+
const omitted = entries.length - visible.length;
|
|
564
|
+
if (omitted > 0)
|
|
565
|
+
rendered.push(`${omitted} more blocking process(es)`);
|
|
566
|
+
if (rendered.length === 0)
|
|
567
|
+
return "a live harness process";
|
|
568
|
+
if (rendered.length === 1)
|
|
569
|
+
return rendered[0];
|
|
570
|
+
const last = rendered.pop();
|
|
571
|
+
return `${rendered.join(", ")}, and ${last}`;
|
|
572
|
+
}
|
|
481
573
|
function formatFailClosedBlockingMessage(reason) {
|
|
574
|
+
if (reason.kind === "migration_guard") {
|
|
575
|
+
return [
|
|
576
|
+
`Magic Context cannot migrate the shared database because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
|
|
577
|
+
"Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
|
|
578
|
+
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
579
|
+
].join(" ");
|
|
580
|
+
}
|
|
482
581
|
if (reason.kind === "schema_fence") {
|
|
483
582
|
return [
|
|
484
|
-
`Magic Context cannot operate:
|
|
485
|
-
`is newer than this build supports (max v${reason.supportedVersion}).`,
|
|
486
|
-
"A newer OpenCode/Pi instance upgraded the database; this build fail-closed",
|
|
487
|
-
"so it cannot corrupt the cache or silently fall back to native compaction.",
|
|
488
|
-
`Update or unpin Magic Context on this harness, then restart.`,
|
|
583
|
+
`Magic Context cannot operate: this Magic Context build is older than the database; upgrade/restart this harness (database schema v${reason.persistedVersion}, build supports through v${reason.supportedVersion}).`,
|
|
489
584
|
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
490
585
|
].join(" ");
|
|
491
586
|
}
|
|
@@ -546,7 +641,7 @@ function createFailClosedController(options) {
|
|
|
546
641
|
const shouldReprobe = typeof input.tryReopen === "function" && (blockedPassCount === 1 || blockedPassCount % reprobeEveryN === 0);
|
|
547
642
|
if (shouldReprobe) {
|
|
548
643
|
try {
|
|
549
|
-
const healed = await input.tryReopen();
|
|
644
|
+
const healed = await input.tryReopen?.();
|
|
550
645
|
if (healed) {
|
|
551
646
|
reason = null;
|
|
552
647
|
blockedPassCount = 0;
|
|
@@ -729,6 +824,7 @@ var OVERFLOW_PATTERNS = [
|
|
|
729
824
|
/maximum prompt length is \d+/i,
|
|
730
825
|
/reduce the length of the messages/i,
|
|
731
826
|
/maximum context length is \d+ tokens/i,
|
|
827
|
+
/maximum model length is \d+/i,
|
|
732
828
|
/exceeds the limit of \d+/i,
|
|
733
829
|
/exceeds the available context size/i,
|
|
734
830
|
/greater than the context length/i,
|
|
@@ -744,15 +840,25 @@ var OVERFLOW_PATTERNS = [
|
|
|
744
840
|
/context size has been exceeded/i
|
|
745
841
|
];
|
|
746
842
|
var LIMIT_EXTRACTION_PATTERNS = [
|
|
747
|
-
/maximum prompt length is (\d+)/i,
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
/
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
843
|
+
{ pattern: /maximum prompt length is (\d+)/i, provenance: "prompt_only" },
|
|
844
|
+
{
|
|
845
|
+
pattern: /maximum context length is (\d+) tokens?/i,
|
|
846
|
+
provenance: "combined"
|
|
847
|
+
},
|
|
848
|
+
{ pattern: /maximum model length is (\d+)/i, provenance: "combined" },
|
|
849
|
+
{ pattern: /context length is only (\d+) tokens?/i, provenance: "combined" },
|
|
850
|
+
{ pattern: /exceeds the limit of (\d+)/i, provenance: "unknown" },
|
|
851
|
+
{
|
|
852
|
+
pattern: /too large for model with (\d+) maximum context length/i,
|
|
853
|
+
provenance: "combined"
|
|
854
|
+
},
|
|
855
|
+
{ pattern: /context size.*(\d+) tokens?/i, provenance: "combined" },
|
|
856
|
+
{ pattern: /exceeds? the context length of (\d+)/i, provenance: "combined" },
|
|
857
|
+
{
|
|
858
|
+
pattern: />\s*(\d+)\s*(?:tokens?\s*)?(?:maximum|max|limit)\b/i,
|
|
859
|
+
provenance: "prompt_only"
|
|
860
|
+
},
|
|
861
|
+
{ pattern: /max(?:imum)?.*context.*?(\d+)/i, provenance: "unknown" }
|
|
756
862
|
];
|
|
757
863
|
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
758
864
|
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
@@ -803,14 +909,15 @@ function detectOverflow(error) {
|
|
|
803
909
|
const reportedLimit = parseReportedLimit(message);
|
|
804
910
|
return {
|
|
805
911
|
isOverflow: true,
|
|
806
|
-
reportedLimit,
|
|
912
|
+
reportedLimit: reportedLimit?.value,
|
|
913
|
+
reportedLimitProvenance: reportedLimit?.provenance,
|
|
807
914
|
matchedPattern: matched?.source
|
|
808
915
|
};
|
|
809
916
|
}
|
|
810
917
|
function parseReportedLimit(message) {
|
|
811
918
|
if (!message)
|
|
812
919
|
return;
|
|
813
|
-
for (const pattern of LIMIT_EXTRACTION_PATTERNS) {
|
|
920
|
+
for (const { pattern, provenance } of LIMIT_EXTRACTION_PATTERNS) {
|
|
814
921
|
const match = message.match(pattern);
|
|
815
922
|
if (!match)
|
|
816
923
|
continue;
|
|
@@ -822,7 +929,7 @@ function parseReportedLimit(message) {
|
|
|
822
929
|
continue;
|
|
823
930
|
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
824
931
|
continue;
|
|
825
|
-
return value;
|
|
932
|
+
return { value, provenance };
|
|
826
933
|
}
|
|
827
934
|
return;
|
|
828
935
|
}
|
|
@@ -1304,6 +1411,15 @@ async function runDeferredV22Backfill(db, options = {}) {
|
|
|
1304
1411
|
};
|
|
1305
1412
|
}
|
|
1306
1413
|
|
|
1414
|
+
// ../plugin/src/hooks/magic-context/ctx-reduce-availability.ts
|
|
1415
|
+
var ctxReduceRegisteredGlobally = true;
|
|
1416
|
+
function setCtxReduceRegisteredGlobally(registered) {
|
|
1417
|
+
ctxReduceRegisteredGlobally = registered;
|
|
1418
|
+
}
|
|
1419
|
+
var availabilityBySession = new BoundedSessionMap(1000);
|
|
1420
|
+
var permissionDeniedBySession = new BoundedSessionMap(2000);
|
|
1421
|
+
var ctxReducePermissionDenyLogged = new BoundedSessionMap(1000);
|
|
1422
|
+
|
|
1307
1423
|
// ../plugin/src/hooks/magic-context/derive-budgets.ts
|
|
1308
1424
|
var TRIGGER_BUDGET_PERCENTAGE = 0.05;
|
|
1309
1425
|
var TRIGGER_BUDGET_MIN = 5000;
|
|
@@ -1347,7 +1463,6 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
1347
1463
|
|
|
1348
1464
|
// ../plugin/src/hooks/magic-context/event-resolvers.ts
|
|
1349
1465
|
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
1350
|
-
var MAX_EXECUTE_THRESHOLD = 80;
|
|
1351
1466
|
function resolveCacheTtl(cacheTtl, modelKey) {
|
|
1352
1467
|
if (typeof cacheTtl === "string") {
|
|
1353
1468
|
return cacheTtl;
|
|
@@ -1392,7 +1507,7 @@ function resolveExecuteThresholdDetail(config, modelKey, fallback, options) {
|
|
|
1392
1507
|
const dedupeKey = `${options.sessionId ?? "__global__"}|${modelKey ?? "__default__"}|${tokenMatch.value}|${cap}`;
|
|
1393
1508
|
if (!clampWarnSeen.has(dedupeKey)) {
|
|
1394
1509
|
clampWarnSeen.add(dedupeKey);
|
|
1395
|
-
const msg = `execute_threshold_tokens clamped: ${tokenMatch.value} → ${effectiveTokens} (
|
|
1510
|
+
const msg = `execute_threshold_tokens clamped: ${tokenMatch.value} → ${effectiveTokens} (${MAX_EXECUTE_THRESHOLD}% of ${contextLimit}) for ${modelKey ?? "default"}`;
|
|
1396
1511
|
if (options.sessionId) {
|
|
1397
1512
|
sessionLog(options.sessionId, `WARN: ${msg}`);
|
|
1398
1513
|
} else {
|
|
@@ -1448,7 +1563,7 @@ function resolveExecuteThresholdDetail(config, modelKey, fallback, options) {
|
|
|
1448
1563
|
const dedupeKey = `pct|${options?.sessionId ?? "__global__"}|${modelKey ?? "__default__"}|${resolved}`;
|
|
1449
1564
|
if (!clampWarnSeen.has(dedupeKey)) {
|
|
1450
1565
|
clampWarnSeen.add(dedupeKey);
|
|
1451
|
-
const msg = `execute_threshold clamped ${resolved}% → ${MAX_EXECUTE_THRESHOLD}% for ${modelKey ?? "default"} (capped
|
|
1566
|
+
const msg = `execute_threshold clamped ${resolved}% → ${MAX_EXECUTE_THRESHOLD}% for ${modelKey ?? "default"} (capped against the output-reserved safe window; 10% remains for mid-turn growth before the absolute 95% wall)`;
|
|
1452
1567
|
if (options?.sessionId) {
|
|
1453
1568
|
sessionLog(options.sessionId, `WARN: ${msg}`);
|
|
1454
1569
|
} else {
|
|
@@ -1940,6 +2055,57 @@ import {
|
|
|
1940
2055
|
import { createInterface } from "node:readline";
|
|
1941
2056
|
import { fileURLToPath } from "node:url";
|
|
1942
2057
|
|
|
2058
|
+
// ../plugin/src/features/magic-context/schema-fence-probe.ts
|
|
2059
|
+
var STALE_CHILD_SPAWN_FAILURE = "stale_schema_fence";
|
|
2060
|
+
var STALE_CHILD_SPAWN_LATCH_THRESHOLD = 2;
|
|
2061
|
+
var state = {
|
|
2062
|
+
consecutiveFailures: 0,
|
|
2063
|
+
totalFailures: 0,
|
|
2064
|
+
latched: false,
|
|
2065
|
+
noticeEmitted: false,
|
|
2066
|
+
failure: null
|
|
2067
|
+
};
|
|
2068
|
+
function recordStaleFence(persistedVersion, supportedVersion) {
|
|
2069
|
+
state.consecutiveFailures += 1;
|
|
2070
|
+
state.totalFailures += 1;
|
|
2071
|
+
const latched = state.consecutiveFailures >= STALE_CHILD_SPAWN_LATCH_THRESHOLD;
|
|
2072
|
+
state.latched ||= latched;
|
|
2073
|
+
const failure = {
|
|
2074
|
+
failureClass: STALE_CHILD_SPAWN_FAILURE,
|
|
2075
|
+
persistedVersion,
|
|
2076
|
+
supportedVersion,
|
|
2077
|
+
consecutiveFailures: state.consecutiveFailures,
|
|
2078
|
+
totalFailures: state.totalFailures,
|
|
2079
|
+
latched: state.latched
|
|
2080
|
+
};
|
|
2081
|
+
state.failure = failure;
|
|
2082
|
+
const shouldSurface = state.latched && !state.noticeEmitted;
|
|
2083
|
+
if (shouldSurface)
|
|
2084
|
+
state.noticeEmitted = true;
|
|
2085
|
+
return { allowSpawn: false, failure, shouldSurface };
|
|
2086
|
+
}
|
|
2087
|
+
function probeChildSpawnFence(db) {
|
|
2088
|
+
if (!db) {
|
|
2089
|
+
const knownRejection = getSchemaFenceRejection();
|
|
2090
|
+
if (knownRejection) {
|
|
2091
|
+
return recordStaleFence(knownRejection.persistedVersion, knownRejection.supportedVersion);
|
|
2092
|
+
}
|
|
2093
|
+
return { allowSpawn: true };
|
|
2094
|
+
}
|
|
2095
|
+
try {
|
|
2096
|
+
const persistedVersion = getPersistedSchemaVersion(db);
|
|
2097
|
+
if (persistedVersion > LATEST_SUPPORTED_VERSION) {
|
|
2098
|
+
return recordStaleFence(persistedVersion, LATEST_SUPPORTED_VERSION);
|
|
2099
|
+
}
|
|
2100
|
+
} catch {
|
|
2101
|
+
return { allowSpawn: true };
|
|
2102
|
+
}
|
|
2103
|
+
state.consecutiveFailures = 0;
|
|
2104
|
+
state.latched = false;
|
|
2105
|
+
state.noticeEmitted = false;
|
|
2106
|
+
return { allowSpawn: true };
|
|
2107
|
+
}
|
|
2108
|
+
|
|
1943
2109
|
// ../plugin/src/features/magic-context/subagent-token-capture.ts
|
|
1944
2110
|
function asNumber(value) {
|
|
1945
2111
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -2288,6 +2454,10 @@ class PiSubagentRunner {
|
|
|
2288
2454
|
if (ZERO_TOOL_PROMPT_REQUIRED_AGENTS.has(options.agent) && options.systemPrompt.trim().length === 0) {
|
|
2289
2455
|
return failBeforeSpawn("invalid_prompt", `zero-tool Pi subagent "${options.agent}" requires a non-empty system prompt`, true);
|
|
2290
2456
|
}
|
|
2457
|
+
const fence = probeChildSpawnFence(openDatabase());
|
|
2458
|
+
if (!fence.allowSpawn) {
|
|
2459
|
+
return failBeforeSpawn("spawn_failed", `Magic Context: plugin build is older than its database (database=v${fence.failure.persistedVersion}, supported_fence=v${fence.failure.supportedVersion}) — restart Pi.`);
|
|
2460
|
+
}
|
|
2291
2461
|
const promptBytes = Buffer.byteLength(options.userMessage, "utf8");
|
|
2292
2462
|
const deliverViaStdin = promptBytes > PROMPT_ARGV_MAX_BYTES || this.platform === "win32";
|
|
2293
2463
|
let systemPromptTempDir;
|
|
@@ -2859,7 +3029,7 @@ function registerCtxAugCommand(pi, config) {
|
|
|
2859
3029
|
sessionLog(sessionLabel, "/ctx-aug: spawning sidekick", {
|
|
2860
3030
|
model: currentConfig.model
|
|
2861
3031
|
});
|
|
2862
|
-
const projectIdentity = resolveProjectIdentityForSession(ctx.cwd);
|
|
3032
|
+
const projectIdentity = resolveProjectIdentityForSession(ctx.cwd, currentConfig.allowHomeProject);
|
|
2863
3033
|
if (!projectIdentity) {
|
|
2864
3034
|
sessionLog(sessionLabel, "Error: Could not resolve project identity for sidekick.");
|
|
2865
3035
|
return;
|
|
@@ -2903,264 +3073,10 @@ ${sidekickText}
|
|
|
2903
3073
|
}
|
|
2904
3074
|
|
|
2905
3075
|
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
2906
|
-
import { existsSync as existsSync5 } from "node:fs";
|
|
2907
|
-
|
|
2908
|
-
// ../plugin/src/features/magic-context/compaction-marker.ts
|
|
2909
|
-
import { createHash as createHash2 } from "node:crypto";
|
|
2910
3076
|
import { existsSync as existsSync4 } from "node:fs";
|
|
2911
|
-
import { join as join3 } from "node:path";
|
|
2912
|
-
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
2913
|
-
var ID_PREFIX_HEX_LENGTH = 12;
|
|
2914
|
-
var ID_SUFFIX_LENGTH = 14;
|
|
2915
|
-
var ID_PREFIX_MASK = (1n << BigInt(ID_PREFIX_HEX_LENGTH * 4)) - 1n;
|
|
2916
|
-
function deterministicBase62(seed, length) {
|
|
2917
|
-
let value = BigInt(`0x${createHash2("sha256").update(seed).digest("hex")}`);
|
|
2918
|
-
const chars = Array(length);
|
|
2919
|
-
for (let index = length - 1;index >= 0; index -= 1) {
|
|
2920
|
-
chars[index] = BASE62_CHARS[Number(value % 62n)];
|
|
2921
|
-
value /= 62n;
|
|
2922
|
-
}
|
|
2923
|
-
return chars.join("");
|
|
2924
|
-
}
|
|
2925
|
-
function generateId(prefix, timestampMs, counter, identity) {
|
|
2926
|
-
const encoded = BigInt(Math.max(0, Math.floor(timestampMs))) * 0x1000n + counter & ID_PREFIX_MASK;
|
|
2927
|
-
const hex = encoded.toString(16).padStart(ID_PREFIX_HEX_LENGTH, "0");
|
|
2928
|
-
return `${prefix}_${hex}${deterministicBase62(`${prefix}\x00${identity}`, ID_SUFFIX_LENGTH)}`;
|
|
2929
|
-
}
|
|
2930
|
-
function generateMessageId(timestampMs, counter = 0n, identity = "") {
|
|
2931
|
-
return generateId("msg", timestampMs, counter, identity);
|
|
2932
|
-
}
|
|
2933
|
-
function generatePartId(timestampMs, counter = 0n, identity = "") {
|
|
2934
|
-
return generateId("prt", timestampMs, counter, identity);
|
|
2935
|
-
}
|
|
2936
|
-
function getOpenCodeDbPath() {
|
|
2937
|
-
return join3(getDataDir(), "opencode", "opencode.db");
|
|
2938
|
-
}
|
|
2939
|
-
var cachedWriteDb = null;
|
|
2940
|
-
var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
|
|
2941
|
-
var REQUIRED_PART_COLUMNS = [
|
|
2942
|
-
"id",
|
|
2943
|
-
"message_id",
|
|
2944
|
-
"session_id",
|
|
2945
|
-
"time_created",
|
|
2946
|
-
"time_updated",
|
|
2947
|
-
"data"
|
|
2948
|
-
];
|
|
2949
|
-
var cachedSchemaCompatible = null;
|
|
2950
|
-
function isOpenCodeSchemaCompatible(db, dbPath) {
|
|
2951
|
-
if (cachedSchemaCompatible?.path === dbPath) {
|
|
2952
|
-
return cachedSchemaCompatible.compatible;
|
|
2953
|
-
}
|
|
2954
|
-
try {
|
|
2955
|
-
const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
|
|
2956
|
-
const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
|
|
2957
|
-
const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
|
|
2958
|
-
const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
|
|
2959
|
-
if (missingMessage.length > 0 || missingPart.length > 0) {
|
|
2960
|
-
log(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
|
|
2961
|
-
cachedSchemaCompatible = { path: dbPath, compatible: false };
|
|
2962
|
-
return false;
|
|
2963
|
-
}
|
|
2964
|
-
cachedSchemaCompatible = { path: dbPath, compatible: true };
|
|
2965
|
-
return true;
|
|
2966
|
-
} catch (error) {
|
|
2967
|
-
log(`[magic-context] compaction-marker: schema probe failed: ${error instanceof Error ? error.message : String(error)}. ` + `Marker injection disabled until next process restart.`);
|
|
2968
|
-
cachedSchemaCompatible = { path: dbPath, compatible: false };
|
|
2969
|
-
return false;
|
|
2970
|
-
}
|
|
2971
|
-
}
|
|
2972
|
-
function getWritableOpenCodeDb() {
|
|
2973
|
-
const dbPath = getOpenCodeDbPath();
|
|
2974
|
-
if (cachedWriteDb?.path === dbPath) {
|
|
2975
|
-
return cachedWriteDb.db;
|
|
2976
|
-
}
|
|
2977
|
-
if (cachedWriteDb) {
|
|
2978
|
-
try {
|
|
2979
|
-
closeQuietly(cachedWriteDb.db);
|
|
2980
|
-
} catch {}
|
|
2981
|
-
}
|
|
2982
|
-
if (!existsSync4(dbPath)) {
|
|
2983
|
-
throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
|
|
2984
|
-
}
|
|
2985
|
-
const db = new Database(dbPath);
|
|
2986
|
-
db.exec("PRAGMA busy_timeout=5000");
|
|
2987
|
-
db.exec("PRAGMA journal_mode=WAL");
|
|
2988
|
-
cachedWriteDb = { path: dbPath, db };
|
|
2989
|
-
return db;
|
|
2990
|
-
}
|
|
2991
|
-
function getNonSummaryMessageSortKey(sessionId, messageId) {
|
|
2992
|
-
const db = getWritableOpenCodeDb();
|
|
2993
|
-
const row = db.prepare(`SELECT time_created, id
|
|
2994
|
-
FROM message
|
|
2995
|
-
WHERE session_id = ?
|
|
2996
|
-
AND id = ?
|
|
2997
|
-
AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
|
|
2998
|
-
AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
|
|
2999
|
-
LIMIT 1`).get(sessionId, messageId);
|
|
3000
|
-
if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
|
|
3001
|
-
return null;
|
|
3002
|
-
}
|
|
3003
|
-
return { id: row.id, timeCreated: row.time_created };
|
|
3004
|
-
}
|
|
3005
|
-
function findBoundaryUserMessage(sessionId, endMessageId) {
|
|
3006
|
-
const db = getWritableOpenCodeDb();
|
|
3007
|
-
const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
|
|
3008
|
-
if (!target)
|
|
3009
|
-
return null;
|
|
3010
|
-
const boundary = db.prepare(`SELECT id, time_created, data
|
|
3011
|
-
FROM message
|
|
3012
|
-
WHERE session_id = ?
|
|
3013
|
-
AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
|
|
3014
|
-
AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
|
|
3015
|
-
AND COALESCE(json_extract(data, '$.role'), '') = 'user'
|
|
3016
|
-
AND (time_created < ? OR (time_created = ? AND id <= ?))
|
|
3017
|
-
ORDER BY time_created DESC, id DESC
|
|
3018
|
-
LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
|
|
3019
|
-
if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
|
|
3020
|
-
return null;
|
|
3021
|
-
}
|
|
3022
|
-
return { id: boundary.id, timeCreated: boundary.time_created };
|
|
3023
|
-
}
|
|
3024
|
-
function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
|
|
3025
|
-
const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
|
|
3026
|
-
const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
|
|
3027
|
-
if (!left || !right)
|
|
3028
|
-
return null;
|
|
3029
|
-
if (left.timeCreated < right.timeCreated)
|
|
3030
|
-
return -1;
|
|
3031
|
-
if (left.timeCreated > right.timeCreated)
|
|
3032
|
-
return 1;
|
|
3033
|
-
if (left.id < right.id)
|
|
3034
|
-
return -1;
|
|
3035
|
-
if (left.id > right.id)
|
|
3036
|
-
return 1;
|
|
3037
|
-
return 0;
|
|
3038
|
-
}
|
|
3039
|
-
function removeLegacyMarkerLineageRows(db, args) {
|
|
3040
|
-
const legacySummaries = db.prepare(`SELECT m.id
|
|
3041
|
-
FROM message m
|
|
3042
|
-
WHERE m.session_id = ?
|
|
3043
|
-
AND m.id <> ?
|
|
3044
|
-
AND COALESCE(json_extract(m.data, '$.summary'), 0) = 1
|
|
3045
|
-
AND COALESCE(json_extract(m.data, '$.finish'), '') = 'stop'
|
|
3046
|
-
AND COALESCE(json_extract(m.data, '$.parentID'), '') = ?
|
|
3047
|
-
AND EXISTS (
|
|
3048
|
-
SELECT 1
|
|
3049
|
-
FROM part p
|
|
3050
|
-
WHERE p.session_id = m.session_id
|
|
3051
|
-
AND p.message_id = m.id
|
|
3052
|
-
AND COALESCE(json_extract(p.data, '$.type'), '') = 'text'
|
|
3053
|
-
AND COALESCE(json_extract(p.data, '$.text'), '') = ?
|
|
3054
|
-
)`).all(args.sessionId, args.summaryMessageId, args.boundaryMessageId, args.summaryText);
|
|
3055
|
-
const legacySummaryIds = legacySummaries.flatMap((row) => typeof row.id === "string" ? [row.id] : []);
|
|
3056
|
-
if (legacySummaryIds.length === 0)
|
|
3057
|
-
return;
|
|
3058
|
-
const deleteSummaryParts = db.prepare("DELETE FROM part WHERE session_id = ? AND message_id = ?");
|
|
3059
|
-
const deleteSummary = db.prepare("DELETE FROM message WHERE session_id = ? AND id = ?");
|
|
3060
|
-
for (const summaryMessageId of legacySummaryIds) {
|
|
3061
|
-
deleteSummaryParts.run(args.sessionId, summaryMessageId);
|
|
3062
|
-
deleteSummary.run(args.sessionId, summaryMessageId);
|
|
3063
|
-
}
|
|
3064
|
-
db.prepare(`DELETE FROM part
|
|
3065
|
-
WHERE session_id = ?
|
|
3066
|
-
AND message_id = ?
|
|
3067
|
-
AND id <> ?
|
|
3068
|
-
AND COALESCE(json_extract(data, '$.type'), '') = 'compaction'
|
|
3069
|
-
AND COALESCE(json_extract(data, '$.auto'), 0) = 1`).run(args.sessionId, args.boundaryMessageId, args.compactionPartId);
|
|
3070
|
-
}
|
|
3071
|
-
function injectCompactionMarker(args) {
|
|
3072
|
-
const db = getWritableOpenCodeDb();
|
|
3073
|
-
if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
|
|
3074
|
-
return null;
|
|
3075
|
-
}
|
|
3076
|
-
const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
|
|
3077
|
-
if (!boundary) {
|
|
3078
|
-
log(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
|
|
3079
|
-
return null;
|
|
3080
|
-
}
|
|
3081
|
-
const boundaryTime = boundary.timeCreated;
|
|
3082
|
-
const markerIdentity = `${args.sessionId}\x00${args.endMessageId}`;
|
|
3083
|
-
const summaryMsgId = generateMessageId(boundaryTime + 1, 1n, `${markerIdentity}\x00summary-message`);
|
|
3084
|
-
const compactionPartId = generatePartId(boundaryTime, 1n, `${markerIdentity}\x00compaction-part`);
|
|
3085
|
-
const summaryPartId = generatePartId(boundaryTime + 1, 2n, `${markerIdentity}\x00summary-part`);
|
|
3086
|
-
const summaryMsgData = JSON.stringify({
|
|
3087
|
-
role: "assistant",
|
|
3088
|
-
parentID: boundary.id,
|
|
3089
|
-
summary: true,
|
|
3090
|
-
finish: "stop",
|
|
3091
|
-
mode: "compaction",
|
|
3092
|
-
agent: "compaction",
|
|
3093
|
-
path: { cwd: args.directory, root: args.directory },
|
|
3094
|
-
cost: 0,
|
|
3095
|
-
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
3096
|
-
modelID: "magic-context",
|
|
3097
|
-
providerID: "magic-context",
|
|
3098
|
-
time: { created: boundaryTime + 1 }
|
|
3099
|
-
});
|
|
3100
|
-
try {
|
|
3101
|
-
db.transaction(() => {
|
|
3102
|
-
removeLegacyMarkerLineageRows(db, {
|
|
3103
|
-
sessionId: args.sessionId,
|
|
3104
|
-
boundaryMessageId: boundary.id,
|
|
3105
|
-
summaryText: args.summaryText,
|
|
3106
|
-
summaryMessageId: summaryMsgId,
|
|
3107
|
-
compactionPartId
|
|
3108
|
-
});
|
|
3109
|
-
db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
|
|
3110
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
3111
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
3112
|
-
message_id = excluded.message_id,
|
|
3113
|
-
session_id = excluded.session_id,
|
|
3114
|
-
time_created = excluded.time_created,
|
|
3115
|
-
time_updated = excluded.time_updated,
|
|
3116
|
-
data = excluded.data`).run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
|
|
3117
|
-
db.prepare(`INSERT INTO message (id, session_id, time_created, time_updated, data)
|
|
3118
|
-
VALUES (?, ?, ?, ?, ?)
|
|
3119
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
3120
|
-
session_id = excluded.session_id,
|
|
3121
|
-
time_created = excluded.time_created,
|
|
3122
|
-
time_updated = excluded.time_updated,
|
|
3123
|
-
data = excluded.data`).run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
|
|
3124
|
-
db.prepare(`INSERT INTO part (id, message_id, session_id, time_created, time_updated, data)
|
|
3125
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
3126
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
3127
|
-
message_id = excluded.message_id,
|
|
3128
|
-
session_id = excluded.session_id,
|
|
3129
|
-
time_created = excluded.time_created,
|
|
3130
|
-
time_updated = excluded.time_updated,
|
|
3131
|
-
data = excluded.data`).run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
|
|
3132
|
-
})();
|
|
3133
|
-
log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
|
|
3134
|
-
return {
|
|
3135
|
-
boundaryMessageId: boundary.id,
|
|
3136
|
-
summaryMessageId: summaryMsgId,
|
|
3137
|
-
compactionPartId,
|
|
3138
|
-
summaryPartId
|
|
3139
|
-
};
|
|
3140
|
-
} catch (error) {
|
|
3141
|
-
log(`[magic-context] compaction-marker: injection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3142
|
-
return null;
|
|
3143
|
-
}
|
|
3144
|
-
}
|
|
3145
|
-
function removeCompactionMarker(state) {
|
|
3146
|
-
try {
|
|
3147
|
-
const db = getWritableOpenCodeDb();
|
|
3148
|
-
db.transaction(() => {
|
|
3149
|
-
db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
|
|
3150
|
-
db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
|
|
3151
|
-
db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
|
|
3152
|
-
})();
|
|
3153
|
-
return true;
|
|
3154
|
-
} catch (error) {
|
|
3155
|
-
log(`[magic-context] compaction-marker: removal failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3156
|
-
return false;
|
|
3157
|
-
}
|
|
3158
|
-
}
|
|
3159
|
-
|
|
3160
|
-
// ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
|
|
3161
3077
|
function openOpenCodeDb() {
|
|
3162
3078
|
const dbPath = getOpenCodeDbPath();
|
|
3163
|
-
if (!
|
|
3079
|
+
if (!existsSync4(dbPath)) {
|
|
3164
3080
|
log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
|
|
3165
3081
|
return null;
|
|
3166
3082
|
}
|
|
@@ -3175,8 +3091,8 @@ function openOpenCodeDb() {
|
|
|
3175
3091
|
}
|
|
3176
3092
|
|
|
3177
3093
|
// ../plugin/src/features/magic-context/dreamer/task-executor.ts
|
|
3178
|
-
import { createHash as
|
|
3179
|
-
import { existsSync as
|
|
3094
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
3095
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
3180
3096
|
|
|
3181
3097
|
// ../plugin/src/agents/dreamer.ts
|
|
3182
3098
|
var DREAMER_AGENT = "dreamer";
|
|
@@ -3186,6 +3102,201 @@ var DREAMER_MEMORY_MAPPER_AGENT = "dreamer-memory-mapper";
|
|
|
3186
3102
|
var DREAMER_CLASSIFIER_AGENT = "dreamer-classifier";
|
|
3187
3103
|
var DREAMER_DOCS_AGENT = "dreamer-docs";
|
|
3188
3104
|
var DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
|
|
3105
|
+
|
|
3106
|
+
// ../plugin/src/hooks/magic-context/send-session-notification.ts
|
|
3107
|
+
var MAX_QUEUED_IGNORED_NOTIFICATIONS = 16;
|
|
3108
|
+
var queuedIgnoredNotifications = new Map;
|
|
3109
|
+
var flushingIgnoredNotifications = new Set;
|
|
3110
|
+
var midTurnDetector = (sessionId) => isMidTurn(undefined, sessionId);
|
|
3111
|
+
function queueIgnoredNotification(notification) {
|
|
3112
|
+
const queued = queuedIgnoredNotifications.get(notification.sessionId) ?? [];
|
|
3113
|
+
queued.push(notification);
|
|
3114
|
+
if (queued.length > MAX_QUEUED_IGNORED_NOTIFICATIONS) {
|
|
3115
|
+
queued.splice(0, queued.length - MAX_QUEUED_IGNORED_NOTIFICATIONS);
|
|
3116
|
+
sessionLog(notification.sessionId, `ignored notification queue full; dropped oldest entries (kept newest ${MAX_QUEUED_IGNORED_NOTIFICATIONS})`);
|
|
3117
|
+
}
|
|
3118
|
+
queuedIgnoredNotifications.set(notification.sessionId, queued);
|
|
3119
|
+
}
|
|
3120
|
+
async function trySendTuiToast(sessionId, text, params, forcePersist) {
|
|
3121
|
+
if (forcePersist)
|
|
3122
|
+
return false;
|
|
3123
|
+
const title = extractToastTitle(text);
|
|
3124
|
+
const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
|
3125
|
+
const toastVariant = inferToastVariant(text);
|
|
3126
|
+
const duration = params.toastDurationMs ?? 5000;
|
|
3127
|
+
const { isTuiConnected: checkTui } = await import("./rpc-notifications-s2rw51c6.js");
|
|
3128
|
+
if (!checkTui(sessionId))
|
|
3129
|
+
return false;
|
|
3130
|
+
try {
|
|
3131
|
+
const { pushNotification: pushNotification2 } = await import("./rpc-notifications-s2rw51c6.js");
|
|
3132
|
+
pushNotification2("toast", {
|
|
3133
|
+
title,
|
|
3134
|
+
message,
|
|
3135
|
+
variant: toastVariant,
|
|
3136
|
+
duration
|
|
3137
|
+
}, sessionId);
|
|
3138
|
+
return true;
|
|
3139
|
+
} catch {
|
|
3140
|
+
sessionLog(sessionId, "TUI RPC toast enqueue failed, falling back to ignored message");
|
|
3141
|
+
return false;
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
function hasNotificationSessionClient(client) {
|
|
3145
|
+
if (client === null || typeof client !== "object")
|
|
3146
|
+
return false;
|
|
3147
|
+
const candidate = client;
|
|
3148
|
+
if (candidate.session === undefined)
|
|
3149
|
+
return true;
|
|
3150
|
+
if (candidate.session === null || typeof candidate.session !== "object")
|
|
3151
|
+
return false;
|
|
3152
|
+
const session = candidate.session;
|
|
3153
|
+
return (session.prompt === undefined || typeof session.prompt === "function") && (session.promptAsync === undefined || typeof session.promptAsync === "function");
|
|
3154
|
+
}
|
|
3155
|
+
function inferToastVariant(text) {
|
|
3156
|
+
const lower = text.toLowerCase();
|
|
3157
|
+
if (lower.includes("error") || lower.includes("failed") || lower.includes("alert"))
|
|
3158
|
+
return "error";
|
|
3159
|
+
if (lower.includes("warning") || lower.includes("⚠"))
|
|
3160
|
+
return "warning";
|
|
3161
|
+
if (lower.includes("complete") || lower.includes("success") || lower.includes("✓") || lower.includes("finished"))
|
|
3162
|
+
return "success";
|
|
3163
|
+
return "info";
|
|
3164
|
+
}
|
|
3165
|
+
function extractToastTitle(text) {
|
|
3166
|
+
const headingMatch = text.match(/^#+\s+(.+)/m);
|
|
3167
|
+
if (headingMatch)
|
|
3168
|
+
return headingMatch[1].trim();
|
|
3169
|
+
const firstLine = text.split(`
|
|
3170
|
+
`)[0].trim();
|
|
3171
|
+
if (firstLine.length <= 80)
|
|
3172
|
+
return firstLine;
|
|
3173
|
+
return "Magic Context";
|
|
3174
|
+
}
|
|
3175
|
+
async function sendIgnoredMessageNow(client, sessionId, text, params, forcePersist) {
|
|
3176
|
+
if (midTurnDetector(sessionId)) {
|
|
3177
|
+
queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
|
|
3178
|
+
return "queued";
|
|
3179
|
+
}
|
|
3180
|
+
const { waitForSafeNotificationTarget } = await import("./safe-notification-target-ng8ygena.js");
|
|
3181
|
+
if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
|
|
3182
|
+
sessionLog(sessionId, "notification skipped (session not titled yet)");
|
|
3183
|
+
return "skipped";
|
|
3184
|
+
}
|
|
3185
|
+
if (midTurnDetector(sessionId)) {
|
|
3186
|
+
queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
|
|
3187
|
+
return "queued";
|
|
3188
|
+
}
|
|
3189
|
+
if (!hasNotificationSessionClient(client)) {
|
|
3190
|
+
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
3191
|
+
return "failed";
|
|
3192
|
+
}
|
|
3193
|
+
const c = client;
|
|
3194
|
+
let agent = params.agent || undefined;
|
|
3195
|
+
let variant = params.variant || undefined;
|
|
3196
|
+
let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
|
|
3197
|
+
if (!agent || !model || !variant) {
|
|
3198
|
+
try {
|
|
3199
|
+
const { resolvePromptContext } = await import("./prompt-context-602yq94t.js");
|
|
3200
|
+
const resolved = await resolvePromptContext(client, sessionId);
|
|
3201
|
+
if (resolved) {
|
|
3202
|
+
agent = agent ?? resolved.agent;
|
|
3203
|
+
model = model ?? resolved.model;
|
|
3204
|
+
variant = variant ?? resolved.variant;
|
|
3205
|
+
}
|
|
3206
|
+
} catch {}
|
|
3207
|
+
}
|
|
3208
|
+
if (midTurnDetector(sessionId)) {
|
|
3209
|
+
queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
|
|
3210
|
+
return "queued";
|
|
3211
|
+
}
|
|
3212
|
+
const input = {
|
|
3213
|
+
path: { id: sessionId },
|
|
3214
|
+
body: {
|
|
3215
|
+
noReply: true,
|
|
3216
|
+
agent,
|
|
3217
|
+
model,
|
|
3218
|
+
variant,
|
|
3219
|
+
parts: [
|
|
3220
|
+
{
|
|
3221
|
+
type: "text",
|
|
3222
|
+
text,
|
|
3223
|
+
ignored: true
|
|
3224
|
+
}
|
|
3225
|
+
]
|
|
3226
|
+
}
|
|
3227
|
+
};
|
|
3228
|
+
try {
|
|
3229
|
+
if (typeof c.session?.prompt === "function") {
|
|
3230
|
+
await Promise.resolve(c.session.prompt(input));
|
|
3231
|
+
return "sent";
|
|
3232
|
+
}
|
|
3233
|
+
if (typeof c.session?.promptAsync === "function") {
|
|
3234
|
+
await c.session.promptAsync(input);
|
|
3235
|
+
return "sent";
|
|
3236
|
+
}
|
|
3237
|
+
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
3238
|
+
return "failed";
|
|
3239
|
+
} catch (error) {
|
|
3240
|
+
const msg = getErrorMessage(error);
|
|
3241
|
+
sessionLog(sessionId, "failed to send notification:", msg);
|
|
3242
|
+
return "failed";
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
async function sendIgnoredMessage(client, sessionId, text, params, forcePersist = false) {
|
|
3246
|
+
if (await trySendTuiToast(sessionId, text, params, forcePersist))
|
|
3247
|
+
return "sent";
|
|
3248
|
+
if (midTurnDetector(sessionId)) {
|
|
3249
|
+
queueIgnoredNotification({ client, sessionId, text, params, forcePersist });
|
|
3250
|
+
return "queued";
|
|
3251
|
+
}
|
|
3252
|
+
return sendIgnoredMessageNow(client, sessionId, text, params, forcePersist);
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
// ../plugin/src/hooks/magic-context/child-session-spawn.ts
|
|
3256
|
+
var STALE_PLUGIN_RESTART_NOTICE = "Magic Context: plugin build is older than its database — restart OpenCode";
|
|
3257
|
+
async function surfaceStalePluginBuild(args) {
|
|
3258
|
+
if (!args.parentSessionId)
|
|
3259
|
+
return;
|
|
3260
|
+
try {
|
|
3261
|
+
if (args.db) {
|
|
3262
|
+
updateSessionMeta(args.db, args.parentSessionId, {
|
|
3263
|
+
lastTransformError: STALE_PLUGIN_RESTART_NOTICE
|
|
3264
|
+
});
|
|
3265
|
+
}
|
|
3266
|
+
pushNotification("toast", {
|
|
3267
|
+
title: "Magic Context",
|
|
3268
|
+
message: STALE_PLUGIN_RESTART_NOTICE,
|
|
3269
|
+
variant: "error",
|
|
3270
|
+
duration: 1e4
|
|
3271
|
+
}, args.parentSessionId);
|
|
3272
|
+
pushNotification("action", { action: "refresh-sidebar" }, args.parentSessionId);
|
|
3273
|
+
await sendIgnoredMessage(args.client, args.parentSessionId, STALE_PLUGIN_RESTART_NOTICE, args.notificationParams ?? {}, true);
|
|
3274
|
+
} catch (error) {
|
|
3275
|
+
sessionLog(args.parentSessionId, `stale plugin-build warning delivery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
async function createChildSessionWithFence(args) {
|
|
3279
|
+
const verdict = probeChildSpawnFence(args.db);
|
|
3280
|
+
if (!verdict.allowSpawn) {
|
|
3281
|
+
if (args.parentSessionId) {
|
|
3282
|
+
sessionLog(args.parentSessionId, `child session skipped (${verdict.failure.failureClass}): database=v${verdict.failure.persistedVersion}, supported_fence=v${verdict.failure.supportedVersion}, consecutive=${verdict.failure.consecutiveFailures}, total=${verdict.failure.totalFailures}`);
|
|
3283
|
+
}
|
|
3284
|
+
if (verdict.shouldSurface) {
|
|
3285
|
+
if (args.onFenceLatched)
|
|
3286
|
+
await args.onFenceLatched(verdict.failure);
|
|
3287
|
+
else
|
|
3288
|
+
await surfaceStalePluginBuild(args);
|
|
3289
|
+
}
|
|
3290
|
+
return null;
|
|
3291
|
+
}
|
|
3292
|
+
return args.client.session.create({
|
|
3293
|
+
body: {
|
|
3294
|
+
...args.parentSessionId ? { parentID: args.parentSessionId } : {},
|
|
3295
|
+
title: args.title
|
|
3296
|
+
},
|
|
3297
|
+
query: { directory: args.directory }
|
|
3298
|
+
});
|
|
3299
|
+
}
|
|
3189
3300
|
// ../plugin/src/shared/model-suggestion-retry.ts
|
|
3190
3301
|
var ABORT_CALL_TIMEOUT_MS = 3000;
|
|
3191
3302
|
function copyPromptArgs(args, body) {
|
|
@@ -3839,7 +3950,7 @@ function parseCuesManifest(text) {
|
|
|
3839
3950
|
const body = extractCompleteManifestBody(text, "cues");
|
|
3840
3951
|
const out = [];
|
|
3841
3952
|
for (const match of body.matchAll(/<cue\s+id="(\d+)"\s*>([\s\S]*?)<\/cue>/g)) {
|
|
3842
|
-
const id = Number.parseInt(match[1], 10);
|
|
3953
|
+
const id = Number.parseInt(match[1] ?? "", 10);
|
|
3843
3954
|
if (!Number.isInteger(id))
|
|
3844
3955
|
continue;
|
|
3845
3956
|
out.push({ id, cue: unescapeXml(match[2] ?? "").trim() });
|
|
@@ -3940,7 +4051,10 @@ async function runCompressCues(args) {
|
|
|
3940
4051
|
break;
|
|
3941
4052
|
}
|
|
3942
4053
|
const sliceMs = computeChunkSliceMs(remainingMs, chunks.length - i);
|
|
3943
|
-
const
|
|
4054
|
+
const chunk = chunks[i];
|
|
4055
|
+
if (!chunk)
|
|
4056
|
+
break;
|
|
4057
|
+
const outcome = await compressOneChunk(args, chunk, sliceMs, abortController.signal);
|
|
3944
4058
|
result.compressed += outcome.compressed;
|
|
3945
4059
|
result.skipped += outcome.skipped;
|
|
3946
4060
|
result.remaining -= outcome.compressed;
|
|
@@ -3975,12 +4089,12 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
3975
4089
|
projectPath: args.projectIdentity,
|
|
3976
4090
|
memories: chunk.map(toPromptMemory)
|
|
3977
4091
|
});
|
|
3978
|
-
const createResponse = await
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
4092
|
+
const createResponse = await createChildSessionWithFence({
|
|
4093
|
+
client: args.client,
|
|
4094
|
+
db: args.db,
|
|
4095
|
+
parentSessionId: args.parentSessionId,
|
|
4096
|
+
title: "magic-context-dream-compress-cues",
|
|
4097
|
+
directory: args.sessionDirectory
|
|
3984
4098
|
});
|
|
3985
4099
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
3986
4100
|
preferResponseOnMissingData: true
|
|
@@ -4464,12 +4578,12 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
4464
4578
|
abortController.abort();
|
|
4465
4579
|
});
|
|
4466
4580
|
try {
|
|
4467
|
-
const createResponse = await
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4581
|
+
const createResponse = await createChildSessionWithFence({
|
|
4582
|
+
client: args.client,
|
|
4583
|
+
db: args.db,
|
|
4584
|
+
parentSessionId: args.parentSessionId,
|
|
4585
|
+
title: "magic-context-dream-user-memories",
|
|
4586
|
+
directory: args.sessionDirectory
|
|
4473
4587
|
});
|
|
4474
4588
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
4475
4589
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
@@ -4585,7 +4699,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
4585
4699
|
}
|
|
4586
4700
|
|
|
4587
4701
|
// ../plugin/src/features/magic-context/dreamer/classify.ts
|
|
4588
|
-
import { createHash as
|
|
4702
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
4589
4703
|
|
|
4590
4704
|
// ../plugin/src/plugin/rust-tool-backends.ts
|
|
4591
4705
|
function isRustAuthorityDrainingError(error) {
|
|
@@ -5063,12 +5177,12 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
5063
5177
|
recordInvocation(args, startedAt, { status: "completed" });
|
|
5064
5178
|
return run2;
|
|
5065
5179
|
}
|
|
5066
|
-
const createResponse = await
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5180
|
+
const createResponse = await createChildSessionWithFence({
|
|
5181
|
+
client: args.client,
|
|
5182
|
+
db: args.db,
|
|
5183
|
+
parentSessionId: args.parentSessionId,
|
|
5184
|
+
title: "magic-context-dream-classify",
|
|
5185
|
+
directory: args.sessionDirectory
|
|
5072
5186
|
});
|
|
5073
5187
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
5074
5188
|
preferResponseOnMissingData: true
|
|
@@ -5146,7 +5260,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
|
|
|
5146
5260
|
v: 1,
|
|
5147
5261
|
session_id: args.moduleSessionId,
|
|
5148
5262
|
task: "classify",
|
|
5149
|
-
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${
|
|
5263
|
+
command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash2("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
|
|
5150
5264
|
authority_generation: args.moduleAuthorityGeneration,
|
|
5151
5265
|
payload: {
|
|
5152
5266
|
prompt_body: prompt,
|
|
@@ -5842,7 +5956,7 @@ function throwIfAborted2(signal) {
|
|
|
5842
5956
|
}
|
|
5843
5957
|
|
|
5844
5958
|
// ../plugin/src/features/magic-context/smart-notes/compiler.ts
|
|
5845
|
-
import { createHash as
|
|
5959
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
5846
5960
|
|
|
5847
5961
|
// ../plugin/src/features/magic-context/smart-notes/compiler-prompt.ts
|
|
5848
5962
|
var SMART_NOTE_COMPILER_SYSTEM_PROMPT = `You are the Magic Context smart-note compiler for the magic-context system.
|
|
@@ -5880,7 +5994,7 @@ function getAsyncModule() {
|
|
|
5880
5994
|
asyncModulePromise ??= (async () => {
|
|
5881
5995
|
const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
|
|
5882
5996
|
import("./index-ayd60xnw.js").then((m)=>__toESM(m.default,1)),
|
|
5883
|
-
import("./index-
|
|
5997
|
+
import("./index-3pnd4qh9.js")
|
|
5884
5998
|
]);
|
|
5885
5999
|
return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
|
|
5886
6000
|
})();
|
|
@@ -6099,12 +6213,12 @@ Remember: output only the JSON object described by the system prompt.`;
|
|
|
6099
6213
|
});
|
|
6100
6214
|
};
|
|
6101
6215
|
try {
|
|
6102
|
-
const createResponse = await
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
}
|
|
6107
|
-
|
|
6216
|
+
const createResponse = await createChildSessionWithFence({
|
|
6217
|
+
client: args.client,
|
|
6218
|
+
db: args.db ?? null,
|
|
6219
|
+
parentSessionId: args.parentSessionId,
|
|
6220
|
+
title: `magic-context-smart-note-compile-${args.note.id}`,
|
|
6221
|
+
directory: args.sessionDirectory ?? args.projectIdentity
|
|
6108
6222
|
});
|
|
6109
6223
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
6110
6224
|
preferResponseOnMissingData: true
|
|
@@ -6266,7 +6380,7 @@ function manifestAdvisoryWarnings(code, manifest) {
|
|
|
6266
6380
|
return warnings;
|
|
6267
6381
|
}
|
|
6268
6382
|
function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
|
|
6269
|
-
return
|
|
6383
|
+
return createHash3("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
|
|
6270
6384
|
}
|
|
6271
6385
|
function extractJsonObject(output) {
|
|
6272
6386
|
const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
@@ -6885,12 +6999,12 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
|
|
|
6885
6999
|
});
|
|
6886
7000
|
};
|
|
6887
7001
|
try {
|
|
6888
|
-
const createResponse = await
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
}
|
|
6893
|
-
|
|
7002
|
+
const createResponse = await createChildSessionWithFence({
|
|
7003
|
+
client: args.client,
|
|
7004
|
+
db: args.db,
|
|
7005
|
+
parentSessionId: args.parentSessionId,
|
|
7006
|
+
title: `magic-context-smart-note-confirm-${noteId}`,
|
|
7007
|
+
directory: args.sessionDirectory ?? args.projectIdentity
|
|
6894
7008
|
});
|
|
6895
7009
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
6896
7010
|
preferResponseOnMissingData: true
|
|
@@ -6964,8 +7078,8 @@ Output exactly JSON: {"met": false}`;
|
|
|
6964
7078
|
}
|
|
6965
7079
|
|
|
6966
7080
|
// ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
|
|
6967
|
-
import { existsSync as
|
|
6968
|
-
import { join as
|
|
7081
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
7082
|
+
import { join as join3 } from "node:path";
|
|
6969
7083
|
|
|
6970
7084
|
// ../plugin/src/features/magic-context/dreamer/protected-regions.ts
|
|
6971
7085
|
var PROTECTED_START_TOKEN = "mc:protected START";
|
|
@@ -7066,9 +7180,9 @@ var MAINTAIN_DOCS_SNAPSHOT_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
|
7066
7180
|
function snapshotMaintainDocsFiles(docsDir) {
|
|
7067
7181
|
const snapshot = new Map;
|
|
7068
7182
|
for (const name of MAINTAIN_DOCS_SNAPSHOT_FILES) {
|
|
7069
|
-
const path4 =
|
|
7183
|
+
const path4 = join3(docsDir, name);
|
|
7070
7184
|
try {
|
|
7071
|
-
if (
|
|
7185
|
+
if (existsSync5(path4)) {
|
|
7072
7186
|
snapshot.set(name, readFileSync2(path4, "utf8"));
|
|
7073
7187
|
}
|
|
7074
7188
|
} catch {}
|
|
@@ -7077,7 +7191,7 @@ function snapshotMaintainDocsFiles(docsDir) {
|
|
|
7077
7191
|
}
|
|
7078
7192
|
function enforceMaintainDocsProtectedRegions(args) {
|
|
7079
7193
|
for (const [fileName, original] of args.snapshot) {
|
|
7080
|
-
const path4 =
|
|
7194
|
+
const path4 = join3(args.docsDir, fileName);
|
|
7081
7195
|
try {
|
|
7082
7196
|
const current = readFileSync2(path4, "utf8");
|
|
7083
7197
|
const { text, violated } = enforceProtectedRegions(original, current);
|
|
@@ -7093,10 +7207,10 @@ function enforceMaintainDocsProtectedRegions(args) {
|
|
|
7093
7207
|
}
|
|
7094
7208
|
|
|
7095
7209
|
// ../plugin/src/features/magic-context/dreamer/map-memories.ts
|
|
7096
|
-
import { createHash as
|
|
7210
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
7097
7211
|
|
|
7098
7212
|
// ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
|
|
7099
|
-
import { existsSync as
|
|
7213
|
+
import { existsSync as existsSync6, statSync } from "node:fs";
|
|
7100
7214
|
import path4 from "node:path";
|
|
7101
7215
|
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.
|
|
7102
7216
|
|
|
@@ -7134,7 +7248,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
|
|
|
7134
7248
|
if (!abs.startsWith(`${root}/`))
|
|
7135
7249
|
continue;
|
|
7136
7250
|
try {
|
|
7137
|
-
if (
|
|
7251
|
+
if (existsSync6(abs) && statSync(abs).isFile())
|
|
7138
7252
|
found.add(rel);
|
|
7139
7253
|
} catch {}
|
|
7140
7254
|
if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
|
|
@@ -7235,12 +7349,12 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
7235
7349
|
let agentSessionId = null;
|
|
7236
7350
|
const startedAt = Date.now();
|
|
7237
7351
|
try {
|
|
7238
|
-
const createResponse = await
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7352
|
+
const createResponse = await createChildSessionWithFence({
|
|
7353
|
+
client: args.client,
|
|
7354
|
+
db: args.db,
|
|
7355
|
+
parentSessionId: args.parentSessionId,
|
|
7356
|
+
title: "magic-context-dream-map-memories",
|
|
7357
|
+
directory: args.sessionDirectory
|
|
7244
7358
|
});
|
|
7245
7359
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
7246
7360
|
preferResponseOnMissingData: true
|
|
@@ -7353,7 +7467,7 @@ async function applyBatchMappings(args, batch, manifestText) {
|
|
|
7353
7467
|
memory_project: args.projectIdentity,
|
|
7354
7468
|
context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
|
|
7355
7469
|
authority_generation: args.moduleRoute.moduleAuthorityGeneration,
|
|
7356
|
-
command_id: `${args.moduleRoute.moduleCommandId}:${
|
|
7470
|
+
command_id: `${args.moduleRoute.moduleCommandId}:${createHash4("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
|
|
7357
7471
|
rows
|
|
7358
7472
|
}
|
|
7359
7473
|
}
|
|
@@ -7852,12 +7966,12 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7852
7966
|
let agentSessionId = null;
|
|
7853
7967
|
const startedAt = Date.now();
|
|
7854
7968
|
try {
|
|
7855
|
-
const createResponse = await
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7969
|
+
const createResponse = await createChildSessionWithFence({
|
|
7970
|
+
client: args.client,
|
|
7971
|
+
db: args.db,
|
|
7972
|
+
parentSessionId: args.parentSessionId,
|
|
7973
|
+
title: "magic-context-dream-refresh-primers",
|
|
7974
|
+
directory: args.sessionDirectory
|
|
7861
7975
|
});
|
|
7862
7976
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
7863
7977
|
preferResponseOnMissingData: true
|
|
@@ -8355,8 +8469,8 @@ function extractToolRows(parts) {
|
|
|
8355
8469
|
const record = part;
|
|
8356
8470
|
if (record.type !== "tool" || typeof record.tool !== "string")
|
|
8357
8471
|
continue;
|
|
8358
|
-
const
|
|
8359
|
-
const stateRecord =
|
|
8472
|
+
const state2 = record.state;
|
|
8473
|
+
const stateRecord = state2 && typeof state2 === "object" ? state2 : {};
|
|
8360
8474
|
const output = stringifyToolOutput(stateRecord.output);
|
|
8361
8475
|
const errorText = stringifyToolOutput(stateRecord.error);
|
|
8362
8476
|
const status = typeof stateRecord.status === "string" ? stateRecord.status : "";
|
|
@@ -8473,7 +8587,7 @@ function recordRetrospectiveWindowProcessed(db, projectPath, windowKey) {
|
|
|
8473
8587
|
}
|
|
8474
8588
|
|
|
8475
8589
|
// ../plugin/src/features/magic-context/dreamer/verify.ts
|
|
8476
|
-
import { createHash as
|
|
8590
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
8477
8591
|
|
|
8478
8592
|
// ../plugin/src/features/magic-context/dreamer/verify-gate.ts
|
|
8479
8593
|
import path5 from "node:path";
|
|
@@ -8683,12 +8797,12 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
8683
8797
|
let agentSessionId = null;
|
|
8684
8798
|
const startedAt = Date.now();
|
|
8685
8799
|
try {
|
|
8686
|
-
const createResponse = await
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8800
|
+
const createResponse = await createChildSessionWithFence({
|
|
8801
|
+
client: args.client,
|
|
8802
|
+
db: args.db,
|
|
8803
|
+
parentSessionId: args.parentSessionId,
|
|
8804
|
+
title: "magic-context-dream-verify",
|
|
8805
|
+
directory: args.sessionDirectory
|
|
8692
8806
|
});
|
|
8693
8807
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
8694
8808
|
preferResponseOnMissingData: true
|
|
@@ -8811,7 +8925,7 @@ async function applyVerifyManifest(args, batch, manifestText) {
|
|
|
8811
8925
|
memory_project: args.projectIdentity,
|
|
8812
8926
|
context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
|
|
8813
8927
|
authority_generation: args.moduleRoute.moduleAuthorityGeneration,
|
|
8814
|
-
command_id: `${args.moduleRoute.moduleCommandId}:${
|
|
8928
|
+
command_id: `${args.moduleRoute.moduleCommandId}:${createHash5("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
|
|
8815
8929
|
rows
|
|
8816
8930
|
}
|
|
8817
8931
|
}
|
|
@@ -9308,7 +9422,7 @@ function parseFrictionGateVerdict(verdict) {
|
|
|
9308
9422
|
}
|
|
9309
9423
|
function computeRetrospectiveWindowKey(flagged) {
|
|
9310
9424
|
const anchors = flagged.map((message) => `${message.sessionId}:${message.ts}`).sort().join("|");
|
|
9311
|
-
return
|
|
9425
|
+
return createHash6("sha256").update(anchors).digest("hex").slice(0, 32);
|
|
9312
9426
|
}
|
|
9313
9427
|
function renderFrictionWindow(messages, flaggedOrdinals, radius = 2) {
|
|
9314
9428
|
const flagged = new Set(flaggedOrdinals);
|
|
@@ -9375,12 +9489,12 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
9375
9489
|
});
|
|
9376
9490
|
let childSessionId = null;
|
|
9377
9491
|
try {
|
|
9378
|
-
const createResponse = await
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9492
|
+
const createResponse = await createChildSessionWithFence({
|
|
9493
|
+
client: deps.client,
|
|
9494
|
+
db,
|
|
9495
|
+
parentSessionId: parent ?? undefined,
|
|
9496
|
+
title: "magic-context-dream-retrospective",
|
|
9497
|
+
directory: deps.sessionDirectory
|
|
9384
9498
|
});
|
|
9385
9499
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
9386
9500
|
childSessionId = typeof created?.id === "string" ? created.id : null;
|
|
@@ -9541,8 +9655,8 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9541
9655
|
const lastRunAt = getTaskScheduleState(db, projectIdentity, config.task)?.lastRunAt ?? null;
|
|
9542
9656
|
const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
|
|
9543
9657
|
const existingDocs = task === "maintain-docs" ? {
|
|
9544
|
-
architecture:
|
|
9545
|
-
structure:
|
|
9658
|
+
architecture: existsSync7(`${docsDir}/ARCHITECTURE.md`),
|
|
9659
|
+
structure: existsSync7(`${docsDir}/STRUCTURE.md`)
|
|
9546
9660
|
} : undefined;
|
|
9547
9661
|
const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
|
|
9548
9662
|
let curateMemories;
|
|
@@ -9565,12 +9679,12 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9565
9679
|
});
|
|
9566
9680
|
let childSessionId = null;
|
|
9567
9681
|
try {
|
|
9568
|
-
const createResponse = await
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
}
|
|
9573
|
-
|
|
9682
|
+
const createResponse = await createChildSessionWithFence({
|
|
9683
|
+
client: deps.client,
|
|
9684
|
+
db,
|
|
9685
|
+
parentSessionId: parent ?? undefined,
|
|
9686
|
+
title: `magic-context-dream-${task}`,
|
|
9687
|
+
directory: docsDir
|
|
9574
9688
|
});
|
|
9575
9689
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
9576
9690
|
preferResponseOnMissingData: true
|
|
@@ -9742,11 +9856,11 @@ function planDueTasks(db, projectIdentity, tasks, now) {
|
|
|
9742
9856
|
const due = [];
|
|
9743
9857
|
for (const config of tasks) {
|
|
9744
9858
|
reconcileSchedule(db, projectIdentity, config, now);
|
|
9745
|
-
const
|
|
9746
|
-
if (!
|
|
9859
|
+
const state2 = getTaskScheduleState(db, projectIdentity, config.task);
|
|
9860
|
+
if (!state2 || state2.nextDueAt === null)
|
|
9747
9861
|
continue;
|
|
9748
|
-
if (now >=
|
|
9749
|
-
due.push({ config, scheduledAt:
|
|
9862
|
+
if (now >= state2.nextDueAt) {
|
|
9863
|
+
due.push({ config, scheduledAt: state2.nextDueAt });
|
|
9750
9864
|
}
|
|
9751
9865
|
}
|
|
9752
9866
|
return due;
|
|
@@ -11251,6 +11365,101 @@ function executeFlush(db, sessionId) {
|
|
|
11251
11365
|
}
|
|
11252
11366
|
}
|
|
11253
11367
|
|
|
11368
|
+
// src/compaction-off-pi.ts
|
|
11369
|
+
var COMPACTION_OFF_COMMAND_UNAVAILABLE = `Unavailable: magic-context is in compaction-off mode (${COMPACTION_ENABLED_PATH}=false).`;
|
|
11370
|
+
var NO_TRANSITION = {
|
|
11371
|
+
recordToWrite: null,
|
|
11372
|
+
invalidatedBaseline: false,
|
|
11373
|
+
clearDeferredMarkerState: false,
|
|
11374
|
+
historianCatchUpSignaled: false,
|
|
11375
|
+
notice: null
|
|
11376
|
+
};
|
|
11377
|
+
var PI_COMPACTION_OFF_NOTICE = "Magic Context is in compaction-off mode. Native Pi compaction now owns this session's context window; the first turn after disabling may trigger one native compaction cycle on long sessions.";
|
|
11378
|
+
var PI_COMPACTION_ON_NOTICE = "Magic Context context-window management resumed. Run /ctx-wrapup to digest history accumulated while compaction was off.";
|
|
11379
|
+
function reconcilePiCompactionMode(args) {
|
|
11380
|
+
const stored = getCompactionModeRecord(args.db, args.sessionId);
|
|
11381
|
+
if (stored === "on_notice_pending") {
|
|
11382
|
+
return {
|
|
11383
|
+
...NO_TRANSITION,
|
|
11384
|
+
recordToWrite: "on",
|
|
11385
|
+
notice: PI_COMPACTION_ON_NOTICE
|
|
11386
|
+
};
|
|
11387
|
+
}
|
|
11388
|
+
if (stored === "off_notice_pending") {
|
|
11389
|
+
return {
|
|
11390
|
+
...NO_TRANSITION,
|
|
11391
|
+
recordToWrite: "off",
|
|
11392
|
+
notice: PI_COMPACTION_OFF_NOTICE
|
|
11393
|
+
};
|
|
11394
|
+
}
|
|
11395
|
+
if (!args.compactionOff) {
|
|
11396
|
+
if (stored === null || resolveCompactionModeRecord(stored) === "on") {
|
|
11397
|
+
return stored === null ? { ...NO_TRANSITION, recordToWrite: "on" } : NO_TRANSITION;
|
|
11398
|
+
}
|
|
11399
|
+
clearCachedM0M1(args.db, args.sessionId);
|
|
11400
|
+
if (!args.historianRunnable) {
|
|
11401
|
+
return {
|
|
11402
|
+
...NO_TRANSITION,
|
|
11403
|
+
recordToWrite: "on",
|
|
11404
|
+
invalidatedBaseline: true
|
|
11405
|
+
};
|
|
11406
|
+
}
|
|
11407
|
+
updateSessionMeta(args.db, args.sessionId, {
|
|
11408
|
+
compartmentInProgress: true
|
|
11409
|
+
});
|
|
11410
|
+
setCompactionModeRecord(args.db, args.sessionId, "on_notice_pending");
|
|
11411
|
+
return {
|
|
11412
|
+
recordToWrite: "on",
|
|
11413
|
+
invalidatedBaseline: true,
|
|
11414
|
+
clearDeferredMarkerState: false,
|
|
11415
|
+
historianCatchUpSignaled: true,
|
|
11416
|
+
notice: PI_COMPACTION_ON_NOTICE
|
|
11417
|
+
};
|
|
11418
|
+
}
|
|
11419
|
+
if (resolveCompactionModeRecord(stored) === "off")
|
|
11420
|
+
return NO_TRANSITION;
|
|
11421
|
+
let clearedSomething = false;
|
|
11422
|
+
if (getPendingPiCompactionMarkerState(args.db, args.sessionId) !== null) {
|
|
11423
|
+
setPendingPiCompactionMarkerState(args.db, args.sessionId, null);
|
|
11424
|
+
clearedSomething = true;
|
|
11425
|
+
}
|
|
11426
|
+
if (getOverflowState(args.db, args.sessionId).needsEmergencyRecovery) {
|
|
11427
|
+
clearEmergencyRecovery(args.db, args.sessionId);
|
|
11428
|
+
clearedSomething = true;
|
|
11429
|
+
}
|
|
11430
|
+
const channel2 = getChannel2NudgeState(args.db, args.sessionId);
|
|
11431
|
+
if (channel2 === "pending" || channel2 === "claimed") {
|
|
11432
|
+
setChannel2NudgeState(args.db, args.sessionId, "");
|
|
11433
|
+
clearedSomething = true;
|
|
11434
|
+
}
|
|
11435
|
+
if (getPendingOps(args.db, args.sessionId).length > 0) {
|
|
11436
|
+
clearPendingOps(args.db, args.sessionId);
|
|
11437
|
+
clearedSomething = true;
|
|
11438
|
+
}
|
|
11439
|
+
const meta = getOrCreateSessionMeta(args.db, args.sessionId);
|
|
11440
|
+
if (meta.compartmentInProgress) {
|
|
11441
|
+
updateSessionMeta(args.db, args.sessionId, {
|
|
11442
|
+
compartmentInProgress: false
|
|
11443
|
+
});
|
|
11444
|
+
}
|
|
11445
|
+
clearCachedM0M1(args.db, args.sessionId);
|
|
11446
|
+
sessionLog(args.sessionId, `Pi compaction-off transition: clearedPendingMarker=${clearedSomething}`);
|
|
11447
|
+
const notice = clearedSomething ? PI_COMPACTION_OFF_NOTICE : null;
|
|
11448
|
+
if (notice) {
|
|
11449
|
+
setCompactionModeRecord(args.db, args.sessionId, "off_notice_pending");
|
|
11450
|
+
}
|
|
11451
|
+
return {
|
|
11452
|
+
recordToWrite: "off",
|
|
11453
|
+
invalidatedBaseline: true,
|
|
11454
|
+
clearDeferredMarkerState: true,
|
|
11455
|
+
historianCatchUpSignaled: false,
|
|
11456
|
+
notice
|
|
11457
|
+
};
|
|
11458
|
+
}
|
|
11459
|
+
function commitPiCompactionModeRecord(db, sessionId, record) {
|
|
11460
|
+
setCompactionModeRecord(db, sessionId, record);
|
|
11461
|
+
}
|
|
11462
|
+
|
|
11254
11463
|
// src/context-handler.ts
|
|
11255
11464
|
import * as crypto3 from "node:crypto";
|
|
11256
11465
|
|
|
@@ -11264,6 +11473,9 @@ var UNIT_TO_MS = {
|
|
|
11264
11473
|
};
|
|
11265
11474
|
function parseCacheTtl(ttl) {
|
|
11266
11475
|
const normalizedTtl = ttl.trim();
|
|
11476
|
+
if (normalizedTtl.toLowerCase() === "never") {
|
|
11477
|
+
return Number.POSITIVE_INFINITY;
|
|
11478
|
+
}
|
|
11267
11479
|
if (NUMERIC_PATTERN.test(normalizedTtl)) {
|
|
11268
11480
|
return Number(normalizedTtl);
|
|
11269
11481
|
}
|
|
@@ -11979,9 +12191,9 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
11979
12191
|
}
|
|
11980
12192
|
|
|
11981
12193
|
// ../plugin/src/hooks/magic-context/boundary-execution.ts
|
|
11982
|
-
var FORCE_MATERIALIZE_PERCENTAGE = 85;
|
|
11983
12194
|
function detectMidTurnBypassReason(input) {
|
|
11984
|
-
|
|
12195
|
+
const { forceMaterializationPercentage } = escalationBands(input.effectiveExecuteThresholdPercentage);
|
|
12196
|
+
if (input.contextUsage.percentage >= forceMaterializationPercentage)
|
|
11985
12197
|
return "force-materialize";
|
|
11986
12198
|
if (input.historyRefreshSessions.has(input.sessionId))
|
|
11987
12199
|
return "explicit-bust";
|
|
@@ -12474,29 +12686,29 @@ function callIdFromPart(part) {
|
|
|
12474
12686
|
const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
|
|
12475
12687
|
if (direct)
|
|
12476
12688
|
return direct;
|
|
12477
|
-
const
|
|
12478
|
-
return
|
|
12689
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
12690
|
+
return state2 ? firstStringField(state2, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
|
|
12479
12691
|
}
|
|
12480
12692
|
function toolSignalFromPart(part) {
|
|
12481
12693
|
if (!isRecord(part))
|
|
12482
12694
|
return null;
|
|
12483
12695
|
const type = partType(part);
|
|
12484
|
-
const
|
|
12696
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
12485
12697
|
const callId = callIdFromPart(part);
|
|
12486
12698
|
if (!callId && type !== "tool")
|
|
12487
12699
|
return null;
|
|
12488
12700
|
if (type === "tool") {
|
|
12489
|
-
const hasInput =
|
|
12490
|
-
const outputKey =
|
|
12701
|
+
const hasInput = state2 !== null && hasOwn(state2, "input");
|
|
12702
|
+
const outputKey = state2 ? hasOwn(state2, "output") ? "output" : hasOwn(state2, "error") ? "error" : hasOwn(state2, "result") ? "result" : null : null;
|
|
12491
12703
|
const hasOutput = outputKey !== null;
|
|
12492
|
-
const outputValue = outputKey &&
|
|
12704
|
+
const outputValue = outputKey && state2 ? state2[outputKey] : undefined;
|
|
12493
12705
|
const providerExecuted = part.providerExecuted === true;
|
|
12494
12706
|
const openInvocation = !providerExecuted && !hasOutput;
|
|
12495
12707
|
return {
|
|
12496
12708
|
callId,
|
|
12497
12709
|
hasInput: hasInput || openInvocation,
|
|
12498
12710
|
hasOutput,
|
|
12499
|
-
inputText: hasInput &&
|
|
12711
|
+
inputText: hasInput && state2 ? stringValue(state2.input) : "",
|
|
12500
12712
|
outputText: hasOutput ? stringValue(outputValue) : ""
|
|
12501
12713
|
};
|
|
12502
12714
|
}
|
|
@@ -12724,24 +12936,27 @@ function tokenForMessage(message, options) {
|
|
|
12724
12936
|
function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
12725
12937
|
const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
|
|
12726
12938
|
const sliceCount = ordered.length;
|
|
12727
|
-
const
|
|
12728
|
-
const
|
|
12939
|
+
const firstOrdinal = ordered.length > 0 ? ordered[0].ordinal : 1;
|
|
12940
|
+
const terminalOrdinal = ordered.length > 0 ? ordered[ordered.length - 1].ordinal : 0;
|
|
12941
|
+
const rawMessageCount = Math.max(sliceCount, terminalOrdinal, options.absoluteMessageCount ?? sliceCount);
|
|
12942
|
+
const ordinalSpan = terminalOrdinal >= firstOrdinal ? terminalOrdinal - firstOrdinal + 1 : 0;
|
|
12729
12943
|
const tokensByOrdinal = new Map;
|
|
12730
12944
|
const idsByOrdinal = new Map;
|
|
12731
|
-
const prefix = new Array(
|
|
12945
|
+
const prefix = new Array(ordinalSpan + 1).fill(0);
|
|
12732
12946
|
for (const message of ordered) {
|
|
12733
12947
|
const stored = options.storedTotalForMessage?.(message);
|
|
12734
12948
|
const total = stored !== undefined && stored !== null ? stored : tokenForMessage(message, options).total;
|
|
12735
12949
|
tokensByOrdinal.set(message.ordinal, total);
|
|
12736
12950
|
idsByOrdinal.set(message.ordinal, message.id);
|
|
12737
|
-
|
|
12738
|
-
|
|
12951
|
+
const relative = message.ordinal - firstOrdinal + 1;
|
|
12952
|
+
if (relative >= 1 && relative <= ordinalSpan) {
|
|
12953
|
+
prefix[relative] = total;
|
|
12739
12954
|
}
|
|
12740
12955
|
}
|
|
12741
|
-
for (let k = 1;k <=
|
|
12956
|
+
for (let k = 1;k <= ordinalSpan; k += 1) {
|
|
12742
12957
|
prefix[k] += prefix[k - 1];
|
|
12743
12958
|
}
|
|
12744
|
-
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(
|
|
12959
|
+
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
|
|
12745
12960
|
return {
|
|
12746
12961
|
sessionId,
|
|
12747
12962
|
providerShapeVersion: options.providerShapeVersion,
|
|
@@ -12753,27 +12968,27 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
12753
12968
|
return idsByOrdinal.get(ordinal) ?? null;
|
|
12754
12969
|
},
|
|
12755
12970
|
suffixTokensFromOrdinal(ordinal) {
|
|
12756
|
-
if (ordinal <=
|
|
12757
|
-
return prefix[
|
|
12758
|
-
if (ordinal >
|
|
12971
|
+
if (ordinal <= firstOrdinal)
|
|
12972
|
+
return prefix[ordinalSpan];
|
|
12973
|
+
if (ordinal > terminalOrdinal)
|
|
12759
12974
|
return 0;
|
|
12760
|
-
return prefix[
|
|
12975
|
+
return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
|
|
12761
12976
|
},
|
|
12762
12977
|
rangeTokens(startInclusive, endExclusive) {
|
|
12763
|
-
const start = Math.max(
|
|
12764
|
-
const end = Math.max(start, Math.min(
|
|
12765
|
-
return prefix[end -
|
|
12978
|
+
const start = Math.max(firstOrdinal, startInclusive);
|
|
12979
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
12980
|
+
return prefix[end - firstOrdinal] - prefix[start - firstOrdinal];
|
|
12766
12981
|
},
|
|
12767
12982
|
findSuffixStartForTokens(tokens) {
|
|
12768
12983
|
if (!Number.isFinite(tokens) || tokens <= 0)
|
|
12769
|
-
return
|
|
12984
|
+
return terminalOrdinal + 1;
|
|
12770
12985
|
const target = Math.max(0, Math.floor(tokens));
|
|
12771
|
-
const total = prefix[
|
|
12986
|
+
const total = prefix[ordinalSpan];
|
|
12772
12987
|
if (total < target)
|
|
12773
|
-
return
|
|
12988
|
+
return firstOrdinal;
|
|
12774
12989
|
const cut = total - target;
|
|
12775
12990
|
let lo = 0;
|
|
12776
|
-
let hi =
|
|
12991
|
+
let hi = ordinalSpan;
|
|
12777
12992
|
let best = 0;
|
|
12778
12993
|
while (lo <= hi) {
|
|
12779
12994
|
const mid = lo + hi >> 1;
|
|
@@ -12784,29 +12999,31 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
12784
12999
|
hi = mid - 1;
|
|
12785
13000
|
}
|
|
12786
13001
|
}
|
|
12787
|
-
return
|
|
13002
|
+
return firstOrdinal + best;
|
|
12788
13003
|
},
|
|
12789
13004
|
findHeadEndForCap(startInclusive, endExclusive, capTokens) {
|
|
12790
|
-
const start = Math.max(
|
|
12791
|
-
const end = Math.max(start, Math.min(
|
|
13005
|
+
const start = Math.max(firstOrdinal, Math.min(terminalOrdinal + 1, startInclusive));
|
|
13006
|
+
const end = Math.max(start, Math.min(terminalOrdinal + 1, endExclusive));
|
|
12792
13007
|
if (!Number.isFinite(capTokens) || capTokens <= 0)
|
|
12793
13008
|
return start;
|
|
12794
|
-
const
|
|
12795
|
-
const
|
|
12796
|
-
|
|
12797
|
-
let
|
|
12798
|
-
let
|
|
13009
|
+
const startIndex = start - firstOrdinal;
|
|
13010
|
+
const endIndex = end - firstOrdinal;
|
|
13011
|
+
const cut = prefix[startIndex] + Math.floor(capTokens);
|
|
13012
|
+
let lo = startIndex + 1;
|
|
13013
|
+
let hi = endIndex;
|
|
13014
|
+
let bestEndIndex = startIndex;
|
|
12799
13015
|
while (lo <= hi) {
|
|
12800
13016
|
const mid = lo + hi >> 1;
|
|
12801
13017
|
if (prefix[mid] <= cut) {
|
|
12802
|
-
|
|
13018
|
+
bestEndIndex = mid;
|
|
12803
13019
|
lo = mid + 1;
|
|
12804
13020
|
} else {
|
|
12805
13021
|
hi = mid - 1;
|
|
12806
13022
|
}
|
|
12807
13023
|
}
|
|
13024
|
+
let bestEnd = firstOrdinal + bestEndIndex;
|
|
12808
13025
|
if (bestEnd === start && start < end)
|
|
12809
|
-
|
|
13026
|
+
bestEnd = start + 1;
|
|
12810
13027
|
return Math.min(bestEnd, end);
|
|
12811
13028
|
}
|
|
12812
13029
|
};
|
|
@@ -13122,7 +13339,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
13122
13339
|
if (ctx.migrationFloorActive)
|
|
13123
13340
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
13124
13341
|
let protectedTailStart = Math.max(boundary, runtimeFloor);
|
|
13125
|
-
|
|
13342
|
+
const forceMaterializationPercentage = escalationBands(ctx.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13343
|
+
if (!ctx.emergencyTailScale && usagePercentage < forceMaterializationPercentage) {
|
|
13126
13344
|
let lastMeaningfulUserOrdinal = 0;
|
|
13127
13345
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
13128
13346
|
const message = messages[i];
|
|
@@ -13363,7 +13581,8 @@ function getRawHistoryEligibility(db, sessionId) {
|
|
|
13363
13581
|
function hasRunnableCompartmentWindow(snapshot) {
|
|
13364
13582
|
if (snapshot.offset >= snapshot.protectedTailStart)
|
|
13365
13583
|
return false;
|
|
13366
|
-
|
|
13584
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13585
|
+
if (snapshot.usagePercentage >= forceMaterializationPercentage || snapshot.emergencyTailScale) {
|
|
13367
13586
|
return snapshot.trueRawEligibleTokens >= deriveMinForceEligibleTokens(snapshot.N) || snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
13368
13587
|
}
|
|
13369
13588
|
return snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
@@ -13426,11 +13645,18 @@ function validateBoundarySnapshot(args) {
|
|
|
13426
13645
|
return { ok: true };
|
|
13427
13646
|
}
|
|
13428
13647
|
function recordHighPressureNoEligibleHead(db, snapshot) {
|
|
13429
|
-
|
|
13648
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13649
|
+
if (snapshot.usagePercentage < forceMaterializationPercentage && !snapshot.emergencyTailScale) {
|
|
13430
13650
|
return 0;
|
|
13651
|
+
}
|
|
13431
13652
|
return recordProtectedTailNoEligibleHead(db, snapshot.sessionId);
|
|
13432
13653
|
}
|
|
13433
13654
|
|
|
13655
|
+
// ../plugin/src/hooks/magic-context/sentinel.ts
|
|
13656
|
+
function modelAcceptsEmptyContent(providerID) {
|
|
13657
|
+
return providerID === "anthropic";
|
|
13658
|
+
}
|
|
13659
|
+
|
|
13434
13660
|
// ../plugin/src/hooks/magic-context/compartment-trigger.ts
|
|
13435
13661
|
var PROACTIVE_TRIGGER_OFFSET_PERCENTAGE = 2;
|
|
13436
13662
|
var POST_DROP_TARGET_RATIO = 0.75;
|
|
@@ -13438,7 +13664,6 @@ var MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE = 6000;
|
|
|
13438
13664
|
var MIN_PROACTIVE_TAIL_MESSAGE_COUNT = 12;
|
|
13439
13665
|
var DEFAULT_MIN_COMMIT_CLUSTERS_FOR_TRIGGER = 3;
|
|
13440
13666
|
var TAIL_SIZE_TRIGGER_MULTIPLIER = 3;
|
|
13441
|
-
var FORCE_COMPARTMENT_PERCENTAGE = 80;
|
|
13442
13667
|
var BLOCK_UNTIL_DONE_PERCENTAGE = 95;
|
|
13443
13668
|
var CONTENT_TAG_OWNER_SUFFIX = /:(?:p|file)\d+$/;
|
|
13444
13669
|
function tagOwnerMessageId(row) {
|
|
@@ -13475,7 +13700,7 @@ function estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, tag
|
|
|
13475
13700
|
function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage) {
|
|
13476
13701
|
return Math.max(0, executeThresholdPercentage - PROACTIVE_TRIGGER_OFFSET_PERCENTAGE);
|
|
13477
13702
|
}
|
|
13478
|
-
function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, clearReasoningAge, clearedReasoningThroughTag) {
|
|
13703
|
+
function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, clearReasoningAge, clearedReasoningThroughTag, canClearReasoning) {
|
|
13479
13704
|
const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
|
|
13480
13705
|
if (totalActiveBytes === 0)
|
|
13481
13706
|
return null;
|
|
@@ -13486,7 +13711,7 @@ function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, c
|
|
|
13486
13711
|
droppableBytes += activeTags.filter((tag) => pendingDropTagIds.has(tag.tagNumber)).reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
|
|
13487
13712
|
}
|
|
13488
13713
|
const maxTag = activeTags.reduce((max, t) => Math.max(max, t.tagNumber), 0);
|
|
13489
|
-
if (clearReasoningAge !== undefined && clearedReasoningThroughTag !== undefined) {
|
|
13714
|
+
if (canClearReasoning && clearReasoningAge !== undefined && clearedReasoningThroughTag !== undefined) {
|
|
13490
13715
|
const reasoningAgeCutoff = maxTag - clearReasoningAge;
|
|
13491
13716
|
for (const tag of activeTags) {
|
|
13492
13717
|
if (tag.type !== "message")
|
|
@@ -13586,7 +13811,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
|
|
|
13586
13811
|
}
|
|
13587
13812
|
});
|
|
13588
13813
|
}
|
|
13589
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride) {
|
|
13814
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection) {
|
|
13590
13815
|
if (sessionMeta.compartmentInProgress) {
|
|
13591
13816
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
13592
13817
|
return { shouldFire: false };
|
|
@@ -13640,18 +13865,20 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
13640
13865
|
}
|
|
13641
13866
|
return { shouldFire: false };
|
|
13642
13867
|
}
|
|
13643
|
-
const
|
|
13868
|
+
const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
|
|
13869
|
+
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), clearReasoningAge, sessionMeta.clearedReasoningThroughTag, canClearReasoning);
|
|
13644
13870
|
const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
|
|
13645
|
-
|
|
13871
|
+
const forceMaterializationPercentage = escalationBands(executeThresholdPercentage).forceMaterializationPercentage;
|
|
13872
|
+
if (usage.percentage >= forceMaterializationPercentage) {
|
|
13646
13873
|
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
13647
|
-
sessionLog(sessionId, `compartment trigger: skipping force
|
|
13874
|
+
sessionLog(sessionId, `compartment trigger: skipping force band ${forceMaterializationPercentage}% because projected post-drop usage is ${projectedPostDropPercentage.toFixed(1)}% (target ${relativePostDropTarget.toFixed(1)}%)`);
|
|
13648
13875
|
return { shouldFire: false };
|
|
13649
13876
|
}
|
|
13650
13877
|
sessionLog(sessionId, `compartment trigger: force-firing at ${usage.percentage.toFixed(1)}% (projected post-drop ${projectedPostDropPercentage?.toFixed(1) ?? "none"}%)`);
|
|
13651
13878
|
if (tailInfo.boundarySnapshot && hasRunnableCompartmentWindow(tailInfo.boundarySnapshot)) {
|
|
13652
13879
|
return {
|
|
13653
13880
|
shouldFire: true,
|
|
13654
|
-
reason: "
|
|
13881
|
+
reason: "force_band",
|
|
13655
13882
|
boundarySnapshot: tailInfo.boundarySnapshot
|
|
13656
13883
|
};
|
|
13657
13884
|
}
|
|
@@ -13676,9 +13903,9 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
13676
13903
|
});
|
|
13677
13904
|
});
|
|
13678
13905
|
if (hasRunnableCompartmentWindow(scaledBoundary)) {
|
|
13679
|
-
return { shouldFire: true, reason: "
|
|
13906
|
+
return { shouldFire: true, reason: "force_band", boundarySnapshot: scaledBoundary };
|
|
13680
13907
|
}
|
|
13681
|
-
sessionLog(sessionId, "compartment trigger:
|
|
13908
|
+
sessionLog(sessionId, "compartment trigger: force_band skipped — raw exists but protected head genuinely empty after emergency tail scale");
|
|
13682
13909
|
return { shouldFire: false };
|
|
13683
13910
|
}
|
|
13684
13911
|
const clusterEnabled = commitClusterTrigger?.enabled ?? true;
|
|
@@ -13843,11 +14070,6 @@ ${body}${hintText}
|
|
|
13843
14070
|
</system-reminder>`;
|
|
13844
14071
|
}
|
|
13845
14072
|
|
|
13846
|
-
// ../plugin/src/hooks/magic-context/sentinel.ts
|
|
13847
|
-
function modelAcceptsEmptyContent(providerID) {
|
|
13848
|
-
return providerID === "anthropic";
|
|
13849
|
-
}
|
|
13850
|
-
|
|
13851
14073
|
// ../plugin/src/hooks/magic-context/supersession-reclaim.ts
|
|
13852
14074
|
var TODOWRITE_KEEP = 1;
|
|
13853
14075
|
var CTX_REDUCE_KEEP = 5;
|
|
@@ -13977,7 +14199,7 @@ function advanceToolReclaimWatermarkToCurrentMax(db, sessionId) {
|
|
|
13977
14199
|
}
|
|
13978
14200
|
|
|
13979
14201
|
// ../plugin/src/shared/tag-transcript.ts
|
|
13980
|
-
import { createHash as
|
|
14202
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
13981
14203
|
|
|
13982
14204
|
// ../plugin/src/hooks/magic-context/image-token-estimate.ts
|
|
13983
14205
|
var IMAGE_TOKEN_DIVISOR = 750;
|
|
@@ -14132,7 +14354,7 @@ function readUint32BE(b, offset) {
|
|
|
14132
14354
|
// ../plugin/src/shared/tag-transcript.ts
|
|
14133
14355
|
var TEXT_TAG_IDENTITY_MARKER = ":mc-text-v1:";
|
|
14134
14356
|
function textIdentityDigest(value) {
|
|
14135
|
-
return
|
|
14357
|
+
return createHash7("sha256").update(value).digest("hex");
|
|
14136
14358
|
}
|
|
14137
14359
|
function buildContentDerivedTextIds(messageId, parts) {
|
|
14138
14360
|
const sources = parts.filter((part) => part.kind === "text").map((part) => stripTagPrefix(part.getText() ?? ""));
|
|
@@ -15162,16 +15384,16 @@ function sealDeliveredAfterUnconfirmedSend(db, sessionId) {
|
|
|
15162
15384
|
}
|
|
15163
15385
|
}
|
|
15164
15386
|
var channel1StateBySession = new Map;
|
|
15165
|
-
function setPiChannel1Baseline(sessionId,
|
|
15166
|
-
channel1StateBySession.set(sessionId,
|
|
15387
|
+
function setPiChannel1Baseline(sessionId, state2) {
|
|
15388
|
+
channel1StateBySession.set(sessionId, state2);
|
|
15167
15389
|
}
|
|
15168
15390
|
function clearPiChannel1State(sessionId) {
|
|
15169
15391
|
channel1StateBySession.delete(sessionId);
|
|
15170
15392
|
}
|
|
15171
15393
|
function markPiChannel1Reduced(sessionId, db) {
|
|
15172
|
-
const
|
|
15173
|
-
if (
|
|
15174
|
-
|
|
15394
|
+
const state2 = channel1StateBySession.get(sessionId);
|
|
15395
|
+
if (state2)
|
|
15396
|
+
state2.reducedSinceRefresh = true;
|
|
15175
15397
|
if (db)
|
|
15176
15398
|
resetLastNudgeCycle(db, sessionId);
|
|
15177
15399
|
}
|
|
@@ -15246,11 +15468,11 @@ function computeTailTokenEstimatePi(messages) {
|
|
|
15246
15468
|
}
|
|
15247
15469
|
function maybeChannel1ReminderForToolResult(args) {
|
|
15248
15470
|
const { db, sessionId, toolName } = args;
|
|
15249
|
-
const
|
|
15250
|
-
if (!
|
|
15471
|
+
const state2 = channel1StateBySession.get(sessionId);
|
|
15472
|
+
if (!state2)
|
|
15251
15473
|
return null;
|
|
15252
15474
|
if (toolName === "ctx_reduce") {
|
|
15253
|
-
|
|
15475
|
+
state2.reducedSinceRefresh = true;
|
|
15254
15476
|
resetLastNudgeCycle(db, sessionId);
|
|
15255
15477
|
return null;
|
|
15256
15478
|
}
|
|
@@ -15259,21 +15481,21 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
15259
15481
|
return null;
|
|
15260
15482
|
if (text.includes(CHANNEL1_SENTINEL))
|
|
15261
15483
|
return null;
|
|
15262
|
-
|
|
15263
|
-
if (
|
|
15484
|
+
state2.turnToolTokens += toolOutputTokens(text);
|
|
15485
|
+
if (state2.reducedSinceRefresh)
|
|
15264
15486
|
return null;
|
|
15265
|
-
const undroppedTokens =
|
|
15487
|
+
const undroppedTokens = state2.tailToolTokens + state2.turnToolTokens;
|
|
15266
15488
|
const pressure = computePressure({
|
|
15267
|
-
lastInputTokens:
|
|
15268
|
-
turnToolTokens:
|
|
15269
|
-
contextLimit:
|
|
15270
|
-
executeThresholdPercentage:
|
|
15489
|
+
lastInputTokens: state2.lastInputTokens,
|
|
15490
|
+
turnToolTokens: state2.turnToolTokens,
|
|
15491
|
+
contextLimit: state2.contextLimit,
|
|
15492
|
+
executeThresholdPercentage: state2.executeThresholdPercentage
|
|
15271
15493
|
});
|
|
15272
|
-
const workingWindowTokens = Math.round(
|
|
15494
|
+
const workingWindowTokens = Math.round(state2.contextLimit * state2.executeThresholdPercentage / 100);
|
|
15273
15495
|
const decision = decideChannel1({
|
|
15274
15496
|
undroppedTokens,
|
|
15275
15497
|
pressure,
|
|
15276
|
-
estimatedInputTokens:
|
|
15498
|
+
estimatedInputTokens: state2.lastInputTokens + state2.turnToolTokens,
|
|
15277
15499
|
workingWindowTokens,
|
|
15278
15500
|
lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
|
|
15279
15501
|
lastNudgeLevel: getLastNudgeLevel(db, sessionId),
|
|
@@ -15285,18 +15507,18 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
15285
15507
|
return null;
|
|
15286
15508
|
return {
|
|
15287
15509
|
type: "text",
|
|
15288
|
-
text: buildChannel1Reminder(decision.level, decision.undroppedTokens,
|
|
15510
|
+
text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
|
|
15289
15511
|
};
|
|
15290
15512
|
}
|
|
15291
15513
|
var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
|
|
15292
15514
|
function maybeDeliverChannel2Pi(pi, db, sessionId, deliverAs = "followUp") {
|
|
15293
|
-
let
|
|
15515
|
+
let state2;
|
|
15294
15516
|
try {
|
|
15295
|
-
|
|
15517
|
+
state2 = getChannel2NudgeState(db, sessionId);
|
|
15296
15518
|
} catch {
|
|
15297
15519
|
return false;
|
|
15298
15520
|
}
|
|
15299
|
-
if (
|
|
15521
|
+
if (state2 !== "pending")
|
|
15300
15522
|
return false;
|
|
15301
15523
|
const baseline = channel1StateBySession.get(sessionId);
|
|
15302
15524
|
if (!baseline)
|
|
@@ -15968,14 +16190,17 @@ var EMPTY_PI_PROJECT_DOCS = {
|
|
|
15968
16190
|
renderedBlock: "",
|
|
15969
16191
|
canonicalHash: ""
|
|
15970
16192
|
};
|
|
15971
|
-
function
|
|
15972
|
-
return
|
|
16193
|
+
function getRenderableCompartmentsPi(db, state2) {
|
|
16194
|
+
return state2.compactionOff ? [] : getCompartments(db, state2.sessionId);
|
|
16195
|
+
}
|
|
16196
|
+
function readProjectDocsForPiM0(state2) {
|
|
16197
|
+
return state2.injectDocs !== false ? readProjectDocsCanonical(state2.projectDirectory) : EMPTY_PI_PROJECT_DOCS;
|
|
15973
16198
|
}
|
|
15974
|
-
function memoryProjectPath(
|
|
15975
|
-
return
|
|
16199
|
+
function memoryProjectPath(state2) {
|
|
16200
|
+
return state2.memoryEnabled === false ? undefined : state2.projectIdentity;
|
|
15976
16201
|
}
|
|
15977
|
-
function resolveWorkspaceRenderContextPi(
|
|
15978
|
-
const memPath = memoryProjectPath(
|
|
16202
|
+
function resolveWorkspaceRenderContextPi(state2, db) {
|
|
16203
|
+
const memPath = memoryProjectPath(state2);
|
|
15979
16204
|
if (!memPath) {
|
|
15980
16205
|
return {
|
|
15981
16206
|
identities: [],
|
|
@@ -16051,12 +16276,12 @@ function piImageFromDataUrl(dataUrl) {
|
|
|
16051
16276
|
return null;
|
|
16052
16277
|
return { type: "image", mimeType: match[1], data: match[2] };
|
|
16053
16278
|
}
|
|
16054
|
-
function resolveMuralForM0Pi(
|
|
16055
|
-
if (
|
|
16056
|
-
return
|
|
16057
|
-
if (!
|
|
16279
|
+
function resolveMuralForM0Pi(state2, db, modelKey, budgetTokens) {
|
|
16280
|
+
if (state2.mural)
|
|
16281
|
+
return state2.mural;
|
|
16282
|
+
if (!state2.muralEnabled)
|
|
16058
16283
|
return;
|
|
16059
|
-
return resolveMuralWire(db, memoryProjectPath(
|
|
16284
|
+
return resolveMuralWire(db, memoryProjectPath(state2), modelKey, true, budgetTokens);
|
|
16060
16285
|
}
|
|
16061
16286
|
function cachedInjectionTokenCounts(sessionId, m0, m1) {
|
|
16062
16287
|
const cached = injectionTokenCountsBySession.get(sessionId);
|
|
@@ -16109,17 +16334,17 @@ function trimPiMessagesToCachedBoundary(db, sessionId, piMessages, entryIds) {
|
|
|
16109
16334
|
function setCachedBoundary(db, sessionId, boundary) {
|
|
16110
16335
|
db.prepare("UPDATE session_meta SET cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(boundary, sessionId);
|
|
16111
16336
|
}
|
|
16112
|
-
function getCachedMarkers(db,
|
|
16113
|
-
const meta = getOrCreateSessionMeta(db,
|
|
16337
|
+
function getCachedMarkers(db, state2, compartmentsForNormalization) {
|
|
16338
|
+
const meta = getOrCreateSessionMeta(db, state2.sessionId);
|
|
16114
16339
|
if (!meta.cachedM0Bytes)
|
|
16115
16340
|
return null;
|
|
16116
16341
|
if (meta.cachedM0MaxCompartmentSeq === null || meta.cachedM0MaxMemoryId === null || meta.cachedM0MaxMutationId === null || meta.cachedM0MaxMemoryMutationId === null || meta.cachedM0ProjectMemoryEpoch === null || meta.cachedM0ProjectUserProfileVersion === null || meta.cachedM0ProjectDocsHash === null || meta.cachedM0SessionFactsVersion === null || meta.cachedM0MaterializedAt === null || meta.cachedM0UpgradeState === null) {
|
|
16117
16342
|
return null;
|
|
16118
16343
|
}
|
|
16119
|
-
const compartments = compartmentsForNormalization ??
|
|
16344
|
+
const compartments = compartmentsForNormalization ?? getRenderableCompartmentsPi(db, state2);
|
|
16120
16345
|
const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(meta.cachedM0UpgradeState);
|
|
16121
16346
|
const maxCompartmentSeq = normalizeCachedMaxCompartmentSeq(meta.cachedM0MaxCompartmentSeq, compartments);
|
|
16122
|
-
const cachedBoundary = getCachedBoundary(db,
|
|
16347
|
+
const cachedBoundary = getCachedBoundary(db, state2.sessionId);
|
|
16123
16348
|
const liveBoundary = lastBaselineEndMessageId(compartments);
|
|
16124
16349
|
if (maxCompartmentSeq >= 0 && cachedBoundary === null && liveBoundary !== null) {
|
|
16125
16350
|
return null;
|
|
@@ -16147,38 +16372,38 @@ function lastBaselineEndMessageId(compartments) {
|
|
|
16147
16372
|
const last = compartments.at(-1);
|
|
16148
16373
|
return last?.endMessageId && last.endMessageId.length > 0 ? last.endMessageId : null;
|
|
16149
16374
|
}
|
|
16150
|
-
function readCurrentMarkers(db,
|
|
16151
|
-
return readCurrentMarkersFromCompartments(db,
|
|
16375
|
+
function readCurrentMarkers(db, state2, projectDocsHash) {
|
|
16376
|
+
return readCurrentMarkersFromCompartments(db, state2, getRenderableCompartmentsPi(db, state2), projectDocsHash);
|
|
16152
16377
|
}
|
|
16153
|
-
function readCurrentMarkersFromCompartments(db,
|
|
16154
|
-
const memPath = memoryProjectPath(
|
|
16155
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16378
|
+
function readCurrentMarkersFromCompartments(db, state2, compartments, projectDocsHash) {
|
|
16379
|
+
const memPath = memoryProjectPath(state2);
|
|
16380
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16156
16381
|
const maxMemoryId = memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0;
|
|
16157
16382
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
16158
16383
|
const globalState = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH);
|
|
16159
16384
|
return {
|
|
16160
16385
|
maxCompartmentSeq: compartments.length > 0 ? compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ) : EMPTY_MAX_COMPARTMENT_SEQ,
|
|
16161
16386
|
maxMemoryId,
|
|
16162
|
-
maxMutationId: getMaxM0MutationId(db,
|
|
16387
|
+
maxMutationId: getMaxM0MutationId(db, state2.sessionId) ?? 0,
|
|
16163
16388
|
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
16164
16389
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
16165
16390
|
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
16166
16391
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
16167
|
-
projectDocsHash: projectDocsHash ?? readProjectDocsForPiM0(
|
|
16168
|
-
sessionFactsVersion: getSessionFactsVersion(db,
|
|
16392
|
+
projectDocsHash: projectDocsHash ?? readProjectDocsForPiM0(state2).canonicalHash,
|
|
16393
|
+
sessionFactsVersion: getSessionFactsVersion(db, state2.sessionId),
|
|
16169
16394
|
materializedAt: Date.now(),
|
|
16170
16395
|
upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
|
|
16171
16396
|
compartmentRenderEpoch: COMPARTMENT_RENDER_EPOCH,
|
|
16172
16397
|
lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
|
|
16173
|
-
systemHash: (
|
|
16174
|
-
modelKey: (
|
|
16175
|
-
projectIdentity:
|
|
16398
|
+
systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
|
|
16399
|
+
modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
|
|
16400
|
+
projectIdentity: state2.projectIdentity
|
|
16176
16401
|
};
|
|
16177
16402
|
}
|
|
16178
|
-
function mustMaterializePi(
|
|
16179
|
-
const meta = getOrCreateSessionMeta(db,
|
|
16180
|
-
const currentCompartments = currentCompartmentsOverride ??
|
|
16181
|
-
const current = readCurrentMarkersFromCompartments(db,
|
|
16403
|
+
function mustMaterializePi(state2, db, currentCompartmentsOverride) {
|
|
16404
|
+
const meta = getOrCreateSessionMeta(db, state2.sessionId);
|
|
16405
|
+
const currentCompartments = currentCompartmentsOverride ?? getRenderableCompartmentsPi(db, state2);
|
|
16406
|
+
const current = readCurrentMarkersFromCompartments(db, state2, currentCompartments, meta.cachedM0ProjectDocsHash ?? undefined);
|
|
16182
16407
|
if (!meta.cachedM0Bytes)
|
|
16183
16408
|
return { value: true, reason: "first_render" };
|
|
16184
16409
|
if (!meta.cachedM1Bytes)
|
|
@@ -16186,21 +16411,21 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
|
|
|
16186
16411
|
if (!decodeCachedM0(meta.cachedM0Bytes)) {
|
|
16187
16412
|
return { value: true, reason: "cache_invalid" };
|
|
16188
16413
|
}
|
|
16189
|
-
const cached = getCachedMarkers(db,
|
|
16414
|
+
const cached = getCachedMarkers(db, state2, currentCompartments);
|
|
16190
16415
|
if (cached === null) {
|
|
16191
16416
|
return { value: true, reason: "cache_invalid" };
|
|
16192
16417
|
}
|
|
16193
16418
|
if (cached.compartmentRenderEpoch !== current.compartmentRenderEpoch) {
|
|
16194
16419
|
return { value: true, reason: "compartment_render_epoch" };
|
|
16195
16420
|
}
|
|
16196
|
-
const hard =
|
|
16421
|
+
const hard = state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
|
|
16197
16422
|
if (hard.modelKey !== "" && hard.modelKey !== (meta.cachedM0ModelKey ?? "")) {
|
|
16198
16423
|
return { value: true, reason: "model_change" };
|
|
16199
16424
|
}
|
|
16200
16425
|
if (hard.systemHash !== "" && hard.systemHash !== (meta.cachedM0SystemHash ?? "")) {
|
|
16201
16426
|
return { value: true, reason: "system_hash" };
|
|
16202
16427
|
}
|
|
16203
|
-
if (meta.cachedM0ProjectIdentity !== null && meta.cachedM0ProjectIdentity !==
|
|
16428
|
+
if (meta.cachedM0ProjectIdentity !== null && meta.cachedM0ProjectIdentity !== state2.projectIdentity) {
|
|
16204
16429
|
return { value: true, reason: "project_change" };
|
|
16205
16430
|
}
|
|
16206
16431
|
if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (meta.cachedM0MaterializedAt ?? 0)) {
|
|
@@ -16230,9 +16455,9 @@ ${memories.map((memory) => `- ${escapeXmlContent(memory.content)}`).join(`
|
|
|
16230
16455
|
`)}
|
|
16231
16456
|
</${wrapper}>`;
|
|
16232
16457
|
}
|
|
16233
|
-
function renderM0Pi(
|
|
16234
|
-
const memPath = memoryProjectPath(
|
|
16235
|
-
const workspace = workspaceOverride ?? resolveWorkspaceRenderContextPi(
|
|
16458
|
+
function renderM0Pi(state2, db, projectDocs = readProjectDocsForPiM0(state2).renderedBlock, decayPressureMultiplier = 1, memoriesOverride, compartmentsOverride, userProfileOverride, workspaceOverride, mural) {
|
|
16459
|
+
const memPath = memoryProjectPath(state2);
|
|
16460
|
+
const workspace = workspaceOverride ?? resolveWorkspaceRenderContextPi(state2, db);
|
|
16236
16461
|
const allMemories = memoriesOverride ?? (memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"]) : []);
|
|
16237
16462
|
const memoryRenderOptions = {
|
|
16238
16463
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
@@ -16241,23 +16466,25 @@ function renderM0Pi(state, db, projectDocs = readProjectDocsForPiM0(state).rende
|
|
|
16241
16466
|
workspace
|
|
16242
16467
|
})
|
|
16243
16468
|
};
|
|
16244
|
-
const memories = allMemories.length > 0 ? workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(
|
|
16469
|
+
const memories = allMemories.length > 0 ? workspace.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(state2.sessionId, allMemories, state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS, workspace, memoryRenderOptions).renderOrder : trimMemoriesToBudgetV2(state2.sessionId, allMemories, state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS).renderOrder : allMemories;
|
|
16245
16470
|
const memoryBlock = memories.length > 0 ? renderMemoryBlockV2(memories, "project-memory", memoryRenderOptions) : undefined;
|
|
16246
|
-
const baseHistoryBudget =
|
|
16471
|
+
const baseHistoryBudget = state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
16247
16472
|
const decayed = renderDecayedCompartments({
|
|
16248
|
-
compartments: compartmentsOverride ??
|
|
16473
|
+
compartments: compartmentsOverride ?? getRenderableCompartmentsPi(db, state2),
|
|
16249
16474
|
historyBudgetTokens: baseHistoryBudget / Math.max(1, decayPressureMultiplier)
|
|
16250
16475
|
});
|
|
16251
16476
|
const sections = [];
|
|
16252
16477
|
if (projectDocs.length > 0)
|
|
16253
16478
|
sections.push(projectDocs);
|
|
16254
|
-
const trimmedProfile = trimUserMemoriesToBudget(userProfileOverride ?? safeGetActiveUserMemoriesPi(db),
|
|
16479
|
+
const trimmedProfile = trimUserMemoriesToBudget(userProfileOverride ?? safeGetActiveUserMemoriesPi(db), state2.userProfileBudgetTokens ?? DEFAULT_USER_PROFILE_BUDGET_TOKENS);
|
|
16255
16480
|
const userProfile = renderUserProfileBlock(db, "user-profile", trimmedProfile);
|
|
16256
16481
|
if (userProfile.length > 0)
|
|
16257
16482
|
sections.push(userProfile);
|
|
16258
|
-
|
|
16483
|
+
if (!state2.compactionOff) {
|
|
16484
|
+
sections.push(decayed.length > 0 ? `<session-history>
|
|
16259
16485
|
${decayed}
|
|
16260
16486
|
</session-history>` : "<session-history></session-history>");
|
|
16487
|
+
}
|
|
16261
16488
|
if (memoryBlock)
|
|
16262
16489
|
sections.push(memoryBlock);
|
|
16263
16490
|
if (mural?.enabled && mural.supportsVision && mural.dataUrl) {
|
|
@@ -16269,18 +16496,18 @@ The project memory mural image follows.
|
|
|
16269
16496
|
|
|
16270
16497
|
`).trim();
|
|
16271
16498
|
}
|
|
16272
|
-
function renderedMemoryIdsForPi(
|
|
16499
|
+
function renderedMemoryIdsForPi(state2, memories, workspace, db) {
|
|
16273
16500
|
if (memories.length === 0)
|
|
16274
16501
|
return [];
|
|
16275
|
-
const resolvedWorkspace = workspace ?? (db ? resolveWorkspaceRenderContextPi(
|
|
16502
|
+
const resolvedWorkspace = workspace ?? (db ? resolveWorkspaceRenderContextPi(state2, db) : undefined);
|
|
16276
16503
|
const renderOptions = resolvedWorkspace ? {
|
|
16277
16504
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
16278
16505
|
memories,
|
|
16279
|
-
projectPath: memoryProjectPath(
|
|
16506
|
+
projectPath: memoryProjectPath(state2),
|
|
16280
16507
|
workspace: resolvedWorkspace
|
|
16281
16508
|
})
|
|
16282
16509
|
} : {};
|
|
16283
|
-
const trimmed = resolvedWorkspace?.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(
|
|
16510
|
+
const trimmed = resolvedWorkspace?.isWorkspaced ? trimWorkspaceMemoriesToBudgetV2(state2.sessionId, [...memories], state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS, resolvedWorkspace, renderOptions) : trimMemoriesToBudgetV2(state2.sessionId, [...memories], state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS);
|
|
16284
16511
|
return trimmed.renderOrder.map((memory) => memory.id);
|
|
16285
16512
|
}
|
|
16286
16513
|
function isTransientSqliteLockError(error) {
|
|
@@ -16303,11 +16530,11 @@ class PiMaterializeContentionError extends Error {
|
|
|
16303
16530
|
this.name = "PiMaterializeContentionError";
|
|
16304
16531
|
}
|
|
16305
16532
|
}
|
|
16306
|
-
function readFrozenM0InputsPi(
|
|
16307
|
-
const memPath = memoryProjectPath(
|
|
16533
|
+
function readFrozenM0InputsPi(state2, db, docs = readProjectDocsForPiM0(state2), memoryCutoff) {
|
|
16534
|
+
const memPath = memoryProjectPath(state2);
|
|
16308
16535
|
const read = db.transaction(() => {
|
|
16309
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16310
|
-
const compartments =
|
|
16536
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16537
|
+
const compartments = getRenderableCompartmentsPi(db, state2);
|
|
16311
16538
|
const memories = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], memoryCutoff, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"], memoryCutoff) : [];
|
|
16312
16539
|
const userProfile = safeGetActiveUserMemoriesPi(db);
|
|
16313
16540
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
@@ -16315,72 +16542,72 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsForPiM0(state), m
|
|
|
16315
16542
|
const markers = {
|
|
16316
16543
|
maxCompartmentSeq: compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ),
|
|
16317
16544
|
maxMemoryId: memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0,
|
|
16318
|
-
maxMutationId: getMaxM0MutationId(db,
|
|
16545
|
+
maxMutationId: getMaxM0MutationId(db, state2.sessionId) ?? 0,
|
|
16319
16546
|
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
16320
16547
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
16321
16548
|
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
16322
16549
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
16323
16550
|
projectDocsHash: docs.canonicalHash,
|
|
16324
|
-
sessionFactsVersion: getSessionFactsVersion(db,
|
|
16551
|
+
sessionFactsVersion: getSessionFactsVersion(db, state2.sessionId),
|
|
16325
16552
|
materializedAt: memoryCutoff ?? Date.now(),
|
|
16326
16553
|
upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
|
|
16327
16554
|
compartmentRenderEpoch: COMPARTMENT_RENDER_EPOCH,
|
|
16328
16555
|
lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
|
|
16329
|
-
systemHash: (
|
|
16330
|
-
modelKey: (
|
|
16331
|
-
projectIdentity:
|
|
16556
|
+
systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
|
|
16557
|
+
modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
|
|
16558
|
+
projectIdentity: state2.projectIdentity
|
|
16332
16559
|
};
|
|
16333
16560
|
return { docs, markers, compartments, memories, userProfile, workspace };
|
|
16334
16561
|
});
|
|
16335
16562
|
return read();
|
|
16336
16563
|
}
|
|
16337
|
-
function renderFreshM0PiNonPersisted(
|
|
16338
|
-
const docs = readProjectDocsForPiM0(
|
|
16339
|
-
const cachedMaterializedAt = getOrCreateSessionMeta(db,
|
|
16340
|
-
const frozen = readFrozenM0InputsPi(
|
|
16564
|
+
function renderFreshM0PiNonPersisted(state2, db) {
|
|
16565
|
+
const docs = readProjectDocsForPiM0(state2);
|
|
16566
|
+
const cachedMaterializedAt = getOrCreateSessionMeta(db, state2.sessionId).cachedM0MaterializedAt ?? 0;
|
|
16567
|
+
const frozen = readFrozenM0InputsPi(state2, db, docs, cachedMaterializedAt);
|
|
16341
16568
|
frozen.markers.materializedAt = cachedMaterializedAt;
|
|
16342
|
-
const historyBudget =
|
|
16343
|
-
const memoryBudget =
|
|
16344
|
-
const mural = resolveMuralForM0Pi(
|
|
16345
|
-
rememberPiMural(
|
|
16569
|
+
const historyBudget = state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
16570
|
+
const memoryBudget = state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
16571
|
+
const mural = resolveMuralForM0Pi(state2, db, frozen.markers.modelKey, memoryBudget);
|
|
16572
|
+
rememberPiMural(state2.sessionId, mural);
|
|
16346
16573
|
let dpm = 1;
|
|
16347
|
-
let m0 = renderM0Pi(
|
|
16574
|
+
let m0 = renderM0Pi(state2, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace, mural);
|
|
16348
16575
|
let attempts = 0;
|
|
16349
16576
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
16350
16577
|
dpm *= 1.15;
|
|
16351
|
-
m0 = renderM0Pi(
|
|
16578
|
+
m0 = renderM0Pi(state2, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace, mural);
|
|
16352
16579
|
attempts += 1;
|
|
16353
16580
|
}
|
|
16354
16581
|
return {
|
|
16355
16582
|
m0,
|
|
16356
16583
|
snapshotMarkers: frozen.markers,
|
|
16357
|
-
renderedMemoryIds: renderedMemoryIdsForPi(
|
|
16584
|
+
renderedMemoryIds: renderedMemoryIdsForPi(state2, frozen.memories, frozen.workspace, db)
|
|
16358
16585
|
};
|
|
16359
16586
|
}
|
|
16360
|
-
function materializeM0Pi(
|
|
16361
|
-
const docs = readProjectDocsForPiM0(
|
|
16587
|
+
function materializeM0Pi(state2, db) {
|
|
16588
|
+
const docs = readProjectDocsForPiM0(state2);
|
|
16362
16589
|
const foldMaterializedAt = Date.now();
|
|
16363
|
-
const frozen = readFrozenM0InputsPi(
|
|
16590
|
+
const frozen = readFrozenM0InputsPi(state2, db, docs, foldMaterializedAt);
|
|
16364
16591
|
const snapshotMarkers = frozen.markers;
|
|
16365
16592
|
const snapshotMemories = frozen.memories;
|
|
16366
16593
|
const snapshotCompartments = frozen.compartments;
|
|
16367
16594
|
const snapshotUserProfile = frozen.userProfile;
|
|
16368
|
-
const renderedMemoryIds = renderedMemoryIdsForPi(
|
|
16369
|
-
const memoryBudget =
|
|
16370
|
-
const mural = resolveMuralForM0Pi(
|
|
16595
|
+
const renderedMemoryIds = renderedMemoryIdsForPi(state2, snapshotMemories, frozen.workspace, db);
|
|
16596
|
+
const memoryBudget = state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
16597
|
+
const mural = resolveMuralForM0Pi(state2, db, snapshotMarkers.modelKey, memoryBudget);
|
|
16371
16598
|
const frozenMuralDataUrl = mural?.enabled && mural.supportsVision ? mural.dataUrl ?? null : null;
|
|
16372
16599
|
const frozenMuralHash = mural?.enabled && mural.supportsVision ? mural.contentHash ?? null : null;
|
|
16373
16600
|
let decayPressureMultiplier = 1;
|
|
16374
|
-
let m0 = renderM0Pi(
|
|
16375
|
-
const historyBudget =
|
|
16601
|
+
let m0 = renderM0Pi(state2, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile, frozen.workspace, mural);
|
|
16602
|
+
const historyBudget = state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
16376
16603
|
let attempts = 0;
|
|
16377
16604
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
16378
16605
|
decayPressureMultiplier *= 1.15;
|
|
16379
|
-
m0 = renderM0Pi(
|
|
16606
|
+
m0 = renderM0Pi(state2, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile, frozen.workspace, mural);
|
|
16380
16607
|
attempts += 1;
|
|
16381
16608
|
}
|
|
16382
16609
|
const m0Bytes = Buffer.from(m0, "utf8");
|
|
16383
|
-
const phase3ProjectDocsHash = readProjectDocsForPiM0(
|
|
16610
|
+
const phase3ProjectDocsHash = readProjectDocsForPiM0(state2).canonicalHash;
|
|
16384
16611
|
try {
|
|
16385
16612
|
db.exec("BEGIN IMMEDIATE");
|
|
16386
16613
|
} catch (error) {
|
|
@@ -16390,7 +16617,7 @@ function materializeM0Pi(state, db) {
|
|
|
16390
16617
|
throw error;
|
|
16391
16618
|
}
|
|
16392
16619
|
try {
|
|
16393
|
-
const current = readCurrentMarkers(db,
|
|
16620
|
+
const current = readCurrentMarkers(db, state2, phase3ProjectDocsHash);
|
|
16394
16621
|
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
16395
16622
|
const stale = memoryEpochStale || current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.projectIdentity !== snapshotMarkers.projectIdentity || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState;
|
|
16396
16623
|
if (stale) {
|
|
@@ -16398,9 +16625,9 @@ function materializeM0Pi(state, db) {
|
|
|
16398
16625
|
throw new PiMaterializeContentionError("snapshot changed before persist");
|
|
16399
16626
|
}
|
|
16400
16627
|
snapshotMarkers.materializedAt = foldMaterializedAt;
|
|
16401
|
-
const m1Render = renderM1PiWithMetadata(
|
|
16628
|
+
const m1Render = renderM1PiWithMetadata(state2, db, snapshotMarkers, renderedMemoryIds);
|
|
16402
16629
|
const m1Bytes = Buffer.from(m1Render.text, "utf8");
|
|
16403
|
-
persistCachedM0(db,
|
|
16630
|
+
persistCachedM0(db, state2.sessionId, {
|
|
16404
16631
|
m0Bytes,
|
|
16405
16632
|
muralDataUrl: frozenMuralDataUrl,
|
|
16406
16633
|
muralHash: frozenMuralHash,
|
|
@@ -16420,10 +16647,10 @@ function materializeM0Pi(state, db) {
|
|
|
16420
16647
|
modelKey: snapshotMarkers.modelKey,
|
|
16421
16648
|
projectIdentity: snapshotMarkers.projectIdentity
|
|
16422
16649
|
});
|
|
16423
|
-
db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds),
|
|
16424
|
-
setCachedBoundary(db,
|
|
16650
|
+
db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds), state2.sessionId);
|
|
16651
|
+
setCachedBoundary(db, state2.sessionId, snapshotMarkers.lastBaselineEndMessageId);
|
|
16425
16652
|
db.exec("COMMIT");
|
|
16426
|
-
rememberPiMuralPayload(
|
|
16653
|
+
rememberPiMuralPayload(state2.sessionId, frozenMuralDataUrl, frozenMuralHash);
|
|
16427
16654
|
return {
|
|
16428
16655
|
m0,
|
|
16429
16656
|
m1: m1Render.text,
|
|
@@ -16437,11 +16664,11 @@ function materializeM0Pi(state, db) {
|
|
|
16437
16664
|
throw error;
|
|
16438
16665
|
}
|
|
16439
16666
|
}
|
|
16440
|
-
function materializeM0PiWithRetry(
|
|
16667
|
+
function materializeM0PiWithRetry(state2, db, maxRetries = 3) {
|
|
16441
16668
|
let lastError = null;
|
|
16442
16669
|
for (let attempt = 0;attempt < maxRetries; attempt++) {
|
|
16443
16670
|
try {
|
|
16444
|
-
return materializeM0Pi(
|
|
16671
|
+
return materializeM0Pi(state2, db);
|
|
16445
16672
|
} catch (error) {
|
|
16446
16673
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16447
16674
|
throw error;
|
|
@@ -16483,10 +16710,10 @@ ${lines.join(`
|
|
|
16483
16710
|
count: mutations.length
|
|
16484
16711
|
};
|
|
16485
16712
|
}
|
|
16486
|
-
function renderM1PiWithMetadata(
|
|
16713
|
+
function renderM1PiWithMetadata(state2, db, markers, renderedMemoryIds, compartmentsOverride) {
|
|
16487
16714
|
const sections = [];
|
|
16488
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16489
|
-
const memPath = memoryProjectPath(
|
|
16715
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16716
|
+
const memPath = memoryProjectPath(state2);
|
|
16490
16717
|
const memoryUpdates = memPath ? renderMemoryUpdatesBlockPi({
|
|
16491
16718
|
db,
|
|
16492
16719
|
projectPath: memPath,
|
|
@@ -16496,7 +16723,7 @@ function renderM1PiWithMetadata(state, db, markers, renderedMemoryIds, compartme
|
|
|
16496
16723
|
}) : { block: undefined, count: 0 };
|
|
16497
16724
|
if (memoryUpdates.block)
|
|
16498
16725
|
sections.push(memoryUpdates.block);
|
|
16499
|
-
const newCompartments = (compartmentsOverride ??
|
|
16726
|
+
const newCompartments = (compartmentsOverride ?? getRenderableCompartmentsPi(db, state2)).filter((compartment) => compartment.sequence > markers.maxCompartmentSeq);
|
|
16500
16727
|
if (newCompartments.length > 0) {
|
|
16501
16728
|
const body = newCompartments.map((compartment) => renderCompartmentAtTier(compartment, 1)).join(`
|
|
16502
16729
|
|
|
@@ -16507,7 +16734,7 @@ ${body}
|
|
|
16507
16734
|
}
|
|
16508
16735
|
const newMemories = memPath ? workspace.isWorkspaced ? readNewMemoriesForM1Union(db, workspace.expandedIdentities, markers.maxMemoryId, markers.materializedAt, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"], markers.materializedAt).filter((memory) => memory.id > markers.maxMemoryId) : [];
|
|
16509
16736
|
if (newMemories.length > 0) {
|
|
16510
|
-
const memoryBudget =
|
|
16737
|
+
const memoryBudget = state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
16511
16738
|
const memoryRenderOptions = {
|
|
16512
16739
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
16513
16740
|
memories: newMemories,
|
|
@@ -16515,14 +16742,14 @@ ${body}
|
|
|
16515
16742
|
workspace
|
|
16516
16743
|
})
|
|
16517
16744
|
};
|
|
16518
|
-
const trimmedNewMemories = trimMemoriesToBudgetV2(
|
|
16745
|
+
const trimmedNewMemories = trimMemoriesToBudgetV2(state2.sessionId, newMemories, Math.max(1, Math.floor(memoryBudget * 0.25)), memoryRenderOptions).renderOrder;
|
|
16519
16746
|
const newMemoriesBlock = renderMemoryBlockV2(trimmedNewMemories, "new-memories", memoryRenderOptions);
|
|
16520
16747
|
if (newMemoriesBlock)
|
|
16521
16748
|
sections.push(newMemoriesBlock);
|
|
16522
16749
|
}
|
|
16523
16750
|
const currentUserProfileVersion = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH)?.projectUserProfileVersion ?? 0;
|
|
16524
16751
|
if (currentUserProfileVersion !== markers.projectUserProfileVersion) {
|
|
16525
|
-
const profileBudget =
|
|
16752
|
+
const profileBudget = state2.userProfileBudgetTokens ?? DEFAULT_USER_PROFILE_BUDGET_TOKENS;
|
|
16526
16753
|
const trimmedProfile = trimUserMemoriesToBudget(safeGetActiveUserMemoriesPi(db), Math.max(1, Math.floor(profileBudget * 0.25)));
|
|
16527
16754
|
const profileBlock = renderUserProfileBlock(db, "new-user-profile", trimmedProfile);
|
|
16528
16755
|
if (profileBlock)
|
|
@@ -16535,7 +16762,10 @@ ${body}
|
|
|
16535
16762
|
};
|
|
16536
16763
|
}
|
|
16537
16764
|
return {
|
|
16538
|
-
text: `<
|
|
16765
|
+
text: state2.compactionOff ? `<knowledge-updates>
|
|
16766
|
+
${sections.join(`
|
|
16767
|
+
`)}
|
|
16768
|
+
</knowledge-updates>` : `<session-history-since>
|
|
16539
16769
|
${sections.join(`
|
|
16540
16770
|
`)}
|
|
16541
16771
|
</session-history-since>`,
|
|
@@ -16631,8 +16861,8 @@ function cachedPiRowMatchesSnapshot(args) {
|
|
|
16631
16861
|
return false;
|
|
16632
16862
|
return bufferEqualsNullable(args.row.cached_m0_bytes, args.m0Bytes) && rowMarkers.projectMemoryEpoch === args.markers.projectMemoryEpoch && rowMarkers.projectUserProfileVersion === args.markers.projectUserProfileVersion && rowMarkers.maxCompartmentSeq === args.markers.maxCompartmentSeq && rowMarkers.maxMemoryId === args.markers.maxMemoryId && rowMarkers.maxMutationId === args.markers.maxMutationId && rowMarkers.maxMemoryMutationId === args.markers.maxMemoryMutationId && rowMarkers.materializedAt === args.markers.materializedAt && rowMarkers.sessionFactsVersion === args.markers.sessionFactsVersion && (rowMarkers.upgradeState ?? null) === (args.markers.upgradeState ?? null) && rowMarkers.compartmentRenderEpoch === args.markers.compartmentRenderEpoch && (rowMarkers.systemHash ?? "") === (args.markers.systemHash ?? "") && (rowMarkers.modelKey ?? "") === (args.markers.modelKey ?? "") && (rowMarkers.projectIdentity ?? null) === (args.markers.projectIdentity ?? null) && (rowMarkers.workspaceFingerprint ?? null) === (args.markers.workspaceFingerprint ?? null);
|
|
16633
16863
|
}
|
|
16634
|
-
function adoptCachedPiProjectIdentity(db,
|
|
16635
|
-
db.prepare("UPDATE session_meta SET cached_m0_project_identity = ? WHERE session_id = ? AND cached_m0_project_identity IS NULL").run(
|
|
16864
|
+
function adoptCachedPiProjectIdentity(db, state2) {
|
|
16865
|
+
db.prepare("UPDATE session_meta SET cached_m0_project_identity = ? WHERE session_id = ? AND cached_m0_project_identity IS NULL").run(state2.projectIdentity, state2.sessionId);
|
|
16636
16866
|
}
|
|
16637
16867
|
function decodeCachedM1(row, sessionId) {
|
|
16638
16868
|
if (!row.cached_m1_bytes) {
|
|
@@ -16653,12 +16883,12 @@ function applyCachedPiRow(args) {
|
|
|
16653
16883
|
markers
|
|
16654
16884
|
};
|
|
16655
16885
|
}
|
|
16656
|
-
function replayCachedM1Pi(db,
|
|
16657
|
-
const row = readCachedPiM0M1Row(db,
|
|
16886
|
+
function replayCachedM1Pi(db, state2, compartmentsForNormalization) {
|
|
16887
|
+
const row = readCachedPiM0M1Row(db, state2.sessionId);
|
|
16658
16888
|
if (!row) {
|
|
16659
|
-
throw new PiMaterializeContentionError(`missing cached m[0]/m[1] for ${
|
|
16889
|
+
throw new PiMaterializeContentionError(`missing cached m[0]/m[1] for ${state2.sessionId}`);
|
|
16660
16890
|
}
|
|
16661
|
-
return applyCachedPiRow({ row, state, compartmentsForNormalization });
|
|
16891
|
+
return applyCachedPiRow({ row, state: state2, compartmentsForNormalization });
|
|
16662
16892
|
}
|
|
16663
16893
|
function softRefreshCachedM1Pi(args) {
|
|
16664
16894
|
args.db.exec("BEGIN IMMEDIATE");
|
|
@@ -16675,7 +16905,7 @@ function softRefreshCachedM1Pi(args) {
|
|
|
16675
16905
|
if (!sibling) {
|
|
16676
16906
|
throw new PiMaterializeContentionError(`missing sibling cached m[0]/m[1] for ${args.state.sessionId}`);
|
|
16677
16907
|
}
|
|
16678
|
-
const siblingCompartments =
|
|
16908
|
+
const siblingCompartments = getRenderableCompartmentsPi(args.db, args.state);
|
|
16679
16909
|
return {
|
|
16680
16910
|
...applyCachedPiRow({
|
|
16681
16911
|
row: sibling,
|
|
@@ -16742,9 +16972,9 @@ function prependM0M1Messages(piMessages, m0, m1, mural) {
|
|
|
16742
16972
|
timestamp: baseTimestamp - 1
|
|
16743
16973
|
});
|
|
16744
16974
|
}
|
|
16745
|
-
function injectM0M1Pi(
|
|
16746
|
-
const currentCompartments =
|
|
16747
|
-
let decision = mustMaterializePi(
|
|
16975
|
+
function injectM0M1Pi(state2, db, piMessages, entryIds, recomputeM1ThisPass = false) {
|
|
16976
|
+
const currentCompartments = getRenderableCompartmentsPi(db, state2);
|
|
16977
|
+
let decision = mustMaterializePi(state2, db, currentCompartments);
|
|
16748
16978
|
let m0 = "";
|
|
16749
16979
|
let m1 = PI_M1_PLACEHOLDER;
|
|
16750
16980
|
let markers = null;
|
|
@@ -16755,7 +16985,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16755
16985
|
let freshFallbackRenderedMemoryIds = null;
|
|
16756
16986
|
if (decision.value) {
|
|
16757
16987
|
try {
|
|
16758
|
-
const result = materializeM0PiWithRetry(
|
|
16988
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16759
16989
|
m0 = result.m0;
|
|
16760
16990
|
m1 = result.m1;
|
|
16761
16991
|
markers = result.snapshotMarkers;
|
|
@@ -16765,30 +16995,30 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16765
16995
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16766
16996
|
throw error;
|
|
16767
16997
|
try {
|
|
16768
|
-
const cached = replayCachedM1Pi(db,
|
|
16998
|
+
const cached = replayCachedM1Pi(db, state2, currentCompartments);
|
|
16769
16999
|
contentionExhausted = true;
|
|
16770
17000
|
m0 = cached.m0;
|
|
16771
17001
|
m1 = cached.m1;
|
|
16772
17002
|
markers = cached.markers;
|
|
16773
|
-
sessionLog(
|
|
17003
|
+
sessionLog(state2.sessionId, "pi m[0] materialization contention exhausted; reusing cached m[0]/m[1]");
|
|
16774
17004
|
} catch {
|
|
16775
|
-
const fresh = renderFreshM0PiNonPersisted(
|
|
17005
|
+
const fresh = renderFreshM0PiNonPersisted(state2, db);
|
|
16776
17006
|
m0 = fresh.m0;
|
|
16777
17007
|
markers = fresh.snapshotMarkers;
|
|
16778
17008
|
freshFallbackRenderedMemoryIds = fresh.renderedMemoryIds;
|
|
16779
17009
|
contentionExhausted = true;
|
|
16780
|
-
sessionLog(
|
|
17010
|
+
sessionLog(state2.sessionId, "pi m[0] materialization contention exhausted with no cached fallback; rendered fresh non-persisted m[0]/m[1]");
|
|
16781
17011
|
}
|
|
16782
17012
|
}
|
|
16783
17013
|
} else {
|
|
16784
|
-
const meta = getOrCreateSessionMeta(db,
|
|
17014
|
+
const meta = getOrCreateSessionMeta(db, state2.sessionId);
|
|
16785
17015
|
m0 = decodeCachedM0(meta.cachedM0Bytes) ?? "";
|
|
16786
|
-
rememberPiMuralPayload(
|
|
16787
|
-
markers = getCachedMarkers(db,
|
|
17016
|
+
rememberPiMuralPayload(state2.sessionId, meta.cachedM0MuralDataUrl, meta.cachedM0MuralHash);
|
|
17017
|
+
markers = getCachedMarkers(db, state2, currentCompartments);
|
|
16788
17018
|
if (!m0 || !markers) {
|
|
16789
17019
|
decision = { value: true, reason: "cache_invalid" };
|
|
16790
17020
|
try {
|
|
16791
|
-
const result = materializeM0PiWithRetry(
|
|
17021
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16792
17022
|
m0 = result.m0;
|
|
16793
17023
|
m1 = result.m1;
|
|
16794
17024
|
markers = result.snapshotMarkers;
|
|
@@ -16797,30 +17027,30 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16797
17027
|
} catch (error) {
|
|
16798
17028
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16799
17029
|
throw error;
|
|
16800
|
-
const fresh = renderFreshM0PiNonPersisted(
|
|
17030
|
+
const fresh = renderFreshM0PiNonPersisted(state2, db);
|
|
16801
17031
|
m0 = fresh.m0;
|
|
16802
17032
|
markers = fresh.snapshotMarkers;
|
|
16803
17033
|
freshFallbackRenderedMemoryIds = fresh.renderedMemoryIds;
|
|
16804
17034
|
contentionExhausted = true;
|
|
16805
|
-
sessionLog(
|
|
17035
|
+
sessionLog(state2.sessionId, "pi m[0] cache_invalid materialization contention exhausted; rendered fresh non-persisted m[0]/m[1]");
|
|
16806
17036
|
}
|
|
16807
17037
|
}
|
|
16808
17038
|
}
|
|
16809
17039
|
if (!markers) {
|
|
16810
|
-
throw new PiMaterializeContentionError(`missing m[0] markers for ${
|
|
17040
|
+
throw new PiMaterializeContentionError(`missing m[0] markers for ${state2.sessionId}`);
|
|
16811
17041
|
}
|
|
16812
17042
|
if (!materialized && markers.projectIdentity === null) {
|
|
16813
|
-
adoptCachedPiProjectIdentity(db,
|
|
16814
|
-
markers = { ...markers, projectIdentity:
|
|
17043
|
+
adoptCachedPiProjectIdentity(db, state2);
|
|
17044
|
+
markers = { ...markers, projectIdentity: state2.projectIdentity };
|
|
16815
17045
|
}
|
|
16816
17046
|
if (materialized) {} else if (contentionExhausted && freshFallbackRenderedMemoryIds) {
|
|
16817
|
-
const freshM1 = renderM1PiWithMetadata(
|
|
17047
|
+
const freshM1 = renderM1PiWithMetadata(state2, db, markers, freshFallbackRenderedMemoryIds);
|
|
16818
17048
|
m1 = freshM1.text;
|
|
16819
17049
|
memoryUpdateCount = freshM1.memoryUpdateCount;
|
|
16820
17050
|
m1Recomputed = true;
|
|
16821
17051
|
} else if (contentionExhausted) {} else if (recomputeM1ThisPass) {
|
|
16822
17052
|
const refreshed = softRefreshCachedM1Pi({
|
|
16823
|
-
state,
|
|
17053
|
+
state: state2,
|
|
16824
17054
|
db,
|
|
16825
17055
|
m0Bytes: Buffer.from(m0, "utf8"),
|
|
16826
17056
|
markers,
|
|
@@ -16832,7 +17062,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16832
17062
|
memoryUpdateCount = refreshed.memoryUpdateCount;
|
|
16833
17063
|
m1Recomputed = refreshed.recomputed;
|
|
16834
17064
|
} else {
|
|
16835
|
-
const replayed = replayCachedM1Pi(db,
|
|
17065
|
+
const replayed = replayCachedM1Pi(db, state2, currentCompartments);
|
|
16836
17066
|
m0 = replayed.m0;
|
|
16837
17067
|
m1 = replayed.m1;
|
|
16838
17068
|
markers = replayed.markers;
|
|
@@ -16840,14 +17070,14 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16840
17070
|
const M0_DRIFT_RATIO_FLOOR_TOKENS = 500;
|
|
16841
17071
|
const M1_DRIFT_RATIO = 0.15;
|
|
16842
17072
|
const M1_ABSOLUTE_CAP_RATIO = 0.2;
|
|
16843
|
-
const m1AbsoluteBudget = (
|
|
17073
|
+
const m1AbsoluteBudget = (state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
|
|
16844
17074
|
const m1HasContent = m1 !== PI_M1_PLACEHOLDER;
|
|
16845
|
-
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(
|
|
17075
|
+
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(state2.sessionId, m0, m1);
|
|
16846
17076
|
const m1OverAbsoluteCap = m1HasContent && m1Tokens > m1AbsoluteBudget;
|
|
16847
17077
|
if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1HasContent && m0Tokens >= M0_DRIFT_RATIO_FLOOR_TOKENS && m1Tokens > m0Tokens * M1_DRIFT_RATIO)) {
|
|
16848
17078
|
decision = { value: true, reason: "drift" };
|
|
16849
17079
|
try {
|
|
16850
|
-
const result = materializeM0PiWithRetry(
|
|
17080
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16851
17081
|
m0 = result.m0;
|
|
16852
17082
|
m1 = result.m1;
|
|
16853
17083
|
markers = result.snapshotMarkers;
|
|
@@ -16870,17 +17100,17 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16870
17100
|
}
|
|
16871
17101
|
}
|
|
16872
17102
|
const skippedVisibleMessages = boundaryId ? trimPiMessagesToBoundary(piMessages, entryIds, boundaryId) : 0;
|
|
16873
|
-
const muralWire = m0.includes("<memory-mural>") ? muralForWire(
|
|
17103
|
+
const muralWire = m0.includes("<memory-mural>") ? muralForWire(state2.sessionId) : undefined;
|
|
16874
17104
|
if (!muralWire)
|
|
16875
17105
|
m0 = stripMemoryMuralBlock(m0);
|
|
16876
17106
|
prependM0M1Messages(piMessages, m0, m1, muralWire);
|
|
16877
|
-
sessionLog(
|
|
16878
|
-
const memPath = memoryProjectPath(
|
|
16879
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
17107
|
+
sessionLog(state2.sessionId, `injected m[0]/m[1] into Pi messages (${m0.length} + ${m1.length} bytes, materialized=${materialized}${decision.reason ? ` reason=${decision.reason}` : ""})`);
|
|
17108
|
+
const memPath = memoryProjectPath(state2);
|
|
17109
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16880
17110
|
const memoryCount = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories).length : getMemoriesByProject(db, memPath, ["active", "permanent"]).length : 0;
|
|
16881
17111
|
return {
|
|
16882
17112
|
injected: true,
|
|
16883
|
-
compartmentCount:
|
|
17113
|
+
compartmentCount: currentCompartments.length,
|
|
16884
17114
|
factCount: 0,
|
|
16885
17115
|
memoryCount,
|
|
16886
17116
|
skippedVisibleMessages,
|
|
@@ -16942,6 +17172,16 @@ function isSentinelPart(part) {
|
|
|
16942
17172
|
return p.type === "text" && typeof p.text === "string" && (p.text === "" || p.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT);
|
|
16943
17173
|
}
|
|
16944
17174
|
|
|
17175
|
+
// src/pi-context-limit.ts
|
|
17176
|
+
function resolvePiUsableContextLimit(args) {
|
|
17177
|
+
const rawContext = isSaneLimit(args.rawContextWindow) ? args.rawContextWindow : undefined;
|
|
17178
|
+
const detected = typeof args.detectedContextLimit === "number" && Number.isFinite(args.detectedContextLimit) && args.detectedContextLimit >= 1024 ? args.detectedContextLimit : undefined;
|
|
17179
|
+
const context = rawContext !== undefined && detected !== undefined ? Math.min(rawContext, detected) : rawContext ?? detected;
|
|
17180
|
+
if (context === undefined)
|
|
17181
|
+
return;
|
|
17182
|
+
return resolveLimit({ context, output: args.model?.maxTokens }, args.model?.provider ?? "unknown", args.model?.id ?? "unknown");
|
|
17183
|
+
}
|
|
17184
|
+
|
|
16945
17185
|
// src/pi-historian-runner.ts
|
|
16946
17186
|
import * as crypto2 from "node:crypto";
|
|
16947
17187
|
|
|
@@ -17745,6 +17985,8 @@ If no candidates, omit the \`<primer_candidates>\` section entirely.
|
|
|
17745
17985
|
|
|
17746
17986
|
Output valid XML only in this shape:
|
|
17747
17987
|
|
|
17988
|
+
Closing tags must match their opening tier tag (e.g. \`<p1>...</p1>\`, never \`<p1>...</p2>\`).
|
|
17989
|
+
|
|
17748
17990
|
\`\`\`xml
|
|
17749
17991
|
<output>
|
|
17750
17992
|
<compartments>
|
|
@@ -17961,161 +18203,6 @@ function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex)
|
|
|
17961
18203
|
sessionLog(sessionId, `compartment agent: queued ${dropsQueued} drops for messages 0-${upToMessageIndex}`);
|
|
17962
18204
|
}
|
|
17963
18205
|
|
|
17964
|
-
// ../plugin/src/hooks/magic-context/compartment-parser.ts
|
|
17965
|
-
var COMPARTMENT_REGEX = /<compartment\s+([^>]*?)\s*>(.*?)<\/compartment>/gs;
|
|
17966
|
-
var ATTR_START_REGEX = /\bstart="(\d+)"/;
|
|
17967
|
-
var ATTR_END_REGEX = /\bend="(\d+)"/;
|
|
17968
|
-
var ATTR_TITLE_REGEX = /\btitle="([^"]*)"/;
|
|
17969
|
-
var ATTR_EPISODE_REGEX = /\bepisode_type="([^"]*)"/;
|
|
17970
|
-
var ATTR_IMPORTANCE_REGEX = /\bimportance="(\d+)"/;
|
|
17971
|
-
function makeTierRegex(n) {
|
|
17972
|
-
return new RegExp(`<p${n}\\s*/>|<p${n}\\s*>(.*?)</p${n}>`, "s");
|
|
17973
|
-
}
|
|
17974
|
-
var TIER_REGEXES = [makeTierRegex(1), makeTierRegex(2), makeTierRegex(3), makeTierRegex(4)];
|
|
17975
|
-
var CATEGORY_BLOCK_REGEX = /<(PROJECT_RULES|ARCHITECTURE|CONSTRAINTS|CONFIG_VALUES|NAMING)>(.*?)<\/\1>/gs;
|
|
17976
|
-
var FACT_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
|
|
17977
|
-
var UNPROCESSED_REGEX = /<unprocessed_from>(\d+)<\/unprocessed_from>/;
|
|
17978
|
-
var USER_OBSERVATIONS_REGEX = /<user_observations>(.*?)<\/user_observations>/s;
|
|
17979
|
-
var USER_OBS_ITEM_REGEX = /^\s*\*\s*(.+)$/gm;
|
|
17980
|
-
var PRIMER_CANDIDATES_REGEX = /<primer_candidates>(.*?)<\/primer_candidates>/s;
|
|
17981
|
-
var PRIMER_ELEMENT_REGEX = /<primer\s+at_compartment="(\d+)"\s*>(.*?)<\/primer>/gs;
|
|
17982
|
-
var PRIMER_ITEM_REGEX = /^\s*(?:\*|-|\d+\.)\s*(.+)$/gm;
|
|
17983
|
-
var FACTS_BLOCK_REGEX = /<facts>(.*?)<\/facts>/s;
|
|
17984
|
-
var EVENTS_BLOCK_REGEX = /<events>(.*?)<\/events>/s;
|
|
17985
|
-
var EVENT_ELEMENT_REGEX = /<([a-z_]+)\s+at_compartment="(\d+)"\s*>(.*?)<\/\1>/gs;
|
|
17986
|
-
var EVENT_FIELD_REGEX = /<([a-z_]+)\s*>(.*?)<\/\1>/gs;
|
|
17987
|
-
function extractTier(inner, index) {
|
|
17988
|
-
const m = inner.match(TIER_REGEXES[index]);
|
|
17989
|
-
if (!m)
|
|
17990
|
-
return;
|
|
17991
|
-
return unescapeXml3((m[1] ?? "").trim());
|
|
17992
|
-
}
|
|
17993
|
-
function parseCompartmentOutput(text) {
|
|
17994
|
-
const compartments = [];
|
|
17995
|
-
const facts = [];
|
|
17996
|
-
for (const match of text.matchAll(COMPARTMENT_REGEX)) {
|
|
17997
|
-
const attrs = match[1];
|
|
17998
|
-
const inner = match[2];
|
|
17999
|
-
const startMatch = attrs.match(ATTR_START_REGEX);
|
|
18000
|
-
const endMatch = attrs.match(ATTR_END_REGEX);
|
|
18001
|
-
const titleMatch = attrs.match(ATTR_TITLE_REGEX);
|
|
18002
|
-
if (!startMatch || !endMatch || !titleMatch)
|
|
18003
|
-
continue;
|
|
18004
|
-
const startMessage = parseInt(startMatch[1], 10);
|
|
18005
|
-
const endMessage = parseInt(endMatch[1], 10);
|
|
18006
|
-
const title = unescapeXml3(titleMatch[1]);
|
|
18007
|
-
if (Number.isNaN(startMessage) || Number.isNaN(endMessage) || !title)
|
|
18008
|
-
continue;
|
|
18009
|
-
const episodeMatch = attrs.match(ATTR_EPISODE_REGEX);
|
|
18010
|
-
const importanceMatch = attrs.match(ATTR_IMPORTANCE_REGEX);
|
|
18011
|
-
const episodeType = episodeMatch ? unescapeXml3(episodeMatch[1]) : undefined;
|
|
18012
|
-
const importance = importanceMatch ? parseInt(importanceMatch[1], 10) : undefined;
|
|
18013
|
-
const p1 = extractTier(inner, 0);
|
|
18014
|
-
if (typeof p1 === "string" && p1.length > 0) {
|
|
18015
|
-
const p2 = extractTier(inner, 1);
|
|
18016
|
-
const p3 = extractTier(inner, 2);
|
|
18017
|
-
const p4 = extractTier(inner, 3);
|
|
18018
|
-
compartments.push({
|
|
18019
|
-
startMessage,
|
|
18020
|
-
endMessage,
|
|
18021
|
-
title,
|
|
18022
|
-
content: p1,
|
|
18023
|
-
p1,
|
|
18024
|
-
p2: typeof p2 === "string" ? p2 : p1,
|
|
18025
|
-
p3: typeof p3 === "string" ? p3 : typeof p2 === "string" ? p2 : p1,
|
|
18026
|
-
p4: typeof p4 === "string" ? p4 : "",
|
|
18027
|
-
importance,
|
|
18028
|
-
episodeType
|
|
18029
|
-
});
|
|
18030
|
-
continue;
|
|
18031
|
-
}
|
|
18032
|
-
const content = unescapeXml3(inner.trim());
|
|
18033
|
-
if (content) {
|
|
18034
|
-
compartments.push({
|
|
18035
|
-
startMessage,
|
|
18036
|
-
endMessage,
|
|
18037
|
-
title,
|
|
18038
|
-
content,
|
|
18039
|
-
importance,
|
|
18040
|
-
episodeType
|
|
18041
|
-
});
|
|
18042
|
-
}
|
|
18043
|
-
}
|
|
18044
|
-
const factsBlockMatch = text.match(FACTS_BLOCK_REGEX);
|
|
18045
|
-
const factsScope = factsBlockMatch ? factsBlockMatch[1] : text.replace(EVENTS_BLOCK_REGEX, "").replace(/<compartment\s+[^>]*?\s*>.*?<\/compartment>/gs, "");
|
|
18046
|
-
for (const categoryMatch of factsScope.matchAll(CATEGORY_BLOCK_REGEX)) {
|
|
18047
|
-
const category = categoryMatch[1];
|
|
18048
|
-
const blockContent = categoryMatch[2];
|
|
18049
|
-
for (const itemMatch of blockContent.matchAll(FACT_ITEM_REGEX)) {
|
|
18050
|
-
const content = unescapeXml3(itemMatch[1].trim());
|
|
18051
|
-
if (content) {
|
|
18052
|
-
facts.push({ category, content });
|
|
18053
|
-
}
|
|
18054
|
-
}
|
|
18055
|
-
}
|
|
18056
|
-
const unprocessedMatch = text.match(UNPROCESSED_REGEX);
|
|
18057
|
-
const unprocessedFrom = unprocessedMatch ? parseInt(unprocessedMatch[1], 10) : null;
|
|
18058
|
-
const userObservations = [];
|
|
18059
|
-
const userObsMatch = text.match(USER_OBSERVATIONS_REGEX);
|
|
18060
|
-
if (userObsMatch) {
|
|
18061
|
-
for (const itemMatch of userObsMatch[1].matchAll(USER_OBS_ITEM_REGEX)) {
|
|
18062
|
-
const obs = unescapeXml3(itemMatch[1].trim());
|
|
18063
|
-
if (obs)
|
|
18064
|
-
userObservations.push(obs);
|
|
18065
|
-
}
|
|
18066
|
-
}
|
|
18067
|
-
const primerCandidates = [];
|
|
18068
|
-
const primerMatch = text.match(PRIMER_CANDIDATES_REGEX);
|
|
18069
|
-
if (primerMatch) {
|
|
18070
|
-
const block = primerMatch[1];
|
|
18071
|
-
let sawElement = false;
|
|
18072
|
-
for (const el of block.matchAll(PRIMER_ELEMENT_REGEX)) {
|
|
18073
|
-
sawElement = true;
|
|
18074
|
-
const question = unescapeXml3(el[2].trim());
|
|
18075
|
-
if (question) {
|
|
18076
|
-
primerCandidates.push({
|
|
18077
|
-
question,
|
|
18078
|
-
originCompartmentIndex: Number.parseInt(el[1], 10)
|
|
18079
|
-
});
|
|
18080
|
-
}
|
|
18081
|
-
}
|
|
18082
|
-
if (!sawElement) {
|
|
18083
|
-
for (const itemMatch of block.matchAll(PRIMER_ITEM_REGEX)) {
|
|
18084
|
-
const question = unescapeXml3(itemMatch[1].trim());
|
|
18085
|
-
if (question)
|
|
18086
|
-
primerCandidates.push({ question });
|
|
18087
|
-
}
|
|
18088
|
-
}
|
|
18089
|
-
}
|
|
18090
|
-
const events = parseEvents(text);
|
|
18091
|
-
compartments.sort((a, b) => a.startMessage - b.startMessage);
|
|
18092
|
-
return { compartments, facts, events, unprocessedFrom, userObservations, primerCandidates };
|
|
18093
|
-
}
|
|
18094
|
-
function parseEvents(text) {
|
|
18095
|
-
const blockMatch = text.match(EVENTS_BLOCK_REGEX);
|
|
18096
|
-
if (!blockMatch)
|
|
18097
|
-
return [];
|
|
18098
|
-
const block = blockMatch[1];
|
|
18099
|
-
const events = [];
|
|
18100
|
-
for (const elMatch of block.matchAll(EVENT_ELEMENT_REGEX)) {
|
|
18101
|
-
const kind = elMatch[1];
|
|
18102
|
-
const atRaw = parseInt(elMatch[2], 10);
|
|
18103
|
-
const atCompartment = Number.isNaN(atRaw) ? null : atRaw;
|
|
18104
|
-
const fields = {};
|
|
18105
|
-
for (const fieldMatch of elMatch[3].matchAll(EVENT_FIELD_REGEX)) {
|
|
18106
|
-
const name = fieldMatch[1];
|
|
18107
|
-
const value = unescapeXml3(fieldMatch[2].trim());
|
|
18108
|
-
if (value)
|
|
18109
|
-
fields[name] = value;
|
|
18110
|
-
}
|
|
18111
|
-
events.push({ kind, atCompartment, fields });
|
|
18112
|
-
}
|
|
18113
|
-
return events;
|
|
18114
|
-
}
|
|
18115
|
-
function unescapeXml3(s) {
|
|
18116
|
-
return s.replace(/&/g, "&").replace(/'/g, "'").replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">");
|
|
18117
|
-
}
|
|
18118
|
-
|
|
18119
18206
|
// ../plugin/src/hooks/magic-context/compartment-runner-mapping.ts
|
|
18120
18207
|
function tierFieldsOf(c) {
|
|
18121
18208
|
return {
|
|
@@ -20285,6 +20372,7 @@ async function runPiHistorian(deps) {
|
|
|
20285
20372
|
twoPass,
|
|
20286
20373
|
thinkingLevel,
|
|
20287
20374
|
memoryEnabled,
|
|
20375
|
+
allowHomeProject,
|
|
20288
20376
|
autoPromote,
|
|
20289
20377
|
userMemoriesEnabled,
|
|
20290
20378
|
onPublished,
|
|
@@ -20423,7 +20511,7 @@ async function runPiHistorian(deps) {
|
|
|
20423
20511
|
rollbackDrainReservation();
|
|
20424
20512
|
return;
|
|
20425
20513
|
}
|
|
20426
|
-
const projectPath = resolveProjectIdentityForSession(directory);
|
|
20514
|
+
const projectPath = resolveProjectIdentityForSession(directory, allowHomeProject);
|
|
20427
20515
|
if (!projectPath) {
|
|
20428
20516
|
rollbackDrainReservation();
|
|
20429
20517
|
return;
|
|
@@ -21427,7 +21515,7 @@ function stripPiProcessedImages(args) {
|
|
|
21427
21515
|
}
|
|
21428
21516
|
|
|
21429
21517
|
// src/system-prompt.ts
|
|
21430
|
-
import { createHash as
|
|
21518
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
21431
21519
|
|
|
21432
21520
|
// ../plugin/src/agents/magic-context-prompt.ts
|
|
21433
21521
|
var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
|
|
@@ -21580,7 +21668,7 @@ function processSystemPromptForCache(args) {
|
|
|
21580
21668
|
sessionLog(sessionId, `system prompt date frozen: real=${liveDate}, using=${stickyDate} (cache-stable pass)`);
|
|
21581
21669
|
}
|
|
21582
21670
|
}
|
|
21583
|
-
const currentHash =
|
|
21671
|
+
const currentHash = createHash8("md5").update(frozenPrompt).digest("hex");
|
|
21584
21672
|
const hashChanged = !isFirstHash && currentHash !== previousHash;
|
|
21585
21673
|
if (hashChanged) {
|
|
21586
21674
|
sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${frozenPrompt.length})`);
|
|
@@ -22378,7 +22466,6 @@ function extractStableId(msg, index, entryIds) {
|
|
|
22378
22466
|
}
|
|
22379
22467
|
|
|
22380
22468
|
// src/context-handler.ts
|
|
22381
|
-
var FORCE_MATERIALIZATION_PERCENTAGE = 85;
|
|
22382
22469
|
var EMERGENCY_BLOCK_PERCENTAGE = 95;
|
|
22383
22470
|
var FORWARD_PRESSURE_LIMIT_FACTOR = 0.85;
|
|
22384
22471
|
function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUsageTokens, correctedLimit) {
|
|
@@ -23000,8 +23087,8 @@ function parsePiFallbackToolOwnerId(ownerMsgId) {
|
|
|
23000
23087
|
return { timestamp, role: match[2] ?? "" };
|
|
23001
23088
|
}
|
|
23002
23089
|
function databaseIsInTransaction(db) {
|
|
23003
|
-
const
|
|
23004
|
-
return
|
|
23090
|
+
const state2 = db;
|
|
23091
|
+
return state2.inTransaction === true || state2.isTransaction === true;
|
|
23005
23092
|
}
|
|
23006
23093
|
function runImmediateTransaction(db, fn) {
|
|
23007
23094
|
if (databaseIsInTransaction(db)) {
|
|
@@ -23127,7 +23214,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23127
23214
|
const options = baseOptions.resolveForProject?.(projectDirectory) ?? baseOptions;
|
|
23128
23215
|
const schedulerConfig = options.scheduler ?? DEFAULT_SCHEDULER_CONFIG;
|
|
23129
23216
|
const scheduler = schedulerFor(options);
|
|
23130
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDirectory) ?? "";
|
|
23217
|
+
const projectIdentity = resolveProjectIdentityForSession(projectDirectory, options.allowHomeProject) ?? "";
|
|
23131
23218
|
updateSessionProjectTracking(sessionId, projectIdentity, options.db);
|
|
23132
23219
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
23133
23220
|
const tEntryBranch = performance.now();
|
|
@@ -23149,7 +23236,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23149
23236
|
const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
|
|
23150
23237
|
const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
|
|
23151
23238
|
const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
|
|
23152
|
-
if (strictEntryIds && options.injection) {
|
|
23239
|
+
if (strictEntryIds && options.injection && !options.compactionOff) {
|
|
23153
23240
|
const removed = trimPiMessagesToCachedBoundary(options.db, sessionId, event.messages, strictEntryIds);
|
|
23154
23241
|
if (removed > 0) {
|
|
23155
23242
|
logTransformTiming(sessionId, "cachedBoundaryEarlyTrim", tEntryBranch, `removed=${removed}`);
|
|
@@ -23197,6 +23284,30 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23197
23284
|
const tMeta = performance.now();
|
|
23198
23285
|
const sessionMetaForUsage = getOrCreateSessionMeta(options.db, sessionId);
|
|
23199
23286
|
logTransformTiming(sessionId, "getOrCreateSessionMeta", tMeta);
|
|
23287
|
+
const compactionTransition = reconcilePiCompactionMode({
|
|
23288
|
+
db: options.db,
|
|
23289
|
+
sessionId,
|
|
23290
|
+
compactionOff: options.compactionOff === true,
|
|
23291
|
+
historianRunnable: options.historian !== undefined
|
|
23292
|
+
});
|
|
23293
|
+
if (compactionTransition.recordToWrite) {
|
|
23294
|
+
if (compactionTransition.clearDeferredMarkerState) {
|
|
23295
|
+
clearPiCompactionOffInMemoryState(sessionId);
|
|
23296
|
+
}
|
|
23297
|
+
if (compactionTransition.invalidatedBaseline) {
|
|
23298
|
+
clearPiInjectionTokenCountCache(sessionId);
|
|
23299
|
+
sessionMetaForUsage.cachedM0Bytes = null;
|
|
23300
|
+
sessionMetaForUsage.cachedM1Bytes = null;
|
|
23301
|
+
}
|
|
23302
|
+
let noticeDelivered = compactionTransition.notice === null;
|
|
23303
|
+
if (compactionTransition.notice && ctx.ui?.notify) {
|
|
23304
|
+
ctx.ui.notify(compactionTransition.notice, "info");
|
|
23305
|
+
noticeDelivered = true;
|
|
23306
|
+
}
|
|
23307
|
+
if (noticeDelivered) {
|
|
23308
|
+
commitPiCompactionModeRecord(options.db, sessionId, compactionTransition.recordToWrite);
|
|
23309
|
+
}
|
|
23310
|
+
}
|
|
23200
23311
|
const usageReset = {
|
|
23201
23312
|
lastContextPercentage: 0,
|
|
23202
23313
|
lastInputTokens: 0,
|
|
@@ -23240,12 +23351,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23240
23351
|
usageInputTokens = typeof piUsage?.tokens === "number" ? piUsage.tokens : 0;
|
|
23241
23352
|
}
|
|
23242
23353
|
let usageContextLimit = isSaneLimit(piUsage?.contextWindow) ? piUsage.contextWindow : undefined;
|
|
23354
|
+
let detectedContextLimit;
|
|
23243
23355
|
const tEmergencyRecovery = performance.now();
|
|
23244
23356
|
let needsEmergencyBump = false;
|
|
23245
23357
|
let emergencyRecoveryArmed = false;
|
|
23246
23358
|
try {
|
|
23247
|
-
const overflowState = getOverflowState(options.db, sessionId);
|
|
23359
|
+
const overflowState = options.compactionOff ? { detectedContextLimit: 0, needsEmergencyRecovery: false } : getOverflowState(options.db, sessionId);
|
|
23248
23360
|
if (overflowState.detectedContextLimit > 0) {
|
|
23361
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
23249
23362
|
usageContextLimit = Math.min(usageContextLimit ?? overflowState.detectedContextLimit, overflowState.detectedContextLimit);
|
|
23250
23363
|
}
|
|
23251
23364
|
emergencyRecoveryArmed = overflowState.needsEmergencyRecovery;
|
|
@@ -23263,6 +23376,17 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23263
23376
|
usageContextLimit = modelWindow;
|
|
23264
23377
|
}
|
|
23265
23378
|
}
|
|
23379
|
+
usageContextLimit = resolvePiUsableContextLimit({
|
|
23380
|
+
rawContextWindow: usageContextLimit,
|
|
23381
|
+
model: ctx.model,
|
|
23382
|
+
detectedContextLimit
|
|
23383
|
+
});
|
|
23384
|
+
const effectiveExecuteThresholdPercentage = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage, modelKey, 65, {
|
|
23385
|
+
tokensConfig: schedulerConfig.executeThresholdTokens,
|
|
23386
|
+
contextLimit: usageContextLimit,
|
|
23387
|
+
sessionId
|
|
23388
|
+
});
|
|
23389
|
+
const { forceMaterializationPercentage } = escalationBands(effectiveExecuteThresholdPercentage);
|
|
23266
23390
|
if (!usedPersistedUsage && isSaneLimit(usageContextLimit) && usageInputTokens > 0) {
|
|
23267
23391
|
usagePercentage = usageInputTokens / usageContextLimit * 100;
|
|
23268
23392
|
}
|
|
@@ -23283,7 +23407,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23283
23407
|
logTransformTiming(sessionId, "schedulerAndUsage", tScheduler);
|
|
23284
23408
|
const piMessageCount = fullWireMessageCount;
|
|
23285
23409
|
const looksLikeImportedSession = schedulerDecision === "defer" && usagePercentage === 0 && sessionMeta.lastResponseTime === 0 && piMessageCount >= 50;
|
|
23286
|
-
if (looksLikeImportedSession) {
|
|
23410
|
+
if (looksLikeImportedSession && !options.compactionOff) {
|
|
23287
23411
|
schedulerDecision = "execute";
|
|
23288
23412
|
sessionLog(sessionId, `transform: large imported session detected (${piMessageCount} messages, no usage baseline) — forcing execute on first pass`);
|
|
23289
23413
|
}
|
|
@@ -23294,7 +23418,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23294
23418
|
if (storedStableIdScheme < PI_STABLE_ID_SCHEME && !realEntryIdsAvailable) {
|
|
23295
23419
|
sessionLog(sessionId, `stable-id scheme cutover deferred: real SessionEntry ids unavailable this pass (branch resolution failed) — will retry when getBranch() succeeds`);
|
|
23296
23420
|
}
|
|
23297
|
-
if (stableIdSchemeCutover) {
|
|
23421
|
+
if (stableIdSchemeCutover && !options.compactionOff) {
|
|
23298
23422
|
schedulerDecision = "execute";
|
|
23299
23423
|
signalPiPendingMaterialization(sessionId);
|
|
23300
23424
|
sessionLog(sessionId, `stable-id scheme cutover: stored=${storedStableIdScheme} < current=${PI_STABLE_ID_SCHEME} — forcing execute+materialize this pass`);
|
|
@@ -23306,14 +23430,18 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23306
23430
|
contextUsage: { percentage: usagePercentage },
|
|
23307
23431
|
sessionMeta,
|
|
23308
23432
|
historyRefreshSessions,
|
|
23309
|
-
sessionId
|
|
23433
|
+
sessionId,
|
|
23434
|
+
effectiveExecuteThresholdPercentage
|
|
23310
23435
|
});
|
|
23311
|
-
const { midTurnAdjustedSchedulerDecision, sideEffect } =
|
|
23436
|
+
const { midTurnAdjustedSchedulerDecision, sideEffect } = options.compactionOff ? {
|
|
23437
|
+
midTurnAdjustedSchedulerDecision: "defer",
|
|
23438
|
+
sideEffect: "none"
|
|
23439
|
+
} : applyMidTurnDeferral({
|
|
23312
23440
|
base: schedulerDecisionEarly,
|
|
23313
23441
|
bypassReason,
|
|
23314
23442
|
midTurn
|
|
23315
23443
|
});
|
|
23316
|
-
if (sideEffect === "set-flag") {
|
|
23444
|
+
if (sideEffect === "set-flag" && !options.compactionOff) {
|
|
23317
23445
|
const flagPayload = {
|
|
23318
23446
|
id: crypto3.randomUUID(),
|
|
23319
23447
|
reason: `${schedulerDecisionEarly}-${bypassReason}`,
|
|
@@ -23323,8 +23451,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23323
23451
|
}
|
|
23324
23452
|
schedulerDecision = midTurnAdjustedSchedulerDecision;
|
|
23325
23453
|
sessionLog(sessionId, `[boundary-exec] base=${schedulerDecisionEarly} bypass=${bypassReason} midTurn=${midTurn} effective=${midTurnAdjustedSchedulerDecision} sideEffect=${sideEffect}`);
|
|
23326
|
-
const forceMaterialization = usagePercentage >=
|
|
23327
|
-
const isEmergency = usagePercentage >= EMERGENCY_BLOCK_PERCENTAGE;
|
|
23454
|
+
const forceMaterialization = !options.compactionOff && usagePercentage >= forceMaterializationPercentage;
|
|
23455
|
+
const isEmergency = !options.compactionOff && usagePercentage >= EMERGENCY_BLOCK_PERCENTAGE;
|
|
23328
23456
|
if (isEmergency) {
|
|
23329
23457
|
const lastNotifiedAt = lastEmergencyNotificationAtMs.get(sessionId) ?? 0;
|
|
23330
23458
|
const now = Date.now();
|
|
@@ -23340,7 +23468,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23340
23468
|
sessionLog(sessionId, "EMERGENCY: historian wait completed (or timed out)");
|
|
23341
23469
|
} catch {}
|
|
23342
23470
|
}
|
|
23343
|
-
if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump <
|
|
23471
|
+
if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump < forceMaterializationPercentage && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
|
|
23344
23472
|
try {
|
|
23345
23473
|
clearEmergencyRecovery(options.db, sessionId);
|
|
23346
23474
|
sessionLog(sessionId, "EMERGENCY: disarming recovery — no eligible pre-tail history to compact (would otherwise loop at 95%)");
|
|
@@ -23392,6 +23520,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23392
23520
|
stableIdSchemeCutover,
|
|
23393
23521
|
schedulerDecision,
|
|
23394
23522
|
forceMaterialization: forceMaterialization || isEmergency,
|
|
23523
|
+
forceMaterializationPercentage,
|
|
23395
23524
|
contextUsage: {
|
|
23396
23525
|
percentage: usagePercentage,
|
|
23397
23526
|
inputTokens: usageInputTokens
|
|
@@ -23404,7 +23533,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23404
23533
|
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
23405
23534
|
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
23406
23535
|
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
23407
|
-
isSubagent: sessionMeta.isSubagent
|
|
23536
|
+
isSubagent: sessionMeta.isSubagent,
|
|
23537
|
+
compactionOff: options.compactionOff === true
|
|
23408
23538
|
});
|
|
23409
23539
|
logTransformTiming(sessionId, "runPipeline", tRunPipeline);
|
|
23410
23540
|
const postPipelineStart = performance.now();
|
|
@@ -23428,7 +23558,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23428
23558
|
}
|
|
23429
23559
|
logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
|
|
23430
23560
|
const tHistorianScheduling = performance.now();
|
|
23431
|
-
if (options.historian) {
|
|
23561
|
+
if (options.historian && !options.compactionOff) {
|
|
23432
23562
|
maybeFireHistorian({
|
|
23433
23563
|
pi,
|
|
23434
23564
|
ctx,
|
|
@@ -23446,22 +23576,24 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23446
23576
|
let outputMessages = result.messages;
|
|
23447
23577
|
const tNoteNudges = performance.now();
|
|
23448
23578
|
try {
|
|
23449
|
-
|
|
23450
|
-
|
|
23451
|
-
|
|
23452
|
-
|
|
23453
|
-
|
|
23454
|
-
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
|
|
23458
|
-
|
|
23579
|
+
if (!options.compactionOff) {
|
|
23580
|
+
outputMessages = applyNoteNudges({
|
|
23581
|
+
sessionId,
|
|
23582
|
+
db: options.db,
|
|
23583
|
+
messages: outputMessages,
|
|
23584
|
+
projectIdentity,
|
|
23585
|
+
entryIds: strictEntryIds,
|
|
23586
|
+
entryIdByRef: result.postCommitEntryIdByRef,
|
|
23587
|
+
isCacheBusting: isCacheBusting || result.executedWorkThisPass,
|
|
23588
|
+
syntheticLeadingCount: result.syntheticLeadingCount
|
|
23589
|
+
});
|
|
23590
|
+
}
|
|
23459
23591
|
} catch (err) {
|
|
23460
23592
|
sessionLog(sessionId, `note nudges failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
23461
23593
|
}
|
|
23462
23594
|
logTransformTiming(sessionId, "noteNudges", tNoteNudges);
|
|
23463
23595
|
const tAutoSearch = performance.now();
|
|
23464
|
-
if (options.autoSearch?.enabled) {
|
|
23596
|
+
if (options.autoSearch?.enabled && !options.compactionOff) {
|
|
23465
23597
|
try {
|
|
23466
23598
|
outputMessages = await runAutoSearchHintForPi({
|
|
23467
23599
|
sessionId,
|
|
@@ -23486,7 +23618,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23486
23618
|
const tTodoCapture = performance.now();
|
|
23487
23619
|
try {
|
|
23488
23620
|
const sessionMetaForTodo = getOrCreateSessionMeta(options.db, sessionId);
|
|
23489
|
-
if (!sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
23621
|
+
if (!options.compactionOff && !sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
23490
23622
|
const isCacheBustingForTodo = isCacheBusting || result.executedWorkThisPass;
|
|
23491
23623
|
outputMessages = injectSyntheticTodowriteForPi({
|
|
23492
23624
|
db: options.db,
|
|
@@ -23504,7 +23636,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23504
23636
|
const tChannelAccounting = performance.now();
|
|
23505
23637
|
try {
|
|
23506
23638
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
23507
|
-
if (!sessionMetaForCh1.isSubagent) {
|
|
23639
|
+
if (!options.compactionOff && !sessionMetaForCh1.isSubagent) {
|
|
23508
23640
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage ?? 65, liveModelBySession.get(sessionId), 65, {
|
|
23509
23641
|
tokensConfig: schedulerConfig.executeThresholdTokens,
|
|
23510
23642
|
contextLimit: usageContextLimit ?? 0
|
|
@@ -23571,7 +23703,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23571
23703
|
}
|
|
23572
23704
|
logTransformTiming(sessionId, "workMetrics", tWorkMetrics);
|
|
23573
23705
|
const tStableIdSchemePersist = performance.now();
|
|
23574
|
-
if (stableIdSchemeCutover) {
|
|
23706
|
+
if (stableIdSchemeCutover && !options.compactionOff) {
|
|
23575
23707
|
persistStableIdSchemeForRun(options.db, sessionId, {
|
|
23576
23708
|
piStableIdScheme: PI_STABLE_ID_SCHEME
|
|
23577
23709
|
});
|
|
@@ -23596,7 +23728,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23596
23728
|
sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
23597
23729
|
return { messages: outputMessages };
|
|
23598
23730
|
} catch (err) {
|
|
23599
|
-
if (isFailClosedBlockingError(err))
|
|
23731
|
+
if (isFailClosedBlockingError(err) && !baseOptions.compactionOff)
|
|
23600
23732
|
throw err;
|
|
23601
23733
|
const message = err instanceof Error ? err.message : String(err);
|
|
23602
23734
|
const stack = err instanceof Error ? err.stack : undefined;
|
|
@@ -23753,6 +23885,7 @@ function spawnPiHistorianRun(args) {
|
|
|
23753
23885
|
twoPass: historian.twoPass,
|
|
23754
23886
|
thinkingLevel: historian.thinkingLevel,
|
|
23755
23887
|
memoryEnabled: historian.memoryEnabled,
|
|
23888
|
+
allowHomeProject: historian.allowHomeProject,
|
|
23756
23889
|
autoPromote: historian.autoPromote,
|
|
23757
23890
|
userMemoriesEnabled: historian.userMemoriesEnabled,
|
|
23758
23891
|
language: historian.language,
|
|
@@ -23832,15 +23965,22 @@ function maybeFireHistorian(args) {
|
|
|
23832
23965
|
const piUsage = ctx.getContextUsage?.();
|
|
23833
23966
|
let usageSource;
|
|
23834
23967
|
usageContextLimit = isSaneLimit(piUsage?.contextWindow) ? piUsage.contextWindow : undefined;
|
|
23968
|
+
let detectedContextLimit;
|
|
23835
23969
|
if (usageContextLimit === undefined && isSaneLimit(ctx.model?.contextWindow)) {
|
|
23836
23970
|
usageContextLimit = ctx.model.contextWindow;
|
|
23837
23971
|
}
|
|
23838
23972
|
try {
|
|
23839
23973
|
const overflowState = getOverflowState(db, sessionId);
|
|
23840
23974
|
if (overflowState.detectedContextLimit > 0) {
|
|
23975
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
23841
23976
|
usageContextLimit = Math.min(usageContextLimit ?? overflowState.detectedContextLimit, overflowState.detectedContextLimit);
|
|
23842
23977
|
}
|
|
23843
23978
|
} catch {}
|
|
23979
|
+
usageContextLimit = resolvePiUsableContextLimit({
|
|
23980
|
+
rawContextWindow: usageContextLimit,
|
|
23981
|
+
model: ctx.model,
|
|
23982
|
+
detectedContextLimit
|
|
23983
|
+
});
|
|
23844
23984
|
const sessionMetaForUsage = getOrCreateSessionMeta(db, sessionId);
|
|
23845
23985
|
if (sessionMetaForUsage.lastContextPercentage > 0 && sessionMetaForUsage.lastInputTokens > 0) {
|
|
23846
23986
|
usage = {
|
|
@@ -23879,6 +24019,7 @@ function maybeFireHistorian(args) {
|
|
|
23879
24019
|
modelKey,
|
|
23880
24020
|
usageContextLimit
|
|
23881
24021
|
});
|
|
24022
|
+
const historianForceMaterializationPercentage = escalationBands(triggerInputs.executeThresholdPercentage).forceMaterializationPercentage;
|
|
23882
24023
|
const boundaryContextLimit = triggerInputs.contextLimit;
|
|
23883
24024
|
const resolvePiBoundarySnapshot = (emergencyTailScale) => resolveProtectedTailBoundary(resolveBoundaryContext({
|
|
23884
24025
|
db,
|
|
@@ -23894,7 +24035,7 @@ function maybeFireHistorian(args) {
|
|
|
23894
24035
|
}));
|
|
23895
24036
|
const resolveRunnablePiBoundarySnapshot = () => {
|
|
23896
24037
|
let snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot());
|
|
23897
|
-
if (!hasRunnableCompartmentWindow(snapshot) && usage.percentage >=
|
|
24038
|
+
if (!hasRunnableCompartmentWindow(snapshot) && usage.percentage >= historianForceMaterializationPercentage) {
|
|
23898
24039
|
snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot(usage.percentage >= 95 ? 0.25 : 0.5));
|
|
23899
24040
|
}
|
|
23900
24041
|
return snapshot;
|
|
@@ -23938,15 +24079,15 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
23938
24079
|
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit, () => {
|
|
23939
24080
|
const messages = provider.readMessages();
|
|
23940
24081
|
return { messages, absoluteMessageCount: messages.length };
|
|
23941
|
-
}, args.taggerFloor);
|
|
24082
|
+
}, args.taggerFloor, { canClearReasoning: true });
|
|
23942
24083
|
if (!trigger.shouldFire) {
|
|
23943
24084
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
23944
24085
|
try {
|
|
23945
24086
|
const overflowState = getOverflowState(db, sessionId);
|
|
23946
|
-
if (overflowState.needsEmergencyRecovery && usage.percentage <
|
|
24087
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < historianForceMaterializationPercentage && !inFlightHistorian.has(sessionId)) {
|
|
23947
24088
|
boundarySnapshot ??= resolveRunnablePiBoundarySnapshot();
|
|
23948
24089
|
}
|
|
23949
|
-
if (overflowState.needsEmergencyRecovery && usage.percentage <
|
|
24090
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < historianForceMaterializationPercentage && !inFlightHistorian.has(sessionId) && boundarySnapshot !== undefined && !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
23950
24091
|
clearEmergencyRecovery(db, sessionId);
|
|
23951
24092
|
sessionLog(sessionId, `historian: disarming stale emergency recovery — real pressure ${usage.percentage.toFixed(1)}% with no runnable compartment window (would otherwise bump to 95% every pass)`);
|
|
23952
24093
|
}
|
|
@@ -24034,7 +24175,45 @@ function captureReasoningMutationRollback(messages) {
|
|
|
24034
24175
|
}
|
|
24035
24176
|
};
|
|
24036
24177
|
}
|
|
24178
|
+
async function runCompactionOffPipeline(args) {
|
|
24179
|
+
let injectionResult = null;
|
|
24180
|
+
if (args.injection) {
|
|
24181
|
+
injectionResult = injectM0M1Pi({
|
|
24182
|
+
sessionId: args.sessionId,
|
|
24183
|
+
projectIdentity: args.projectIdentity,
|
|
24184
|
+
projectDirectory: args.projectDirectory,
|
|
24185
|
+
memoryEnabled: args.injection.memoryEnabled,
|
|
24186
|
+
injectDocs: args.injection.injectDocs,
|
|
24187
|
+
injectionBudgetTokens: args.injection.injectionBudgetTokens,
|
|
24188
|
+
historyBudgetTokens: args.injection.historyBudgetTokens,
|
|
24189
|
+
muralEnabled: args.injection.muralEnabled === true,
|
|
24190
|
+
compactionOff: true
|
|
24191
|
+
}, args.db, args.messages, args.entryIds, false);
|
|
24192
|
+
}
|
|
24193
|
+
return {
|
|
24194
|
+
messages: args.messages,
|
|
24195
|
+
heuristicsExecuted: false,
|
|
24196
|
+
executedWorkThisPass: false,
|
|
24197
|
+
historyInjected: false,
|
|
24198
|
+
syntheticLeadingCount: injectionResult?.syntheticLeadingCount ?? 0,
|
|
24199
|
+
heuristicsResult: null,
|
|
24200
|
+
injectionResult,
|
|
24201
|
+
materialized: injectionResult?.m0Materialized === true,
|
|
24202
|
+
materializeReason: injectionResult?.m0Reason ?? null,
|
|
24203
|
+
droppedTokens: 0,
|
|
24204
|
+
droppedCount: 0,
|
|
24205
|
+
emergency: false,
|
|
24206
|
+
bustedThisPass: injectionResult?.m0Materialized === true,
|
|
24207
|
+
targetCount: 0,
|
|
24208
|
+
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
24209
|
+
activeTags: [],
|
|
24210
|
+
postCommitEntryIdByRef: new Map
|
|
24211
|
+
};
|
|
24212
|
+
}
|
|
24037
24213
|
async function runPipeline(args) {
|
|
24214
|
+
if (args.compactionOff)
|
|
24215
|
+
return runCompactionOffPipeline(args);
|
|
24216
|
+
const forceMaterializationPercentage = args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage;
|
|
24038
24217
|
let executedWorkThisPass = false;
|
|
24039
24218
|
let historyWasConsumedThisPass = false;
|
|
24040
24219
|
let materializationSatisfiedThisPass = false;
|
|
@@ -24073,7 +24252,7 @@ async function runPipeline(args) {
|
|
|
24073
24252
|
})();
|
|
24074
24253
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
24075
24254
|
const ctxReduceCallable = !args.sessionMeta.isSubagent;
|
|
24076
|
-
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >=
|
|
24255
|
+
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= forceMaterializationPercentage;
|
|
24077
24256
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
24078
24257
|
const piHardSignals = args.injection ? (() => {
|
|
24079
24258
|
const hardMeta = args.sessionMeta;
|
|
@@ -24323,7 +24502,7 @@ async function runPipeline(args) {
|
|
|
24323
24502
|
}
|
|
24324
24503
|
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
24325
24504
|
const alreadyMutatingThisPass = pendingOpsDidMutate || heuristicOrReasoningDidMutate;
|
|
24326
|
-
const emergencyDropEligible = args.forceMaterialization === true || args.contextUsage.percentage >=
|
|
24505
|
+
const emergencyDropEligible = args.forceMaterialization === true || args.contextUsage.percentage >= forceMaterializationPercentage;
|
|
24327
24506
|
let autoReclaimTargetCount = 0;
|
|
24328
24507
|
let autoReclaimDidMutate = false;
|
|
24329
24508
|
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
@@ -24710,6 +24889,13 @@ function appendReminderToPiUserMessage(message, reminder) {
|
|
|
24710
24889
|
}
|
|
24711
24890
|
contentArr.push({ type: "text", text: reminder.trimStart() });
|
|
24712
24891
|
}
|
|
24892
|
+
function clearPiCompactionOffInMemoryState(sessionId) {
|
|
24893
|
+
historyRefreshSessions.delete(sessionId);
|
|
24894
|
+
deferredHistoryRefreshSessions.delete(sessionId);
|
|
24895
|
+
pendingMaterializationSessions.delete(sessionId);
|
|
24896
|
+
deferredMaterializationSessions.delete(sessionId);
|
|
24897
|
+
clearPiChannel1State(sessionId);
|
|
24898
|
+
}
|
|
24713
24899
|
function clearContextHandlerSession(sessionId) {
|
|
24714
24900
|
invalidateTrueRawTokenCache({ sessionId, reason: "pi.branch.changed" });
|
|
24715
24901
|
activeContextHandlerSessions.delete(sessionId);
|
|
@@ -24768,6 +24954,14 @@ No active Pi session is available.`,
|
|
|
24768
24954
|
});
|
|
24769
24955
|
return;
|
|
24770
24956
|
}
|
|
24957
|
+
if (deps.compactionOff) {
|
|
24958
|
+
sendCtxStatusMessage(pi, {
|
|
24959
|
+
title: "/ctx-flush",
|
|
24960
|
+
text: COMPACTION_OFF_COMMAND_UNAVAILABLE,
|
|
24961
|
+
level: "warning"
|
|
24962
|
+
});
|
|
24963
|
+
return;
|
|
24964
|
+
}
|
|
24771
24965
|
const pendingBefore = getPendingOps(deps.db, sessionId).length;
|
|
24772
24966
|
const result = executeFlush(deps.db, sessionId);
|
|
24773
24967
|
signalPiHistoryRefresh(sessionId);
|
|
@@ -24798,104 +24992,9 @@ function cleanupHistorianStateFile(path6) {
|
|
|
24798
24992
|
unlinkSync(path6);
|
|
24799
24993
|
} catch {}
|
|
24800
24994
|
}
|
|
24801
|
-
// ../plugin/src/hooks/magic-context/compaction-marker-manager.ts
|
|
24802
|
-
var MARKER_SUMMARY_TEXT = "[Compacted by magic-context — session history is managed by the plugin]";
|
|
24803
|
-
function dropMarkerSummaryTag(db, sessionId, summaryMessageId) {
|
|
24804
|
-
const tagNumber = getTagNumberByMessageId(db, sessionId, `${summaryMessageId}:p0`);
|
|
24805
|
-
if (tagNumber !== null)
|
|
24806
|
-
updateTagStatus(db, sessionId, tagNumber, "dropped");
|
|
24807
|
-
}
|
|
24808
|
-
function persistMarkerStateAndDropReplacedTag(db, sessionId, state, replacedSummaryMessageId) {
|
|
24809
|
-
db.transaction(() => {
|
|
24810
|
-
setPersistedCompactionMarkerState(db, sessionId, state);
|
|
24811
|
-
if (replacedSummaryMessageId !== null) {
|
|
24812
|
-
dropMarkerSummaryTag(db, sessionId, replacedSummaryMessageId);
|
|
24813
|
-
}
|
|
24814
|
-
})();
|
|
24815
|
-
}
|
|
24816
|
-
function getCompartmentEndMessageIdForOrdinal(db, sessionId, endOrdinal) {
|
|
24817
|
-
const row = db.prepare(`SELECT end_message_id
|
|
24818
|
-
FROM compartments
|
|
24819
|
-
WHERE session_id = ? AND end_message = ?
|
|
24820
|
-
ORDER BY sequence DESC
|
|
24821
|
-
LIMIT 1`).get(sessionId, endOrdinal);
|
|
24822
|
-
return typeof row?.end_message_id === "string" && row.end_message_id.length > 0 ? row.end_message_id : null;
|
|
24823
|
-
}
|
|
24824
|
-
function existingMarkerAlreadyCoversTarget(sessionId, existing, targetOrdinal, targetEndMessageId) {
|
|
24825
|
-
if (existing.boundaryOrdinal < targetOrdinal) {
|
|
24826
|
-
return false;
|
|
24827
|
-
}
|
|
24828
|
-
if (existing.boundaryOrdinal === targetOrdinal) {
|
|
24829
|
-
const boundaryCompare = compareOpenCodeMessagesByCanonicalOrder(sessionId, existing.boundaryMessageId, targetEndMessageId);
|
|
24830
|
-
if (boundaryCompare === null || boundaryCompare > 0) {
|
|
24831
|
-
return false;
|
|
24832
|
-
}
|
|
24833
|
-
if (existing.targetEndMessageId !== null && existing.targetEndMessageId !== targetEndMessageId) {
|
|
24834
|
-
return false;
|
|
24835
|
-
}
|
|
24836
|
-
return true;
|
|
24837
|
-
}
|
|
24838
|
-
if (existing.targetEndMessageId !== null) {
|
|
24839
|
-
const targetCompare = compareOpenCodeMessagesByCanonicalOrder(sessionId, existing.targetEndMessageId, targetEndMessageId);
|
|
24840
|
-
if (targetCompare !== null && targetCompare <= 0) {
|
|
24841
|
-
return false;
|
|
24842
|
-
}
|
|
24843
|
-
}
|
|
24844
|
-
return true;
|
|
24845
|
-
}
|
|
24846
|
-
function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
|
|
24847
|
-
if (getHarness() !== "opencode") {
|
|
24848
|
-
return true;
|
|
24849
|
-
}
|
|
24850
|
-
const targetEndMessageId = getCompartmentEndMessageIdForOrdinal(db, sessionId, lastCompartmentEnd);
|
|
24851
|
-
if (!targetEndMessageId) {
|
|
24852
|
-
sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
|
|
24853
|
-
return false;
|
|
24854
|
-
}
|
|
24855
|
-
const existing = getPersistedCompactionMarkerState(db, sessionId);
|
|
24856
|
-
const removedSummaryMessageId = existing?.summaryMessageId ?? null;
|
|
24857
|
-
if (existing) {
|
|
24858
|
-
if (existingMarkerAlreadyCoversTarget(sessionId, existing, lastCompartmentEnd, targetEndMessageId)) {
|
|
24859
|
-
return true;
|
|
24860
|
-
}
|
|
24861
|
-
}
|
|
24862
|
-
const boundary = findBoundaryUserMessage(sessionId, targetEndMessageId);
|
|
24863
|
-
if (!boundary) {
|
|
24864
|
-
sessionLog(sessionId, `compaction-marker: no user boundary found at or before endMessageId ${targetEndMessageId} (ordinal ${lastCompartmentEnd}); preserving existing marker`);
|
|
24865
|
-
return false;
|
|
24866
|
-
}
|
|
24867
|
-
if (existing) {
|
|
24868
|
-
const removed = removeCompactionMarker(existing);
|
|
24869
|
-
if (!removed) {
|
|
24870
|
-
sessionLog(sessionId, `compaction-marker: failed to remove old boundary at ordinal ${existing.boundaryOrdinal}; preserving persisted state for retry (not injecting new marker this pass)`);
|
|
24871
|
-
return false;
|
|
24872
|
-
}
|
|
24873
|
-
persistMarkerStateAndDropReplacedTag(db, sessionId, null, removedSummaryMessageId);
|
|
24874
|
-
sessionLog(sessionId, `compaction-marker: removed old boundary at ordinal ${existing.boundaryOrdinal}, moving to ${lastCompartmentEnd}`);
|
|
24875
|
-
}
|
|
24876
|
-
const result = injectCompactionMarker({
|
|
24877
|
-
sessionId,
|
|
24878
|
-
endOrdinal: lastCompartmentEnd,
|
|
24879
|
-
endMessageId: targetEndMessageId,
|
|
24880
|
-
summaryText: MARKER_SUMMARY_TEXT,
|
|
24881
|
-
directory: directory ?? process.cwd(),
|
|
24882
|
-
resolvedBoundary: boundary
|
|
24883
|
-
});
|
|
24884
|
-
if (result) {
|
|
24885
|
-
persistMarkerStateAndDropReplacedTag(db, sessionId, {
|
|
24886
|
-
...result,
|
|
24887
|
-
boundaryOrdinal: lastCompartmentEnd,
|
|
24888
|
-
targetEndMessageId
|
|
24889
|
-
}, removedSummaryMessageId);
|
|
24890
|
-
sessionLog(sessionId, `compaction-marker: injected at ordinal ${lastCompartmentEnd}, boundary user msg ${result.boundaryMessageId}`);
|
|
24891
|
-
return true;
|
|
24892
|
-
}
|
|
24893
|
-
return false;
|
|
24894
|
-
}
|
|
24895
|
-
|
|
24896
24995
|
// ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
|
|
24897
24996
|
import { mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
24898
|
-
import { join as
|
|
24997
|
+
import { join as join4 } from "node:path";
|
|
24899
24998
|
|
|
24900
24999
|
// ../plugin/src/agents/historian.ts
|
|
24901
25000
|
var HISTORIAN_AGENT = "historian";
|
|
@@ -24907,6 +25006,24 @@ function historianResponseDumpDir(directory) {
|
|
|
24907
25006
|
return getProjectMagicContextHistorianDir(directory);
|
|
24908
25007
|
}
|
|
24909
25008
|
var MAX_HISTORIAN_RETRIES2 = 2;
|
|
25009
|
+
var HISTORIAN_REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
|
|
25010
|
+
function extractLatestHistorianReasoning(messages) {
|
|
25011
|
+
if (!Array.isArray(messages))
|
|
25012
|
+
return null;
|
|
25013
|
+
const latest = messages.filter((message) => isRecord(message) && isRecord(message.info) && message.info.role === "assistant").sort((left, right) => historianMessageCreatedAt(right) - historianMessageCreatedAt(left))[0];
|
|
25014
|
+
if (!latest || !Array.isArray(latest.parts))
|
|
25015
|
+
return null;
|
|
25016
|
+
return latest.parts.filter(isHistorianReasoningPart).map((part) => part.text).join(`
|
|
25017
|
+
`) || null;
|
|
25018
|
+
}
|
|
25019
|
+
function isHistorianReasoningPart(part) {
|
|
25020
|
+
return isRecord(part) && typeof part.type === "string" && HISTORIAN_REASONING_PART_TYPES.has(part.type) && typeof part.text === "string" && part.text.length > 0;
|
|
25021
|
+
}
|
|
25022
|
+
function historianMessageCreatedAt(message) {
|
|
25023
|
+
if (!isRecord(message.info) || !isRecord(message.info.time))
|
|
25024
|
+
return 0;
|
|
25025
|
+
return typeof message.info.time.created === "number" ? message.info.time.created : 0;
|
|
25026
|
+
}
|
|
24910
25027
|
async function runValidatedHistorianPass(args) {
|
|
24911
25028
|
const firstRun = await runHistorianPrompt({
|
|
24912
25029
|
...args,
|
|
@@ -24972,6 +25089,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
24972
25089
|
sessionLog(args.parentSessionId, "historian two-pass: running editor on draft");
|
|
24973
25090
|
const editorRun = await runHistorianPrompt({
|
|
24974
25091
|
client: args.client,
|
|
25092
|
+
db: args.db,
|
|
24975
25093
|
parentSessionId: args.parentSessionId,
|
|
24976
25094
|
sessionDirectory: args.sessionDirectory,
|
|
24977
25095
|
prompt: buildHistorianEditorPrompt(args.draftXml),
|
|
@@ -24998,6 +25116,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
24998
25116
|
async function runHistorianPrompt(args) {
|
|
24999
25117
|
const {
|
|
25000
25118
|
client,
|
|
25119
|
+
db,
|
|
25001
25120
|
parentSessionId,
|
|
25002
25121
|
sessionDirectory,
|
|
25003
25122
|
prompt,
|
|
@@ -25031,12 +25150,12 @@ async function runHistorianPrompt(args) {
|
|
|
25031
25150
|
};
|
|
25032
25151
|
try {
|
|
25033
25152
|
sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
|
|
25034
|
-
const createResponse = await
|
|
25035
|
-
|
|
25036
|
-
|
|
25037
|
-
|
|
25038
|
-
|
|
25039
|
-
|
|
25153
|
+
const createResponse = await createChildSessionWithFence({
|
|
25154
|
+
client,
|
|
25155
|
+
db,
|
|
25156
|
+
parentSessionId,
|
|
25157
|
+
title: "magic-context-compartment",
|
|
25158
|
+
directory: sessionDirectory
|
|
25040
25159
|
});
|
|
25041
25160
|
const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
25042
25161
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
@@ -25084,7 +25203,18 @@ async function runHistorianPrompt(args) {
|
|
|
25084
25203
|
preferResponseOnMissingData: true
|
|
25085
25204
|
});
|
|
25086
25205
|
const invocationId = recordInvocation5({ status: "completed", messages });
|
|
25087
|
-
const
|
|
25206
|
+
const lengthCapped = hasLengthCappedOutput(messages);
|
|
25207
|
+
const textResult = extractLatestAssistantText(messages);
|
|
25208
|
+
const reasoningResult = textResult ? null : extractLatestHistorianReasoning(messages);
|
|
25209
|
+
if (!textResult && reasoningResult && lengthCapped) {
|
|
25210
|
+
const outputTokens = sumTokensFromChildMessages(messages).output;
|
|
25211
|
+
return {
|
|
25212
|
+
ok: false,
|
|
25213
|
+
error: `historian output length-capped at ${outputTokens} tokens (all reasoning, no text) — set historian.maxTokens or route historian.model to a low-reasoning lane/variant`,
|
|
25214
|
+
invocationId: invocationId ?? undefined
|
|
25215
|
+
};
|
|
25216
|
+
}
|
|
25217
|
+
const result = textResult ?? reasoningResult;
|
|
25088
25218
|
if (!result) {
|
|
25089
25219
|
return {
|
|
25090
25220
|
ok: false,
|
|
@@ -25136,6 +25266,7 @@ async function runFallbackHistorianPass(args) {
|
|
|
25136
25266
|
args.callbacks?.onModelFallback?.(modelId, i + 1, chain.length);
|
|
25137
25267
|
const fallbackRun = await runHistorianPrompt({
|
|
25138
25268
|
client: args.client,
|
|
25269
|
+
db: args.db,
|
|
25139
25270
|
parentSessionId: args.parentSessionId,
|
|
25140
25271
|
sessionDirectory: args.sessionDirectory,
|
|
25141
25272
|
prompt: args.prompt,
|
|
@@ -25212,7 +25343,7 @@ function dumpHistorianResponse(sessionId, directory, label, text) {
|
|
|
25212
25343
|
ensureCortexKitArtifactGitignore(directory);
|
|
25213
25344
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
25214
25345
|
const safeLabel = sanitizeDumpName(label);
|
|
25215
|
-
const dumpPath =
|
|
25346
|
+
const dumpPath = join4(dumpDir, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
25216
25347
|
writeFileSync5(dumpPath, text, "utf8");
|
|
25217
25348
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
25218
25349
|
label,
|
|
@@ -25231,116 +25362,6 @@ function sanitizeDumpName(value) {
|
|
|
25231
25362
|
return value.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
25232
25363
|
}
|
|
25233
25364
|
|
|
25234
|
-
// ../plugin/src/hooks/magic-context/send-session-notification.ts
|
|
25235
|
-
function hasNotificationSessionClient(client) {
|
|
25236
|
-
if (client === null || typeof client !== "object")
|
|
25237
|
-
return false;
|
|
25238
|
-
const candidate = client;
|
|
25239
|
-
if (candidate.session === undefined)
|
|
25240
|
-
return true;
|
|
25241
|
-
if (candidate.session === null || typeof candidate.session !== "object")
|
|
25242
|
-
return false;
|
|
25243
|
-
const session = candidate.session;
|
|
25244
|
-
return (session.prompt === undefined || typeof session.prompt === "function") && (session.promptAsync === undefined || typeof session.promptAsync === "function");
|
|
25245
|
-
}
|
|
25246
|
-
function inferToastVariant(text) {
|
|
25247
|
-
const lower = text.toLowerCase();
|
|
25248
|
-
if (lower.includes("error") || lower.includes("failed") || lower.includes("alert"))
|
|
25249
|
-
return "error";
|
|
25250
|
-
if (lower.includes("warning") || lower.includes("⚠"))
|
|
25251
|
-
return "warning";
|
|
25252
|
-
if (lower.includes("complete") || lower.includes("success") || lower.includes("✓") || lower.includes("finished"))
|
|
25253
|
-
return "success";
|
|
25254
|
-
return "info";
|
|
25255
|
-
}
|
|
25256
|
-
function extractToastTitle(text) {
|
|
25257
|
-
const headingMatch = text.match(/^#+\s+(.+)/m);
|
|
25258
|
-
if (headingMatch)
|
|
25259
|
-
return headingMatch[1].trim();
|
|
25260
|
-
const firstLine = text.split(`
|
|
25261
|
-
`)[0].trim();
|
|
25262
|
-
if (firstLine.length <= 80)
|
|
25263
|
-
return firstLine;
|
|
25264
|
-
return "Magic Context";
|
|
25265
|
-
}
|
|
25266
|
-
async function sendIgnoredMessage(client, sessionId, text, params, forcePersist = false) {
|
|
25267
|
-
const title = extractToastTitle(text);
|
|
25268
|
-
const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
|
25269
|
-
const toastVariant = inferToastVariant(text);
|
|
25270
|
-
const duration = params.toastDurationMs ?? 5000;
|
|
25271
|
-
const { isTuiConnected: checkTui } = await import("./rpc-notifications-td0amw6w.js");
|
|
25272
|
-
if (!forcePersist && checkTui(sessionId)) {
|
|
25273
|
-
try {
|
|
25274
|
-
const { pushNotification } = await import("./rpc-notifications-td0amw6w.js");
|
|
25275
|
-
pushNotification("toast", {
|
|
25276
|
-
title,
|
|
25277
|
-
message,
|
|
25278
|
-
variant: toastVariant,
|
|
25279
|
-
duration
|
|
25280
|
-
}, sessionId);
|
|
25281
|
-
return "sent";
|
|
25282
|
-
} catch {
|
|
25283
|
-
sessionLog(sessionId, "TUI RPC toast enqueue failed, falling back to ignored message");
|
|
25284
|
-
}
|
|
25285
|
-
}
|
|
25286
|
-
const { waitForSafeNotificationTarget } = await import("./safe-notification-target-ng8ygena.js");
|
|
25287
|
-
if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
|
|
25288
|
-
sessionLog(sessionId, "notification skipped (session not titled yet)");
|
|
25289
|
-
return "skipped";
|
|
25290
|
-
}
|
|
25291
|
-
if (!hasNotificationSessionClient(client)) {
|
|
25292
|
-
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
25293
|
-
return "failed";
|
|
25294
|
-
}
|
|
25295
|
-
const c = client;
|
|
25296
|
-
let agent = params.agent || undefined;
|
|
25297
|
-
let variant = params.variant || undefined;
|
|
25298
|
-
let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
|
|
25299
|
-
if (!agent || !model || !variant) {
|
|
25300
|
-
try {
|
|
25301
|
-
const { resolvePromptContext } = await import("./prompt-context-602yq94t.js");
|
|
25302
|
-
const resolved = await resolvePromptContext(client, sessionId);
|
|
25303
|
-
if (resolved) {
|
|
25304
|
-
agent = agent ?? resolved.agent;
|
|
25305
|
-
model = model ?? resolved.model;
|
|
25306
|
-
variant = variant ?? resolved.variant;
|
|
25307
|
-
}
|
|
25308
|
-
} catch {}
|
|
25309
|
-
}
|
|
25310
|
-
const input = {
|
|
25311
|
-
path: { id: sessionId },
|
|
25312
|
-
body: {
|
|
25313
|
-
noReply: true,
|
|
25314
|
-
agent,
|
|
25315
|
-
model,
|
|
25316
|
-
variant,
|
|
25317
|
-
parts: [
|
|
25318
|
-
{
|
|
25319
|
-
type: "text",
|
|
25320
|
-
text,
|
|
25321
|
-
ignored: true
|
|
25322
|
-
}
|
|
25323
|
-
]
|
|
25324
|
-
}
|
|
25325
|
-
};
|
|
25326
|
-
try {
|
|
25327
|
-
if (typeof c.session?.prompt === "function") {
|
|
25328
|
-
await Promise.resolve(c.session.prompt(input));
|
|
25329
|
-
return "sent";
|
|
25330
|
-
}
|
|
25331
|
-
if (typeof c.session?.promptAsync === "function") {
|
|
25332
|
-
await c.session.promptAsync(input);
|
|
25333
|
-
return "sent";
|
|
25334
|
-
}
|
|
25335
|
-
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
25336
|
-
return "failed";
|
|
25337
|
-
} catch (error) {
|
|
25338
|
-
const msg = getErrorMessage(error);
|
|
25339
|
-
sessionLog(sessionId, "failed to send notification:", msg);
|
|
25340
|
-
return "failed";
|
|
25341
|
-
}
|
|
25342
|
-
}
|
|
25343
|
-
|
|
25344
25365
|
// ../plugin/src/hooks/magic-context/compartment-runner-incremental.ts
|
|
25345
25366
|
var HISTORIAN_ALERT_COOLDOWN_MS2 = 60 * 1000;
|
|
25346
25367
|
var lastHistorianAlertBySession2 = new Map;
|
|
@@ -25558,6 +25579,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
25558
25579
|
emitProgress(`Running historian (pass ${passCount + 1})…`);
|
|
25559
25580
|
const validatedPass = await runValidatedHistorianPass({
|
|
25560
25581
|
client,
|
|
25582
|
+
db,
|
|
25561
25583
|
parentSessionId: sessionId,
|
|
25562
25584
|
sessionDirectory,
|
|
25563
25585
|
prompt,
|
|
@@ -25977,6 +25999,7 @@ ${chunk.text}`,
|
|
|
25977
25999
|
Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${chunk.startIndex}-${chunk.endIndex}.`, notifParams());
|
|
25978
26000
|
const validatedPass = await runValidatedHistorianPass({
|
|
25979
26001
|
client,
|
|
26002
|
+
db,
|
|
25980
26003
|
parentSessionId: sessionId,
|
|
25981
26004
|
sessionDirectory,
|
|
25982
26005
|
prompt,
|
|
@@ -26332,8 +26355,8 @@ function renderStatusText(ctx, db, sessionId) {
|
|
|
26332
26355
|
const inputTokens = typeof usage?.tokens === "number" ? usage.tokens : undefined;
|
|
26333
26356
|
const pct = typeof usage?.percent === "number" ? usage.percent : undefined;
|
|
26334
26357
|
const meta = readSessionMetaStatus(db, sessionId);
|
|
26335
|
-
const
|
|
26336
|
-
return `mc: ${inputTokens === undefined ? "--" : fmt(inputTokens)} (${pct === undefined ? "--" : `${Math.round(pct)}%`}) · ${
|
|
26358
|
+
const state2 = renderHistorianState(meta, recompSessions.has(sessionId));
|
|
26359
|
+
return `mc: ${inputTokens === undefined ? "--" : fmt(inputTokens)} (${pct === undefined ? "--" : `${Math.round(pct)}%`}) · ${state2}`;
|
|
26337
26360
|
}
|
|
26338
26361
|
function renderHistorianState(meta, recompActive) {
|
|
26339
26362
|
const failureCount = meta?.historian_failure_count ?? 0;
|
|
@@ -26436,6 +26459,14 @@ No active Pi session is available.`,
|
|
|
26436
26459
|
return;
|
|
26437
26460
|
}
|
|
26438
26461
|
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
26462
|
+
if (currentDeps.compactionOff) {
|
|
26463
|
+
sendCtxStatusMessage(pi, {
|
|
26464
|
+
title: "/ctx-recomp",
|
|
26465
|
+
text: COMPACTION_OFF_COMMAND_UNAVAILABLE,
|
|
26466
|
+
level: "warning"
|
|
26467
|
+
});
|
|
26468
|
+
return;
|
|
26469
|
+
}
|
|
26439
26470
|
const parsed = parseRecompArgs(args);
|
|
26440
26471
|
if (parsed.kind === "error") {
|
|
26441
26472
|
sendCtxStatusMessage(pi, {
|
|
@@ -26788,7 +26819,7 @@ function contextualizeUpgradeReason(reason) {
|
|
|
26788
26819
|
// src/pi-memory-migration.ts
|
|
26789
26820
|
var MIGRATION_SYSTEM_PROMPT2 = "You re-organize a software project's long-term memory into a stricter taxonomy. " + "Follow the user instructions exactly. Output ONLY the requested XML blocks, nothing else.";
|
|
26790
26821
|
async function runPiMemoryMigration(deps) {
|
|
26791
|
-
const projectPath = resolveProjectIdentityForSession(deps.directory);
|
|
26822
|
+
const projectPath = resolveProjectIdentityForSession(deps.directory, deps.allowHomeProject);
|
|
26792
26823
|
if (!projectPath) {
|
|
26793
26824
|
return {
|
|
26794
26825
|
ran: false,
|
|
@@ -26903,6 +26934,14 @@ No active Pi session is available.`,
|
|
|
26903
26934
|
return;
|
|
26904
26935
|
}
|
|
26905
26936
|
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
26937
|
+
if (currentDeps.compactionOff) {
|
|
26938
|
+
sendCtxStatusMessage(pi, {
|
|
26939
|
+
title: "/ctx-session-upgrade",
|
|
26940
|
+
text: COMPACTION_OFF_COMMAND_UNAVAILABLE,
|
|
26941
|
+
level: "warning"
|
|
26942
|
+
});
|
|
26943
|
+
return;
|
|
26944
|
+
}
|
|
26906
26945
|
if (!currentDeps.historianModel) {
|
|
26907
26946
|
sendCtxStatusMessage(pi, {
|
|
26908
26947
|
title: "/ctx-session-upgrade",
|
|
@@ -26949,6 +26988,7 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
26949
26988
|
timeoutMs: currentDeps.historianTimeoutMs,
|
|
26950
26989
|
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
26951
26990
|
directory: ctx.cwd,
|
|
26991
|
+
allowHomeProject: currentDeps.allowHomeProject,
|
|
26952
26992
|
sessionId,
|
|
26953
26993
|
userMemoriesEnabled: currentDeps.userMemoriesEnabled,
|
|
26954
26994
|
language: currentDeps.language
|
|
@@ -26959,7 +26999,7 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
26959
26999
|
}
|
|
26960
27000
|
};
|
|
26961
27001
|
if (upgradableCount === 0) {
|
|
26962
|
-
const projectPath = resolveProjectIdentityForSession(ctx.cwd);
|
|
27002
|
+
const projectPath = resolveProjectIdentityForSession(ctx.cwd, currentDeps.allowHomeProject);
|
|
26963
27003
|
if (!projectPath)
|
|
26964
27004
|
return;
|
|
26965
27005
|
const migrationPending = migrationEnabled && !isMemoryMigrationDone(currentDeps.db, projectPath);
|
|
@@ -27180,8 +27220,8 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
27180
27220
|
"### Cache TTL",
|
|
27181
27221
|
`- Configured: ${meta.cacheTtl}`,
|
|
27182
27222
|
`- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
|
|
27183
|
-
`- Remaining: ${cacheExpired ? "expired" : `${Math.round(remainingMs / 1000)}s`}`,
|
|
27184
|
-
`- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
|
|
27223
|
+
`- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(remainingMs / 1000)}s`}`,
|
|
27224
|
+
`- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
|
|
27185
27225
|
"",
|
|
27186
27226
|
"### Execute Threshold",
|
|
27187
27227
|
`- Execute threshold: ${formatExecuteThreshold(thresholdDetail, displayContextLimit)}`,
|
|
@@ -27286,7 +27326,7 @@ ${c.content}
|
|
|
27286
27326
|
// package.json
|
|
27287
27327
|
var package_default = {
|
|
27288
27328
|
name: "@cortexkit/pi-magic-context",
|
|
27289
|
-
version: "0.
|
|
27329
|
+
version: "0.34.0",
|
|
27290
27330
|
type: "module",
|
|
27291
27331
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
27292
27332
|
main: "dist/index.js",
|
|
@@ -27312,7 +27352,7 @@ var package_default = {
|
|
|
27312
27352
|
"README.md"
|
|
27313
27353
|
],
|
|
27314
27354
|
scripts: {
|
|
27315
|
-
build: "bun build src/index.ts src/subagent-entry.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external @huggingface/transformers --external node:sqlite",
|
|
27355
|
+
build: "rm -f dist/index.js dist/subagent-entry.js dist/*-*.js && bun build src/index.ts src/subagent-entry.ts --outdir dist --target node --format esm --splitting --external @earendil-works/pi-coding-agent --external @earendil-works/pi-tui --external @huggingface/transformers --external node:sqlite",
|
|
27316
27356
|
typecheck: "tsc --noEmit",
|
|
27317
27357
|
test: "bun test",
|
|
27318
27358
|
lint: "biome check src",
|
|
@@ -27456,7 +27496,7 @@ function renderInner(s, theme, innerWidth) {
|
|
|
27456
27496
|
lines.push(`Upgrade: ${theme.fg("accent", "up to date")}`);
|
|
27457
27497
|
}
|
|
27458
27498
|
lines.push(`Pending drops: ${s.pendingOpsCount}`);
|
|
27459
|
-
lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : `${Math.round(s.cacheRemainingMs / 1000)}s remaining`}`);
|
|
27499
|
+
lines.push(`Cache TTL: ${s.cacheTtl} · last response ${s.lastResponseTime > 0 ? `${Math.round((Date.now() - s.lastResponseTime) / 1000)}s ago` : "never"} · ${s.cacheExpired ? theme.fg("warning", "expired") : s.cacheRemainingMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(s.cacheRemainingMs / 1000)}s remaining`}`);
|
|
27460
27500
|
lines.push("");
|
|
27461
27501
|
lines.push(theme.fg("muted", "Tags"));
|
|
27462
27502
|
lines.push(`Active ${s.activeTags} (~${formatBytes(s.activeBytes)}) · Dropped ${s.droppedTags} · Total ${s.totalTags}`);
|
|
@@ -27498,8 +27538,18 @@ function buildPiStatusDetail(pi, ctx, deps, sessionId) {
|
|
|
27498
27538
|
const usage = ctx.getContextUsage?.();
|
|
27499
27539
|
const meta = getOrCreateSessionMeta(deps.db, sessionId);
|
|
27500
27540
|
const inputTokens = typeof usage?.tokens === "number" ? usage.tokens : meta.lastInputTokens;
|
|
27501
|
-
|
|
27502
|
-
|
|
27541
|
+
let detectedContextLimit;
|
|
27542
|
+
try {
|
|
27543
|
+
const detected = getOverflowState(deps.db, sessionId).detectedContextLimit;
|
|
27544
|
+
if (detected > 0)
|
|
27545
|
+
detectedContextLimit = detected;
|
|
27546
|
+
} catch {}
|
|
27547
|
+
const contextLimit = resolvePiUsableContextLimit({
|
|
27548
|
+
rawContextWindow: usage?.contextWindow ?? ctx.model?.contextWindow,
|
|
27549
|
+
model: ctx.model,
|
|
27550
|
+
detectedContextLimit
|
|
27551
|
+
}) ?? (meta.lastContextPercentage > 0 ? Math.round(inputTokens / (meta.lastContextPercentage / 100)) : 0);
|
|
27552
|
+
const usagePercentage = contextLimit > 0 && inputTokens > 0 ? inputTokens / contextLimit * 100 : meta.lastContextPercentage;
|
|
27503
27553
|
const compartments = getCompartments(deps.db, sessionId);
|
|
27504
27554
|
const metaRow = readSessionMetaRow(deps.db, sessionId);
|
|
27505
27555
|
const memoryBlockCount = Number(metaRow?.memory_block_count ?? 0);
|
|
@@ -27547,9 +27597,15 @@ ${safeStringify(tool.parameters)}`);
|
|
|
27547
27597
|
sessionId
|
|
27548
27598
|
});
|
|
27549
27599
|
const cacheTtl = meta.cacheTtl || "5m";
|
|
27550
|
-
|
|
27600
|
+
let cacheTtlMs;
|
|
27601
|
+
try {
|
|
27602
|
+
cacheTtlMs = parseCacheTtl(cacheTtl);
|
|
27603
|
+
} catch {
|
|
27604
|
+
cacheTtlMs = 5 * 60 * 1000;
|
|
27605
|
+
}
|
|
27606
|
+
const neverExpires = cacheTtlMs === Number.POSITIVE_INFINITY;
|
|
27551
27607
|
const elapsed = meta.lastResponseTime > 0 ? Date.now() - meta.lastResponseTime : 0;
|
|
27552
|
-
const cacheRemainingMs = meta.lastResponseTime > 0 ? Math.max(0, cacheTtlMs - elapsed) : cacheTtlMs;
|
|
27608
|
+
const cacheRemainingMs = neverExpires ? Number.POSITIVE_INFINITY : meta.lastResponseTime > 0 ? Math.max(0, cacheTtlMs - elapsed) : cacheTtlMs;
|
|
27553
27609
|
const cacheExpired = meta.lastResponseTime > 0 && cacheRemainingMs === 0;
|
|
27554
27610
|
const historyBlockTokens = compartmentTokens + factTokens;
|
|
27555
27611
|
const historyBudgetPercentage = deps.historyBudgetPercentage ?? 0.15;
|
|
@@ -27704,22 +27760,6 @@ function readPendingOpsCount(db, sessionId) {
|
|
|
27704
27760
|
return 0;
|
|
27705
27761
|
}
|
|
27706
27762
|
}
|
|
27707
|
-
function parseTtlString(ttl) {
|
|
27708
|
-
const match = ttl.match(/^(\d+)(s|m|h)$/);
|
|
27709
|
-
if (!match)
|
|
27710
|
-
return 5 * 60 * 1000;
|
|
27711
|
-
const val = Number.parseInt(match[1] ?? "5", 10);
|
|
27712
|
-
switch (match[2]) {
|
|
27713
|
-
case "s":
|
|
27714
|
-
return val * 1000;
|
|
27715
|
-
case "m":
|
|
27716
|
-
return val * 60 * 1000;
|
|
27717
|
-
case "h":
|
|
27718
|
-
return val * 3600 * 1000;
|
|
27719
|
-
default:
|
|
27720
|
-
return 5 * 60 * 1000;
|
|
27721
|
-
}
|
|
27722
|
-
}
|
|
27723
27763
|
function safeRead(fn, fallback) {
|
|
27724
27764
|
try {
|
|
27725
27765
|
return fn();
|
|
@@ -27783,7 +27823,18 @@ No active Pi session is available.`,
|
|
|
27783
27823
|
}
|
|
27784
27824
|
const usage = ctx.getContextUsage?.();
|
|
27785
27825
|
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
27786
|
-
|
|
27826
|
+
let detectedContextLimit;
|
|
27827
|
+
try {
|
|
27828
|
+
const detected = getOverflowState(currentDeps.db, sessionId).detectedContextLimit;
|
|
27829
|
+
if (detected > 0)
|
|
27830
|
+
detectedContextLimit = detected;
|
|
27831
|
+
} catch {}
|
|
27832
|
+
const usableContextLimit = resolvePiUsableContextLimit({
|
|
27833
|
+
rawContextWindow: usage?.contextWindow ?? ctx.model?.contextWindow,
|
|
27834
|
+
model: ctx.model,
|
|
27835
|
+
detectedContextLimit
|
|
27836
|
+
});
|
|
27837
|
+
const statusText = executeStatus(currentDeps.db, sessionId, currentDeps.protectedTags ?? 20, currentDeps.executeThresholdPercentage, modelKey, currentDeps.historyBudgetPercentage, currentDeps.commitClusterTrigger, currentDeps.executeThresholdTokens, usableContextLimit);
|
|
27787
27838
|
const details = buildStatusDetails(currentDeps, sessionId);
|
|
27788
27839
|
sendCtxStatusMessage(pi, { title: "/ctx-status", text: statusText, level: "info" }, details);
|
|
27789
27840
|
} catch (error) {
|
|
@@ -27885,6 +27936,14 @@ No active Pi session is available.`,
|
|
|
27885
27936
|
return;
|
|
27886
27937
|
}
|
|
27887
27938
|
const currentDeps = deps.resolveRuntimeDeps?.(ctx) ?? deps;
|
|
27939
|
+
if (currentDeps.compactionOff) {
|
|
27940
|
+
sendCtxStatusMessage(pi, {
|
|
27941
|
+
title: "/ctx-wrapup",
|
|
27942
|
+
text: COMPACTION_OFF_COMMAND_UNAVAILABLE,
|
|
27943
|
+
level: "warning"
|
|
27944
|
+
});
|
|
27945
|
+
return;
|
|
27946
|
+
}
|
|
27888
27947
|
const sessionMeta = getOrCreateSessionMeta(currentDeps.db, sessionId);
|
|
27889
27948
|
if (sessionMeta.isSubagent) {
|
|
27890
27949
|
sendCtxStatusMessage(pi, {
|
|
@@ -27937,7 +27996,7 @@ async function runPiWrapup(pi, deps, ctx, sessionId, messagesToKeep) {
|
|
|
27937
27996
|
const unregister = setRawMessageProvider(sessionId, provider);
|
|
27938
27997
|
let holderId = "";
|
|
27939
27998
|
try {
|
|
27940
|
-
const contextLimit = resolvePiContextLimit(ctx);
|
|
27999
|
+
const contextLimit = resolvePiContextLimit(ctx, deps.db, sessionId);
|
|
27941
28000
|
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
27942
28001
|
const executeThresholdPercentage = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
|
|
27943
28002
|
tokensConfig: deps.executeThresholdTokens,
|
|
@@ -28166,15 +28225,19 @@ Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments.
|
|
|
28166
28225
|
unregister();
|
|
28167
28226
|
}
|
|
28168
28227
|
}
|
|
28169
|
-
function resolvePiContextLimit(ctx) {
|
|
28228
|
+
function resolvePiContextLimit(ctx, db, sessionId) {
|
|
28170
28229
|
const usage = ctx.getContextUsage?.();
|
|
28171
|
-
|
|
28172
|
-
|
|
28173
|
-
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
}
|
|
28177
|
-
return
|
|
28230
|
+
let detectedContextLimit;
|
|
28231
|
+
try {
|
|
28232
|
+
const detected = getOverflowState(db, sessionId).detectedContextLimit;
|
|
28233
|
+
if (detected > 0)
|
|
28234
|
+
detectedContextLimit = detected;
|
|
28235
|
+
} catch {}
|
|
28236
|
+
return resolvePiUsableContextLimit({
|
|
28237
|
+
rawContextWindow: usage?.contextWindow ?? ctx.model?.contextWindow,
|
|
28238
|
+
model: ctx.model,
|
|
28239
|
+
detectedContextLimit
|
|
28240
|
+
}) ?? 128000;
|
|
28178
28241
|
}
|
|
28179
28242
|
async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarker, maxWaitMs) {
|
|
28180
28243
|
const waitStartedAt = Date.now();
|
|
@@ -28194,15 +28257,15 @@ async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarke
|
|
|
28194
28257
|
function estimateChunks(tokens, chunkTokens) {
|
|
28195
28258
|
return Math.max(1, Math.ceil(Math.max(0, tokens) / Math.max(1, chunkTokens)));
|
|
28196
28259
|
}
|
|
28197
|
-
function formatExistingWrapup(
|
|
28198
|
-
if (!
|
|
28260
|
+
function formatExistingWrapup(state2) {
|
|
28261
|
+
if (!state2) {
|
|
28199
28262
|
return `## Magic Wrapup — Skipped
|
|
28200
28263
|
|
|
28201
28264
|
Another /ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`;
|
|
28202
28265
|
}
|
|
28203
28266
|
return `## Magic Wrapup — Skipped
|
|
28204
28267
|
|
|
28205
|
-
Another /ctx-wrapup is already compacting this session (chunk ${
|
|
28268
|
+
Another /ctx-wrapup is already compacting this session (chunk ${state2.chunkIndex}/${Math.max(state2.chunkIndex, state2.expectedChunks)}, wrapped through message ${state2.lastCompartmentEnd}). Wait for it to finish, then try again.`;
|
|
28206
28269
|
}
|
|
28207
28270
|
function readBranchEntries(ctx) {
|
|
28208
28271
|
const getBranch = ctx.sessionManager.getBranch;
|
|
@@ -28326,15 +28389,43 @@ function stripTagPrefixFromAssistantMessage(message) {
|
|
|
28326
28389
|
|
|
28327
28390
|
// src/index.ts
|
|
28328
28391
|
var PREFIX2 = "[magic-context][pi]";
|
|
28329
|
-
|
|
28392
|
+
var PI_ACTIVE_LATCH = Symbol.for("magic-context.pi.active");
|
|
28393
|
+
function isPiMagicContextActiveInProcess() {
|
|
28394
|
+
return globalThis[PI_ACTIVE_LATCH] === true;
|
|
28395
|
+
}
|
|
28396
|
+
function markPiMagicContextActive() {
|
|
28397
|
+
globalThis[PI_ACTIVE_LATCH] = true;
|
|
28398
|
+
}
|
|
28399
|
+
function clearPiMagicContextActive() {
|
|
28400
|
+
try {
|
|
28401
|
+
delete globalThis[PI_ACTIVE_LATCH];
|
|
28402
|
+
} catch {
|
|
28403
|
+
globalThis[PI_ACTIVE_LATCH] = undefined;
|
|
28404
|
+
}
|
|
28405
|
+
}
|
|
28406
|
+
function resolveCurrentProject(ctx, allowHomeProject = false) {
|
|
28330
28407
|
const projectDir = ctx.cwd;
|
|
28331
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDir) ?? "";
|
|
28408
|
+
const projectIdentity = resolveProjectIdentityForSession(projectDir, allowHomeProject) ?? "";
|
|
28332
28409
|
return { projectDir, projectIdentity };
|
|
28333
28410
|
}
|
|
28334
28411
|
function signalPiDeferredCompactionMarkerDrain(sessionId) {
|
|
28335
28412
|
signalPiDeferredHistoryRefresh(sessionId);
|
|
28336
28413
|
signalPiDeferredMaterialization(sessionId);
|
|
28337
28414
|
}
|
|
28415
|
+
async function handlePiSessionBeforeCompact(args) {
|
|
28416
|
+
try {
|
|
28417
|
+
const sessionId = args.ctx.sessionManager?.getSessionId?.();
|
|
28418
|
+
if (typeof sessionId === "string" && sessionId.length > 0) {
|
|
28419
|
+
clearPiM0Cache(args.db, sessionId, "session_before_compact");
|
|
28420
|
+
}
|
|
28421
|
+
} catch {}
|
|
28422
|
+
if (args.compactionOff) {
|
|
28423
|
+
info("session_before_compact: native Pi compaction proceeds (compaction-off mode)");
|
|
28424
|
+
return;
|
|
28425
|
+
}
|
|
28426
|
+
info("session_before_compact: cancelling — magic-context owns compaction");
|
|
28427
|
+
return { cancel: true };
|
|
28428
|
+
}
|
|
28338
28429
|
function persistPiMessageEndModelMeta(args) {
|
|
28339
28430
|
if (!args.message || typeof args.message !== "object")
|
|
28340
28431
|
return;
|
|
@@ -28440,7 +28531,10 @@ var __test = {
|
|
|
28440
28531
|
logPiConfigLoad,
|
|
28441
28532
|
resetLoggedPiConfigDirs() {
|
|
28442
28533
|
loggedPiConfigDirs.clear();
|
|
28443
|
-
}
|
|
28534
|
+
},
|
|
28535
|
+
isPiMagicContextActiveInProcess,
|
|
28536
|
+
markPiMagicContextActive,
|
|
28537
|
+
clearPiMagicContextActive
|
|
28444
28538
|
};
|
|
28445
28539
|
function formatTokens(value) {
|
|
28446
28540
|
return value.toLocaleString();
|
|
@@ -28456,23 +28550,28 @@ function getPiMessageModel(message) {
|
|
|
28456
28550
|
};
|
|
28457
28551
|
}
|
|
28458
28552
|
function resolvePiPressureContextLimit(args) {
|
|
28459
|
-
let
|
|
28553
|
+
let detectedContextLimit;
|
|
28460
28554
|
try {
|
|
28461
28555
|
const overflowState = getOverflowState(args.db, args.sessionId);
|
|
28462
28556
|
if (overflowState.detectedContextLimit > 0) {
|
|
28463
|
-
|
|
28557
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
28464
28558
|
}
|
|
28465
28559
|
} catch (err) {
|
|
28466
28560
|
warn("message_end: getOverflowState failed:", err);
|
|
28467
28561
|
}
|
|
28468
|
-
return
|
|
28562
|
+
return resolvePiUsableContextLimit({
|
|
28563
|
+
rawContextWindow: args.piContextWindow,
|
|
28564
|
+
model: args.model,
|
|
28565
|
+
detectedContextLimit
|
|
28566
|
+
}) ?? 0;
|
|
28469
28567
|
}
|
|
28470
28568
|
async function persistPiPressureFromMessageEnd(args) {
|
|
28471
28569
|
const { provider, model } = getPiMessageModel(args.message);
|
|
28472
28570
|
const effectiveContextLimit = resolvePiPressureContextLimit({
|
|
28473
28571
|
db: args.db,
|
|
28474
28572
|
sessionId: args.sessionId,
|
|
28475
|
-
piContextWindow: args.piContextWindow
|
|
28573
|
+
piContextWindow: args.piContextWindow,
|
|
28574
|
+
model: args.piModel ?? { provider, id: model }
|
|
28476
28575
|
});
|
|
28477
28576
|
const usage = extractAssistantUsage(args.message);
|
|
28478
28577
|
const pressure = computePiPressure(usage, effectiveContextLimit);
|
|
@@ -28499,8 +28598,8 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
28499
28598
|
}
|
|
28500
28599
|
} else if (typeof args.piTokens === "number") {
|
|
28501
28600
|
updates.lastInputTokens = args.piTokens;
|
|
28502
|
-
if (
|
|
28503
|
-
updates.lastContextPercentage = args.piTokens /
|
|
28601
|
+
if (effectiveContextLimit > 0) {
|
|
28602
|
+
updates.lastContextPercentage = args.piTokens / effectiveContextLimit * 100;
|
|
28504
28603
|
}
|
|
28505
28604
|
}
|
|
28506
28605
|
updateSessionMeta(args.db, args.sessionId, updates);
|
|
@@ -28527,7 +28626,8 @@ function resolveSidekickFromConfig(config) {
|
|
|
28527
28626
|
timeoutMs: sidekick.timeout_ms,
|
|
28528
28627
|
thinking_level: sidekick.thinking_level,
|
|
28529
28628
|
fallbackModels: resolveFallbackChain(sidekick.fallback_models),
|
|
28530
|
-
language: config.language
|
|
28629
|
+
language: config.language,
|
|
28630
|
+
allowHomeProject: config.allow_home_project
|
|
28531
28631
|
};
|
|
28532
28632
|
}
|
|
28533
28633
|
function resolveHistorianFromConfig(config) {
|
|
@@ -28557,7 +28657,8 @@ function resolveHistorianFromConfig(config) {
|
|
|
28557
28657
|
memoryEnabled: config.memory.enabled,
|
|
28558
28658
|
autoPromote: config.memory.auto_promote,
|
|
28559
28659
|
userMemoriesEnabled: userMemoryCollectionEnabled(config.dreamer),
|
|
28560
|
-
language: config.language
|
|
28660
|
+
language: config.language,
|
|
28661
|
+
allowHomeProject: config.allow_home_project
|
|
28561
28662
|
};
|
|
28562
28663
|
}
|
|
28563
28664
|
function resolveAutoSearchFromConfig(config) {
|
|
@@ -28577,9 +28678,22 @@ async function src_default(pi) {
|
|
|
28577
28678
|
log(`${PREFIX2} subagent child detected (${MAGIC_CONTEXT_PI_SUBAGENT_ENV}=1); skipping full extension registration`);
|
|
28578
28679
|
return;
|
|
28579
28680
|
}
|
|
28681
|
+
if (isPiMagicContextActiveInProcess()) {
|
|
28682
|
+
log(`${PREFIX2} in-process re-init detected (Magic Context already active in this process); skipping full extension registration`);
|
|
28683
|
+
return;
|
|
28684
|
+
}
|
|
28685
|
+
markPiMagicContextActive();
|
|
28580
28686
|
beginBootQuietPeriod();
|
|
28687
|
+
const bootProjectDir = process.cwd();
|
|
28688
|
+
ensureConfigLocationsMigrated(bootProjectDir);
|
|
28689
|
+
const bootConfig = loadPiConfig({ cwd: bootProjectDir });
|
|
28690
|
+
setStoragePrivatePermissionEnforcement(bootConfig.config.storage.enforce_private_permissions);
|
|
28691
|
+
setSqlitePragmaConfig({
|
|
28692
|
+
cacheSizeMb: bootConfig.config.sqlite.cache_size_mb,
|
|
28693
|
+
mmapSizeMb: bootConfig.config.sqlite.mmap_size_mb
|
|
28694
|
+
});
|
|
28581
28695
|
const storageDir = getMagicContextStorageDir();
|
|
28582
|
-
const dbPath =
|
|
28696
|
+
const dbPath = join5(storageDir, "context.db");
|
|
28583
28697
|
let db;
|
|
28584
28698
|
let openFailureCause = null;
|
|
28585
28699
|
try {
|
|
@@ -28596,16 +28710,26 @@ async function src_default(pi) {
|
|
|
28596
28710
|
info("plugin DISABLED via config (enabled: false) — skipping registration");
|
|
28597
28711
|
return;
|
|
28598
28712
|
}
|
|
28713
|
+
const migration = getMigrationOnOpenRefusal();
|
|
28714
|
+
const blockingProcesses = migration?.serverPids.map((pid) => ({
|
|
28715
|
+
harness: "OpenCode server",
|
|
28716
|
+
pid
|
|
28717
|
+
})) ?? [];
|
|
28599
28718
|
const fence = getSchemaFenceRejection();
|
|
28600
|
-
const reason =
|
|
28719
|
+
const reason = migration && blockingProcesses.length > 0 ? {
|
|
28720
|
+
kind: "migration_guard",
|
|
28721
|
+
persistedVersion: migration.persistedVersion,
|
|
28722
|
+
supportedVersion: migration.supportedVersion,
|
|
28723
|
+
blockingProcesses
|
|
28724
|
+
} : fence ? {
|
|
28601
28725
|
kind: "schema_fence",
|
|
28602
28726
|
persistedVersion: fence.persistedVersion,
|
|
28603
28727
|
supportedVersion: fence.supportedVersion
|
|
28604
28728
|
} : {
|
|
28605
28729
|
kind: "storage_failure",
|
|
28606
|
-
cause: openFailureCause ?? `storage unavailable at ${dbPath} (cache schema newer than this binary, or open failed)`
|
|
28730
|
+
cause: migration?.unreadableFile ? `migration guard could not read RPC discovery file ${migration.unreadableFile}` : openFailureCause ?? `storage unavailable at ${dbPath} (cache schema newer than this binary, or open failed)`
|
|
28607
28731
|
};
|
|
28608
|
-
if (early.config.fail_closed_blocking === false) {
|
|
28732
|
+
if (early.config.fail_closed_blocking === false || !isCompactionEnabled(early.config)) {
|
|
28609
28733
|
warn(`Magic Context (pi) storage unavailable at ${dbPath}: ${formatFailClosedBlockingMessage(reason)}. ` + "fail_closed_blocking=false — degrading silently (hooks not registered).");
|
|
28610
28734
|
return;
|
|
28611
28735
|
}
|
|
@@ -28653,26 +28777,30 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28653
28777
|
})();
|
|
28654
28778
|
}, 0);
|
|
28655
28779
|
const projectDir = process.cwd();
|
|
28656
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDir) ?? "";
|
|
28657
28780
|
const seenDreamerProjectIdentities = new Set;
|
|
28658
|
-
if (projectIdentity)
|
|
28659
|
-
seenDreamerProjectIdentities.add(projectIdentity);
|
|
28660
|
-
try {
|
|
28661
|
-
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
28662
|
-
for (const sid of pendingPiMarkerSessions) {
|
|
28663
|
-
signalPiDeferredCompactionMarkerDrain(sid);
|
|
28664
|
-
}
|
|
28665
|
-
if (pendingPiMarkerSessions.length > 0) {
|
|
28666
|
-
log(`${PREFIX2} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
28667
|
-
}
|
|
28668
|
-
} catch (err) {
|
|
28669
|
-
warn(`Magic Context (pi) failed to rehydrate deferred Pi compaction markers: ${err instanceof Error ? err.message : String(err)}`);
|
|
28670
|
-
}
|
|
28671
|
-
info(`loaded v${PLUGIN_VERSION} | harness=pi | db=${dbPath} | ` + `project=${projectIdentity} | dir=${projectDir}`);
|
|
28672
28781
|
ensureConfigLocationsMigrated(projectDir);
|
|
28673
28782
|
const { config, warnings, loadedFromPaths } = loadPiConfig({
|
|
28674
28783
|
cwd: projectDir
|
|
28675
28784
|
});
|
|
28785
|
+
const projectIdentity = resolveProjectIdentityForSession(projectDir, config.allow_home_project) ?? "";
|
|
28786
|
+
if (projectIdentity)
|
|
28787
|
+
seenDreamerProjectIdentities.add(projectIdentity);
|
|
28788
|
+
info(`loaded v${PLUGIN_VERSION} | harness=pi | db=${dbPath} | ` + `project=${projectIdentity} | dir=${projectDir}`);
|
|
28789
|
+
const compactionOff = !isCompactionEnabled(config);
|
|
28790
|
+
setCtxReduceRegisteredGlobally(!compactionOff);
|
|
28791
|
+
if (!compactionOff) {
|
|
28792
|
+
try {
|
|
28793
|
+
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
28794
|
+
for (const sid of pendingPiMarkerSessions) {
|
|
28795
|
+
signalPiDeferredCompactionMarkerDrain(sid);
|
|
28796
|
+
}
|
|
28797
|
+
if (pendingPiMarkerSessions.length > 0) {
|
|
28798
|
+
log(`${PREFIX2} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
28799
|
+
}
|
|
28800
|
+
} catch (err) {
|
|
28801
|
+
warn(`Magic Context (pi) failed to rehydrate deferred Pi compaction markers: ${err instanceof Error ? err.message : String(err)}`);
|
|
28802
|
+
}
|
|
28803
|
+
}
|
|
28676
28804
|
configurePiSubagentExtensions(config.pi?.subagent_extensions);
|
|
28677
28805
|
logPiConfigLoad({
|
|
28678
28806
|
dir: projectDir,
|
|
@@ -28680,6 +28808,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28680
28808
|
warnings,
|
|
28681
28809
|
dedupe: true
|
|
28682
28810
|
});
|
|
28811
|
+
setStoragePrivatePermissionEnforcement(config.storage.enforce_private_permissions);
|
|
28683
28812
|
setSqlitePragmaConfig({
|
|
28684
28813
|
cacheSizeMb: config.sqlite.cache_size_mb,
|
|
28685
28814
|
mmapSizeMb: config.sqlite.mmap_size_mb
|
|
@@ -28719,6 +28848,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28719
28848
|
language: cfg.language,
|
|
28720
28849
|
autoSearch: auto,
|
|
28721
28850
|
resolveForProject: resolveContextOptionsForProject,
|
|
28851
|
+
compactionOff,
|
|
28852
|
+
allowHomeProject: cfg.allow_home_project,
|
|
28722
28853
|
maybeAutoEmbedSession: (sessionId, dir, identity) => {
|
|
28723
28854
|
maybeAutoEmbedPiSession({
|
|
28724
28855
|
db: database,
|
|
@@ -28740,7 +28871,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28740
28871
|
hist.onStatusChange = (ctx) => {
|
|
28741
28872
|
updateStatusLine(ctx, {
|
|
28742
28873
|
db: database,
|
|
28743
|
-
projectIdentity: resolveCurrentProject(ctx).projectIdentity ?? ""
|
|
28874
|
+
projectIdentity: resolveCurrentProject(ctx, cfg.allow_home_project).projectIdentity ?? ""
|
|
28744
28875
|
});
|
|
28745
28876
|
};
|
|
28746
28877
|
}
|
|
@@ -28770,14 +28901,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28770
28901
|
dedupe: true
|
|
28771
28902
|
});
|
|
28772
28903
|
const switchedConfig = switchedLoad.config;
|
|
28773
|
-
const switchedIdentity = identityOverride ?? resolveProjectIdentityForSession(dir) ?? "";
|
|
28904
|
+
const switchedIdentity = identityOverride ?? resolveProjectIdentityForSession(dir, switchedConfig.allow_home_project) ?? "";
|
|
28774
28905
|
const built = buildProjectDeps(dir, switchedIdentity, switchedConfig);
|
|
28775
28906
|
projectDepsByDir.set(dir, built);
|
|
28776
28907
|
return built;
|
|
28777
28908
|
}
|
|
28778
28909
|
function resolveCurrentProjectDeps(ctx) {
|
|
28779
|
-
|
|
28780
|
-
return resolveProjectDepsForDir(currentProject.projectDir, currentProject.projectIdentity);
|
|
28910
|
+
return resolveProjectDepsForDir(ctx.cwd);
|
|
28781
28911
|
}
|
|
28782
28912
|
function resolveContextOptionsForProject(dir) {
|
|
28783
28913
|
return resolveProjectDepsForDir(dir).contextOptions;
|
|
@@ -28793,11 +28923,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28793
28923
|
memoryToolEnabled: true,
|
|
28794
28924
|
protectedTags: config.protected_tags ?? 20,
|
|
28795
28925
|
resolveProtectedTags: (ctx) => resolveCurrentProjectDeps(ctx).config.protected_tags ?? 20,
|
|
28926
|
+
resolveProjectIdentity: (ctx) => resolveCurrentProjectDeps(ctx).projectIdentity,
|
|
28796
28927
|
dreamerEnabled: isDreamerRunnable(config),
|
|
28797
28928
|
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
28798
|
-
todowriteEnabled
|
|
28929
|
+
todowriteEnabled,
|
|
28930
|
+
compactionOff
|
|
28799
28931
|
});
|
|
28800
|
-
info(todowriteEnabled ? "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, todowrite, ctx_reduce; registered /todos" : "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce (todowrite disabled)");
|
|
28932
|
+
info(compactionOff ? todowriteEnabled ? "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, todowrite; registered /todos (ctx_reduce unavailable in compaction-off mode)" : "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand (ctx_reduce unavailable in compaction-off mode; todowrite disabled)" : todowriteEnabled ? "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, todowrite, ctx_reduce; registered /todos" : "registered tools: ctx_search, ctx_memory, ctx_note, ctx_expand, ctx_reduce (todowrite disabled)");
|
|
28801
28933
|
pi.on("session_start", async (event, ctx) => {
|
|
28802
28934
|
await handlePiCloneSessionStart(event, ctx, {
|
|
28803
28935
|
db,
|
|
@@ -28841,7 +28973,6 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28841
28973
|
return {
|
|
28842
28974
|
db,
|
|
28843
28975
|
projectIdentity: current.projectIdentity,
|
|
28844
|
-
resolveProject: resolveCurrentProject,
|
|
28845
28976
|
protectedTags: current.config.protected_tags,
|
|
28846
28977
|
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
28847
28978
|
historyBudgetPercentage: current.config.history_budget_percentage,
|
|
@@ -28858,7 +28989,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28858
28989
|
info("registered /ctx-status");
|
|
28859
28990
|
registerStatusLine(pi, { db, projectIdentity });
|
|
28860
28991
|
info("registered magic-context status line");
|
|
28861
|
-
registerCtxFlushCommand(pi, { db });
|
|
28992
|
+
registerCtxFlushCommand(pi, { db, compactionOff });
|
|
28862
28993
|
info("registered /ctx-flush");
|
|
28863
28994
|
registerCtxRecompCommand(pi, {
|
|
28864
28995
|
db,
|
|
@@ -28871,6 +29002,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28871
29002
|
language: bootProjectDeps.config.language,
|
|
28872
29003
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28873
29004
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29005
|
+
compactionOff,
|
|
28874
29006
|
resolveRuntimeDeps: (ctx) => {
|
|
28875
29007
|
const current = resolveCurrentProjectDeps(ctx);
|
|
28876
29008
|
return {
|
|
@@ -28883,7 +29015,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28883
29015
|
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
28884
29016
|
language: current.config.language,
|
|
28885
29017
|
memoryEnabled: current.config.memory.enabled,
|
|
28886
|
-
autoPromote: current.config.memory.auto_promote
|
|
29018
|
+
autoPromote: current.config.memory.auto_promote,
|
|
29019
|
+
compactionOff
|
|
28887
29020
|
};
|
|
28888
29021
|
}
|
|
28889
29022
|
});
|
|
@@ -28899,6 +29032,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28899
29032
|
language: bootProjectDeps.config.language,
|
|
28900
29033
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28901
29034
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29035
|
+
compactionOff,
|
|
28902
29036
|
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
28903
29037
|
executeThresholdPercentage: bootProjectDeps.config.execute_threshold_percentage,
|
|
28904
29038
|
executeThresholdTokens: bootProjectDeps.config.execute_threshold_tokens,
|
|
@@ -28915,6 +29049,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28915
29049
|
language: current.config.language,
|
|
28916
29050
|
memoryEnabled: current.config.memory.enabled,
|
|
28917
29051
|
autoPromote: current.config.memory.auto_promote,
|
|
29052
|
+
compactionOff,
|
|
28918
29053
|
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer),
|
|
28919
29054
|
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
28920
29055
|
executeThresholdTokens: current.config.execute_threshold_tokens
|
|
@@ -28932,7 +29067,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28932
29067
|
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
28933
29068
|
language: bootProjectDeps.config.language,
|
|
28934
29069
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
29070
|
+
allowHomeProject: bootProjectDeps.config.allow_home_project,
|
|
28935
29071
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29072
|
+
compactionOff,
|
|
28936
29073
|
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
28937
29074
|
resolveRuntimeDeps: (ctx) => {
|
|
28938
29075
|
const current = resolveCurrentProjectDeps(ctx);
|
|
@@ -28946,7 +29083,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28946
29083
|
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
28947
29084
|
language: current.config.language,
|
|
28948
29085
|
memoryEnabled: current.config.memory.enabled,
|
|
29086
|
+
allowHomeProject: current.config.allow_home_project,
|
|
28949
29087
|
autoPromote: current.config.memory.auto_promote,
|
|
29088
|
+
compactionOff,
|
|
28950
29089
|
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer)
|
|
28951
29090
|
};
|
|
28952
29091
|
}
|
|
@@ -28956,7 +29095,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28956
29095
|
db,
|
|
28957
29096
|
projectDir,
|
|
28958
29097
|
projectIdentity,
|
|
28959
|
-
resolveProject:
|
|
29098
|
+
resolveProject: (ctx) => {
|
|
29099
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
29100
|
+
return {
|
|
29101
|
+
projectDir: current.projectDir,
|
|
29102
|
+
projectIdentity: current.projectIdentity
|
|
29103
|
+
};
|
|
29104
|
+
},
|
|
28960
29105
|
dreamerEnabled: bootProjectDeps.dreamerEnabled,
|
|
28961
29106
|
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
28962
29107
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity)
|
|
@@ -28968,7 +29113,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28968
29113
|
projectIdentity,
|
|
28969
29114
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28970
29115
|
resolveMemoryEnabled: (ctx) => resolveCurrentProjectDeps(ctx).config.memory.enabled,
|
|
28971
|
-
resolveProject:
|
|
29116
|
+
resolveProject: (ctx) => {
|
|
29117
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
29118
|
+
return {
|
|
29119
|
+
projectDir: current.projectDir,
|
|
29120
|
+
projectIdentity: current.projectIdentity
|
|
29121
|
+
};
|
|
29122
|
+
}
|
|
28972
29123
|
});
|
|
28973
29124
|
info("registered /ctx-embed");
|
|
28974
29125
|
const dreamerConfig = bootProjectDeps.dreamerConfig;
|
|
@@ -29057,11 +29208,11 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
29057
29208
|
try {
|
|
29058
29209
|
const smForDrain = sm;
|
|
29059
29210
|
const canDrain = typeof smForDrain.appendCompaction === "function" && typeof smForDrain.getBranch === "function";
|
|
29060
|
-
if (canDrain && getPendingPiCompactionMarkerState(db, sessionId)) {
|
|
29211
|
+
if (!compactionOff && canDrain && getPendingPiCompactionMarkerState(db, sessionId)) {
|
|
29061
29212
|
signalPiDeferredCompactionMarkerDrain(sessionId);
|
|
29062
29213
|
}
|
|
29063
29214
|
} catch {}
|
|
29064
|
-
if (ctx.hasUI && effectiveProjectDeps.historianConfig?.model) {
|
|
29215
|
+
if (!compactionOff && ctx.hasUI && effectiveProjectDeps.historianConfig?.model) {
|
|
29065
29216
|
maybeSendUpgradeReminder({
|
|
29066
29217
|
client: null,
|
|
29067
29218
|
db,
|
|
@@ -29089,7 +29240,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
29089
29240
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
29090
29241
|
includeGuidance: true,
|
|
29091
29242
|
protectedTags: effectiveConfig.protected_tags,
|
|
29092
|
-
ctxReduceCallable:
|
|
29243
|
+
ctxReduceCallable: !compactionOff,
|
|
29093
29244
|
dreamerEnabled: effectiveProjectDeps.dreamerEnabled,
|
|
29094
29245
|
temporalAwarenessEnabled: effectiveConfig.temporal_awareness ?? false,
|
|
29095
29246
|
cavemanTextCompressionEnabled: effectiveConfig.caveman_text_compression?.enabled === true,
|
|
@@ -29134,7 +29285,7 @@ ${block}` : event.systemPrompt;
|
|
|
29134
29285
|
const lastAssistant = Array.isArray(msgs) ? [...msgs].reverse().find((m) => m?.role === "assistant") : undefined;
|
|
29135
29286
|
if (lastAssistant?.stopReason === "stop") {
|
|
29136
29287
|
const sessionId = ctx.sessionManager?.getSessionId?.();
|
|
29137
|
-
if (sessionId && db)
|
|
29288
|
+
if (sessionId && db && !compactionOff)
|
|
29138
29289
|
maybeDeliverChannel2Pi(pi, db, sessionId);
|
|
29139
29290
|
}
|
|
29140
29291
|
} catch (err) {
|
|
@@ -29159,7 +29310,7 @@ ${block}` : event.systemPrompt;
|
|
|
29159
29310
|
toolCallId
|
|
29160
29311
|
});
|
|
29161
29312
|
if (Array.isArray(todos) && todos.length > 0 && todos.every((t) => t.status === "completed" || t.status === "cancelled")) {
|
|
29162
|
-
if (sessionMeta && !sessionMeta.isSubagent) {
|
|
29313
|
+
if (!compactionOff && sessionMeta && !sessionMeta.isSubagent) {
|
|
29163
29314
|
onNoteTrigger(db, sessionId, "todos_complete");
|
|
29164
29315
|
}
|
|
29165
29316
|
}
|
|
@@ -29175,7 +29326,7 @@ ${block}` : event.systemPrompt;
|
|
|
29175
29326
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
29176
29327
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
29177
29328
|
return;
|
|
29178
|
-
if (event.toolName === "ctx_reduce") {
|
|
29329
|
+
if (!compactionOff && event.toolName === "ctx_reduce") {
|
|
29179
29330
|
markPiChannel1Reduced(sessionId, db);
|
|
29180
29331
|
}
|
|
29181
29332
|
} catch (err) {
|
|
@@ -29187,6 +29338,8 @@ ${block}` : event.systemPrompt;
|
|
|
29187
29338
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
29188
29339
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
29189
29340
|
return;
|
|
29341
|
+
if (compactionOff)
|
|
29342
|
+
return;
|
|
29190
29343
|
if (db)
|
|
29191
29344
|
maybeDeliverChannel2Pi(pi, db, sessionId, "steer");
|
|
29192
29345
|
const block = maybeChannel1ReminderForToolResult({
|
|
@@ -29202,20 +29355,11 @@ ${block}` : event.systemPrompt;
|
|
|
29202
29355
|
log(`tool_result hook failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
29203
29356
|
}
|
|
29204
29357
|
});
|
|
29205
|
-
pi.on("session_before_compact", async (_event, ctx) => {
|
|
29206
|
-
try {
|
|
29207
|
-
const sessionId = ctx.sessionManager?.getSessionId?.();
|
|
29208
|
-
if (typeof sessionId === "string" && sessionId.length > 0) {
|
|
29209
|
-
clearPiM0Cache(db, sessionId, "session_before_compact");
|
|
29210
|
-
}
|
|
29211
|
-
} catch {}
|
|
29212
|
-
info("session_before_compact: cancelling — magic-context owns compaction");
|
|
29213
|
-
return { cancel: true };
|
|
29214
|
-
});
|
|
29358
|
+
pi.on("session_before_compact", async (_event, ctx) => handlePiSessionBeforeCompact({ db, compactionOff, ctx }));
|
|
29215
29359
|
pi.on("message_end", async (event, ctx) => {
|
|
29216
29360
|
try {
|
|
29217
29361
|
const msg = event.message;
|
|
29218
|
-
if (msg !== null && typeof msg === "object") {
|
|
29362
|
+
if (!compactionOff && msg !== null && typeof msg === "object") {
|
|
29219
29363
|
stripTagPrefixFromAssistantMessage(msg);
|
|
29220
29364
|
}
|
|
29221
29365
|
} catch (err) {
|
|
@@ -29247,6 +29391,7 @@ ${block}` : event.systemPrompt;
|
|
|
29247
29391
|
sessionId,
|
|
29248
29392
|
message: event.message,
|
|
29249
29393
|
piContextWindow,
|
|
29394
|
+
piModel: ctx.model,
|
|
29250
29395
|
piTokens: piUsage && typeof piUsage.tokens === "number" ? piUsage.tokens : undefined,
|
|
29251
29396
|
notifyIssue: async (message) => {
|
|
29252
29397
|
const uiNotify = ctx.ui?.notify;
|
|
@@ -29276,6 +29421,8 @@ ${block}` : event.systemPrompt;
|
|
|
29276
29421
|
warn("message_end: persist session_meta usage failed:", err);
|
|
29277
29422
|
}
|
|
29278
29423
|
try {
|
|
29424
|
+
if (compactionOff)
|
|
29425
|
+
return;
|
|
29279
29426
|
const sm = ctx.sessionManager;
|
|
29280
29427
|
const sessionId = sm?.getSessionId?.();
|
|
29281
29428
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
@@ -29293,8 +29440,8 @@ ${block}` : event.systemPrompt;
|
|
|
29293
29440
|
if (!detection.isOverflow)
|
|
29294
29441
|
return;
|
|
29295
29442
|
const modelKey = typeof msg.provider === "string" && typeof msg.model === "string" && msg.provider.length > 0 && msg.model.length > 0 ? `${msg.provider}/${msg.model}` : undefined;
|
|
29296
|
-
recordOverflowDetected(db, sessionId, detection.reportedLimit, modelKey);
|
|
29297
|
-
log(`[magic-context][${sessionId}] overflow detected: reportedLimit=${detection.reportedLimit ?? "?"} pattern=${detection.matchedPattern ?? "?"}`);
|
|
29443
|
+
recordOverflowDetected(db, sessionId, detection.reportedLimit, modelKey, "provider_overflow", detection.reportedLimitProvenance);
|
|
29444
|
+
log(`[magic-context][${sessionId}] overflow detected: reportedLimit=${detection.reportedLimit ?? "?"} provenance=${detection.reportedLimitProvenance ?? "?"} pattern=${detection.matchedPattern ?? "?"}`);
|
|
29298
29445
|
} catch (err) {
|
|
29299
29446
|
warn("message_end: overflow detection failed:", err);
|
|
29300
29447
|
}
|
|
@@ -29331,6 +29478,7 @@ ${block}` : event.systemPrompt;
|
|
|
29331
29478
|
clearContextHandlerSession(sessionId);
|
|
29332
29479
|
}
|
|
29333
29480
|
} catch {}
|
|
29481
|
+
clearPiMagicContextActive();
|
|
29334
29482
|
});
|
|
29335
29483
|
pi.on("session_before_switch", (_event, ctx) => {
|
|
29336
29484
|
try {
|
|
@@ -29359,6 +29507,7 @@ export {
|
|
|
29359
29507
|
resolveDreamerFromConfig,
|
|
29360
29508
|
persistPiPressureFromMessageEnd,
|
|
29361
29509
|
persistPiMessageEndModelMeta,
|
|
29510
|
+
handlePiSessionBeforeCompact,
|
|
29362
29511
|
src_default as default,
|
|
29363
29512
|
capturePiTodowriteMessageIfCompatible,
|
|
29364
29513
|
capturePiTodowriteArgsIfCompatible,
|