@cortexkit/pi-magic-context 0.33.1 → 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-e3kftg52.js → index-0k3j1tc3.js} +714 -170
- package/dist/{rpc-notifications-td0amw6w.js → index-hw34xmzk.js} +2 -10
- package/dist/index.js +1154 -553
- 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,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AGE_RECLAIM_MIN_TOKENS,
|
|
3
|
+
BoundedSessionMap,
|
|
4
|
+
COMPACTION_ENABLED_PATH,
|
|
3
5
|
COMPARTMENT_LEASE_RENEWAL_MS,
|
|
4
6
|
COMPARTMENT_RENDER_EPOCH,
|
|
5
7
|
DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
|
|
@@ -10,6 +12,8 @@ import {
|
|
|
10
12
|
Database,
|
|
11
13
|
GIT_SWEEP_LEASE_RENEWAL_MS,
|
|
12
14
|
GLOBAL_USER_PROFILE_PROJECT_PATH,
|
|
15
|
+
LATEST_SUPPORTED_VERSION,
|
|
16
|
+
MAX_EXECUTE_THRESHOLD,
|
|
13
17
|
PRIMER_CANDIDATE_MAX_AGE_MS,
|
|
14
18
|
PRIMER_CANDIDATE_TTL_MS,
|
|
15
19
|
ProjectIdentityError,
|
|
@@ -57,6 +61,7 @@ import {
|
|
|
57
61
|
clearInjectionCache,
|
|
58
62
|
clearMemoryVerifications,
|
|
59
63
|
clearPendingCompactionMarkerStateIf,
|
|
64
|
+
clearPendingOps,
|
|
60
65
|
clearPendingPiCompactionMarkerStateIf,
|
|
61
66
|
clearPersistedReasoningWatermark,
|
|
62
67
|
clearPersistedTodoSyntheticAnchor,
|
|
@@ -89,6 +94,7 @@ import {
|
|
|
89
94
|
encodeCachedM0UpgradeIdentity,
|
|
90
95
|
enqueueShadowEmbeddingItems,
|
|
91
96
|
ensureProjectRegisteredFromPiDirectory,
|
|
97
|
+
escalationBands,
|
|
92
98
|
escapeXmlAttr,
|
|
93
99
|
escapeXmlContent,
|
|
94
100
|
estimateTokens,
|
|
@@ -109,6 +115,7 @@ import {
|
|
|
109
115
|
getAutoSearchHintDecisions,
|
|
110
116
|
getCachedAbsoluteMessageCount,
|
|
111
117
|
getChannel2NudgeState,
|
|
118
|
+
getCompactionModeRecord,
|
|
112
119
|
getCompartments,
|
|
113
120
|
getCompartmentsByEndMessageId,
|
|
114
121
|
getContextStoreUuid,
|
|
@@ -141,6 +148,7 @@ import {
|
|
|
141
148
|
getMemoryVerifications,
|
|
142
149
|
getMessageIndexReconciliationStartOrdinal,
|
|
143
150
|
getMessageIndexSourceIdentity,
|
|
151
|
+
getMigrationOnOpenRefusal,
|
|
144
152
|
getModuleNoteEvaluationBridge,
|
|
145
153
|
getMuralCueState,
|
|
146
154
|
getNoteLastReadAt,
|
|
@@ -156,6 +164,7 @@ import {
|
|
|
156
164
|
getPendingPiCompactionMarkerState,
|
|
157
165
|
getPendingSmartNotes,
|
|
158
166
|
getPersistedNoteNudge,
|
|
167
|
+
getPersistedSchemaVersion,
|
|
159
168
|
getPersistedTodoSyntheticAnchor,
|
|
160
169
|
getPersistedToolTagAccounting,
|
|
161
170
|
getPrimerCandidatesByIds,
|
|
@@ -203,11 +212,13 @@ import {
|
|
|
203
212
|
insertUserMemory,
|
|
204
213
|
insertUserMemoryCandidates,
|
|
205
214
|
invalidateMemory,
|
|
215
|
+
isCompactionEnabled,
|
|
206
216
|
isCompartmentLeaseHeld,
|
|
207
217
|
isDreamerRunnable,
|
|
208
218
|
isEditTool,
|
|
209
219
|
isMessageIndexReconciledThrough,
|
|
210
220
|
isMessageIndexSourceCurrent,
|
|
221
|
+
isMidTurn,
|
|
211
222
|
isMidTurnPi,
|
|
212
223
|
isRecord,
|
|
213
224
|
isSaneLimit,
|
|
@@ -282,7 +293,9 @@ import {
|
|
|
282
293
|
reserveProtectedTailDrainTokens,
|
|
283
294
|
resetLastNudgeCycle,
|
|
284
295
|
resetLastNudgeCycleIfTailShrank,
|
|
296
|
+
resolveCompactionModeRecord,
|
|
285
297
|
resolveGitTopLevel,
|
|
298
|
+
resolveLimit,
|
|
286
299
|
resolveModelRefForPi,
|
|
287
300
|
resolveMuralWire,
|
|
288
301
|
resolvePiStableId,
|
|
@@ -298,6 +311,7 @@ import {
|
|
|
298
311
|
saveSourceContent,
|
|
299
312
|
scheduleAfterBootQuiet,
|
|
300
313
|
setChannel2NudgeState,
|
|
314
|
+
setCompactionModeRecord,
|
|
301
315
|
setDeferredExecutePendingIfAbsent,
|
|
302
316
|
setEmergencyDropSample,
|
|
303
317
|
setLastNudgeLevel,
|
|
@@ -312,6 +326,7 @@ import {
|
|
|
312
326
|
setRecompPartialRange,
|
|
313
327
|
setSessionWorkMetrics,
|
|
314
328
|
setSqlitePragmaConfig,
|
|
329
|
+
setStoragePrivatePermissionEnforcement,
|
|
315
330
|
setTodoSnapshot,
|
|
316
331
|
sourceNameForMemory,
|
|
317
332
|
stableStringify,
|
|
@@ -346,7 +361,10 @@ import {
|
|
|
346
361
|
withMigrationLanguageDirective,
|
|
347
362
|
withRawMessageProvider,
|
|
348
363
|
withRawSessionMessageCache
|
|
349
|
-
} from "./index-
|
|
364
|
+
} from "./index-0k3j1tc3.js";
|
|
365
|
+
import {
|
|
366
|
+
pushNotification
|
|
367
|
+
} from "./index-hw34xmzk.js";
|
|
350
368
|
import {
|
|
351
369
|
ensureCortexKitArtifactGitignore,
|
|
352
370
|
getHarness,
|
|
@@ -528,14 +546,41 @@ function isMagicContextHiddenAgentName(agent) {
|
|
|
528
546
|
return true;
|
|
529
547
|
return false;
|
|
530
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
|
+
}
|
|
531
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
|
+
}
|
|
532
581
|
if (reason.kind === "schema_fence") {
|
|
533
582
|
return [
|
|
534
|
-
`Magic Context cannot operate:
|
|
535
|
-
`is newer than this build supports (max v${reason.supportedVersion}).`,
|
|
536
|
-
"A newer OpenCode/Pi instance upgraded the database; this build fail-closed",
|
|
537
|
-
"so it cannot corrupt the cache or silently fall back to native compaction.",
|
|
538
|
-
`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}).`,
|
|
539
584
|
`Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
|
|
540
585
|
].join(" ");
|
|
541
586
|
}
|
|
@@ -596,7 +641,7 @@ function createFailClosedController(options) {
|
|
|
596
641
|
const shouldReprobe = typeof input.tryReopen === "function" && (blockedPassCount === 1 || blockedPassCount % reprobeEveryN === 0);
|
|
597
642
|
if (shouldReprobe) {
|
|
598
643
|
try {
|
|
599
|
-
const healed = await input.tryReopen();
|
|
644
|
+
const healed = await input.tryReopen?.();
|
|
600
645
|
if (healed) {
|
|
601
646
|
reason = null;
|
|
602
647
|
blockedPassCount = 0;
|
|
@@ -779,6 +824,7 @@ var OVERFLOW_PATTERNS = [
|
|
|
779
824
|
/maximum prompt length is \d+/i,
|
|
780
825
|
/reduce the length of the messages/i,
|
|
781
826
|
/maximum context length is \d+ tokens/i,
|
|
827
|
+
/maximum model length is \d+/i,
|
|
782
828
|
/exceeds the limit of \d+/i,
|
|
783
829
|
/exceeds the available context size/i,
|
|
784
830
|
/greater than the context length/i,
|
|
@@ -794,15 +840,25 @@ var OVERFLOW_PATTERNS = [
|
|
|
794
840
|
/context size has been exceeded/i
|
|
795
841
|
];
|
|
796
842
|
var LIMIT_EXTRACTION_PATTERNS = [
|
|
797
|
-
/maximum prompt length is (\d+)/i,
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
/
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
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" }
|
|
806
862
|
];
|
|
807
863
|
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
808
864
|
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
@@ -853,14 +909,15 @@ function detectOverflow(error) {
|
|
|
853
909
|
const reportedLimit = parseReportedLimit(message);
|
|
854
910
|
return {
|
|
855
911
|
isOverflow: true,
|
|
856
|
-
reportedLimit,
|
|
912
|
+
reportedLimit: reportedLimit?.value,
|
|
913
|
+
reportedLimitProvenance: reportedLimit?.provenance,
|
|
857
914
|
matchedPattern: matched?.source
|
|
858
915
|
};
|
|
859
916
|
}
|
|
860
917
|
function parseReportedLimit(message) {
|
|
861
918
|
if (!message)
|
|
862
919
|
return;
|
|
863
|
-
for (const pattern of LIMIT_EXTRACTION_PATTERNS) {
|
|
920
|
+
for (const { pattern, provenance } of LIMIT_EXTRACTION_PATTERNS) {
|
|
864
921
|
const match = message.match(pattern);
|
|
865
922
|
if (!match)
|
|
866
923
|
continue;
|
|
@@ -872,7 +929,7 @@ function parseReportedLimit(message) {
|
|
|
872
929
|
continue;
|
|
873
930
|
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
874
931
|
continue;
|
|
875
|
-
return value;
|
|
932
|
+
return { value, provenance };
|
|
876
933
|
}
|
|
877
934
|
return;
|
|
878
935
|
}
|
|
@@ -1354,6 +1411,15 @@ async function runDeferredV22Backfill(db, options = {}) {
|
|
|
1354
1411
|
};
|
|
1355
1412
|
}
|
|
1356
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
|
+
|
|
1357
1423
|
// ../plugin/src/hooks/magic-context/derive-budgets.ts
|
|
1358
1424
|
var TRIGGER_BUDGET_PERCENTAGE = 0.05;
|
|
1359
1425
|
var TRIGGER_BUDGET_MIN = 5000;
|
|
@@ -1397,7 +1463,6 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
1397
1463
|
|
|
1398
1464
|
// ../plugin/src/hooks/magic-context/event-resolvers.ts
|
|
1399
1465
|
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
1400
|
-
var MAX_EXECUTE_THRESHOLD = 80;
|
|
1401
1466
|
function resolveCacheTtl(cacheTtl, modelKey) {
|
|
1402
1467
|
if (typeof cacheTtl === "string") {
|
|
1403
1468
|
return cacheTtl;
|
|
@@ -1442,7 +1507,7 @@ function resolveExecuteThresholdDetail(config, modelKey, fallback, options) {
|
|
|
1442
1507
|
const dedupeKey = `${options.sessionId ?? "__global__"}|${modelKey ?? "__default__"}|${tokenMatch.value}|${cap}`;
|
|
1443
1508
|
if (!clampWarnSeen.has(dedupeKey)) {
|
|
1444
1509
|
clampWarnSeen.add(dedupeKey);
|
|
1445
|
-
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"}`;
|
|
1446
1511
|
if (options.sessionId) {
|
|
1447
1512
|
sessionLog(options.sessionId, `WARN: ${msg}`);
|
|
1448
1513
|
} else {
|
|
@@ -1498,7 +1563,7 @@ function resolveExecuteThresholdDetail(config, modelKey, fallback, options) {
|
|
|
1498
1563
|
const dedupeKey = `pct|${options?.sessionId ?? "__global__"}|${modelKey ?? "__default__"}|${resolved}`;
|
|
1499
1564
|
if (!clampWarnSeen.has(dedupeKey)) {
|
|
1500
1565
|
clampWarnSeen.add(dedupeKey);
|
|
1501
|
-
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)`;
|
|
1502
1567
|
if (options?.sessionId) {
|
|
1503
1568
|
sessionLog(options.sessionId, `WARN: ${msg}`);
|
|
1504
1569
|
} else {
|
|
@@ -1990,6 +2055,57 @@ import {
|
|
|
1990
2055
|
import { createInterface } from "node:readline";
|
|
1991
2056
|
import { fileURLToPath } from "node:url";
|
|
1992
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
|
+
|
|
1993
2109
|
// ../plugin/src/features/magic-context/subagent-token-capture.ts
|
|
1994
2110
|
function asNumber(value) {
|
|
1995
2111
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -2338,6 +2454,10 @@ class PiSubagentRunner {
|
|
|
2338
2454
|
if (ZERO_TOOL_PROMPT_REQUIRED_AGENTS.has(options.agent) && options.systemPrompt.trim().length === 0) {
|
|
2339
2455
|
return failBeforeSpawn("invalid_prompt", `zero-tool Pi subagent "${options.agent}" requires a non-empty system prompt`, true);
|
|
2340
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
|
+
}
|
|
2341
2461
|
const promptBytes = Buffer.byteLength(options.userMessage, "utf8");
|
|
2342
2462
|
const deliverViaStdin = promptBytes > PROMPT_ARGV_MAX_BYTES || this.platform === "win32";
|
|
2343
2463
|
let systemPromptTempDir;
|
|
@@ -2909,7 +3029,7 @@ function registerCtxAugCommand(pi, config) {
|
|
|
2909
3029
|
sessionLog(sessionLabel, "/ctx-aug: spawning sidekick", {
|
|
2910
3030
|
model: currentConfig.model
|
|
2911
3031
|
});
|
|
2912
|
-
const projectIdentity = resolveProjectIdentityForSession(ctx.cwd);
|
|
3032
|
+
const projectIdentity = resolveProjectIdentityForSession(ctx.cwd, currentConfig.allowHomeProject);
|
|
2913
3033
|
if (!projectIdentity) {
|
|
2914
3034
|
sessionLog(sessionLabel, "Error: Could not resolve project identity for sidekick.");
|
|
2915
3035
|
return;
|
|
@@ -2982,6 +3102,201 @@ var DREAMER_MEMORY_MAPPER_AGENT = "dreamer-memory-mapper";
|
|
|
2982
3102
|
var DREAMER_CLASSIFIER_AGENT = "dreamer-classifier";
|
|
2983
3103
|
var DREAMER_DOCS_AGENT = "dreamer-docs";
|
|
2984
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
|
+
}
|
|
2985
3300
|
// ../plugin/src/shared/model-suggestion-retry.ts
|
|
2986
3301
|
var ABORT_CALL_TIMEOUT_MS = 3000;
|
|
2987
3302
|
function copyPromptArgs(args, body) {
|
|
@@ -3635,7 +3950,7 @@ function parseCuesManifest(text) {
|
|
|
3635
3950
|
const body = extractCompleteManifestBody(text, "cues");
|
|
3636
3951
|
const out = [];
|
|
3637
3952
|
for (const match of body.matchAll(/<cue\s+id="(\d+)"\s*>([\s\S]*?)<\/cue>/g)) {
|
|
3638
|
-
const id = Number.parseInt(match[1], 10);
|
|
3953
|
+
const id = Number.parseInt(match[1] ?? "", 10);
|
|
3639
3954
|
if (!Number.isInteger(id))
|
|
3640
3955
|
continue;
|
|
3641
3956
|
out.push({ id, cue: unescapeXml(match[2] ?? "").trim() });
|
|
@@ -3736,7 +4051,10 @@ async function runCompressCues(args) {
|
|
|
3736
4051
|
break;
|
|
3737
4052
|
}
|
|
3738
4053
|
const sliceMs = computeChunkSliceMs(remainingMs, chunks.length - i);
|
|
3739
|
-
const
|
|
4054
|
+
const chunk = chunks[i];
|
|
4055
|
+
if (!chunk)
|
|
4056
|
+
break;
|
|
4057
|
+
const outcome = await compressOneChunk(args, chunk, sliceMs, abortController.signal);
|
|
3740
4058
|
result.compressed += outcome.compressed;
|
|
3741
4059
|
result.skipped += outcome.skipped;
|
|
3742
4060
|
result.remaining -= outcome.compressed;
|
|
@@ -3771,12 +4089,12 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
|
|
|
3771
4089
|
projectPath: args.projectIdentity,
|
|
3772
4090
|
memories: chunk.map(toPromptMemory)
|
|
3773
4091
|
});
|
|
3774
|
-
const createResponse = await
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
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
|
|
3780
4098
|
});
|
|
3781
4099
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
3782
4100
|
preferResponseOnMissingData: true
|
|
@@ -4260,12 +4578,12 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
4260
4578
|
abortController.abort();
|
|
4261
4579
|
});
|
|
4262
4580
|
try {
|
|
4263
|
-
const createResponse = await
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
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
|
|
4269
4587
|
});
|
|
4270
4588
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
4271
4589
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
@@ -4859,12 +5177,12 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
|
|
|
4859
5177
|
recordInvocation(args, startedAt, { status: "completed" });
|
|
4860
5178
|
return run2;
|
|
4861
5179
|
}
|
|
4862
|
-
const createResponse = await
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
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
|
|
4868
5186
|
});
|
|
4869
5187
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
4870
5188
|
preferResponseOnMissingData: true
|
|
@@ -5676,7 +5994,7 @@ function getAsyncModule() {
|
|
|
5676
5994
|
asyncModulePromise ??= (async () => {
|
|
5677
5995
|
const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
|
|
5678
5996
|
import("./index-ayd60xnw.js").then((m)=>__toESM(m.default,1)),
|
|
5679
|
-
import("./index-
|
|
5997
|
+
import("./index-3pnd4qh9.js")
|
|
5680
5998
|
]);
|
|
5681
5999
|
return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
|
|
5682
6000
|
})();
|
|
@@ -5895,12 +6213,12 @@ Remember: output only the JSON object described by the system prompt.`;
|
|
|
5895
6213
|
});
|
|
5896
6214
|
};
|
|
5897
6215
|
try {
|
|
5898
|
-
const createResponse = await
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
}
|
|
5903
|
-
|
|
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
|
|
5904
6222
|
});
|
|
5905
6223
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
5906
6224
|
preferResponseOnMissingData: true
|
|
@@ -6681,12 +6999,12 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
|
|
|
6681
6999
|
});
|
|
6682
7000
|
};
|
|
6683
7001
|
try {
|
|
6684
|
-
const createResponse = await
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
}
|
|
6689
|
-
|
|
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
|
|
6690
7008
|
});
|
|
6691
7009
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
6692
7010
|
preferResponseOnMissingData: true
|
|
@@ -7031,12 +7349,12 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
|
|
|
7031
7349
|
let agentSessionId = null;
|
|
7032
7350
|
const startedAt = Date.now();
|
|
7033
7351
|
try {
|
|
7034
|
-
const createResponse = await
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
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
|
|
7040
7358
|
});
|
|
7041
7359
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
7042
7360
|
preferResponseOnMissingData: true
|
|
@@ -7648,12 +7966,12 @@ async function refreshOnePrimer(args, primer, sliceMs, signal) {
|
|
|
7648
7966
|
let agentSessionId = null;
|
|
7649
7967
|
const startedAt = Date.now();
|
|
7650
7968
|
try {
|
|
7651
|
-
const createResponse = await
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7656
|
-
|
|
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
|
|
7657
7975
|
});
|
|
7658
7976
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
7659
7977
|
preferResponseOnMissingData: true
|
|
@@ -8151,8 +8469,8 @@ function extractToolRows(parts) {
|
|
|
8151
8469
|
const record = part;
|
|
8152
8470
|
if (record.type !== "tool" || typeof record.tool !== "string")
|
|
8153
8471
|
continue;
|
|
8154
|
-
const
|
|
8155
|
-
const stateRecord =
|
|
8472
|
+
const state2 = record.state;
|
|
8473
|
+
const stateRecord = state2 && typeof state2 === "object" ? state2 : {};
|
|
8156
8474
|
const output = stringifyToolOutput(stateRecord.output);
|
|
8157
8475
|
const errorText = stringifyToolOutput(stateRecord.error);
|
|
8158
8476
|
const status = typeof stateRecord.status === "string" ? stateRecord.status : "";
|
|
@@ -8479,12 +8797,12 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
|
|
|
8479
8797
|
let agentSessionId = null;
|
|
8480
8798
|
const startedAt = Date.now();
|
|
8481
8799
|
try {
|
|
8482
|
-
const createResponse = await
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
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
|
|
8488
8806
|
});
|
|
8489
8807
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
8490
8808
|
preferResponseOnMissingData: true
|
|
@@ -9171,12 +9489,12 @@ async function runRetrospectiveTask(config, ctx, helpers) {
|
|
|
9171
9489
|
});
|
|
9172
9490
|
let childSessionId = null;
|
|
9173
9491
|
try {
|
|
9174
|
-
const createResponse = await
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
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
|
|
9180
9498
|
});
|
|
9181
9499
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
9182
9500
|
childSessionId = typeof created?.id === "string" ? created.id : null;
|
|
@@ -9361,12 +9679,12 @@ async function runAgenticTask(config, ctx, helpers) {
|
|
|
9361
9679
|
});
|
|
9362
9680
|
let childSessionId = null;
|
|
9363
9681
|
try {
|
|
9364
|
-
const createResponse = await
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
}
|
|
9369
|
-
|
|
9682
|
+
const createResponse = await createChildSessionWithFence({
|
|
9683
|
+
client: deps.client,
|
|
9684
|
+
db,
|
|
9685
|
+
parentSessionId: parent ?? undefined,
|
|
9686
|
+
title: `magic-context-dream-${task}`,
|
|
9687
|
+
directory: docsDir
|
|
9370
9688
|
});
|
|
9371
9689
|
const created = normalizeSDKResponse(createResponse, null, {
|
|
9372
9690
|
preferResponseOnMissingData: true
|
|
@@ -9538,11 +9856,11 @@ function planDueTasks(db, projectIdentity, tasks, now) {
|
|
|
9538
9856
|
const due = [];
|
|
9539
9857
|
for (const config of tasks) {
|
|
9540
9858
|
reconcileSchedule(db, projectIdentity, config, now);
|
|
9541
|
-
const
|
|
9542
|
-
if (!
|
|
9859
|
+
const state2 = getTaskScheduleState(db, projectIdentity, config.task);
|
|
9860
|
+
if (!state2 || state2.nextDueAt === null)
|
|
9543
9861
|
continue;
|
|
9544
|
-
if (now >=
|
|
9545
|
-
due.push({ config, scheduledAt:
|
|
9862
|
+
if (now >= state2.nextDueAt) {
|
|
9863
|
+
due.push({ config, scheduledAt: state2.nextDueAt });
|
|
9546
9864
|
}
|
|
9547
9865
|
}
|
|
9548
9866
|
return due;
|
|
@@ -11047,6 +11365,101 @@ function executeFlush(db, sessionId) {
|
|
|
11047
11365
|
}
|
|
11048
11366
|
}
|
|
11049
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
|
+
|
|
11050
11463
|
// src/context-handler.ts
|
|
11051
11464
|
import * as crypto3 from "node:crypto";
|
|
11052
11465
|
|
|
@@ -11060,6 +11473,9 @@ var UNIT_TO_MS = {
|
|
|
11060
11473
|
};
|
|
11061
11474
|
function parseCacheTtl(ttl) {
|
|
11062
11475
|
const normalizedTtl = ttl.trim();
|
|
11476
|
+
if (normalizedTtl.toLowerCase() === "never") {
|
|
11477
|
+
return Number.POSITIVE_INFINITY;
|
|
11478
|
+
}
|
|
11063
11479
|
if (NUMERIC_PATTERN.test(normalizedTtl)) {
|
|
11064
11480
|
return Number(normalizedTtl);
|
|
11065
11481
|
}
|
|
@@ -11775,9 +12191,9 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
|
|
|
11775
12191
|
}
|
|
11776
12192
|
|
|
11777
12193
|
// ../plugin/src/hooks/magic-context/boundary-execution.ts
|
|
11778
|
-
var FORCE_MATERIALIZE_PERCENTAGE = 85;
|
|
11779
12194
|
function detectMidTurnBypassReason(input) {
|
|
11780
|
-
|
|
12195
|
+
const { forceMaterializationPercentage } = escalationBands(input.effectiveExecuteThresholdPercentage);
|
|
12196
|
+
if (input.contextUsage.percentage >= forceMaterializationPercentage)
|
|
11781
12197
|
return "force-materialize";
|
|
11782
12198
|
if (input.historyRefreshSessions.has(input.sessionId))
|
|
11783
12199
|
return "explicit-bust";
|
|
@@ -12270,29 +12686,29 @@ function callIdFromPart(part) {
|
|
|
12270
12686
|
const direct = firstStringField(part, ["callID", "callId", "toolCallId", "tool_call_id", "id"]);
|
|
12271
12687
|
if (direct)
|
|
12272
12688
|
return direct;
|
|
12273
|
-
const
|
|
12274
|
-
return
|
|
12689
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
12690
|
+
return state2 ? firstStringField(state2, ["callID", "callId", "toolCallId", "tool_call_id", "id"]) ?? "" : "";
|
|
12275
12691
|
}
|
|
12276
12692
|
function toolSignalFromPart(part) {
|
|
12277
12693
|
if (!isRecord(part))
|
|
12278
12694
|
return null;
|
|
12279
12695
|
const type = partType(part);
|
|
12280
|
-
const
|
|
12696
|
+
const state2 = isRecord(part.state) ? part.state : null;
|
|
12281
12697
|
const callId = callIdFromPart(part);
|
|
12282
12698
|
if (!callId && type !== "tool")
|
|
12283
12699
|
return null;
|
|
12284
12700
|
if (type === "tool") {
|
|
12285
|
-
const hasInput =
|
|
12286
|
-
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;
|
|
12287
12703
|
const hasOutput = outputKey !== null;
|
|
12288
|
-
const outputValue = outputKey &&
|
|
12704
|
+
const outputValue = outputKey && state2 ? state2[outputKey] : undefined;
|
|
12289
12705
|
const providerExecuted = part.providerExecuted === true;
|
|
12290
12706
|
const openInvocation = !providerExecuted && !hasOutput;
|
|
12291
12707
|
return {
|
|
12292
12708
|
callId,
|
|
12293
12709
|
hasInput: hasInput || openInvocation,
|
|
12294
12710
|
hasOutput,
|
|
12295
|
-
inputText: hasInput &&
|
|
12711
|
+
inputText: hasInput && state2 ? stringValue(state2.input) : "",
|
|
12296
12712
|
outputText: hasOutput ? stringValue(outputValue) : ""
|
|
12297
12713
|
};
|
|
12298
12714
|
}
|
|
@@ -12520,24 +12936,27 @@ function tokenForMessage(message, options) {
|
|
|
12520
12936
|
function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
12521
12937
|
const ordered = [...messages].sort((a, b) => a.ordinal - b.ordinal);
|
|
12522
12938
|
const sliceCount = ordered.length;
|
|
12523
|
-
const
|
|
12524
|
-
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;
|
|
12525
12943
|
const tokensByOrdinal = new Map;
|
|
12526
12944
|
const idsByOrdinal = new Map;
|
|
12527
|
-
const prefix = new Array(
|
|
12945
|
+
const prefix = new Array(ordinalSpan + 1).fill(0);
|
|
12528
12946
|
for (const message of ordered) {
|
|
12529
12947
|
const stored = options.storedTotalForMessage?.(message);
|
|
12530
12948
|
const total = stored !== undefined && stored !== null ? stored : tokenForMessage(message, options).total;
|
|
12531
12949
|
tokensByOrdinal.set(message.ordinal, total);
|
|
12532
12950
|
idsByOrdinal.set(message.ordinal, message.id);
|
|
12533
|
-
|
|
12534
|
-
|
|
12951
|
+
const relative = message.ordinal - firstOrdinal + 1;
|
|
12952
|
+
if (relative >= 1 && relative <= ordinalSpan) {
|
|
12953
|
+
prefix[relative] = total;
|
|
12535
12954
|
}
|
|
12536
12955
|
}
|
|
12537
|
-
for (let k = 1;k <=
|
|
12956
|
+
for (let k = 1;k <= ordinalSpan; k += 1) {
|
|
12538
12957
|
prefix[k] += prefix[k - 1];
|
|
12539
12958
|
}
|
|
12540
|
-
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(
|
|
12959
|
+
const ordinalToIndex = (ordinal) => Math.max(0, Math.min(ordinalSpan, ordinal - firstOrdinal));
|
|
12541
12960
|
return {
|
|
12542
12961
|
sessionId,
|
|
12543
12962
|
providerShapeVersion: options.providerShapeVersion,
|
|
@@ -12549,27 +12968,27 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
12549
12968
|
return idsByOrdinal.get(ordinal) ?? null;
|
|
12550
12969
|
},
|
|
12551
12970
|
suffixTokensFromOrdinal(ordinal) {
|
|
12552
|
-
if (ordinal <=
|
|
12553
|
-
return prefix[
|
|
12554
|
-
if (ordinal >
|
|
12971
|
+
if (ordinal <= firstOrdinal)
|
|
12972
|
+
return prefix[ordinalSpan];
|
|
12973
|
+
if (ordinal > terminalOrdinal)
|
|
12555
12974
|
return 0;
|
|
12556
|
-
return prefix[
|
|
12975
|
+
return prefix[ordinalSpan] - prefix[ordinalToIndex(ordinal)];
|
|
12557
12976
|
},
|
|
12558
12977
|
rangeTokens(startInclusive, endExclusive) {
|
|
12559
|
-
const start = Math.max(
|
|
12560
|
-
const end = Math.max(start, Math.min(
|
|
12561
|
-
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];
|
|
12562
12981
|
},
|
|
12563
12982
|
findSuffixStartForTokens(tokens) {
|
|
12564
12983
|
if (!Number.isFinite(tokens) || tokens <= 0)
|
|
12565
|
-
return
|
|
12984
|
+
return terminalOrdinal + 1;
|
|
12566
12985
|
const target = Math.max(0, Math.floor(tokens));
|
|
12567
|
-
const total = prefix[
|
|
12986
|
+
const total = prefix[ordinalSpan];
|
|
12568
12987
|
if (total < target)
|
|
12569
|
-
return
|
|
12988
|
+
return firstOrdinal;
|
|
12570
12989
|
const cut = total - target;
|
|
12571
12990
|
let lo = 0;
|
|
12572
|
-
let hi =
|
|
12991
|
+
let hi = ordinalSpan;
|
|
12573
12992
|
let best = 0;
|
|
12574
12993
|
while (lo <= hi) {
|
|
12575
12994
|
const mid = lo + hi >> 1;
|
|
@@ -12580,29 +12999,31 @@ function buildTrueRawTokenIndex(sessionId, messages, options) {
|
|
|
12580
12999
|
hi = mid - 1;
|
|
12581
13000
|
}
|
|
12582
13001
|
}
|
|
12583
|
-
return
|
|
13002
|
+
return firstOrdinal + best;
|
|
12584
13003
|
},
|
|
12585
13004
|
findHeadEndForCap(startInclusive, endExclusive, capTokens) {
|
|
12586
|
-
const start = Math.max(
|
|
12587
|
-
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));
|
|
12588
13007
|
if (!Number.isFinite(capTokens) || capTokens <= 0)
|
|
12589
13008
|
return start;
|
|
12590
|
-
const
|
|
12591
|
-
const
|
|
12592
|
-
|
|
12593
|
-
let
|
|
12594
|
-
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;
|
|
12595
13015
|
while (lo <= hi) {
|
|
12596
13016
|
const mid = lo + hi >> 1;
|
|
12597
13017
|
if (prefix[mid] <= cut) {
|
|
12598
|
-
|
|
13018
|
+
bestEndIndex = mid;
|
|
12599
13019
|
lo = mid + 1;
|
|
12600
13020
|
} else {
|
|
12601
13021
|
hi = mid - 1;
|
|
12602
13022
|
}
|
|
12603
13023
|
}
|
|
13024
|
+
let bestEnd = firstOrdinal + bestEndIndex;
|
|
12604
13025
|
if (bestEnd === start && start < end)
|
|
12605
|
-
|
|
13026
|
+
bestEnd = start + 1;
|
|
12606
13027
|
return Math.min(bestEnd, end);
|
|
12607
13028
|
}
|
|
12608
13029
|
};
|
|
@@ -12918,7 +13339,8 @@ function resolveProtectedTailBoundary(ctx) {
|
|
|
12918
13339
|
if (ctx.migrationFloorActive)
|
|
12919
13340
|
runtimeFloor = Math.max(runtimeFloor, ctx.priorBoundaryOrdinal);
|
|
12920
13341
|
let protectedTailStart = Math.max(boundary, runtimeFloor);
|
|
12921
|
-
|
|
13342
|
+
const forceMaterializationPercentage = escalationBands(ctx.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13343
|
+
if (!ctx.emergencyTailScale && usagePercentage < forceMaterializationPercentage) {
|
|
12922
13344
|
let lastMeaningfulUserOrdinal = 0;
|
|
12923
13345
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
12924
13346
|
const message = messages[i];
|
|
@@ -13159,7 +13581,8 @@ function getRawHistoryEligibility(db, sessionId) {
|
|
|
13159
13581
|
function hasRunnableCompartmentWindow(snapshot) {
|
|
13160
13582
|
if (snapshot.offset >= snapshot.protectedTailStart)
|
|
13161
13583
|
return false;
|
|
13162
|
-
|
|
13584
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13585
|
+
if (snapshot.usagePercentage >= forceMaterializationPercentage || snapshot.emergencyTailScale) {
|
|
13163
13586
|
return snapshot.trueRawEligibleTokens >= deriveMinForceEligibleTokens(snapshot.N) || snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
13164
13587
|
}
|
|
13165
13588
|
return snapshot.eligibleEndOrdinal > snapshot.offset;
|
|
@@ -13222,11 +13645,18 @@ function validateBoundarySnapshot(args) {
|
|
|
13222
13645
|
return { ok: true };
|
|
13223
13646
|
}
|
|
13224
13647
|
function recordHighPressureNoEligibleHead(db, snapshot) {
|
|
13225
|
-
|
|
13648
|
+
const forceMaterializationPercentage = escalationBands(snapshot.executeThresholdPercentage).forceMaterializationPercentage;
|
|
13649
|
+
if (snapshot.usagePercentage < forceMaterializationPercentage && !snapshot.emergencyTailScale) {
|
|
13226
13650
|
return 0;
|
|
13651
|
+
}
|
|
13227
13652
|
return recordProtectedTailNoEligibleHead(db, snapshot.sessionId);
|
|
13228
13653
|
}
|
|
13229
13654
|
|
|
13655
|
+
// ../plugin/src/hooks/magic-context/sentinel.ts
|
|
13656
|
+
function modelAcceptsEmptyContent(providerID) {
|
|
13657
|
+
return providerID === "anthropic";
|
|
13658
|
+
}
|
|
13659
|
+
|
|
13230
13660
|
// ../plugin/src/hooks/magic-context/compartment-trigger.ts
|
|
13231
13661
|
var PROACTIVE_TRIGGER_OFFSET_PERCENTAGE = 2;
|
|
13232
13662
|
var POST_DROP_TARGET_RATIO = 0.75;
|
|
@@ -13234,7 +13664,6 @@ var MIN_PROACTIVE_TAIL_TOKEN_ESTIMATE = 6000;
|
|
|
13234
13664
|
var MIN_PROACTIVE_TAIL_MESSAGE_COUNT = 12;
|
|
13235
13665
|
var DEFAULT_MIN_COMMIT_CLUSTERS_FOR_TRIGGER = 3;
|
|
13236
13666
|
var TAIL_SIZE_TRIGGER_MULTIPLIER = 3;
|
|
13237
|
-
var FORCE_COMPARTMENT_PERCENTAGE = 80;
|
|
13238
13667
|
var BLOCK_UNTIL_DONE_PERCENTAGE = 95;
|
|
13239
13668
|
var CONTENT_TAG_OWNER_SUFFIX = /:(?:p|file)\d+$/;
|
|
13240
13669
|
function tagOwnerMessageId(row) {
|
|
@@ -13271,7 +13700,7 @@ function estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, tag
|
|
|
13271
13700
|
function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage) {
|
|
13272
13701
|
return Math.max(0, executeThresholdPercentage - PROACTIVE_TRIGGER_OFFSET_PERCENTAGE);
|
|
13273
13702
|
}
|
|
13274
|
-
function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, clearReasoningAge, clearedReasoningThroughTag) {
|
|
13703
|
+
function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, clearReasoningAge, clearedReasoningThroughTag, canClearReasoning) {
|
|
13275
13704
|
const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
|
|
13276
13705
|
if (totalActiveBytes === 0)
|
|
13277
13706
|
return null;
|
|
@@ -13282,7 +13711,7 @@ function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, c
|
|
|
13282
13711
|
droppableBytes += activeTags.filter((tag) => pendingDropTagIds.has(tag.tagNumber)).reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
|
|
13283
13712
|
}
|
|
13284
13713
|
const maxTag = activeTags.reduce((max, t) => Math.max(max, t.tagNumber), 0);
|
|
13285
|
-
if (clearReasoningAge !== undefined && clearedReasoningThroughTag !== undefined) {
|
|
13714
|
+
if (canClearReasoning && clearReasoningAge !== undefined && clearedReasoningThroughTag !== undefined) {
|
|
13286
13715
|
const reasoningAgeCutoff = maxTag - clearReasoningAge;
|
|
13287
13716
|
for (const tag of activeTags) {
|
|
13288
13717
|
if (tag.type !== "message")
|
|
@@ -13382,7 +13811,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
|
|
|
13382
13811
|
}
|
|
13383
13812
|
});
|
|
13384
13813
|
}
|
|
13385
|
-
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) {
|
|
13386
13815
|
if (sessionMeta.compartmentInProgress) {
|
|
13387
13816
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
13388
13817
|
return { shouldFire: false };
|
|
@@ -13436,18 +13865,20 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
13436
13865
|
}
|
|
13437
13866
|
return { shouldFire: false };
|
|
13438
13867
|
}
|
|
13439
|
-
const
|
|
13868
|
+
const canClearReasoning = reasoningProjection?.canClearReasoning ?? modelAcceptsEmptyContent(reasoningProjection?.providerID);
|
|
13869
|
+
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), clearReasoningAge, sessionMeta.clearedReasoningThroughTag, canClearReasoning);
|
|
13440
13870
|
const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
|
|
13441
|
-
|
|
13871
|
+
const forceMaterializationPercentage = escalationBands(executeThresholdPercentage).forceMaterializationPercentage;
|
|
13872
|
+
if (usage.percentage >= forceMaterializationPercentage) {
|
|
13442
13873
|
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
13443
|
-
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)}%)`);
|
|
13444
13875
|
return { shouldFire: false };
|
|
13445
13876
|
}
|
|
13446
13877
|
sessionLog(sessionId, `compartment trigger: force-firing at ${usage.percentage.toFixed(1)}% (projected post-drop ${projectedPostDropPercentage?.toFixed(1) ?? "none"}%)`);
|
|
13447
13878
|
if (tailInfo.boundarySnapshot && hasRunnableCompartmentWindow(tailInfo.boundarySnapshot)) {
|
|
13448
13879
|
return {
|
|
13449
13880
|
shouldFire: true,
|
|
13450
|
-
reason: "
|
|
13881
|
+
reason: "force_band",
|
|
13451
13882
|
boundarySnapshot: tailInfo.boundarySnapshot
|
|
13452
13883
|
};
|
|
13453
13884
|
}
|
|
@@ -13472,9 +13903,9 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
13472
13903
|
});
|
|
13473
13904
|
});
|
|
13474
13905
|
if (hasRunnableCompartmentWindow(scaledBoundary)) {
|
|
13475
|
-
return { shouldFire: true, reason: "
|
|
13906
|
+
return { shouldFire: true, reason: "force_band", boundarySnapshot: scaledBoundary };
|
|
13476
13907
|
}
|
|
13477
|
-
sessionLog(sessionId, "compartment trigger:
|
|
13908
|
+
sessionLog(sessionId, "compartment trigger: force_band skipped — raw exists but protected head genuinely empty after emergency tail scale");
|
|
13478
13909
|
return { shouldFire: false };
|
|
13479
13910
|
}
|
|
13480
13911
|
const clusterEnabled = commitClusterTrigger?.enabled ?? true;
|
|
@@ -13639,11 +14070,6 @@ ${body}${hintText}
|
|
|
13639
14070
|
</system-reminder>`;
|
|
13640
14071
|
}
|
|
13641
14072
|
|
|
13642
|
-
// ../plugin/src/hooks/magic-context/sentinel.ts
|
|
13643
|
-
function modelAcceptsEmptyContent(providerID) {
|
|
13644
|
-
return providerID === "anthropic";
|
|
13645
|
-
}
|
|
13646
|
-
|
|
13647
14073
|
// ../plugin/src/hooks/magic-context/supersession-reclaim.ts
|
|
13648
14074
|
var TODOWRITE_KEEP = 1;
|
|
13649
14075
|
var CTX_REDUCE_KEEP = 5;
|
|
@@ -14958,16 +15384,16 @@ function sealDeliveredAfterUnconfirmedSend(db, sessionId) {
|
|
|
14958
15384
|
}
|
|
14959
15385
|
}
|
|
14960
15386
|
var channel1StateBySession = new Map;
|
|
14961
|
-
function setPiChannel1Baseline(sessionId,
|
|
14962
|
-
channel1StateBySession.set(sessionId,
|
|
15387
|
+
function setPiChannel1Baseline(sessionId, state2) {
|
|
15388
|
+
channel1StateBySession.set(sessionId, state2);
|
|
14963
15389
|
}
|
|
14964
15390
|
function clearPiChannel1State(sessionId) {
|
|
14965
15391
|
channel1StateBySession.delete(sessionId);
|
|
14966
15392
|
}
|
|
14967
15393
|
function markPiChannel1Reduced(sessionId, db) {
|
|
14968
|
-
const
|
|
14969
|
-
if (
|
|
14970
|
-
|
|
15394
|
+
const state2 = channel1StateBySession.get(sessionId);
|
|
15395
|
+
if (state2)
|
|
15396
|
+
state2.reducedSinceRefresh = true;
|
|
14971
15397
|
if (db)
|
|
14972
15398
|
resetLastNudgeCycle(db, sessionId);
|
|
14973
15399
|
}
|
|
@@ -15042,11 +15468,11 @@ function computeTailTokenEstimatePi(messages) {
|
|
|
15042
15468
|
}
|
|
15043
15469
|
function maybeChannel1ReminderForToolResult(args) {
|
|
15044
15470
|
const { db, sessionId, toolName } = args;
|
|
15045
|
-
const
|
|
15046
|
-
if (!
|
|
15471
|
+
const state2 = channel1StateBySession.get(sessionId);
|
|
15472
|
+
if (!state2)
|
|
15047
15473
|
return null;
|
|
15048
15474
|
if (toolName === "ctx_reduce") {
|
|
15049
|
-
|
|
15475
|
+
state2.reducedSinceRefresh = true;
|
|
15050
15476
|
resetLastNudgeCycle(db, sessionId);
|
|
15051
15477
|
return null;
|
|
15052
15478
|
}
|
|
@@ -15055,21 +15481,21 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
15055
15481
|
return null;
|
|
15056
15482
|
if (text.includes(CHANNEL1_SENTINEL))
|
|
15057
15483
|
return null;
|
|
15058
|
-
|
|
15059
|
-
if (
|
|
15484
|
+
state2.turnToolTokens += toolOutputTokens(text);
|
|
15485
|
+
if (state2.reducedSinceRefresh)
|
|
15060
15486
|
return null;
|
|
15061
|
-
const undroppedTokens =
|
|
15487
|
+
const undroppedTokens = state2.tailToolTokens + state2.turnToolTokens;
|
|
15062
15488
|
const pressure = computePressure({
|
|
15063
|
-
lastInputTokens:
|
|
15064
|
-
turnToolTokens:
|
|
15065
|
-
contextLimit:
|
|
15066
|
-
executeThresholdPercentage:
|
|
15489
|
+
lastInputTokens: state2.lastInputTokens,
|
|
15490
|
+
turnToolTokens: state2.turnToolTokens,
|
|
15491
|
+
contextLimit: state2.contextLimit,
|
|
15492
|
+
executeThresholdPercentage: state2.executeThresholdPercentage
|
|
15067
15493
|
});
|
|
15068
|
-
const workingWindowTokens = Math.round(
|
|
15494
|
+
const workingWindowTokens = Math.round(state2.contextLimit * state2.executeThresholdPercentage / 100);
|
|
15069
15495
|
const decision = decideChannel1({
|
|
15070
15496
|
undroppedTokens,
|
|
15071
15497
|
pressure,
|
|
15072
|
-
estimatedInputTokens:
|
|
15498
|
+
estimatedInputTokens: state2.lastInputTokens + state2.turnToolTokens,
|
|
15073
15499
|
workingWindowTokens,
|
|
15074
15500
|
lastNudgeUndropped: getLastNudgeUndropped(db, sessionId),
|
|
15075
15501
|
lastNudgeLevel: getLastNudgeLevel(db, sessionId),
|
|
@@ -15081,18 +15507,18 @@ function maybeChannel1ReminderForToolResult(args) {
|
|
|
15081
15507
|
return null;
|
|
15082
15508
|
return {
|
|
15083
15509
|
type: "text",
|
|
15084
|
-
text: buildChannel1Reminder(decision.level, decision.undroppedTokens,
|
|
15510
|
+
text: buildChannel1Reminder(decision.level, decision.undroppedTokens, state2.oldestReclaimableToolTags)
|
|
15085
15511
|
};
|
|
15086
15512
|
}
|
|
15087
15513
|
var CHANNEL2_NUDGE_CUSTOM_TYPE = "magic-context:ceiling-nudge";
|
|
15088
15514
|
function maybeDeliverChannel2Pi(pi, db, sessionId, deliverAs = "followUp") {
|
|
15089
|
-
let
|
|
15515
|
+
let state2;
|
|
15090
15516
|
try {
|
|
15091
|
-
|
|
15517
|
+
state2 = getChannel2NudgeState(db, sessionId);
|
|
15092
15518
|
} catch {
|
|
15093
15519
|
return false;
|
|
15094
15520
|
}
|
|
15095
|
-
if (
|
|
15521
|
+
if (state2 !== "pending")
|
|
15096
15522
|
return false;
|
|
15097
15523
|
const baseline = channel1StateBySession.get(sessionId);
|
|
15098
15524
|
if (!baseline)
|
|
@@ -15764,14 +16190,17 @@ var EMPTY_PI_PROJECT_DOCS = {
|
|
|
15764
16190
|
renderedBlock: "",
|
|
15765
16191
|
canonicalHash: ""
|
|
15766
16192
|
};
|
|
15767
|
-
function
|
|
15768
|
-
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;
|
|
15769
16198
|
}
|
|
15770
|
-
function memoryProjectPath(
|
|
15771
|
-
return
|
|
16199
|
+
function memoryProjectPath(state2) {
|
|
16200
|
+
return state2.memoryEnabled === false ? undefined : state2.projectIdentity;
|
|
15772
16201
|
}
|
|
15773
|
-
function resolveWorkspaceRenderContextPi(
|
|
15774
|
-
const memPath = memoryProjectPath(
|
|
16202
|
+
function resolveWorkspaceRenderContextPi(state2, db) {
|
|
16203
|
+
const memPath = memoryProjectPath(state2);
|
|
15775
16204
|
if (!memPath) {
|
|
15776
16205
|
return {
|
|
15777
16206
|
identities: [],
|
|
@@ -15847,12 +16276,12 @@ function piImageFromDataUrl(dataUrl) {
|
|
|
15847
16276
|
return null;
|
|
15848
16277
|
return { type: "image", mimeType: match[1], data: match[2] };
|
|
15849
16278
|
}
|
|
15850
|
-
function resolveMuralForM0Pi(
|
|
15851
|
-
if (
|
|
15852
|
-
return
|
|
15853
|
-
if (!
|
|
16279
|
+
function resolveMuralForM0Pi(state2, db, modelKey, budgetTokens) {
|
|
16280
|
+
if (state2.mural)
|
|
16281
|
+
return state2.mural;
|
|
16282
|
+
if (!state2.muralEnabled)
|
|
15854
16283
|
return;
|
|
15855
|
-
return resolveMuralWire(db, memoryProjectPath(
|
|
16284
|
+
return resolveMuralWire(db, memoryProjectPath(state2), modelKey, true, budgetTokens);
|
|
15856
16285
|
}
|
|
15857
16286
|
function cachedInjectionTokenCounts(sessionId, m0, m1) {
|
|
15858
16287
|
const cached = injectionTokenCountsBySession.get(sessionId);
|
|
@@ -15905,17 +16334,17 @@ function trimPiMessagesToCachedBoundary(db, sessionId, piMessages, entryIds) {
|
|
|
15905
16334
|
function setCachedBoundary(db, sessionId, boundary) {
|
|
15906
16335
|
db.prepare("UPDATE session_meta SET cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(boundary, sessionId);
|
|
15907
16336
|
}
|
|
15908
|
-
function getCachedMarkers(db,
|
|
15909
|
-
const meta = getOrCreateSessionMeta(db,
|
|
16337
|
+
function getCachedMarkers(db, state2, compartmentsForNormalization) {
|
|
16338
|
+
const meta = getOrCreateSessionMeta(db, state2.sessionId);
|
|
15910
16339
|
if (!meta.cachedM0Bytes)
|
|
15911
16340
|
return null;
|
|
15912
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) {
|
|
15913
16342
|
return null;
|
|
15914
16343
|
}
|
|
15915
|
-
const compartments = compartmentsForNormalization ??
|
|
16344
|
+
const compartments = compartmentsForNormalization ?? getRenderableCompartmentsPi(db, state2);
|
|
15916
16345
|
const cachedUpgradeIdentity = decodeCachedM0UpgradeIdentity(meta.cachedM0UpgradeState);
|
|
15917
16346
|
const maxCompartmentSeq = normalizeCachedMaxCompartmentSeq(meta.cachedM0MaxCompartmentSeq, compartments);
|
|
15918
|
-
const cachedBoundary = getCachedBoundary(db,
|
|
16347
|
+
const cachedBoundary = getCachedBoundary(db, state2.sessionId);
|
|
15919
16348
|
const liveBoundary = lastBaselineEndMessageId(compartments);
|
|
15920
16349
|
if (maxCompartmentSeq >= 0 && cachedBoundary === null && liveBoundary !== null) {
|
|
15921
16350
|
return null;
|
|
@@ -15943,38 +16372,38 @@ function lastBaselineEndMessageId(compartments) {
|
|
|
15943
16372
|
const last = compartments.at(-1);
|
|
15944
16373
|
return last?.endMessageId && last.endMessageId.length > 0 ? last.endMessageId : null;
|
|
15945
16374
|
}
|
|
15946
|
-
function readCurrentMarkers(db,
|
|
15947
|
-
return readCurrentMarkersFromCompartments(db,
|
|
16375
|
+
function readCurrentMarkers(db, state2, projectDocsHash) {
|
|
16376
|
+
return readCurrentMarkersFromCompartments(db, state2, getRenderableCompartmentsPi(db, state2), projectDocsHash);
|
|
15948
16377
|
}
|
|
15949
|
-
function readCurrentMarkersFromCompartments(db,
|
|
15950
|
-
const memPath = memoryProjectPath(
|
|
15951
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16378
|
+
function readCurrentMarkersFromCompartments(db, state2, compartments, projectDocsHash) {
|
|
16379
|
+
const memPath = memoryProjectPath(state2);
|
|
16380
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
15952
16381
|
const maxMemoryId = memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0;
|
|
15953
16382
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
15954
16383
|
const globalState = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH);
|
|
15955
16384
|
return {
|
|
15956
16385
|
maxCompartmentSeq: compartments.length > 0 ? compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ) : EMPTY_MAX_COMPARTMENT_SEQ,
|
|
15957
16386
|
maxMemoryId,
|
|
15958
|
-
maxMutationId: getMaxM0MutationId(db,
|
|
16387
|
+
maxMutationId: getMaxM0MutationId(db, state2.sessionId) ?? 0,
|
|
15959
16388
|
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
15960
16389
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
15961
16390
|
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
15962
16391
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
15963
|
-
projectDocsHash: projectDocsHash ?? readProjectDocsForPiM0(
|
|
15964
|
-
sessionFactsVersion: getSessionFactsVersion(db,
|
|
16392
|
+
projectDocsHash: projectDocsHash ?? readProjectDocsForPiM0(state2).canonicalHash,
|
|
16393
|
+
sessionFactsVersion: getSessionFactsVersion(db, state2.sessionId),
|
|
15965
16394
|
materializedAt: Date.now(),
|
|
15966
16395
|
upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
|
|
15967
16396
|
compartmentRenderEpoch: COMPARTMENT_RENDER_EPOCH,
|
|
15968
16397
|
lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
|
|
15969
|
-
systemHash: (
|
|
15970
|
-
modelKey: (
|
|
15971
|
-
projectIdentity:
|
|
16398
|
+
systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
|
|
16399
|
+
modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
|
|
16400
|
+
projectIdentity: state2.projectIdentity
|
|
15972
16401
|
};
|
|
15973
16402
|
}
|
|
15974
|
-
function mustMaterializePi(
|
|
15975
|
-
const meta = getOrCreateSessionMeta(db,
|
|
15976
|
-
const currentCompartments = currentCompartmentsOverride ??
|
|
15977
|
-
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);
|
|
15978
16407
|
if (!meta.cachedM0Bytes)
|
|
15979
16408
|
return { value: true, reason: "first_render" };
|
|
15980
16409
|
if (!meta.cachedM1Bytes)
|
|
@@ -15982,21 +16411,21 @@ function mustMaterializePi(state, db, currentCompartmentsOverride) {
|
|
|
15982
16411
|
if (!decodeCachedM0(meta.cachedM0Bytes)) {
|
|
15983
16412
|
return { value: true, reason: "cache_invalid" };
|
|
15984
16413
|
}
|
|
15985
|
-
const cached = getCachedMarkers(db,
|
|
16414
|
+
const cached = getCachedMarkers(db, state2, currentCompartments);
|
|
15986
16415
|
if (cached === null) {
|
|
15987
16416
|
return { value: true, reason: "cache_invalid" };
|
|
15988
16417
|
}
|
|
15989
16418
|
if (cached.compartmentRenderEpoch !== current.compartmentRenderEpoch) {
|
|
15990
16419
|
return { value: true, reason: "compartment_render_epoch" };
|
|
15991
16420
|
}
|
|
15992
|
-
const hard =
|
|
16421
|
+
const hard = state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS;
|
|
15993
16422
|
if (hard.modelKey !== "" && hard.modelKey !== (meta.cachedM0ModelKey ?? "")) {
|
|
15994
16423
|
return { value: true, reason: "model_change" };
|
|
15995
16424
|
}
|
|
15996
16425
|
if (hard.systemHash !== "" && hard.systemHash !== (meta.cachedM0SystemHash ?? "")) {
|
|
15997
16426
|
return { value: true, reason: "system_hash" };
|
|
15998
16427
|
}
|
|
15999
|
-
if (meta.cachedM0ProjectIdentity !== null && meta.cachedM0ProjectIdentity !==
|
|
16428
|
+
if (meta.cachedM0ProjectIdentity !== null && meta.cachedM0ProjectIdentity !== state2.projectIdentity) {
|
|
16000
16429
|
return { value: true, reason: "project_change" };
|
|
16001
16430
|
}
|
|
16002
16431
|
if (hard.cacheExpired && hard.lastResponseTime > 0 && hard.lastResponseTime > (meta.cachedM0MaterializedAt ?? 0)) {
|
|
@@ -16026,9 +16455,9 @@ ${memories.map((memory) => `- ${escapeXmlContent(memory.content)}`).join(`
|
|
|
16026
16455
|
`)}
|
|
16027
16456
|
</${wrapper}>`;
|
|
16028
16457
|
}
|
|
16029
|
-
function renderM0Pi(
|
|
16030
|
-
const memPath = memoryProjectPath(
|
|
16031
|
-
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);
|
|
16032
16461
|
const allMemories = memoriesOverride ?? (memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], Date.now(), workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"]) : []);
|
|
16033
16462
|
const memoryRenderOptions = {
|
|
16034
16463
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
@@ -16037,23 +16466,25 @@ function renderM0Pi(state, db, projectDocs = readProjectDocsForPiM0(state).rende
|
|
|
16037
16466
|
workspace
|
|
16038
16467
|
})
|
|
16039
16468
|
};
|
|
16040
|
-
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;
|
|
16041
16470
|
const memoryBlock = memories.length > 0 ? renderMemoryBlockV2(memories, "project-memory", memoryRenderOptions) : undefined;
|
|
16042
|
-
const baseHistoryBudget =
|
|
16471
|
+
const baseHistoryBudget = state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS;
|
|
16043
16472
|
const decayed = renderDecayedCompartments({
|
|
16044
|
-
compartments: compartmentsOverride ??
|
|
16473
|
+
compartments: compartmentsOverride ?? getRenderableCompartmentsPi(db, state2),
|
|
16045
16474
|
historyBudgetTokens: baseHistoryBudget / Math.max(1, decayPressureMultiplier)
|
|
16046
16475
|
});
|
|
16047
16476
|
const sections = [];
|
|
16048
16477
|
if (projectDocs.length > 0)
|
|
16049
16478
|
sections.push(projectDocs);
|
|
16050
|
-
const trimmedProfile = trimUserMemoriesToBudget(userProfileOverride ?? safeGetActiveUserMemoriesPi(db),
|
|
16479
|
+
const trimmedProfile = trimUserMemoriesToBudget(userProfileOverride ?? safeGetActiveUserMemoriesPi(db), state2.userProfileBudgetTokens ?? DEFAULT_USER_PROFILE_BUDGET_TOKENS);
|
|
16051
16480
|
const userProfile = renderUserProfileBlock(db, "user-profile", trimmedProfile);
|
|
16052
16481
|
if (userProfile.length > 0)
|
|
16053
16482
|
sections.push(userProfile);
|
|
16054
|
-
|
|
16483
|
+
if (!state2.compactionOff) {
|
|
16484
|
+
sections.push(decayed.length > 0 ? `<session-history>
|
|
16055
16485
|
${decayed}
|
|
16056
16486
|
</session-history>` : "<session-history></session-history>");
|
|
16487
|
+
}
|
|
16057
16488
|
if (memoryBlock)
|
|
16058
16489
|
sections.push(memoryBlock);
|
|
16059
16490
|
if (mural?.enabled && mural.supportsVision && mural.dataUrl) {
|
|
@@ -16065,18 +16496,18 @@ The project memory mural image follows.
|
|
|
16065
16496
|
|
|
16066
16497
|
`).trim();
|
|
16067
16498
|
}
|
|
16068
|
-
function renderedMemoryIdsForPi(
|
|
16499
|
+
function renderedMemoryIdsForPi(state2, memories, workspace, db) {
|
|
16069
16500
|
if (memories.length === 0)
|
|
16070
16501
|
return [];
|
|
16071
|
-
const resolvedWorkspace = workspace ?? (db ? resolveWorkspaceRenderContextPi(
|
|
16502
|
+
const resolvedWorkspace = workspace ?? (db ? resolveWorkspaceRenderContextPi(state2, db) : undefined);
|
|
16072
16503
|
const renderOptions = resolvedWorkspace ? {
|
|
16073
16504
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
16074
16505
|
memories,
|
|
16075
|
-
projectPath: memoryProjectPath(
|
|
16506
|
+
projectPath: memoryProjectPath(state2),
|
|
16076
16507
|
workspace: resolvedWorkspace
|
|
16077
16508
|
})
|
|
16078
16509
|
} : {};
|
|
16079
|
-
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);
|
|
16080
16511
|
return trimmed.renderOrder.map((memory) => memory.id);
|
|
16081
16512
|
}
|
|
16082
16513
|
function isTransientSqliteLockError(error) {
|
|
@@ -16099,11 +16530,11 @@ class PiMaterializeContentionError extends Error {
|
|
|
16099
16530
|
this.name = "PiMaterializeContentionError";
|
|
16100
16531
|
}
|
|
16101
16532
|
}
|
|
16102
|
-
function readFrozenM0InputsPi(
|
|
16103
|
-
const memPath = memoryProjectPath(
|
|
16533
|
+
function readFrozenM0InputsPi(state2, db, docs = readProjectDocsForPiM0(state2), memoryCutoff) {
|
|
16534
|
+
const memPath = memoryProjectPath(state2);
|
|
16104
16535
|
const read = db.transaction(() => {
|
|
16105
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16106
|
-
const compartments =
|
|
16536
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16537
|
+
const compartments = getRenderableCompartmentsPi(db, state2);
|
|
16107
16538
|
const memories = memPath ? workspace.isWorkspaced ? getMemoriesByProjects(db, workspace.expandedIdentities, ["active", "permanent"], memoryCutoff, workspace.ownIdentities, workspace.shareCategories) : getMemoriesByProject(db, memPath, ["active", "permanent"], memoryCutoff) : [];
|
|
16108
16539
|
const userProfile = safeGetActiveUserMemoriesPi(db);
|
|
16109
16540
|
const projectState = memPath ? getProjectState(db, memPath) : undefined;
|
|
@@ -16111,72 +16542,72 @@ function readFrozenM0InputsPi(state, db, docs = readProjectDocsForPiM0(state), m
|
|
|
16111
16542
|
const markers = {
|
|
16112
16543
|
maxCompartmentSeq: compartments.reduce((max, compartment) => compartment.sequence > max ? compartment.sequence : max, EMPTY_MAX_COMPARTMENT_SEQ),
|
|
16113
16544
|
maxMemoryId: memPath ? workspace.isWorkspaced ? getMaxMemoryIdForProjects(db, workspace.expandedIdentities, workspace.ownIdentities, workspace.shareCategories) : getMaxMemoryIdForProjects(db, [memPath]) : 0,
|
|
16114
|
-
maxMutationId: getMaxM0MutationId(db,
|
|
16545
|
+
maxMutationId: getMaxM0MutationId(db, state2.sessionId) ?? 0,
|
|
16115
16546
|
maxMemoryMutationId: memPath ? workspace.isWorkspaced ? getMaxMemoryMutationIdForProjects(db, workspace.expandedIdentities) ?? 0 : getMaxMemoryMutationId(db, memPath) ?? 0 : 0,
|
|
16116
16547
|
projectMemoryEpoch: projectState?.projectMemoryEpoch ?? 0,
|
|
16117
16548
|
workspaceFingerprint: workspace.isWorkspaced ? computeWorkspaceEpochFingerprint(db, workspace.identities) : null,
|
|
16118
16549
|
projectUserProfileVersion: globalState?.projectUserProfileVersion ?? 0,
|
|
16119
16550
|
projectDocsHash: docs.canonicalHash,
|
|
16120
|
-
sessionFactsVersion: getSessionFactsVersion(db,
|
|
16551
|
+
sessionFactsVersion: getSessionFactsVersion(db, state2.sessionId),
|
|
16121
16552
|
materializedAt: memoryCutoff ?? Date.now(),
|
|
16122
16553
|
upgradeState: `${PI_M0_UPGRADE_STATE}:${compartments.some((c) => c.legacy === 1) ? "legacy" : "ready"}`,
|
|
16123
16554
|
compartmentRenderEpoch: COMPARTMENT_RENDER_EPOCH,
|
|
16124
16555
|
lastBaselineEndMessageId: lastBaselineEndMessageId(compartments),
|
|
16125
|
-
systemHash: (
|
|
16126
|
-
modelKey: (
|
|
16127
|
-
projectIdentity:
|
|
16556
|
+
systemHash: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).systemHash,
|
|
16557
|
+
modelKey: (state2.hardSignals ?? EMPTY_PI_HARD_SIGNALS).modelKey,
|
|
16558
|
+
projectIdentity: state2.projectIdentity
|
|
16128
16559
|
};
|
|
16129
16560
|
return { docs, markers, compartments, memories, userProfile, workspace };
|
|
16130
16561
|
});
|
|
16131
16562
|
return read();
|
|
16132
16563
|
}
|
|
16133
|
-
function renderFreshM0PiNonPersisted(
|
|
16134
|
-
const docs = readProjectDocsForPiM0(
|
|
16135
|
-
const cachedMaterializedAt = getOrCreateSessionMeta(db,
|
|
16136
|
-
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);
|
|
16137
16568
|
frozen.markers.materializedAt = cachedMaterializedAt;
|
|
16138
|
-
const historyBudget =
|
|
16139
|
-
const memoryBudget =
|
|
16140
|
-
const mural = resolveMuralForM0Pi(
|
|
16141
|
-
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);
|
|
16142
16573
|
let dpm = 1;
|
|
16143
|
-
let m0 = renderM0Pi(
|
|
16574
|
+
let m0 = renderM0Pi(state2, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace, mural);
|
|
16144
16575
|
let attempts = 0;
|
|
16145
16576
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
16146
16577
|
dpm *= 1.15;
|
|
16147
|
-
m0 = renderM0Pi(
|
|
16578
|
+
m0 = renderM0Pi(state2, db, docs.renderedBlock, dpm, frozen.memories, frozen.compartments, frozen.userProfile, frozen.workspace, mural);
|
|
16148
16579
|
attempts += 1;
|
|
16149
16580
|
}
|
|
16150
16581
|
return {
|
|
16151
16582
|
m0,
|
|
16152
16583
|
snapshotMarkers: frozen.markers,
|
|
16153
|
-
renderedMemoryIds: renderedMemoryIdsForPi(
|
|
16584
|
+
renderedMemoryIds: renderedMemoryIdsForPi(state2, frozen.memories, frozen.workspace, db)
|
|
16154
16585
|
};
|
|
16155
16586
|
}
|
|
16156
|
-
function materializeM0Pi(
|
|
16157
|
-
const docs = readProjectDocsForPiM0(
|
|
16587
|
+
function materializeM0Pi(state2, db) {
|
|
16588
|
+
const docs = readProjectDocsForPiM0(state2);
|
|
16158
16589
|
const foldMaterializedAt = Date.now();
|
|
16159
|
-
const frozen = readFrozenM0InputsPi(
|
|
16590
|
+
const frozen = readFrozenM0InputsPi(state2, db, docs, foldMaterializedAt);
|
|
16160
16591
|
const snapshotMarkers = frozen.markers;
|
|
16161
16592
|
const snapshotMemories = frozen.memories;
|
|
16162
16593
|
const snapshotCompartments = frozen.compartments;
|
|
16163
16594
|
const snapshotUserProfile = frozen.userProfile;
|
|
16164
|
-
const renderedMemoryIds = renderedMemoryIdsForPi(
|
|
16165
|
-
const memoryBudget =
|
|
16166
|
-
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);
|
|
16167
16598
|
const frozenMuralDataUrl = mural?.enabled && mural.supportsVision ? mural.dataUrl ?? null : null;
|
|
16168
16599
|
const frozenMuralHash = mural?.enabled && mural.supportsVision ? mural.contentHash ?? null : null;
|
|
16169
16600
|
let decayPressureMultiplier = 1;
|
|
16170
|
-
let m0 = renderM0Pi(
|
|
16171
|
-
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;
|
|
16172
16603
|
let attempts = 0;
|
|
16173
16604
|
while (historyBudget > 0 && historySliceTokensPi(m0) > historyBudget * 1.05 && attempts < 3) {
|
|
16174
16605
|
decayPressureMultiplier *= 1.15;
|
|
16175
|
-
m0 = renderM0Pi(
|
|
16606
|
+
m0 = renderM0Pi(state2, db, docs.renderedBlock, decayPressureMultiplier, snapshotMemories, snapshotCompartments, snapshotUserProfile, frozen.workspace, mural);
|
|
16176
16607
|
attempts += 1;
|
|
16177
16608
|
}
|
|
16178
16609
|
const m0Bytes = Buffer.from(m0, "utf8");
|
|
16179
|
-
const phase3ProjectDocsHash = readProjectDocsForPiM0(
|
|
16610
|
+
const phase3ProjectDocsHash = readProjectDocsForPiM0(state2).canonicalHash;
|
|
16180
16611
|
try {
|
|
16181
16612
|
db.exec("BEGIN IMMEDIATE");
|
|
16182
16613
|
} catch (error) {
|
|
@@ -16186,7 +16617,7 @@ function materializeM0Pi(state, db) {
|
|
|
16186
16617
|
throw error;
|
|
16187
16618
|
}
|
|
16188
16619
|
try {
|
|
16189
|
-
const current = readCurrentMarkers(db,
|
|
16620
|
+
const current = readCurrentMarkers(db, state2, phase3ProjectDocsHash);
|
|
16190
16621
|
const memoryEpochStale = current.workspaceFingerprint !== null || snapshotMarkers.workspaceFingerprint !== null ? current.workspaceFingerprint !== snapshotMarkers.workspaceFingerprint : current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch;
|
|
16191
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;
|
|
16192
16623
|
if (stale) {
|
|
@@ -16194,9 +16625,9 @@ function materializeM0Pi(state, db) {
|
|
|
16194
16625
|
throw new PiMaterializeContentionError("snapshot changed before persist");
|
|
16195
16626
|
}
|
|
16196
16627
|
snapshotMarkers.materializedAt = foldMaterializedAt;
|
|
16197
|
-
const m1Render = renderM1PiWithMetadata(
|
|
16628
|
+
const m1Render = renderM1PiWithMetadata(state2, db, snapshotMarkers, renderedMemoryIds);
|
|
16198
16629
|
const m1Bytes = Buffer.from(m1Render.text, "utf8");
|
|
16199
|
-
persistCachedM0(db,
|
|
16630
|
+
persistCachedM0(db, state2.sessionId, {
|
|
16200
16631
|
m0Bytes,
|
|
16201
16632
|
muralDataUrl: frozenMuralDataUrl,
|
|
16202
16633
|
muralHash: frozenMuralHash,
|
|
@@ -16216,10 +16647,10 @@ function materializeM0Pi(state, db) {
|
|
|
16216
16647
|
modelKey: snapshotMarkers.modelKey,
|
|
16217
16648
|
projectIdentity: snapshotMarkers.projectIdentity
|
|
16218
16649
|
});
|
|
16219
|
-
db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(renderedMemoryIds.length, JSON.stringify(renderedMemoryIds),
|
|
16220
|
-
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);
|
|
16221
16652
|
db.exec("COMMIT");
|
|
16222
|
-
rememberPiMuralPayload(
|
|
16653
|
+
rememberPiMuralPayload(state2.sessionId, frozenMuralDataUrl, frozenMuralHash);
|
|
16223
16654
|
return {
|
|
16224
16655
|
m0,
|
|
16225
16656
|
m1: m1Render.text,
|
|
@@ -16233,11 +16664,11 @@ function materializeM0Pi(state, db) {
|
|
|
16233
16664
|
throw error;
|
|
16234
16665
|
}
|
|
16235
16666
|
}
|
|
16236
|
-
function materializeM0PiWithRetry(
|
|
16667
|
+
function materializeM0PiWithRetry(state2, db, maxRetries = 3) {
|
|
16237
16668
|
let lastError = null;
|
|
16238
16669
|
for (let attempt = 0;attempt < maxRetries; attempt++) {
|
|
16239
16670
|
try {
|
|
16240
|
-
return materializeM0Pi(
|
|
16671
|
+
return materializeM0Pi(state2, db);
|
|
16241
16672
|
} catch (error) {
|
|
16242
16673
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16243
16674
|
throw error;
|
|
@@ -16279,10 +16710,10 @@ ${lines.join(`
|
|
|
16279
16710
|
count: mutations.length
|
|
16280
16711
|
};
|
|
16281
16712
|
}
|
|
16282
|
-
function renderM1PiWithMetadata(
|
|
16713
|
+
function renderM1PiWithMetadata(state2, db, markers, renderedMemoryIds, compartmentsOverride) {
|
|
16283
16714
|
const sections = [];
|
|
16284
|
-
const workspace = resolveWorkspaceRenderContextPi(
|
|
16285
|
-
const memPath = memoryProjectPath(
|
|
16715
|
+
const workspace = resolveWorkspaceRenderContextPi(state2, db);
|
|
16716
|
+
const memPath = memoryProjectPath(state2);
|
|
16286
16717
|
const memoryUpdates = memPath ? renderMemoryUpdatesBlockPi({
|
|
16287
16718
|
db,
|
|
16288
16719
|
projectPath: memPath,
|
|
@@ -16292,7 +16723,7 @@ function renderM1PiWithMetadata(state, db, markers, renderedMemoryIds, compartme
|
|
|
16292
16723
|
}) : { block: undefined, count: 0 };
|
|
16293
16724
|
if (memoryUpdates.block)
|
|
16294
16725
|
sections.push(memoryUpdates.block);
|
|
16295
|
-
const newCompartments = (compartmentsOverride ??
|
|
16726
|
+
const newCompartments = (compartmentsOverride ?? getRenderableCompartmentsPi(db, state2)).filter((compartment) => compartment.sequence > markers.maxCompartmentSeq);
|
|
16296
16727
|
if (newCompartments.length > 0) {
|
|
16297
16728
|
const body = newCompartments.map((compartment) => renderCompartmentAtTier(compartment, 1)).join(`
|
|
16298
16729
|
|
|
@@ -16303,7 +16734,7 @@ ${body}
|
|
|
16303
16734
|
}
|
|
16304
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) : [];
|
|
16305
16736
|
if (newMemories.length > 0) {
|
|
16306
|
-
const memoryBudget =
|
|
16737
|
+
const memoryBudget = state2.injectionBudgetTokens ?? DEFAULT_MEMORY_BUDGET_TOKENS;
|
|
16307
16738
|
const memoryRenderOptions = {
|
|
16308
16739
|
sourceNameByMemoryId: sourceNamesForPiMemories({
|
|
16309
16740
|
memories: newMemories,
|
|
@@ -16311,14 +16742,14 @@ ${body}
|
|
|
16311
16742
|
workspace
|
|
16312
16743
|
})
|
|
16313
16744
|
};
|
|
16314
|
-
const trimmedNewMemories = trimMemoriesToBudgetV2(
|
|
16745
|
+
const trimmedNewMemories = trimMemoriesToBudgetV2(state2.sessionId, newMemories, Math.max(1, Math.floor(memoryBudget * 0.25)), memoryRenderOptions).renderOrder;
|
|
16315
16746
|
const newMemoriesBlock = renderMemoryBlockV2(trimmedNewMemories, "new-memories", memoryRenderOptions);
|
|
16316
16747
|
if (newMemoriesBlock)
|
|
16317
16748
|
sections.push(newMemoriesBlock);
|
|
16318
16749
|
}
|
|
16319
16750
|
const currentUserProfileVersion = getProjectState(db, GLOBAL_USER_PROFILE_PROJECT_PATH)?.projectUserProfileVersion ?? 0;
|
|
16320
16751
|
if (currentUserProfileVersion !== markers.projectUserProfileVersion) {
|
|
16321
|
-
const profileBudget =
|
|
16752
|
+
const profileBudget = state2.userProfileBudgetTokens ?? DEFAULT_USER_PROFILE_BUDGET_TOKENS;
|
|
16322
16753
|
const trimmedProfile = trimUserMemoriesToBudget(safeGetActiveUserMemoriesPi(db), Math.max(1, Math.floor(profileBudget * 0.25)));
|
|
16323
16754
|
const profileBlock = renderUserProfileBlock(db, "new-user-profile", trimmedProfile);
|
|
16324
16755
|
if (profileBlock)
|
|
@@ -16331,7 +16762,10 @@ ${body}
|
|
|
16331
16762
|
};
|
|
16332
16763
|
}
|
|
16333
16764
|
return {
|
|
16334
|
-
text: `<
|
|
16765
|
+
text: state2.compactionOff ? `<knowledge-updates>
|
|
16766
|
+
${sections.join(`
|
|
16767
|
+
`)}
|
|
16768
|
+
</knowledge-updates>` : `<session-history-since>
|
|
16335
16769
|
${sections.join(`
|
|
16336
16770
|
`)}
|
|
16337
16771
|
</session-history-since>`,
|
|
@@ -16427,8 +16861,8 @@ function cachedPiRowMatchesSnapshot(args) {
|
|
|
16427
16861
|
return false;
|
|
16428
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);
|
|
16429
16863
|
}
|
|
16430
|
-
function adoptCachedPiProjectIdentity(db,
|
|
16431
|
-
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);
|
|
16432
16866
|
}
|
|
16433
16867
|
function decodeCachedM1(row, sessionId) {
|
|
16434
16868
|
if (!row.cached_m1_bytes) {
|
|
@@ -16449,12 +16883,12 @@ function applyCachedPiRow(args) {
|
|
|
16449
16883
|
markers
|
|
16450
16884
|
};
|
|
16451
16885
|
}
|
|
16452
|
-
function replayCachedM1Pi(db,
|
|
16453
|
-
const row = readCachedPiM0M1Row(db,
|
|
16886
|
+
function replayCachedM1Pi(db, state2, compartmentsForNormalization) {
|
|
16887
|
+
const row = readCachedPiM0M1Row(db, state2.sessionId);
|
|
16454
16888
|
if (!row) {
|
|
16455
|
-
throw new PiMaterializeContentionError(`missing cached m[0]/m[1] for ${
|
|
16889
|
+
throw new PiMaterializeContentionError(`missing cached m[0]/m[1] for ${state2.sessionId}`);
|
|
16456
16890
|
}
|
|
16457
|
-
return applyCachedPiRow({ row, state, compartmentsForNormalization });
|
|
16891
|
+
return applyCachedPiRow({ row, state: state2, compartmentsForNormalization });
|
|
16458
16892
|
}
|
|
16459
16893
|
function softRefreshCachedM1Pi(args) {
|
|
16460
16894
|
args.db.exec("BEGIN IMMEDIATE");
|
|
@@ -16471,7 +16905,7 @@ function softRefreshCachedM1Pi(args) {
|
|
|
16471
16905
|
if (!sibling) {
|
|
16472
16906
|
throw new PiMaterializeContentionError(`missing sibling cached m[0]/m[1] for ${args.state.sessionId}`);
|
|
16473
16907
|
}
|
|
16474
|
-
const siblingCompartments =
|
|
16908
|
+
const siblingCompartments = getRenderableCompartmentsPi(args.db, args.state);
|
|
16475
16909
|
return {
|
|
16476
16910
|
...applyCachedPiRow({
|
|
16477
16911
|
row: sibling,
|
|
@@ -16538,9 +16972,9 @@ function prependM0M1Messages(piMessages, m0, m1, mural) {
|
|
|
16538
16972
|
timestamp: baseTimestamp - 1
|
|
16539
16973
|
});
|
|
16540
16974
|
}
|
|
16541
|
-
function injectM0M1Pi(
|
|
16542
|
-
const currentCompartments =
|
|
16543
|
-
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);
|
|
16544
16978
|
let m0 = "";
|
|
16545
16979
|
let m1 = PI_M1_PLACEHOLDER;
|
|
16546
16980
|
let markers = null;
|
|
@@ -16551,7 +16985,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16551
16985
|
let freshFallbackRenderedMemoryIds = null;
|
|
16552
16986
|
if (decision.value) {
|
|
16553
16987
|
try {
|
|
16554
|
-
const result = materializeM0PiWithRetry(
|
|
16988
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16555
16989
|
m0 = result.m0;
|
|
16556
16990
|
m1 = result.m1;
|
|
16557
16991
|
markers = result.snapshotMarkers;
|
|
@@ -16561,30 +16995,30 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16561
16995
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16562
16996
|
throw error;
|
|
16563
16997
|
try {
|
|
16564
|
-
const cached = replayCachedM1Pi(db,
|
|
16998
|
+
const cached = replayCachedM1Pi(db, state2, currentCompartments);
|
|
16565
16999
|
contentionExhausted = true;
|
|
16566
17000
|
m0 = cached.m0;
|
|
16567
17001
|
m1 = cached.m1;
|
|
16568
17002
|
markers = cached.markers;
|
|
16569
|
-
sessionLog(
|
|
17003
|
+
sessionLog(state2.sessionId, "pi m[0] materialization contention exhausted; reusing cached m[0]/m[1]");
|
|
16570
17004
|
} catch {
|
|
16571
|
-
const fresh = renderFreshM0PiNonPersisted(
|
|
17005
|
+
const fresh = renderFreshM0PiNonPersisted(state2, db);
|
|
16572
17006
|
m0 = fresh.m0;
|
|
16573
17007
|
markers = fresh.snapshotMarkers;
|
|
16574
17008
|
freshFallbackRenderedMemoryIds = fresh.renderedMemoryIds;
|
|
16575
17009
|
contentionExhausted = true;
|
|
16576
|
-
sessionLog(
|
|
17010
|
+
sessionLog(state2.sessionId, "pi m[0] materialization contention exhausted with no cached fallback; rendered fresh non-persisted m[0]/m[1]");
|
|
16577
17011
|
}
|
|
16578
17012
|
}
|
|
16579
17013
|
} else {
|
|
16580
|
-
const meta = getOrCreateSessionMeta(db,
|
|
17014
|
+
const meta = getOrCreateSessionMeta(db, state2.sessionId);
|
|
16581
17015
|
m0 = decodeCachedM0(meta.cachedM0Bytes) ?? "";
|
|
16582
|
-
rememberPiMuralPayload(
|
|
16583
|
-
markers = getCachedMarkers(db,
|
|
17016
|
+
rememberPiMuralPayload(state2.sessionId, meta.cachedM0MuralDataUrl, meta.cachedM0MuralHash);
|
|
17017
|
+
markers = getCachedMarkers(db, state2, currentCompartments);
|
|
16584
17018
|
if (!m0 || !markers) {
|
|
16585
17019
|
decision = { value: true, reason: "cache_invalid" };
|
|
16586
17020
|
try {
|
|
16587
|
-
const result = materializeM0PiWithRetry(
|
|
17021
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16588
17022
|
m0 = result.m0;
|
|
16589
17023
|
m1 = result.m1;
|
|
16590
17024
|
markers = result.snapshotMarkers;
|
|
@@ -16593,30 +17027,30 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16593
17027
|
} catch (error) {
|
|
16594
17028
|
if (!(error instanceof PiMaterializeContentionError))
|
|
16595
17029
|
throw error;
|
|
16596
|
-
const fresh = renderFreshM0PiNonPersisted(
|
|
17030
|
+
const fresh = renderFreshM0PiNonPersisted(state2, db);
|
|
16597
17031
|
m0 = fresh.m0;
|
|
16598
17032
|
markers = fresh.snapshotMarkers;
|
|
16599
17033
|
freshFallbackRenderedMemoryIds = fresh.renderedMemoryIds;
|
|
16600
17034
|
contentionExhausted = true;
|
|
16601
|
-
sessionLog(
|
|
17035
|
+
sessionLog(state2.sessionId, "pi m[0] cache_invalid materialization contention exhausted; rendered fresh non-persisted m[0]/m[1]");
|
|
16602
17036
|
}
|
|
16603
17037
|
}
|
|
16604
17038
|
}
|
|
16605
17039
|
if (!markers) {
|
|
16606
|
-
throw new PiMaterializeContentionError(`missing m[0] markers for ${
|
|
17040
|
+
throw new PiMaterializeContentionError(`missing m[0] markers for ${state2.sessionId}`);
|
|
16607
17041
|
}
|
|
16608
17042
|
if (!materialized && markers.projectIdentity === null) {
|
|
16609
|
-
adoptCachedPiProjectIdentity(db,
|
|
16610
|
-
markers = { ...markers, projectIdentity:
|
|
17043
|
+
adoptCachedPiProjectIdentity(db, state2);
|
|
17044
|
+
markers = { ...markers, projectIdentity: state2.projectIdentity };
|
|
16611
17045
|
}
|
|
16612
17046
|
if (materialized) {} else if (contentionExhausted && freshFallbackRenderedMemoryIds) {
|
|
16613
|
-
const freshM1 = renderM1PiWithMetadata(
|
|
17047
|
+
const freshM1 = renderM1PiWithMetadata(state2, db, markers, freshFallbackRenderedMemoryIds);
|
|
16614
17048
|
m1 = freshM1.text;
|
|
16615
17049
|
memoryUpdateCount = freshM1.memoryUpdateCount;
|
|
16616
17050
|
m1Recomputed = true;
|
|
16617
17051
|
} else if (contentionExhausted) {} else if (recomputeM1ThisPass) {
|
|
16618
17052
|
const refreshed = softRefreshCachedM1Pi({
|
|
16619
|
-
state,
|
|
17053
|
+
state: state2,
|
|
16620
17054
|
db,
|
|
16621
17055
|
m0Bytes: Buffer.from(m0, "utf8"),
|
|
16622
17056
|
markers,
|
|
@@ -16628,7 +17062,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16628
17062
|
memoryUpdateCount = refreshed.memoryUpdateCount;
|
|
16629
17063
|
m1Recomputed = refreshed.recomputed;
|
|
16630
17064
|
} else {
|
|
16631
|
-
const replayed = replayCachedM1Pi(db,
|
|
17065
|
+
const replayed = replayCachedM1Pi(db, state2, currentCompartments);
|
|
16632
17066
|
m0 = replayed.m0;
|
|
16633
17067
|
m1 = replayed.m1;
|
|
16634
17068
|
markers = replayed.markers;
|
|
@@ -16636,14 +17070,14 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16636
17070
|
const M0_DRIFT_RATIO_FLOOR_TOKENS = 500;
|
|
16637
17071
|
const M1_DRIFT_RATIO = 0.15;
|
|
16638
17072
|
const M1_ABSOLUTE_CAP_RATIO = 0.2;
|
|
16639
|
-
const m1AbsoluteBudget = (
|
|
17073
|
+
const m1AbsoluteBudget = (state2.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
|
|
16640
17074
|
const m1HasContent = m1 !== PI_M1_PLACEHOLDER;
|
|
16641
|
-
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(
|
|
17075
|
+
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(state2.sessionId, m0, m1);
|
|
16642
17076
|
const m1OverAbsoluteCap = m1HasContent && m1Tokens > m1AbsoluteBudget;
|
|
16643
17077
|
if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1HasContent && m0Tokens >= M0_DRIFT_RATIO_FLOOR_TOKENS && m1Tokens > m0Tokens * M1_DRIFT_RATIO)) {
|
|
16644
17078
|
decision = { value: true, reason: "drift" };
|
|
16645
17079
|
try {
|
|
16646
|
-
const result = materializeM0PiWithRetry(
|
|
17080
|
+
const result = materializeM0PiWithRetry(state2, db);
|
|
16647
17081
|
m0 = result.m0;
|
|
16648
17082
|
m1 = result.m1;
|
|
16649
17083
|
markers = result.snapshotMarkers;
|
|
@@ -16666,17 +17100,17 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
16666
17100
|
}
|
|
16667
17101
|
}
|
|
16668
17102
|
const skippedVisibleMessages = boundaryId ? trimPiMessagesToBoundary(piMessages, entryIds, boundaryId) : 0;
|
|
16669
|
-
const muralWire = m0.includes("<memory-mural>") ? muralForWire(
|
|
17103
|
+
const muralWire = m0.includes("<memory-mural>") ? muralForWire(state2.sessionId) : undefined;
|
|
16670
17104
|
if (!muralWire)
|
|
16671
17105
|
m0 = stripMemoryMuralBlock(m0);
|
|
16672
17106
|
prependM0M1Messages(piMessages, m0, m1, muralWire);
|
|
16673
|
-
sessionLog(
|
|
16674
|
-
const memPath = memoryProjectPath(
|
|
16675
|
-
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);
|
|
16676
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;
|
|
16677
17111
|
return {
|
|
16678
17112
|
injected: true,
|
|
16679
|
-
compartmentCount:
|
|
17113
|
+
compartmentCount: currentCompartments.length,
|
|
16680
17114
|
factCount: 0,
|
|
16681
17115
|
memoryCount,
|
|
16682
17116
|
skippedVisibleMessages,
|
|
@@ -16738,6 +17172,16 @@ function isSentinelPart(part) {
|
|
|
16738
17172
|
return p.type === "text" && typeof p.text === "string" && (p.text === "" || p.text === WHOLE_MESSAGE_PLACEHOLDER_TEXT);
|
|
16739
17173
|
}
|
|
16740
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
|
+
|
|
16741
17185
|
// src/pi-historian-runner.ts
|
|
16742
17186
|
import * as crypto2 from "node:crypto";
|
|
16743
17187
|
|
|
@@ -19928,6 +20372,7 @@ async function runPiHistorian(deps) {
|
|
|
19928
20372
|
twoPass,
|
|
19929
20373
|
thinkingLevel,
|
|
19930
20374
|
memoryEnabled,
|
|
20375
|
+
allowHomeProject,
|
|
19931
20376
|
autoPromote,
|
|
19932
20377
|
userMemoriesEnabled,
|
|
19933
20378
|
onPublished,
|
|
@@ -20066,7 +20511,7 @@ async function runPiHistorian(deps) {
|
|
|
20066
20511
|
rollbackDrainReservation();
|
|
20067
20512
|
return;
|
|
20068
20513
|
}
|
|
20069
|
-
const projectPath = resolveProjectIdentityForSession(directory);
|
|
20514
|
+
const projectPath = resolveProjectIdentityForSession(directory, allowHomeProject);
|
|
20070
20515
|
if (!projectPath) {
|
|
20071
20516
|
rollbackDrainReservation();
|
|
20072
20517
|
return;
|
|
@@ -22021,7 +22466,6 @@ function extractStableId(msg, index, entryIds) {
|
|
|
22021
22466
|
}
|
|
22022
22467
|
|
|
22023
22468
|
// src/context-handler.ts
|
|
22024
|
-
var FORCE_MATERIALIZATION_PERCENTAGE = 85;
|
|
22025
22469
|
var EMERGENCY_BLOCK_PERCENTAGE = 95;
|
|
22026
22470
|
var FORWARD_PRESSURE_LIMIT_FACTOR = 0.85;
|
|
22027
22471
|
function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUsageTokens, correctedLimit) {
|
|
@@ -22643,8 +23087,8 @@ function parsePiFallbackToolOwnerId(ownerMsgId) {
|
|
|
22643
23087
|
return { timestamp, role: match[2] ?? "" };
|
|
22644
23088
|
}
|
|
22645
23089
|
function databaseIsInTransaction(db) {
|
|
22646
|
-
const
|
|
22647
|
-
return
|
|
23090
|
+
const state2 = db;
|
|
23091
|
+
return state2.inTransaction === true || state2.isTransaction === true;
|
|
22648
23092
|
}
|
|
22649
23093
|
function runImmediateTransaction(db, fn) {
|
|
22650
23094
|
if (databaseIsInTransaction(db)) {
|
|
@@ -22770,7 +23214,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22770
23214
|
const options = baseOptions.resolveForProject?.(projectDirectory) ?? baseOptions;
|
|
22771
23215
|
const schedulerConfig = options.scheduler ?? DEFAULT_SCHEDULER_CONFIG;
|
|
22772
23216
|
const scheduler = schedulerFor(options);
|
|
22773
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDirectory) ?? "";
|
|
23217
|
+
const projectIdentity = resolveProjectIdentityForSession(projectDirectory, options.allowHomeProject) ?? "";
|
|
22774
23218
|
updateSessionProjectTracking(sessionId, projectIdentity, options.db);
|
|
22775
23219
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
22776
23220
|
const tEntryBranch = performance.now();
|
|
@@ -22792,7 +23236,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22792
23236
|
const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
|
|
22793
23237
|
const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
|
|
22794
23238
|
const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
|
|
22795
|
-
if (strictEntryIds && options.injection) {
|
|
23239
|
+
if (strictEntryIds && options.injection && !options.compactionOff) {
|
|
22796
23240
|
const removed = trimPiMessagesToCachedBoundary(options.db, sessionId, event.messages, strictEntryIds);
|
|
22797
23241
|
if (removed > 0) {
|
|
22798
23242
|
logTransformTiming(sessionId, "cachedBoundaryEarlyTrim", tEntryBranch, `removed=${removed}`);
|
|
@@ -22840,10 +23284,34 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22840
23284
|
const tMeta = performance.now();
|
|
22841
23285
|
const sessionMetaForUsage = getOrCreateSessionMeta(options.db, sessionId);
|
|
22842
23286
|
logTransformTiming(sessionId, "getOrCreateSessionMeta", tMeta);
|
|
22843
|
-
const
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
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
|
+
}
|
|
23311
|
+
const usageReset = {
|
|
23312
|
+
lastContextPercentage: 0,
|
|
23313
|
+
lastInputTokens: 0,
|
|
23314
|
+
observedSafeInputTokens: 0,
|
|
22847
23315
|
cacheAlertSent: false
|
|
22848
23316
|
};
|
|
22849
23317
|
if (modelChanged) {
|
|
@@ -22883,12 +23351,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22883
23351
|
usageInputTokens = typeof piUsage?.tokens === "number" ? piUsage.tokens : 0;
|
|
22884
23352
|
}
|
|
22885
23353
|
let usageContextLimit = isSaneLimit(piUsage?.contextWindow) ? piUsage.contextWindow : undefined;
|
|
23354
|
+
let detectedContextLimit;
|
|
22886
23355
|
const tEmergencyRecovery = performance.now();
|
|
22887
23356
|
let needsEmergencyBump = false;
|
|
22888
23357
|
let emergencyRecoveryArmed = false;
|
|
22889
23358
|
try {
|
|
22890
|
-
const overflowState = getOverflowState(options.db, sessionId);
|
|
23359
|
+
const overflowState = options.compactionOff ? { detectedContextLimit: 0, needsEmergencyRecovery: false } : getOverflowState(options.db, sessionId);
|
|
22891
23360
|
if (overflowState.detectedContextLimit > 0) {
|
|
23361
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
22892
23362
|
usageContextLimit = Math.min(usageContextLimit ?? overflowState.detectedContextLimit, overflowState.detectedContextLimit);
|
|
22893
23363
|
}
|
|
22894
23364
|
emergencyRecoveryArmed = overflowState.needsEmergencyRecovery;
|
|
@@ -22906,6 +23376,17 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22906
23376
|
usageContextLimit = modelWindow;
|
|
22907
23377
|
}
|
|
22908
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);
|
|
22909
23390
|
if (!usedPersistedUsage && isSaneLimit(usageContextLimit) && usageInputTokens > 0) {
|
|
22910
23391
|
usagePercentage = usageInputTokens / usageContextLimit * 100;
|
|
22911
23392
|
}
|
|
@@ -22926,7 +23407,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22926
23407
|
logTransformTiming(sessionId, "schedulerAndUsage", tScheduler);
|
|
22927
23408
|
const piMessageCount = fullWireMessageCount;
|
|
22928
23409
|
const looksLikeImportedSession = schedulerDecision === "defer" && usagePercentage === 0 && sessionMeta.lastResponseTime === 0 && piMessageCount >= 50;
|
|
22929
|
-
if (looksLikeImportedSession) {
|
|
23410
|
+
if (looksLikeImportedSession && !options.compactionOff) {
|
|
22930
23411
|
schedulerDecision = "execute";
|
|
22931
23412
|
sessionLog(sessionId, `transform: large imported session detected (${piMessageCount} messages, no usage baseline) — forcing execute on first pass`);
|
|
22932
23413
|
}
|
|
@@ -22937,7 +23418,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22937
23418
|
if (storedStableIdScheme < PI_STABLE_ID_SCHEME && !realEntryIdsAvailable) {
|
|
22938
23419
|
sessionLog(sessionId, `stable-id scheme cutover deferred: real SessionEntry ids unavailable this pass (branch resolution failed) — will retry when getBranch() succeeds`);
|
|
22939
23420
|
}
|
|
22940
|
-
if (stableIdSchemeCutover) {
|
|
23421
|
+
if (stableIdSchemeCutover && !options.compactionOff) {
|
|
22941
23422
|
schedulerDecision = "execute";
|
|
22942
23423
|
signalPiPendingMaterialization(sessionId);
|
|
22943
23424
|
sessionLog(sessionId, `stable-id scheme cutover: stored=${storedStableIdScheme} < current=${PI_STABLE_ID_SCHEME} — forcing execute+materialize this pass`);
|
|
@@ -22949,14 +23430,18 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22949
23430
|
contextUsage: { percentage: usagePercentage },
|
|
22950
23431
|
sessionMeta,
|
|
22951
23432
|
historyRefreshSessions,
|
|
22952
|
-
sessionId
|
|
23433
|
+
sessionId,
|
|
23434
|
+
effectiveExecuteThresholdPercentage
|
|
22953
23435
|
});
|
|
22954
|
-
const { midTurnAdjustedSchedulerDecision, sideEffect } =
|
|
23436
|
+
const { midTurnAdjustedSchedulerDecision, sideEffect } = options.compactionOff ? {
|
|
23437
|
+
midTurnAdjustedSchedulerDecision: "defer",
|
|
23438
|
+
sideEffect: "none"
|
|
23439
|
+
} : applyMidTurnDeferral({
|
|
22955
23440
|
base: schedulerDecisionEarly,
|
|
22956
23441
|
bypassReason,
|
|
22957
23442
|
midTurn
|
|
22958
23443
|
});
|
|
22959
|
-
if (sideEffect === "set-flag") {
|
|
23444
|
+
if (sideEffect === "set-flag" && !options.compactionOff) {
|
|
22960
23445
|
const flagPayload = {
|
|
22961
23446
|
id: crypto3.randomUUID(),
|
|
22962
23447
|
reason: `${schedulerDecisionEarly}-${bypassReason}`,
|
|
@@ -22966,8 +23451,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22966
23451
|
}
|
|
22967
23452
|
schedulerDecision = midTurnAdjustedSchedulerDecision;
|
|
22968
23453
|
sessionLog(sessionId, `[boundary-exec] base=${schedulerDecisionEarly} bypass=${bypassReason} midTurn=${midTurn} effective=${midTurnAdjustedSchedulerDecision} sideEffect=${sideEffect}`);
|
|
22969
|
-
const forceMaterialization = usagePercentage >=
|
|
22970
|
-
const isEmergency = usagePercentage >= EMERGENCY_BLOCK_PERCENTAGE;
|
|
23454
|
+
const forceMaterialization = !options.compactionOff && usagePercentage >= forceMaterializationPercentage;
|
|
23455
|
+
const isEmergency = !options.compactionOff && usagePercentage >= EMERGENCY_BLOCK_PERCENTAGE;
|
|
22971
23456
|
if (isEmergency) {
|
|
22972
23457
|
const lastNotifiedAt = lastEmergencyNotificationAtMs.get(sessionId) ?? 0;
|
|
22973
23458
|
const now = Date.now();
|
|
@@ -22983,7 +23468,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
22983
23468
|
sessionLog(sessionId, "EMERGENCY: historian wait completed (or timed out)");
|
|
22984
23469
|
} catch {}
|
|
22985
23470
|
}
|
|
22986
|
-
if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump <
|
|
23471
|
+
if (emergencyRecoveryArmed && realUsagePercentageBeforeEmergencyBump < forceMaterializationPercentage && !inFlightHistorian.has(sessionId) && !hasEligiblePiCompartmentHistory(options.db, sessionId)) {
|
|
22987
23472
|
try {
|
|
22988
23473
|
clearEmergencyRecovery(options.db, sessionId);
|
|
22989
23474
|
sessionLog(sessionId, "EMERGENCY: disarming recovery — no eligible pre-tail history to compact (would otherwise loop at 95%)");
|
|
@@ -23035,6 +23520,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23035
23520
|
stableIdSchemeCutover,
|
|
23036
23521
|
schedulerDecision,
|
|
23037
23522
|
forceMaterialization: forceMaterialization || isEmergency,
|
|
23523
|
+
forceMaterializationPercentage,
|
|
23038
23524
|
contextUsage: {
|
|
23039
23525
|
percentage: usagePercentage,
|
|
23040
23526
|
inputTokens: usageInputTokens
|
|
@@ -23047,7 +23533,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23047
23533
|
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
23048
23534
|
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
23049
23535
|
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
23050
|
-
isSubagent: sessionMeta.isSubagent
|
|
23536
|
+
isSubagent: sessionMeta.isSubagent,
|
|
23537
|
+
compactionOff: options.compactionOff === true
|
|
23051
23538
|
});
|
|
23052
23539
|
logTransformTiming(sessionId, "runPipeline", tRunPipeline);
|
|
23053
23540
|
const postPipelineStart = performance.now();
|
|
@@ -23071,7 +23558,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23071
23558
|
}
|
|
23072
23559
|
logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
|
|
23073
23560
|
const tHistorianScheduling = performance.now();
|
|
23074
|
-
if (options.historian) {
|
|
23561
|
+
if (options.historian && !options.compactionOff) {
|
|
23075
23562
|
maybeFireHistorian({
|
|
23076
23563
|
pi,
|
|
23077
23564
|
ctx,
|
|
@@ -23089,22 +23576,24 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23089
23576
|
let outputMessages = result.messages;
|
|
23090
23577
|
const tNoteNudges = performance.now();
|
|
23091
23578
|
try {
|
|
23092
|
-
|
|
23093
|
-
|
|
23094
|
-
|
|
23095
|
-
|
|
23096
|
-
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23100
|
-
|
|
23101
|
-
|
|
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
|
+
}
|
|
23102
23591
|
} catch (err) {
|
|
23103
23592
|
sessionLog(sessionId, `note nudges failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
23104
23593
|
}
|
|
23105
23594
|
logTransformTiming(sessionId, "noteNudges", tNoteNudges);
|
|
23106
23595
|
const tAutoSearch = performance.now();
|
|
23107
|
-
if (options.autoSearch?.enabled) {
|
|
23596
|
+
if (options.autoSearch?.enabled && !options.compactionOff) {
|
|
23108
23597
|
try {
|
|
23109
23598
|
outputMessages = await runAutoSearchHintForPi({
|
|
23110
23599
|
sessionId,
|
|
@@ -23129,7 +23618,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23129
23618
|
const tTodoCapture = performance.now();
|
|
23130
23619
|
try {
|
|
23131
23620
|
const sessionMetaForTodo = getOrCreateSessionMeta(options.db, sessionId);
|
|
23132
|
-
if (!sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
23621
|
+
if (!options.compactionOff && !sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
23133
23622
|
const isCacheBustingForTodo = isCacheBusting || result.executedWorkThisPass;
|
|
23134
23623
|
outputMessages = injectSyntheticTodowriteForPi({
|
|
23135
23624
|
db: options.db,
|
|
@@ -23147,7 +23636,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23147
23636
|
const tChannelAccounting = performance.now();
|
|
23148
23637
|
try {
|
|
23149
23638
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
23150
|
-
if (!sessionMetaForCh1.isSubagent) {
|
|
23639
|
+
if (!options.compactionOff && !sessionMetaForCh1.isSubagent) {
|
|
23151
23640
|
const resolvedExecuteThresholdPct = resolveExecuteThreshold(schedulerConfig.executeThresholdPercentage ?? 65, liveModelBySession.get(sessionId), 65, {
|
|
23152
23641
|
tokensConfig: schedulerConfig.executeThresholdTokens,
|
|
23153
23642
|
contextLimit: usageContextLimit ?? 0
|
|
@@ -23214,7 +23703,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23214
23703
|
}
|
|
23215
23704
|
logTransformTiming(sessionId, "workMetrics", tWorkMetrics);
|
|
23216
23705
|
const tStableIdSchemePersist = performance.now();
|
|
23217
|
-
if (stableIdSchemeCutover) {
|
|
23706
|
+
if (stableIdSchemeCutover && !options.compactionOff) {
|
|
23218
23707
|
persistStableIdSchemeForRun(options.db, sessionId, {
|
|
23219
23708
|
piStableIdScheme: PI_STABLE_ID_SCHEME
|
|
23220
23709
|
});
|
|
@@ -23239,7 +23728,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
23239
23728
|
sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
23240
23729
|
return { messages: outputMessages };
|
|
23241
23730
|
} catch (err) {
|
|
23242
|
-
if (isFailClosedBlockingError(err))
|
|
23731
|
+
if (isFailClosedBlockingError(err) && !baseOptions.compactionOff)
|
|
23243
23732
|
throw err;
|
|
23244
23733
|
const message = err instanceof Error ? err.message : String(err);
|
|
23245
23734
|
const stack = err instanceof Error ? err.stack : undefined;
|
|
@@ -23396,6 +23885,7 @@ function spawnPiHistorianRun(args) {
|
|
|
23396
23885
|
twoPass: historian.twoPass,
|
|
23397
23886
|
thinkingLevel: historian.thinkingLevel,
|
|
23398
23887
|
memoryEnabled: historian.memoryEnabled,
|
|
23888
|
+
allowHomeProject: historian.allowHomeProject,
|
|
23399
23889
|
autoPromote: historian.autoPromote,
|
|
23400
23890
|
userMemoriesEnabled: historian.userMemoriesEnabled,
|
|
23401
23891
|
language: historian.language,
|
|
@@ -23475,15 +23965,22 @@ function maybeFireHistorian(args) {
|
|
|
23475
23965
|
const piUsage = ctx.getContextUsage?.();
|
|
23476
23966
|
let usageSource;
|
|
23477
23967
|
usageContextLimit = isSaneLimit(piUsage?.contextWindow) ? piUsage.contextWindow : undefined;
|
|
23968
|
+
let detectedContextLimit;
|
|
23478
23969
|
if (usageContextLimit === undefined && isSaneLimit(ctx.model?.contextWindow)) {
|
|
23479
23970
|
usageContextLimit = ctx.model.contextWindow;
|
|
23480
23971
|
}
|
|
23481
23972
|
try {
|
|
23482
23973
|
const overflowState = getOverflowState(db, sessionId);
|
|
23483
23974
|
if (overflowState.detectedContextLimit > 0) {
|
|
23975
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
23484
23976
|
usageContextLimit = Math.min(usageContextLimit ?? overflowState.detectedContextLimit, overflowState.detectedContextLimit);
|
|
23485
23977
|
}
|
|
23486
23978
|
} catch {}
|
|
23979
|
+
usageContextLimit = resolvePiUsableContextLimit({
|
|
23980
|
+
rawContextWindow: usageContextLimit,
|
|
23981
|
+
model: ctx.model,
|
|
23982
|
+
detectedContextLimit
|
|
23983
|
+
});
|
|
23487
23984
|
const sessionMetaForUsage = getOrCreateSessionMeta(db, sessionId);
|
|
23488
23985
|
if (sessionMetaForUsage.lastContextPercentage > 0 && sessionMetaForUsage.lastInputTokens > 0) {
|
|
23489
23986
|
usage = {
|
|
@@ -23522,6 +24019,7 @@ function maybeFireHistorian(args) {
|
|
|
23522
24019
|
modelKey,
|
|
23523
24020
|
usageContextLimit
|
|
23524
24021
|
});
|
|
24022
|
+
const historianForceMaterializationPercentage = escalationBands(triggerInputs.executeThresholdPercentage).forceMaterializationPercentage;
|
|
23525
24023
|
const boundaryContextLimit = triggerInputs.contextLimit;
|
|
23526
24024
|
const resolvePiBoundarySnapshot = (emergencyTailScale) => resolveProtectedTailBoundary(resolveBoundaryContext({
|
|
23527
24025
|
db,
|
|
@@ -23537,7 +24035,7 @@ function maybeFireHistorian(args) {
|
|
|
23537
24035
|
}));
|
|
23538
24036
|
const resolveRunnablePiBoundarySnapshot = () => {
|
|
23539
24037
|
let snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot());
|
|
23540
|
-
if (!hasRunnableCompartmentWindow(snapshot) && usage.percentage >=
|
|
24038
|
+
if (!hasRunnableCompartmentWindow(snapshot) && usage.percentage >= historianForceMaterializationPercentage) {
|
|
23541
24039
|
snapshot = ensureRunnablePiBoundaryForTests(resolvePiBoundarySnapshot(usage.percentage >= 95 ? 0.25 : 0.5));
|
|
23542
24040
|
}
|
|
23543
24041
|
return snapshot;
|
|
@@ -23581,15 +24079,15 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
23581
24079
|
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit, () => {
|
|
23582
24080
|
const messages = provider.readMessages();
|
|
23583
24081
|
return { messages, absoluteMessageCount: messages.length };
|
|
23584
|
-
}, args.taggerFloor);
|
|
24082
|
+
}, args.taggerFloor, { canClearReasoning: true });
|
|
23585
24083
|
if (!trigger.shouldFire) {
|
|
23586
24084
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
23587
24085
|
try {
|
|
23588
24086
|
const overflowState = getOverflowState(db, sessionId);
|
|
23589
|
-
if (overflowState.needsEmergencyRecovery && usage.percentage <
|
|
24087
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < historianForceMaterializationPercentage && !inFlightHistorian.has(sessionId)) {
|
|
23590
24088
|
boundarySnapshot ??= resolveRunnablePiBoundarySnapshot();
|
|
23591
24089
|
}
|
|
23592
|
-
if (overflowState.needsEmergencyRecovery && usage.percentage <
|
|
24090
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < historianForceMaterializationPercentage && !inFlightHistorian.has(sessionId) && boundarySnapshot !== undefined && !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
23593
24091
|
clearEmergencyRecovery(db, sessionId);
|
|
23594
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)`);
|
|
23595
24093
|
}
|
|
@@ -23677,7 +24175,45 @@ function captureReasoningMutationRollback(messages) {
|
|
|
23677
24175
|
}
|
|
23678
24176
|
};
|
|
23679
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
|
+
}
|
|
23680
24213
|
async function runPipeline(args) {
|
|
24214
|
+
if (args.compactionOff)
|
|
24215
|
+
return runCompactionOffPipeline(args);
|
|
24216
|
+
const forceMaterializationPercentage = args.forceMaterializationPercentage ?? escalationBands(65).forceMaterializationPercentage;
|
|
23681
24217
|
let executedWorkThisPass = false;
|
|
23682
24218
|
let historyWasConsumedThisPass = false;
|
|
23683
24219
|
let materializationSatisfiedThisPass = false;
|
|
@@ -23716,7 +24252,7 @@ async function runPipeline(args) {
|
|
|
23716
24252
|
})();
|
|
23717
24253
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
23718
24254
|
const ctxReduceCallable = !args.sessionMeta.isSubagent;
|
|
23719
|
-
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >=
|
|
24255
|
+
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= forceMaterializationPercentage;
|
|
23720
24256
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
23721
24257
|
const piHardSignals = args.injection ? (() => {
|
|
23722
24258
|
const hardMeta = args.sessionMeta;
|
|
@@ -23966,7 +24502,7 @@ async function runPipeline(args) {
|
|
|
23966
24502
|
}
|
|
23967
24503
|
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
23968
24504
|
const alreadyMutatingThisPass = pendingOpsDidMutate || heuristicOrReasoningDidMutate;
|
|
23969
|
-
const emergencyDropEligible = args.forceMaterialization === true || args.contextUsage.percentage >=
|
|
24505
|
+
const emergencyDropEligible = args.forceMaterialization === true || args.contextUsage.percentage >= forceMaterializationPercentage;
|
|
23970
24506
|
let autoReclaimTargetCount = 0;
|
|
23971
24507
|
let autoReclaimDidMutate = false;
|
|
23972
24508
|
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
@@ -24353,6 +24889,13 @@ function appendReminderToPiUserMessage(message, reminder) {
|
|
|
24353
24889
|
}
|
|
24354
24890
|
contentArr.push({ type: "text", text: reminder.trimStart() });
|
|
24355
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
|
+
}
|
|
24356
24899
|
function clearContextHandlerSession(sessionId) {
|
|
24357
24900
|
invalidateTrueRawTokenCache({ sessionId, reason: "pi.branch.changed" });
|
|
24358
24901
|
activeContextHandlerSessions.delete(sessionId);
|
|
@@ -24411,6 +24954,14 @@ No active Pi session is available.`,
|
|
|
24411
24954
|
});
|
|
24412
24955
|
return;
|
|
24413
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
|
+
}
|
|
24414
24965
|
const pendingBefore = getPendingOps(deps.db, sessionId).length;
|
|
24415
24966
|
const result = executeFlush(deps.db, sessionId);
|
|
24416
24967
|
signalPiHistoryRefresh(sessionId);
|
|
@@ -24455,6 +25006,24 @@ function historianResponseDumpDir(directory) {
|
|
|
24455
25006
|
return getProjectMagicContextHistorianDir(directory);
|
|
24456
25007
|
}
|
|
24457
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
|
+
}
|
|
24458
25027
|
async function runValidatedHistorianPass(args) {
|
|
24459
25028
|
const firstRun = await runHistorianPrompt({
|
|
24460
25029
|
...args,
|
|
@@ -24520,6 +25089,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
24520
25089
|
sessionLog(args.parentSessionId, "historian two-pass: running editor on draft");
|
|
24521
25090
|
const editorRun = await runHistorianPrompt({
|
|
24522
25091
|
client: args.client,
|
|
25092
|
+
db: args.db,
|
|
24523
25093
|
parentSessionId: args.parentSessionId,
|
|
24524
25094
|
sessionDirectory: args.sessionDirectory,
|
|
24525
25095
|
prompt: buildHistorianEditorPrompt(args.draftXml),
|
|
@@ -24546,6 +25116,7 @@ async function runEditorPassOrFallback(args) {
|
|
|
24546
25116
|
async function runHistorianPrompt(args) {
|
|
24547
25117
|
const {
|
|
24548
25118
|
client,
|
|
25119
|
+
db,
|
|
24549
25120
|
parentSessionId,
|
|
24550
25121
|
sessionDirectory,
|
|
24551
25122
|
prompt,
|
|
@@ -24579,12 +25150,12 @@ async function runHistorianPrompt(args) {
|
|
|
24579
25150
|
};
|
|
24580
25151
|
try {
|
|
24581
25152
|
sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
|
|
24582
|
-
const createResponse = await
|
|
24583
|
-
|
|
24584
|
-
|
|
24585
|
-
|
|
24586
|
-
|
|
24587
|
-
|
|
25153
|
+
const createResponse = await createChildSessionWithFence({
|
|
25154
|
+
client,
|
|
25155
|
+
db,
|
|
25156
|
+
parentSessionId,
|
|
25157
|
+
title: "magic-context-compartment",
|
|
25158
|
+
directory: sessionDirectory
|
|
24588
25159
|
});
|
|
24589
25160
|
const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
24590
25161
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
@@ -24632,7 +25203,18 @@ async function runHistorianPrompt(args) {
|
|
|
24632
25203
|
preferResponseOnMissingData: true
|
|
24633
25204
|
});
|
|
24634
25205
|
const invocationId = recordInvocation5({ status: "completed", messages });
|
|
24635
|
-
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;
|
|
24636
25218
|
if (!result) {
|
|
24637
25219
|
return {
|
|
24638
25220
|
ok: false,
|
|
@@ -24684,6 +25266,7 @@ async function runFallbackHistorianPass(args) {
|
|
|
24684
25266
|
args.callbacks?.onModelFallback?.(modelId, i + 1, chain.length);
|
|
24685
25267
|
const fallbackRun = await runHistorianPrompt({
|
|
24686
25268
|
client: args.client,
|
|
25269
|
+
db: args.db,
|
|
24687
25270
|
parentSessionId: args.parentSessionId,
|
|
24688
25271
|
sessionDirectory: args.sessionDirectory,
|
|
24689
25272
|
prompt: args.prompt,
|
|
@@ -24779,116 +25362,6 @@ function sanitizeDumpName(value) {
|
|
|
24779
25362
|
return value.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
24780
25363
|
}
|
|
24781
25364
|
|
|
24782
|
-
// ../plugin/src/hooks/magic-context/send-session-notification.ts
|
|
24783
|
-
function hasNotificationSessionClient(client) {
|
|
24784
|
-
if (client === null || typeof client !== "object")
|
|
24785
|
-
return false;
|
|
24786
|
-
const candidate = client;
|
|
24787
|
-
if (candidate.session === undefined)
|
|
24788
|
-
return true;
|
|
24789
|
-
if (candidate.session === null || typeof candidate.session !== "object")
|
|
24790
|
-
return false;
|
|
24791
|
-
const session = candidate.session;
|
|
24792
|
-
return (session.prompt === undefined || typeof session.prompt === "function") && (session.promptAsync === undefined || typeof session.promptAsync === "function");
|
|
24793
|
-
}
|
|
24794
|
-
function inferToastVariant(text) {
|
|
24795
|
-
const lower = text.toLowerCase();
|
|
24796
|
-
if (lower.includes("error") || lower.includes("failed") || lower.includes("alert"))
|
|
24797
|
-
return "error";
|
|
24798
|
-
if (lower.includes("warning") || lower.includes("⚠"))
|
|
24799
|
-
return "warning";
|
|
24800
|
-
if (lower.includes("complete") || lower.includes("success") || lower.includes("✓") || lower.includes("finished"))
|
|
24801
|
-
return "success";
|
|
24802
|
-
return "info";
|
|
24803
|
-
}
|
|
24804
|
-
function extractToastTitle(text) {
|
|
24805
|
-
const headingMatch = text.match(/^#+\s+(.+)/m);
|
|
24806
|
-
if (headingMatch)
|
|
24807
|
-
return headingMatch[1].trim();
|
|
24808
|
-
const firstLine = text.split(`
|
|
24809
|
-
`)[0].trim();
|
|
24810
|
-
if (firstLine.length <= 80)
|
|
24811
|
-
return firstLine;
|
|
24812
|
-
return "Magic Context";
|
|
24813
|
-
}
|
|
24814
|
-
async function sendIgnoredMessage(client, sessionId, text, params, forcePersist = false) {
|
|
24815
|
-
const title = extractToastTitle(text);
|
|
24816
|
-
const message = text.length > 200 ? `${text.slice(0, 200)}…` : text;
|
|
24817
|
-
const toastVariant = inferToastVariant(text);
|
|
24818
|
-
const duration = params.toastDurationMs ?? 5000;
|
|
24819
|
-
const { isTuiConnected: checkTui } = await import("./rpc-notifications-td0amw6w.js");
|
|
24820
|
-
if (!forcePersist && checkTui(sessionId)) {
|
|
24821
|
-
try {
|
|
24822
|
-
const { pushNotification } = await import("./rpc-notifications-td0amw6w.js");
|
|
24823
|
-
pushNotification("toast", {
|
|
24824
|
-
title,
|
|
24825
|
-
message,
|
|
24826
|
-
variant: toastVariant,
|
|
24827
|
-
duration
|
|
24828
|
-
}, sessionId);
|
|
24829
|
-
return "sent";
|
|
24830
|
-
} catch {
|
|
24831
|
-
sessionLog(sessionId, "TUI RPC toast enqueue failed, falling back to ignored message");
|
|
24832
|
-
}
|
|
24833
|
-
}
|
|
24834
|
-
const { waitForSafeNotificationTarget } = await import("./safe-notification-target-ng8ygena.js");
|
|
24835
|
-
if (await waitForSafeNotificationTarget(client, sessionId) === "skip") {
|
|
24836
|
-
sessionLog(sessionId, "notification skipped (session not titled yet)");
|
|
24837
|
-
return "skipped";
|
|
24838
|
-
}
|
|
24839
|
-
if (!hasNotificationSessionClient(client)) {
|
|
24840
|
-
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
24841
|
-
return "failed";
|
|
24842
|
-
}
|
|
24843
|
-
const c = client;
|
|
24844
|
-
let agent = params.agent || undefined;
|
|
24845
|
-
let variant = params.variant || undefined;
|
|
24846
|
-
let model = params.providerId && params.modelId ? { providerID: params.providerId, modelID: params.modelId } : undefined;
|
|
24847
|
-
if (!agent || !model || !variant) {
|
|
24848
|
-
try {
|
|
24849
|
-
const { resolvePromptContext } = await import("./prompt-context-602yq94t.js");
|
|
24850
|
-
const resolved = await resolvePromptContext(client, sessionId);
|
|
24851
|
-
if (resolved) {
|
|
24852
|
-
agent = agent ?? resolved.agent;
|
|
24853
|
-
model = model ?? resolved.model;
|
|
24854
|
-
variant = variant ?? resolved.variant;
|
|
24855
|
-
}
|
|
24856
|
-
} catch {}
|
|
24857
|
-
}
|
|
24858
|
-
const input = {
|
|
24859
|
-
path: { id: sessionId },
|
|
24860
|
-
body: {
|
|
24861
|
-
noReply: true,
|
|
24862
|
-
agent,
|
|
24863
|
-
model,
|
|
24864
|
-
variant,
|
|
24865
|
-
parts: [
|
|
24866
|
-
{
|
|
24867
|
-
type: "text",
|
|
24868
|
-
text,
|
|
24869
|
-
ignored: true
|
|
24870
|
-
}
|
|
24871
|
-
]
|
|
24872
|
-
}
|
|
24873
|
-
};
|
|
24874
|
-
try {
|
|
24875
|
-
if (typeof c.session?.prompt === "function") {
|
|
24876
|
-
await Promise.resolve(c.session.prompt(input));
|
|
24877
|
-
return "sent";
|
|
24878
|
-
}
|
|
24879
|
-
if (typeof c.session?.promptAsync === "function") {
|
|
24880
|
-
await c.session.promptAsync(input);
|
|
24881
|
-
return "sent";
|
|
24882
|
-
}
|
|
24883
|
-
sessionLog(sessionId, "session prompt API unavailable for notification");
|
|
24884
|
-
return "failed";
|
|
24885
|
-
} catch (error) {
|
|
24886
|
-
const msg = getErrorMessage(error);
|
|
24887
|
-
sessionLog(sessionId, "failed to send notification:", msg);
|
|
24888
|
-
return "failed";
|
|
24889
|
-
}
|
|
24890
|
-
}
|
|
24891
|
-
|
|
24892
25365
|
// ../plugin/src/hooks/magic-context/compartment-runner-incremental.ts
|
|
24893
25366
|
var HISTORIAN_ALERT_COOLDOWN_MS2 = 60 * 1000;
|
|
24894
25367
|
var lastHistorianAlertBySession2 = new Map;
|
|
@@ -25106,6 +25579,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
25106
25579
|
emitProgress(`Running historian (pass ${passCount + 1})…`);
|
|
25107
25580
|
const validatedPass = await runValidatedHistorianPass({
|
|
25108
25581
|
client,
|
|
25582
|
+
db,
|
|
25109
25583
|
parentSessionId: sessionId,
|
|
25110
25584
|
sessionDirectory,
|
|
25111
25585
|
prompt,
|
|
@@ -25525,6 +25999,7 @@ ${chunk.text}`,
|
|
|
25525
25999
|
Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${chunk.startIndex}-${chunk.endIndex}.`, notifParams());
|
|
25526
26000
|
const validatedPass = await runValidatedHistorianPass({
|
|
25527
26001
|
client,
|
|
26002
|
+
db,
|
|
25528
26003
|
parentSessionId: sessionId,
|
|
25529
26004
|
sessionDirectory,
|
|
25530
26005
|
prompt,
|
|
@@ -25880,8 +26355,8 @@ function renderStatusText(ctx, db, sessionId) {
|
|
|
25880
26355
|
const inputTokens = typeof usage?.tokens === "number" ? usage.tokens : undefined;
|
|
25881
26356
|
const pct = typeof usage?.percent === "number" ? usage.percent : undefined;
|
|
25882
26357
|
const meta = readSessionMetaStatus(db, sessionId);
|
|
25883
|
-
const
|
|
25884
|
-
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}`;
|
|
25885
26360
|
}
|
|
25886
26361
|
function renderHistorianState(meta, recompActive) {
|
|
25887
26362
|
const failureCount = meta?.historian_failure_count ?? 0;
|
|
@@ -25984,6 +26459,14 @@ No active Pi session is available.`,
|
|
|
25984
26459
|
return;
|
|
25985
26460
|
}
|
|
25986
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
|
+
}
|
|
25987
26470
|
const parsed = parseRecompArgs(args);
|
|
25988
26471
|
if (parsed.kind === "error") {
|
|
25989
26472
|
sendCtxStatusMessage(pi, {
|
|
@@ -26336,7 +26819,7 @@ function contextualizeUpgradeReason(reason) {
|
|
|
26336
26819
|
// src/pi-memory-migration.ts
|
|
26337
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.";
|
|
26338
26821
|
async function runPiMemoryMigration(deps) {
|
|
26339
|
-
const projectPath = resolveProjectIdentityForSession(deps.directory);
|
|
26822
|
+
const projectPath = resolveProjectIdentityForSession(deps.directory, deps.allowHomeProject);
|
|
26340
26823
|
if (!projectPath) {
|
|
26341
26824
|
return {
|
|
26342
26825
|
ran: false,
|
|
@@ -26451,6 +26934,14 @@ No active Pi session is available.`,
|
|
|
26451
26934
|
return;
|
|
26452
26935
|
}
|
|
26453
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
|
+
}
|
|
26454
26945
|
if (!currentDeps.historianModel) {
|
|
26455
26946
|
sendCtxStatusMessage(pi, {
|
|
26456
26947
|
title: "/ctx-session-upgrade",
|
|
@@ -26497,6 +26988,7 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
26497
26988
|
timeoutMs: currentDeps.historianTimeoutMs,
|
|
26498
26989
|
thinkingLevel: currentDeps.historianThinkingLevel,
|
|
26499
26990
|
directory: ctx.cwd,
|
|
26991
|
+
allowHomeProject: currentDeps.allowHomeProject,
|
|
26500
26992
|
sessionId,
|
|
26501
26993
|
userMemoriesEnabled: currentDeps.userMemoriesEnabled,
|
|
26502
26994
|
language: currentDeps.language
|
|
@@ -26507,7 +26999,7 @@ An upgrade or recomp is already running for this session in the background. Wait
|
|
|
26507
26999
|
}
|
|
26508
27000
|
};
|
|
26509
27001
|
if (upgradableCount === 0) {
|
|
26510
|
-
const projectPath = resolveProjectIdentityForSession(ctx.cwd);
|
|
27002
|
+
const projectPath = resolveProjectIdentityForSession(ctx.cwd, currentDeps.allowHomeProject);
|
|
26511
27003
|
if (!projectPath)
|
|
26512
27004
|
return;
|
|
26513
27005
|
const migrationPending = migrationEnabled && !isMemoryMigrationDone(currentDeps.db, projectPath);
|
|
@@ -26728,8 +27220,8 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
26728
27220
|
"### Cache TTL",
|
|
26729
27221
|
`- Configured: ${meta.cacheTtl}`,
|
|
26730
27222
|
`- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
|
|
26731
|
-
`- Remaining: ${cacheExpired ? "expired" : `${Math.round(remainingMs / 1000)}s`}`,
|
|
26732
|
-
`- 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}%`}`,
|
|
26733
27225
|
"",
|
|
26734
27226
|
"### Execute Threshold",
|
|
26735
27227
|
`- Execute threshold: ${formatExecuteThreshold(thresholdDetail, displayContextLimit)}`,
|
|
@@ -26834,7 +27326,7 @@ ${c.content}
|
|
|
26834
27326
|
// package.json
|
|
26835
27327
|
var package_default = {
|
|
26836
27328
|
name: "@cortexkit/pi-magic-context",
|
|
26837
|
-
version: "0.
|
|
27329
|
+
version: "0.34.0",
|
|
26838
27330
|
type: "module",
|
|
26839
27331
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
26840
27332
|
main: "dist/index.js",
|
|
@@ -27004,7 +27496,7 @@ function renderInner(s, theme, innerWidth) {
|
|
|
27004
27496
|
lines.push(`Upgrade: ${theme.fg("accent", "up to date")}`);
|
|
27005
27497
|
}
|
|
27006
27498
|
lines.push(`Pending drops: ${s.pendingOpsCount}`);
|
|
27007
|
-
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`}`);
|
|
27008
27500
|
lines.push("");
|
|
27009
27501
|
lines.push(theme.fg("muted", "Tags"));
|
|
27010
27502
|
lines.push(`Active ${s.activeTags} (~${formatBytes(s.activeBytes)}) · Dropped ${s.droppedTags} · Total ${s.totalTags}`);
|
|
@@ -27046,8 +27538,18 @@ function buildPiStatusDetail(pi, ctx, deps, sessionId) {
|
|
|
27046
27538
|
const usage = ctx.getContextUsage?.();
|
|
27047
27539
|
const meta = getOrCreateSessionMeta(deps.db, sessionId);
|
|
27048
27540
|
const inputTokens = typeof usage?.tokens === "number" ? usage.tokens : meta.lastInputTokens;
|
|
27049
|
-
|
|
27050
|
-
|
|
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;
|
|
27051
27553
|
const compartments = getCompartments(deps.db, sessionId);
|
|
27052
27554
|
const metaRow = readSessionMetaRow(deps.db, sessionId);
|
|
27053
27555
|
const memoryBlockCount = Number(metaRow?.memory_block_count ?? 0);
|
|
@@ -27095,9 +27597,15 @@ ${safeStringify(tool.parameters)}`);
|
|
|
27095
27597
|
sessionId
|
|
27096
27598
|
});
|
|
27097
27599
|
const cacheTtl = meta.cacheTtl || "5m";
|
|
27098
|
-
|
|
27600
|
+
let cacheTtlMs;
|
|
27601
|
+
try {
|
|
27602
|
+
cacheTtlMs = parseCacheTtl(cacheTtl);
|
|
27603
|
+
} catch {
|
|
27604
|
+
cacheTtlMs = 5 * 60 * 1000;
|
|
27605
|
+
}
|
|
27606
|
+
const neverExpires = cacheTtlMs === Number.POSITIVE_INFINITY;
|
|
27099
27607
|
const elapsed = meta.lastResponseTime > 0 ? Date.now() - meta.lastResponseTime : 0;
|
|
27100
|
-
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;
|
|
27101
27609
|
const cacheExpired = meta.lastResponseTime > 0 && cacheRemainingMs === 0;
|
|
27102
27610
|
const historyBlockTokens = compartmentTokens + factTokens;
|
|
27103
27611
|
const historyBudgetPercentage = deps.historyBudgetPercentage ?? 0.15;
|
|
@@ -27252,22 +27760,6 @@ function readPendingOpsCount(db, sessionId) {
|
|
|
27252
27760
|
return 0;
|
|
27253
27761
|
}
|
|
27254
27762
|
}
|
|
27255
|
-
function parseTtlString(ttl) {
|
|
27256
|
-
const match = ttl.match(/^(\d+)(s|m|h)$/);
|
|
27257
|
-
if (!match)
|
|
27258
|
-
return 5 * 60 * 1000;
|
|
27259
|
-
const val = Number.parseInt(match[1] ?? "5", 10);
|
|
27260
|
-
switch (match[2]) {
|
|
27261
|
-
case "s":
|
|
27262
|
-
return val * 1000;
|
|
27263
|
-
case "m":
|
|
27264
|
-
return val * 60 * 1000;
|
|
27265
|
-
case "h":
|
|
27266
|
-
return val * 3600 * 1000;
|
|
27267
|
-
default:
|
|
27268
|
-
return 5 * 60 * 1000;
|
|
27269
|
-
}
|
|
27270
|
-
}
|
|
27271
27763
|
function safeRead(fn, fallback) {
|
|
27272
27764
|
try {
|
|
27273
27765
|
return fn();
|
|
@@ -27331,7 +27823,18 @@ No active Pi session is available.`,
|
|
|
27331
27823
|
}
|
|
27332
27824
|
const usage = ctx.getContextUsage?.();
|
|
27333
27825
|
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
27334
|
-
|
|
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);
|
|
27335
27838
|
const details = buildStatusDetails(currentDeps, sessionId);
|
|
27336
27839
|
sendCtxStatusMessage(pi, { title: "/ctx-status", text: statusText, level: "info" }, details);
|
|
27337
27840
|
} catch (error) {
|
|
@@ -27433,6 +27936,14 @@ No active Pi session is available.`,
|
|
|
27433
27936
|
return;
|
|
27434
27937
|
}
|
|
27435
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
|
+
}
|
|
27436
27947
|
const sessionMeta = getOrCreateSessionMeta(currentDeps.db, sessionId);
|
|
27437
27948
|
if (sessionMeta.isSubagent) {
|
|
27438
27949
|
sendCtxStatusMessage(pi, {
|
|
@@ -27485,7 +27996,7 @@ async function runPiWrapup(pi, deps, ctx, sessionId, messagesToKeep) {
|
|
|
27485
27996
|
const unregister = setRawMessageProvider(sessionId, provider);
|
|
27486
27997
|
let holderId = "";
|
|
27487
27998
|
try {
|
|
27488
|
-
const contextLimit = resolvePiContextLimit(ctx);
|
|
27999
|
+
const contextLimit = resolvePiContextLimit(ctx, deps.db, sessionId);
|
|
27489
28000
|
const modelKey = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined;
|
|
27490
28001
|
const executeThresholdPercentage = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, modelKey, 65, {
|
|
27491
28002
|
tokensConfig: deps.executeThresholdTokens,
|
|
@@ -27714,15 +28225,19 @@ Wrapped up ${messagesWrapped} messages into ${compartmentsCreated} compartments.
|
|
|
27714
28225
|
unregister();
|
|
27715
28226
|
}
|
|
27716
28227
|
}
|
|
27717
|
-
function resolvePiContextLimit(ctx) {
|
|
28228
|
+
function resolvePiContextLimit(ctx, db, sessionId) {
|
|
27718
28229
|
const usage = ctx.getContextUsage?.();
|
|
27719
|
-
|
|
27720
|
-
|
|
27721
|
-
|
|
27722
|
-
|
|
27723
|
-
|
|
27724
|
-
}
|
|
27725
|
-
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;
|
|
27726
28241
|
}
|
|
27727
28242
|
async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarker, maxWaitMs) {
|
|
27728
28243
|
const waitStartedAt = Date.now();
|
|
@@ -27742,15 +28257,15 @@ async function acquireCompartmentLeaseEventually(db, sessionId, renewWrapupMarke
|
|
|
27742
28257
|
function estimateChunks(tokens, chunkTokens) {
|
|
27743
28258
|
return Math.max(1, Math.ceil(Math.max(0, tokens) / Math.max(1, chunkTokens)));
|
|
27744
28259
|
}
|
|
27745
|
-
function formatExistingWrapup(
|
|
27746
|
-
if (!
|
|
28260
|
+
function formatExistingWrapup(state2) {
|
|
28261
|
+
if (!state2) {
|
|
27747
28262
|
return `## Magic Wrapup — Skipped
|
|
27748
28263
|
|
|
27749
28264
|
Another /ctx-wrapup is already compacting this session. Wait for it to finish, then try again.`;
|
|
27750
28265
|
}
|
|
27751
28266
|
return `## Magic Wrapup — Skipped
|
|
27752
28267
|
|
|
27753
|
-
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.`;
|
|
27754
28269
|
}
|
|
27755
28270
|
function readBranchEntries(ctx) {
|
|
27756
28271
|
const getBranch = ctx.sessionManager.getBranch;
|
|
@@ -27874,15 +28389,43 @@ function stripTagPrefixFromAssistantMessage(message) {
|
|
|
27874
28389
|
|
|
27875
28390
|
// src/index.ts
|
|
27876
28391
|
var PREFIX2 = "[magic-context][pi]";
|
|
27877
|
-
|
|
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) {
|
|
27878
28407
|
const projectDir = ctx.cwd;
|
|
27879
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDir) ?? "";
|
|
28408
|
+
const projectIdentity = resolveProjectIdentityForSession(projectDir, allowHomeProject) ?? "";
|
|
27880
28409
|
return { projectDir, projectIdentity };
|
|
27881
28410
|
}
|
|
27882
28411
|
function signalPiDeferredCompactionMarkerDrain(sessionId) {
|
|
27883
28412
|
signalPiDeferredHistoryRefresh(sessionId);
|
|
27884
28413
|
signalPiDeferredMaterialization(sessionId);
|
|
27885
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
|
+
}
|
|
27886
28429
|
function persistPiMessageEndModelMeta(args) {
|
|
27887
28430
|
if (!args.message || typeof args.message !== "object")
|
|
27888
28431
|
return;
|
|
@@ -27988,7 +28531,10 @@ var __test = {
|
|
|
27988
28531
|
logPiConfigLoad,
|
|
27989
28532
|
resetLoggedPiConfigDirs() {
|
|
27990
28533
|
loggedPiConfigDirs.clear();
|
|
27991
|
-
}
|
|
28534
|
+
},
|
|
28535
|
+
isPiMagicContextActiveInProcess,
|
|
28536
|
+
markPiMagicContextActive,
|
|
28537
|
+
clearPiMagicContextActive
|
|
27992
28538
|
};
|
|
27993
28539
|
function formatTokens(value) {
|
|
27994
28540
|
return value.toLocaleString();
|
|
@@ -28004,23 +28550,28 @@ function getPiMessageModel(message) {
|
|
|
28004
28550
|
};
|
|
28005
28551
|
}
|
|
28006
28552
|
function resolvePiPressureContextLimit(args) {
|
|
28007
|
-
let
|
|
28553
|
+
let detectedContextLimit;
|
|
28008
28554
|
try {
|
|
28009
28555
|
const overflowState = getOverflowState(args.db, args.sessionId);
|
|
28010
28556
|
if (overflowState.detectedContextLimit > 0) {
|
|
28011
|
-
|
|
28557
|
+
detectedContextLimit = overflowState.detectedContextLimit;
|
|
28012
28558
|
}
|
|
28013
28559
|
} catch (err) {
|
|
28014
28560
|
warn("message_end: getOverflowState failed:", err);
|
|
28015
28561
|
}
|
|
28016
|
-
return
|
|
28562
|
+
return resolvePiUsableContextLimit({
|
|
28563
|
+
rawContextWindow: args.piContextWindow,
|
|
28564
|
+
model: args.model,
|
|
28565
|
+
detectedContextLimit
|
|
28566
|
+
}) ?? 0;
|
|
28017
28567
|
}
|
|
28018
28568
|
async function persistPiPressureFromMessageEnd(args) {
|
|
28019
28569
|
const { provider, model } = getPiMessageModel(args.message);
|
|
28020
28570
|
const effectiveContextLimit = resolvePiPressureContextLimit({
|
|
28021
28571
|
db: args.db,
|
|
28022
28572
|
sessionId: args.sessionId,
|
|
28023
|
-
piContextWindow: args.piContextWindow
|
|
28573
|
+
piContextWindow: args.piContextWindow,
|
|
28574
|
+
model: args.piModel ?? { provider, id: model }
|
|
28024
28575
|
});
|
|
28025
28576
|
const usage = extractAssistantUsage(args.message);
|
|
28026
28577
|
const pressure = computePiPressure(usage, effectiveContextLimit);
|
|
@@ -28047,8 +28598,8 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
28047
28598
|
}
|
|
28048
28599
|
} else if (typeof args.piTokens === "number") {
|
|
28049
28600
|
updates.lastInputTokens = args.piTokens;
|
|
28050
|
-
if (
|
|
28051
|
-
updates.lastContextPercentage = args.piTokens /
|
|
28601
|
+
if (effectiveContextLimit > 0) {
|
|
28602
|
+
updates.lastContextPercentage = args.piTokens / effectiveContextLimit * 100;
|
|
28052
28603
|
}
|
|
28053
28604
|
}
|
|
28054
28605
|
updateSessionMeta(args.db, args.sessionId, updates);
|
|
@@ -28075,7 +28626,8 @@ function resolveSidekickFromConfig(config) {
|
|
|
28075
28626
|
timeoutMs: sidekick.timeout_ms,
|
|
28076
28627
|
thinking_level: sidekick.thinking_level,
|
|
28077
28628
|
fallbackModels: resolveFallbackChain(sidekick.fallback_models),
|
|
28078
|
-
language: config.language
|
|
28629
|
+
language: config.language,
|
|
28630
|
+
allowHomeProject: config.allow_home_project
|
|
28079
28631
|
};
|
|
28080
28632
|
}
|
|
28081
28633
|
function resolveHistorianFromConfig(config) {
|
|
@@ -28105,7 +28657,8 @@ function resolveHistorianFromConfig(config) {
|
|
|
28105
28657
|
memoryEnabled: config.memory.enabled,
|
|
28106
28658
|
autoPromote: config.memory.auto_promote,
|
|
28107
28659
|
userMemoriesEnabled: userMemoryCollectionEnabled(config.dreamer),
|
|
28108
|
-
language: config.language
|
|
28660
|
+
language: config.language,
|
|
28661
|
+
allowHomeProject: config.allow_home_project
|
|
28109
28662
|
};
|
|
28110
28663
|
}
|
|
28111
28664
|
function resolveAutoSearchFromConfig(config) {
|
|
@@ -28125,7 +28678,20 @@ async function src_default(pi) {
|
|
|
28125
28678
|
log(`${PREFIX2} subagent child detected (${MAGIC_CONTEXT_PI_SUBAGENT_ENV}=1); skipping full extension registration`);
|
|
28126
28679
|
return;
|
|
28127
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();
|
|
28128
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
|
+
});
|
|
28129
28695
|
const storageDir = getMagicContextStorageDir();
|
|
28130
28696
|
const dbPath = join5(storageDir, "context.db");
|
|
28131
28697
|
let db;
|
|
@@ -28144,16 +28710,26 @@ async function src_default(pi) {
|
|
|
28144
28710
|
info("plugin DISABLED via config (enabled: false) — skipping registration");
|
|
28145
28711
|
return;
|
|
28146
28712
|
}
|
|
28713
|
+
const migration = getMigrationOnOpenRefusal();
|
|
28714
|
+
const blockingProcesses = migration?.serverPids.map((pid) => ({
|
|
28715
|
+
harness: "OpenCode server",
|
|
28716
|
+
pid
|
|
28717
|
+
})) ?? [];
|
|
28147
28718
|
const fence = getSchemaFenceRejection();
|
|
28148
|
-
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 ? {
|
|
28149
28725
|
kind: "schema_fence",
|
|
28150
28726
|
persistedVersion: fence.persistedVersion,
|
|
28151
28727
|
supportedVersion: fence.supportedVersion
|
|
28152
28728
|
} : {
|
|
28153
28729
|
kind: "storage_failure",
|
|
28154
|
-
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)`
|
|
28155
28731
|
};
|
|
28156
|
-
if (early.config.fail_closed_blocking === false) {
|
|
28732
|
+
if (early.config.fail_closed_blocking === false || !isCompactionEnabled(early.config)) {
|
|
28157
28733
|
warn(`Magic Context (pi) storage unavailable at ${dbPath}: ${formatFailClosedBlockingMessage(reason)}. ` + "fail_closed_blocking=false — degrading silently (hooks not registered).");
|
|
28158
28734
|
return;
|
|
28159
28735
|
}
|
|
@@ -28201,26 +28777,30 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28201
28777
|
})();
|
|
28202
28778
|
}, 0);
|
|
28203
28779
|
const projectDir = process.cwd();
|
|
28204
|
-
const projectIdentity = resolveProjectIdentityForSession(projectDir) ?? "";
|
|
28205
28780
|
const seenDreamerProjectIdentities = new Set;
|
|
28206
|
-
if (projectIdentity)
|
|
28207
|
-
seenDreamerProjectIdentities.add(projectIdentity);
|
|
28208
|
-
try {
|
|
28209
|
-
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
28210
|
-
for (const sid of pendingPiMarkerSessions) {
|
|
28211
|
-
signalPiDeferredCompactionMarkerDrain(sid);
|
|
28212
|
-
}
|
|
28213
|
-
if (pendingPiMarkerSessions.length > 0) {
|
|
28214
|
-
log(`${PREFIX2} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
28215
|
-
}
|
|
28216
|
-
} catch (err) {
|
|
28217
|
-
warn(`Magic Context (pi) failed to rehydrate deferred Pi compaction markers: ${err instanceof Error ? err.message : String(err)}`);
|
|
28218
|
-
}
|
|
28219
|
-
info(`loaded v${PLUGIN_VERSION} | harness=pi | db=${dbPath} | ` + `project=${projectIdentity} | dir=${projectDir}`);
|
|
28220
28781
|
ensureConfigLocationsMigrated(projectDir);
|
|
28221
28782
|
const { config, warnings, loadedFromPaths } = loadPiConfig({
|
|
28222
28783
|
cwd: projectDir
|
|
28223
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
|
+
}
|
|
28224
28804
|
configurePiSubagentExtensions(config.pi?.subagent_extensions);
|
|
28225
28805
|
logPiConfigLoad({
|
|
28226
28806
|
dir: projectDir,
|
|
@@ -28228,6 +28808,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28228
28808
|
warnings,
|
|
28229
28809
|
dedupe: true
|
|
28230
28810
|
});
|
|
28811
|
+
setStoragePrivatePermissionEnforcement(config.storage.enforce_private_permissions);
|
|
28231
28812
|
setSqlitePragmaConfig({
|
|
28232
28813
|
cacheSizeMb: config.sqlite.cache_size_mb,
|
|
28233
28814
|
mmapSizeMb: config.sqlite.mmap_size_mb
|
|
@@ -28267,6 +28848,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28267
28848
|
language: cfg.language,
|
|
28268
28849
|
autoSearch: auto,
|
|
28269
28850
|
resolveForProject: resolveContextOptionsForProject,
|
|
28851
|
+
compactionOff,
|
|
28852
|
+
allowHomeProject: cfg.allow_home_project,
|
|
28270
28853
|
maybeAutoEmbedSession: (sessionId, dir, identity) => {
|
|
28271
28854
|
maybeAutoEmbedPiSession({
|
|
28272
28855
|
db: database,
|
|
@@ -28288,7 +28871,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28288
28871
|
hist.onStatusChange = (ctx) => {
|
|
28289
28872
|
updateStatusLine(ctx, {
|
|
28290
28873
|
db: database,
|
|
28291
|
-
projectIdentity: resolveCurrentProject(ctx).projectIdentity ?? ""
|
|
28874
|
+
projectIdentity: resolveCurrentProject(ctx, cfg.allow_home_project).projectIdentity ?? ""
|
|
28292
28875
|
});
|
|
28293
28876
|
};
|
|
28294
28877
|
}
|
|
@@ -28318,14 +28901,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28318
28901
|
dedupe: true
|
|
28319
28902
|
});
|
|
28320
28903
|
const switchedConfig = switchedLoad.config;
|
|
28321
|
-
const switchedIdentity = identityOverride ?? resolveProjectIdentityForSession(dir) ?? "";
|
|
28904
|
+
const switchedIdentity = identityOverride ?? resolveProjectIdentityForSession(dir, switchedConfig.allow_home_project) ?? "";
|
|
28322
28905
|
const built = buildProjectDeps(dir, switchedIdentity, switchedConfig);
|
|
28323
28906
|
projectDepsByDir.set(dir, built);
|
|
28324
28907
|
return built;
|
|
28325
28908
|
}
|
|
28326
28909
|
function resolveCurrentProjectDeps(ctx) {
|
|
28327
|
-
|
|
28328
|
-
return resolveProjectDepsForDir(currentProject.projectDir, currentProject.projectIdentity);
|
|
28910
|
+
return resolveProjectDepsForDir(ctx.cwd);
|
|
28329
28911
|
}
|
|
28330
28912
|
function resolveContextOptionsForProject(dir) {
|
|
28331
28913
|
return resolveProjectDepsForDir(dir).contextOptions;
|
|
@@ -28341,11 +28923,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28341
28923
|
memoryToolEnabled: true,
|
|
28342
28924
|
protectedTags: config.protected_tags ?? 20,
|
|
28343
28925
|
resolveProtectedTags: (ctx) => resolveCurrentProjectDeps(ctx).config.protected_tags ?? 20,
|
|
28926
|
+
resolveProjectIdentity: (ctx) => resolveCurrentProjectDeps(ctx).projectIdentity,
|
|
28344
28927
|
dreamerEnabled: isDreamerRunnable(config),
|
|
28345
28928
|
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
28346
|
-
todowriteEnabled
|
|
28929
|
+
todowriteEnabled,
|
|
28930
|
+
compactionOff
|
|
28347
28931
|
});
|
|
28348
|
-
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)");
|
|
28349
28933
|
pi.on("session_start", async (event, ctx) => {
|
|
28350
28934
|
await handlePiCloneSessionStart(event, ctx, {
|
|
28351
28935
|
db,
|
|
@@ -28389,7 +28973,6 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28389
28973
|
return {
|
|
28390
28974
|
db,
|
|
28391
28975
|
projectIdentity: current.projectIdentity,
|
|
28392
|
-
resolveProject: resolveCurrentProject,
|
|
28393
28976
|
protectedTags: current.config.protected_tags,
|
|
28394
28977
|
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
28395
28978
|
historyBudgetPercentage: current.config.history_budget_percentage,
|
|
@@ -28406,7 +28989,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28406
28989
|
info("registered /ctx-status");
|
|
28407
28990
|
registerStatusLine(pi, { db, projectIdentity });
|
|
28408
28991
|
info("registered magic-context status line");
|
|
28409
|
-
registerCtxFlushCommand(pi, { db });
|
|
28992
|
+
registerCtxFlushCommand(pi, { db, compactionOff });
|
|
28410
28993
|
info("registered /ctx-flush");
|
|
28411
28994
|
registerCtxRecompCommand(pi, {
|
|
28412
28995
|
db,
|
|
@@ -28419,6 +29002,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28419
29002
|
language: bootProjectDeps.config.language,
|
|
28420
29003
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28421
29004
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29005
|
+
compactionOff,
|
|
28422
29006
|
resolveRuntimeDeps: (ctx) => {
|
|
28423
29007
|
const current = resolveCurrentProjectDeps(ctx);
|
|
28424
29008
|
return {
|
|
@@ -28431,7 +29015,8 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28431
29015
|
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
28432
29016
|
language: current.config.language,
|
|
28433
29017
|
memoryEnabled: current.config.memory.enabled,
|
|
28434
|
-
autoPromote: current.config.memory.auto_promote
|
|
29018
|
+
autoPromote: current.config.memory.auto_promote,
|
|
29019
|
+
compactionOff
|
|
28435
29020
|
};
|
|
28436
29021
|
}
|
|
28437
29022
|
});
|
|
@@ -28447,6 +29032,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28447
29032
|
language: bootProjectDeps.config.language,
|
|
28448
29033
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28449
29034
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29035
|
+
compactionOff,
|
|
28450
29036
|
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
28451
29037
|
executeThresholdPercentage: bootProjectDeps.config.execute_threshold_percentage,
|
|
28452
29038
|
executeThresholdTokens: bootProjectDeps.config.execute_threshold_tokens,
|
|
@@ -28463,6 +29049,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28463
29049
|
language: current.config.language,
|
|
28464
29050
|
memoryEnabled: current.config.memory.enabled,
|
|
28465
29051
|
autoPromote: current.config.memory.auto_promote,
|
|
29052
|
+
compactionOff,
|
|
28466
29053
|
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer),
|
|
28467
29054
|
executeThresholdPercentage: current.config.execute_threshold_percentage,
|
|
28468
29055
|
executeThresholdTokens: current.config.execute_threshold_tokens
|
|
@@ -28480,7 +29067,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28480
29067
|
historianThinkingLevel: bootProjectDeps.historianConfig?.thinkingLevel,
|
|
28481
29068
|
language: bootProjectDeps.config.language,
|
|
28482
29069
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
29070
|
+
allowHomeProject: bootProjectDeps.config.allow_home_project,
|
|
28483
29071
|
autoPromote: bootProjectDeps.config.memory.auto_promote,
|
|
29072
|
+
compactionOff,
|
|
28484
29073
|
userMemoriesEnabled: userMemoryCollectionEnabled(bootProjectDeps.config.dreamer),
|
|
28485
29074
|
resolveRuntimeDeps: (ctx) => {
|
|
28486
29075
|
const current = resolveCurrentProjectDeps(ctx);
|
|
@@ -28494,7 +29083,9 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28494
29083
|
historianThinkingLevel: current.historianConfig?.thinkingLevel,
|
|
28495
29084
|
language: current.config.language,
|
|
28496
29085
|
memoryEnabled: current.config.memory.enabled,
|
|
29086
|
+
allowHomeProject: current.config.allow_home_project,
|
|
28497
29087
|
autoPromote: current.config.memory.auto_promote,
|
|
29088
|
+
compactionOff,
|
|
28498
29089
|
userMemoriesEnabled: userMemoryCollectionEnabled(current.config.dreamer)
|
|
28499
29090
|
};
|
|
28500
29091
|
}
|
|
@@ -28504,7 +29095,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28504
29095
|
db,
|
|
28505
29096
|
projectDir,
|
|
28506
29097
|
projectIdentity,
|
|
28507
|
-
resolveProject:
|
|
29098
|
+
resolveProject: (ctx) => {
|
|
29099
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
29100
|
+
return {
|
|
29101
|
+
projectDir: current.projectDir,
|
|
29102
|
+
projectIdentity: current.projectIdentity
|
|
29103
|
+
};
|
|
29104
|
+
},
|
|
28508
29105
|
dreamerEnabled: bootProjectDeps.dreamerEnabled,
|
|
28509
29106
|
resolveDreamerEnabled: (ctx) => resolveCurrentProjectDeps(ctx).dreamerEnabled,
|
|
28510
29107
|
onProjectSeen: (identity) => seenDreamerProjectIdentities.add(identity)
|
|
@@ -28516,7 +29113,13 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28516
29113
|
projectIdentity,
|
|
28517
29114
|
memoryEnabled: bootProjectDeps.config.memory.enabled,
|
|
28518
29115
|
resolveMemoryEnabled: (ctx) => resolveCurrentProjectDeps(ctx).config.memory.enabled,
|
|
28519
|
-
resolveProject:
|
|
29116
|
+
resolveProject: (ctx) => {
|
|
29117
|
+
const current = resolveCurrentProjectDeps(ctx);
|
|
29118
|
+
return {
|
|
29119
|
+
projectDir: current.projectDir,
|
|
29120
|
+
projectIdentity: current.projectIdentity
|
|
29121
|
+
};
|
|
29122
|
+
}
|
|
28520
29123
|
});
|
|
28521
29124
|
info("registered /ctx-embed");
|
|
28522
29125
|
const dreamerConfig = bootProjectDeps.dreamerConfig;
|
|
@@ -28605,11 +29208,11 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28605
29208
|
try {
|
|
28606
29209
|
const smForDrain = sm;
|
|
28607
29210
|
const canDrain = typeof smForDrain.appendCompaction === "function" && typeof smForDrain.getBranch === "function";
|
|
28608
|
-
if (canDrain && getPendingPiCompactionMarkerState(db, sessionId)) {
|
|
29211
|
+
if (!compactionOff && canDrain && getPendingPiCompactionMarkerState(db, sessionId)) {
|
|
28609
29212
|
signalPiDeferredCompactionMarkerDrain(sessionId);
|
|
28610
29213
|
}
|
|
28611
29214
|
} catch {}
|
|
28612
|
-
if (ctx.hasUI && effectiveProjectDeps.historianConfig?.model) {
|
|
29215
|
+
if (!compactionOff && ctx.hasUI && effectiveProjectDeps.historianConfig?.model) {
|
|
28613
29216
|
maybeSendUpgradeReminder({
|
|
28614
29217
|
client: null,
|
|
28615
29218
|
db,
|
|
@@ -28637,7 +29240,7 @@ async function startPiMagicContextRuntime(pi, database, dbPath) {
|
|
|
28637
29240
|
memoryEnabled: effectiveConfig.memory.enabled,
|
|
28638
29241
|
includeGuidance: true,
|
|
28639
29242
|
protectedTags: effectiveConfig.protected_tags,
|
|
28640
|
-
ctxReduceCallable:
|
|
29243
|
+
ctxReduceCallable: !compactionOff,
|
|
28641
29244
|
dreamerEnabled: effectiveProjectDeps.dreamerEnabled,
|
|
28642
29245
|
temporalAwarenessEnabled: effectiveConfig.temporal_awareness ?? false,
|
|
28643
29246
|
cavemanTextCompressionEnabled: effectiveConfig.caveman_text_compression?.enabled === true,
|
|
@@ -28682,7 +29285,7 @@ ${block}` : event.systemPrompt;
|
|
|
28682
29285
|
const lastAssistant = Array.isArray(msgs) ? [...msgs].reverse().find((m) => m?.role === "assistant") : undefined;
|
|
28683
29286
|
if (lastAssistant?.stopReason === "stop") {
|
|
28684
29287
|
const sessionId = ctx.sessionManager?.getSessionId?.();
|
|
28685
|
-
if (sessionId && db)
|
|
29288
|
+
if (sessionId && db && !compactionOff)
|
|
28686
29289
|
maybeDeliverChannel2Pi(pi, db, sessionId);
|
|
28687
29290
|
}
|
|
28688
29291
|
} catch (err) {
|
|
@@ -28707,7 +29310,7 @@ ${block}` : event.systemPrompt;
|
|
|
28707
29310
|
toolCallId
|
|
28708
29311
|
});
|
|
28709
29312
|
if (Array.isArray(todos) && todos.length > 0 && todos.every((t) => t.status === "completed" || t.status === "cancelled")) {
|
|
28710
|
-
if (sessionMeta && !sessionMeta.isSubagent) {
|
|
29313
|
+
if (!compactionOff && sessionMeta && !sessionMeta.isSubagent) {
|
|
28711
29314
|
onNoteTrigger(db, sessionId, "todos_complete");
|
|
28712
29315
|
}
|
|
28713
29316
|
}
|
|
@@ -28723,7 +29326,7 @@ ${block}` : event.systemPrompt;
|
|
|
28723
29326
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
28724
29327
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
28725
29328
|
return;
|
|
28726
|
-
if (event.toolName === "ctx_reduce") {
|
|
29329
|
+
if (!compactionOff && event.toolName === "ctx_reduce") {
|
|
28727
29330
|
markPiChannel1Reduced(sessionId, db);
|
|
28728
29331
|
}
|
|
28729
29332
|
} catch (err) {
|
|
@@ -28735,6 +29338,8 @@ ${block}` : event.systemPrompt;
|
|
|
28735
29338
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
28736
29339
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
28737
29340
|
return;
|
|
29341
|
+
if (compactionOff)
|
|
29342
|
+
return;
|
|
28738
29343
|
if (db)
|
|
28739
29344
|
maybeDeliverChannel2Pi(pi, db, sessionId, "steer");
|
|
28740
29345
|
const block = maybeChannel1ReminderForToolResult({
|
|
@@ -28750,20 +29355,11 @@ ${block}` : event.systemPrompt;
|
|
|
28750
29355
|
log(`tool_result hook failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
28751
29356
|
}
|
|
28752
29357
|
});
|
|
28753
|
-
pi.on("session_before_compact", async (_event, ctx) => {
|
|
28754
|
-
try {
|
|
28755
|
-
const sessionId = ctx.sessionManager?.getSessionId?.();
|
|
28756
|
-
if (typeof sessionId === "string" && sessionId.length > 0) {
|
|
28757
|
-
clearPiM0Cache(db, sessionId, "session_before_compact");
|
|
28758
|
-
}
|
|
28759
|
-
} catch {}
|
|
28760
|
-
info("session_before_compact: cancelling — magic-context owns compaction");
|
|
28761
|
-
return { cancel: true };
|
|
28762
|
-
});
|
|
29358
|
+
pi.on("session_before_compact", async (_event, ctx) => handlePiSessionBeforeCompact({ db, compactionOff, ctx }));
|
|
28763
29359
|
pi.on("message_end", async (event, ctx) => {
|
|
28764
29360
|
try {
|
|
28765
29361
|
const msg = event.message;
|
|
28766
|
-
if (msg !== null && typeof msg === "object") {
|
|
29362
|
+
if (!compactionOff && msg !== null && typeof msg === "object") {
|
|
28767
29363
|
stripTagPrefixFromAssistantMessage(msg);
|
|
28768
29364
|
}
|
|
28769
29365
|
} catch (err) {
|
|
@@ -28795,6 +29391,7 @@ ${block}` : event.systemPrompt;
|
|
|
28795
29391
|
sessionId,
|
|
28796
29392
|
message: event.message,
|
|
28797
29393
|
piContextWindow,
|
|
29394
|
+
piModel: ctx.model,
|
|
28798
29395
|
piTokens: piUsage && typeof piUsage.tokens === "number" ? piUsage.tokens : undefined,
|
|
28799
29396
|
notifyIssue: async (message) => {
|
|
28800
29397
|
const uiNotify = ctx.ui?.notify;
|
|
@@ -28824,6 +29421,8 @@ ${block}` : event.systemPrompt;
|
|
|
28824
29421
|
warn("message_end: persist session_meta usage failed:", err);
|
|
28825
29422
|
}
|
|
28826
29423
|
try {
|
|
29424
|
+
if (compactionOff)
|
|
29425
|
+
return;
|
|
28827
29426
|
const sm = ctx.sessionManager;
|
|
28828
29427
|
const sessionId = sm?.getSessionId?.();
|
|
28829
29428
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
@@ -28841,8 +29440,8 @@ ${block}` : event.systemPrompt;
|
|
|
28841
29440
|
if (!detection.isOverflow)
|
|
28842
29441
|
return;
|
|
28843
29442
|
const modelKey = typeof msg.provider === "string" && typeof msg.model === "string" && msg.provider.length > 0 && msg.model.length > 0 ? `${msg.provider}/${msg.model}` : undefined;
|
|
28844
|
-
recordOverflowDetected(db, sessionId, detection.reportedLimit, modelKey);
|
|
28845
|
-
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 ?? "?"}`);
|
|
28846
29445
|
} catch (err) {
|
|
28847
29446
|
warn("message_end: overflow detection failed:", err);
|
|
28848
29447
|
}
|
|
@@ -28879,6 +29478,7 @@ ${block}` : event.systemPrompt;
|
|
|
28879
29478
|
clearContextHandlerSession(sessionId);
|
|
28880
29479
|
}
|
|
28881
29480
|
} catch {}
|
|
29481
|
+
clearPiMagicContextActive();
|
|
28882
29482
|
});
|
|
28883
29483
|
pi.on("session_before_switch", (_event, ctx) => {
|
|
28884
29484
|
try {
|
|
@@ -28907,6 +29507,7 @@ export {
|
|
|
28907
29507
|
resolveDreamerFromConfig,
|
|
28908
29508
|
persistPiPressureFromMessageEnd,
|
|
28909
29509
|
persistPiMessageEndModelMeta,
|
|
29510
|
+
handlePiSessionBeforeCompact,
|
|
28910
29511
|
src_default as default,
|
|
28911
29512
|
capturePiTodowriteMessageIfCompatible,
|
|
28912
29513
|
capturePiTodowriteArgsIfCompatible,
|