@cortexkit/pi-magic-context 0.21.2 → 0.21.5
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.js +587 -106
- package/dist/subagent-entry.js +207 -15
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -141906,6 +141906,10 @@ function getLastCompartmentEndMessage(db, sessionId) {
|
|
|
141906
141906
|
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
141907
141907
|
return row?.max_end ?? -1;
|
|
141908
141908
|
}
|
|
141909
|
+
function getCompartmentsByEndMessageId(db, sessionId, endMessageId) {
|
|
141910
|
+
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? AND end_message_id = ? ORDER BY sequence ASC").all(sessionId, endMessageId).filter(isCompartmentRow);
|
|
141911
|
+
return rows.map(toCompartment);
|
|
141912
|
+
}
|
|
141909
141913
|
function appendCompartments(db, sessionId, compartments) {
|
|
141910
141914
|
if (compartments.length === 0)
|
|
141911
141915
|
return;
|
|
@@ -142015,7 +142019,7 @@ function promoteRecompStaging(db, sessionId) {
|
|
|
142015
142019
|
insertFactRows(db, sessionId, staging.facts, now);
|
|
142016
142020
|
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
142017
142021
|
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
142018
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE session_id = ?").run(sessionId);
|
|
142022
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
142019
142023
|
return { compartments: staging.compartments, facts: staging.facts };
|
|
142020
142024
|
})();
|
|
142021
142025
|
}
|
|
@@ -142245,8 +142249,10 @@ function deleteOrphanProjectKeyFiles(db, now = Date.now()) {
|
|
|
142245
142249
|
if (existsSync2(row.projectPath))
|
|
142246
142250
|
continue;
|
|
142247
142251
|
try {
|
|
142248
|
-
db.
|
|
142249
|
-
|
|
142252
|
+
db.transaction(() => {
|
|
142253
|
+
db.prepare("DELETE FROM project_key_files WHERE project_path = ?").run(row.projectPath);
|
|
142254
|
+
db.prepare("DELETE FROM project_key_files_version WHERE project_path = ?").run(row.projectPath);
|
|
142255
|
+
})();
|
|
142250
142256
|
deletedProjects++;
|
|
142251
142257
|
} catch (error) {
|
|
142252
142258
|
log(`[key-files] orphan GC failed for ${row.projectPath}:`, error);
|
|
@@ -142653,6 +142659,16 @@ var MIGRATIONS = [
|
|
|
142653
142659
|
WHERE auto_search_hint_decisions IS NULL
|
|
142654
142660
|
`);
|
|
142655
142661
|
}
|
|
142662
|
+
},
|
|
142663
|
+
{
|
|
142664
|
+
version: 18,
|
|
142665
|
+
description: "Add pending_pi_compaction_marker_state column for Pi deferred marker drain",
|
|
142666
|
+
up: (db) => {
|
|
142667
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
142668
|
+
if (!cols.some((c) => c.name === "pending_pi_compaction_marker_state")) {
|
|
142669
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN pending_pi_compaction_marker_state TEXT");
|
|
142670
|
+
}
|
|
142671
|
+
}
|
|
142656
142672
|
}
|
|
142657
142673
|
];
|
|
142658
142674
|
function ensureMigrationsTable(db) {
|
|
@@ -142668,7 +142684,7 @@ function getCurrentVersion(db) {
|
|
|
142668
142684
|
const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
|
|
142669
142685
|
return row?.version ?? 0;
|
|
142670
142686
|
}
|
|
142671
|
-
function isSiblingMigrationConflict(error, version) {
|
|
142687
|
+
function isSiblingMigrationConflict(db, error, version) {
|
|
142672
142688
|
if (!(error instanceof Error))
|
|
142673
142689
|
return false;
|
|
142674
142690
|
const code = error.code;
|
|
@@ -142680,7 +142696,8 @@ function isSiblingMigrationConflict(error, version) {
|
|
|
142680
142696
|
return false;
|
|
142681
142697
|
if (!msg.toLowerCase().includes("version"))
|
|
142682
142698
|
return false;
|
|
142683
|
-
|
|
142699
|
+
const confirmed = db.prepare("SELECT 1 FROM schema_migrations WHERE version = ?").get(version);
|
|
142700
|
+
return confirmed != null;
|
|
142684
142701
|
}
|
|
142685
142702
|
function runMigrations(db) {
|
|
142686
142703
|
ensureMigrationsTable(db);
|
|
@@ -142701,7 +142718,7 @@ function runMigrations(db) {
|
|
|
142701
142718
|
log(`[migrations] applied v${migration.version}: ${migration.description}`);
|
|
142702
142719
|
migrationIndex += 1;
|
|
142703
142720
|
} catch (error) {
|
|
142704
|
-
if (isSiblingMigrationConflict(error, migration.version)) {
|
|
142721
|
+
if (isSiblingMigrationConflict(db, error, migration.version)) {
|
|
142705
142722
|
log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
|
|
142706
142723
|
const reReadVersion = getCurrentVersion(db);
|
|
142707
142724
|
if (reReadVersion <= currentVersion) {
|
|
@@ -143298,6 +143315,11 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143298
143315
|
-- Excluded from healNullTextColumns. Readers filter IS NOT NULL AND
|
|
143299
143316
|
-- != empty-string defensively. Plan v6 section 3.
|
|
143300
143317
|
pending_compaction_marker_state TEXT,
|
|
143318
|
+
-- pending_pi_compaction_marker_state: intentionally NULLABLE without a
|
|
143319
|
+
-- default. Absence of a deferred Pi-native marker is SQL NULL; presence
|
|
143320
|
+
-- is a valid JSON blob written via setPendingPiCompactionMarkerState.
|
|
143321
|
+
-- Excluded from healNullTextColumns.
|
|
143322
|
+
pending_pi_compaction_marker_state TEXT,
|
|
143301
143323
|
-- deferred_execute_state: intentionally NULLABLE without a default.
|
|
143302
143324
|
-- Absence is SQL NULL; presence is a JSON blob written via
|
|
143303
143325
|
-- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
|
|
@@ -143394,6 +143416,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143394
143416
|
ensureColumn(db, "session_meta", "detected_context_limit", "INTEGER DEFAULT 0");
|
|
143395
143417
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
143396
143418
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
143419
|
+
ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
|
|
143397
143420
|
ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
|
|
143398
143421
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143399
143422
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -144009,6 +144032,39 @@ function clearPendingCompactionMarkerStateIf(db, sessionId, expected) {
|
|
|
144009
144032
|
WHERE session_id = ? AND pending_compaction_marker_state = ?`).run(sessionId, expectedBlob);
|
|
144010
144033
|
return result.changes > 0;
|
|
144011
144034
|
}
|
|
144035
|
+
function isPendingPiCompactionMarker(value) {
|
|
144036
|
+
return typeof value === "object" && value !== null && typeof value.firstKeptEntryId === "string" && typeof value.endMessageId === "string" && typeof value.ordinal === "number" && typeof value.tokensBefore === "number" && typeof value.summary === "string" && typeof value.publishedAt === "number";
|
|
144037
|
+
}
|
|
144038
|
+
function getPendingPiCompactionMarkerState(db, sessionId) {
|
|
144039
|
+
const row = db.prepare("SELECT pending_pi_compaction_marker_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
144040
|
+
const raw = row?.pending_pi_compaction_marker_state;
|
|
144041
|
+
if (raw === null || raw === undefined || raw === "")
|
|
144042
|
+
return null;
|
|
144043
|
+
try {
|
|
144044
|
+
const parsed = JSON.parse(raw);
|
|
144045
|
+
if (isPendingPiCompactionMarker(parsed)) {
|
|
144046
|
+
return parsed;
|
|
144047
|
+
}
|
|
144048
|
+
} catch {}
|
|
144049
|
+
return null;
|
|
144050
|
+
}
|
|
144051
|
+
function setPendingPiCompactionMarkerState(db, sessionId, state) {
|
|
144052
|
+
ensureSessionMetaRow(db, sessionId);
|
|
144053
|
+
const blob = state ? stableStringify(state) : null;
|
|
144054
|
+
db.prepare("UPDATE session_meta SET pending_pi_compaction_marker_state = ? WHERE session_id = ?").run(blob, sessionId);
|
|
144055
|
+
}
|
|
144056
|
+
function clearPendingPiCompactionMarkerStateIf(db, sessionId, expected) {
|
|
144057
|
+
const expectedBlob = stableStringify(expected);
|
|
144058
|
+
const result = db.prepare(`UPDATE session_meta SET pending_pi_compaction_marker_state = NULL
|
|
144059
|
+
WHERE session_id = ? AND pending_pi_compaction_marker_state = ?`).run(sessionId, expectedBlob);
|
|
144060
|
+
return result.changes > 0;
|
|
144061
|
+
}
|
|
144062
|
+
function getSessionsWithPendingPiMarker(db) {
|
|
144063
|
+
const rows = db.prepare(`SELECT session_id FROM session_meta
|
|
144064
|
+
WHERE pending_pi_compaction_marker_state IS NOT NULL
|
|
144065
|
+
AND pending_pi_compaction_marker_state != ''`).all();
|
|
144066
|
+
return rows.map((r) => r.session_id);
|
|
144067
|
+
}
|
|
144012
144068
|
function peekDeferredExecutePending(db, sessionId) {
|
|
144013
144069
|
const row = db.prepare("SELECT deferred_execute_state FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
144014
144070
|
const raw = row?.deferred_execute_state;
|
|
@@ -144129,6 +144185,12 @@ function getNoteById(db, noteId) {
|
|
|
144129
144185
|
const row = db.prepare("SELECT * FROM notes WHERE id = ?").get(noteId);
|
|
144130
144186
|
return isNoteRow(row) ? toNote(row) : null;
|
|
144131
144187
|
}
|
|
144188
|
+
function noteBelongsToScope(note, scope) {
|
|
144189
|
+
if (note.type === "session") {
|
|
144190
|
+
return note.sessionId === scope.sessionId;
|
|
144191
|
+
}
|
|
144192
|
+
return note.projectPath === scope.projectPath;
|
|
144193
|
+
}
|
|
144132
144194
|
function buildStatusClause(status) {
|
|
144133
144195
|
if (status === undefined) {
|
|
144134
144196
|
return null;
|
|
@@ -144190,9 +144252,9 @@ function getPendingSmartNotes(db, projectPath) {
|
|
|
144190
144252
|
function getReadySmartNotes(db, projectPath) {
|
|
144191
144253
|
return getSmartNotes(db, projectPath, "ready");
|
|
144192
144254
|
}
|
|
144193
|
-
function updateNote(db, noteId, updates) {
|
|
144255
|
+
function updateNote(db, noteId, updates, scope) {
|
|
144194
144256
|
const existing = getNoteById(db, noteId);
|
|
144195
|
-
if (!existing) {
|
|
144257
|
+
if (!existing || !noteBelongsToScope(existing, scope)) {
|
|
144196
144258
|
return null;
|
|
144197
144259
|
}
|
|
144198
144260
|
const now = Date.now();
|
|
@@ -144239,7 +144301,11 @@ function updateNote(db, noteId, updates) {
|
|
|
144239
144301
|
const result = db.prepare(`UPDATE notes SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
|
|
144240
144302
|
return isNoteRow(result) ? toNote(result) : null;
|
|
144241
144303
|
}
|
|
144242
|
-
function dismissNote(db, noteId) {
|
|
144304
|
+
function dismissNote(db, noteId, scope) {
|
|
144305
|
+
const existing = getNoteById(db, noteId);
|
|
144306
|
+
if (!existing || !noteBelongsToScope(existing, scope)) {
|
|
144307
|
+
return false;
|
|
144308
|
+
}
|
|
144243
144309
|
const result = db.prepare("UPDATE notes SET status = 'dismissed', updated_at = ? WHERE id = ? AND status != 'dismissed'").run(Date.now(), noteId);
|
|
144244
144310
|
return result.changes > 0;
|
|
144245
144311
|
}
|
|
@@ -144901,7 +144967,21 @@ function resolveHistorianContextLimit(historianModelOverride) {
|
|
|
144901
144967
|
|
|
144902
144968
|
// ../plugin/src/hooks/magic-context/event-resolvers.ts
|
|
144903
144969
|
init_logger();
|
|
144970
|
+
var DEFAULT_CONTEXT_LIMIT = 128000;
|
|
144904
144971
|
var MAX_EXECUTE_THRESHOLD = 80;
|
|
144972
|
+
function resolveContextLimit(providerID, modelID, ctx) {
|
|
144973
|
+
const fromModelsDev = providerID && modelID ? getModelsDevContextLimit(providerID, modelID) : undefined;
|
|
144974
|
+
const baseline = fromModelsDev ?? DEFAULT_CONTEXT_LIMIT;
|
|
144975
|
+
if (ctx?.db && ctx.sessionID) {
|
|
144976
|
+
try {
|
|
144977
|
+
const overflow = getOverflowState(ctx.db, ctx.sessionID);
|
|
144978
|
+
if (overflow.detectedContextLimit > 0 && overflow.detectedContextLimit < baseline) {
|
|
144979
|
+
return overflow.detectedContextLimit;
|
|
144980
|
+
}
|
|
144981
|
+
} catch {}
|
|
144982
|
+
}
|
|
144983
|
+
return baseline;
|
|
144984
|
+
}
|
|
144905
144985
|
function resolveCacheTtl(cacheTtl, modelKey) {
|
|
144906
144986
|
if (typeof cacheTtl === "string") {
|
|
144907
144987
|
return cacheTtl;
|
|
@@ -145269,6 +145349,14 @@ class PiSubagentRunner {
|
|
|
145269
145349
|
}
|
|
145270
145350
|
async run(options) {
|
|
145271
145351
|
const startTime = Date.now();
|
|
145352
|
+
if (options.signal?.aborted) {
|
|
145353
|
+
return {
|
|
145354
|
+
ok: false,
|
|
145355
|
+
reason: "abort",
|
|
145356
|
+
error: "pi subagent aborted by caller",
|
|
145357
|
+
durationMs: Date.now() - startTime
|
|
145358
|
+
};
|
|
145359
|
+
}
|
|
145272
145360
|
const args = buildArgs(options);
|
|
145273
145361
|
return new Promise((resolve2) => {
|
|
145274
145362
|
let settled = false;
|
|
@@ -145301,6 +145389,16 @@ class PiSubagentRunner {
|
|
|
145301
145389
|
});
|
|
145302
145390
|
return;
|
|
145303
145391
|
}
|
|
145392
|
+
if (options.signal?.aborted) {
|
|
145393
|
+
terminateChild(child);
|
|
145394
|
+
settle({
|
|
145395
|
+
ok: false,
|
|
145396
|
+
reason: "abort",
|
|
145397
|
+
error: "pi subagent aborted by caller",
|
|
145398
|
+
durationMs: Date.now() - startTime
|
|
145399
|
+
});
|
|
145400
|
+
return;
|
|
145401
|
+
}
|
|
145304
145402
|
emitProgress({ type: "spawned", argv: args, pid: child.pid });
|
|
145305
145403
|
let stderr = "";
|
|
145306
145404
|
child.stderr?.on("data", (chunk) => {
|
|
@@ -146297,6 +146395,43 @@ function normalizeProjectRelativePath(projectPath, filePath) {
|
|
|
146297
146395
|
return null;
|
|
146298
146396
|
return rel;
|
|
146299
146397
|
}
|
|
146398
|
+
function isDocumentationOrMetaFile(rel) {
|
|
146399
|
+
const lower = rel.toLowerCase();
|
|
146400
|
+
if (lower.endsWith(".md") || lower.endsWith(".mdx") || lower.endsWith(".rst"))
|
|
146401
|
+
return true;
|
|
146402
|
+
if (lower.endsWith(".txt"))
|
|
146403
|
+
return true;
|
|
146404
|
+
const base = lower.split("/").pop() ?? "";
|
|
146405
|
+
const baseNoExt = base.replace(/\.[^.]+$/, "");
|
|
146406
|
+
const META_BASENAMES = new Set([
|
|
146407
|
+
"license",
|
|
146408
|
+
"licence",
|
|
146409
|
+
"notice",
|
|
146410
|
+
"copying",
|
|
146411
|
+
"authors",
|
|
146412
|
+
"contributors",
|
|
146413
|
+
"changelog",
|
|
146414
|
+
"changes",
|
|
146415
|
+
"history",
|
|
146416
|
+
"readme",
|
|
146417
|
+
"contributing",
|
|
146418
|
+
"code_of_conduct",
|
|
146419
|
+
"security",
|
|
146420
|
+
"support",
|
|
146421
|
+
"maintainers",
|
|
146422
|
+
"governance",
|
|
146423
|
+
"package-lock",
|
|
146424
|
+
"bun.lock",
|
|
146425
|
+
"bun.lockb",
|
|
146426
|
+
"yarn.lock",
|
|
146427
|
+
"pnpm-lock",
|
|
146428
|
+
"cargo.lock",
|
|
146429
|
+
"uv.lock",
|
|
146430
|
+
"poetry.lock",
|
|
146431
|
+
"gemfile.lock"
|
|
146432
|
+
]);
|
|
146433
|
+
return META_BASENAMES.has(base) || META_BASENAMES.has(baseNoExt);
|
|
146434
|
+
}
|
|
146300
146435
|
function primarySessionIds(db) {
|
|
146301
146436
|
try {
|
|
146302
146437
|
const rows = db.prepare("SELECT session_id AS sessionId FROM session_meta WHERE is_subagent = 0").all();
|
|
@@ -146328,6 +146463,8 @@ function collectKeyFileCandidates(args) {
|
|
|
146328
146463
|
const rel = normalizeProjectRelativePath(args.projectPath, row.file_path);
|
|
146329
146464
|
if (!rel)
|
|
146330
146465
|
continue;
|
|
146466
|
+
if (isDocumentationOrMetaFile(rel))
|
|
146467
|
+
continue;
|
|
146331
146468
|
const timestamp = toMs(row.time_created);
|
|
146332
146469
|
const candidate = byPath.get(rel) ?? {
|
|
146333
146470
|
path: rel,
|
|
@@ -146464,7 +146601,8 @@ Rules:
|
|
|
146464
146601
|
- Total approx_token_estimate must be < ${args.config.token_budget}.
|
|
146465
146602
|
- path must be relative, no .., no absolute paths, no symlinks escaping project root.
|
|
146466
146603
|
- path must be unique case-sensitively and case-insensitively.
|
|
146467
|
-
- content must be plain text; no XML tags inside
|
|
146604
|
+
- content must be plain text; no XML tags inside.
|
|
146605
|
+
- DO NOT pick prose documentation (README.md, CONTRIBUTING.md, CHANGELOG, LICENSE, *.md/*.mdx/*.rst/*.txt) or lockfiles. Key files are project SOURCE the agent needs repeated orientation context on, not reference docs. Project docs are surfaced through a separate injection path.`;
|
|
146468
146606
|
}
|
|
146469
146607
|
function validateLlmOutput(raw, config, projectPath) {
|
|
146470
146608
|
let obj;
|
|
@@ -148269,6 +148407,13 @@ async function evaluateSmartNotes(args) {
|
|
|
148269
148407
|
For each note below, determine whether its surface condition has been met.
|
|
148270
148408
|
You have access to tools like GitHub CLI (gh), web search, and the local codebase to verify conditions.
|
|
148271
148409
|
|
|
148410
|
+
You DO NOT have access to:
|
|
148411
|
+
- Any conversation between the user and the original agent that wrote the note
|
|
148412
|
+
- The state of any active session, including whether messages have been sent
|
|
148413
|
+
- The current task, mood, or intent of the human user
|
|
148414
|
+
|
|
148415
|
+
If a condition references conversation context the user is having ("When the user mentions X", "When they ask to do Y", "When we revisit Z", "When relevant to current discussion", etc.), it is UNEVALUATABLE — skip it (do not include in results) so the note stays pending. These are misuse cases that should never have been written as smart notes; leaving them pending is the correct outcome, the dreamer's archive-stale task will eventually retire them.
|
|
148416
|
+
|
|
148272
148417
|
## Pending Smart Notes
|
|
148273
148418
|
|
|
148274
148419
|
${noteDescriptions}
|
|
@@ -148277,7 +148422,8 @@ ${noteDescriptions}
|
|
|
148277
148422
|
|
|
148278
148423
|
1. Check each condition using the tools available to you.
|
|
148279
148424
|
2. Be conservative — only mark a condition as met when you have clear evidence.
|
|
148280
|
-
3.
|
|
148425
|
+
3. Skip conditions that depend on session/conversation context you cannot observe — do not invent a "false" verdict for them, just omit them from your response.
|
|
148426
|
+
4. Respond with a JSON array of results:
|
|
148281
148427
|
|
|
148282
148428
|
\`\`\`json
|
|
148283
148429
|
[
|
|
@@ -148285,7 +148431,7 @@ ${noteDescriptions}
|
|
|
148285
148431
|
]
|
|
148286
148432
|
\`\`\`
|
|
148287
148433
|
|
|
148288
|
-
Only include notes whose conditions you could definitively evaluate. Skip notes where you cannot determine the status (they will be re-evaluated next run).`;
|
|
148434
|
+
Only include notes whose conditions you could definitively evaluate against external signals. Skip notes where you cannot determine the status (they will be re-evaluated next run, or eventually archived as stale).`;
|
|
148289
148435
|
const taskStartedAt = Date.now();
|
|
148290
148436
|
let agentSessionId = null;
|
|
148291
148437
|
const abortController = new AbortController;
|
|
@@ -163039,7 +163185,6 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
163039
163185
|
enabled: exports_external.boolean().default(true),
|
|
163040
163186
|
min_clusters: exports_external.number().min(1).default(3)
|
|
163041
163187
|
}).default({ enabled: true, min_clusters: 3 }),
|
|
163042
|
-
compaction_markers: exports_external.boolean().default(true),
|
|
163043
163188
|
system_prompt_injection: exports_external.object({
|
|
163044
163189
|
enabled: exports_external.boolean().default(true),
|
|
163045
163190
|
skip_signatures: exports_external.array(exports_external.string()).default(["<!-- magic-context: skip -->"])
|
|
@@ -164703,6 +164848,21 @@ var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
|
164703
164848
|
function substituteConfigVariables(input) {
|
|
164704
164849
|
const warnings = [];
|
|
164705
164850
|
let text = input.text;
|
|
164851
|
+
if (input.isProjectConfig) {
|
|
164852
|
+
const hasEnvTokens = ENV_PATTERN.test(text);
|
|
164853
|
+
const hasFileTokens = FILE_PATTERN.test(text);
|
|
164854
|
+
ENV_PATTERN.lastIndex = 0;
|
|
164855
|
+
FILE_PATTERN.lastIndex = 0;
|
|
164856
|
+
if (hasEnvTokens || hasFileTokens) {
|
|
164857
|
+
const tokenTypes = [
|
|
164858
|
+
hasEnvTokens ? "{env:}" : undefined,
|
|
164859
|
+
hasFileTokens ? "{file:}" : undefined
|
|
164860
|
+
].filter(Boolean).join(" and ");
|
|
164861
|
+
warnings.push(`Project-level config no longer supports ${tokenTypes} tokens for security reasons; leaving tokens literal. Move secret expansion to user-level config.`);
|
|
164862
|
+
}
|
|
164863
|
+
return { text, warnings };
|
|
164864
|
+
}
|
|
164865
|
+
text = stripJsonComments(text);
|
|
164706
164866
|
text = text.replace(ENV_PATTERN, (_, rawName) => {
|
|
164707
164867
|
const varName = rawName.trim();
|
|
164708
164868
|
const value = varName ? process.env[varName] : undefined;
|
|
@@ -164710,7 +164870,7 @@ function substituteConfigVariables(input) {
|
|
|
164710
164870
|
warnings.push(`Environment variable ${varName} is not set (referenced via {env:${varName}}); using empty string`);
|
|
164711
164871
|
return "";
|
|
164712
164872
|
}
|
|
164713
|
-
return value;
|
|
164873
|
+
return JSON.stringify(value).slice(1, -1);
|
|
164714
164874
|
});
|
|
164715
164875
|
const fileMatches = Array.from(text.matchAll(FILE_PATTERN));
|
|
164716
164876
|
if (fileMatches.length === 0) {
|
|
@@ -166148,8 +166308,7 @@ var FORCE_COMPARTMENT_PERCENTAGE = 80;
|
|
|
166148
166308
|
function getProactiveCompartmentTriggerPercentage(executeThresholdPercentage) {
|
|
166149
166309
|
return Math.max(0, executeThresholdPercentage - PROACTIVE_TRIGGER_OFFSET_PERCENTAGE);
|
|
166150
166310
|
}
|
|
166151
|
-
function estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTags, clearReasoningAge, clearedReasoningThroughTag, dropToolStructure = true) {
|
|
166152
|
-
const activeTags = getTagsBySession(db, sessionId).filter((tag) => tag.status === "active");
|
|
166311
|
+
function estimateProjectedPostDropPercentage(db, sessionId, usage, activeTags, autoDropToolAge, protectedTags, clearReasoningAge, clearedReasoningThroughTag, dropToolStructure = true) {
|
|
166153
166312
|
const totalActiveBytes = activeTags.reduce((sum, tag) => sum + tag.byteSize + tag.reasoningByteSize, 0);
|
|
166154
166313
|
if (totalActiveBytes === 0)
|
|
166155
166314
|
return null;
|
|
@@ -166236,15 +166395,24 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget) {
|
|
|
166236
166395
|
}
|
|
166237
166396
|
});
|
|
166238
166397
|
}
|
|
166239
|
-
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger) {
|
|
166398
|
+
function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, autoDropToolAge, protectedTagCount, clearReasoningAge, dropToolStructure = true, commitClusterTrigger, preloadedActiveTags) {
|
|
166240
166399
|
if (sessionMeta.compartmentInProgress) {
|
|
166400
|
+
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
166241
166401
|
return { shouldFire: false };
|
|
166242
166402
|
}
|
|
166243
166403
|
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget);
|
|
166244
166404
|
if (!tailInfo.hasNewRawHistory) {
|
|
166405
|
+
try {
|
|
166406
|
+
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
166407
|
+
const rawMessageCount = getRawSessionMessageCount(sessionId);
|
|
166408
|
+
const protectedTailStart = getProtectedTailStartOrdinal(sessionId);
|
|
166409
|
+
sessionLog(sessionId, `compartment trigger: skipped — no new raw history (usage=${usage.percentage.toFixed(1)}% nextStartOrdinal=${tailInfo.nextStartOrdinal} lastCompartmentEnd=${lastCompartmentEnd} rawMessageCount=${rawMessageCount} protectedTailStart=${protectedTailStart})`);
|
|
166410
|
+
} catch (error51) {
|
|
166411
|
+
sessionLog(sessionId, `compartment trigger: skipped — no new raw history (usage=${usage.percentage.toFixed(1)}% nextStartOrdinal=${tailInfo.nextStartOrdinal} diagnostic-collection-failed: ${error51 instanceof Error ? error51.message : String(error51)})`);
|
|
166412
|
+
}
|
|
166245
166413
|
return { shouldFire: false };
|
|
166246
166414
|
}
|
|
166247
|
-
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, autoDropToolAge, protectedTagCount, clearReasoningAge, sessionMeta.clearedReasoningThroughTag, dropToolStructure);
|
|
166415
|
+
const projectedPostDropPercentage = estimateProjectedPostDropPercentage(db, sessionId, usage, preloadedActiveTags ?? getActiveTagsBySession(db, sessionId), autoDropToolAge, protectedTagCount, clearReasoningAge, sessionMeta.clearedReasoningThroughTag, dropToolStructure);
|
|
166248
166416
|
const relativePostDropTarget = executeThresholdPercentage * POST_DROP_TARGET_RATIO;
|
|
166249
166417
|
if (usage.percentage >= FORCE_COMPARTMENT_PERCENTAGE) {
|
|
166250
166418
|
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
@@ -166266,6 +166434,7 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
166266
166434
|
}
|
|
166267
166435
|
const proactiveTriggerPercentage = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
166268
166436
|
if (usage.percentage < proactiveTriggerPercentage) {
|
|
166437
|
+
sessionLog(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — below proactive floor (${proactiveTriggerPercentage}%)`);
|
|
166269
166438
|
return { shouldFire: false };
|
|
166270
166439
|
}
|
|
166271
166440
|
if (projectedPostDropPercentage !== null && projectedPostDropPercentage <= relativePostDropTarget) {
|
|
@@ -167667,11 +167836,12 @@ async function runAutoSearchHintForPi(args) {
|
|
|
167667
167836
|
}) : args.entryIds;
|
|
167668
167837
|
if (!options.enabled)
|
|
167669
167838
|
return messages;
|
|
167670
|
-
|
|
167671
|
-
|
|
167672
|
-
|
|
167673
|
-
|
|
167674
|
-
|
|
167839
|
+
const strictResolutionFailed = entryIds === null;
|
|
167840
|
+
const effectiveEntryIds = strictResolutionFailed ? messages.map((message) => {
|
|
167841
|
+
const id = message.id;
|
|
167842
|
+
return typeof id === "string" ? id : undefined;
|
|
167843
|
+
}) : entryIds;
|
|
167844
|
+
const found = findLatestMeaningfulUserMessage(messages, effectiveEntryIds);
|
|
167675
167845
|
if (found === null)
|
|
167676
167846
|
return messages;
|
|
167677
167847
|
const { message: userMsg, messageId: userMsgId } = found;
|
|
@@ -167683,6 +167853,10 @@ async function runAutoSearchHintForPi(args) {
|
|
|
167683
167853
|
}
|
|
167684
167854
|
return messages;
|
|
167685
167855
|
}
|
|
167856
|
+
if (strictResolutionFailed) {
|
|
167857
|
+
sessionLog(sessionId, "Pi auto-search: strict entry-id resolution failed; replayed persisted decisions only");
|
|
167858
|
+
return messages;
|
|
167859
|
+
}
|
|
167686
167860
|
const writeNoHintAndReconcile = (reason) => {
|
|
167687
167861
|
const outcome2 = appendAutoSearchHintDecision(db, sessionId, {
|
|
167688
167862
|
messageId: userMsgId,
|
|
@@ -167769,6 +167943,59 @@ ${hintText}`;
|
|
|
167769
167943
|
}
|
|
167770
167944
|
function clearAutoSearchForPiSession(_sessionId) {}
|
|
167771
167945
|
|
|
167946
|
+
// src/compaction-marker-manager-pi.ts
|
|
167947
|
+
init_logger();
|
|
167948
|
+
function applyDeferredPiCompactionMarker(deps, sessionId, pending) {
|
|
167949
|
+
try {
|
|
167950
|
+
const matches = getCompartmentsByEndMessageId(deps.db, sessionId, pending.endMessageId);
|
|
167951
|
+
if (matches.length === 0 || matches.length > 1) {
|
|
167952
|
+
if (matches.length > 1) {
|
|
167953
|
+
sessionLog(sessionId, `Pi compaction-marker drain: ${matches.length} compartments share endMessageId=${pending.endMessageId}; treating as stale`);
|
|
167954
|
+
}
|
|
167955
|
+
return { kind: "stale-skip", reason: "compartment-removed" };
|
|
167956
|
+
}
|
|
167957
|
+
if (matches[0]?.endMessage !== pending.ordinal) {
|
|
167958
|
+
return { kind: "stale-skip", reason: "target-superseded" };
|
|
167959
|
+
}
|
|
167960
|
+
const branchEntries = deps.readBranchEntries();
|
|
167961
|
+
if (!branchEntries.some((entry) => getEntryId(entry) === pending.firstKeptEntryId)) {
|
|
167962
|
+
return { kind: "stale-skip", reason: "entry-removed" };
|
|
167963
|
+
}
|
|
167964
|
+
const latestFirstKept = findLatestCompactionFirstKept(branchEntries);
|
|
167965
|
+
if (latestFirstKept === pending.firstKeptEntryId) {
|
|
167966
|
+
return { kind: "already-current" };
|
|
167967
|
+
}
|
|
167968
|
+
deps.appendCompaction(pending.summary, pending.firstKeptEntryId, pending.tokensBefore, {
|
|
167969
|
+
source: "magic-context",
|
|
167970
|
+
lastCompactedOrdinal: pending.ordinal
|
|
167971
|
+
}, true);
|
|
167972
|
+
sessionLog(sessionId, `Pi compaction-marker drain: applied firstKept=${pending.firstKeptEntryId} tokensBefore=${pending.tokensBefore}`);
|
|
167973
|
+
return { kind: "applied", firstKeptEntryId: pending.firstKeptEntryId };
|
|
167974
|
+
} catch (err) {
|
|
167975
|
+
const error51 = err instanceof Error ? err : new Error(String(err));
|
|
167976
|
+
sessionLog(sessionId, `Pi compaction-marker drain: retryable failure for ordinal ${pending.ordinal}:`, error51);
|
|
167977
|
+
return { kind: "retryable-failure", error: error51 };
|
|
167978
|
+
}
|
|
167979
|
+
}
|
|
167980
|
+
function findLatestCompactionFirstKept(branchEntries) {
|
|
167981
|
+
for (let i = branchEntries.length - 1;i >= 0; i--) {
|
|
167982
|
+
const entry = branchEntries[i];
|
|
167983
|
+
if (entry === null || typeof entry !== "object")
|
|
167984
|
+
continue;
|
|
167985
|
+
const record2 = entry;
|
|
167986
|
+
if (record2.type === "compaction" && typeof record2.firstKeptEntryId === "string") {
|
|
167987
|
+
return record2.firstKeptEntryId;
|
|
167988
|
+
}
|
|
167989
|
+
}
|
|
167990
|
+
return null;
|
|
167991
|
+
}
|
|
167992
|
+
function getEntryId(entry) {
|
|
167993
|
+
if (entry === null || typeof entry !== "object")
|
|
167994
|
+
return null;
|
|
167995
|
+
const id = entry.id;
|
|
167996
|
+
return typeof id === "string" ? id : null;
|
|
167997
|
+
}
|
|
167998
|
+
|
|
167772
167999
|
// src/detect-recent-commit.ts
|
|
167773
168000
|
var COMMIT_LOOKBACK = 5;
|
|
167774
168001
|
var COMMIT_HASH_PATTERN2 = /\b[0-9a-f]{7,12}\b/;
|
|
@@ -169549,7 +169776,6 @@ async function runPiHistorian(deps) {
|
|
|
169549
169776
|
memoryEnabled,
|
|
169550
169777
|
autoPromote,
|
|
169551
169778
|
onPublished,
|
|
169552
|
-
appendCompaction,
|
|
169553
169779
|
readBranchEntries,
|
|
169554
169780
|
notifyIssue
|
|
169555
169781
|
} = deps;
|
|
@@ -169722,20 +169948,34 @@ ${chunk.text}`, { stateFilePath });
|
|
|
169722
169948
|
await notify(`Historian failed: ${errorMsg}`);
|
|
169723
169949
|
return;
|
|
169724
169950
|
}
|
|
169951
|
+
const markerSummary = buildPiCompactionSummary(newCompartments);
|
|
169952
|
+
const lastNewEndMessageId = newCompartments[newCompartments.length - 1]?.endMessageId;
|
|
169953
|
+
let firstKeptEntryId = null;
|
|
169954
|
+
if (readBranchEntries) {
|
|
169955
|
+
try {
|
|
169956
|
+
firstKeptEntryId = findFirstKeptEntryId(readBranchEntries(), lastNewEnd);
|
|
169957
|
+
if (!firstKeptEntryId) {
|
|
169958
|
+
sessionLog(sessionId, `historian: native compaction queue skipped; no firstKeptEntryId after ordinal ${lastNewEnd}`);
|
|
169959
|
+
}
|
|
169960
|
+
} catch (error51) {
|
|
169961
|
+
sessionLog(sessionId, `historian: native compaction queue lookup failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
169962
|
+
}
|
|
169963
|
+
}
|
|
169725
169964
|
db.transaction(() => {
|
|
169726
169965
|
appendCompartments(db, sessionId, newCompartments);
|
|
169727
169966
|
replaceSessionFacts(db, sessionId, validatedPass.facts ?? []);
|
|
169728
169967
|
clearHistorianFailureState(db, sessionId);
|
|
169968
|
+
if (firstKeptEntryId && lastNewEndMessageId) {
|
|
169969
|
+
setPendingPiCompactionMarkerState(db, sessionId, {
|
|
169970
|
+
firstKeptEntryId,
|
|
169971
|
+
endMessageId: lastNewEndMessageId,
|
|
169972
|
+
ordinal: lastNewEnd,
|
|
169973
|
+
tokensBefore: chunk.tokenEstimate,
|
|
169974
|
+
summary: markerSummary,
|
|
169975
|
+
publishedAt: Date.now()
|
|
169976
|
+
});
|
|
169977
|
+
}
|
|
169729
169978
|
})();
|
|
169730
|
-
appendPiNativeCompaction({
|
|
169731
|
-
sessionId,
|
|
169732
|
-
appendCompaction,
|
|
169733
|
-
readBranchEntries,
|
|
169734
|
-
lastCompactedOrdinal: lastNewEnd,
|
|
169735
|
-
tokensBefore: chunk.tokenEstimate,
|
|
169736
|
-
summary: buildPiCompactionSummary(newCompartments)
|
|
169737
|
-
});
|
|
169738
|
-
clearInjectionCache(sessionId);
|
|
169739
169979
|
onNoteTrigger(db, sessionId, "historian_complete");
|
|
169740
169980
|
onPublished?.();
|
|
169741
169981
|
if (memoryEnabled !== false && autoPromote !== false) {
|
|
@@ -169796,25 +170036,6 @@ function buildPiCompactionSummary(compartments) {
|
|
|
169796
170036
|
}
|
|
169797
170037
|
return `Magic Context compacted: ${titles.join("; ")}`;
|
|
169798
170038
|
}
|
|
169799
|
-
function appendPiNativeCompaction(args) {
|
|
169800
|
-
const { appendCompaction, readBranchEntries } = args;
|
|
169801
|
-
if (!appendCompaction || !readBranchEntries)
|
|
169802
|
-
return;
|
|
169803
|
-
try {
|
|
169804
|
-
const firstKeptEntryId = findFirstKeptEntryId(readBranchEntries(), args.lastCompactedOrdinal);
|
|
169805
|
-
if (!firstKeptEntryId) {
|
|
169806
|
-
sessionLog(args.sessionId, `historian: native compaction skipped; no firstKeptEntryId after ordinal ${args.lastCompactedOrdinal}`);
|
|
169807
|
-
return;
|
|
169808
|
-
}
|
|
169809
|
-
appendCompaction(args.summary, firstKeptEntryId, args.tokensBefore, {
|
|
169810
|
-
source: "magic-context",
|
|
169811
|
-
lastCompactedOrdinal: args.lastCompactedOrdinal
|
|
169812
|
-
}, true);
|
|
169813
|
-
sessionLog(args.sessionId, `historian: appended native compaction firstKept=${firstKeptEntryId} tokensBefore=${args.tokensBefore}`);
|
|
169814
|
-
} catch (error51) {
|
|
169815
|
-
sessionLog(args.sessionId, `historian: native compaction append failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
169816
|
-
}
|
|
169817
|
-
}
|
|
169818
170039
|
function findFirstKeptEntryId(entries, lastCompactedOrdinal) {
|
|
169819
170040
|
const rawMessages = convertEntriesToRawMessages(entries);
|
|
169820
170041
|
const target = lastCompactedOrdinal + 1;
|
|
@@ -170695,6 +170916,19 @@ function stripTagPrefix2(text) {
|
|
|
170695
170916
|
return text.slice(match[0].length);
|
|
170696
170917
|
}
|
|
170697
170918
|
|
|
170919
|
+
// src/timeout.ts
|
|
170920
|
+
function withTimeout(p, ms) {
|
|
170921
|
+
let handle;
|
|
170922
|
+
const timeout = new Promise((resolve4) => {
|
|
170923
|
+
handle = setTimeout(() => resolve4(undefined), ms);
|
|
170924
|
+
handle.unref?.();
|
|
170925
|
+
});
|
|
170926
|
+
return Promise.race([p, timeout]).finally(() => {
|
|
170927
|
+
if (handle)
|
|
170928
|
+
clearTimeout(handle);
|
|
170929
|
+
});
|
|
170930
|
+
}
|
|
170931
|
+
|
|
170698
170932
|
// src/tokenize-pi-messages.ts
|
|
170699
170933
|
function tokenizePiMessages(messages) {
|
|
170700
170934
|
let conversation = 0;
|
|
@@ -171197,6 +171431,7 @@ var deferredMaterializationSessions = new Set;
|
|
|
171197
171431
|
var sessionsByProject = new Map;
|
|
171198
171432
|
var lastSeenProjectIdentityBySession = new Map;
|
|
171199
171433
|
var rawMessageProviderUnregistersBySession = new Map;
|
|
171434
|
+
var activeContextHandlerSessions = new Set;
|
|
171200
171435
|
var lastHeuristicsTurnIdBySession = new Map;
|
|
171201
171436
|
var firstContextPassSeenBySession = new Set;
|
|
171202
171437
|
var recentReduceBySession = new Map;
|
|
@@ -171248,6 +171483,7 @@ function consumeDeferredMaterialization(sessionId) {
|
|
|
171248
171483
|
return wasSet;
|
|
171249
171484
|
}
|
|
171250
171485
|
function trackSessionForProject(projectIdentity, sessionId) {
|
|
171486
|
+
activeContextHandlerSessions.add(sessionId);
|
|
171251
171487
|
let sessions = sessionsByProject.get(projectIdentity);
|
|
171252
171488
|
if (!sessions) {
|
|
171253
171489
|
sessions = new Set;
|
|
@@ -171255,6 +171491,9 @@ function trackSessionForProject(projectIdentity, sessionId) {
|
|
|
171255
171491
|
}
|
|
171256
171492
|
sessions.add(sessionId);
|
|
171257
171493
|
}
|
|
171494
|
+
function isContextHandlerSessionActive(sessionId) {
|
|
171495
|
+
return activeContextHandlerSessions.has(sessionId);
|
|
171496
|
+
}
|
|
171258
171497
|
function updateSessionProjectTracking(sessionId, projectIdentity) {
|
|
171259
171498
|
const prev = lastSeenProjectIdentityBySession.get(sessionId);
|
|
171260
171499
|
if (prev && prev !== projectIdentity) {
|
|
@@ -171351,20 +171590,26 @@ function resolveSessionId2(ctx) {
|
|
|
171351
171590
|
return;
|
|
171352
171591
|
}
|
|
171353
171592
|
}
|
|
171354
|
-
function collectMessageEntryIdsByRef(ctx, messages, sessionId) {
|
|
171355
|
-
const sm = ctx.sessionManager;
|
|
171356
|
-
if (typeof sm?.getBranch !== "function")
|
|
171357
|
-
return null;
|
|
171593
|
+
function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEntries) {
|
|
171358
171594
|
let entries;
|
|
171359
|
-
|
|
171360
|
-
entries =
|
|
171361
|
-
}
|
|
171362
|
-
|
|
171363
|
-
|
|
171595
|
+
if (preloadedBranchEntries !== undefined) {
|
|
171596
|
+
entries = preloadedBranchEntries;
|
|
171597
|
+
} else {
|
|
171598
|
+
const sm = ctx.sessionManager;
|
|
171599
|
+
if (typeof sm?.getBranch !== "function")
|
|
171600
|
+
return null;
|
|
171601
|
+
try {
|
|
171602
|
+
const branch = sm.getBranch.call(sm);
|
|
171603
|
+
if (!Array.isArray(branch))
|
|
171604
|
+
return null;
|
|
171605
|
+
entries = branch;
|
|
171606
|
+
} catch (error51) {
|
|
171607
|
+
sessionLog(sessionId ?? "pi", `collectMessageEntryIdsByRef getBranch failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
171608
|
+
return null;
|
|
171609
|
+
}
|
|
171364
171610
|
}
|
|
171365
|
-
if (!Array.isArray(entries))
|
|
171366
|
-
return null;
|
|
171367
171611
|
const entryIdByMsgRef = new Map;
|
|
171612
|
+
const entryIdsByFingerprint = new Map;
|
|
171368
171613
|
for (const entry of entries) {
|
|
171369
171614
|
if (!entry || typeof entry !== "object")
|
|
171370
171615
|
continue;
|
|
@@ -171375,10 +171620,21 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId) {
|
|
|
171375
171620
|
continue;
|
|
171376
171621
|
if (!e.message || typeof e.message !== "object")
|
|
171377
171622
|
continue;
|
|
171378
|
-
|
|
171623
|
+
const message = e.message;
|
|
171624
|
+
entryIdByMsgRef.set(message, e.id);
|
|
171625
|
+
const fingerprint = piMessageEntryFingerprint(e.message);
|
|
171626
|
+
if (fingerprint) {
|
|
171627
|
+
const bucket = entryIdsByFingerprint.get(fingerprint);
|
|
171628
|
+
if (bucket)
|
|
171629
|
+
bucket.push(e.id);
|
|
171630
|
+
else
|
|
171631
|
+
entryIdsByFingerprint.set(fingerprint, [e.id]);
|
|
171632
|
+
}
|
|
171379
171633
|
}
|
|
171380
171634
|
const result = new Array(messages.length);
|
|
171381
171635
|
let resolved = 0;
|
|
171636
|
+
let fingerprintResolved = 0;
|
|
171637
|
+
const consumedFingerprintIds = new Set;
|
|
171382
171638
|
for (let i = 0;i < messages.length; i++) {
|
|
171383
171639
|
const msg = messages[i];
|
|
171384
171640
|
if (!msg || typeof msg !== "object") {
|
|
@@ -171389,15 +171645,67 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId) {
|
|
|
171389
171645
|
if (typeof id === "string") {
|
|
171390
171646
|
result[i] = id;
|
|
171391
171647
|
resolved += 1;
|
|
171648
|
+
continue;
|
|
171649
|
+
}
|
|
171650
|
+
const fingerprint = piMessageEntryFingerprint(msg);
|
|
171651
|
+
const fingerprintId = fingerprint ? entryIdsByFingerprint.get(fingerprint)?.find((candidate) => !consumedFingerprintIds.has(candidate)) : undefined;
|
|
171652
|
+
if (typeof fingerprintId === "string") {
|
|
171653
|
+
consumedFingerprintIds.add(fingerprintId);
|
|
171654
|
+
result[i] = fingerprintId;
|
|
171655
|
+
resolved += 1;
|
|
171656
|
+
fingerprintResolved += 1;
|
|
171392
171657
|
} else {
|
|
171393
171658
|
result[i] = undefined;
|
|
171394
171659
|
}
|
|
171395
171660
|
}
|
|
171396
171661
|
if (resolved < messages.length) {
|
|
171397
|
-
log(`[magic-context][pi]${sessionId ? `[${sessionId}]` : ""} ` + `collectMessageEntryIdsByRef: resolved=${resolved}/${messages.length} ` + `(branchEntries=${entries.length}, messageEntries=${entryIdByMsgRef.size}) — ` + `unmapped slots fall through to synthesized ids; boundary lookup still works ` + `for any compartment whose start/end message is among the resolved set`);
|
|
171662
|
+
log(`[magic-context][pi]${sessionId ? `[${sessionId}]` : ""} ` + `collectMessageEntryIdsByRef: resolved=${resolved}/${messages.length} ` + `(fingerprint=${fingerprintResolved}, branchEntries=${entries.length}, messageEntries=${entryIdByMsgRef.size}) — ` + `unmapped slots fall through to synthesized ids; boundary lookup still works ` + `for any compartment whose start/end message is among the resolved set`);
|
|
171398
171663
|
}
|
|
171399
171664
|
return result;
|
|
171400
171665
|
}
|
|
171666
|
+
function readPiBranchEntriesForContext(ctx, sessionId) {
|
|
171667
|
+
const sm = ctx.sessionManager;
|
|
171668
|
+
if (typeof sm?.getBranch !== "function")
|
|
171669
|
+
return null;
|
|
171670
|
+
try {
|
|
171671
|
+
const entries = sm.getBranch.call(sm);
|
|
171672
|
+
return Array.isArray(entries) ? entries : null;
|
|
171673
|
+
} catch (error51) {
|
|
171674
|
+
sessionLog(sessionId, `Pi branch pre-read failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
171675
|
+
return null;
|
|
171676
|
+
}
|
|
171677
|
+
}
|
|
171678
|
+
function piMessageEntryFingerprint(message) {
|
|
171679
|
+
if (!message || typeof message !== "object")
|
|
171680
|
+
return null;
|
|
171681
|
+
const record2 = message;
|
|
171682
|
+
if (typeof record2.role !== "string")
|
|
171683
|
+
return null;
|
|
171684
|
+
const firstText = firstPiTextContent(record2.content);
|
|
171685
|
+
const firstTextHash = crypto2.createHash("sha256").update(firstText ?? "").digest("hex").slice(0, 16);
|
|
171686
|
+
return JSON.stringify([
|
|
171687
|
+
typeof record2.responseId === "string" ? record2.responseId : null,
|
|
171688
|
+
typeof record2.timestamp === "number" || typeof record2.timestamp === "string" ? record2.timestamp : null,
|
|
171689
|
+
record2.role,
|
|
171690
|
+
typeof record2.toolCallId === "string" ? record2.toolCallId : null,
|
|
171691
|
+
firstTextHash
|
|
171692
|
+
]);
|
|
171693
|
+
}
|
|
171694
|
+
function firstPiTextContent(content) {
|
|
171695
|
+
if (typeof content === "string")
|
|
171696
|
+
return content;
|
|
171697
|
+
if (!Array.isArray(content))
|
|
171698
|
+
return null;
|
|
171699
|
+
for (const part of content) {
|
|
171700
|
+
if (!part || typeof part !== "object")
|
|
171701
|
+
continue;
|
|
171702
|
+
const record2 = part;
|
|
171703
|
+
if (record2.type === "text" && typeof record2.text === "string") {
|
|
171704
|
+
return record2.text;
|
|
171705
|
+
}
|
|
171706
|
+
}
|
|
171707
|
+
return null;
|
|
171708
|
+
}
|
|
171401
171709
|
function registerPiContextHandler(pi, options) {
|
|
171402
171710
|
const tagger = createTagger();
|
|
171403
171711
|
const schedulerConfig = options.scheduler ?? {
|
|
@@ -171429,15 +171737,16 @@ function registerPiContextHandler(pi, options) {
|
|
|
171429
171737
|
const projectIdentity = resolveProjectIdentity(projectDirectory);
|
|
171430
171738
|
updateSessionProjectTracking(sessionId, projectIdentity);
|
|
171431
171739
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
171740
|
+
const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
|
|
171432
171741
|
const rawMessageProvider = {
|
|
171433
|
-
readMessages: () => readPiSessionMessages(ctx),
|
|
171742
|
+
readMessages: () => branchEntries !== null ? convertEntriesToRawMessages([...branchEntries]) : readPiSessionMessages(ctx),
|
|
171434
171743
|
readMessageById: (messageId) => readPiSessionMessageById(ctx, messageId)
|
|
171435
171744
|
};
|
|
171436
171745
|
rawMessageProviderUnregistersBySession.get(sessionId)?.();
|
|
171437
171746
|
const unregisterRaw = setRawMessageProvider(sessionId, rawMessageProvider);
|
|
171438
171747
|
rawMessageProviderUnregistersBySession.set(sessionId, unregisterRaw);
|
|
171439
171748
|
scheduleReconciliation(options.db, sessionId, readRawSessionMessages);
|
|
171440
|
-
const strictEntryIds = collectMessageEntryIdsByRef(ctx, event.messages, sessionId);
|
|
171749
|
+
const strictEntryIds = branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
|
|
171441
171750
|
const tLastUser = performance.now();
|
|
171442
171751
|
const latestUser = findLatestUserMessageIdPi(event.messages, buildPiMessageIdByIndex(event.messages, strictEntryIds));
|
|
171443
171752
|
logTransformTiming(sessionId, "findLastUserMessageId", tLastUser);
|
|
@@ -171559,10 +171868,7 @@ function registerPiContextHandler(pi, options) {
|
|
|
171559
171868
|
const histPromise = inFlightHistorian.get(sessionId);
|
|
171560
171869
|
if (histPromise) {
|
|
171561
171870
|
try {
|
|
171562
|
-
await
|
|
171563
|
-
histPromise,
|
|
171564
|
-
new Promise((resolve4) => setTimeout(resolve4, 30000))
|
|
171565
|
-
]);
|
|
171871
|
+
await withTimeout(histPromise, 30000);
|
|
171566
171872
|
sessionLog(sessionId, "EMERGENCY: historian wait completed (or timed out)");
|
|
171567
171873
|
} catch {}
|
|
171568
171874
|
}
|
|
@@ -171570,7 +171876,7 @@ function registerPiContextHandler(pi, options) {
|
|
|
171570
171876
|
const isCacheBusting = historyRefreshSessions.has(sessionId);
|
|
171571
171877
|
sessionLog(sessionId, `transform: usage=${usagePercentage.toFixed(1)}% (${usageInputTokens} tokens, limit=${usageContextLimit ?? "?"}) decision=${schedulerDecision}${forceMaterialization ? " force=true" : ""}${isEmergency ? " EMERGENCY=true" : ""}${isCacheBusting ? " busting=true" : ""}`);
|
|
171572
171878
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tEmergencyRecovery);
|
|
171573
|
-
const entryIds =
|
|
171879
|
+
const entryIds = strictEntryIds ?? undefined;
|
|
171574
171880
|
const result = await runPipeline({
|
|
171575
171881
|
db: options.db,
|
|
171576
171882
|
tagger,
|
|
@@ -171592,7 +171898,9 @@ function registerPiContextHandler(pi, options) {
|
|
|
171592
171898
|
reasoningClearing: {
|
|
171593
171899
|
clearReasoningAge: options.heuristics?.clearReasoningAge ?? DEFAULT_CLEAR_REASONING_AGE
|
|
171594
171900
|
},
|
|
171595
|
-
temporalAwareness: options.injection?.temporalAwareness === true
|
|
171901
|
+
temporalAwareness: options.injection?.temporalAwareness === true,
|
|
171902
|
+
appendCompaction: resolvePiAppendCompaction(ctx),
|
|
171903
|
+
readBranchEntries: resolvePiReadBranchEntries(ctx)
|
|
171596
171904
|
});
|
|
171597
171905
|
if (options.historian) {
|
|
171598
171906
|
maybeFireHistorian({
|
|
@@ -171600,7 +171908,9 @@ function registerPiContextHandler(pi, options) {
|
|
|
171600
171908
|
sessionId,
|
|
171601
171909
|
db: options.db,
|
|
171602
171910
|
historian: options.historian,
|
|
171603
|
-
isFirstContextPassForSession
|
|
171911
|
+
isFirstContextPassForSession,
|
|
171912
|
+
activeTags: result.activeTags,
|
|
171913
|
+
rawMessageProvider
|
|
171604
171914
|
});
|
|
171605
171915
|
maybeFireCompressor({
|
|
171606
171916
|
ctx,
|
|
@@ -171719,6 +172029,43 @@ async function awaitInFlightHistorians() {
|
|
|
171719
172029
|
];
|
|
171720
172030
|
await Promise.allSettled(promises);
|
|
171721
172031
|
}
|
|
172032
|
+
function splitModelKeyForPi(modelKey) {
|
|
172033
|
+
if (!modelKey)
|
|
172034
|
+
return { providerID: undefined, modelID: undefined };
|
|
172035
|
+
const slash = modelKey.indexOf("/");
|
|
172036
|
+
if (slash <= 0 || slash === modelKey.length - 1) {
|
|
172037
|
+
return { providerID: undefined, modelID: undefined };
|
|
172038
|
+
}
|
|
172039
|
+
return {
|
|
172040
|
+
providerID: modelKey.slice(0, slash),
|
|
172041
|
+
modelID: modelKey.slice(slash + 1)
|
|
172042
|
+
};
|
|
172043
|
+
}
|
|
172044
|
+
function resolvePiHistorianTriggerInputs(args) {
|
|
172045
|
+
const { providerID, modelID } = splitModelKeyForPi(args.modelKey);
|
|
172046
|
+
let contextLimit = resolveContextLimit(providerID, modelID, {
|
|
172047
|
+
db: args.db,
|
|
172048
|
+
sessionID: args.sessionId
|
|
172049
|
+
});
|
|
172050
|
+
if ((providerID === undefined || modelID === undefined) && typeof args.usageContextLimit === "number" && Number.isFinite(args.usageContextLimit) && args.usageContextLimit > 0) {
|
|
172051
|
+
contextLimit = args.usageContextLimit;
|
|
172052
|
+
}
|
|
172053
|
+
const executeThresholdPercentage = resolveExecuteThreshold(args.historian.executeThresholdPercentage ?? 65, args.modelKey, 65, {
|
|
172054
|
+
tokensConfig: args.historian.executeThresholdTokens,
|
|
172055
|
+
contextLimit,
|
|
172056
|
+
sessionId: args.sessionId
|
|
172057
|
+
});
|
|
172058
|
+
return {
|
|
172059
|
+
executeThresholdPercentage,
|
|
172060
|
+
triggerBudget: deriveTriggerBudget(contextLimit, executeThresholdPercentage),
|
|
172061
|
+
autoDropToolAge: args.historian.autoDropToolAge ?? 100,
|
|
172062
|
+
protectedTags: args.historian.protectedTags,
|
|
172063
|
+
clearReasoningAge: args.historian.clearReasoningAge ?? DEFAULT_CLEAR_REASONING_AGE,
|
|
172064
|
+
dropToolStructure: args.historian.dropToolStructure ?? true,
|
|
172065
|
+
commitClusterTrigger: args.historian.commitClusterTrigger,
|
|
172066
|
+
contextLimit
|
|
172067
|
+
};
|
|
172068
|
+
}
|
|
171722
172069
|
function resolveHistoryBudgetTokensForPi(args) {
|
|
171723
172070
|
const {
|
|
171724
172071
|
historyBudgetPercentage,
|
|
@@ -171777,6 +172124,10 @@ function maybeFireCompressor(args) {
|
|
|
171777
172124
|
maxCompartmentsPerPass: compressor.maxCompartmentsPerPass,
|
|
171778
172125
|
graceCompartments: compressor.graceCompartments,
|
|
171779
172126
|
onPublished: () => {
|
|
172127
|
+
if (!isContextHandlerSessionActive(sessionId)) {
|
|
172128
|
+
sessionLog(sessionId, "compressor publication ignored: session was cleared");
|
|
172129
|
+
return;
|
|
172130
|
+
}
|
|
171780
172131
|
signalPiDeferredHistoryRefresh(sessionId);
|
|
171781
172132
|
signalPiDeferredMaterialization(sessionId);
|
|
171782
172133
|
historian.onStatusChange?.(ctx, sessionId);
|
|
@@ -171789,7 +172140,9 @@ function maybeFireCompressor(args) {
|
|
|
171789
172140
|
sessionLog(sessionId, `compressor failed in background: ${err instanceof Error ? err.message : String(err)}`);
|
|
171790
172141
|
}).finally(() => {
|
|
171791
172142
|
inFlightCompressor.delete(sessionId);
|
|
171792
|
-
|
|
172143
|
+
if (isContextHandlerSessionActive(sessionId)) {
|
|
172144
|
+
historian.onStatusChange?.(ctx, sessionId);
|
|
172145
|
+
}
|
|
171793
172146
|
});
|
|
171794
172147
|
inFlightCompressor.set(sessionId, runPromise);
|
|
171795
172148
|
}
|
|
@@ -171834,6 +172187,10 @@ function spawnPiHistorianRun(args) {
|
|
|
171834
172187
|
memoryEnabled: historian.memoryEnabled,
|
|
171835
172188
|
autoPromote: historian.autoPromote,
|
|
171836
172189
|
onPublished: () => {
|
|
172190
|
+
if (!isContextHandlerSessionActive(sessionId)) {
|
|
172191
|
+
sessionLog(sessionId, "historian publication ignored: session was cleared");
|
|
172192
|
+
return;
|
|
172193
|
+
}
|
|
171837
172194
|
try {
|
|
171838
172195
|
clearEmergencyRecovery(db, sessionId);
|
|
171839
172196
|
} catch (err) {
|
|
@@ -171846,7 +172203,9 @@ function spawnPiHistorianRun(args) {
|
|
|
171846
172203
|
}).finally(() => {
|
|
171847
172204
|
inFlightHistorian.delete(sessionId);
|
|
171848
172205
|
unregister();
|
|
171849
|
-
|
|
172206
|
+
if (isContextHandlerSessionActive(sessionId)) {
|
|
172207
|
+
historian.onStatusChange?.(ctx, sessionId);
|
|
172208
|
+
}
|
|
171850
172209
|
});
|
|
171851
172210
|
inFlightHistorian.set(sessionId, runPromise);
|
|
171852
172211
|
historian.onStatusChange?.(ctx, sessionId);
|
|
@@ -171877,7 +172236,10 @@ function maybeFireHistorian(args) {
|
|
|
171877
172236
|
return;
|
|
171878
172237
|
}
|
|
171879
172238
|
let usage;
|
|
172239
|
+
let usageContextLimit;
|
|
171880
172240
|
try {
|
|
172241
|
+
const piUsage = ctx.getContextUsage?.();
|
|
172242
|
+
usageContextLimit = typeof piUsage?.contextWindow === "number" && piUsage.contextWindow > 0 ? piUsage.contextWindow : undefined;
|
|
171881
172243
|
const sessionMetaForUsage = getOrCreateSessionMeta(db, sessionId);
|
|
171882
172244
|
if (sessionMetaForUsage.lastContextPercentage > 0 && sessionMetaForUsage.lastInputTokens > 0) {
|
|
171883
172245
|
usage = {
|
|
@@ -171886,7 +172248,6 @@ function maybeFireHistorian(args) {
|
|
|
171886
172248
|
};
|
|
171887
172249
|
sessionLog(sessionId, `historian trigger eval: usage=${usage.percentage.toFixed(1)}% (${usage.inputTokens} tokens) [from session_meta], checking trigger...`);
|
|
171888
172250
|
} else {
|
|
171889
|
-
const piUsage = ctx.getContextUsage?.();
|
|
171890
172251
|
if (!piUsage || piUsage.tokens === null || piUsage.percent === null || piUsage.contextWindow === 0) {
|
|
171891
172252
|
sessionLog(sessionId, `historian trigger eval: no usage info yet (tokens=${piUsage?.tokens ?? "<no piUsage>"}, percent=${piUsage?.percent ?? "<no piUsage>"}, contextWindow=${piUsage?.contextWindow ?? "<no piUsage>"})`);
|
|
171892
172253
|
return;
|
|
@@ -171901,7 +172262,7 @@ function maybeFireHistorian(args) {
|
|
|
171901
172262
|
sessionLog(sessionId, `historian trigger eval: getContextUsage threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
171902
172263
|
return;
|
|
171903
172264
|
}
|
|
171904
|
-
const provider2 = {
|
|
172265
|
+
const provider2 = args.rawMessageProvider ?? {
|
|
171905
172266
|
readMessages: () => readPiSessionMessages(ctx)
|
|
171906
172267
|
};
|
|
171907
172268
|
const unregister = setRawMessageProvider(sessionId, provider2);
|
|
@@ -171933,7 +172294,15 @@ Historian previously failed ${failureState.failureCount} time(s), so magic-conte
|
|
|
171933
172294
|
}
|
|
171934
172295
|
}
|
|
171935
172296
|
const sessionMeta = getOrCreateSessionMeta(db, sessionId);
|
|
171936
|
-
const
|
|
172297
|
+
const modelKey = liveModelBySession.get(sessionId);
|
|
172298
|
+
const triggerInputs = resolvePiHistorianTriggerInputs({
|
|
172299
|
+
db,
|
|
172300
|
+
sessionId,
|
|
172301
|
+
historian,
|
|
172302
|
+
modelKey,
|
|
172303
|
+
usageContextLimit
|
|
172304
|
+
});
|
|
172305
|
+
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.autoDropToolAge, triggerInputs.protectedTags, triggerInputs.clearReasoningAge, triggerInputs.dropToolStructure, triggerInputs.commitClusterTrigger, args.activeTags);
|
|
171937
172306
|
if (!trigger.shouldFire) {
|
|
171938
172307
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
171939
172308
|
return;
|
|
@@ -171951,12 +172320,17 @@ Historian previously failed ${failureState.failureCount} time(s), so magic-conte
|
|
|
171951
172320
|
} catch (err) {
|
|
171952
172321
|
const message = err instanceof Error ? err.message : String(err);
|
|
171953
172322
|
sessionLog(sessionId, `historian trigger eval failed: ${message}`);
|
|
172323
|
+
} finally {
|
|
171954
172324
|
if (!triggered)
|
|
171955
172325
|
unregister();
|
|
171956
172326
|
}
|
|
171957
172327
|
}
|
|
171958
172328
|
async function runPipeline(args) {
|
|
171959
172329
|
let executedWorkThisPass = false;
|
|
172330
|
+
let historyWasConsumedThisPass = false;
|
|
172331
|
+
let suppressDeferredHistoryDrain = false;
|
|
172332
|
+
let casLost = false;
|
|
172333
|
+
const deferredHistoryWasPendingAtPassStart = deferredHistoryRefreshSessions.has(args.sessionId);
|
|
171960
172334
|
if (args.temporalAwareness) {
|
|
171961
172335
|
const tTemporal = performance.now();
|
|
171962
172336
|
try {
|
|
@@ -171997,7 +172371,7 @@ async function runPipeline(args) {
|
|
|
171997
172371
|
}
|
|
171998
172372
|
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
171999
172373
|
const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
|
|
172000
|
-
const deferredHistoryRefreshWasPending =
|
|
172374
|
+
const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
|
|
172001
172375
|
const pendingOps = getPendingOps(args.db, args.sessionId);
|
|
172002
172376
|
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal;
|
|
172003
172377
|
const canConsumeDeferredLate = baseShouldApplyPendingOps || shouldRunHeuristics;
|
|
@@ -172140,9 +172514,10 @@ async function runPipeline(args) {
|
|
|
172140
172514
|
injectionResult = injectSessionHistoryIntoPi(args.db, args.sessionId, args.messages, args.isCacheBusting || deferredHistoryRefresh, args.projectIdentity, args.injection.injectionBudgetTokens, args.injection.temporalAwareness, args.entryIds);
|
|
172141
172515
|
if (args.isCacheBusting) {
|
|
172142
172516
|
historyRefreshSessions.delete(args.sessionId);
|
|
172517
|
+
historyWasConsumedThisPass = true;
|
|
172143
172518
|
}
|
|
172144
172519
|
if (deferredHistoryRefresh) {
|
|
172145
|
-
|
|
172520
|
+
historyWasConsumedThisPass = true;
|
|
172146
172521
|
}
|
|
172147
172522
|
logTransformTiming(args.sessionId, "prepareCompartmentInjection", tInjection);
|
|
172148
172523
|
logTransformTiming(args.sessionId, "compartmentPhase", tInjection);
|
|
@@ -172156,6 +172531,34 @@ async function runPipeline(args) {
|
|
|
172156
172531
|
messages: args.messages,
|
|
172157
172532
|
isCacheBusting: args.isCacheBusting
|
|
172158
172533
|
});
|
|
172534
|
+
const deferredHistoryDrainEligible = historyWasConsumedThisPass && deferredHistoryWasPendingAtPassStart && !suppressDeferredHistoryDrain && !casLost;
|
|
172535
|
+
if (deferredHistoryDrainEligible) {
|
|
172536
|
+
try {
|
|
172537
|
+
const pending = getPendingPiCompactionMarkerState(args.db, args.sessionId);
|
|
172538
|
+
if (!pending) {
|
|
172539
|
+
consumeDeferredHistoryRefresh(args.sessionId);
|
|
172540
|
+
} else if (!args.appendCompaction || !args.readBranchEntries) {
|
|
172541
|
+
suppressDeferredHistoryDrain = true;
|
|
172542
|
+
sessionLog(args.sessionId, "Pi compaction-marker drain skipped: sessionManager appendCompaction/getBranch unavailable; preserving deferred-history signal");
|
|
172543
|
+
} else {
|
|
172544
|
+
const outcome = applyDeferredPiCompactionMarker({
|
|
172545
|
+
db: args.db,
|
|
172546
|
+
appendCompaction: args.appendCompaction,
|
|
172547
|
+
readBranchEntries: args.readBranchEntries
|
|
172548
|
+
}, args.sessionId, pending);
|
|
172549
|
+
if (outcome.kind === "retryable-failure") {
|
|
172550
|
+
sessionLog(args.sessionId, `Pi compaction-marker drain retryable failure: ${outcome.error.message}`);
|
|
172551
|
+
} else if (clearPendingPiCompactionMarkerStateIf(args.db, args.sessionId, pending)) {
|
|
172552
|
+
consumeDeferredHistoryRefresh(args.sessionId);
|
|
172553
|
+
} else {
|
|
172554
|
+
casLost = true;
|
|
172555
|
+
sessionLog(args.sessionId, "CAS-clear failed (newer blob written or another actor cleared); preserving deferred-history signal");
|
|
172556
|
+
}
|
|
172557
|
+
}
|
|
172558
|
+
} catch (err) {
|
|
172559
|
+
sessionLog(args.sessionId, `Pi compaction-marker drain failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
172560
|
+
}
|
|
172561
|
+
}
|
|
172159
172562
|
if (executedWorkThisPass) {
|
|
172160
172563
|
try {
|
|
172161
172564
|
const currentFlag = peekDeferredExecutePending(args.db, args.sessionId);
|
|
@@ -172185,7 +172588,8 @@ async function runPipeline(args) {
|
|
|
172185
172588
|
heuristicsResult,
|
|
172186
172589
|
injectionResult,
|
|
172187
172590
|
targetCount: targets.size,
|
|
172188
|
-
reasoningWatermark: getOrCreateSessionMeta(args.db, args.sessionId).clearedReasoningThroughTag ?? 0
|
|
172591
|
+
reasoningWatermark: getOrCreateSessionMeta(args.db, args.sessionId).clearedReasoningThroughTag ?? 0,
|
|
172592
|
+
activeTags
|
|
172189
172593
|
};
|
|
172190
172594
|
}
|
|
172191
172595
|
function applyRollingNudge(args) {
|
|
@@ -172217,11 +172621,15 @@ function applyStickyTurnReminder(args) {
|
|
|
172217
172621
|
const messageIdByIndex = buildPiMessageIdByIndex(args.messages, args.entryIds);
|
|
172218
172622
|
if (reminder.messageId) {
|
|
172219
172623
|
const reinjected = appendReminderToUserMessageByIdPi(args.messages, messageIdByIndex, reminder.messageId, reminder.text);
|
|
172220
|
-
if (!reinjected && args.isCacheBustingPass) {
|
|
172624
|
+
if (!reinjected && args.isCacheBustingPass && args.entryIds !== null) {
|
|
172221
172625
|
clearPersistedStickyTurnReminder(args.db, args.sessionId);
|
|
172222
172626
|
}
|
|
172223
172627
|
return args.messages;
|
|
172224
172628
|
}
|
|
172629
|
+
if (args.entryIds === null) {
|
|
172630
|
+
sessionLog(args.sessionId, "Pi sticky turn reminder: strict resolution failed; replay-only until next pass");
|
|
172631
|
+
return args.messages;
|
|
172632
|
+
}
|
|
172225
172633
|
const latest = findLatestUserMessageIdPi(args.messages, messageIdByIndex);
|
|
172226
172634
|
if (latest) {
|
|
172227
172635
|
appendReminderToPiUserMessage(args.messages[latest.index], reminder.text);
|
|
@@ -172303,8 +172711,6 @@ function buildPiMessageIdByIndex(messages, entryIds) {
|
|
|
172303
172711
|
const messageId = messages[index]?.id;
|
|
172304
172712
|
if (typeof messageId === "string") {
|
|
172305
172713
|
ids.set(index, messageId);
|
|
172306
|
-
} else if (entryIds === null) {
|
|
172307
|
-
ids.set(index, `pi:${index}:${readTimestamp(messages[index])}`);
|
|
172308
172714
|
}
|
|
172309
172715
|
}
|
|
172310
172716
|
return ids;
|
|
@@ -172333,10 +172739,6 @@ function appendReminderToUserMessageByIdPi(messages, messageIdByIndex, messageId
|
|
|
172333
172739
|
}
|
|
172334
172740
|
return false;
|
|
172335
172741
|
}
|
|
172336
|
-
function readTimestamp(message) {
|
|
172337
|
-
const ts = message.timestamp;
|
|
172338
|
-
return typeof ts === "number" && Number.isFinite(ts) ? String(ts) : "no-ts";
|
|
172339
|
-
}
|
|
172340
172742
|
function appendReminderToPiUserMessage(message, reminder) {
|
|
172341
172743
|
if (message.role !== "user")
|
|
172342
172744
|
return;
|
|
@@ -172363,6 +172765,7 @@ function appendReminderToPiUserMessage(message, reminder) {
|
|
|
172363
172765
|
contentArr.push({ type: "text", text: reminder.trimStart() });
|
|
172364
172766
|
}
|
|
172365
172767
|
function clearContextHandlerSession(sessionId) {
|
|
172768
|
+
activeContextHandlerSessions.delete(sessionId);
|
|
172366
172769
|
clearAutoSearchForPiSession(sessionId);
|
|
172367
172770
|
lastEmergencyNotificationAtMs.delete(sessionId);
|
|
172368
172771
|
historyRefreshSessions.delete(sessionId);
|
|
@@ -173501,7 +173904,7 @@ async function executePartialRecompInternal(deps, range) {
|
|
|
173501
173904
|
}
|
|
173502
173905
|
deps.onCompartmentStatePublished?.(sessionId);
|
|
173503
173906
|
const lastEnd = merged[merged.length - 1]?.endMessage ?? snapEnd;
|
|
173504
|
-
if (
|
|
173907
|
+
if (lastEnd > 0) {
|
|
173505
173908
|
updateCompactionMarkerAfterPublication(db, sessionId, lastEnd, deps.directory);
|
|
173506
173909
|
const stalePending = getPendingCompactionMarkerState(db, sessionId);
|
|
173507
173910
|
if (stalePending) {
|
|
@@ -173760,7 +174163,7 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
|
|
|
173760
174163
|
if (lastCompartmentEnd2 > 0) {
|
|
173761
174164
|
queueDropsForCompartmentalizedMessages(db, sessionId, lastCompartmentEnd2);
|
|
173762
174165
|
}
|
|
173763
|
-
if (
|
|
174166
|
+
if (lastCompartmentEnd2 > 0) {
|
|
173764
174167
|
updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd2, deps.directory);
|
|
173765
174168
|
const stalePending = getPendingCompactionMarkerState(db, sessionId);
|
|
173766
174169
|
if (stalePending) {
|
|
@@ -174184,6 +174587,7 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
174184
174587
|
text: result,
|
|
174185
174588
|
level: inferLevel(result)
|
|
174186
174589
|
});
|
|
174590
|
+
queueAndApplyPiRecompMarker({ db: deps.db, sessionId, ctx });
|
|
174187
174591
|
signalPiHistoryRefresh(sessionId);
|
|
174188
174592
|
signalPiPendingMaterialization(sessionId);
|
|
174189
174593
|
clearPiCompressorState(sessionId);
|
|
@@ -174206,6 +174610,60 @@ ${describeError(error51).brief}`,
|
|
|
174206
174610
|
}
|
|
174207
174611
|
});
|
|
174208
174612
|
}
|
|
174613
|
+
function queueAndApplyPiRecompMarker(args) {
|
|
174614
|
+
const appendCompaction = resolvePiAppendCompaction2(args.ctx);
|
|
174615
|
+
const readBranchEntries = resolvePiReadBranchEntries2(args.ctx);
|
|
174616
|
+
if (!appendCompaction || !readBranchEntries)
|
|
174617
|
+
return;
|
|
174618
|
+
const compartments = getCompartments(args.db, args.sessionId);
|
|
174619
|
+
const last = compartments[compartments.length - 1];
|
|
174620
|
+
if (!last)
|
|
174621
|
+
return;
|
|
174622
|
+
let firstKeptEntryId = null;
|
|
174623
|
+
try {
|
|
174624
|
+
firstKeptEntryId = findFirstKeptEntryId(readBranchEntries(), last.endMessage);
|
|
174625
|
+
} catch {
|
|
174626
|
+
firstKeptEntryId = null;
|
|
174627
|
+
}
|
|
174628
|
+
if (!firstKeptEntryId || last.endMessageId.length === 0)
|
|
174629
|
+
return;
|
|
174630
|
+
const pending = {
|
|
174631
|
+
firstKeptEntryId,
|
|
174632
|
+
endMessageId: last.endMessageId,
|
|
174633
|
+
ordinal: last.endMessage,
|
|
174634
|
+
tokensBefore: 0,
|
|
174635
|
+
summary: buildPiCompactionSummary(compartments),
|
|
174636
|
+
publishedAt: Date.now()
|
|
174637
|
+
};
|
|
174638
|
+
setPendingPiCompactionMarkerState(args.db, args.sessionId, pending);
|
|
174639
|
+
const outcome = applyDeferredPiCompactionMarker({ db: args.db, appendCompaction, readBranchEntries }, args.sessionId, pending);
|
|
174640
|
+
if (outcome.kind === "retryable-failure") {
|
|
174641
|
+
signalPiDeferredHistoryRefresh(args.sessionId);
|
|
174642
|
+
return;
|
|
174643
|
+
}
|
|
174644
|
+
if (!clearPendingPiCompactionMarkerStateIf(args.db, args.sessionId, pending)) {
|
|
174645
|
+
signalPiDeferredHistoryRefresh(args.sessionId);
|
|
174646
|
+
}
|
|
174647
|
+
}
|
|
174648
|
+
function resolvePiAppendCompaction2(ctx) {
|
|
174649
|
+
const sm = ctx?.sessionManager;
|
|
174650
|
+
if (typeof sm?.appendCompaction !== "function")
|
|
174651
|
+
return;
|
|
174652
|
+
return sm.appendCompaction.bind(sm);
|
|
174653
|
+
}
|
|
174654
|
+
function resolvePiReadBranchEntries2(ctx) {
|
|
174655
|
+
const sm = ctx?.sessionManager;
|
|
174656
|
+
if (typeof sm?.getBranch !== "function")
|
|
174657
|
+
return;
|
|
174658
|
+
return () => {
|
|
174659
|
+
try {
|
|
174660
|
+
const entries = sm.getBranch?.call(sm);
|
|
174661
|
+
return Array.isArray(entries) ? entries : [];
|
|
174662
|
+
} catch {
|
|
174663
|
+
return [];
|
|
174664
|
+
}
|
|
174665
|
+
};
|
|
174666
|
+
}
|
|
174209
174667
|
function parseRecompArgs(raw) {
|
|
174210
174668
|
const trimmed = raw.trim();
|
|
174211
174669
|
if (trimmed.length === 0)
|
|
@@ -174477,7 +174935,7 @@ import {
|
|
|
174477
174935
|
// package.json
|
|
174478
174936
|
var package_default = {
|
|
174479
174937
|
name: "@cortexkit/pi-magic-context",
|
|
174480
|
-
version: "0.21.
|
|
174938
|
+
version: "0.21.5",
|
|
174481
174939
|
type: "module",
|
|
174482
174940
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
174483
174941
|
main: "dist/index.js",
|
|
@@ -179579,8 +180037,15 @@ function createCtxNoteTool(deps) {
|
|
|
179579
180037
|
if (typeof params.note_id !== "number") {
|
|
179580
180038
|
return err3("Error: 'note_id' is required when action is 'dismiss'.");
|
|
179581
180039
|
}
|
|
179582
|
-
const
|
|
179583
|
-
|
|
180040
|
+
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
180041
|
+
if (!projectIdentity) {
|
|
180042
|
+
return err3("Error: Could not resolve project identity for note dismiss.");
|
|
180043
|
+
}
|
|
180044
|
+
const dismissed = dismissNote(deps.db, params.note_id, {
|
|
180045
|
+
projectPath: projectIdentity,
|
|
180046
|
+
sessionId
|
|
180047
|
+
});
|
|
180048
|
+
return dismissed ? ok3(`Note #${params.note_id} dismissed.`) : err3(`Error: Note #${params.note_id} not found in your session/project or already dismissed.`);
|
|
179584
180049
|
}
|
|
179585
180050
|
if (action2 === "update") {
|
|
179586
180051
|
if (typeof params.note_id !== "number") {
|
|
@@ -179594,9 +180059,16 @@ function createCtxNoteTool(deps) {
|
|
|
179594
180059
|
if (!updates.content && !updates.surfaceCondition) {
|
|
179595
180060
|
return err3("Error: Provide 'content' and/or 'surface_condition' to update.");
|
|
179596
180061
|
}
|
|
179597
|
-
const
|
|
180062
|
+
const projectIdentity = resolveProjectIdentity(ctx.cwd);
|
|
180063
|
+
if (!projectIdentity) {
|
|
180064
|
+
return err3("Error: Could not resolve project identity for note update.");
|
|
180065
|
+
}
|
|
180066
|
+
const updated = updateNote(deps.db, params.note_id, updates, {
|
|
180067
|
+
projectPath: projectIdentity,
|
|
180068
|
+
sessionId
|
|
180069
|
+
});
|
|
179598
180070
|
if (!updated) {
|
|
179599
|
-
return err3(`Note #${params.note_id} not found.`);
|
|
180071
|
+
return err3(`Error: Note #${params.note_id} not found in your session/project.`);
|
|
179600
180072
|
}
|
|
179601
180073
|
const parts = [];
|
|
179602
180074
|
if (updates.content)
|
|
@@ -180207,7 +180679,6 @@ function resolveHistorianFromConfig(config2) {
|
|
|
180207
180679
|
if (!model || model.length === 0)
|
|
180208
180680
|
return;
|
|
180209
180681
|
const historianContextLimit = resolveHistorianContextLimit(model);
|
|
180210
|
-
const triggerBudget = deriveTriggerBudget(historianContextLimit, 65);
|
|
180211
180682
|
const historianChunkTokens = deriveHistorianChunkTokens(historianContextLimit);
|
|
180212
180683
|
const fbRaw = historian?.fallback_models;
|
|
180213
180684
|
const fallbackModels = typeof fbRaw === "string" ? [fbRaw] : fbRaw;
|
|
@@ -180220,7 +180691,12 @@ function resolveHistorianFromConfig(config2) {
|
|
|
180220
180691
|
twoPass: historian?.two_pass === true,
|
|
180221
180692
|
thinkingLevel: historian?.thinking_level,
|
|
180222
180693
|
executeThresholdPercentage: config2.execute_threshold_percentage,
|
|
180223
|
-
|
|
180694
|
+
executeThresholdTokens: config2.execute_threshold_tokens,
|
|
180695
|
+
commitClusterTrigger: config2.commit_cluster_trigger,
|
|
180696
|
+
autoDropToolAge: config2.auto_drop_tool_age,
|
|
180697
|
+
protectedTags: config2.protected_tags,
|
|
180698
|
+
clearReasoningAge: config2.clear_reasoning_age,
|
|
180699
|
+
dropToolStructure: config2.drop_tool_structure,
|
|
180224
180700
|
historyBudgetPercentage: config2.history_budget_percentage,
|
|
180225
180701
|
compressor: {
|
|
180226
180702
|
enabled: config2.compressor.enabled,
|
|
@@ -180270,6 +180746,17 @@ async function src_default2(pi) {
|
|
|
180270
180746
|
const projectDir = process.cwd();
|
|
180271
180747
|
const projectIdentity = resolveProjectIdentity(projectDir);
|
|
180272
180748
|
const seenDreamerProjectIdentities = new Set([projectIdentity]);
|
|
180749
|
+
try {
|
|
180750
|
+
const pendingPiMarkerSessions = getSessionsWithPendingPiMarker(db);
|
|
180751
|
+
for (const sid of pendingPiMarkerSessions) {
|
|
180752
|
+
signalPiDeferredHistoryRefresh(sid);
|
|
180753
|
+
}
|
|
180754
|
+
if (pendingPiMarkerSessions.length > 0) {
|
|
180755
|
+
log(`${PREFIX2} rehydrated ${pendingPiMarkerSessions.length} Pi deferred compaction marker session(s)`);
|
|
180756
|
+
}
|
|
180757
|
+
} catch (err5) {
|
|
180758
|
+
warn(`Magic Context (pi) failed to rehydrate deferred Pi compaction markers: ${err5 instanceof Error ? err5.message : String(err5)}`);
|
|
180759
|
+
}
|
|
180273
180760
|
info(`loaded v${PLUGIN_VERSION} | harness=pi | db=${dbPath} | ` + `project=${projectIdentity} | dir=${projectDir}`);
|
|
180274
180761
|
const { config: config2, warnings, loadedFromPaths } = loadPiConfig({
|
|
180275
180762
|
cwd: projectDir
|
|
@@ -180625,18 +181112,12 @@ ${block}` : event.systemPrompt;
|
|
|
180625
181112
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
180626
181113
|
const SHUTDOWN_DRAIN_MS = 5000;
|
|
180627
181114
|
try {
|
|
180628
|
-
await
|
|
180629
|
-
awaitInFlightHistorians(),
|
|
180630
|
-
new Promise((resolve4) => setTimeout(resolve4, SHUTDOWN_DRAIN_MS))
|
|
180631
|
-
]);
|
|
181115
|
+
await withTimeout(awaitInFlightHistorians(), SHUTDOWN_DRAIN_MS);
|
|
180632
181116
|
} catch (err5) {
|
|
180633
181117
|
warn("shutdown: historian drain threw:", err5);
|
|
180634
181118
|
}
|
|
180635
181119
|
try {
|
|
180636
|
-
await
|
|
180637
|
-
awaitInFlightDreamers(),
|
|
180638
|
-
new Promise((resolve4) => setTimeout(resolve4, SHUTDOWN_DRAIN_MS))
|
|
180639
|
-
]);
|
|
181120
|
+
await withTimeout(awaitInFlightDreamers(), SHUTDOWN_DRAIN_MS);
|
|
180640
181121
|
} catch (err5) {
|
|
180641
181122
|
warn("shutdown: dreamer drain threw:", err5);
|
|
180642
181123
|
}
|