@cortexkit/pi-magic-context 0.31.4 → 0.32.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.js +2298 -707
- package/dist/subagent-entry.js +482 -114
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15166,7 +15166,7 @@ async function resolvePromptContext(client, sessionId) {
|
|
|
15166
15166
|
var PROMPT_CONTEXT_MESSAGE_LIMIT = 50;
|
|
15167
15167
|
|
|
15168
15168
|
// src/index.ts
|
|
15169
|
-
import { createRequire as
|
|
15169
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
15170
15170
|
import { join as join13, resolve as resolve3 } from "node:path";
|
|
15171
15171
|
|
|
15172
15172
|
// ../plugin/src/config/agent-disable.ts
|
|
@@ -148774,6 +148774,12 @@ function parseJsonRecord(value) {
|
|
|
148774
148774
|
return null;
|
|
148775
148775
|
}
|
|
148776
148776
|
}
|
|
148777
|
+
function isRawCompactionSummaryInfo(info) {
|
|
148778
|
+
if (info === null || typeof info !== "object" || Array.isArray(info))
|
|
148779
|
+
return false;
|
|
148780
|
+
const candidate = info;
|
|
148781
|
+
return candidate.summary === true && candidate.finish === "stop";
|
|
148782
|
+
}
|
|
148777
148783
|
function parseJsonUnknown(value) {
|
|
148778
148784
|
try {
|
|
148779
148785
|
return JSON.parse(value);
|
|
@@ -148796,7 +148802,7 @@ function attachRawPartVersion(value, timeUpdated) {
|
|
|
148796
148802
|
return value;
|
|
148797
148803
|
}
|
|
148798
148804
|
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
148799
|
-
const messageRows = db.prepare("SELECT id, data, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
148805
|
+
const messageRows = db.prepare("SELECT id, data, time_created, time_updated FROM message WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawMessageRow);
|
|
148800
148806
|
const partRows = db.prepare("SELECT message_id, data, time_updated FROM part WHERE session_id = ? ORDER BY time_created ASC, id ASC").all(sessionId).filter(isRawPartRow);
|
|
148801
148807
|
const partsByMessageId = new Map;
|
|
148802
148808
|
for (const part of partRows) {
|
|
@@ -148804,10 +148810,7 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
148804
148810
|
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
148805
148811
|
partsByMessageId.set(part.message_id, list);
|
|
148806
148812
|
}
|
|
148807
|
-
const filtered = messageRows.filter((row) =>
|
|
148808
|
-
const info = parseJsonRecord(row.data);
|
|
148809
|
-
return !(info?.summary === true && info?.finish === "stop");
|
|
148810
|
-
});
|
|
148813
|
+
const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
|
|
148811
148814
|
return filtered.flatMap((row, index) => {
|
|
148812
148815
|
const info = parseJsonRecord(row.data);
|
|
148813
148816
|
if (!info)
|
|
@@ -148818,6 +148821,7 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
148818
148821
|
id: row.id,
|
|
148819
148822
|
role,
|
|
148820
148823
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
148824
|
+
createdAt: row.time_created ?? null,
|
|
148821
148825
|
version: row.time_updated ?? null
|
|
148822
148826
|
};
|
|
148823
148827
|
});
|
|
@@ -148832,7 +148836,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
148832
148836
|
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
148833
148837
|
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
148834
148838
|
return null;
|
|
148835
|
-
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
148839
|
+
const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
|
|
148836
148840
|
WHERE session_id = ?
|
|
148837
148841
|
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
148838
148842
|
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
@@ -148868,6 +148872,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
148868
148872
|
id: row.id,
|
|
148869
148873
|
role: typeof info.role === "string" ? info.role : "unknown",
|
|
148870
148874
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
148875
|
+
createdAt: row.time_created ?? null,
|
|
148871
148876
|
version: row.time_updated ?? null
|
|
148872
148877
|
});
|
|
148873
148878
|
ord += 1;
|
|
@@ -149630,6 +149635,7 @@ var reconciliationScheduledSessions = new Set;
|
|
|
149630
149635
|
var sessionLocks = new Map;
|
|
149631
149636
|
var incrementalTimers = new Map;
|
|
149632
149637
|
var pendingIncrementalKeys = new Set;
|
|
149638
|
+
var completedIncrementalKeys = new Set;
|
|
149633
149639
|
function defer(fn) {
|
|
149634
149640
|
const immediate = globalThis.setImmediate;
|
|
149635
149641
|
if (typeof immediate === "function") {
|
|
@@ -149697,9 +149703,9 @@ function scheduleReconciliation(db, sessionId, readMessages) {
|
|
|
149697
149703
|
});
|
|
149698
149704
|
});
|
|
149699
149705
|
}
|
|
149700
|
-
function scheduleIncrementalIndex(db, sessionId, messageId,
|
|
149706
|
+
function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
|
|
149701
149707
|
const key = `${sessionId}\x00${messageId}`;
|
|
149702
|
-
if (incrementalTimers.has(key) || pendingIncrementalKeys.has(key)) {
|
|
149708
|
+
if (completedIncrementalKeys.has(key) || incrementalTimers.has(key) || pendingIncrementalKeys.has(key)) {
|
|
149703
149709
|
return;
|
|
149704
149710
|
}
|
|
149705
149711
|
const timer = setTimeout(() => {
|
|
@@ -149707,12 +149713,12 @@ function scheduleIncrementalIndex(db, sessionId, messageId, readSingleMessage) {
|
|
|
149707
149713
|
pendingIncrementalKeys.add(key);
|
|
149708
149714
|
let attemptedOrdinal = null;
|
|
149709
149715
|
runWithSessionLock(sessionId, () => {
|
|
149710
|
-
const message =
|
|
149711
|
-
if (!message)
|
|
149716
|
+
const message = typeof messageSource === "function" ? messageSource(sessionId, messageId) : messageSource;
|
|
149717
|
+
if (!message)
|
|
149712
149718
|
return;
|
|
149713
|
-
}
|
|
149714
149719
|
attemptedOrdinal = message.ordinal;
|
|
149715
149720
|
indexSingleMessage(db, sessionId, message);
|
|
149721
|
+
completedIncrementalKeys.add(key);
|
|
149716
149722
|
}).catch((error) => {
|
|
149717
149723
|
markMessageIndexDirty(db, sessionId, attemptedOrdinal ?? getLastIndexedOrdinal(db, sessionId) + 1);
|
|
149718
149724
|
reconciledSessions.delete(sessionId);
|
|
@@ -149739,6 +149745,10 @@ function clearSessionTracking(sessionId) {
|
|
|
149739
149745
|
pendingIncrementalKeys.delete(key);
|
|
149740
149746
|
}
|
|
149741
149747
|
}
|
|
149748
|
+
for (const key of completedIncrementalKeys) {
|
|
149749
|
+
if (key.startsWith(prefix))
|
|
149750
|
+
completedIncrementalKeys.delete(key);
|
|
149751
|
+
}
|
|
149742
149752
|
}
|
|
149743
149753
|
|
|
149744
149754
|
// ../plugin/src/features/magic-context/overflow-detection.ts
|
|
@@ -152561,6 +152571,160 @@ function readProjectDocsCanonical(projectDirectory) {
|
|
|
152561
152571
|
});
|
|
152562
152572
|
return { renderedBlock, canonicalHash };
|
|
152563
152573
|
}
|
|
152574
|
+
// ../plugin/src/features/magic-context/storage-clone.ts
|
|
152575
|
+
function runImmediate(db, body) {
|
|
152576
|
+
db.exec("BEGIN IMMEDIATE");
|
|
152577
|
+
let committed = false;
|
|
152578
|
+
try {
|
|
152579
|
+
const result = body();
|
|
152580
|
+
db.exec("COMMIT");
|
|
152581
|
+
committed = true;
|
|
152582
|
+
return result;
|
|
152583
|
+
} finally {
|
|
152584
|
+
if (!committed) {
|
|
152585
|
+
try {
|
|
152586
|
+
db.exec("ROLLBACK");
|
|
152587
|
+
} catch {}
|
|
152588
|
+
}
|
|
152589
|
+
}
|
|
152590
|
+
}
|
|
152591
|
+
function countRows(db, table, sessionId) {
|
|
152592
|
+
const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
|
|
152593
|
+
return typeof row?.count === "number" ? row.count : 0;
|
|
152594
|
+
}
|
|
152595
|
+
function filterIdBlob(raw, includeMessageId) {
|
|
152596
|
+
if (!raw)
|
|
152597
|
+
return "";
|
|
152598
|
+
try {
|
|
152599
|
+
const value = JSON.parse(raw);
|
|
152600
|
+
if (!Array.isArray(value))
|
|
152601
|
+
return "";
|
|
152602
|
+
const filtered = value.filter((id) => typeof id === "string" && includeMessageId(id));
|
|
152603
|
+
return filtered.length > 0 ? JSON.stringify(filtered) : "";
|
|
152604
|
+
} catch {
|
|
152605
|
+
return "";
|
|
152606
|
+
}
|
|
152607
|
+
}
|
|
152608
|
+
function clampWatermark(value, maxCopiedTag) {
|
|
152609
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
152610
|
+
return 0;
|
|
152611
|
+
return Math.min(Math.floor(value), maxCopiedTag);
|
|
152612
|
+
}
|
|
152613
|
+
function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
|
|
152614
|
+
return runImmediate(db, () => {
|
|
152615
|
+
if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0) {
|
|
152616
|
+
return {
|
|
152617
|
+
kind: "destination-not-empty",
|
|
152618
|
+
compartmentsCopied: 0,
|
|
152619
|
+
tagsCopied: 0,
|
|
152620
|
+
pendingOpsCopied: 0,
|
|
152621
|
+
pendingMarkerMigrated: false
|
|
152622
|
+
};
|
|
152623
|
+
}
|
|
152624
|
+
const sourceCompartments = db.prepare(`SELECT sequence, start_message, end_message, start_message_id, end_message_id,
|
|
152625
|
+
title, content, p1, p2, p3, p4, importance, episode_type, legacy,
|
|
152626
|
+
created_at, harness
|
|
152627
|
+
FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sourceSessionId);
|
|
152628
|
+
const insertCompartment = db.prepare(`INSERT INTO compartments
|
|
152629
|
+
(session_id, sequence, start_message, end_message, start_message_id,
|
|
152630
|
+
end_message_id, title, content, p1, p2, p3, p4, importance,
|
|
152631
|
+
episode_type, legacy, created_at, harness)
|
|
152632
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
152633
|
+
const copiedCompartments = [];
|
|
152634
|
+
for (const row of sourceCompartments) {
|
|
152635
|
+
const startMessage = filter.resolveBoundaryOrdinal(row.start_message_id);
|
|
152636
|
+
const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
|
|
152637
|
+
if (startMessage === undefined || endMessage === undefined)
|
|
152638
|
+
continue;
|
|
152639
|
+
insertCompartment.run(destinationSessionId, row.sequence, startMessage, endMessage, row.start_message_id, row.end_message_id, row.title, row.content, row.p1, row.p2, row.p3, row.p4, row.importance, row.episode_type, row.legacy, row.created_at, row.harness);
|
|
152640
|
+
copiedCompartments.push({
|
|
152641
|
+
sequence: row.sequence,
|
|
152642
|
+
startMessage,
|
|
152643
|
+
endMessage,
|
|
152644
|
+
startMessageId: row.start_message_id,
|
|
152645
|
+
endMessageId: row.end_message_id
|
|
152646
|
+
});
|
|
152647
|
+
}
|
|
152648
|
+
const sourceTags = db.prepare(`SELECT message_id, type, status, byte_size, tag_number, harness,
|
|
152649
|
+
entry_fingerprint, token_count, input_token_count,
|
|
152650
|
+
reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
|
|
152651
|
+
input_byte_size, caveman_depth, tool_owner_message_id
|
|
152652
|
+
FROM tags WHERE session_id = ? ORDER BY tag_number ASC`).all(sourceSessionId);
|
|
152653
|
+
const insertTag = db.prepare(`INSERT INTO tags
|
|
152654
|
+
(session_id, message_id, type, status, byte_size, tag_number, harness,
|
|
152655
|
+
entry_fingerprint, token_count, input_token_count, reasoning_token_count,
|
|
152656
|
+
reasoning_byte_size, drop_mode, tool_name, input_byte_size,
|
|
152657
|
+
caveman_depth, tool_owner_message_id)
|
|
152658
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
152659
|
+
const copiedTagNumbers = [];
|
|
152660
|
+
for (const row of sourceTags) {
|
|
152661
|
+
if (!filter.includeTag({
|
|
152662
|
+
messageId: row.message_id,
|
|
152663
|
+
type: row.type,
|
|
152664
|
+
tagNumber: row.tag_number,
|
|
152665
|
+
toolOwnerMessageId: row.tool_owner_message_id
|
|
152666
|
+
})) {
|
|
152667
|
+
continue;
|
|
152668
|
+
}
|
|
152669
|
+
insertTag.run(destinationSessionId, row.message_id, row.type, row.status, row.byte_size, row.tag_number, row.harness, row.entry_fingerprint, row.token_count, row.input_token_count, row.reasoning_token_count, row.reasoning_byte_size, row.drop_mode, row.tool_name, row.input_byte_size, row.caveman_depth, row.tool_owner_message_id);
|
|
152670
|
+
copiedTagNumbers.push(row.tag_number);
|
|
152671
|
+
}
|
|
152672
|
+
if (copiedTagNumbers.length > 0) {
|
|
152673
|
+
const placeholders2 = copiedTagNumbers.map(() => "?").join(", ");
|
|
152674
|
+
db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
|
|
152675
|
+
SELECT tag_id, ?, content, created_at, harness
|
|
152676
|
+
FROM source_contents
|
|
152677
|
+
WHERE session_id = ? AND tag_id IN (${placeholders2})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
152678
|
+
db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
|
|
152679
|
+
SELECT ?, tag_id, operation, queued_at, harness
|
|
152680
|
+
FROM pending_ops
|
|
152681
|
+
WHERE session_id = ? AND tag_id IN (${placeholders2})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
152682
|
+
}
|
|
152683
|
+
const meta = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
|
|
152684
|
+
pi_stable_id_scheme, stripped_placeholder_ids,
|
|
152685
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
152686
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
152687
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
152688
|
+
todo_synthetic_state_json
|
|
152689
|
+
FROM session_meta WHERE session_id = ?`).get(sourceSessionId);
|
|
152690
|
+
const maxCopiedTag = copiedTagNumbers.reduce((max, value) => Math.max(max, value), 0);
|
|
152691
|
+
const pendingMarker = filter.selectPendingPiMarker(meta?.pending_pi_compaction_marker_state ?? null, copiedCompartments);
|
|
152692
|
+
const todoAnchor = meta?.todo_synthetic_anchor_message_id ?? "";
|
|
152693
|
+
const migrateTodo = todoAnchor.length > 0 && filter.includeMessageId(todoAnchor);
|
|
152694
|
+
db.prepare(`INSERT INTO session_meta
|
|
152695
|
+
(session_id, harness, counter, cleared_reasoning_through_tag,
|
|
152696
|
+
tool_reclaim_watermark, pi_stable_id_scheme, stripped_placeholder_ids,
|
|
152697
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
152698
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
152699
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
152700
|
+
todo_synthetic_state_json)
|
|
152701
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
152702
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
152703
|
+
harness = excluded.harness,
|
|
152704
|
+
counter = excluded.counter,
|
|
152705
|
+
cleared_reasoning_through_tag = excluded.cleared_reasoning_through_tag,
|
|
152706
|
+
tool_reclaim_watermark = excluded.tool_reclaim_watermark,
|
|
152707
|
+
pi_stable_id_scheme = excluded.pi_stable_id_scheme,
|
|
152708
|
+
stripped_placeholder_ids = excluded.stripped_placeholder_ids,
|
|
152709
|
+
stale_reduce_stripped_ids = excluded.stale_reduce_stripped_ids,
|
|
152710
|
+
processed_image_stripped_ids = excluded.processed_image_stripped_ids,
|
|
152711
|
+
pending_pi_compaction_marker_state = excluded.pending_pi_compaction_marker_state,
|
|
152712
|
+
last_todo_state = excluded.last_todo_state,
|
|
152713
|
+
todo_synthetic_call_id = excluded.todo_synthetic_call_id,
|
|
152714
|
+
todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
|
|
152715
|
+
todo_synthetic_state_json = excluded.todo_synthetic_state_json,
|
|
152716
|
+
cached_m0_bytes = NULL,
|
|
152717
|
+
cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta?.pi_stable_id_scheme === "number" && Number.isFinite(meta.pi_stable_id_scheme) ? meta.pi_stable_id_scheme : null, filterIdBlob(meta?.stripped_placeholder_ids ?? null, filter.includeMessageId), filterIdBlob(meta?.stale_reduce_stripped_ids ?? null, filter.includeMessageId), filterIdBlob(meta?.processed_image_stripped_ids ?? null, filter.includeMessageId), pendingMarker, migrateTodo ? meta?.last_todo_state ?? "" : "", migrateTodo ? meta?.todo_synthetic_call_id ?? "" : "", migrateTodo ? todoAnchor : "", migrateTodo ? meta?.todo_synthetic_state_json ?? "" : "");
|
|
152718
|
+
const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
|
|
152719
|
+
return {
|
|
152720
|
+
kind: "migrated",
|
|
152721
|
+
compartmentsCopied: copiedCompartments.length,
|
|
152722
|
+
tagsCopied: copiedTagNumbers.length,
|
|
152723
|
+
pendingOpsCopied: typeof pendingOpsRow?.count === "number" ? pendingOpsRow.count : 0,
|
|
152724
|
+
pendingMarkerMigrated: pendingMarker !== null
|
|
152725
|
+
};
|
|
152726
|
+
});
|
|
152727
|
+
}
|
|
152564
152728
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
152565
152729
|
import { chmodSync, copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
|
|
152566
152730
|
init_data_path();
|
|
@@ -155070,6 +155234,36 @@ function parseStrippedBlob(raw) {
|
|
|
155070
155234
|
} catch {}
|
|
155071
155235
|
return [];
|
|
155072
155236
|
}
|
|
155237
|
+
function getProcessedImageStrippedIds(db, sessionId) {
|
|
155238
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
155239
|
+
return new Set(parseStrippedBlob(row?.processed_image_stripped_ids));
|
|
155240
|
+
}
|
|
155241
|
+
function addProcessedImageStrippedIds(db, sessionId, ids) {
|
|
155242
|
+
const add = [...ids];
|
|
155243
|
+
if (add.length === 0)
|
|
155244
|
+
return true;
|
|
155245
|
+
ensureSessionMetaRow(db, sessionId);
|
|
155246
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
155247
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
155248
|
+
const rawStored = row ? row.processed_image_stripped_ids ?? null : null;
|
|
155249
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
155250
|
+
let changed = false;
|
|
155251
|
+
for (const id of add) {
|
|
155252
|
+
if (!current.has(id)) {
|
|
155253
|
+
current.add(id);
|
|
155254
|
+
changed = true;
|
|
155255
|
+
}
|
|
155256
|
+
}
|
|
155257
|
+
if (!changed)
|
|
155258
|
+
return true;
|
|
155259
|
+
const nextBlob = JSON.stringify([...current]);
|
|
155260
|
+
const result = db.prepare("UPDATE session_meta SET processed_image_stripped_ids = ? WHERE session_id = ? AND processed_image_stripped_ids IS ?").run(nextBlob, sessionId, rawStored);
|
|
155261
|
+
if (result.changes > 0)
|
|
155262
|
+
return true;
|
|
155263
|
+
}
|
|
155264
|
+
sessionLog(sessionId, `processed_image_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
155265
|
+
return false;
|
|
155266
|
+
}
|
|
155073
155267
|
function isPendingCompactionMarker(value) {
|
|
155074
155268
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
155075
155269
|
}
|
|
@@ -155792,6 +155986,7 @@ var getTagNumbersByMessageIdStatements = new WeakMap;
|
|
|
155792
155986
|
var deleteTagsByMessageIdStatements = new WeakMap;
|
|
155793
155987
|
var getMaxTagNumberBySessionStatements = new WeakMap;
|
|
155794
155988
|
var getTagNumberByMessageIdStatements = new WeakMap;
|
|
155989
|
+
var hasPiFallbackMessageTagStatements = new WeakMap;
|
|
155795
155990
|
function getInsertTagStatement(db) {
|
|
155796
155991
|
let stmt = insertTagStatements.get(db);
|
|
155797
155992
|
if (!stmt) {
|
|
@@ -155935,6 +156130,18 @@ function getUpdateTagInputTokenCountStatement(db) {
|
|
|
155935
156130
|
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
155936
156131
|
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
155937
156132
|
}
|
|
156133
|
+
function getPersistedToolTagAccounting(db, sessionId, tagNumber) {
|
|
156134
|
+
const row = db.prepare(`SELECT byte_size AS byteSize,
|
|
156135
|
+
token_count AS tokenCount,
|
|
156136
|
+
input_byte_size AS inputByteSize,
|
|
156137
|
+
input_token_count AS inputTokenCount
|
|
156138
|
+
FROM tags
|
|
156139
|
+
WHERE session_id = ? AND tag_number = ? AND type = 'tool'`).get(sessionId, tagNumber);
|
|
156140
|
+
if (!row || typeof row.byteSize !== "number" || row.tokenCount !== null && typeof row.tokenCount !== "number" || typeof row.inputByteSize !== "number" || row.inputTokenCount !== null && typeof row.inputTokenCount !== "number") {
|
|
156141
|
+
return null;
|
|
156142
|
+
}
|
|
156143
|
+
return row;
|
|
156144
|
+
}
|
|
155938
156145
|
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
|
|
155939
156146
|
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
155940
156147
|
FROM tags
|
|
@@ -156036,6 +156243,19 @@ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
|
156036
156243
|
function updateCavemanDepth(db, sessionId, tagNumber, depth) {
|
|
156037
156244
|
db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
|
|
156038
156245
|
}
|
|
156246
|
+
function hasPiFallbackMessageTags(db, sessionId) {
|
|
156247
|
+
let statement = hasPiFallbackMessageTagStatements.get(db);
|
|
156248
|
+
if (!statement) {
|
|
156249
|
+
statement = db.prepare(`SELECT 1
|
|
156250
|
+
FROM tags
|
|
156251
|
+
WHERE session_id = ?
|
|
156252
|
+
AND type = 'message'
|
|
156253
|
+
AND message_id LIKE 'pi-msg-%'
|
|
156254
|
+
LIMIT 1`);
|
|
156255
|
+
hasPiFallbackMessageTagStatements.set(db, statement);
|
|
156256
|
+
}
|
|
156257
|
+
return statement.get(sessionId) != null;
|
|
156258
|
+
}
|
|
156039
156259
|
function findAdoptableFallbackTags(db, sessionId, entryFingerprint) {
|
|
156040
156260
|
const rows = db.prepare(`SELECT tag_number AS tagNumber, message_id AS messageId
|
|
156041
156261
|
FROM tags
|
|
@@ -156206,27 +156426,24 @@ function adoptPiFallbackToolOwnerTag(db, sessionId, tagNumber, callId, oldOwnerM
|
|
|
156206
156426
|
}
|
|
156207
156427
|
const existing = getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, newOwnerMessageId);
|
|
156208
156428
|
if (existing === null) {
|
|
156209
|
-
const
|
|
156429
|
+
const result = db.prepare(`UPDATE tags
|
|
156210
156430
|
SET tool_owner_message_id = ?
|
|
156211
156431
|
WHERE session_id = ?
|
|
156212
156432
|
AND tag_number = ?
|
|
156213
156433
|
AND type = 'tool'
|
|
156214
156434
|
AND message_id = ?
|
|
156215
156435
|
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
156216
|
-
return (
|
|
156436
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
156217
156437
|
}
|
|
156218
156438
|
if (existing.tagNumber === tagNumber) {
|
|
156219
156439
|
return { action: "skipped" };
|
|
156220
156440
|
}
|
|
156221
|
-
foldDuplicateIntoSurvivor(db, sessionId,
|
|
156222
|
-
|
|
156223
|
-
|
|
156224
|
-
|
|
156225
|
-
|
|
156226
|
-
|
|
156227
|
-
AND message_id = ?
|
|
156228
|
-
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
156229
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers: [existing.tagNumber] } : { action: "skipped" };
|
|
156441
|
+
foldDuplicateIntoSurvivor(db, sessionId, existing, survivor);
|
|
156442
|
+
return {
|
|
156443
|
+
action: "folded",
|
|
156444
|
+
tagNumber: existing.tagNumber,
|
|
156445
|
+
deletedTagNumbers: [tagNumber]
|
|
156446
|
+
};
|
|
156230
156447
|
}
|
|
156231
156448
|
function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId) {
|
|
156232
156449
|
const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
|
|
@@ -156235,26 +156452,28 @@ function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageI
|
|
|
156235
156452
|
}
|
|
156236
156453
|
const duplicates = getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, newRealMessageId).filter((row) => row.tagNumber !== tagNumber);
|
|
156237
156454
|
if (duplicates.length === 0) {
|
|
156238
|
-
const
|
|
156455
|
+
const result = db.prepare(`UPDATE tags
|
|
156239
156456
|
SET message_id = ?
|
|
156240
156457
|
WHERE session_id = ?
|
|
156241
156458
|
AND tag_number = ?
|
|
156242
156459
|
AND type = 'message'
|
|
156243
156460
|
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
156244
|
-
return (
|
|
156461
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
156245
156462
|
}
|
|
156246
|
-
const
|
|
156247
|
-
|
|
156248
|
-
|
|
156463
|
+
const realSurvivor = duplicates[0];
|
|
156464
|
+
if (!realSurvivor)
|
|
156465
|
+
return { action: "skipped" };
|
|
156466
|
+
const deletedTagNumbers = [tagNumber];
|
|
156467
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, survivor);
|
|
156468
|
+
for (const duplicate of duplicates.slice(1)) {
|
|
156469
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, duplicate);
|
|
156249
156470
|
deletedTagNumbers.push(duplicate.tagNumber);
|
|
156250
156471
|
}
|
|
156251
|
-
|
|
156252
|
-
|
|
156253
|
-
|
|
156254
|
-
|
|
156255
|
-
|
|
156256
|
-
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
156257
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers } : { action: "skipped" };
|
|
156472
|
+
return {
|
|
156473
|
+
action: "folded",
|
|
156474
|
+
tagNumber: realSurvivor.tagNumber,
|
|
156475
|
+
deletedTagNumbers
|
|
156476
|
+
};
|
|
156258
156477
|
}
|
|
156259
156478
|
var getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
156260
156479
|
function getMaxTagNumberBySession(db, sessionId) {
|
|
@@ -156326,10 +156545,40 @@ function getActiveTagsBySessionStatement(db) {
|
|
|
156326
156545
|
}
|
|
156327
156546
|
return stmt;
|
|
156328
156547
|
}
|
|
156548
|
+
function getMaxDroppedTagNumberStatement(db) {
|
|
156549
|
+
let stmt = getMaxDroppedTagNumberStatements.get(db);
|
|
156550
|
+
if (!stmt) {
|
|
156551
|
+
stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ? AND status = 'dropped'");
|
|
156552
|
+
getMaxDroppedTagNumberStatements.set(db, stmt);
|
|
156553
|
+
}
|
|
156554
|
+
return stmt;
|
|
156555
|
+
}
|
|
156329
156556
|
function getActiveTagsBySession(db, sessionId) {
|
|
156330
156557
|
const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
|
|
156331
156558
|
return rows.map(toTagEntry);
|
|
156332
156559
|
}
|
|
156560
|
+
function getTagsForPendingOperations(db, sessionId, pendingTagNumbers, protectedTags, recentToolWindow) {
|
|
156561
|
+
const byNumber = new Map;
|
|
156562
|
+
for (const tag of getTagsByNumbers(db, sessionId, pendingTagNumbers)) {
|
|
156563
|
+
byNumber.set(tag.tagNumber, tag);
|
|
156564
|
+
}
|
|
156565
|
+
const addRows = (sql, limit) => {
|
|
156566
|
+
if (limit <= 0)
|
|
156567
|
+
return;
|
|
156568
|
+
const rows = db.prepare(sql).all(sessionId, limit).filter(isTagRow);
|
|
156569
|
+
for (const row of rows) {
|
|
156570
|
+
const tag = toTagEntry(row);
|
|
156571
|
+
byNumber.set(tag.tagNumber, tag);
|
|
156572
|
+
}
|
|
156573
|
+
};
|
|
156574
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
156575
|
+
WHERE session_id = ? AND status = 'active'
|
|
156576
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, protectedTags);
|
|
156577
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
156578
|
+
WHERE session_id = ? AND type = 'tool'
|
|
156579
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, recentToolWindow);
|
|
156580
|
+
return [...byNumber.values()].sort((left, right) => left.tagNumber - right.tagNumber);
|
|
156581
|
+
}
|
|
156333
156582
|
function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
156334
156583
|
if (tagNumbers.length === 0)
|
|
156335
156584
|
return [];
|
|
@@ -156344,6 +156593,10 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
156344
156593
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders3}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
156345
156594
|
return rows.map(toTagEntry);
|
|
156346
156595
|
}
|
|
156596
|
+
function getMaxDroppedTagNumber(db, sessionId) {
|
|
156597
|
+
const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
|
|
156598
|
+
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
156599
|
+
}
|
|
156347
156600
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
156348
156601
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
156349
156602
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -157256,6 +157509,461 @@ function shouldKeepSubagents() {
|
|
|
157256
157509
|
// src/index.ts
|
|
157257
157510
|
init_logger();
|
|
157258
157511
|
|
|
157512
|
+
// src/clone-inheritance.ts
|
|
157513
|
+
import { readFile } from "node:fs/promises";
|
|
157514
|
+
init_logger();
|
|
157515
|
+
|
|
157516
|
+
// src/read-session-pi.ts
|
|
157517
|
+
var SYNTH_USER_ID_PREFIX = "synth-user-";
|
|
157518
|
+
function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
|
|
157519
|
+
if (!msg || typeof msg !== "object")
|
|
157520
|
+
return;
|
|
157521
|
+
const byRef = entryIdByRef?.get(msg);
|
|
157522
|
+
if (typeof byRef === "string" && byRef.length > 0)
|
|
157523
|
+
return byRef;
|
|
157524
|
+
const positional = entryIds?.[index];
|
|
157525
|
+
if (typeof positional === "string" && positional.length > 0)
|
|
157526
|
+
return positional;
|
|
157527
|
+
const m = msg;
|
|
157528
|
+
const role = m.role ?? "unknown";
|
|
157529
|
+
return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
|
|
157530
|
+
}
|
|
157531
|
+
function isMidTurnPi(event, _sessionId, branchEntries) {
|
|
157532
|
+
const messages = event?.messages;
|
|
157533
|
+
if (!Array.isArray(messages))
|
|
157534
|
+
return false;
|
|
157535
|
+
let latestAssistantIndex = -1;
|
|
157536
|
+
let latestAssistant = null;
|
|
157537
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
157538
|
+
const msg = messages[i];
|
|
157539
|
+
if (msg !== null && typeof msg === "object") {
|
|
157540
|
+
const record = msg;
|
|
157541
|
+
if (record.role === "assistant") {
|
|
157542
|
+
latestAssistantIndex = i;
|
|
157543
|
+
latestAssistant = record;
|
|
157544
|
+
break;
|
|
157545
|
+
}
|
|
157546
|
+
}
|
|
157547
|
+
}
|
|
157548
|
+
if (latestAssistant === null)
|
|
157549
|
+
return false;
|
|
157550
|
+
if (hasRealUserAfter(messages, latestAssistantIndex, branchEntries))
|
|
157551
|
+
return false;
|
|
157552
|
+
if (latestAssistant.stopReason === "toolUse")
|
|
157553
|
+
return true;
|
|
157554
|
+
const toolCallIds = getToolCallIds(latestAssistant.content);
|
|
157555
|
+
if (toolCallIds.size === 0)
|
|
157556
|
+
return false;
|
|
157557
|
+
const pairedToolResultIds = new Set;
|
|
157558
|
+
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
157559
|
+
if (msg === null || typeof msg !== "object")
|
|
157560
|
+
continue;
|
|
157561
|
+
const record = msg;
|
|
157562
|
+
if (record.role !== "toolResult")
|
|
157563
|
+
continue;
|
|
157564
|
+
if (typeof record.toolCallId === "string") {
|
|
157565
|
+
pairedToolResultIds.add(record.toolCallId);
|
|
157566
|
+
}
|
|
157567
|
+
}
|
|
157568
|
+
for (const id of toolCallIds) {
|
|
157569
|
+
if (!pairedToolResultIds.has(id))
|
|
157570
|
+
return true;
|
|
157571
|
+
}
|
|
157572
|
+
return false;
|
|
157573
|
+
}
|
|
157574
|
+
function hasRealUserAfter(messages, latestAssistantIndex, branchEntries) {
|
|
157575
|
+
if (!branchEntries)
|
|
157576
|
+
return false;
|
|
157577
|
+
const genuineUserMessages = new Set;
|
|
157578
|
+
for (const entry of branchEntries) {
|
|
157579
|
+
if (entry === null || typeof entry !== "object")
|
|
157580
|
+
continue;
|
|
157581
|
+
const record = entry;
|
|
157582
|
+
if (record.type !== "message")
|
|
157583
|
+
continue;
|
|
157584
|
+
const message = record.message;
|
|
157585
|
+
if (message === null || typeof message !== "object")
|
|
157586
|
+
continue;
|
|
157587
|
+
if (message.role === "user") {
|
|
157588
|
+
genuineUserMessages.add(message);
|
|
157589
|
+
}
|
|
157590
|
+
}
|
|
157591
|
+
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
157592
|
+
if (msg !== null && typeof msg === "object" && genuineUserMessages.has(msg)) {
|
|
157593
|
+
return true;
|
|
157594
|
+
}
|
|
157595
|
+
}
|
|
157596
|
+
return false;
|
|
157597
|
+
}
|
|
157598
|
+
function getToolCallIds(content) {
|
|
157599
|
+
const ids = new Set;
|
|
157600
|
+
if (!Array.isArray(content))
|
|
157601
|
+
return ids;
|
|
157602
|
+
for (const item of content) {
|
|
157603
|
+
if (item === null || typeof item !== "object")
|
|
157604
|
+
continue;
|
|
157605
|
+
const record = item;
|
|
157606
|
+
if (record.type === "toolCall" && typeof record.id === "string") {
|
|
157607
|
+
ids.add(record.id);
|
|
157608
|
+
}
|
|
157609
|
+
}
|
|
157610
|
+
return ids;
|
|
157611
|
+
}
|
|
157612
|
+
function readPiSessionMessages(ctx) {
|
|
157613
|
+
const sm = ctx.sessionManager;
|
|
157614
|
+
if (sm === undefined)
|
|
157615
|
+
return [];
|
|
157616
|
+
const getBranch = sm.getBranch;
|
|
157617
|
+
if (typeof getBranch !== "function")
|
|
157618
|
+
return [];
|
|
157619
|
+
let entries;
|
|
157620
|
+
try {
|
|
157621
|
+
entries = getBranch.call(sm);
|
|
157622
|
+
} catch {
|
|
157623
|
+
return [];
|
|
157624
|
+
}
|
|
157625
|
+
if (!Array.isArray(entries))
|
|
157626
|
+
return [];
|
|
157627
|
+
return convertEntriesToRawMessages(entries);
|
|
157628
|
+
}
|
|
157629
|
+
function findLastModelKeyFromBranch(entries) {
|
|
157630
|
+
if (!Array.isArray(entries))
|
|
157631
|
+
return;
|
|
157632
|
+
for (let i = entries.length - 1;i >= 0; i--) {
|
|
157633
|
+
const e = entries[i];
|
|
157634
|
+
if (!e || typeof e !== "object")
|
|
157635
|
+
continue;
|
|
157636
|
+
const v = e;
|
|
157637
|
+
if (v.type !== "model_change")
|
|
157638
|
+
continue;
|
|
157639
|
+
if (typeof v.provider === "string" && v.provider.length > 0 && typeof v.modelId === "string" && v.modelId.length > 0) {
|
|
157640
|
+
return `${v.provider}/${v.modelId}`;
|
|
157641
|
+
}
|
|
157642
|
+
}
|
|
157643
|
+
return;
|
|
157644
|
+
}
|
|
157645
|
+
function rawEntryVersion(entry) {
|
|
157646
|
+
const record = entry;
|
|
157647
|
+
const updated = record.updatedAt ?? record.updated_at ?? record.timestamp;
|
|
157648
|
+
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
157649
|
+
}
|
|
157650
|
+
function attachPiPartVersion(parts, version) {
|
|
157651
|
+
return parts.map((part) => {
|
|
157652
|
+
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
157653
|
+
return part;
|
|
157654
|
+
try {
|
|
157655
|
+
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
157656
|
+
value: version,
|
|
157657
|
+
enumerable: false,
|
|
157658
|
+
configurable: true
|
|
157659
|
+
});
|
|
157660
|
+
} catch {}
|
|
157661
|
+
return part;
|
|
157662
|
+
});
|
|
157663
|
+
}
|
|
157664
|
+
function convertEntriesToRawMessages(entries) {
|
|
157665
|
+
const result = [];
|
|
157666
|
+
let nextOrdinal = 1;
|
|
157667
|
+
let pendingToolParts = [];
|
|
157668
|
+
let pendingFirstRealId = "";
|
|
157669
|
+
let pendingFirstRealVersion = "";
|
|
157670
|
+
for (const entry of entries) {
|
|
157671
|
+
if (!isMessageEntry(entry)) {
|
|
157672
|
+
continue;
|
|
157673
|
+
}
|
|
157674
|
+
const msg = entry.message;
|
|
157675
|
+
const role = msg.role;
|
|
157676
|
+
if (role === "toolResult") {
|
|
157677
|
+
const version = rawEntryVersion(entry);
|
|
157678
|
+
pendingToolParts.push(...attachPiPartVersion(synthesizeToolResultParts(msg), version));
|
|
157679
|
+
if (pendingFirstRealId === "") {
|
|
157680
|
+
pendingFirstRealId = entry.id;
|
|
157681
|
+
pendingFirstRealVersion = version;
|
|
157682
|
+
}
|
|
157683
|
+
continue;
|
|
157684
|
+
}
|
|
157685
|
+
if (role === "user") {
|
|
157686
|
+
const version = rawEntryVersion(entry);
|
|
157687
|
+
const parts = [
|
|
157688
|
+
...pendingToolParts,
|
|
157689
|
+
...attachPiPartVersion(synthesizeUserParts(msg), version)
|
|
157690
|
+
];
|
|
157691
|
+
pendingToolParts = [];
|
|
157692
|
+
pendingFirstRealId = "";
|
|
157693
|
+
pendingFirstRealVersion = "";
|
|
157694
|
+
result.push({
|
|
157695
|
+
ordinal: nextOrdinal++,
|
|
157696
|
+
id: entry.id,
|
|
157697
|
+
role: "user",
|
|
157698
|
+
parts,
|
|
157699
|
+
version
|
|
157700
|
+
});
|
|
157701
|
+
continue;
|
|
157702
|
+
}
|
|
157703
|
+
if (role === "assistant") {
|
|
157704
|
+
if (pendingToolParts.length > 0) {
|
|
157705
|
+
result.push({
|
|
157706
|
+
ordinal: nextOrdinal++,
|
|
157707
|
+
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
157708
|
+
role: "user",
|
|
157709
|
+
parts: pendingToolParts,
|
|
157710
|
+
version: pendingFirstRealVersion
|
|
157711
|
+
});
|
|
157712
|
+
pendingToolParts = [];
|
|
157713
|
+
pendingFirstRealId = "";
|
|
157714
|
+
pendingFirstRealVersion = "";
|
|
157715
|
+
}
|
|
157716
|
+
const version = rawEntryVersion(entry);
|
|
157717
|
+
result.push({
|
|
157718
|
+
ordinal: nextOrdinal++,
|
|
157719
|
+
id: entry.id,
|
|
157720
|
+
role: "assistant",
|
|
157721
|
+
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version),
|
|
157722
|
+
version
|
|
157723
|
+
});
|
|
157724
|
+
continue;
|
|
157725
|
+
}
|
|
157726
|
+
result.push({
|
|
157727
|
+
ordinal: nextOrdinal++,
|
|
157728
|
+
id: entry.id,
|
|
157729
|
+
role: typeof role === "string" ? role : "unknown",
|
|
157730
|
+
parts: [],
|
|
157731
|
+
version: rawEntryVersion(entry)
|
|
157732
|
+
});
|
|
157733
|
+
}
|
|
157734
|
+
if (pendingToolParts.length > 0) {
|
|
157735
|
+
result.push({
|
|
157736
|
+
ordinal: nextOrdinal,
|
|
157737
|
+
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
157738
|
+
role: "user",
|
|
157739
|
+
parts: pendingToolParts,
|
|
157740
|
+
version: pendingFirstRealVersion
|
|
157741
|
+
});
|
|
157742
|
+
}
|
|
157743
|
+
return result;
|
|
157744
|
+
}
|
|
157745
|
+
function isMessageEntry(value) {
|
|
157746
|
+
if (value === null || typeof value !== "object")
|
|
157747
|
+
return false;
|
|
157748
|
+
const v = value;
|
|
157749
|
+
if (v.type !== "message")
|
|
157750
|
+
return false;
|
|
157751
|
+
if (typeof v.id !== "string")
|
|
157752
|
+
return false;
|
|
157753
|
+
if (v.message === null || typeof v.message !== "object")
|
|
157754
|
+
return false;
|
|
157755
|
+
return true;
|
|
157756
|
+
}
|
|
157757
|
+
function synthesizeUserParts(msg) {
|
|
157758
|
+
const m = msg;
|
|
157759
|
+
if (typeof m.content === "string") {
|
|
157760
|
+
if (m.content.trim().length === 0)
|
|
157761
|
+
return [];
|
|
157762
|
+
return [{ type: "text", text: m.content }];
|
|
157763
|
+
}
|
|
157764
|
+
if (!Array.isArray(m.content))
|
|
157765
|
+
return [];
|
|
157766
|
+
const parts = [];
|
|
157767
|
+
for (const c of m.content) {
|
|
157768
|
+
if (c === null || typeof c !== "object")
|
|
157769
|
+
continue;
|
|
157770
|
+
const cc = c;
|
|
157771
|
+
if (cc.type === "text" && typeof cc.text === "string") {
|
|
157772
|
+
parts.push({ type: "text", text: cc.text });
|
|
157773
|
+
}
|
|
157774
|
+
}
|
|
157775
|
+
return parts;
|
|
157776
|
+
}
|
|
157777
|
+
function synthesizeAssistantParts(msg) {
|
|
157778
|
+
const m = msg;
|
|
157779
|
+
if (!Array.isArray(m.content))
|
|
157780
|
+
return [];
|
|
157781
|
+
const parts = [];
|
|
157782
|
+
for (const c of m.content) {
|
|
157783
|
+
if (c === null || typeof c !== "object")
|
|
157784
|
+
continue;
|
|
157785
|
+
const cc = c;
|
|
157786
|
+
if (cc.type === "text" && typeof cc.text === "string") {
|
|
157787
|
+
parts.push({ type: "text", text: cc.text });
|
|
157788
|
+
} else if (cc.type === "toolCall" && typeof cc.id === "string") {
|
|
157789
|
+
parts.push({
|
|
157790
|
+
type: "tool",
|
|
157791
|
+
tool: typeof cc.name === "string" ? cc.name : "unknown",
|
|
157792
|
+
callID: cc.id,
|
|
157793
|
+
state: {
|
|
157794
|
+
input: cc.arguments ?? {}
|
|
157795
|
+
}
|
|
157796
|
+
});
|
|
157797
|
+
}
|
|
157798
|
+
}
|
|
157799
|
+
return parts;
|
|
157800
|
+
}
|
|
157801
|
+
function synthesizeToolResultParts(msg) {
|
|
157802
|
+
const m = msg;
|
|
157803
|
+
const callID = typeof m.toolCallId === "string" ? m.toolCallId : "";
|
|
157804
|
+
const tool = typeof m.toolName === "string" ? m.toolName : "unknown";
|
|
157805
|
+
if (!callID)
|
|
157806
|
+
return [];
|
|
157807
|
+
let output = "";
|
|
157808
|
+
if (Array.isArray(m.content)) {
|
|
157809
|
+
const fragments = [];
|
|
157810
|
+
for (const c of m.content) {
|
|
157811
|
+
if (c === null || typeof c !== "object")
|
|
157812
|
+
continue;
|
|
157813
|
+
const cc = c;
|
|
157814
|
+
if (cc.type === "text" && typeof cc.text === "string") {
|
|
157815
|
+
fragments.push(cc.text);
|
|
157816
|
+
}
|
|
157817
|
+
}
|
|
157818
|
+
output = fragments.join(`
|
|
157819
|
+
`);
|
|
157820
|
+
}
|
|
157821
|
+
return [
|
|
157822
|
+
{
|
|
157823
|
+
type: "tool",
|
|
157824
|
+
tool,
|
|
157825
|
+
callID,
|
|
157826
|
+
state: {
|
|
157827
|
+
output
|
|
157828
|
+
}
|
|
157829
|
+
}
|
|
157830
|
+
];
|
|
157831
|
+
}
|
|
157832
|
+
|
|
157833
|
+
// src/clone-inheritance.ts
|
|
157834
|
+
var CONTENT_ID_SUFFIX2 = /:(?:p|file)\d+$/;
|
|
157835
|
+
function entryId(entry) {
|
|
157836
|
+
if (entry === null || typeof entry !== "object")
|
|
157837
|
+
return null;
|
|
157838
|
+
const id = entry.id;
|
|
157839
|
+
return typeof id === "string" && id.length > 0 ? id : null;
|
|
157840
|
+
}
|
|
157841
|
+
function branchPosition(entries, id) {
|
|
157842
|
+
return entries.findIndex((entry) => entryId(entry) === id);
|
|
157843
|
+
}
|
|
157844
|
+
function latestCompactionFirstKept(entries) {
|
|
157845
|
+
for (let index = entries.length - 1;index >= 0; index--) {
|
|
157846
|
+
const entry = entries[index];
|
|
157847
|
+
if (entry === null || typeof entry !== "object")
|
|
157848
|
+
continue;
|
|
157849
|
+
const value = entry;
|
|
157850
|
+
if (value.type === "compaction" && typeof value.firstKeptEntryId === "string" && value.firstKeptEntryId.length > 0) {
|
|
157851
|
+
return value.firstKeptEntryId;
|
|
157852
|
+
}
|
|
157853
|
+
}
|
|
157854
|
+
return null;
|
|
157855
|
+
}
|
|
157856
|
+
function parsePendingMarker(raw) {
|
|
157857
|
+
if (!raw)
|
|
157858
|
+
return null;
|
|
157859
|
+
try {
|
|
157860
|
+
const value = JSON.parse(raw);
|
|
157861
|
+
if (typeof value.firstKeptEntryId === "string" && typeof value.endMessageId === "string" && typeof value.ordinal === "number" && Number.isFinite(value.ordinal) && typeof value.tokensBefore === "number" && Number.isFinite(value.tokensBefore) && typeof value.summary === "string" && typeof value.publishedAt === "number" && Number.isFinite(value.publishedAt)) {
|
|
157862
|
+
return value;
|
|
157863
|
+
}
|
|
157864
|
+
} catch {
|
|
157865
|
+
return null;
|
|
157866
|
+
}
|
|
157867
|
+
return null;
|
|
157868
|
+
}
|
|
157869
|
+
function createCloneFilter(entries) {
|
|
157870
|
+
const rawMessages = convertEntriesToRawMessages([...entries]);
|
|
157871
|
+
const rawOrdinalById = new Map(rawMessages.map((message) => [message.id, message.ordinal]));
|
|
157872
|
+
const validStateIds = new Set(rawOrdinalById.keys());
|
|
157873
|
+
for (const entry of entries) {
|
|
157874
|
+
const id = entryId(entry);
|
|
157875
|
+
if (id)
|
|
157876
|
+
validStateIds.add(id);
|
|
157877
|
+
}
|
|
157878
|
+
const includeMessageId = (id) => validStateIds.has(id);
|
|
157879
|
+
return {
|
|
157880
|
+
resolveBoundaryOrdinal: (id) => rawOrdinalById.get(id),
|
|
157881
|
+
includeMessageId,
|
|
157882
|
+
includeTag: (tag) => {
|
|
157883
|
+
if (tag.type === "tool") {
|
|
157884
|
+
return typeof tag.toolOwnerMessageId === "string" && includeMessageId(tag.toolOwnerMessageId);
|
|
157885
|
+
}
|
|
157886
|
+
return rawOrdinalById.has(tag.messageId.replace(CONTENT_ID_SUFFIX2, ""));
|
|
157887
|
+
},
|
|
157888
|
+
selectPendingPiMarker: (rawState, copiedCompartments) => {
|
|
157889
|
+
const pending = parsePendingMarker(rawState);
|
|
157890
|
+
if (!pending)
|
|
157891
|
+
return null;
|
|
157892
|
+
const pendingFirstKeptPosition = branchPosition(entries, pending.firstKeptEntryId);
|
|
157893
|
+
if (pendingFirstKeptPosition < 0)
|
|
157894
|
+
return null;
|
|
157895
|
+
const mappedOrdinal = rawOrdinalById.get(pending.endMessageId);
|
|
157896
|
+
if (mappedOrdinal === undefined)
|
|
157897
|
+
return null;
|
|
157898
|
+
const matchingCompartment = copiedCompartments.find((compartment) => compartment.endMessageId === pending.endMessageId && compartment.endMessage === mappedOrdinal);
|
|
157899
|
+
if (!matchingCompartment)
|
|
157900
|
+
return null;
|
|
157901
|
+
const currentFirstKept = latestCompactionFirstKept(entries);
|
|
157902
|
+
if (currentFirstKept !== null) {
|
|
157903
|
+
const currentPosition = branchPosition(entries, currentFirstKept);
|
|
157904
|
+
if (currentPosition >= pendingFirstKeptPosition)
|
|
157905
|
+
return null;
|
|
157906
|
+
}
|
|
157907
|
+
return JSON.stringify({ ...pending, ordinal: mappedOrdinal });
|
|
157908
|
+
}
|
|
157909
|
+
};
|
|
157910
|
+
}
|
|
157911
|
+
async function readPiSessionIdFromFile(filePath) {
|
|
157912
|
+
const contents = await readFile(filePath, "utf8");
|
|
157913
|
+
const newline = contents.indexOf(`
|
|
157914
|
+
`);
|
|
157915
|
+
const headerText = newline >= 0 ? contents.slice(0, newline) : contents;
|
|
157916
|
+
const header = JSON.parse(headerText);
|
|
157917
|
+
if (header.type !== "session" || typeof header.id !== "string" || header.id.length === 0) {
|
|
157918
|
+
throw new Error("previous session file has no valid session header");
|
|
157919
|
+
}
|
|
157920
|
+
return header.id;
|
|
157921
|
+
}
|
|
157922
|
+
async function handlePiCloneSessionStart(event, ctx, deps) {
|
|
157923
|
+
if (event.reason !== "fork" || typeof event.previousSessionFile !== "string") {
|
|
157924
|
+
return null;
|
|
157925
|
+
}
|
|
157926
|
+
let stage = "resolve-destination";
|
|
157927
|
+
let sourceSessionId = "unknown";
|
|
157928
|
+
let destinationSessionId = "unknown";
|
|
157929
|
+
const writeLog = deps.writeLog ?? log;
|
|
157930
|
+
try {
|
|
157931
|
+
const manager = ctx.sessionManager;
|
|
157932
|
+
if (typeof manager?.getSessionId !== "function") {
|
|
157933
|
+
throw new Error("Pi session manager does not expose getSessionId");
|
|
157934
|
+
}
|
|
157935
|
+
destinationSessionId = manager.getSessionId() ?? "";
|
|
157936
|
+
if (destinationSessionId.length === 0) {
|
|
157937
|
+
throw new Error("Pi clone session id is empty");
|
|
157938
|
+
}
|
|
157939
|
+
stage = "read-source-header";
|
|
157940
|
+
sourceSessionId = await readPiSessionIdFromFile(event.previousSessionFile);
|
|
157941
|
+
stage = "read-clone-branch";
|
|
157942
|
+
if (typeof manager.getBranch !== "function") {
|
|
157943
|
+
throw new Error("Pi session manager does not expose getBranch");
|
|
157944
|
+
}
|
|
157945
|
+
const branchEntries = manager.getBranch();
|
|
157946
|
+
if (!Array.isArray(branchEntries)) {
|
|
157947
|
+
throw new Error("Pi clone branch is unavailable");
|
|
157948
|
+
}
|
|
157949
|
+
stage = "copy-state";
|
|
157950
|
+
const result = copySessionStateForClone(deps.db, sourceSessionId, destinationSessionId, createCloneFilter(branchEntries));
|
|
157951
|
+
if (result.kind === "destination-not-empty") {
|
|
157952
|
+
writeLog(`[magic-context][pi] clone-inheritance: skipped source=${sourceSessionId} dest=${destinationSessionId} stage=destination-guard reason=destination-not-empty`);
|
|
157953
|
+
return result;
|
|
157954
|
+
}
|
|
157955
|
+
stage = "signal-marker";
|
|
157956
|
+
if (result.pendingMarkerMigrated) {
|
|
157957
|
+
deps.signalPendingMarker(destinationSessionId);
|
|
157958
|
+
}
|
|
157959
|
+
writeLog(`[magic-context][pi] clone-inheritance: migrated compartments=${result.compartmentsCopied} tags=${result.tagsCopied} source=${sourceSessionId} dest=${destinationSessionId} reason=fork`);
|
|
157960
|
+
return result;
|
|
157961
|
+
} catch (error) {
|
|
157962
|
+
writeLog(`[magic-context][pi] clone-inheritance: failed source=${sourceSessionId} dest=${destinationSessionId} stage=${stage} error=${error instanceof Error ? error.message : String(error)}; run /ctx-wrapup to rebuild, or re-clone`);
|
|
157963
|
+
return null;
|
|
157964
|
+
}
|
|
157965
|
+
}
|
|
157966
|
+
|
|
157259
157967
|
// ../plugin/src/agents/language-directive.ts
|
|
157260
157968
|
var ENGLISH_LANGUAGE_NAMES = new Intl.DisplayNames(["en"], {
|
|
157261
157969
|
type: "language",
|
|
@@ -157588,18 +158296,48 @@ function inferAccountingSubagent(agent) {
|
|
|
157588
158296
|
return "recomp";
|
|
157589
158297
|
return "historian";
|
|
157590
158298
|
}
|
|
158299
|
+
var ALREADY_PROCESSING_PREFIX = "Agent is already processing";
|
|
158300
|
+
var ISOLATED_RETRY_MODEL_UNAVAILABLE_MESSAGE = "model unavailable in isolated retry: it is provided by a disabled extension; configure it through models.json or add a built-in/provider-configured fallback";
|
|
158301
|
+
var MODEL_RESOLUTION_ERROR_PATTERNS = [
|
|
158302
|
+
/unknown model/i,
|
|
158303
|
+
/unknown provider/i,
|
|
158304
|
+
/model.+not found/i,
|
|
158305
|
+
/provider.+not found/i,
|
|
158306
|
+
/could not resolve model/i,
|
|
158307
|
+
/no models? (matched|available|configured)/i,
|
|
158308
|
+
/model.+not configured/i
|
|
158309
|
+
];
|
|
157591
158310
|
|
|
157592
158311
|
class PiSubagentRunner {
|
|
157593
158312
|
harness = "pi";
|
|
157594
158313
|
invocation;
|
|
157595
158314
|
spawnImpl;
|
|
157596
158315
|
platform;
|
|
158316
|
+
extraArgs;
|
|
157597
158317
|
constructor(options = {}) {
|
|
157598
158318
|
this.invocation = options.piBinary ? { command: options.piBinary, prefixArgs: [] } : resolvePiInvocation();
|
|
157599
158319
|
this.spawnImpl = options.spawnImpl ?? childProcess.spawn;
|
|
157600
158320
|
this.platform = options.platform ?? process.platform;
|
|
158321
|
+
this.extraArgs = options.extraArgs ?? [];
|
|
157601
158322
|
}
|
|
157602
158323
|
async run(options) {
|
|
158324
|
+
const primaryRunMode = { disableDiscoveredExtensions: false };
|
|
158325
|
+
const primaryResult = await this.runModelChain(options, primaryRunMode);
|
|
158326
|
+
if (this.spawnUsesNoExtensions(primaryRunMode) || !isPiExtensionCollisionFailure(primaryResult)) {
|
|
158327
|
+
return primaryResult;
|
|
158328
|
+
}
|
|
158329
|
+
const sessionId = options.accountingSessionId ?? "pi-subagent";
|
|
158330
|
+
sessionLog(sessionId, "pi subagent: a loaded Pi extension started an agent turn before the child's prompt could run; retrying with an isolated extension set (user extensions disabled for this run)");
|
|
158331
|
+
const isolatedResult = await this.runModelChain(options, {
|
|
158332
|
+
disableDiscoveredExtensions: true
|
|
158333
|
+
});
|
|
158334
|
+
if (!isolatedResult.ok && isIsolatedRetryModelUnavailable(isolatedResult)) {
|
|
158335
|
+
sessionLog(sessionId, ISOLATED_RETRY_MODEL_UNAVAILABLE_MESSAGE);
|
|
158336
|
+
return annotateIsolatedRetryModelUnavailable(isolatedResult);
|
|
158337
|
+
}
|
|
158338
|
+
return isolatedResult;
|
|
158339
|
+
}
|
|
158340
|
+
async runModelChain(options, runMode) {
|
|
157603
158341
|
const models = [options.model, ...options.fallbackModels ?? []].filter((model) => typeof model === "string" && model.length > 0);
|
|
157604
158342
|
const attempts = models.length > 0 ? models : [undefined];
|
|
157605
158343
|
let lastResult = null;
|
|
@@ -157610,17 +158348,23 @@ class PiSubagentRunner {
|
|
|
157610
158348
|
model,
|
|
157611
158349
|
fallbackModels: undefined
|
|
157612
158350
|
};
|
|
157613
|
-
const result = await this.runOnce(attemptOptions);
|
|
158351
|
+
const result = await this.runOnce(attemptOptions, runMode);
|
|
157614
158352
|
if (result.ok)
|
|
157615
158353
|
return result;
|
|
157616
158354
|
lastResult = result;
|
|
158355
|
+
if (!this.spawnUsesNoExtensions(runMode) && isPiExtensionCollisionFailure(result)) {
|
|
158356
|
+
return result;
|
|
158357
|
+
}
|
|
157617
158358
|
if (index >= attempts.length - 1 || !isFallbackEligible(result.reason)) {
|
|
157618
158359
|
return result;
|
|
157619
158360
|
}
|
|
157620
158361
|
}
|
|
157621
|
-
return lastResult ?? this.runOnce({ ...options, fallbackModels: undefined });
|
|
158362
|
+
return lastResult ?? this.runOnce({ ...options, fallbackModels: undefined }, runMode);
|
|
157622
158363
|
}
|
|
157623
|
-
|
|
158364
|
+
spawnUsesNoExtensions(runMode) {
|
|
158365
|
+
return runMode.disableDiscoveredExtensions || hasNoExtensionsArg([...this.invocation.prefixArgs, ...this.extraArgs]);
|
|
158366
|
+
}
|
|
158367
|
+
async runOnce(options, runMode) {
|
|
157624
158368
|
const startTime = Date.now();
|
|
157625
158369
|
let recordedAccounting = false;
|
|
157626
158370
|
const recordAccounting = (result, messages = []) => {
|
|
@@ -157695,6 +158439,7 @@ class PiSubagentRunner {
|
|
|
157695
158439
|
}
|
|
157696
158440
|
}
|
|
157697
158441
|
const args = buildArgs(options, {
|
|
158442
|
+
disableDiscoveredExtensions: runMode.disableDiscoveredExtensions,
|
|
157698
158443
|
omitPositionalMessage: deliverViaStdin,
|
|
157699
158444
|
systemPromptPath
|
|
157700
158445
|
});
|
|
@@ -157722,7 +158467,7 @@ class PiSubagentRunner {
|
|
|
157722
158467
|
};
|
|
157723
158468
|
let child;
|
|
157724
158469
|
try {
|
|
157725
|
-
child = this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...args], {
|
|
158470
|
+
child = this.spawnImpl(this.invocation.command, [...this.invocation.prefixArgs, ...this.extraArgs, ...args], {
|
|
157726
158471
|
cwd: options.cwd,
|
|
157727
158472
|
env: {
|
|
157728
158473
|
...process.env,
|
|
@@ -158016,6 +158761,32 @@ class PiSubagentRunner {
|
|
|
158016
158761
|
});
|
|
158017
158762
|
}
|
|
158018
158763
|
}
|
|
158764
|
+
function getResultStderr(result) {
|
|
158765
|
+
const stderr = result.meta?.stderr;
|
|
158766
|
+
return typeof stderr === "string" ? stderr : "";
|
|
158767
|
+
}
|
|
158768
|
+
function hasNoExtensionsArg(args) {
|
|
158769
|
+
return args.includes("--no-extensions");
|
|
158770
|
+
}
|
|
158771
|
+
function isPiExtensionCollisionFailure(result) {
|
|
158772
|
+
return !result.ok && result.reason === "non_zero_exit" && getResultStderr(result).includes(ALREADY_PROCESSING_PREFIX);
|
|
158773
|
+
}
|
|
158774
|
+
function isIsolatedRetryModelUnavailable(result) {
|
|
158775
|
+
if (result.ok)
|
|
158776
|
+
return false;
|
|
158777
|
+
const diagnosticText = `${result.error}
|
|
158778
|
+
${getResultStderr(result)}`;
|
|
158779
|
+
return MODEL_RESOLUTION_ERROR_PATTERNS.some((pattern) => pattern.test(diagnosticText));
|
|
158780
|
+
}
|
|
158781
|
+
function annotateIsolatedRetryModelUnavailable(result) {
|
|
158782
|
+
if (result.error.startsWith(ISOLATED_RETRY_MODEL_UNAVAILABLE_MESSAGE)) {
|
|
158783
|
+
return result;
|
|
158784
|
+
}
|
|
158785
|
+
return {
|
|
158786
|
+
...result,
|
|
158787
|
+
error: `${ISOLATED_RETRY_MODEL_UNAVAILABLE_MESSAGE}. Original failure: ${result.error}`
|
|
158788
|
+
};
|
|
158789
|
+
}
|
|
158019
158790
|
function isFallbackEligible(reason) {
|
|
158020
158791
|
return reason === "model_failed" || reason === "truncated" || reason === "non_zero_exit" || reason === "no_assistant";
|
|
158021
158792
|
}
|
|
@@ -158030,9 +158801,13 @@ function buildArgs(options, opts) {
|
|
|
158030
158801
|
"--no-prompt-templates",
|
|
158031
158802
|
"--no-context-files"
|
|
158032
158803
|
];
|
|
158033
|
-
|
|
158804
|
+
if (opts?.disableDiscoveredExtensions) {
|
|
158805
|
+
args.push("--no-extensions");
|
|
158806
|
+
}
|
|
158807
|
+
const subagentEntryPath = opts?.subagentEntryPath ?? SUBAGENT_ENTRY_PATH;
|
|
158808
|
+
const shouldLoadSubagentExtension = subagentEntryPath && (SEARCH_ONLY_SUBAGENT_TOOL_AGENTS.has(options.agent) || DREAMER_ACTION_AGENTS.has(options.agent));
|
|
158034
158809
|
if (shouldLoadSubagentExtension) {
|
|
158035
|
-
args.push("--extension",
|
|
158810
|
+
args.push("--extension", subagentEntryPath);
|
|
158036
158811
|
if (DREAMER_ACTION_AGENTS.has(options.agent)) {
|
|
158037
158812
|
args.push("--magic-context-dreamer-actions");
|
|
158038
158813
|
}
|
|
@@ -173412,8 +174187,11 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
173412
174187
|
provider: "local",
|
|
173413
174188
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
173414
174189
|
}).describe("Embedding provider configuration"),
|
|
173415
|
-
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add
|
|
174190
|
+
temporal_awareness: exports_external.boolean().default(true).describe('Inject wall-clock gap markers (<!-- +Xm -->) between user messages where > 5 min elapsed since the previous message, and add compact date ranges to compartment headings. Gives the agent a sense of session pacing and "how long ago" across multi-day sessions. Graduated from experimental.temporal_awareness; default: true (set false to opt out).'),
|
|
173416
174191
|
keep_subagents: exports_external.boolean().default(false).describe("Debug: keep the child sessions Magic Context spawns for its own subagents (historian, dreamer, sidekick, memory-migration) instead of deleting them on success. Useful for short-term inspection/data collection — their full transcript (prompt, tool calls, token usage, output) stays in the host session store. Kept sessions accumulate until manually cleared; leave false for normal use. Requires a restart to take effect."),
|
|
174192
|
+
shadow_transform: exports_external.object({
|
|
174193
|
+
enabled: exports_external.boolean().default(false).describe("Dev flag: mirror every transform pass to the Magic Context Rust module over subc and byte-compare outputs. No behavior impact; default off.")
|
|
174194
|
+
}).default({ enabled: false }).describe("Developer-only shadow transform lane. When enabled, the plugin fire-and-forgets a copy of each finalized transform to the Rust module for comparison; the live output is unchanged."),
|
|
173417
174195
|
todowrite: exports_external.object({
|
|
173418
174196
|
enabled: exports_external.boolean().default(true).describe("Pi only: register Magic Context's todowrite task-list tool. Disable if you use your own todo extension. OpenCode ships its own built-in todowrite; this setting has no effect there."),
|
|
173419
174197
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
@@ -175131,7 +175909,7 @@ var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
|
175131
175909
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
175132
175910
|
var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
|
|
175133
175911
|
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
175134
|
-
function
|
|
175912
|
+
function runImmediate2(db, body) {
|
|
175135
175913
|
db.exec("BEGIN IMMEDIATE");
|
|
175136
175914
|
let committed = false;
|
|
175137
175915
|
try {
|
|
@@ -175164,7 +175942,7 @@ function getGitSweepCoordinatorState(db, projectPath) {
|
|
|
175164
175942
|
function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
|
|
175165
175943
|
const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
|
|
175166
175944
|
const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
|
|
175167
|
-
return
|
|
175945
|
+
return runImmediate2(db, () => {
|
|
175168
175946
|
const now = Date.now();
|
|
175169
175947
|
const row = getGitSweepCoordinatorState(db, projectPath);
|
|
175170
175948
|
if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
|
|
@@ -175212,7 +175990,7 @@ function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
|
|
|
175212
175990
|
});
|
|
175213
175991
|
}
|
|
175214
175992
|
function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
|
|
175215
|
-
return
|
|
175993
|
+
return runImmediate2(db, () => {
|
|
175216
175994
|
const now = Date.now();
|
|
175217
175995
|
const leaseExpiresAt = now + leaseTtlMs;
|
|
175218
175996
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -175224,7 +176002,7 @@ function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LE
|
|
|
175224
176002
|
});
|
|
175225
176003
|
}
|
|
175226
176004
|
function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
175227
|
-
return
|
|
176005
|
+
return runImmediate2(db, () => {
|
|
175228
176006
|
const now = Date.now();
|
|
175229
176007
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
175230
176008
|
SET lease_holder = NULL,
|
|
@@ -175237,7 +176015,7 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
|
175237
176015
|
});
|
|
175238
176016
|
}
|
|
175239
176017
|
function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
|
|
175240
|
-
return
|
|
176018
|
+
return runImmediate2(db, () => {
|
|
175241
176019
|
const now = Date.now();
|
|
175242
176020
|
const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
|
|
175243
176021
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -175251,7 +176029,7 @@ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWE
|
|
|
175251
176029
|
});
|
|
175252
176030
|
}
|
|
175253
176031
|
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
175254
|
-
|
|
176032
|
+
runImmediate2(db, () => {
|
|
175255
176033
|
db.prepare(`UPDATE git_sweep_coordinator
|
|
175256
176034
|
SET lease_holder = NULL,
|
|
175257
176035
|
lease_expires_at = NULL
|
|
@@ -177248,7 +178026,7 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
|
|
|
177248
178026
|
const expiry = Number(expiryStr);
|
|
177249
178027
|
return Number.isFinite(expiry) && expiry >= Date.now();
|
|
177250
178028
|
}
|
|
177251
|
-
function
|
|
178029
|
+
function runImmediate3(db, body) {
|
|
177252
178030
|
db.exec("BEGIN IMMEDIATE");
|
|
177253
178031
|
let committed = false;
|
|
177254
178032
|
try {
|
|
@@ -177266,7 +178044,7 @@ function runImmediate2(db, body) {
|
|
|
177266
178044
|
}
|
|
177267
178045
|
function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177268
178046
|
const keys = rowKeys(leaseKey);
|
|
177269
|
-
return
|
|
178047
|
+
return runImmediate3(db, () => {
|
|
177270
178048
|
if (isLeaseActive(db, leaseKey)) {
|
|
177271
178049
|
const existingHolder = getLeaseHolder(db, leaseKey);
|
|
177272
178050
|
if (existingHolder && existingHolder !== holderId) {
|
|
@@ -177282,7 +178060,7 @@ function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
|
177282
178060
|
}
|
|
177283
178061
|
function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177284
178062
|
const keys = rowKeys(leaseKey);
|
|
177285
|
-
return
|
|
178063
|
+
return runImmediate3(db, () => {
|
|
177286
178064
|
if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
|
|
177287
178065
|
return false;
|
|
177288
178066
|
}
|
|
@@ -177293,7 +178071,7 @@ function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
|
177293
178071
|
});
|
|
177294
178072
|
}
|
|
177295
178073
|
function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
|
|
177296
|
-
return
|
|
178074
|
+
return runImmediate3(db, () => {
|
|
177297
178075
|
if (!peekLeaseHolderAndExpiry(db, holderId, leaseKey)) {
|
|
177298
178076
|
throw new Error("Dream lease lost before guarded write");
|
|
177299
178077
|
}
|
|
@@ -177347,7 +178125,7 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
|
|
|
177347
178125
|
}
|
|
177348
178126
|
function releaseLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177349
178127
|
const keys = rowKeys(leaseKey);
|
|
177350
|
-
|
|
178128
|
+
runImmediate3(db, () => {
|
|
177351
178129
|
if (getLeaseHolder(db, leaseKey) !== holderId) {
|
|
177352
178130
|
return;
|
|
177353
178131
|
}
|
|
@@ -183320,6 +184098,9 @@ async function sweepGitCommits(args) {
|
|
|
183320
184098
|
}
|
|
183321
184099
|
}
|
|
183322
184100
|
|
|
184101
|
+
// src/embedding-bootstrap.ts
|
|
184102
|
+
import { statSync as statSync7 } from "node:fs";
|
|
184103
|
+
|
|
183323
184104
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
183324
184105
|
import { createHash as createHash11 } from "node:crypto";
|
|
183325
184106
|
init_logger();
|
|
@@ -183867,6 +184648,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
183867
184648
|
delete projectRaw.sqlite;
|
|
183868
184649
|
warnings.push("Ignoring sqlite.* from project config (security: SQLite cache/mmap PRAGMAs apply to the " + "process-global shared database handle; only user-level config may set them).");
|
|
183869
184650
|
}
|
|
184651
|
+
if ("shadow_transform" in projectRaw) {
|
|
184652
|
+
delete projectRaw.shadow_transform;
|
|
184653
|
+
warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
|
|
184654
|
+
}
|
|
183870
184655
|
const embedding2 = projectRaw.embedding;
|
|
183871
184656
|
if (isPlainObject3(embedding2)) {
|
|
183872
184657
|
const removed = [];
|
|
@@ -184540,8 +185325,38 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
184540
185325
|
}
|
|
184541
185326
|
|
|
184542
185327
|
// src/embedding-bootstrap.ts
|
|
185328
|
+
var registrationFingerprintsByDatabase = new WeakMap;
|
|
185329
|
+
function configCandidatePaths(directory, loadedPaths) {
|
|
185330
|
+
const projectBase = cortexKitProjectConfigBasePath(directory);
|
|
185331
|
+
const userBase = cortexKitUserConfigBasePath();
|
|
185332
|
+
return [
|
|
185333
|
+
`${projectBase}.jsonc`,
|
|
185334
|
+
`${projectBase}.json`,
|
|
185335
|
+
`${userBase}.jsonc`,
|
|
185336
|
+
`${userBase}.json`,
|
|
185337
|
+
...loadedPaths
|
|
185338
|
+
].filter((path11, index, paths) => paths.indexOf(path11) === index);
|
|
185339
|
+
}
|
|
185340
|
+
function configFingerprint(paths) {
|
|
185341
|
+
return paths.map((path11) => {
|
|
185342
|
+
try {
|
|
185343
|
+
const stat2 = statSync7(path11);
|
|
185344
|
+
return `${path11}:${stat2.size}:${stat2.mtimeMs}`;
|
|
185345
|
+
} catch {
|
|
185346
|
+
return `${path11}:missing`;
|
|
185347
|
+
}
|
|
185348
|
+
}).join("|");
|
|
185349
|
+
}
|
|
184543
185350
|
async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
184544
185351
|
const projectIdentity = resolveProjectIdentity(directory);
|
|
185352
|
+
let registrationFingerprints = registrationFingerprintsByDatabase.get(db);
|
|
185353
|
+
if (!registrationFingerprints) {
|
|
185354
|
+
registrationFingerprints = new Map;
|
|
185355
|
+
registrationFingerprintsByDatabase.set(db, registrationFingerprints);
|
|
185356
|
+
}
|
|
185357
|
+
const cached2 = registrationFingerprints.get(projectIdentity);
|
|
185358
|
+
if (cached2 && configFingerprint(cached2.paths) === cached2.fingerprint)
|
|
185359
|
+
return;
|
|
184545
185360
|
const detailed = loadPiConfigDetailed({ cwd: directory });
|
|
184546
185361
|
if (isConfigLoadUntrusted(detailed)) {
|
|
184547
185362
|
handleUntrustedLoad(db, projectIdentity, directory, detailed);
|
|
@@ -184552,315 +185367,65 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
184552
185367
|
gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
|
|
184553
185368
|
};
|
|
184554
185369
|
registerProjectEmbedding(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
184555
|
-
|
|
184556
|
-
|
|
184557
|
-
|
|
184558
|
-
|
|
184559
|
-
function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
|
|
184560
|
-
if (!msg || typeof msg !== "object")
|
|
184561
|
-
return;
|
|
184562
|
-
const byRef = entryIdByRef?.get(msg);
|
|
184563
|
-
if (typeof byRef === "string" && byRef.length > 0)
|
|
184564
|
-
return byRef;
|
|
184565
|
-
const positional = entryIds?.[index];
|
|
184566
|
-
if (typeof positional === "string" && positional.length > 0)
|
|
184567
|
-
return positional;
|
|
184568
|
-
const m = msg;
|
|
184569
|
-
const role = m.role ?? "unknown";
|
|
184570
|
-
return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
|
|
184571
|
-
}
|
|
184572
|
-
function isMidTurnPi(event, _sessionId) {
|
|
184573
|
-
const messages = event?.messages;
|
|
184574
|
-
if (!Array.isArray(messages))
|
|
184575
|
-
return false;
|
|
184576
|
-
let latestAssistantIndex = -1;
|
|
184577
|
-
let latestAssistant = null;
|
|
184578
|
-
for (let i = messages.length - 1;i >= 0; i--) {
|
|
184579
|
-
const msg = messages[i];
|
|
184580
|
-
if (msg !== null && typeof msg === "object") {
|
|
184581
|
-
const record2 = msg;
|
|
184582
|
-
if (record2.role === "assistant") {
|
|
184583
|
-
latestAssistantIndex = i;
|
|
184584
|
-
latestAssistant = record2;
|
|
184585
|
-
break;
|
|
184586
|
-
}
|
|
184587
|
-
}
|
|
184588
|
-
}
|
|
184589
|
-
if (latestAssistant === null)
|
|
184590
|
-
return false;
|
|
184591
|
-
if (hasRealUserAfter(messages, latestAssistantIndex))
|
|
184592
|
-
return false;
|
|
184593
|
-
if (latestAssistant.stopReason === "toolUse")
|
|
184594
|
-
return true;
|
|
184595
|
-
const toolCallIds = getToolCallIds(latestAssistant.content);
|
|
184596
|
-
if (toolCallIds.size === 0)
|
|
184597
|
-
return false;
|
|
184598
|
-
const pairedToolResultIds = new Set;
|
|
184599
|
-
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
184600
|
-
if (msg === null || typeof msg !== "object")
|
|
184601
|
-
continue;
|
|
184602
|
-
const record2 = msg;
|
|
184603
|
-
if (record2.role !== "toolResult")
|
|
184604
|
-
continue;
|
|
184605
|
-
if (typeof record2.toolCallId === "string") {
|
|
184606
|
-
pairedToolResultIds.add(record2.toolCallId);
|
|
184607
|
-
}
|
|
184608
|
-
}
|
|
184609
|
-
for (const id of toolCallIds) {
|
|
184610
|
-
if (!pairedToolResultIds.has(id))
|
|
184611
|
-
return true;
|
|
184612
|
-
}
|
|
184613
|
-
return false;
|
|
184614
|
-
}
|
|
184615
|
-
function hasRealUserAfter(messages, latestAssistantIndex) {
|
|
184616
|
-
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
184617
|
-
if (msg === null || typeof msg !== "object")
|
|
184618
|
-
continue;
|
|
184619
|
-
if (msg.role === "user")
|
|
184620
|
-
return true;
|
|
184621
|
-
}
|
|
184622
|
-
return false;
|
|
184623
|
-
}
|
|
184624
|
-
function getToolCallIds(content) {
|
|
184625
|
-
const ids = new Set;
|
|
184626
|
-
if (!Array.isArray(content))
|
|
184627
|
-
return ids;
|
|
184628
|
-
for (const item of content) {
|
|
184629
|
-
if (item === null || typeof item !== "object")
|
|
184630
|
-
continue;
|
|
184631
|
-
const record2 = item;
|
|
184632
|
-
if (record2.type === "toolCall" && typeof record2.id === "string") {
|
|
184633
|
-
ids.add(record2.id);
|
|
184634
|
-
}
|
|
184635
|
-
}
|
|
184636
|
-
return ids;
|
|
184637
|
-
}
|
|
184638
|
-
function readPiSessionMessages(ctx) {
|
|
184639
|
-
const sm = ctx.sessionManager;
|
|
184640
|
-
if (sm === undefined)
|
|
184641
|
-
return [];
|
|
184642
|
-
const getBranch = sm.getBranch;
|
|
184643
|
-
if (typeof getBranch !== "function")
|
|
184644
|
-
return [];
|
|
184645
|
-
let entries;
|
|
184646
|
-
try {
|
|
184647
|
-
entries = getBranch.call(sm);
|
|
184648
|
-
} catch {
|
|
184649
|
-
return [];
|
|
184650
|
-
}
|
|
184651
|
-
if (!Array.isArray(entries))
|
|
184652
|
-
return [];
|
|
184653
|
-
return convertEntriesToRawMessages(entries);
|
|
184654
|
-
}
|
|
184655
|
-
function findLastModelKeyFromBranch(entries) {
|
|
184656
|
-
if (!Array.isArray(entries))
|
|
184657
|
-
return;
|
|
184658
|
-
for (let i = entries.length - 1;i >= 0; i--) {
|
|
184659
|
-
const e = entries[i];
|
|
184660
|
-
if (!e || typeof e !== "object")
|
|
184661
|
-
continue;
|
|
184662
|
-
const v = e;
|
|
184663
|
-
if (v.type !== "model_change")
|
|
184664
|
-
continue;
|
|
184665
|
-
if (typeof v.provider === "string" && v.provider.length > 0 && typeof v.modelId === "string" && v.modelId.length > 0) {
|
|
184666
|
-
return `${v.provider}/${v.modelId}`;
|
|
184667
|
-
}
|
|
184668
|
-
}
|
|
184669
|
-
return;
|
|
184670
|
-
}
|
|
184671
|
-
function rawEntryVersion(entry) {
|
|
184672
|
-
const record2 = entry;
|
|
184673
|
-
const updated = record2.updatedAt ?? record2.updated_at ?? record2.timestamp;
|
|
184674
|
-
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
184675
|
-
}
|
|
184676
|
-
function attachPiPartVersion(parts, version2) {
|
|
184677
|
-
return parts.map((part) => {
|
|
184678
|
-
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
184679
|
-
return part;
|
|
184680
|
-
try {
|
|
184681
|
-
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
184682
|
-
value: version2,
|
|
184683
|
-
enumerable: false,
|
|
184684
|
-
configurable: true
|
|
184685
|
-
});
|
|
184686
|
-
} catch {}
|
|
184687
|
-
return part;
|
|
185370
|
+
const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
|
|
185371
|
+
registrationFingerprints.set(projectIdentity, {
|
|
185372
|
+
paths: fingerprintPaths,
|
|
185373
|
+
fingerprint: configFingerprint(fingerprintPaths)
|
|
184688
185374
|
});
|
|
184689
185375
|
}
|
|
184690
|
-
|
|
184691
|
-
|
|
184692
|
-
|
|
184693
|
-
|
|
184694
|
-
|
|
184695
|
-
|
|
184696
|
-
|
|
184697
|
-
|
|
184698
|
-
|
|
184699
|
-
|
|
184700
|
-
|
|
184701
|
-
|
|
184702
|
-
|
|
184703
|
-
|
|
184704
|
-
|
|
184705
|
-
|
|
184706
|
-
pendingFirstRealId = entry.id;
|
|
184707
|
-
pendingFirstRealVersion = version2;
|
|
184708
|
-
}
|
|
184709
|
-
continue;
|
|
184710
|
-
}
|
|
184711
|
-
if (role === "user") {
|
|
184712
|
-
const version2 = rawEntryVersion(entry);
|
|
184713
|
-
const parts = [
|
|
184714
|
-
...pendingToolParts,
|
|
184715
|
-
...attachPiPartVersion(synthesizeUserParts(msg), version2)
|
|
184716
|
-
];
|
|
184717
|
-
pendingToolParts = [];
|
|
184718
|
-
pendingFirstRealId = "";
|
|
184719
|
-
pendingFirstRealVersion = "";
|
|
184720
|
-
result.push({
|
|
184721
|
-
ordinal: nextOrdinal++,
|
|
184722
|
-
id: entry.id,
|
|
184723
|
-
role: "user",
|
|
184724
|
-
parts,
|
|
184725
|
-
version: version2
|
|
184726
|
-
});
|
|
184727
|
-
continue;
|
|
184728
|
-
}
|
|
184729
|
-
if (role === "assistant") {
|
|
184730
|
-
if (pendingToolParts.length > 0) {
|
|
184731
|
-
result.push({
|
|
184732
|
-
ordinal: nextOrdinal++,
|
|
184733
|
-
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
184734
|
-
role: "user",
|
|
184735
|
-
parts: pendingToolParts,
|
|
184736
|
-
version: pendingFirstRealVersion
|
|
184737
|
-
});
|
|
184738
|
-
pendingToolParts = [];
|
|
184739
|
-
pendingFirstRealId = "";
|
|
184740
|
-
pendingFirstRealVersion = "";
|
|
185376
|
+
|
|
185377
|
+
// src/dreamer/pi-session-api.ts
|
|
185378
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
185379
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
185380
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
185381
|
+
var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
|
|
185382
|
+
var defaultLoaders = [
|
|
185383
|
+
{
|
|
185384
|
+
name: "Bare import",
|
|
185385
|
+
load: async () => await import(PI_CODING_AGENT_MODULE)
|
|
185386
|
+
},
|
|
185387
|
+
{
|
|
185388
|
+
name: "Resolve from running Pi binary entry",
|
|
185389
|
+
load: async () => {
|
|
185390
|
+
if (!process.argv[1]) {
|
|
185391
|
+
throw new Error("process.argv[1] is undefined");
|
|
184741
185392
|
}
|
|
184742
|
-
const
|
|
184743
|
-
|
|
184744
|
-
|
|
184745
|
-
id: entry.id,
|
|
184746
|
-
role: "assistant",
|
|
184747
|
-
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version2),
|
|
184748
|
-
version: version2
|
|
184749
|
-
});
|
|
184750
|
-
continue;
|
|
185393
|
+
const require2 = createRequire3(process.argv[1]);
|
|
185394
|
+
const resolved = require2.resolve(PI_CODING_AGENT_MODULE);
|
|
185395
|
+
return await import(pathToFileURL2(resolved).href);
|
|
184751
185396
|
}
|
|
184752
|
-
result.push({
|
|
184753
|
-
ordinal: nextOrdinal++,
|
|
184754
|
-
id: entry.id,
|
|
184755
|
-
role: typeof role === "string" ? role : "unknown",
|
|
184756
|
-
parts: [],
|
|
184757
|
-
version: rawEntryVersion(entry)
|
|
184758
|
-
});
|
|
184759
|
-
}
|
|
184760
|
-
if (pendingToolParts.length > 0) {
|
|
184761
|
-
result.push({
|
|
184762
|
-
ordinal: nextOrdinal,
|
|
184763
|
-
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
184764
|
-
role: "user",
|
|
184765
|
-
parts: pendingToolParts,
|
|
184766
|
-
version: pendingFirstRealVersion
|
|
184767
|
-
});
|
|
184768
185397
|
}
|
|
184769
|
-
|
|
184770
|
-
|
|
184771
|
-
function
|
|
184772
|
-
if (
|
|
184773
|
-
return
|
|
184774
|
-
|
|
184775
|
-
|
|
184776
|
-
|
|
184777
|
-
|
|
184778
|
-
|
|
184779
|
-
|
|
184780
|
-
|
|
184781
|
-
|
|
184782
|
-
|
|
184783
|
-
function synthesizeUserParts(msg) {
|
|
184784
|
-
const m = msg;
|
|
184785
|
-
if (typeof m.content === "string") {
|
|
184786
|
-
if (m.content.trim().length === 0)
|
|
184787
|
-
return [];
|
|
184788
|
-
return [{ type: "text", text: m.content }];
|
|
184789
|
-
}
|
|
184790
|
-
if (!Array.isArray(m.content))
|
|
184791
|
-
return [];
|
|
184792
|
-
const parts = [];
|
|
184793
|
-
for (const c of m.content) {
|
|
184794
|
-
if (c === null || typeof c !== "object")
|
|
184795
|
-
continue;
|
|
184796
|
-
const cc = c;
|
|
184797
|
-
if (cc.type === "text" && typeof cc.text === "string") {
|
|
184798
|
-
parts.push({ type: "text", text: cc.text });
|
|
184799
|
-
}
|
|
184800
|
-
}
|
|
184801
|
-
return parts;
|
|
184802
|
-
}
|
|
184803
|
-
function synthesizeAssistantParts(msg) {
|
|
184804
|
-
const m = msg;
|
|
184805
|
-
if (!Array.isArray(m.content))
|
|
184806
|
-
return [];
|
|
184807
|
-
const parts = [];
|
|
184808
|
-
for (const c of m.content) {
|
|
184809
|
-
if (c === null || typeof c !== "object")
|
|
184810
|
-
continue;
|
|
184811
|
-
const cc = c;
|
|
184812
|
-
if (cc.type === "text" && typeof cc.text === "string") {
|
|
184813
|
-
parts.push({ type: "text", text: cc.text });
|
|
184814
|
-
} else if (cc.type === "toolCall" && typeof cc.id === "string") {
|
|
184815
|
-
parts.push({
|
|
184816
|
-
type: "tool",
|
|
184817
|
-
tool: typeof cc.name === "string" ? cc.name : "unknown",
|
|
184818
|
-
callID: cc.id,
|
|
184819
|
-
state: {
|
|
184820
|
-
input: cc.arguments ?? {}
|
|
184821
|
-
}
|
|
184822
|
-
});
|
|
184823
|
-
}
|
|
184824
|
-
}
|
|
184825
|
-
return parts;
|
|
184826
|
-
}
|
|
184827
|
-
function synthesizeToolResultParts(msg) {
|
|
184828
|
-
const m = msg;
|
|
184829
|
-
const callID = typeof m.toolCallId === "string" ? m.toolCallId : "";
|
|
184830
|
-
const tool = typeof m.toolName === "string" ? m.toolName : "unknown";
|
|
184831
|
-
if (!callID)
|
|
184832
|
-
return [];
|
|
184833
|
-
let output = "";
|
|
184834
|
-
if (Array.isArray(m.content)) {
|
|
184835
|
-
const fragments = [];
|
|
184836
|
-
for (const c of m.content) {
|
|
184837
|
-
if (c === null || typeof c !== "object")
|
|
184838
|
-
continue;
|
|
184839
|
-
const cc = c;
|
|
184840
|
-
if (cc.type === "text" && typeof cc.text === "string") {
|
|
184841
|
-
fragments.push(cc.text);
|
|
185398
|
+
];
|
|
185399
|
+
var cachedModulePromise = null;
|
|
185400
|
+
async function resolvePiCodingAgentModule(loaders) {
|
|
185401
|
+
if (cachedModulePromise) {
|
|
185402
|
+
return cachedModulePromise;
|
|
185403
|
+
}
|
|
185404
|
+
const activeLoaders = loaders ?? defaultLoaders;
|
|
185405
|
+
const promise2 = (async () => {
|
|
185406
|
+
const errors3 = [];
|
|
185407
|
+
for (const loader of activeLoaders) {
|
|
185408
|
+
try {
|
|
185409
|
+
return await loader.load();
|
|
185410
|
+
} catch (err) {
|
|
185411
|
+
errors3.push(err);
|
|
184842
185412
|
}
|
|
184843
185413
|
}
|
|
184844
|
-
|
|
184845
|
-
`)
|
|
184846
|
-
|
|
184847
|
-
|
|
184848
|
-
|
|
184849
|
-
|
|
184850
|
-
|
|
184851
|
-
|
|
184852
|
-
|
|
184853
|
-
output
|
|
184854
|
-
}
|
|
185414
|
+
throw new Error(`Failed to resolve ${PI_CODING_AGENT_MODULE} via all strategies:
|
|
185415
|
+
` + errors3.map((e, i) => ` - ${activeLoaders[i].name}: ${e.message || e}`).join(`
|
|
185416
|
+
`) + `
|
|
185417
|
+
Likely cause: symlinked or nonstandard install layout.`);
|
|
185418
|
+
})();
|
|
185419
|
+
cachedModulePromise = promise2;
|
|
185420
|
+
promise2.catch(() => {
|
|
185421
|
+
if (cachedModulePromise === promise2) {
|
|
185422
|
+
cachedModulePromise = null;
|
|
184855
185423
|
}
|
|
184856
|
-
|
|
185424
|
+
});
|
|
185425
|
+
return promise2;
|
|
184857
185426
|
}
|
|
184858
|
-
|
|
184859
|
-
|
|
184860
|
-
import { readFileSync as readFileSync9 } from "node:fs";
|
|
184861
|
-
var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
|
|
184862
|
-
async function loadDefaultPiSessionApi() {
|
|
184863
|
-
const mod = await import(PI_CODING_AGENT_MODULE);
|
|
185427
|
+
async function loadDefaultPiSessionApi(loaders) {
|
|
185428
|
+
const mod = await resolvePiCodingAgentModule(loaders);
|
|
184864
185429
|
const listSessions = mod.SessionManager?.listAll;
|
|
184865
185430
|
if (typeof listSessions !== "function") {
|
|
184866
185431
|
throw new Error("Pi session APIs unavailable: expected SessionManager.listAll on pi-coding-agent");
|
|
@@ -185261,6 +185826,8 @@ function makeMessage(role, parts) {
|
|
|
185261
185826
|
}
|
|
185262
185827
|
|
|
185263
185828
|
// src/commands/pi-command-utils.ts
|
|
185829
|
+
init_logger();
|
|
185830
|
+
import { Box, Text } from "@earendil-works/pi-tui";
|
|
185264
185831
|
var CTX_STATUS_CUSTOM_TYPE = "ctx-status";
|
|
185265
185832
|
function resolveSessionId(ctx) {
|
|
185266
185833
|
const sm = ctx.sessionManager;
|
|
@@ -185274,13 +185841,49 @@ function resolveSessionId(ctx) {
|
|
|
185274
185841
|
return;
|
|
185275
185842
|
}
|
|
185276
185843
|
}
|
|
185844
|
+
function statusTitleColor(level) {
|
|
185845
|
+
switch (level) {
|
|
185846
|
+
case "success":
|
|
185847
|
+
return "success";
|
|
185848
|
+
case "warning":
|
|
185849
|
+
return "warning";
|
|
185850
|
+
case "error":
|
|
185851
|
+
return "error";
|
|
185852
|
+
default:
|
|
185853
|
+
return "accent";
|
|
185854
|
+
}
|
|
185855
|
+
}
|
|
185856
|
+
var renderCtxStatusEntry = (entry, _options, theme) => {
|
|
185857
|
+
const data = entry?.data;
|
|
185858
|
+
if (!data || typeof data !== "object" || typeof data.title !== "string" || typeof data.text !== "string") {
|
|
185859
|
+
return;
|
|
185860
|
+
}
|
|
185861
|
+
const title = theme.bold(theme.fg(statusTitleColor(data.level), `[${data.title}]`));
|
|
185862
|
+
const body = theme.fg("customMessageText", data.text);
|
|
185863
|
+
const box = new Box(1, 0, (text) => theme.bg("customMessageBg", text));
|
|
185864
|
+
box.addChild(new Text(`${title}
|
|
185865
|
+
${body}`));
|
|
185866
|
+
return box;
|
|
185867
|
+
};
|
|
185868
|
+
function registerCtxStatusEntryRenderer(pi) {
|
|
185869
|
+
if (typeof pi.registerEntryRenderer !== "function")
|
|
185870
|
+
return false;
|
|
185871
|
+
try {
|
|
185872
|
+
pi.registerEntryRenderer(CTX_STATUS_CUSTOM_TYPE, renderCtxStatusEntry);
|
|
185873
|
+
return true;
|
|
185874
|
+
} catch {
|
|
185875
|
+
return false;
|
|
185876
|
+
}
|
|
185877
|
+
}
|
|
185277
185878
|
function sendCtxStatusMessage(pi, content, details) {
|
|
185278
|
-
|
|
185279
|
-
|
|
185280
|
-
|
|
185281
|
-
|
|
185282
|
-
|
|
185283
|
-
|
|
185879
|
+
const data = {
|
|
185880
|
+
...content,
|
|
185881
|
+
details: details ?? content.details
|
|
185882
|
+
};
|
|
185883
|
+
if (typeof pi.appendEntry === "function") {
|
|
185884
|
+
pi.appendEntry(CTX_STATUS_CUSTOM_TYPE, data);
|
|
185885
|
+
}
|
|
185886
|
+
sessionLog("pi-status", `${content.title}: ${content.text}`);
|
|
185284
185887
|
}
|
|
185285
185888
|
|
|
185286
185889
|
// src/commands/ctx-dream.ts
|
|
@@ -185740,8 +186343,8 @@ function makeToolCompositeKey(ownerMsgId, callId) {
|
|
|
185740
186343
|
return `${ownerMsgId}${TOOL_COMPOSITE_KEY_SEP}${callId}`;
|
|
185741
186344
|
}
|
|
185742
186345
|
var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
|
|
185743
|
-
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
185744
|
-
var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
|
|
186346
|
+
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
186347
|
+
var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id, byte_size, token_count, input_byte_size, input_token_count FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
|
|
185745
186348
|
var PROBE_DATA_VERSION_SQL = "PRAGMA main.data_version";
|
|
185746
186349
|
var probeDataVersionStatements = new WeakMap;
|
|
185747
186350
|
function getProbeDataVersionStatement(db) {
|
|
@@ -185765,6 +186368,14 @@ function isAssignmentRow(row) {
|
|
|
185765
186368
|
return false;
|
|
185766
186369
|
if (candidate.tool_owner_message_id !== null && typeof candidate.tool_owner_message_id !== "string")
|
|
185767
186370
|
return false;
|
|
186371
|
+
if (typeof candidate.byte_size !== "number")
|
|
186372
|
+
return false;
|
|
186373
|
+
if (candidate.token_count !== null && typeof candidate.token_count !== "number")
|
|
186374
|
+
return false;
|
|
186375
|
+
if (typeof candidate.input_byte_size !== "number")
|
|
186376
|
+
return false;
|
|
186377
|
+
if (candidate.input_token_count !== null && typeof candidate.input_token_count !== "number")
|
|
186378
|
+
return false;
|
|
185768
186379
|
return true;
|
|
185769
186380
|
}
|
|
185770
186381
|
var UPSERT_COUNTER_SQL = `
|
|
@@ -185799,6 +186410,7 @@ var MAX_TAG_ALLOC_RETRIES = 5;
|
|
|
185799
186410
|
function createTagger() {
|
|
185800
186411
|
const counters = new Map;
|
|
185801
186412
|
const assignments = new Map;
|
|
186413
|
+
const toolAccountingBySession = new Map;
|
|
185802
186414
|
const loadSignatures = new Map;
|
|
185803
186415
|
function getSessionAssignments(sessionId) {
|
|
185804
186416
|
let map2 = assignments.get(sessionId);
|
|
@@ -185808,6 +186420,14 @@ function createTagger() {
|
|
|
185808
186420
|
}
|
|
185809
186421
|
return map2;
|
|
185810
186422
|
}
|
|
186423
|
+
function getSessionToolAccounting(sessionId) {
|
|
186424
|
+
let map2 = toolAccountingBySession.get(sessionId);
|
|
186425
|
+
if (!map2) {
|
|
186426
|
+
map2 = new Map;
|
|
186427
|
+
toolAccountingBySession.set(sessionId, map2);
|
|
186428
|
+
}
|
|
186429
|
+
return map2;
|
|
186430
|
+
}
|
|
185811
186431
|
function isUniqueConstraintError(error51) {
|
|
185812
186432
|
return error51 instanceof Error && "code" in error51 && error51.code === "SQLITE_CONSTRAINT_UNIQUE";
|
|
185813
186433
|
}
|
|
@@ -185861,6 +186481,14 @@ function createTagger() {
|
|
|
185861
186481
|
}
|
|
185862
186482
|
counters.set(sessionId, next);
|
|
185863
186483
|
sessionAssignments.set(mapKey, next);
|
|
186484
|
+
if (type === "tool") {
|
|
186485
|
+
getSessionToolAccounting(sessionId).set(next, {
|
|
186486
|
+
byteSize: byteSize2,
|
|
186487
|
+
tokenCount: tokenCounts?.tokenCount ?? null,
|
|
186488
|
+
inputByteSize,
|
|
186489
|
+
inputTokenCount: tokenCounts?.inputTokenCount ?? null
|
|
186490
|
+
});
|
|
186491
|
+
}
|
|
185864
186492
|
return next;
|
|
185865
186493
|
}
|
|
185866
186494
|
throw new Error(`tagger.allocateTag: failed to allocate tag for session=${sessionId} key=${mapKey} after ${MAX_TAG_ALLOC_RETRIES} retries`);
|
|
@@ -185921,6 +186549,13 @@ function createTagger() {
|
|
|
185921
186549
|
function getToolTag(sessionId, callId, ownerMsgId) {
|
|
185922
186550
|
return assignments.get(sessionId)?.get(makeToolCompositeKey(ownerMsgId, callId));
|
|
185923
186551
|
}
|
|
186552
|
+
function getToolTagAccounting(sessionId, callId, ownerMsgId) {
|
|
186553
|
+
const tagNumber = getToolTag(sessionId, callId, ownerMsgId);
|
|
186554
|
+
return tagNumber === undefined ? undefined : toolAccountingBySession.get(sessionId)?.get(tagNumber);
|
|
186555
|
+
}
|
|
186556
|
+
function setToolTagAccounting(sessionId, tagNumber, accounting) {
|
|
186557
|
+
getSessionToolAccounting(sessionId).set(tagNumber, accounting);
|
|
186558
|
+
}
|
|
185924
186559
|
function bindTag(sessionId, messageId, tagNumber) {
|
|
185925
186560
|
getSessionAssignments(sessionId).set(messageId, tagNumber);
|
|
185926
186561
|
}
|
|
@@ -185939,6 +186574,7 @@ function createTagger() {
|
|
|
185939
186574
|
function resetCounter(sessionId, db) {
|
|
185940
186575
|
counters.set(sessionId, 0);
|
|
185941
186576
|
assignments.delete(sessionId);
|
|
186577
|
+
toolAccountingBySession.delete(sessionId);
|
|
185942
186578
|
loadSignatures.delete(sessionId);
|
|
185943
186579
|
getResetCounterStatement(db).run(sessionId, getHarness());
|
|
185944
186580
|
}
|
|
@@ -185961,11 +186597,19 @@ function createTagger() {
|
|
|
185961
186597
|
const assignmentRows = (floor > 0 ? db.prepare(GET_ASSIGNMENTS_SCOPED_SQL).all(sessionId, floor) : db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId)).filter(isAssignmentRow);
|
|
185962
186598
|
const sessionAssignments = getSessionAssignments(sessionId);
|
|
185963
186599
|
sessionAssignments.clear();
|
|
186600
|
+
const sessionToolAccounting = getSessionToolAccounting(sessionId);
|
|
186601
|
+
sessionToolAccounting.clear();
|
|
185964
186602
|
let maxTagNumber = 0;
|
|
185965
186603
|
for (const assignment of assignmentRows) {
|
|
185966
186604
|
if (assignment.type === "tool") {
|
|
185967
186605
|
if (assignment.tool_owner_message_id !== null) {
|
|
185968
186606
|
sessionAssignments.set(makeToolCompositeKey(assignment.tool_owner_message_id, assignment.message_id), assignment.tag_number);
|
|
186607
|
+
sessionToolAccounting.set(assignment.tag_number, {
|
|
186608
|
+
byteSize: assignment.byte_size,
|
|
186609
|
+
tokenCount: assignment.token_count,
|
|
186610
|
+
inputByteSize: assignment.input_byte_size,
|
|
186611
|
+
inputTokenCount: assignment.input_token_count
|
|
186612
|
+
});
|
|
185969
186613
|
}
|
|
185970
186614
|
} else {
|
|
185971
186615
|
sessionAssignments.set(assignment.message_id, assignment.tag_number);
|
|
@@ -185985,6 +186629,7 @@ function createTagger() {
|
|
|
185985
186629
|
function cleanup(sessionId) {
|
|
185986
186630
|
counters.delete(sessionId);
|
|
185987
186631
|
assignments.delete(sessionId);
|
|
186632
|
+
toolAccountingBySession.delete(sessionId);
|
|
185988
186633
|
loadSignatures.delete(sessionId);
|
|
185989
186634
|
}
|
|
185990
186635
|
return {
|
|
@@ -185992,6 +186637,8 @@ function createTagger() {
|
|
|
185992
186637
|
assignToolTag,
|
|
185993
186638
|
getTag,
|
|
185994
186639
|
getToolTag,
|
|
186640
|
+
getToolTagAccounting,
|
|
186641
|
+
setToolTagAccounting,
|
|
185995
186642
|
bindTag,
|
|
185996
186643
|
unbindTag,
|
|
185997
186644
|
bindToolTag,
|
|
@@ -187967,26 +188614,28 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
187967
188614
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
187968
188615
|
return { shouldFire: false };
|
|
187969
188616
|
}
|
|
187970
|
-
|
|
188617
|
+
const lazyInMemoryTail = typeof inMemoryTail === "function" ? inMemoryTail : undefined;
|
|
188618
|
+
let resolvedInMemoryTail = typeof inMemoryTail === "function" ? undefined : inMemoryTail;
|
|
188619
|
+
if (resolvedInMemoryTail) {
|
|
187971
188620
|
try {
|
|
187972
188621
|
const policyVersion = loadProtectedTailMeta(db, sessionId).protectedTailPolicyVersion;
|
|
187973
188622
|
if (policyVersion < 3)
|
|
187974
|
-
|
|
188623
|
+
resolvedInMemoryTail = undefined;
|
|
187975
188624
|
} catch {
|
|
187976
|
-
|
|
188625
|
+
resolvedInMemoryTail = undefined;
|
|
187977
188626
|
}
|
|
187978
188627
|
}
|
|
187979
|
-
const taggerFloor = taggerFloorOverride !== undefined && taggerFloorOverride > 0 ? taggerFloorOverride :
|
|
188628
|
+
const taggerFloor = taggerFloorOverride !== undefined && taggerFloorOverride > 0 ? taggerFloorOverride : resolvedInMemoryTail ? deriveTagLoadFloor(db, sessionId, resolvedInMemoryTail.messages.map((m) => m.id)) : 0;
|
|
187980
188629
|
const proactiveFloorForGate = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
187981
188630
|
if (usage.percentage < proactiveFloorForGate) {
|
|
187982
188631
|
try {
|
|
187983
|
-
const boundFloor =
|
|
188632
|
+
const boundFloor = resolvedInMemoryTail || lazyInMemoryTail ? taggerFloor : 0;
|
|
187984
188633
|
const { bound: persistedBound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId, boundFloor);
|
|
187985
188634
|
if (nullCount === 0) {
|
|
187986
|
-
const untaggedUpperBound =
|
|
188635
|
+
const untaggedUpperBound = resolvedInMemoryTail ? estimateUntaggedInMemoryTailUpperBound(db, sessionId, resolvedInMemoryTail, taggerFloor) : 0;
|
|
187987
188636
|
const eligibleUpperBound = persistedBound + untaggedUpperBound;
|
|
187988
188637
|
if (eligibleUpperBound < triggerBudget) {
|
|
187989
|
-
const memorySuffix =
|
|
188638
|
+
const memorySuffix = resolvedInMemoryTail ? ` (persisted=${persistedBound}, untagged-memory≤${untaggedUpperBound})` : "";
|
|
187990
188639
|
sessionLog(sessionId, `compartment trigger: cheap-skip at ${usage.percentage.toFixed(1)}% (below proactive floor ${proactiveFloorForGate}%) — live-tail upper bound ${eligibleUpperBound}${memorySuffix} < triggerBudget ${triggerBudget}; no size trigger possible, skipped full raw read`);
|
|
187991
188640
|
return { shouldFire: false };
|
|
187992
188641
|
}
|
|
@@ -187995,7 +188644,16 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
187995
188644
|
sessionLog(sessionId, `compartment trigger: cheap-gate skipped (falling through to full read): ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
187996
188645
|
}
|
|
187997
188646
|
}
|
|
187998
|
-
|
|
188647
|
+
if (lazyInMemoryTail) {
|
|
188648
|
+
try {
|
|
188649
|
+
const policyVersion = loadProtectedTailMeta(db, sessionId).protectedTailPolicyVersion;
|
|
188650
|
+
if (policyVersion >= 3)
|
|
188651
|
+
resolvedInMemoryTail = lazyInMemoryTail();
|
|
188652
|
+
} catch {
|
|
188653
|
+
resolvedInMemoryTail = undefined;
|
|
188654
|
+
}
|
|
188655
|
+
}
|
|
188656
|
+
const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor);
|
|
187999
188657
|
if (!tailInfo.hasNewRawHistory) {
|
|
188000
188658
|
try {
|
|
188001
188659
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
@@ -188022,11 +188680,11 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
188022
188680
|
}
|
|
188023
188681
|
const scale = usage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE ? 0.25 : 0.5;
|
|
188024
188682
|
const scaledBoundary = withRawSessionMessageCache(() => {
|
|
188025
|
-
if (
|
|
188683
|
+
if (resolvedInMemoryTail) {
|
|
188026
188684
|
primeInMemoryTailRawMessageCache({
|
|
188027
188685
|
sessionId,
|
|
188028
|
-
messages:
|
|
188029
|
-
absoluteMessageCount:
|
|
188686
|
+
messages: resolvedInMemoryTail.messages,
|
|
188687
|
+
absoluteMessageCount: resolvedInMemoryTail.absoluteMessageCount
|
|
188030
188688
|
});
|
|
188031
188689
|
}
|
|
188032
188690
|
return resolveOpenCodeProtectedTailBoundary({
|
|
@@ -188313,12 +188971,26 @@ function computeBudgetPressure(compartments, historyBudget) {
|
|
|
188313
188971
|
|
|
188314
188972
|
// ../plugin/src/hooks/magic-context/decay-render.ts
|
|
188315
188973
|
var DEFAULT_HISTORY_BUDGET_TOKENS = 60000;
|
|
188316
|
-
function escapeXmlAttr2(s) {
|
|
188317
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
188318
|
-
}
|
|
188319
188974
|
function escapeXmlContent2(s) {
|
|
188320
188975
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
188321
188976
|
}
|
|
188977
|
+
function formatDateRange(startDate, endDate) {
|
|
188978
|
+
if (!startDate || !endDate)
|
|
188979
|
+
return "";
|
|
188980
|
+
if (startDate === endDate)
|
|
188981
|
+
return startDate;
|
|
188982
|
+
if (startDate.slice(0, 7) === endDate.slice(0, 7))
|
|
188983
|
+
return `${startDate}→${endDate.slice(8)}`;
|
|
188984
|
+
return `${startDate}→${endDate}`;
|
|
188985
|
+
}
|
|
188986
|
+
function compartmentHeading(c) {
|
|
188987
|
+
const dateRange = formatDateRange(c.startDate, c.endDate);
|
|
188988
|
+
const dateSegment = dateRange ? ` · ${dateRange}` : "";
|
|
188989
|
+
return `## ${c.startMessage}-${c.endMessage}${dateSegment} · ${c.title}`;
|
|
188990
|
+
}
|
|
188991
|
+
function guardCompartmentBody(body) {
|
|
188992
|
+
return body.replace(/^## /gm, " ## ");
|
|
188993
|
+
}
|
|
188322
188994
|
function isTieredRow(c) {
|
|
188323
188995
|
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
188324
188996
|
}
|
|
@@ -188348,25 +189020,22 @@ function renderCompartmentAtTier(c, tier2) {
|
|
|
188348
189020
|
return renderOneCompartment(c, tier2);
|
|
188349
189021
|
}
|
|
188350
189022
|
function renderOneCompartment(c, tier2) {
|
|
188351
|
-
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
188352
189023
|
if (tier2 >= 5)
|
|
188353
189024
|
return "";
|
|
189025
|
+
const heading = compartmentHeading(c);
|
|
188354
189026
|
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
188355
189027
|
const flat = (c.content ?? "").trim();
|
|
188356
189028
|
if (tier2 >= 4 || flat.length === 0)
|
|
188357
|
-
return
|
|
188358
|
-
|
|
188359
|
-
|
|
188360
|
-
|
|
188361
|
-
"</compartment>"
|
|
188362
|
-
].join(`
|
|
188363
|
-
`);
|
|
189029
|
+
return heading;
|
|
189030
|
+
const body2 = guardCompartmentBody(escapeXmlContent2(legacyBodyForTier(flat, tier2)));
|
|
189031
|
+
return `${heading}
|
|
189032
|
+
${body2}`;
|
|
188364
189033
|
}
|
|
188365
189034
|
const body = tierBody(c, tier2);
|
|
188366
189035
|
if (body.length === 0)
|
|
188367
|
-
return
|
|
188368
|
-
return
|
|
188369
|
-
|
|
189036
|
+
return heading;
|
|
189037
|
+
return `${heading}
|
|
189038
|
+
${guardCompartmentBody(escapeXmlContent2(body))}`;
|
|
188370
189039
|
}
|
|
188371
189040
|
function computeTiers(compartments, historyBudgetTokens) {
|
|
188372
189041
|
const v2Compartments = compartments.map((c, originalIndex) => ({ c, originalIndex })).filter(({ c }) => c.legacy !== 1);
|
|
@@ -188489,33 +189158,9 @@ function getVisibleMemoryIds(db, sessionId) {
|
|
|
188489
189158
|
}
|
|
188490
189159
|
}
|
|
188491
189160
|
function renderMemoryBlock(memories) {
|
|
188492
|
-
|
|
188493
|
-
for (const m of memories) {
|
|
188494
|
-
const existing = byCategory.get(m.category);
|
|
188495
|
-
if (existing) {
|
|
188496
|
-
existing.push(m);
|
|
188497
|
-
} else {
|
|
188498
|
-
byCategory.set(m.category, [m]);
|
|
188499
|
-
}
|
|
188500
|
-
}
|
|
188501
|
-
const sections = [];
|
|
188502
|
-
for (const category of CATEGORY_PRIORITY) {
|
|
188503
|
-
const categoryMemories = byCategory.get(category);
|
|
188504
|
-
if (!categoryMemories || categoryMemories.length === 0) {
|
|
188505
|
-
continue;
|
|
188506
|
-
}
|
|
188507
|
-
sections.push(`<${category}>`, ...categoryMemories.map((m) => `- ${escapeXmlContent(m.content)}`), `</${category}>`);
|
|
188508
|
-
}
|
|
188509
|
-
if (sections.length === 0) {
|
|
188510
|
-
return null;
|
|
188511
|
-
}
|
|
188512
|
-
return `<project-memory>
|
|
188513
|
-
${sections.join(`
|
|
188514
|
-
`)}
|
|
188515
|
-
</project-memory>`;
|
|
189161
|
+
return renderMemoryBlockV2(memories) || null;
|
|
188516
189162
|
}
|
|
188517
189163
|
var DEFAULT_MEMORY_BUDGET_TOKENS = 8000;
|
|
188518
|
-
var MEMORY_BLOCK_WRAPPER_TOKENS = 6;
|
|
188519
189164
|
var DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000;
|
|
188520
189165
|
function memoryCanonicalIdentity(memory, workspace) {
|
|
188521
189166
|
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
@@ -188533,11 +189178,18 @@ function memorySelectionOrder(left, right) {
|
|
|
188533
189178
|
return left.id - right.id;
|
|
188534
189179
|
}
|
|
188535
189180
|
function memoryRenderOrder(left, right) {
|
|
188536
|
-
const
|
|
188537
|
-
const
|
|
188538
|
-
|
|
188539
|
-
|
|
188540
|
-
|
|
189181
|
+
const leftPriority = V2_MEMORY_CATEGORIES.indexOf(left.category);
|
|
189182
|
+
const rightPriority = V2_MEMORY_CATEGORIES.indexOf(right.category);
|
|
189183
|
+
if (leftPriority >= 0 || rightPriority >= 0) {
|
|
189184
|
+
if (leftPriority < 0)
|
|
189185
|
+
return 1;
|
|
189186
|
+
if (rightPriority < 0)
|
|
189187
|
+
return -1;
|
|
189188
|
+
if (leftPriority !== rightPriority)
|
|
189189
|
+
return leftPriority - rightPriority;
|
|
189190
|
+
} else if (left.category !== right.category) {
|
|
189191
|
+
return left.category < right.category ? -1 : 1;
|
|
189192
|
+
}
|
|
188541
189193
|
return left.id - right.id;
|
|
188542
189194
|
}
|
|
188543
189195
|
var maxCompartmentSeqStatements = new WeakMap;
|
|
@@ -188548,13 +189200,13 @@ var newCompartmentStatements = new WeakMap;
|
|
|
188548
189200
|
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
188549
189201
|
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
188550
189202
|
const selected = [];
|
|
188551
|
-
|
|
189203
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
188552
189204
|
for (const memory of selectionOrder) {
|
|
188553
|
-
const
|
|
188554
|
-
if (usedTokens +
|
|
189205
|
+
const cost = accounting.candidateCost(memory);
|
|
189206
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188555
189207
|
continue;
|
|
189208
|
+
accounting.admit(memory, cost);
|
|
188556
189209
|
selected.push(memory);
|
|
188557
|
-
usedTokens += memoryTokens;
|
|
188558
189210
|
}
|
|
188559
189211
|
if (selected.length < memories.length) {
|
|
188560
189212
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
@@ -188568,23 +189220,22 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
188568
189220
|
}
|
|
188569
189221
|
const selected = [];
|
|
188570
189222
|
const selectedIds = new Set;
|
|
188571
|
-
|
|
188572
|
-
const tokenCost = (memory) => estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
189223
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
188573
189224
|
const trySelect = (memory) => {
|
|
188574
189225
|
if (selectedIds.has(memory.id))
|
|
188575
189226
|
return false;
|
|
188576
|
-
const
|
|
188577
|
-
if (usedTokens +
|
|
189227
|
+
const cost = accounting.candidateCost(memory);
|
|
189228
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188578
189229
|
return false;
|
|
188579
189230
|
selected.push(memory);
|
|
188580
189231
|
selectedIds.add(memory.id);
|
|
188581
|
-
|
|
189232
|
+
accounting.admit(memory, cost);
|
|
188582
189233
|
return true;
|
|
188583
189234
|
};
|
|
188584
189235
|
for (const memory of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
188585
189236
|
trySelect(memory);
|
|
188586
189237
|
}
|
|
188587
|
-
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
189238
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - accounting.usedTokens);
|
|
188588
189239
|
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
188589
189240
|
const byIdentity = new Map;
|
|
188590
189241
|
for (const memory of memories) {
|
|
@@ -188603,15 +189254,15 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
188603
189254
|
for (const memory of candidates) {
|
|
188604
189255
|
if (selectedIds.has(memory.id))
|
|
188605
189256
|
continue;
|
|
188606
|
-
const
|
|
188607
|
-
if (memberTokens +
|
|
189257
|
+
const cost = accounting.candidateCost(memory);
|
|
189258
|
+
if (memberTokens + cost > floorTokens)
|
|
188608
189259
|
continue;
|
|
188609
|
-
if (usedTokens +
|
|
189260
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188610
189261
|
continue;
|
|
188611
189262
|
selected.push(memory);
|
|
188612
189263
|
selectedIds.add(memory.id);
|
|
188613
|
-
|
|
188614
|
-
memberTokens +=
|
|
189264
|
+
accounting.admit(memory, cost);
|
|
189265
|
+
memberTokens += cost;
|
|
188615
189266
|
}
|
|
188616
189267
|
}
|
|
188617
189268
|
const remaining = memories.filter((memory) => !selectedIds.has(memory.id)).sort(memorySelectionOrder);
|
|
@@ -188635,17 +189286,55 @@ function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
|
188635
189286
|
}
|
|
188636
189287
|
return selected;
|
|
188637
189288
|
}
|
|
189289
|
+
function createMemoryBlockAccounting(renderOptions) {
|
|
189290
|
+
const seenCategories = new Set;
|
|
189291
|
+
const categoryCost = new Map;
|
|
189292
|
+
return {
|
|
189293
|
+
usedTokens: estimateTokens(`<project-memory>
|
|
189294
|
+
</project-memory>`),
|
|
189295
|
+
candidateCost(memory) {
|
|
189296
|
+
const line = renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id));
|
|
189297
|
+
let cost = estimateTokens(`${line}
|
|
189298
|
+
`);
|
|
189299
|
+
if (!seenCategories.has(memory.category)) {
|
|
189300
|
+
let tags = categoryCost.get(memory.category);
|
|
189301
|
+
if (tags === undefined) {
|
|
189302
|
+
tags = estimateTokens(`<${escapeXmlAttr(memory.category)}>
|
|
189303
|
+
</${escapeXmlAttr(memory.category)}>
|
|
189304
|
+
`);
|
|
189305
|
+
categoryCost.set(memory.category, tags);
|
|
189306
|
+
}
|
|
189307
|
+
cost += tags;
|
|
189308
|
+
}
|
|
189309
|
+
return cost;
|
|
189310
|
+
},
|
|
189311
|
+
admit(memory, cost) {
|
|
189312
|
+
this.usedTokens += cost;
|
|
189313
|
+
seenCategories.add(memory.category);
|
|
189314
|
+
}
|
|
189315
|
+
};
|
|
189316
|
+
}
|
|
188638
189317
|
function renderMemoryLineV2(memory, sourceName) {
|
|
188639
|
-
const
|
|
188640
|
-
return
|
|
189318
|
+
const source = sourceName ? ` [${escapeXmlContent(sourceName)}]` : "";
|
|
189319
|
+
return `#${memory.id}${source}: ${escapeXmlContent(memory.content)}`;
|
|
188641
189320
|
}
|
|
188642
189321
|
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
188643
189322
|
if (memories.length === 0)
|
|
188644
189323
|
return "";
|
|
189324
|
+
const ordered = [...memories].sort(memoryRenderOrder);
|
|
188645
189325
|
const lines = [`<${wrapper}>`];
|
|
188646
|
-
|
|
189326
|
+
let openCategory;
|
|
189327
|
+
for (const memory of ordered) {
|
|
189328
|
+
if (memory.category !== openCategory) {
|
|
189329
|
+
if (openCategory !== undefined)
|
|
189330
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
189331
|
+
openCategory = memory.category;
|
|
189332
|
+
lines.push(`<${escapeXmlAttr(openCategory)}>`);
|
|
189333
|
+
}
|
|
188647
189334
|
lines.push(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
188648
189335
|
}
|
|
189336
|
+
if (openCategory !== undefined)
|
|
189337
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
188649
189338
|
lines.push(`</${wrapper}>`);
|
|
188650
189339
|
return lines.join(`
|
|
188651
189340
|
`);
|
|
@@ -188939,6 +189628,7 @@ function readUint32BE(b, offset) {
|
|
|
188939
189628
|
function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
188940
189629
|
const skipPrefixInjection = options.skipPrefixInjection === true;
|
|
188941
189630
|
const targets = new Map;
|
|
189631
|
+
const timing = options.onTiming ? { identity: 0, prefix: 0, targets: 0, tokenCounting: 0 } : undefined;
|
|
188942
189632
|
const toolAggregates = new Map;
|
|
188943
189633
|
const openToolAggregateKeysByCallId = new Map;
|
|
188944
189634
|
let activeToolResultRun;
|
|
@@ -188948,6 +189638,7 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
188948
189638
|
continue;
|
|
188949
189639
|
activeToolResultRun = undefined;
|
|
188950
189640
|
const messageId = message.info.id;
|
|
189641
|
+
const reuseIdentity = messageId !== undefined && options.reuseMessageIds?.has(messageId) === true;
|
|
188951
189642
|
let textOrdinal = 0;
|
|
188952
189643
|
const parts = message.parts;
|
|
188953
189644
|
for (let partIndex = 0;partIndex < parts.length; partIndex += 1) {
|
|
@@ -188973,7 +189664,10 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
188973
189664
|
db,
|
|
188974
189665
|
targets,
|
|
188975
189666
|
skipPrefixInjection,
|
|
188976
|
-
entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null
|
|
189667
|
+
entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null,
|
|
189668
|
+
reuseIdentity,
|
|
189669
|
+
timing,
|
|
189670
|
+
textTokenCache: options.textTokenCache
|
|
188977
189671
|
});
|
|
188978
189672
|
textOrdinal += 1;
|
|
188979
189673
|
continue;
|
|
@@ -188983,12 +189677,8 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
188983
189677
|
activeToolResultRun = undefined;
|
|
188984
189678
|
continue;
|
|
188985
189679
|
}
|
|
189680
|
+
const identityStart = timing ? performance.now() : 0;
|
|
188986
189681
|
const callId = part.id;
|
|
188987
|
-
const text = part.getText() ?? "";
|
|
188988
|
-
const toolByteSize = getToolPartByteSize(part, text);
|
|
188989
|
-
const toolTokenCount = getToolPartTokenCount(part, text);
|
|
188990
|
-
const meta3 = part.getToolMetadata();
|
|
188991
|
-
const inputTokenCount = meta3.inputTokenCount;
|
|
188992
189682
|
if (typeof callId !== "string" || callId.length === 0) {
|
|
188993
189683
|
activeToolResultRun = undefined;
|
|
188994
189684
|
tagToolPart({
|
|
@@ -189001,7 +189691,9 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189001
189691
|
tagger,
|
|
189002
189692
|
db,
|
|
189003
189693
|
targets,
|
|
189004
|
-
skipPrefixInjection
|
|
189694
|
+
skipPrefixInjection,
|
|
189695
|
+
reuseIdentity,
|
|
189696
|
+
timing
|
|
189005
189697
|
});
|
|
189006
189698
|
continue;
|
|
189007
189699
|
}
|
|
@@ -189017,79 +189709,234 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189017
189709
|
const aggregateKey = existingKey ?? makeToolCompositeKey(messageId, callId);
|
|
189018
189710
|
const existing = toolAggregates.get(aggregateKey);
|
|
189019
189711
|
if (existing) {
|
|
189020
|
-
existing.occurrences.push({
|
|
189021
|
-
|
|
189712
|
+
existing.occurrences.push({ message, part, kind: part.kind });
|
|
189713
|
+
const canReuseIdentity = reuseIdentity && existing.identityReusable;
|
|
189714
|
+
let text2 = "";
|
|
189715
|
+
if (canReuseIdentity) {
|
|
189716
|
+
if (part.kind === "tool_result") {
|
|
189717
|
+
text2 = part.getText() ?? "";
|
|
189718
|
+
applyGrownToolResultAccounting({
|
|
189719
|
+
db,
|
|
189720
|
+
sessionId,
|
|
189721
|
+
tagger,
|
|
189722
|
+
aggregate: existing,
|
|
189723
|
+
byteSize: getToolPartByteSize(part, text2),
|
|
189724
|
+
part,
|
|
189725
|
+
text: text2,
|
|
189726
|
+
timing,
|
|
189727
|
+
tokenCache: options.toolTokenCache,
|
|
189728
|
+
tokenCacheKey: aggregateKey
|
|
189729
|
+
});
|
|
189730
|
+
}
|
|
189731
|
+
if (timing)
|
|
189732
|
+
timing.identity += performance.now() - identityStart;
|
|
189733
|
+
} else {
|
|
189734
|
+
const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, aggregateKey);
|
|
189735
|
+
text2 = accounting.text;
|
|
189736
|
+
if (part.kind === "tool_result") {
|
|
189737
|
+
applyGrownToolResultAccounting({
|
|
189738
|
+
db,
|
|
189739
|
+
sessionId,
|
|
189740
|
+
tagger,
|
|
189741
|
+
aggregate: existing,
|
|
189742
|
+
byteSize: accounting.byteSize,
|
|
189743
|
+
part,
|
|
189744
|
+
text: text2,
|
|
189745
|
+
timing,
|
|
189746
|
+
knownTokenCount: accounting.tokenCount
|
|
189747
|
+
});
|
|
189748
|
+
}
|
|
189749
|
+
if (existing.toolName === null && accounting.toolName) {
|
|
189750
|
+
existing.toolName = accounting.toolName;
|
|
189751
|
+
}
|
|
189752
|
+
if (existing.inputByteSize === 0 && part.kind === "tool_use" && accounting.inputByteSize > 0) {
|
|
189753
|
+
existing.inputByteSize = accounting.inputByteSize;
|
|
189754
|
+
updateTagInputByteSize(db, sessionId, existing.tagId, accounting.inputByteSize);
|
|
189755
|
+
}
|
|
189756
|
+
if (existing.inputTokenCount === null && part.kind === "tool_use" && accounting.inputTokenCount > 0) {
|
|
189757
|
+
existing.inputTokenCount = accounting.inputTokenCount;
|
|
189758
|
+
updateTagInputTokenCount(db, sessionId, existing.tagId, accounting.inputTokenCount);
|
|
189759
|
+
}
|
|
189760
|
+
syncToolAggregateAccounting(tagger, sessionId, existing);
|
|
189761
|
+
if (timing)
|
|
189762
|
+
timing.identity += performance.now() - identityStart;
|
|
189763
|
+
}
|
|
189764
|
+
existing.identityReusable &&= reuseIdentity;
|
|
189765
|
+
applyToolPrefixAndTarget({
|
|
189766
|
+
skipPrefixInjection,
|
|
189022
189767
|
part,
|
|
189023
|
-
|
|
189768
|
+
text: text2,
|
|
189769
|
+
tagId: existing.tagId,
|
|
189770
|
+
aggregate: existing,
|
|
189771
|
+
targets,
|
|
189772
|
+
timing
|
|
189024
189773
|
});
|
|
189025
|
-
if (part.kind === "tool_result" && toolByteSize > existing.maxByteSize) {
|
|
189026
|
-
existing.maxByteSize = toolByteSize;
|
|
189027
|
-
existing.maxTokenCount = toolTokenCount;
|
|
189028
|
-
updateTagByteSize(db, sessionId, existing.tagId, toolByteSize);
|
|
189029
|
-
updateTagTokenCount(db, sessionId, existing.tagId, toolTokenCount);
|
|
189030
|
-
}
|
|
189031
|
-
if (existing.toolName === null && meta3.toolName) {
|
|
189032
|
-
existing.toolName = meta3.toolName;
|
|
189033
|
-
}
|
|
189034
|
-
if (existing.inputByteSize === 0 && part.kind === "tool_use" && meta3.inputByteSize > 0) {
|
|
189035
|
-
existing.inputByteSize = meta3.inputByteSize;
|
|
189036
|
-
updateTagInputByteSize(db, sessionId, existing.tagId, meta3.inputByteSize);
|
|
189037
|
-
}
|
|
189038
|
-
if (!existing.inputTokenStored && part.kind === "tool_use" && inputTokenCount > 0) {
|
|
189039
|
-
existing.inputTokenStored = true;
|
|
189040
|
-
updateTagInputTokenCount(db, sessionId, existing.tagId, inputTokenCount);
|
|
189041
|
-
}
|
|
189042
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
189043
|
-
part.setText(prependTag(existing.tagId, text));
|
|
189044
|
-
}
|
|
189045
|
-
targets.set(existing.tagId, buildAggregateTarget(existing.tagId, existing.occurrences));
|
|
189046
189774
|
if (part.kind === "tool_result") {
|
|
189047
189775
|
markToolAggregateResolved(callId, aggregateKey, openToolAggregateKeysByCallId);
|
|
189048
189776
|
activeToolResultRun = { callId, aggregateKey };
|
|
189049
189777
|
}
|
|
189778
|
+
continue;
|
|
189779
|
+
}
|
|
189780
|
+
const reusableTagId = reuseIdentity ? tagger.getToolTag(sessionId, callId, messageId) : undefined;
|
|
189781
|
+
const reusableAccounting = reuseIdentity ? tagger.getToolTagAccounting(sessionId, callId, messageId) : undefined;
|
|
189782
|
+
let aggregate;
|
|
189783
|
+
let text = "";
|
|
189784
|
+
if (reusableTagId !== undefined && reusableAccounting !== undefined) {
|
|
189785
|
+
aggregate = {
|
|
189786
|
+
callId,
|
|
189787
|
+
tagId: reusableTagId,
|
|
189788
|
+
identityReusable: true,
|
|
189789
|
+
occurrences: [{ message, part, kind: part.kind }],
|
|
189790
|
+
maxByteSize: reusableAccounting.byteSize,
|
|
189791
|
+
maxTokenCount: reusableAccounting.tokenCount ?? 0,
|
|
189792
|
+
toolName: null,
|
|
189793
|
+
inputByteSize: reusableAccounting.inputByteSize,
|
|
189794
|
+
inputTokenCount: reusableAccounting.inputTokenCount
|
|
189795
|
+
};
|
|
189796
|
+
if (part.kind === "tool_result") {
|
|
189797
|
+
text = part.getText() ?? "";
|
|
189798
|
+
applyGrownToolResultAccounting({
|
|
189799
|
+
db,
|
|
189800
|
+
sessionId,
|
|
189801
|
+
tagger,
|
|
189802
|
+
aggregate,
|
|
189803
|
+
byteSize: getToolPartByteSize(part, text),
|
|
189804
|
+
part,
|
|
189805
|
+
text,
|
|
189806
|
+
timing,
|
|
189807
|
+
tokenCache: options.toolTokenCache,
|
|
189808
|
+
tokenCacheKey: aggregateKey
|
|
189809
|
+
});
|
|
189810
|
+
}
|
|
189811
|
+
if (timing)
|
|
189812
|
+
timing.identity += performance.now() - identityStart;
|
|
189050
189813
|
} else {
|
|
189051
|
-
const
|
|
189052
|
-
|
|
189053
|
-
const
|
|
189054
|
-
const
|
|
189814
|
+
const accounting = readAggregateToolAccounting(part, timing, options.toolTokenCache, aggregateKey);
|
|
189815
|
+
text = accounting.text;
|
|
189816
|
+
const outputByteSize = part.kind === "tool_result" ? accounting.byteSize : 0;
|
|
189817
|
+
const outputTokenCount = part.kind === "tool_result" ? accounting.tokenCount : 0;
|
|
189818
|
+
const firstInputTokenCount = part.kind === "tool_use" ? accounting.inputTokenCount : 0;
|
|
189819
|
+
const tagId = tagger.assignToolTag(sessionId, callId, messageId, outputByteSize, db, 0, accounting.toolName, accounting.inputByteSize, () => ({
|
|
189055
189820
|
tokenCount: outputTokenCount,
|
|
189056
189821
|
inputTokenCount: firstInputTokenCount,
|
|
189057
189822
|
reasoningTokenCount: null
|
|
189058
189823
|
}));
|
|
189059
|
-
const
|
|
189824
|
+
const persistedAccounting = tagger.getToolTagAccounting(sessionId, callId, messageId);
|
|
189825
|
+
aggregate = {
|
|
189060
189826
|
callId,
|
|
189061
189827
|
tagId,
|
|
189062
|
-
|
|
189063
|
-
|
|
189064
|
-
|
|
189065
|
-
|
|
189066
|
-
|
|
189067
|
-
|
|
189068
|
-
|
|
189069
|
-
maxByteSize: outputByteSize,
|
|
189070
|
-
maxTokenCount: outputTokenCount,
|
|
189071
|
-
toolName: meta3.toolName ?? null,
|
|
189072
|
-
inputByteSize: part.kind === "tool_use" ? meta3.inputByteSize : 0,
|
|
189073
|
-
inputTokenStored: part.kind === "tool_use" && firstInputTokenCount > 0
|
|
189828
|
+
identityReusable: false,
|
|
189829
|
+
occurrences: [{ message, part, kind: part.kind }],
|
|
189830
|
+
maxByteSize: persistedAccounting?.byteSize ?? outputByteSize,
|
|
189831
|
+
maxTokenCount: persistedAccounting?.tokenCount ?? outputTokenCount,
|
|
189832
|
+
toolName: accounting.toolName,
|
|
189833
|
+
inputByteSize: persistedAccounting?.inputByteSize ?? (part.kind === "tool_use" ? accounting.inputByteSize : 0),
|
|
189834
|
+
inputTokenCount: persistedAccounting?.inputTokenCount ?? (part.kind === "tool_use" ? firstInputTokenCount : null)
|
|
189074
189835
|
};
|
|
189075
|
-
toolAggregates.set(aggregateKey, aggregate);
|
|
189076
|
-
if (part.kind === "tool_use") {
|
|
189077
|
-
openToolAggregateKeysByCallId.set(callId, [...pendingKeys, aggregateKey]);
|
|
189078
|
-
}
|
|
189079
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
189080
|
-
part.setText(prependTag(tagId, text));
|
|
189081
|
-
}
|
|
189082
|
-
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
189083
189836
|
if (part.kind === "tool_result") {
|
|
189084
|
-
|
|
189085
|
-
|
|
189837
|
+
applyGrownToolResultAccounting({
|
|
189838
|
+
db,
|
|
189839
|
+
sessionId,
|
|
189840
|
+
tagger,
|
|
189841
|
+
aggregate,
|
|
189842
|
+
byteSize: accounting.byteSize,
|
|
189843
|
+
part,
|
|
189844
|
+
text,
|
|
189845
|
+
timing,
|
|
189846
|
+
knownTokenCount: accounting.tokenCount
|
|
189847
|
+
});
|
|
189086
189848
|
}
|
|
189849
|
+
syncToolAggregateAccounting(tagger, sessionId, aggregate);
|
|
189850
|
+
if (timing)
|
|
189851
|
+
timing.identity += performance.now() - identityStart;
|
|
189852
|
+
}
|
|
189853
|
+
toolAggregates.set(aggregateKey, aggregate);
|
|
189854
|
+
if (part.kind === "tool_use") {
|
|
189855
|
+
openToolAggregateKeysByCallId.set(callId, [...pendingKeys, aggregateKey]);
|
|
189856
|
+
}
|
|
189857
|
+
applyToolPrefixAndTarget({
|
|
189858
|
+
skipPrefixInjection,
|
|
189859
|
+
part,
|
|
189860
|
+
text,
|
|
189861
|
+
tagId: aggregate.tagId,
|
|
189862
|
+
aggregate,
|
|
189863
|
+
targets,
|
|
189864
|
+
timing
|
|
189865
|
+
});
|
|
189866
|
+
if (part.kind === "tool_result") {
|
|
189867
|
+
markToolAggregateResolved(callId, aggregateKey, openToolAggregateKeysByCallId);
|
|
189868
|
+
activeToolResultRun = { callId, aggregateKey };
|
|
189087
189869
|
}
|
|
189088
189870
|
}
|
|
189089
189871
|
}
|
|
189090
189872
|
}
|
|
189873
|
+
if (timing && options.onTiming) {
|
|
189874
|
+
options.onTiming("identity", timing.identity);
|
|
189875
|
+
options.onTiming("prefix", timing.prefix);
|
|
189876
|
+
options.onTiming("targets", timing.targets);
|
|
189877
|
+
options.onTiming("tokenCounting", timing.tokenCounting);
|
|
189878
|
+
}
|
|
189091
189879
|
return { targets };
|
|
189092
189880
|
}
|
|
189881
|
+
function syncToolAggregateAccounting(tagger, sessionId, aggregate) {
|
|
189882
|
+
tagger.setToolTagAccounting(sessionId, aggregate.tagId, {
|
|
189883
|
+
byteSize: aggregate.maxByteSize,
|
|
189884
|
+
tokenCount: aggregate.maxTokenCount,
|
|
189885
|
+
inputByteSize: aggregate.inputByteSize,
|
|
189886
|
+
inputTokenCount: aggregate.inputTokenCount
|
|
189887
|
+
});
|
|
189888
|
+
}
|
|
189889
|
+
function applyGrownToolResultAccounting(args) {
|
|
189890
|
+
if (args.byteSize <= args.aggregate.maxByteSize)
|
|
189891
|
+
return;
|
|
189892
|
+
let tokenCount = args.knownTokenCount;
|
|
189893
|
+
if (tokenCount !== undefined && args.tokenCacheKey) {
|
|
189894
|
+
args.tokenCache?.set(args.tokenCacheKey, { text: args.text, tokenCount });
|
|
189895
|
+
}
|
|
189896
|
+
if (tokenCount === undefined) {
|
|
189897
|
+
const tokenStart = args.timing ? performance.now() : 0;
|
|
189898
|
+
tokenCount = getCachedToolPartTokenCount(args.part, args.text, args.tokenCache, args.tokenCacheKey);
|
|
189899
|
+
if (args.timing)
|
|
189900
|
+
args.timing.tokenCounting += performance.now() - tokenStart;
|
|
189901
|
+
}
|
|
189902
|
+
args.aggregate.maxByteSize = args.byteSize;
|
|
189903
|
+
args.aggregate.maxTokenCount = tokenCount;
|
|
189904
|
+
updateTagByteSize(args.db, args.sessionId, args.aggregate.tagId, args.byteSize);
|
|
189905
|
+
updateTagTokenCount(args.db, args.sessionId, args.aggregate.tagId, tokenCount);
|
|
189906
|
+
syncToolAggregateAccounting(args.tagger, args.sessionId, args.aggregate);
|
|
189907
|
+
}
|
|
189908
|
+
function readAggregateToolAccounting(part, timing, tokenCache, tokenCacheKey) {
|
|
189909
|
+
const text = part.getText() ?? "";
|
|
189910
|
+
const byteSize2 = getToolPartByteSize(part, text);
|
|
189911
|
+
const metadata = part.getToolMetadata();
|
|
189912
|
+
let tokenCount = 0;
|
|
189913
|
+
if (part.kind === "tool_result") {
|
|
189914
|
+
const tokenStart = timing ? performance.now() : 0;
|
|
189915
|
+
tokenCount = getCachedToolPartTokenCount(part, text, tokenCache, tokenCacheKey);
|
|
189916
|
+
if (timing)
|
|
189917
|
+
timing.tokenCounting += performance.now() - tokenStart;
|
|
189918
|
+
}
|
|
189919
|
+
return {
|
|
189920
|
+
text,
|
|
189921
|
+
byteSize: byteSize2,
|
|
189922
|
+
tokenCount,
|
|
189923
|
+
toolName: metadata.toolName ?? null,
|
|
189924
|
+
inputByteSize: metadata.inputByteSize,
|
|
189925
|
+
inputTokenCount: metadata.inputTokenCount
|
|
189926
|
+
};
|
|
189927
|
+
}
|
|
189928
|
+
function applyToolPrefixAndTarget(args) {
|
|
189929
|
+
if (!args.skipPrefixInjection && args.part.kind === "tool_result") {
|
|
189930
|
+
const prefixStart = args.timing ? performance.now() : 0;
|
|
189931
|
+
args.part.setText(prependTag(args.tagId, args.text));
|
|
189932
|
+
if (args.timing)
|
|
189933
|
+
args.timing.prefix += performance.now() - prefixStart;
|
|
189934
|
+
}
|
|
189935
|
+
const targetStart = args.timing ? performance.now() : 0;
|
|
189936
|
+
args.targets.set(args.tagId, buildAggregateTarget(args.tagId, args.aggregate.occurrences));
|
|
189937
|
+
if (args.timing)
|
|
189938
|
+
args.timing.targets += performance.now() - targetStart;
|
|
189939
|
+
}
|
|
189093
189940
|
function findLastUnresolvedToolAggregateKey(pendingKeys, toolAggregates) {
|
|
189094
189941
|
for (let i = pendingKeys.length - 1;i >= 0; i -= 1) {
|
|
189095
189942
|
const key = pendingKeys[i];
|
|
@@ -189140,6 +189987,15 @@ function getToolPartTokenCount(part, text) {
|
|
|
189140
189987
|
}
|
|
189141
189988
|
return 0;
|
|
189142
189989
|
}
|
|
189990
|
+
function getCachedToolPartTokenCount(part, text, cache, cacheKey2) {
|
|
189991
|
+
const cached2 = cacheKey2 ? cache?.get(cacheKey2) : undefined;
|
|
189992
|
+
if (cached2?.text === text)
|
|
189993
|
+
return cached2.tokenCount;
|
|
189994
|
+
const tokenCount = getToolPartTokenCount(part, text);
|
|
189995
|
+
if (cacheKey2)
|
|
189996
|
+
cache?.set(cacheKey2, { text, tokenCount });
|
|
189997
|
+
return tokenCount;
|
|
189998
|
+
}
|
|
189143
189999
|
function getNonTextToolResultByteSize(part) {
|
|
189144
190000
|
const raw = part.rawByteSize?.();
|
|
189145
190001
|
if (typeof raw === "number" && raw > 0)
|
|
@@ -189160,39 +190016,97 @@ function isRecord2(value) {
|
|
|
189160
190016
|
return typeof value === "object" && value !== null;
|
|
189161
190017
|
}
|
|
189162
190018
|
function tagTextPart(args) {
|
|
190019
|
+
const identityStart = args.timing ? performance.now() : 0;
|
|
189163
190020
|
const text = args.part.getText() ?? "";
|
|
189164
190021
|
const contentId = `${args.messageId}:p${args.textOrdinal}`;
|
|
189165
|
-
const
|
|
189166
|
-
|
|
189167
|
-
|
|
189168
|
-
|
|
189169
|
-
|
|
190022
|
+
const reusableTagId = args.reuseIdentity ? args.tagger.getTag(args.sessionId, contentId, "message") : undefined;
|
|
190023
|
+
if (reusableTagId !== undefined) {
|
|
190024
|
+
if (args.timing)
|
|
190025
|
+
args.timing.identity += performance.now() - identityStart;
|
|
190026
|
+
applyTextPrefixAndTarget(args, reusableTagId, text);
|
|
190027
|
+
return;
|
|
190028
|
+
}
|
|
190029
|
+
const tagId = args.tagger.assignTag(args.sessionId, contentId, "message", byteSize(text), args.db, 0, null, 0, args.entryFingerprint, () => {
|
|
190030
|
+
const tokenStart = args.timing ? performance.now() : 0;
|
|
190031
|
+
const cached2 = args.textTokenCache?.get(contentId);
|
|
190032
|
+
const tokenCount = cached2?.text === text ? cached2.tokenCount : estimateTagTextTokens(stripTagPrefix(text));
|
|
190033
|
+
if (cached2?.text !== text) {
|
|
190034
|
+
args.textTokenCache?.set(contentId, { text, tokenCount });
|
|
190035
|
+
}
|
|
190036
|
+
const counts = {
|
|
190037
|
+
tokenCount,
|
|
190038
|
+
inputTokenCount: null,
|
|
190039
|
+
reasoningTokenCount: null
|
|
190040
|
+
};
|
|
190041
|
+
if (args.timing)
|
|
190042
|
+
args.timing.tokenCounting += performance.now() - tokenStart;
|
|
190043
|
+
return counts;
|
|
190044
|
+
});
|
|
189170
190045
|
const sourceContent = stripTagPrefix(text);
|
|
189171
190046
|
if (sourceContent.trim().length > 0) {
|
|
189172
190047
|
saveSourceContent(args.db, args.sessionId, tagId, sourceContent);
|
|
189173
190048
|
}
|
|
190049
|
+
if (args.timing)
|
|
190050
|
+
args.timing.identity += performance.now() - identityStart;
|
|
190051
|
+
applyTextPrefixAndTarget(args, tagId, text);
|
|
190052
|
+
}
|
|
190053
|
+
function applyTextPrefixAndTarget(args, tagId, text) {
|
|
189174
190054
|
if (!args.skipPrefixInjection) {
|
|
190055
|
+
const prefixStart = args.timing ? performance.now() : 0;
|
|
189175
190056
|
args.part.setText(prependTag(tagId, text));
|
|
190057
|
+
if (args.timing)
|
|
190058
|
+
args.timing.prefix += performance.now() - prefixStart;
|
|
189176
190059
|
}
|
|
190060
|
+
const targetStart = args.timing ? performance.now() : 0;
|
|
189177
190061
|
args.targets.set(tagId, buildTextTarget(args.part, args.message));
|
|
190062
|
+
if (args.timing)
|
|
190063
|
+
args.timing.targets += performance.now() - targetStart;
|
|
189178
190064
|
}
|
|
189179
190065
|
function tagToolPart(args) {
|
|
190066
|
+
const identityStart = args.timing ? performance.now() : 0;
|
|
189180
190067
|
const stableId = args.part.id;
|
|
189181
190068
|
const contentId = stableId ?? `${args.messageId}:t${args.partIndex}`;
|
|
190069
|
+
const reusableTagId = args.reuseIdentity ? args.tagger.getToolTag(args.sessionId, contentId, contentId) : undefined;
|
|
190070
|
+
if (reusableTagId !== undefined) {
|
|
190071
|
+
const text2 = args.part.kind === "tool_result" ? args.part.getText() ?? "" : "";
|
|
190072
|
+
if (args.timing)
|
|
190073
|
+
args.timing.identity += performance.now() - identityStart;
|
|
190074
|
+
applySingleToolPrefixAndTarget(args, reusableTagId, text2);
|
|
190075
|
+
return;
|
|
190076
|
+
}
|
|
189182
190077
|
const text = args.part.getText() ?? "";
|
|
189183
190078
|
const toolByteSize = getToolPartByteSize(args.part, text);
|
|
189184
|
-
const toolTokenCount = getToolPartTokenCount(args.part, text);
|
|
189185
190079
|
const meta3 = args.part.getToolMetadata();
|
|
189186
|
-
const
|
|
189187
|
-
|
|
189188
|
-
|
|
189189
|
-
|
|
189190
|
-
|
|
190080
|
+
const tokenStart = args.timing ? performance.now() : 0;
|
|
190081
|
+
const toolTokenCount = getToolPartTokenCount(args.part, text);
|
|
190082
|
+
if (args.timing)
|
|
190083
|
+
args.timing.tokenCounting += performance.now() - tokenStart;
|
|
190084
|
+
const tagId = args.tagger.assignToolTag(args.sessionId, contentId, contentId, toolByteSize, args.db, 0, meta3.toolName ?? null, meta3.inputByteSize, () => {
|
|
190085
|
+
const tokenStart2 = args.timing ? performance.now() : 0;
|
|
190086
|
+
const counts = {
|
|
190087
|
+
tokenCount: toolTokenCount,
|
|
190088
|
+
inputTokenCount: meta3.inputTokenCount,
|
|
190089
|
+
reasoningTokenCount: null
|
|
190090
|
+
};
|
|
190091
|
+
if (args.timing)
|
|
190092
|
+
args.timing.tokenCounting += performance.now() - tokenStart2;
|
|
190093
|
+
return counts;
|
|
190094
|
+
});
|
|
190095
|
+
if (args.timing)
|
|
190096
|
+
args.timing.identity += performance.now() - identityStart;
|
|
190097
|
+
applySingleToolPrefixAndTarget(args, tagId, text);
|
|
190098
|
+
}
|
|
190099
|
+
function applySingleToolPrefixAndTarget(args, tagId, text) {
|
|
189191
190100
|
if (!args.skipPrefixInjection && args.part.kind === "tool_result") {
|
|
189192
|
-
const
|
|
189193
|
-
args.part.setText(
|
|
190101
|
+
const prefixStart = args.timing ? performance.now() : 0;
|
|
190102
|
+
args.part.setText(prependTag(tagId, text));
|
|
190103
|
+
if (args.timing)
|
|
190104
|
+
args.timing.prefix += performance.now() - prefixStart;
|
|
189194
190105
|
}
|
|
190106
|
+
const targetStart = args.timing ? performance.now() : 0;
|
|
189195
190107
|
args.targets.set(tagId, buildToolTarget(args.part, args.message, tagId));
|
|
190108
|
+
if (args.timing)
|
|
190109
|
+
args.timing.targets += performance.now() - targetStart;
|
|
189196
190110
|
}
|
|
189197
190111
|
function setToolContentOrText(part, content) {
|
|
189198
190112
|
try {
|
|
@@ -190472,6 +191386,7 @@ async function runAutoSearchHintForPi(args) {
|
|
|
190472
191386
|
sessionLog(sessionId, "Pi auto-search: strict entry-id resolution failed; replayed persisted decisions only");
|
|
190473
191387
|
return messages;
|
|
190474
191388
|
}
|
|
191389
|
+
await args.ensureProjectRegistered?.();
|
|
190475
191390
|
const writeNoHintAndReconcile = (reason) => {
|
|
190476
191391
|
const outcome2 = appendAutoSearchHintDecision(db, sessionId, {
|
|
190477
191392
|
messageId: userMsgId,
|
|
@@ -190619,8 +191534,17 @@ function getEntryId(entry) {
|
|
|
190619
191534
|
const id = entry.id;
|
|
190620
191535
|
return typeof id === "string" ? id : null;
|
|
190621
191536
|
}
|
|
190622
|
-
function findEntryIndex(branchEntries,
|
|
190623
|
-
return branchEntries.findIndex((entry) => getEntryId(entry) ===
|
|
191537
|
+
function findEntryIndex(branchEntries, entryId2) {
|
|
191538
|
+
return branchEntries.findIndex((entry) => getEntryId(entry) === entryId2);
|
|
191539
|
+
}
|
|
191540
|
+
|
|
191541
|
+
// src/context-perf-hooks.ts
|
|
191542
|
+
var timingObserver;
|
|
191543
|
+
function hasPiTransformTimingObserver() {
|
|
191544
|
+
return timingObserver !== undefined;
|
|
191545
|
+
}
|
|
191546
|
+
function recordPiTransformTiming(sample) {
|
|
191547
|
+
timingObserver?.(sample);
|
|
190624
191548
|
}
|
|
190625
191549
|
|
|
190626
191550
|
// src/ctx-reduce-nudge-pi.ts
|
|
@@ -191319,7 +192243,7 @@ init_logger();
|
|
|
191319
192243
|
function resolveStableId(msg, index, entryIds) {
|
|
191320
192244
|
return resolvePiStableId(msg, index, entryIds) ?? "";
|
|
191321
192245
|
}
|
|
191322
|
-
function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId) {
|
|
192246
|
+
function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId, trimMutableEntryIds = false) {
|
|
191323
192247
|
if (cutoffMessageId.length === 0)
|
|
191324
192248
|
return 0;
|
|
191325
192249
|
const effectiveCutoffId = cutoffMessageId.startsWith(SYNTH_USER_ID_PREFIX) ? cutoffMessageId.slice(SYNTH_USER_ID_PREFIX.length) : cutoffMessageId;
|
|
@@ -191386,6 +192310,10 @@ function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId) {
|
|
|
191386
192310
|
const kept = piMessages.filter((_, index) => !remove.has(index));
|
|
191387
192311
|
const removed = piMessages.length - kept.length;
|
|
191388
192312
|
piMessages.splice(0, piMessages.length, ...kept);
|
|
192313
|
+
if (trimMutableEntryIds && Array.isArray(entryIds)) {
|
|
192314
|
+
const keptIds = entryIds.filter((_, index) => !remove.has(index));
|
|
192315
|
+
entryIds.splice(0, entryIds.length, ...keptIds);
|
|
192316
|
+
}
|
|
191389
192317
|
return removed;
|
|
191390
192318
|
}
|
|
191391
192319
|
function toolPairKey(callId, assistantIndex) {
|
|
@@ -191496,6 +192424,23 @@ var EMPTY_PI_HARD_SIGNALS = {
|
|
|
191496
192424
|
cacheExpired: false,
|
|
191497
192425
|
lastResponseTime: 0
|
|
191498
192426
|
};
|
|
192427
|
+
var injectionTokenCountsBySession = new Map;
|
|
192428
|
+
function cachedInjectionTokenCounts(sessionId, m0, m1) {
|
|
192429
|
+
const cached2 = injectionTokenCountsBySession.get(sessionId);
|
|
192430
|
+
if (cached2?.m0 === m0 && cached2.m1 === m1)
|
|
192431
|
+
return cached2;
|
|
192432
|
+
const counts = {
|
|
192433
|
+
m0,
|
|
192434
|
+
m0Tokens: estimateTokens(m0),
|
|
192435
|
+
m1,
|
|
192436
|
+
m1Tokens: m1 === PI_M1_PLACEHOLDER ? 0 : estimateTokens(m1)
|
|
192437
|
+
};
|
|
192438
|
+
injectionTokenCountsBySession.set(sessionId, counts);
|
|
192439
|
+
return counts;
|
|
192440
|
+
}
|
|
192441
|
+
function clearPiInjectionTokenCountCache(sessionId) {
|
|
192442
|
+
injectionTokenCountsBySession.delete(sessionId);
|
|
192443
|
+
}
|
|
191499
192444
|
function decodeCachedM0(value) {
|
|
191500
192445
|
if (!value)
|
|
191501
192446
|
return null;
|
|
@@ -191514,6 +192459,20 @@ function getCachedBoundary(db, sessionId) {
|
|
|
191514
192459
|
const row = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS boundary FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
191515
192460
|
return typeof row?.boundary === "string" && row.boundary.length > 0 ? row.boundary : null;
|
|
191516
192461
|
}
|
|
192462
|
+
function trimPiMessagesToCachedBoundary(db, sessionId, piMessages, entryIds) {
|
|
192463
|
+
const row = db.prepare(`SELECT cached_m0_bytes AS m0, cached_m1_bytes AS m1,
|
|
192464
|
+
cached_m0_last_baseline_end_message_id AS boundary
|
|
192465
|
+
FROM session_meta WHERE session_id = ?`).get(sessionId);
|
|
192466
|
+
if (!row?.m0 || !row.m1 || typeof row.boundary !== "string")
|
|
192467
|
+
return 0;
|
|
192468
|
+
const boundary = row.boundary;
|
|
192469
|
+
if (boundary.length === 0)
|
|
192470
|
+
return 0;
|
|
192471
|
+
const boundaryIsLive = getCompartments(db, sessionId).some((compartment) => compartment.endMessageId === boundary);
|
|
192472
|
+
if (!boundaryIsLive)
|
|
192473
|
+
return 0;
|
|
192474
|
+
return trimPiMessagesToBoundary(piMessages, entryIds, boundary, true);
|
|
192475
|
+
}
|
|
191517
192476
|
function setCachedBoundary(db, sessionId, boundary) {
|
|
191518
192477
|
db.prepare("UPDATE session_meta SET cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(boundary, sessionId);
|
|
191519
192478
|
}
|
|
@@ -191583,7 +192542,7 @@ function readCurrentMarkersFromCompartments(db, state, compartments, projectDocs
|
|
|
191583
192542
|
function mustMaterializePi(state, db, currentCompartmentsOverride) {
|
|
191584
192543
|
const meta3 = getOrCreateSessionMeta(db, state.sessionId);
|
|
191585
192544
|
const currentCompartments = currentCompartmentsOverride ?? getCompartments(db, state.sessionId);
|
|
191586
|
-
const current = readCurrentMarkersFromCompartments(db, state, currentCompartments);
|
|
192545
|
+
const current = readCurrentMarkersFromCompartments(db, state, currentCompartments, meta3.cachedM0ProjectDocsHash ?? undefined);
|
|
191587
192546
|
if (!meta3.cachedM0Bytes)
|
|
191588
192547
|
return { value: true, reason: "first_render" };
|
|
191589
192548
|
if (!meta3.cachedM1Bytes)
|
|
@@ -192217,8 +193176,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
192217
193176
|
const M1_ABSOLUTE_CAP_RATIO = 0.2;
|
|
192218
193177
|
const m1AbsoluteBudget = (state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
|
|
192219
193178
|
const m1HasContent = m1 !== PI_M1_PLACEHOLDER;
|
|
192220
|
-
const m1Tokens =
|
|
192221
|
-
const m0Tokens = estimateTokens(m0);
|
|
193179
|
+
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(state.sessionId, m0, m1);
|
|
192222
193180
|
const m1OverAbsoluteCap = m1HasContent && m1Tokens > m1AbsoluteBudget;
|
|
192223
193181
|
if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1HasContent && m0Tokens >= M0_DRIFT_RATIO_FLOOR_TOKENS && m1Tokens > m0Tokens * M1_DRIFT_RATIO)) {
|
|
192224
193182
|
decision = { value: true, reason: "drift" };
|
|
@@ -196644,7 +197602,6 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196644
197602
|
const { db, sessionId, messages, isCacheBusting, stableIdByRef } = args;
|
|
196645
197603
|
const persistedIds = getStrippedPlaceholderIds(db, sessionId);
|
|
196646
197604
|
const idsToStrip = new Set(persistedIds);
|
|
196647
|
-
let discovered = 0;
|
|
196648
197605
|
const idOf = (msg, index) => {
|
|
196649
197606
|
const m = msg && typeof msg === "object" ? msg : undefined;
|
|
196650
197607
|
const carried = m ? stableIdByRef?.get(m) : undefined;
|
|
@@ -196663,15 +197620,36 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196663
197620
|
if (!id)
|
|
196664
197621
|
continue;
|
|
196665
197622
|
presentIds?.add(id);
|
|
196666
|
-
if (
|
|
196667
|
-
continue;
|
|
196668
|
-
if (!idsToStrip.has(id)) {
|
|
196669
|
-
idsToStrip.add(id);
|
|
197623
|
+
if (messageIsPlaceholderOnly(messages[i]) && !persistedIds.has(id)) {
|
|
196670
197624
|
discoveredIds.push(id);
|
|
196671
|
-
discovered++;
|
|
196672
197625
|
}
|
|
196673
197626
|
}
|
|
196674
197627
|
}
|
|
197628
|
+
const removedIds = [];
|
|
197629
|
+
if (presentIds) {
|
|
197630
|
+
for (const id of persistedIds) {
|
|
197631
|
+
if (!presentIds.has(id))
|
|
197632
|
+
removedIds.push(id);
|
|
197633
|
+
}
|
|
197634
|
+
}
|
|
197635
|
+
let discovered = 0;
|
|
197636
|
+
let pruned = 0;
|
|
197637
|
+
if (discoveredIds.length > 0 || removedIds.length > 0) {
|
|
197638
|
+
const persisted = (args.applyDelta ?? applyStrippedPlaceholderDelta)(db, sessionId, {
|
|
197639
|
+
add: discoveredIds,
|
|
197640
|
+
remove: removedIds
|
|
197641
|
+
});
|
|
197642
|
+
if (persisted) {
|
|
197643
|
+
for (const id of discoveredIds)
|
|
197644
|
+
idsToStrip.add(id);
|
|
197645
|
+
for (const id of removedIds)
|
|
197646
|
+
idsToStrip.delete(id);
|
|
197647
|
+
discovered = discoveredIds.length;
|
|
197648
|
+
pruned = removedIds.length;
|
|
197649
|
+
} else {
|
|
197650
|
+
sessionLog(sessionId, "placeholder strip: persistence failed; leaving newly discovered messages intact");
|
|
197651
|
+
}
|
|
197652
|
+
}
|
|
196675
197653
|
let removed = 0;
|
|
196676
197654
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
196677
197655
|
const id = idOf(messages[i], i);
|
|
@@ -196680,29 +197658,76 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196680
197658
|
messages.splice(i, 1);
|
|
196681
197659
|
removed++;
|
|
196682
197660
|
}
|
|
196683
|
-
let pruned = 0;
|
|
196684
|
-
if (presentIds) {
|
|
196685
|
-
const removedIds = [];
|
|
196686
|
-
for (const id of persistedIds) {
|
|
196687
|
-
if (!presentIds.has(id))
|
|
196688
|
-
removedIds.push(id);
|
|
196689
|
-
}
|
|
196690
|
-
pruned = removedIds.length;
|
|
196691
|
-
if (discoveredIds.length > 0 || removedIds.length > 0) {
|
|
196692
|
-
applyStrippedPlaceholderDelta(db, sessionId, {
|
|
196693
|
-
add: discoveredIds,
|
|
196694
|
-
remove: removedIds
|
|
196695
|
-
});
|
|
196696
|
-
}
|
|
196697
|
-
} else if (discoveredIds.length > 0) {
|
|
196698
|
-
applyStrippedPlaceholderDelta(db, sessionId, { add: discoveredIds });
|
|
196699
|
-
}
|
|
196700
197661
|
if (removed > 0 || discovered > 0 || pruned > 0) {
|
|
196701
197662
|
sessionLog(sessionId, `placeholder strip: removed=${removed} discovered=${discovered} pruned=${pruned}`);
|
|
196702
197663
|
}
|
|
196703
197664
|
return { removed, discovered };
|
|
196704
197665
|
}
|
|
196705
197666
|
|
|
197667
|
+
// src/strip-processed-images-pi.ts
|
|
197668
|
+
init_logger();
|
|
197669
|
+
function isLargeImagePart(value) {
|
|
197670
|
+
if (!value || typeof value !== "object")
|
|
197671
|
+
return false;
|
|
197672
|
+
const part = value;
|
|
197673
|
+
return part.type === "image" && typeof part.mimeType === "string" && part.mimeType.startsWith("image/") && typeof part.data === "string" && part.data.length > 200;
|
|
197674
|
+
}
|
|
197675
|
+
function stripPiProcessedImages(args) {
|
|
197676
|
+
const frozenIds = getProcessedImageStrippedIds(args.db, args.sessionId);
|
|
197677
|
+
const newlyStrippedIds = [];
|
|
197678
|
+
let hasAssistantResponse = false;
|
|
197679
|
+
if (args.detect && args.watermark > 0) {
|
|
197680
|
+
for (let i = args.messages.length - 1;i >= 0; i--) {
|
|
197681
|
+
const raw = args.messages[i];
|
|
197682
|
+
if (!raw || typeof raw !== "object")
|
|
197683
|
+
continue;
|
|
197684
|
+
const message = raw;
|
|
197685
|
+
if (message.role === "assistant") {
|
|
197686
|
+
hasAssistantResponse = true;
|
|
197687
|
+
continue;
|
|
197688
|
+
}
|
|
197689
|
+
if (message.role !== "user" && message.role !== "toolResult" || !hasAssistantResponse || !Array.isArray(message.content) || !message.content.some(isLargeImagePart)) {
|
|
197690
|
+
continue;
|
|
197691
|
+
}
|
|
197692
|
+
const id = args.stableId(raw, i);
|
|
197693
|
+
if (!id || frozenIds.has(id))
|
|
197694
|
+
continue;
|
|
197695
|
+
const maxTag = args.messageIdToMaxTag.get(id) ?? 0;
|
|
197696
|
+
if (maxTag <= args.watermark)
|
|
197697
|
+
newlyStrippedIds.push(id);
|
|
197698
|
+
}
|
|
197699
|
+
}
|
|
197700
|
+
if (newlyStrippedIds.length > 0) {
|
|
197701
|
+
const persisted = (args.addIds ?? addProcessedImageStrippedIds)(args.db, args.sessionId, newlyStrippedIds);
|
|
197702
|
+
if (persisted) {
|
|
197703
|
+
for (const id of newlyStrippedIds)
|
|
197704
|
+
frozenIds.add(id);
|
|
197705
|
+
} else {
|
|
197706
|
+
newlyStrippedIds.length = 0;
|
|
197707
|
+
sessionLog(args.sessionId, "processed-image strip: persistence failed; leaving newly detected images intact");
|
|
197708
|
+
}
|
|
197709
|
+
}
|
|
197710
|
+
let stripped = 0;
|
|
197711
|
+
for (let i = 0;i < args.messages.length; i++) {
|
|
197712
|
+
const raw = args.messages[i];
|
|
197713
|
+
if (!raw || typeof raw !== "object")
|
|
197714
|
+
continue;
|
|
197715
|
+
const id = args.stableId(raw, i);
|
|
197716
|
+
if (!id || !frozenIds.has(id))
|
|
197717
|
+
continue;
|
|
197718
|
+
const message = raw;
|
|
197719
|
+
if (!Array.isArray(message.content))
|
|
197720
|
+
continue;
|
|
197721
|
+
for (let partIndex = 0;partIndex < message.content.length; partIndex++) {
|
|
197722
|
+
if (!isLargeImagePart(message.content[partIndex]))
|
|
197723
|
+
continue;
|
|
197724
|
+
message.content[partIndex] = { type: "text", text: "" };
|
|
197725
|
+
stripped++;
|
|
197726
|
+
}
|
|
197727
|
+
}
|
|
197728
|
+
return { stripped, newlyStrippedIds };
|
|
197729
|
+
}
|
|
197730
|
+
|
|
196706
197731
|
// src/system-prompt.ts
|
|
196707
197732
|
import { createHash as createHash12 } from "node:crypto";
|
|
196708
197733
|
|
|
@@ -196723,6 +197748,7 @@ Context is managed for you entirely automatically — there's nothing to prune a
|
|
|
196723
197748
|
var CTX_NOTE_GUIDANCE = `Use \`ctx_note\` ONLY for genuinely future concerns — something to revisit much later, not work coming up in the next few turns (that's already in your active context) and not active multi-step work (use todos for that). Magic Context preserves your full context across both compaction and restarts, so an upcoming restart or "let's come back to this later" is never a reason to take a note — nothing is lost either way. Notes you do take survive compression and resurface at natural work boundaries (after commits, historian runs, todo completion).`;
|
|
196724
197749
|
var TOOL_HISTORY_GUIDANCE = `Compressed history intentionally omits tool calls and their outputs — summaries like "I edited file X" are historian records, not patterns to replicate. In the live conversation, older tool calls and their results are cleaned up to save context — you may see your own past messages referencing actions without the corresponding tool call or result visible. This is normal context management. ALWAYS use real tool calls; never simulate, fabricate, or inline tool outputs in your text. If there is no tool result message, the action did not happen. NEVER simulate, hallucinate or claim tool calls, command output, search results, file edits, or diffs in plain text as if they actually occurred.`;
|
|
196725
197750
|
var MEMORY_GUIDANCE = `Use \`ctx_memory\` for durable project knowledge: write what future sessions must know, update/archive/merge the memories you see in \`<project-memory>\` when they drift. Memories persist across sessions and every new session starts with them.
|
|
197751
|
+
Memories are grouped by category as \`#id: fact\` lines; pass the numeric id to \`ctx_memory\` actions.
|
|
196726
197752
|
**Save to memory proactively**: If you spent multiple turns finding something (a file path, a DB location, a config pattern, a workaround), save it with \`ctx_memory\` so future sessions don't repeat the search. Examples:
|
|
196727
197753
|
- Found a project's source code path after searching → \`ctx_memory(action="write", category="CONFIG_VALUES", content="OpenCode source is at ~/Work/OSS/opencode")\`
|
|
196728
197754
|
- Discovered a non-obvious build/test command → \`ctx_memory(action="write", category="PROJECT_RULES", content="Always use scripts/release.sh for releases")\`
|
|
@@ -196736,7 +197762,7 @@ Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space
|
|
|
196736
197762
|
Do not announce or narrate \`ctx_reduce\` drops — just call the tool silently. Saying "I'll drop these outputs" wastes tokens the user does not care about.
|
|
196737
197763
|
${CTX_NOTE_GUIDANCE}
|
|
196738
197764
|
${memoryGuidanceBlock(memoryEnabled)}Use \`ctx_search\` to search across project memories, indexed git commits, and this session's full conversation history (including compacted parts) from one query.
|
|
196739
|
-
Use \`ctx_expand\` to recover the raw conversation behind a
|
|
197765
|
+
Use \`ctx_expand\` to recover the raw conversation behind a summary under a \`## start-end · date · title\` heading inside \`<session-history>\` — pass the heading's start/end range when the summary is not enough (exact wording, values, error text).
|
|
196740
197766
|
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
196741
197767
|
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
196742
197768
|
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
@@ -196751,7 +197777,7 @@ NEVER drop assistant text messages unless they are exceptionally large. Your con
|
|
|
196751
197777
|
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
196752
197778
|
var BASE_INTRO_NO_REDUCE = (memoryEnabled) => `${CTX_NOTE_GUIDANCE}
|
|
196753
197779
|
${memoryGuidanceBlock(memoryEnabled)}Use \`ctx_search\` to search across project memories, indexed git commits, and this session's full conversation history (including compacted parts) from one query.
|
|
196754
|
-
Use \`ctx_expand\` to recover the raw conversation behind a
|
|
197780
|
+
Use \`ctx_expand\` to recover the raw conversation behind a summary under a \`## start-end · date · title\` heading inside \`<session-history>\` — pass the heading's start/end range when the summary is not enough (exact wording, values, error text).
|
|
196755
197781
|
**Search before asking the user**: If you can't remember or don't know something that might have been discussed before or stored in project memory, use \`ctx_search\` before asking the user. Examples:
|
|
196756
197782
|
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
196757
197783
|
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
@@ -196951,74 +197977,222 @@ function withTimeout(p, ms) {
|
|
|
196951
197977
|
}
|
|
196952
197978
|
|
|
196953
197979
|
// src/tokenize-pi-messages.ts
|
|
196954
|
-
function tokenizePiMessages(messages) {
|
|
197980
|
+
function tokenizePiMessages(messages, options) {
|
|
196955
197981
|
let conversation = 0;
|
|
196956
197982
|
let toolCall = 0;
|
|
197983
|
+
let cacheValidationMs = 0;
|
|
197984
|
+
let bpeMs = 0;
|
|
197985
|
+
const liveIds = options ? new Set : undefined;
|
|
196957
197986
|
for (const raw of messages) {
|
|
196958
197987
|
if (!raw || typeof raw !== "object")
|
|
196959
197988
|
continue;
|
|
196960
|
-
const
|
|
196961
|
-
const
|
|
196962
|
-
|
|
196963
|
-
|
|
196964
|
-
|
|
197989
|
+
const cacheValidationStart = options?.onTiming ? performance.now() : 0;
|
|
197990
|
+
const resolvedStableId = options?.stableId(raw);
|
|
197991
|
+
const stableId = resolvedStableId !== undefined && isTokenCacheSafeMessage(raw) ? resolvedStableId : undefined;
|
|
197992
|
+
const fingerprint = stableId === undefined ? null : buildTokenCacheFingerprint(raw);
|
|
197993
|
+
if (stableId !== undefined && fingerprint !== null) {
|
|
197994
|
+
liveIds?.add(stableId);
|
|
197995
|
+
const cached2 = options?.cache.get(stableId);
|
|
197996
|
+
if (cached2 && tokenCacheFingerprintsEqual(cached2.fingerprint, fingerprint)) {
|
|
197997
|
+
conversation += cached2.counts.conversation;
|
|
197998
|
+
toolCall += cached2.counts.toolCall;
|
|
197999
|
+
cacheValidationMs += performance.now() - cacheValidationStart;
|
|
196965
198000
|
continue;
|
|
196966
198001
|
}
|
|
196967
|
-
|
|
198002
|
+
}
|
|
198003
|
+
cacheValidationMs += performance.now() - cacheValidationStart;
|
|
198004
|
+
const bpeStart = options?.onTiming ? performance.now() : 0;
|
|
198005
|
+
const beforeConversation = conversation;
|
|
198006
|
+
const beforeToolCall = toolCall;
|
|
198007
|
+
try {
|
|
198008
|
+
const msg = raw;
|
|
198009
|
+
const content = msg.content;
|
|
198010
|
+
if (msg.role === "user" || msg.role === "assistant") {
|
|
198011
|
+
if (typeof content === "string") {
|
|
198012
|
+
conversation += estimateTokens(content);
|
|
198013
|
+
continue;
|
|
198014
|
+
}
|
|
198015
|
+
if (!Array.isArray(content))
|
|
198016
|
+
continue;
|
|
198017
|
+
for (const part of content) {
|
|
198018
|
+
if (!part || typeof part !== "object")
|
|
198019
|
+
continue;
|
|
198020
|
+
const p = part;
|
|
198021
|
+
switch (p.type) {
|
|
198022
|
+
case "text":
|
|
198023
|
+
if (typeof p.text === "string")
|
|
198024
|
+
conversation += estimateTokens(p.text);
|
|
198025
|
+
if (typeof p.textSignature === "string")
|
|
198026
|
+
conversation += estimateTokens(p.textSignature);
|
|
198027
|
+
break;
|
|
198028
|
+
case "thinking":
|
|
198029
|
+
if (typeof p.thinking === "string")
|
|
198030
|
+
conversation += estimateTokens(p.thinking);
|
|
198031
|
+
if (typeof p.thinkingSignature === "string")
|
|
198032
|
+
conversation += estimateTokens(p.thinkingSignature);
|
|
198033
|
+
break;
|
|
198034
|
+
case "image":
|
|
198035
|
+
conversation += 1200;
|
|
198036
|
+
break;
|
|
198037
|
+
case "toolCall":
|
|
198038
|
+
if (typeof p.name === "string")
|
|
198039
|
+
toolCall += estimateTokens(p.name);
|
|
198040
|
+
if (p.arguments !== undefined) {
|
|
198041
|
+
const s = typeof p.arguments === "string" ? p.arguments : safeJsonStringify2(p.arguments);
|
|
198042
|
+
if (s)
|
|
198043
|
+
toolCall += estimateTokens(s);
|
|
198044
|
+
}
|
|
198045
|
+
break;
|
|
198046
|
+
}
|
|
198047
|
+
}
|
|
196968
198048
|
continue;
|
|
196969
|
-
|
|
196970
|
-
|
|
198049
|
+
}
|
|
198050
|
+
if (msg.role === "toolResult") {
|
|
198051
|
+
if (typeof content === "string") {
|
|
198052
|
+
toolCall += estimateTokens(content);
|
|
196971
198053
|
continue;
|
|
196972
|
-
const p = part;
|
|
196973
|
-
switch (p.type) {
|
|
196974
|
-
case "text":
|
|
196975
|
-
if (typeof p.text === "string")
|
|
196976
|
-
conversation += estimateTokens(p.text);
|
|
196977
|
-
if (typeof p.textSignature === "string")
|
|
196978
|
-
conversation += estimateTokens(p.textSignature);
|
|
196979
|
-
break;
|
|
196980
|
-
case "thinking":
|
|
196981
|
-
if (typeof p.thinking === "string")
|
|
196982
|
-
conversation += estimateTokens(p.thinking);
|
|
196983
|
-
if (typeof p.thinkingSignature === "string")
|
|
196984
|
-
conversation += estimateTokens(p.thinkingSignature);
|
|
196985
|
-
break;
|
|
196986
|
-
case "image":
|
|
196987
|
-
conversation += 1200;
|
|
196988
|
-
break;
|
|
196989
|
-
case "toolCall":
|
|
196990
|
-
if (typeof p.name === "string")
|
|
196991
|
-
toolCall += estimateTokens(p.name);
|
|
196992
|
-
if (p.arguments !== undefined) {
|
|
196993
|
-
const s = typeof p.arguments === "string" ? p.arguments : safeJsonStringify2(p.arguments);
|
|
196994
|
-
if (s)
|
|
196995
|
-
toolCall += estimateTokens(s);
|
|
196996
|
-
}
|
|
196997
|
-
break;
|
|
196998
198054
|
}
|
|
198055
|
+
if (!Array.isArray(content))
|
|
198056
|
+
continue;
|
|
198057
|
+
for (const part of content) {
|
|
198058
|
+
if (!part || typeof part !== "object")
|
|
198059
|
+
continue;
|
|
198060
|
+
const p = part;
|
|
198061
|
+
if (p.type === "text" && typeof p.text === "string") {
|
|
198062
|
+
toolCall += estimateTokens(p.text);
|
|
198063
|
+
} else if (p.type === "image") {
|
|
198064
|
+
toolCall += 1200;
|
|
198065
|
+
}
|
|
198066
|
+
}
|
|
198067
|
+
}
|
|
198068
|
+
} finally {
|
|
198069
|
+
bpeMs += performance.now() - bpeStart;
|
|
198070
|
+
if (stableId !== undefined && fingerprint !== null) {
|
|
198071
|
+
options?.cache.set(stableId, {
|
|
198072
|
+
fingerprint,
|
|
198073
|
+
counts: {
|
|
198074
|
+
conversation: conversation - beforeConversation,
|
|
198075
|
+
toolCall: toolCall - beforeToolCall
|
|
198076
|
+
}
|
|
198077
|
+
});
|
|
198078
|
+
}
|
|
198079
|
+
}
|
|
198080
|
+
}
|
|
198081
|
+
if (options && liveIds) {
|
|
198082
|
+
const cachePruneStart = options.onTiming ? performance.now() : 0;
|
|
198083
|
+
for (const id of options.cache.keys()) {
|
|
198084
|
+
if (!liveIds.has(id))
|
|
198085
|
+
options.cache.delete(id);
|
|
198086
|
+
}
|
|
198087
|
+
options.onTiming?.("cachePrune", performance.now() - cachePruneStart);
|
|
198088
|
+
}
|
|
198089
|
+
options?.onTiming?.("cacheValidation", cacheValidationMs);
|
|
198090
|
+
options?.onTiming?.("bpe", bpeMs);
|
|
198091
|
+
return { conversation, toolCall };
|
|
198092
|
+
}
|
|
198093
|
+
function buildTokenCacheFingerprint(value) {
|
|
198094
|
+
const message = value;
|
|
198095
|
+
const role = typeof message.role === "string" ? message.role : null;
|
|
198096
|
+
const fingerprint = [role];
|
|
198097
|
+
if (role !== "user" && role !== "assistant" && role !== "toolResult") {
|
|
198098
|
+
return fingerprint;
|
|
198099
|
+
}
|
|
198100
|
+
if (typeof message.content === "string") {
|
|
198101
|
+
fingerprint.push("string", message.content);
|
|
198102
|
+
return fingerprint;
|
|
198103
|
+
}
|
|
198104
|
+
if (!Array.isArray(message.content)) {
|
|
198105
|
+
fingerprint.push("non-array");
|
|
198106
|
+
return fingerprint;
|
|
198107
|
+
}
|
|
198108
|
+
fingerprint.push("parts");
|
|
198109
|
+
for (const rawPart of message.content) {
|
|
198110
|
+
if (!rawPart || typeof rawPart !== "object")
|
|
198111
|
+
continue;
|
|
198112
|
+
const part = rawPart;
|
|
198113
|
+
if (role === "toolResult") {
|
|
198114
|
+
if (part.type === "text" && typeof part.text === "string") {
|
|
198115
|
+
fingerprint.push("text", part.text);
|
|
198116
|
+
} else if (part.type === "image") {
|
|
198117
|
+
fingerprint.push("image");
|
|
196999
198118
|
}
|
|
197000
198119
|
continue;
|
|
197001
198120
|
}
|
|
197002
|
-
|
|
197003
|
-
|
|
197004
|
-
|
|
197005
|
-
|
|
198121
|
+
switch (part.type) {
|
|
198122
|
+
case "text":
|
|
198123
|
+
fingerprint.push("text", typeof part.text === "string" ? part.text : null, typeof part.textSignature === "string" ? part.textSignature : null);
|
|
198124
|
+
break;
|
|
198125
|
+
case "thinking":
|
|
198126
|
+
fingerprint.push("thinking", typeof part.thinking === "string" ? part.thinking : null, typeof part.thinkingSignature === "string" ? part.thinkingSignature : null);
|
|
198127
|
+
break;
|
|
198128
|
+
case "image":
|
|
198129
|
+
fingerprint.push("image");
|
|
198130
|
+
break;
|
|
198131
|
+
case "toolCall": {
|
|
198132
|
+
const argumentsJson = part.arguments === undefined ? null : typeof part.arguments === "string" ? part.arguments : safeJsonStringify2(part.arguments);
|
|
198133
|
+
fingerprint.push("toolCall", typeof part.name === "string" ? part.name : null, argumentsJson);
|
|
198134
|
+
break;
|
|
197006
198135
|
}
|
|
197007
|
-
|
|
198136
|
+
}
|
|
198137
|
+
}
|
|
198138
|
+
return fingerprint;
|
|
198139
|
+
}
|
|
198140
|
+
function tokenCacheFingerprintsEqual(left, right) {
|
|
198141
|
+
if (left.length !== right.length)
|
|
198142
|
+
return false;
|
|
198143
|
+
for (let index = 0;index < left.length; index += 1) {
|
|
198144
|
+
if (left[index] !== right[index])
|
|
198145
|
+
return false;
|
|
198146
|
+
}
|
|
198147
|
+
return true;
|
|
198148
|
+
}
|
|
198149
|
+
function isTokenCacheSafeMessage(value) {
|
|
198150
|
+
const prototype = Object.getPrototypeOf(value);
|
|
198151
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
198152
|
+
return false;
|
|
198153
|
+
if ("toJSON" in value)
|
|
198154
|
+
return false;
|
|
198155
|
+
if (!isJsonVisibleDataProperty(value, "role") || !isJsonVisibleDataProperty(value, "content")) {
|
|
198156
|
+
return false;
|
|
198157
|
+
}
|
|
198158
|
+
return isPlainJsonData(value.content, new Set);
|
|
198159
|
+
}
|
|
198160
|
+
function isJsonVisibleDataProperty(value, key) {
|
|
198161
|
+
if (!(key in value))
|
|
198162
|
+
return true;
|
|
198163
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
198164
|
+
return descriptor !== undefined && descriptor.enumerable === true && "value" in descriptor;
|
|
198165
|
+
}
|
|
198166
|
+
function isPlainJsonData(value, seen) {
|
|
198167
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "undefined") {
|
|
198168
|
+
return true;
|
|
198169
|
+
}
|
|
198170
|
+
if (typeof value !== "object" || seen.has(value))
|
|
198171
|
+
return false;
|
|
198172
|
+
const prototype = Object.getPrototypeOf(value);
|
|
198173
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) {
|
|
198174
|
+
return false;
|
|
198175
|
+
}
|
|
198176
|
+
if ("toJSON" in value)
|
|
198177
|
+
return false;
|
|
198178
|
+
seen.add(value);
|
|
198179
|
+
try {
|
|
198180
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
198181
|
+
if (Array.isArray(value) && key === "length")
|
|
197008
198182
|
continue;
|
|
197009
|
-
|
|
197010
|
-
|
|
197011
|
-
|
|
197012
|
-
|
|
197013
|
-
|
|
197014
|
-
toolCall += estimateTokens(p.text);
|
|
197015
|
-
} else if (p.type === "image") {
|
|
197016
|
-
toolCall += 1200;
|
|
197017
|
-
}
|
|
198183
|
+
if (typeof key !== "string")
|
|
198184
|
+
return false;
|
|
198185
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
198186
|
+
if (!descriptor?.enumerable || !("value" in descriptor)) {
|
|
198187
|
+
return false;
|
|
197018
198188
|
}
|
|
198189
|
+
if (!isPlainJsonData(descriptor.value, seen))
|
|
198190
|
+
return false;
|
|
197019
198191
|
}
|
|
198192
|
+
return true;
|
|
198193
|
+
} finally {
|
|
198194
|
+
seen.delete(value);
|
|
197020
198195
|
}
|
|
197021
|
-
return { conversation, toolCall };
|
|
197022
198196
|
}
|
|
197023
198197
|
function safeJsonStringify2(value) {
|
|
197024
198198
|
try {
|
|
@@ -197522,6 +198696,9 @@ function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUs
|
|
|
197522
198696
|
} : { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
197523
198697
|
}
|
|
197524
198698
|
var injectM0M1PiForRun = injectM0M1Pi;
|
|
198699
|
+
var persistReasoningWatermarkForRun = updateSessionMeta;
|
|
198700
|
+
var persistStableIdSchemeForRun = updateSessionMeta;
|
|
198701
|
+
var afterFallbackAdoptionForTests;
|
|
197525
198702
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
197526
198703
|
var PI_STABLE_ID_SCHEME = 1;
|
|
197527
198704
|
var lastEmergencyNotificationAtMs = new Map;
|
|
@@ -197539,9 +198716,26 @@ var activeContextHandlerSessions = new Set;
|
|
|
197539
198716
|
var lastHeuristicsTurnIdBySession = new Map;
|
|
197540
198717
|
var firstContextPassSeenBySession = new Set;
|
|
197541
198718
|
var liveModelBySession = new Map;
|
|
198719
|
+
var taggedStableMessageIdsBySession = new Map;
|
|
198720
|
+
var taggersBySession = new Map;
|
|
198721
|
+
function recordSuccessfulTaggedMessageIds(sessionId, entryIds) {
|
|
198722
|
+
const liveRealIds = new Set;
|
|
198723
|
+
for (const entryId2 of entryIds) {
|
|
198724
|
+
if (entryId2 && !entryId2.startsWith("pi-msg-"))
|
|
198725
|
+
liveRealIds.add(entryId2);
|
|
198726
|
+
}
|
|
198727
|
+
taggedStableMessageIdsBySession.set(sessionId, liveRealIds);
|
|
198728
|
+
}
|
|
198729
|
+
var piMessageTokenCacheBySession = new Map;
|
|
198730
|
+
var piTagTextTokenCacheBySession = new Map;
|
|
198731
|
+
var piTagToolTokenCacheBySession = new Map;
|
|
198732
|
+
var piBranchProjectionBySession = new Map;
|
|
198733
|
+
var piBranchLookupByProjection = new WeakMap;
|
|
197542
198734
|
function logTransformTiming(sessionId, stage, start, extra) {
|
|
197543
|
-
const
|
|
198735
|
+
const elapsedMs = performance.now() - start;
|
|
198736
|
+
const elapsed = elapsedMs.toFixed(1);
|
|
197544
198737
|
const suffix = extra ? ` ${extra}` : "";
|
|
198738
|
+
recordPiTransformTiming({ sessionId, stage, elapsedMs, extra });
|
|
197545
198739
|
sessionLog(sessionId, `transform stage: stage=${stage} elapsed=${elapsed}ms${suffix}`);
|
|
197546
198740
|
}
|
|
197547
198741
|
function resolvePiContextModelKey(ctx) {
|
|
@@ -197558,6 +198752,35 @@ function resolvePiContextModelKey(ctx) {
|
|
|
197558
198752
|
function readPiSessionMessageById(ctx, messageId) {
|
|
197559
198753
|
return readPiSessionMessages(ctx).find((message) => message.id === messageId) ?? null;
|
|
197560
198754
|
}
|
|
198755
|
+
function convertLocatedPiUserEntry(branchEntries, messageId) {
|
|
198756
|
+
let rawOrdinal = 0;
|
|
198757
|
+
let pendingToolStart = -1;
|
|
198758
|
+
for (let index = 0;index < branchEntries.length; index += 1) {
|
|
198759
|
+
const entry = branchEntries[index];
|
|
198760
|
+
if (!entry || typeof entry !== "object")
|
|
198761
|
+
continue;
|
|
198762
|
+
const record2 = entry;
|
|
198763
|
+
if (record2.type !== "message" || !record2.message || typeof record2.message !== "object") {
|
|
198764
|
+
continue;
|
|
198765
|
+
}
|
|
198766
|
+
const role = record2.message.role;
|
|
198767
|
+
if (role === "toolResult") {
|
|
198768
|
+
if (pendingToolStart < 0)
|
|
198769
|
+
pendingToolStart = index;
|
|
198770
|
+
continue;
|
|
198771
|
+
}
|
|
198772
|
+
if (role === "assistant" && pendingToolStart >= 0)
|
|
198773
|
+
rawOrdinal += 1;
|
|
198774
|
+
rawOrdinal += 1;
|
|
198775
|
+
if (record2.id === messageId && role === "user") {
|
|
198776
|
+
const start = pendingToolStart >= 0 ? pendingToolStart : index;
|
|
198777
|
+
const converted = convertEntriesToRawMessages(branchEntries.slice(start, index + 1)).find((message) => message.id === messageId);
|
|
198778
|
+
return converted ? { ...converted, ordinal: rawOrdinal } : null;
|
|
198779
|
+
}
|
|
198780
|
+
pendingToolStart = -1;
|
|
198781
|
+
}
|
|
198782
|
+
return null;
|
|
198783
|
+
}
|
|
197561
198784
|
function signalPiHistoryRefresh(sessionId) {
|
|
197562
198785
|
historyRefreshSessions.add(sessionId);
|
|
197563
198786
|
}
|
|
@@ -197709,29 +198932,7 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197709
198932
|
return null;
|
|
197710
198933
|
}
|
|
197711
198934
|
}
|
|
197712
|
-
const
|
|
197713
|
-
const entryIdsByFingerprint = new Map;
|
|
197714
|
-
for (const entry of entries) {
|
|
197715
|
-
if (!entry || typeof entry !== "object")
|
|
197716
|
-
continue;
|
|
197717
|
-
const e = entry;
|
|
197718
|
-
if (e.type !== "message")
|
|
197719
|
-
continue;
|
|
197720
|
-
if (typeof e.id !== "string")
|
|
197721
|
-
continue;
|
|
197722
|
-
if (!e.message || typeof e.message !== "object")
|
|
197723
|
-
continue;
|
|
197724
|
-
const message = e.message;
|
|
197725
|
-
entryIdByMsgRef.set(message, e.id);
|
|
197726
|
-
const fingerprint = piMessageEntryFingerprint(e.message);
|
|
197727
|
-
if (fingerprint) {
|
|
197728
|
-
const bucket = entryIdsByFingerprint.get(fingerprint);
|
|
197729
|
-
if (bucket)
|
|
197730
|
-
bucket.push(e.id);
|
|
197731
|
-
else
|
|
197732
|
-
entryIdsByFingerprint.set(fingerprint, [e.id]);
|
|
197733
|
-
}
|
|
197734
|
-
}
|
|
198935
|
+
const { entryIdByMessageRef, entryIdsByFingerprint } = getPiBranchEntryLookup(entries);
|
|
197735
198936
|
const result = new Array(messages.length);
|
|
197736
198937
|
let resolved = 0;
|
|
197737
198938
|
let fingerprintResolved = 0;
|
|
@@ -197742,7 +198943,7 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197742
198943
|
result[i] = undefined;
|
|
197743
198944
|
continue;
|
|
197744
198945
|
}
|
|
197745
|
-
const id =
|
|
198946
|
+
const id = entryIdByMessageRef.get(msg);
|
|
197746
198947
|
if (typeof id === "string") {
|
|
197747
198948
|
result[i] = id;
|
|
197748
198949
|
resolved += 1;
|
|
@@ -197761,38 +198962,183 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197761
198962
|
}
|
|
197762
198963
|
}
|
|
197763
198964
|
if (resolved < messages.length) {
|
|
197764
|
-
log(`[magic-context][pi]${sessionId ? `[${sessionId}]` : ""} ` + `collectMessageEntryIdsByRef: resolved=${resolved}/${messages.length} ` + `(fingerprint=${fingerprintResolved}, branchEntries=${entries.length}, messageEntries=${
|
|
198965
|
+
log(`[magic-context][pi]${sessionId ? `[${sessionId}]` : ""} ` + `collectMessageEntryIdsByRef: resolved=${resolved}/${messages.length} ` + `(fingerprint=${fingerprintResolved}, branchEntries=${entries.length}, messageEntries=${entryIdByMessageRef.size}) — ` + `unmapped slots fall through to synthesized ids; boundary lookup still works ` + `for any compartment whose start/end message is among the resolved set`);
|
|
197765
198966
|
}
|
|
197766
198967
|
return result;
|
|
197767
198968
|
}
|
|
197768
|
-
function
|
|
197769
|
-
|
|
197770
|
-
|
|
197771
|
-
|
|
197772
|
-
|
|
197773
|
-
|
|
197774
|
-
|
|
197775
|
-
|
|
197776
|
-
|
|
197777
|
-
|
|
197778
|
-
|
|
197779
|
-
|
|
197780
|
-
|
|
198969
|
+
function addPiBranchEntryToLookup(lookup, entry) {
|
|
198970
|
+
if (!entry || typeof entry !== "object")
|
|
198971
|
+
return;
|
|
198972
|
+
const row = entry;
|
|
198973
|
+
if (row.type !== "message" || typeof row.id !== "string" || !row.message || typeof row.message !== "object") {
|
|
198974
|
+
return;
|
|
198975
|
+
}
|
|
198976
|
+
lookup.entryIdByMessageRef.set(row.message, row.id);
|
|
198977
|
+
const fingerprint = piMessageEntryFingerprint(row.message);
|
|
198978
|
+
if (!fingerprint)
|
|
198979
|
+
return;
|
|
198980
|
+
const bucket = lookup.entryIdsByFingerprint.get(fingerprint);
|
|
198981
|
+
if (bucket)
|
|
198982
|
+
bucket.push(row.id);
|
|
198983
|
+
else
|
|
198984
|
+
lookup.entryIdsByFingerprint.set(fingerprint, [row.id]);
|
|
198985
|
+
}
|
|
198986
|
+
function isPiContextEmitEligible(entry) {
|
|
198987
|
+
if (!entry || typeof entry !== "object")
|
|
198988
|
+
return false;
|
|
198989
|
+
const row = entry;
|
|
198990
|
+
if (typeof row.id !== "string")
|
|
198991
|
+
return false;
|
|
198992
|
+
return row.type === "message" || row.type === "custom_message" || row.type === "branch_summary" && typeof row.summary === "string" && row.summary.length > 0;
|
|
198993
|
+
}
|
|
198994
|
+
function buildPiAlignedEntryIds(entries) {
|
|
198995
|
+
let compactionIndex = -1;
|
|
198996
|
+
let firstKeptEntryId;
|
|
198997
|
+
for (let index = entries.length - 1;index >= 0; index -= 1) {
|
|
198998
|
+
const row = entries[index];
|
|
198999
|
+
if (row?.type !== "compaction")
|
|
197781
199000
|
continue;
|
|
197782
|
-
|
|
199001
|
+
compactionIndex = index;
|
|
199002
|
+
firstKeptEntryId = typeof row.firstKeptEntryId === "string" ? row.firstKeptEntryId : undefined;
|
|
199003
|
+
break;
|
|
197783
199004
|
}
|
|
197784
|
-
|
|
199005
|
+
if (compactionIndex < 0) {
|
|
199006
|
+
return entries.filter(isPiContextEmitEligible).map((entry) => entry.id);
|
|
199007
|
+
}
|
|
199008
|
+
const ids = [undefined];
|
|
199009
|
+
if (firstKeptEntryId !== undefined) {
|
|
199010
|
+
let foundFirstKept = false;
|
|
199011
|
+
for (let index = 0;index < compactionIndex; index += 1) {
|
|
199012
|
+
const entry = entries[index];
|
|
199013
|
+
if (entry?.id === firstKeptEntryId) {
|
|
199014
|
+
foundFirstKept = true;
|
|
199015
|
+
}
|
|
199016
|
+
if (foundFirstKept && isPiContextEmitEligible(entry))
|
|
199017
|
+
ids.push(entry.id);
|
|
199018
|
+
}
|
|
199019
|
+
}
|
|
199020
|
+
for (let index = compactionIndex + 1;index < entries.length; index += 1) {
|
|
199021
|
+
const entry = entries[index];
|
|
199022
|
+
if (isPiContextEmitEligible(entry))
|
|
199023
|
+
ids.push(entry.id);
|
|
199024
|
+
}
|
|
199025
|
+
return ids;
|
|
199026
|
+
}
|
|
199027
|
+
function getPiBranchEntryLookup(entries) {
|
|
199028
|
+
const cached2 = piBranchLookupByProjection.get(entries);
|
|
199029
|
+
if (cached2)
|
|
199030
|
+
return cached2;
|
|
199031
|
+
const lookup = {
|
|
199032
|
+
entryIdByMessageRef: new Map,
|
|
199033
|
+
entryIdsByFingerprint: new Map,
|
|
199034
|
+
alignedEntryIds: buildPiAlignedEntryIds(entries)
|
|
199035
|
+
};
|
|
199036
|
+
for (const entry of entries)
|
|
199037
|
+
addPiBranchEntryToLookup(lookup, entry);
|
|
199038
|
+
piBranchLookupByProjection.set(entries, lookup);
|
|
199039
|
+
return lookup;
|
|
199040
|
+
}
|
|
199041
|
+
function buildEntryIdByRefMap(branchEntries) {
|
|
199042
|
+
return branchEntries ? getPiBranchEntryLookup(branchEntries).entryIdByMessageRef : new Map;
|
|
197785
199043
|
}
|
|
197786
199044
|
function readPiBranchEntriesForContext(ctx, sessionId) {
|
|
197787
199045
|
const sm = ctx.sessionManager;
|
|
197788
|
-
|
|
197789
|
-
|
|
197790
|
-
|
|
199046
|
+
const installProjection = (leafId, entries) => {
|
|
199047
|
+
const indexById = new Map;
|
|
199048
|
+
const lookup = getPiBranchEntryLookup(entries);
|
|
199049
|
+
for (let index = 0;index < entries.length; index += 1) {
|
|
199050
|
+
const entry = entries[index];
|
|
199051
|
+
if (entry && typeof entry === "object") {
|
|
199052
|
+
const id = entry.id;
|
|
199053
|
+
if (typeof id === "string")
|
|
199054
|
+
indexById.set(id, index);
|
|
199055
|
+
}
|
|
199056
|
+
}
|
|
199057
|
+
const projection = { leafId, entries, indexById, lookup };
|
|
199058
|
+
piBranchProjectionBySession.set(sessionId, projection);
|
|
199059
|
+
piBranchLookupByProjection.set(entries, lookup);
|
|
199060
|
+
return entries;
|
|
199061
|
+
};
|
|
199062
|
+
const fallbackToBranch = () => {
|
|
199063
|
+
if (typeof sm?.getBranch !== "function")
|
|
199064
|
+
return null;
|
|
197791
199065
|
const entries = sm.getBranch.call(sm);
|
|
197792
|
-
|
|
199066
|
+
if (!Array.isArray(entries))
|
|
199067
|
+
return null;
|
|
199068
|
+
const leafId = typeof entries.at(-1)?.id === "string" ? entries.at(-1).id ?? "" : "";
|
|
199069
|
+
return leafId ? installProjection(leafId, entries) : entries;
|
|
199070
|
+
};
|
|
199071
|
+
try {
|
|
199072
|
+
if (typeof sm?.getLeafId !== "function" || typeof sm.getEntry !== "function") {
|
|
199073
|
+
return fallbackToBranch();
|
|
199074
|
+
}
|
|
199075
|
+
const leafId = sm.getLeafId.call(sm);
|
|
199076
|
+
if (leafId === null)
|
|
199077
|
+
return [];
|
|
199078
|
+
if (typeof leafId !== "string" || leafId.length === 0) {
|
|
199079
|
+
return fallbackToBranch();
|
|
199080
|
+
}
|
|
199081
|
+
const cached2 = piBranchProjectionBySession.get(sessionId);
|
|
199082
|
+
if (cached2?.leafId === leafId)
|
|
199083
|
+
return cached2.entries;
|
|
199084
|
+
const suffix = [];
|
|
199085
|
+
const seen = new Set;
|
|
199086
|
+
let cursor = leafId;
|
|
199087
|
+
let cachedAncestorIndex;
|
|
199088
|
+
while (cursor !== null) {
|
|
199089
|
+
const priorIndex = cached2?.indexById.get(cursor);
|
|
199090
|
+
if (priorIndex !== undefined) {
|
|
199091
|
+
cachedAncestorIndex = priorIndex;
|
|
199092
|
+
break;
|
|
199093
|
+
}
|
|
199094
|
+
if (seen.has(cursor))
|
|
199095
|
+
return fallbackToBranch();
|
|
199096
|
+
seen.add(cursor);
|
|
199097
|
+
const entry = sm.getEntry.call(sm, cursor);
|
|
199098
|
+
if (!entry || typeof entry !== "object")
|
|
199099
|
+
return fallbackToBranch();
|
|
199100
|
+
const row = entry;
|
|
199101
|
+
if (row.id !== cursor || row.parentId !== null && typeof row.parentId !== "string") {
|
|
199102
|
+
return fallbackToBranch();
|
|
199103
|
+
}
|
|
199104
|
+
suffix.push(entry);
|
|
199105
|
+
cursor = row.parentId;
|
|
199106
|
+
}
|
|
199107
|
+
suffix.reverse();
|
|
199108
|
+
if (cached2 && cachedAncestorIndex === cached2.entries.length - 1) {
|
|
199109
|
+
const entries2 = [...cached2.entries, ...suffix];
|
|
199110
|
+
if (suffix.some((entry) => entry?.type === "compaction")) {
|
|
199111
|
+
return installProjection(leafId, entries2);
|
|
199112
|
+
}
|
|
199113
|
+
for (let index = 0;index < suffix.length; index += 1) {
|
|
199114
|
+
const entry = suffix[index];
|
|
199115
|
+
const id = entry.id;
|
|
199116
|
+
cached2.indexById.set(id, cached2.entries.length + index);
|
|
199117
|
+
addPiBranchEntryToLookup(cached2.lookup, entry);
|
|
199118
|
+
if (isPiContextEmitEligible(entry)) {
|
|
199119
|
+
cached2.lookup.alignedEntryIds.push(entry.id);
|
|
199120
|
+
}
|
|
199121
|
+
}
|
|
199122
|
+
const projection = {
|
|
199123
|
+
leafId,
|
|
199124
|
+
entries: entries2,
|
|
199125
|
+
indexById: cached2.indexById,
|
|
199126
|
+
lookup: cached2.lookup
|
|
199127
|
+
};
|
|
199128
|
+
piBranchProjectionBySession.set(sessionId, projection);
|
|
199129
|
+
piBranchLookupByProjection.set(entries2, cached2.lookup);
|
|
199130
|
+
return entries2;
|
|
199131
|
+
}
|
|
199132
|
+
const entries = cached2 && cachedAncestorIndex !== undefined ? [...cached2.entries.slice(0, cachedAncestorIndex + 1), ...suffix] : suffix;
|
|
199133
|
+
return installProjection(leafId, entries);
|
|
197793
199134
|
} catch (error51) {
|
|
197794
|
-
sessionLog(sessionId, `Pi branch
|
|
197795
|
-
|
|
199135
|
+
sessionLog(sessionId, `Pi branch projection failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
199136
|
+
try {
|
|
199137
|
+
return fallbackToBranch();
|
|
199138
|
+
} catch (fallbackError) {
|
|
199139
|
+
sessionLog(sessionId, `Pi branch pre-read failed: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`);
|
|
199140
|
+
return null;
|
|
199141
|
+
}
|
|
197796
199142
|
}
|
|
197797
199143
|
}
|
|
197798
199144
|
function piMessageEntryFingerprint(message) {
|
|
@@ -197826,13 +199172,15 @@ function firstPiTextContent(content) {
|
|
|
197826
199172
|
}
|
|
197827
199173
|
return null;
|
|
197828
199174
|
}
|
|
197829
|
-
function buildEntryFingerprintMap(messages, resolveStableId2) {
|
|
199175
|
+
function buildEntryFingerprintMap(messages, resolveStableId2, reusableMessageIds, includeReusable = true) {
|
|
197830
199176
|
const map2 = new Map;
|
|
197831
199177
|
for (let i = 0;i < messages.length; i++) {
|
|
197832
199178
|
const msg = messages[i];
|
|
197833
199179
|
const id = resolveStableId2(msg, i);
|
|
197834
199180
|
if (!id)
|
|
197835
199181
|
continue;
|
|
199182
|
+
if (!includeReusable && reusableMessageIds?.has(id))
|
|
199183
|
+
continue;
|
|
197836
199184
|
const fp = piMessageEntryFingerprint(msg);
|
|
197837
199185
|
if (fp)
|
|
197838
199186
|
map2.set(id, fp);
|
|
@@ -197916,8 +199264,10 @@ function hasAdoptablePiFallbackMessageTags(db, sessionId, fingerprintById) {
|
|
|
197916
199264
|
return false;
|
|
197917
199265
|
}
|
|
197918
199266
|
function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {}) {
|
|
197919
|
-
const
|
|
197920
|
-
const
|
|
199267
|
+
const hasFallbackMessageTags = options.hasFallbackMessageTags === true || hasPiFallbackMessageTags(db, sessionId);
|
|
199268
|
+
const hasFallbackToolOwnerTags = options.hasFallbackToolOwnerTags === true || hasPiFallbackToolOwnerTags(db, sessionId);
|
|
199269
|
+
const shouldRunMessageMigration = hasFallbackMessageTags && hasAdoptablePiFallbackMessageTags(db, sessionId, fingerprintById);
|
|
199270
|
+
const shouldRunToolOwnerMigration = Boolean(options.messages && options.resolveStableId && hasFallbackToolOwnerTags);
|
|
197921
199271
|
if (!shouldRunMessageMigration && !shouldRunToolOwnerMigration)
|
|
197922
199272
|
return;
|
|
197923
199273
|
runImmediateTransaction(db, () => {
|
|
@@ -197970,14 +199320,13 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
|
|
|
197970
199320
|
tagger.unbindToolTag(sessionId, realOwnerId, row.callId);
|
|
197971
199321
|
}
|
|
197972
199322
|
tagger.bindToolTag(sessionId, row.callId, realOwnerId, adoption.tagNumber);
|
|
199323
|
+
const accounting = getPersistedToolTagAccounting(db, sessionId, adoption.tagNumber);
|
|
199324
|
+
if (accounting) {
|
|
199325
|
+
tagger.setToolTagAccounting(sessionId, adoption.tagNumber, accounting);
|
|
199326
|
+
}
|
|
197973
199327
|
}
|
|
197974
199328
|
}
|
|
197975
199329
|
}
|
|
197976
|
-
if (options.stampStableIdScheme !== undefined) {
|
|
197977
|
-
updateSessionMeta(db, sessionId, {
|
|
197978
|
-
piStableIdScheme: options.stampStableIdScheme
|
|
197979
|
-
});
|
|
197980
|
-
}
|
|
197981
199330
|
});
|
|
197982
199331
|
}
|
|
197983
199332
|
function registerPiContextHandler(pi, baseOptions) {
|
|
@@ -198010,12 +199359,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198010
199359
|
}
|
|
198011
199360
|
sessionIdForError = sessionId;
|
|
198012
199361
|
const projectDirectory = ctx.cwd;
|
|
199362
|
+
const fullWireMessageCount = event.messages.length;
|
|
198013
199363
|
const options = baseOptions.resolveForProject?.(projectDirectory) ?? baseOptions;
|
|
198014
199364
|
const schedulerConfig = options.scheduler ?? DEFAULT_SCHEDULER_CONFIG;
|
|
198015
199365
|
const scheduler = schedulerFor(options);
|
|
198016
199366
|
const projectIdentity = resolveProjectIdentity(projectDirectory);
|
|
198017
199367
|
updateSessionProjectTracking(sessionId, projectIdentity, options.db);
|
|
198018
199368
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
199369
|
+
const tEntryBranch = performance.now();
|
|
198019
199370
|
const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
|
|
198020
199371
|
schedulePiTransformDecisionResolve({
|
|
198021
199372
|
db: options.db,
|
|
@@ -198030,15 +199381,39 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198030
199381
|
const unregisterRaw = setRawMessageProvider(sessionId, rawMessageProvider);
|
|
198031
199382
|
rawMessageProviderUnregistersBySession.set(sessionId, unregisterRaw);
|
|
198032
199383
|
scheduleReconciliation(options.db, sessionId, readRawSessionMessages);
|
|
198033
|
-
const
|
|
199384
|
+
const branchLookup = branchEntries === null ? null : getPiBranchEntryLookup(branchEntries);
|
|
199385
|
+
const alignedEntryIds = branchLookup?.alignedEntryIds ?? null;
|
|
199386
|
+
const resolvedEntryIds = alignedEntryIds?.length === event.messages.length ? alignedEntryIds : branchEntries === null ? null : collectMessageEntryIdsByRef(ctx, event.messages, sessionId, branchEntries);
|
|
199387
|
+
const strictEntryIds = resolvedEntryIds ? [...resolvedEntryIds] : null;
|
|
199388
|
+
if (strictEntryIds && options.injection) {
|
|
199389
|
+
const removed = trimPiMessagesToCachedBoundary(options.db, sessionId, event.messages, strictEntryIds);
|
|
199390
|
+
if (removed > 0) {
|
|
199391
|
+
logTransformTiming(sessionId, "cachedBoundaryEarlyTrim", tEntryBranch, `removed=${removed}`);
|
|
199392
|
+
}
|
|
199393
|
+
}
|
|
198034
199394
|
const entryIdByRef = buildEntryIdByRefMap(branchEntries);
|
|
199395
|
+
const previouslyTaggedIds = taggedStableMessageIdsBySession.get(sessionId);
|
|
199396
|
+
const reusableMessageIds = new Set;
|
|
199397
|
+
if (strictEntryIds && previouslyTaggedIds) {
|
|
199398
|
+
for (const entryId2 of strictEntryIds) {
|
|
199399
|
+
if (entryId2 && previouslyTaggedIds.has(entryId2)) {
|
|
199400
|
+
reusableMessageIds.add(entryId2);
|
|
199401
|
+
}
|
|
199402
|
+
}
|
|
199403
|
+
}
|
|
199404
|
+
logTransformTiming(sessionId, "entryParseAndBranchResolution", tEntryBranch, `branchEntries=${branchEntries?.length ?? 0}`);
|
|
198035
199405
|
const tLastUser = performance.now();
|
|
198036
199406
|
const latestUser = findLatestUserMessageIdPi(event.messages, buildPiMessageIdByIndex(event.messages, strictEntryIds));
|
|
198037
199407
|
logTransformTiming(sessionId, "findLastUserMessageId", tLastUser);
|
|
199408
|
+
const tMessageIndexScheduling = performance.now();
|
|
198038
199409
|
if (latestUser) {
|
|
198039
|
-
|
|
199410
|
+
const located = branchEntries ? convertLocatedPiUserEntry(branchEntries, latestUser.messageId) : null;
|
|
199411
|
+
scheduleIncrementalIndex(options.db, sessionId, latestUser.messageId, located ?? ((_sessionId, messageId) => readPiSessionMessageById(ctx, messageId)));
|
|
198040
199412
|
}
|
|
198041
|
-
|
|
199413
|
+
logTransformTiming(sessionId, "messageIndexScheduling", tMessageIndexScheduling);
|
|
199414
|
+
const taggerFloor = strictEntryIds ? deriveTagLoadFloor(options.db, sessionId, strictEntryIds) : 0;
|
|
199415
|
+
tagger.initFromDb(sessionId, options.db, taggerFloor);
|
|
199416
|
+
taggersBySession.set(sessionId, tagger);
|
|
198042
199417
|
const isFirstContextPassForSession = !firstContextPassSeenBySession.has(sessionId);
|
|
198043
199418
|
firstContextPassSeenBySession.add(sessionId);
|
|
198044
199419
|
const piUsage = ctx.getContextUsage?.();
|
|
@@ -198142,7 +199517,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198142
199517
|
schedulerDecision = "defer";
|
|
198143
199518
|
}
|
|
198144
199519
|
logTransformTiming(sessionId, "schedulerAndUsage", tScheduler);
|
|
198145
|
-
const piMessageCount =
|
|
199520
|
+
const piMessageCount = fullWireMessageCount;
|
|
198146
199521
|
const looksLikeImportedSession = schedulerDecision === "defer" && usagePercentage === 0 && sessionMeta.lastResponseTime === 0 && piMessageCount >= 50;
|
|
198147
199522
|
if (looksLikeImportedSession) {
|
|
198148
199523
|
schedulerDecision = "execute";
|
|
@@ -198160,8 +199535,9 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198160
199535
|
signalPiPendingMaterialization(sessionId);
|
|
198161
199536
|
sessionLog(sessionId, `stable-id scheme cutover: stored=${storedStableIdScheme} < current=${PI_STABLE_ID_SCHEME} — forcing execute+materialize this pass`);
|
|
198162
199537
|
}
|
|
199538
|
+
const tBoundaryChecks = performance.now();
|
|
198163
199539
|
const schedulerDecisionEarly = schedulerDecision;
|
|
198164
|
-
const midTurn = isMidTurnPi(event, sessionId);
|
|
199540
|
+
const midTurn = isMidTurnPi(event, sessionId, branchEntries);
|
|
198165
199541
|
const bypassReason = detectMidTurnBypassReason({
|
|
198166
199542
|
contextUsage: { percentage: usagePercentage },
|
|
198167
199543
|
sessionMeta,
|
|
@@ -198209,6 +199585,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198209
199585
|
}
|
|
198210
199586
|
}
|
|
198211
199587
|
const isCacheBusting = historyRefreshSessions.has(sessionId);
|
|
199588
|
+
logTransformTiming(sessionId, "boundaryTriggerChecks", tBoundaryChecks);
|
|
198212
199589
|
sessionLog(sessionId, `transform: usage=${usagePercentage.toFixed(1)}% (${usageInputTokens} tokens, limit=${usageContextLimit ?? "?"}) decision=${schedulerDecision}${forceMaterialization ? " force=true" : ""}${isEmergency ? " EMERGENCY=true" : ""}${isCacheBusting ? " busting=true" : ""}`);
|
|
198213
199590
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tEmergencyRecovery);
|
|
198214
199591
|
const entryIds = strictEntryIds ?? undefined;
|
|
@@ -198217,12 +199594,15 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198217
199594
|
contextLimit: usageContextLimit,
|
|
198218
199595
|
sessionId
|
|
198219
199596
|
}) / 100)) : undefined;
|
|
199597
|
+
logTransformTiming(sessionId, "prePipelineTotal", transformStartTime);
|
|
199598
|
+
const tRunPipeline = performance.now();
|
|
198220
199599
|
const result = await runPipeline({
|
|
198221
199600
|
db: options.db,
|
|
198222
199601
|
tagger,
|
|
198223
199602
|
sessionId,
|
|
198224
199603
|
projectIdentity,
|
|
198225
199604
|
projectDirectory,
|
|
199605
|
+
sessionMeta,
|
|
198226
199606
|
messages: event.messages,
|
|
198227
199607
|
smartDrops: options.smartDrops === true,
|
|
198228
199608
|
protectedTags: options.protectedTags ?? 20,
|
|
@@ -198243,6 +199623,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198243
199623
|
} : undefined,
|
|
198244
199624
|
entryIds,
|
|
198245
199625
|
entryIdByRef,
|
|
199626
|
+
reusableMessageIds,
|
|
198246
199627
|
stableIdSchemeCutover,
|
|
198247
199628
|
schedulerDecision,
|
|
198248
199629
|
forceMaterialization: forceMaterialization || isEmergency,
|
|
@@ -198260,8 +199641,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198260
199641
|
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
198261
199642
|
isSubagent: sessionMeta.isSubagent
|
|
198262
199643
|
});
|
|
198263
|
-
|
|
198264
|
-
|
|
199644
|
+
logTransformTiming(sessionId, "runPipeline", tRunPipeline);
|
|
199645
|
+
const postPipelineStart = performance.now();
|
|
199646
|
+
const tTransformDecision = performance.now();
|
|
199647
|
+
if (strictEntryIds) {
|
|
199648
|
+
recordSuccessfulTaggedMessageIds(sessionId, strictEntryIds);
|
|
199649
|
+
}
|
|
199650
|
+
const piDecisionSnapshotNewestAssistant = result.bustedThisPass ? findNewestPiAssistantEntryId(branchEntries) : undefined;
|
|
199651
|
+
if (piDecisionSnapshotNewestAssistant !== undefined) {
|
|
198265
199652
|
recordPendingPiTransformDecision(sessionId, {
|
|
198266
199653
|
tsMs: Date.now(),
|
|
198267
199654
|
decision: schedulerDecision,
|
|
@@ -198274,6 +199661,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198274
199661
|
bustedThisPass: true
|
|
198275
199662
|
}, piDecisionSnapshotNewestAssistant);
|
|
198276
199663
|
}
|
|
199664
|
+
logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
|
|
199665
|
+
const tHistorianScheduling = performance.now();
|
|
198277
199666
|
if (options.historian) {
|
|
198278
199667
|
maybeFireHistorian({
|
|
198279
199668
|
pi,
|
|
@@ -198283,11 +199672,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198283
199672
|
historian: options.historian,
|
|
198284
199673
|
isFirstContextPassForSession,
|
|
198285
199674
|
activeTags: result.activeTags,
|
|
198286
|
-
rawMessageProvider
|
|
199675
|
+
rawMessageProvider,
|
|
199676
|
+
taggerFloor
|
|
198287
199677
|
});
|
|
198288
199678
|
}
|
|
199679
|
+
logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
|
|
198289
199680
|
const tPostTransform = performance.now();
|
|
198290
199681
|
let outputMessages = result.messages;
|
|
199682
|
+
const tNoteNudges = performance.now();
|
|
198291
199683
|
try {
|
|
198292
199684
|
outputMessages = applyNoteNudges({
|
|
198293
199685
|
sessionId,
|
|
@@ -198302,15 +199694,17 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198302
199694
|
} catch (err) {
|
|
198303
199695
|
sessionLog(sessionId, `note nudges failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198304
199696
|
}
|
|
199697
|
+
logTransformTiming(sessionId, "noteNudges", tNoteNudges);
|
|
199698
|
+
const tAutoSearch = performance.now();
|
|
198305
199699
|
if (options.autoSearch?.enabled) {
|
|
198306
199700
|
try {
|
|
198307
|
-
await ensureProjectRegisteredFromPiDirectory(projectDirectory, options.db);
|
|
198308
199701
|
outputMessages = await runAutoSearchHintForPi({
|
|
198309
199702
|
sessionId,
|
|
198310
199703
|
db: options.db,
|
|
198311
199704
|
messages: outputMessages,
|
|
198312
199705
|
entryIds: strictEntryIds,
|
|
198313
199706
|
entryIdByRef: result.postCommitEntryIdByRef,
|
|
199707
|
+
ensureProjectRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDirectory, options.db),
|
|
198314
199708
|
options: {
|
|
198315
199709
|
enabled: true,
|
|
198316
199710
|
scoreThreshold: options.autoSearch.scoreThreshold,
|
|
@@ -198323,6 +199717,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198323
199717
|
sessionLog(sessionId, `auto-search failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198324
199718
|
}
|
|
198325
199719
|
}
|
|
199720
|
+
logTransformTiming(sessionId, "autoSearch", tAutoSearch);
|
|
199721
|
+
const tTodoCapture = performance.now();
|
|
198326
199722
|
try {
|
|
198327
199723
|
const sessionMetaForTodo = getOrCreateSessionMeta(options.db, sessionId);
|
|
198328
199724
|
if (!sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
@@ -198339,6 +199735,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198339
199735
|
} catch (err) {
|
|
198340
199736
|
sessionLog(sessionId, `synthetic todowrite injection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198341
199737
|
}
|
|
199738
|
+
logTransformTiming(sessionId, "todoCapture", tTodoCapture);
|
|
199739
|
+
const tChannelAccounting = performance.now();
|
|
198342
199740
|
try {
|
|
198343
199741
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
198344
199742
|
if (!sessionMetaForCh1.isSubagent) {
|
|
@@ -198398,16 +199796,39 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198398
199796
|
} catch (err) {
|
|
198399
199797
|
sessionLog(sessionId, `channel1 baseline / channel2 trigger failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198400
199798
|
}
|
|
199799
|
+
logTransformTiming(sessionId, "channelNudgeAccounting", tChannelAccounting);
|
|
199800
|
+
const tWorkMetrics = performance.now();
|
|
198401
199801
|
try {
|
|
198402
199802
|
const metrics = computePiWorkMetrics(outputMessages);
|
|
198403
199803
|
setSessionWorkMetrics(options.db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
|
|
198404
199804
|
} catch (err) {
|
|
198405
199805
|
sessionLog(sessionId, `work-metrics update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198406
199806
|
}
|
|
199807
|
+
logTransformTiming(sessionId, "workMetrics", tWorkMetrics);
|
|
199808
|
+
const tStableIdSchemePersist = performance.now();
|
|
199809
|
+
if (stableIdSchemeCutover) {
|
|
199810
|
+
persistStableIdSchemeForRun(options.db, sessionId, {
|
|
199811
|
+
piStableIdScheme: PI_STABLE_ID_SCHEME
|
|
199812
|
+
});
|
|
199813
|
+
invalidateTrueRawTokenCache({
|
|
199814
|
+
sessionId,
|
|
199815
|
+
reason: "pi.stable-id-scheme.changed"
|
|
199816
|
+
});
|
|
199817
|
+
sessionLog(sessionId, `stable-id scheme cutover complete — stamped scheme=${PI_STABLE_ID_SCHEME}`);
|
|
199818
|
+
}
|
|
199819
|
+
logTransformTiming(sessionId, "stableIdSchemePersist", tStableIdSchemePersist);
|
|
198407
199820
|
logTransformTiming(sessionId, "postTransformPhase", tPostTransform);
|
|
198408
|
-
sessionLog(sessionId, `transform completed in ${(performance.now() - transformStartTime).toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
198409
199821
|
clearLastTransformErrorIfSet(options.db, sessionId);
|
|
198410
199822
|
options.maybeAutoEmbedSession?.(sessionId, projectDirectory, projectIdentity);
|
|
199823
|
+
logTransformTiming(sessionId, "postPipelineTotal", postPipelineStart);
|
|
199824
|
+
const transformElapsedMs = performance.now() - transformStartTime;
|
|
199825
|
+
recordPiTransformTiming({
|
|
199826
|
+
sessionId,
|
|
199827
|
+
stage: "total",
|
|
199828
|
+
elapsedMs: transformElapsedMs,
|
|
199829
|
+
extra: `messages=${outputMessages.length} targets=${result.targetCount}`
|
|
199830
|
+
});
|
|
199831
|
+
sessionLog(sessionId, `transform completed in ${transformElapsedMs.toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
198411
199832
|
return { messages: outputMessages };
|
|
198412
199833
|
} catch (err) {
|
|
198413
199834
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -198708,7 +200129,7 @@ function maybeFireHistorian(args) {
|
|
|
198708
200129
|
}
|
|
198709
200130
|
return snapshot;
|
|
198710
200131
|
};
|
|
198711
|
-
|
|
200132
|
+
let boundarySnapshot;
|
|
198712
200133
|
let triggered = false;
|
|
198713
200134
|
try {
|
|
198714
200135
|
if (isFirstContextPassForSession) {
|
|
@@ -198718,7 +200139,10 @@ function maybeFireHistorian(args) {
|
|
|
198718
200139
|
sessionLog(sessionId, "historian: cleared stale compartmentInProgress flag on first context pass after restart");
|
|
198719
200140
|
}
|
|
198720
200141
|
const failureState = getHistorianFailureState(db, sessionId);
|
|
198721
|
-
|
|
200142
|
+
if (failureState.failureCount > 0) {
|
|
200143
|
+
boundarySnapshot = resolveRunnablePiBoundarySnapshot();
|
|
200144
|
+
}
|
|
200145
|
+
const shouldRecoverOnFirstPass = failureState.failureCount > 0 && boundarySnapshot !== undefined && hasEligiblePiCompartmentHistory(db, sessionId, boundarySnapshot);
|
|
198722
200146
|
if (shouldRecoverOnFirstPass) {
|
|
198723
200147
|
triggered = true;
|
|
198724
200148
|
sessionLog(sessionId, `historian recovery triggered on session load after ${failureState.failureCount} failure(s)`);
|
|
@@ -198741,12 +200165,18 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
198741
200165
|
return;
|
|
198742
200166
|
}
|
|
198743
200167
|
}
|
|
198744
|
-
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit)
|
|
200168
|
+
const trigger = checkCompartmentTrigger(db, sessionId, sessionMeta, usage, 0, triggerInputs.executeThresholdPercentage, triggerInputs.triggerBudget, triggerInputs.clearReasoningAge, triggerInputs.commitClusterTrigger, args.activeTags, boundaryContextLimit, () => {
|
|
200169
|
+
const messages = provider2.readMessages();
|
|
200170
|
+
return { messages, absoluteMessageCount: messages.length };
|
|
200171
|
+
}, args.taggerFloor);
|
|
198745
200172
|
if (!trigger.shouldFire) {
|
|
198746
200173
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
198747
200174
|
try {
|
|
198748
200175
|
const overflowState = getOverflowState(db, sessionId);
|
|
198749
|
-
if (overflowState.needsEmergencyRecovery && usage.percentage < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId)
|
|
200176
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId)) {
|
|
200177
|
+
boundarySnapshot ??= resolveRunnablePiBoundarySnapshot();
|
|
200178
|
+
}
|
|
200179
|
+
if (overflowState.needsEmergencyRecovery && usage.percentage < FORCE_MATERIALIZATION_PERCENTAGE && !inFlightHistorian.has(sessionId) && boundarySnapshot !== undefined && !hasRunnableCompartmentWindow(boundarySnapshot)) {
|
|
198750
200180
|
clearEmergencyRecovery(db, sessionId);
|
|
198751
200181
|
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)`);
|
|
198752
200182
|
}
|
|
@@ -198766,7 +200196,7 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
198766
200196
|
provider: provider2,
|
|
198767
200197
|
unregister,
|
|
198768
200198
|
boundarySnapshot: selectPiHistorianRunBoundarySnapshot({
|
|
198769
|
-
resolvedBoundarySnapshot: boundarySnapshot,
|
|
200199
|
+
resolvedBoundarySnapshot: boundarySnapshot ?? trigger.boundarySnapshot ?? resolveRunnablePiBoundarySnapshot(),
|
|
198770
200200
|
triggerBoundarySnapshot: trigger.boundarySnapshot
|
|
198771
200201
|
}),
|
|
198772
200202
|
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
@@ -198789,6 +200219,44 @@ function pendingPiMarkerCoveredByRenderedBoundary(pending, injection) {
|
|
|
198789
200219
|
return true;
|
|
198790
200220
|
return boundary.ordinal !== null && pending.ordinal <= boundary.ordinal;
|
|
198791
200221
|
}
|
|
200222
|
+
function captureReasoningMutationRollback(messages) {
|
|
200223
|
+
const snapshots = [];
|
|
200224
|
+
for (const raw of messages) {
|
|
200225
|
+
if (!raw || typeof raw !== "object")
|
|
200226
|
+
continue;
|
|
200227
|
+
const message = raw;
|
|
200228
|
+
if (message.role !== "assistant" || !Array.isArray(message.content))
|
|
200229
|
+
continue;
|
|
200230
|
+
for (const rawPart of message.content) {
|
|
200231
|
+
if (!rawPart || typeof rawPart !== "object")
|
|
200232
|
+
continue;
|
|
200233
|
+
const part = rawPart;
|
|
200234
|
+
if (part.type === "thinking") {
|
|
200235
|
+
snapshots.push({
|
|
200236
|
+
part,
|
|
200237
|
+
field: "thinking",
|
|
200238
|
+
value: part.thinking,
|
|
200239
|
+
hadSignature: Object.hasOwn(part, "thinkingSignature"),
|
|
200240
|
+
signature: part.thinkingSignature
|
|
200241
|
+
});
|
|
200242
|
+
} else if (part.type === "text") {
|
|
200243
|
+
snapshots.push({ part, field: "text", value: part.text });
|
|
200244
|
+
}
|
|
200245
|
+
}
|
|
200246
|
+
}
|
|
200247
|
+
return () => {
|
|
200248
|
+
for (const snapshot of snapshots) {
|
|
200249
|
+
snapshot.part[snapshot.field] = snapshot.value;
|
|
200250
|
+
if (snapshot.field === "thinking") {
|
|
200251
|
+
if (snapshot.hadSignature) {
|
|
200252
|
+
snapshot.part.thinkingSignature = snapshot.signature;
|
|
200253
|
+
} else {
|
|
200254
|
+
delete snapshot.part.thinkingSignature;
|
|
200255
|
+
}
|
|
200256
|
+
}
|
|
200257
|
+
}
|
|
200258
|
+
};
|
|
200259
|
+
}
|
|
198792
200260
|
async function runPipeline(args) {
|
|
198793
200261
|
let executedWorkThisPass = false;
|
|
198794
200262
|
let historyWasConsumedThisPass = false;
|
|
@@ -198817,7 +200285,9 @@ async function runPipeline(args) {
|
|
|
198817
200285
|
}
|
|
198818
200286
|
logTransformTiming(args.sessionId, "injectTemporalMarkers", tTemporal);
|
|
198819
200287
|
}
|
|
200288
|
+
const tTranscriptBuild = performance.now();
|
|
198820
200289
|
const transcript = createPiTranscript(args.messages, args.sessionId, args.entryIds);
|
|
200290
|
+
logTransformTiming(args.sessionId, "transcriptBuild", tTranscriptBuild);
|
|
198821
200291
|
const workingMessages = transcript.getWorkingMessages();
|
|
198822
200292
|
const stableIdResolver = (msg, index) => resolvePiStableId(msg, index, args.entryIds, args.entryIdByRef ?? undefined);
|
|
198823
200293
|
const currentTurnId = (() => {
|
|
@@ -198825,12 +200295,11 @@ async function runPipeline(args) {
|
|
|
198825
200295
|
return findLatestUserMessageIdPi(args.messages, ids)?.messageId ?? null;
|
|
198826
200296
|
})();
|
|
198827
200297
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
198828
|
-
const
|
|
198829
|
-
const ctxReduceCallable = !sessionMetaForAvailability.isSubagent;
|
|
200298
|
+
const ctxReduceCallable = !args.sessionMeta.isSubagent;
|
|
198830
200299
|
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
198831
200300
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
198832
200301
|
const piHardSignals = args.injection ? (() => {
|
|
198833
|
-
const hardMeta =
|
|
200302
|
+
const hardMeta = args.sessionMeta;
|
|
198834
200303
|
let piTtlMs = 5 * 60 * 1000;
|
|
198835
200304
|
try {
|
|
198836
200305
|
piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
|
|
@@ -198855,28 +200324,44 @@ async function runPipeline(args) {
|
|
|
198855
200324
|
const bypassHistorianGate = args.forceMaterialization === true || m0HardFoldThisPass;
|
|
198856
200325
|
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
198857
200326
|
const shouldRunHeuristics = args.heuristics !== undefined && (!historianRunning || bypassHistorianGate) && (args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || m0HardFoldThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
|
|
198858
|
-
const
|
|
200327
|
+
const tFallbackIdentity = performance.now();
|
|
200328
|
+
const hasFallbackMessageTags = hasPiFallbackMessageTags(args.db, args.sessionId);
|
|
200329
|
+
const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
|
|
198859
200330
|
adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId, {
|
|
198860
200331
|
messages: args.messages,
|
|
198861
200332
|
resolveStableId: stableIdResolver,
|
|
198862
|
-
|
|
200333
|
+
hasFallbackMessageTags
|
|
198863
200334
|
});
|
|
198864
|
-
|
|
198865
|
-
|
|
198866
|
-
sessionId: args.sessionId,
|
|
198867
|
-
reason: "pi.stable-id-scheme.changed"
|
|
198868
|
-
});
|
|
198869
|
-
sessionLog(args.sessionId, `stable-id scheme cutover complete — stamped scheme=${PI_STABLE_ID_SCHEME}`);
|
|
198870
|
-
}
|
|
200335
|
+
logTransformTiming(args.sessionId, "fallbackIdentityAndAdoption", tFallbackIdentity);
|
|
200336
|
+
afterFallbackAdoptionForTests?.(args.stableIdSchemeCutover === true);
|
|
198871
200337
|
const tTag = performance.now();
|
|
200338
|
+
let tagTextTokenCache = piTagTextTokenCacheBySession.get(args.sessionId);
|
|
200339
|
+
if (!tagTextTokenCache) {
|
|
200340
|
+
tagTextTokenCache = new Map;
|
|
200341
|
+
piTagTextTokenCacheBySession.set(args.sessionId, tagTextTokenCache);
|
|
200342
|
+
}
|
|
200343
|
+
let tagToolTokenCache = piTagToolTokenCacheBySession.get(args.sessionId);
|
|
200344
|
+
if (!tagToolTokenCache) {
|
|
200345
|
+
tagToolTokenCache = new Map;
|
|
200346
|
+
piTagToolTokenCacheBySession.set(args.sessionId, tagToolTokenCache);
|
|
200347
|
+
}
|
|
198872
200348
|
const { targets } = tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
|
|
198873
200349
|
skipPrefixInjection: !ctxReduceCallable,
|
|
198874
|
-
entryFingerprintByMessageId
|
|
200350
|
+
entryFingerprintByMessageId,
|
|
200351
|
+
reuseMessageIds: args.reusableMessageIds,
|
|
200352
|
+
textTokenCache: tagTextTokenCache,
|
|
200353
|
+
toolTokenCache: tagToolTokenCache,
|
|
200354
|
+
onTiming: hasPiTransformTimingObserver() ? (phase, elapsedMs) => {
|
|
200355
|
+
recordPiTransformTiming({
|
|
200356
|
+
sessionId: args.sessionId,
|
|
200357
|
+
stage: `tag:${phase}`,
|
|
200358
|
+
elapsedMs
|
|
200359
|
+
});
|
|
200360
|
+
} : undefined
|
|
198875
200361
|
});
|
|
198876
200362
|
logTransformTiming(args.sessionId, "tagMessages", tTag);
|
|
198877
200363
|
try {
|
|
198878
|
-
|
|
198879
|
-
if (!sessionMeta.isSubagent) {
|
|
200364
|
+
if (!args.sessionMeta.isSubagent) {
|
|
198880
200365
|
const hasRecentCommit = detectRecentCommit(args.messages);
|
|
198881
200366
|
const hadPriorCommitState = commitSeenLastPass.has(args.sessionId);
|
|
198882
200367
|
const sawCommitLastPass = commitSeenLastPass.get(args.sessionId) ?? false;
|
|
@@ -198891,6 +200376,7 @@ async function runPipeline(args) {
|
|
|
198891
200376
|
const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
|
|
198892
200377
|
const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
|
|
198893
200378
|
const pendingOps = getPendingOps(args.db, args.sessionId);
|
|
200379
|
+
const pendingOperationTags = getTagsForPendingOperations(args.db, args.sessionId, pendingOps.map((operation) => operation.tagId), args.protectedTags, RECENT_TOOL_SKELETON_WINDOW);
|
|
198894
200380
|
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass;
|
|
198895
200381
|
const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
198896
200382
|
const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
|
|
@@ -198900,7 +200386,7 @@ async function runPipeline(args) {
|
|
|
198900
200386
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
198901
200387
|
try {
|
|
198902
200388
|
const tApplyPending = performance.now();
|
|
198903
|
-
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags,
|
|
200389
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags, pendingOperationTags, pendingOps);
|
|
198904
200390
|
if (pendingOpsDidMutate) {
|
|
198905
200391
|
droppedCount += pendingOps.length;
|
|
198906
200392
|
}
|
|
@@ -198956,6 +200442,7 @@ async function runPipeline(args) {
|
|
|
198956
200442
|
}
|
|
198957
200443
|
}
|
|
198958
200444
|
if (args.heuristics?.caveman?.enabled && !args.isSubagent) {
|
|
200445
|
+
const tCavemanReplay = performance.now();
|
|
198959
200446
|
try {
|
|
198960
200447
|
const tags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
|
|
198961
200448
|
const replayed = replayCavemanCompression(args.sessionId, args.db, targets, tags);
|
|
@@ -198965,6 +200452,7 @@ async function runPipeline(args) {
|
|
|
198965
200452
|
} catch (err) {
|
|
198966
200453
|
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
198967
200454
|
}
|
|
200455
|
+
logTransformTiming(args.sessionId, "cavemanReplay", tCavemanReplay);
|
|
198968
200456
|
}
|
|
198969
200457
|
let heuristicsExecuted = false;
|
|
198970
200458
|
let heuristicsResult = null;
|
|
@@ -199015,10 +200503,10 @@ async function runPipeline(args) {
|
|
|
199015
200503
|
}
|
|
199016
200504
|
}
|
|
199017
200505
|
if (args.reasoningClearing && shouldRunHeuristics) {
|
|
200506
|
+
const rollbackReasoning = captureReasoningMutationRollback(workingMessages);
|
|
199018
200507
|
try {
|
|
199019
200508
|
const tClearReasoning = performance.now();
|
|
199020
|
-
const
|
|
199021
|
-
const prevWatermark = meta3.clearedReasoningThroughTag ?? 0;
|
|
200509
|
+
const prevWatermark = args.sessionMeta.clearedReasoningThroughTag ?? 0;
|
|
199022
200510
|
const clearOutcome = clearOldReasoningPi({
|
|
199023
200511
|
messages: workingMessages,
|
|
199024
200512
|
messageIdToMaxTag,
|
|
@@ -199033,9 +200521,10 @@ async function runPipeline(args) {
|
|
|
199033
200521
|
});
|
|
199034
200522
|
const combinedWatermark = Math.max(clearOutcome.newWatermark, stripOutcome.newWatermark);
|
|
199035
200523
|
if (combinedWatermark > prevWatermark) {
|
|
199036
|
-
|
|
200524
|
+
persistReasoningWatermarkForRun(args.db, args.sessionId, {
|
|
199037
200525
|
clearedReasoningThroughTag: combinedWatermark
|
|
199038
200526
|
});
|
|
200527
|
+
args.sessionMeta.clearedReasoningThroughTag = combinedWatermark;
|
|
199039
200528
|
sessionLog(args.sessionId, `reasoning cleanup: cleared=${clearOutcome.cleared} inlineStripped=${stripOutcome.stripped} watermark=${prevWatermark}→${combinedWatermark}`);
|
|
199040
200529
|
}
|
|
199041
200530
|
logTransformTiming(args.sessionId, "clearOldReasoning", tClearReasoning);
|
|
@@ -199048,7 +200537,8 @@ async function runPipeline(args) {
|
|
|
199048
200537
|
executedWorkThisPass = true;
|
|
199049
200538
|
}
|
|
199050
200539
|
} catch (err) {
|
|
199051
|
-
|
|
200540
|
+
rollbackReasoning();
|
|
200541
|
+
sessionLog(args.sessionId, `reasoning clearing failed; restored original reasoning: ${err instanceof Error ? err.message : String(err)}`);
|
|
199052
200542
|
}
|
|
199053
200543
|
}
|
|
199054
200544
|
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
@@ -199057,7 +200547,7 @@ async function runPipeline(args) {
|
|
|
199057
200547
|
let autoReclaimTargetCount = 0;
|
|
199058
200548
|
let autoReclaimDidMutate = false;
|
|
199059
200549
|
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
199060
|
-
const reclaimMeta =
|
|
200550
|
+
const reclaimMeta = args.sessionMeta;
|
|
199061
200551
|
const syntheticPendingOps = buildSyntheticToolReclaimOps({
|
|
199062
200552
|
db: args.db,
|
|
199063
200553
|
sessionId: args.sessionId,
|
|
@@ -199103,13 +200593,38 @@ async function runPipeline(args) {
|
|
|
199103
200593
|
}
|
|
199104
200594
|
}
|
|
199105
200595
|
}
|
|
200596
|
+
if (args.canUseEmptySentinels) {
|
|
200597
|
+
const tProcessedImages = performance.now();
|
|
200598
|
+
try {
|
|
200599
|
+
const imageResult = stripPiProcessedImages({
|
|
200600
|
+
db: args.db,
|
|
200601
|
+
sessionId: args.sessionId,
|
|
200602
|
+
messages: workingMessages,
|
|
200603
|
+
detect: args.isCacheBusting || shouldApplyPendingOps || shouldRunHeuristics,
|
|
200604
|
+
watermark: getMaxDroppedTagNumber(args.db, args.sessionId),
|
|
200605
|
+
messageIdToMaxTag,
|
|
200606
|
+
stableId: stableIdResolver
|
|
200607
|
+
});
|
|
200608
|
+
if (imageResult.newlyStrippedIds.length > 0) {
|
|
200609
|
+
heuristicOrReasoningDidMutate = true;
|
|
200610
|
+
executedWorkThisPass = true;
|
|
200611
|
+
droppedCount += imageResult.stripped;
|
|
200612
|
+
}
|
|
200613
|
+
} catch (err) {
|
|
200614
|
+
sessionLog(args.sessionId, `processed-image strip failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
200615
|
+
}
|
|
200616
|
+
logTransformTiming(args.sessionId, "stripProcessedImages", tProcessedImages);
|
|
200617
|
+
}
|
|
200618
|
+
const tTranscriptCommit = performance.now();
|
|
199106
200619
|
transcript.commit();
|
|
200620
|
+
logTransformTiming(args.sessionId, "transcriptCommit", tTranscriptCommit);
|
|
199107
200621
|
if (toolReclaimExecutePass) {
|
|
199108
200622
|
advanceToolReclaimWatermarkToCurrentMax(args.db, args.sessionId);
|
|
199109
200623
|
}
|
|
199110
200624
|
if (autoReclaimTargetCount > 0) {
|
|
199111
200625
|
sessionLog(args.sessionId, `tool reclaim auto-drop: targets=${autoReclaimTargetCount} mutated=${autoReclaimDidMutate}`);
|
|
199112
200626
|
}
|
|
200627
|
+
const tPostCommitStableIdMaps = performance.now();
|
|
199113
200628
|
const postCommitStableIdByRef = new Map;
|
|
199114
200629
|
const postCommitEntryIdByRef = new Map;
|
|
199115
200630
|
for (let i = 0;i < args.messages.length; i++) {
|
|
@@ -199124,6 +200639,7 @@ async function runPipeline(args) {
|
|
|
199124
200639
|
postCommitEntryIdByRef.set(m, realId);
|
|
199125
200640
|
}
|
|
199126
200641
|
}
|
|
200642
|
+
logTransformTiming(args.sessionId, "postCommitStableIdMaps", tPostCommitStableIdMaps);
|
|
199127
200643
|
let injectionResult = null;
|
|
199128
200644
|
if (args.injection) {
|
|
199129
200645
|
try {
|
|
@@ -199151,6 +200667,7 @@ async function runPipeline(args) {
|
|
|
199151
200667
|
sessionLog(args.sessionId, `compartment injection failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
199152
200668
|
}
|
|
199153
200669
|
}
|
|
200670
|
+
const tDroppedPlaceholders = performance.now();
|
|
199154
200671
|
stripPiDroppedPlaceholderMessages({
|
|
199155
200672
|
db: args.db,
|
|
199156
200673
|
sessionId: args.sessionId,
|
|
@@ -199159,6 +200676,7 @@ async function runPipeline(args) {
|
|
|
199159
200676
|
stableIdByRef: postCommitStableIdByRef,
|
|
199160
200677
|
forceDiscovery: args.stableIdSchemeCutover === true
|
|
199161
200678
|
});
|
|
200679
|
+
logTransformTiming(args.sessionId, "stripDroppedPlaceholders", tDroppedPlaceholders);
|
|
199162
200680
|
const deferredHistoryDrainEligible = historyWasConsumedThisPass && materializationSatisfiedThisPass && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal) && !suppressDeferredHistoryDrain && !casLost;
|
|
199163
200681
|
let preserveDeferredMaterializationForMarkerDrain = false;
|
|
199164
200682
|
if (deferredHistoryDrainEligible) {
|
|
@@ -199215,11 +200733,28 @@ async function runPipeline(args) {
|
|
|
199215
200733
|
logTransformTiming(args.sessionId, "batchFinalize:heuristics", performance.now());
|
|
199216
200734
|
const outputMessages = transcript.getOutputMessages();
|
|
199217
200735
|
try {
|
|
199218
|
-
const
|
|
200736
|
+
const tTokenAccounting = performance.now();
|
|
200737
|
+
let tokenCache = piMessageTokenCacheBySession.get(args.sessionId);
|
|
200738
|
+
if (!tokenCache) {
|
|
200739
|
+
tokenCache = new Map;
|
|
200740
|
+
piMessageTokenCacheBySession.set(args.sessionId, tokenCache);
|
|
200741
|
+
}
|
|
200742
|
+
const counts = tokenizePiMessages(outputMessages, {
|
|
200743
|
+
cache: tokenCache,
|
|
200744
|
+
stableId: (message) => postCommitEntryIdByRef.get(message),
|
|
200745
|
+
onTiming: hasPiTransformTimingObserver() ? (phase, elapsedMs) => {
|
|
200746
|
+
recordPiTransformTiming({
|
|
200747
|
+
sessionId: args.sessionId,
|
|
200748
|
+
stage: `token:${phase}`,
|
|
200749
|
+
elapsedMs
|
|
200750
|
+
});
|
|
200751
|
+
} : undefined
|
|
200752
|
+
});
|
|
199219
200753
|
updateSessionMeta(args.db, args.sessionId, {
|
|
199220
200754
|
conversationTokens: counts.conversation,
|
|
199221
200755
|
toolCallTokens: counts.toolCall
|
|
199222
200756
|
});
|
|
200757
|
+
logTransformTiming(args.sessionId, "tokenAccounting", tTokenAccounting);
|
|
199223
200758
|
} catch (err) {
|
|
199224
200759
|
sessionLog(args.sessionId, `token accounting failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
199225
200760
|
}
|
|
@@ -199241,15 +200776,18 @@ async function runPipeline(args) {
|
|
|
199241
200776
|
emergency,
|
|
199242
200777
|
bustedThisPass,
|
|
199243
200778
|
targetCount: targets.size,
|
|
199244
|
-
reasoningWatermark:
|
|
200779
|
+
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
199245
200780
|
activeTags,
|
|
199246
200781
|
postCommitEntryIdByRef
|
|
199247
200782
|
};
|
|
199248
200783
|
}
|
|
199249
200784
|
function applyNoteNudges(args) {
|
|
199250
200785
|
const { sessionId, db, messages, projectIdentity, entryIds, entryIdByRef } = args;
|
|
200786
|
+
const tNoteIndexMaps = performance.now();
|
|
199251
200787
|
const messageIdByIndex = buildPiMessageIdByIndex(messages, entryIds, false, entryIdByRef);
|
|
199252
200788
|
const replayMessageIdByIndex = buildPiMessageIdByIndex(messages, entryIds, true, entryIdByRef);
|
|
200789
|
+
logTransformTiming(sessionId, "noteIndexMaps", tNoteIndexMaps);
|
|
200790
|
+
const tStickyReplay = performance.now();
|
|
199253
200791
|
for (const anchor of getNoteNudgeAnchors(db, sessionId)) {
|
|
199254
200792
|
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, anchor.messageId, anchor.text);
|
|
199255
200793
|
}
|
|
@@ -199258,6 +200796,7 @@ function applyNoteNudges(args) {
|
|
|
199258
200796
|
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, decision.messageId, decision.text);
|
|
199259
200797
|
}
|
|
199260
200798
|
}
|
|
200799
|
+
logTransformTiming(sessionId, "stickyReplayDecisions", tStickyReplay);
|
|
199261
200800
|
const latestUser = findLatestUserMessageIdPi(messages, messageIdByIndex);
|
|
199262
200801
|
const latestUserId = latestUser?.messageId ?? null;
|
|
199263
200802
|
const noteReadStillVisible = hasVisibleNoteReadCallPi(messages);
|
|
@@ -199326,9 +200865,9 @@ function buildPiMessageIdByIndex(messages, entryIds, includeMessageIdFallback =
|
|
|
199326
200865
|
}
|
|
199327
200866
|
continue;
|
|
199328
200867
|
}
|
|
199329
|
-
const
|
|
199330
|
-
if (typeof
|
|
199331
|
-
ids.set(index,
|
|
200868
|
+
const entryId2 = entryIds?.[index];
|
|
200869
|
+
if (typeof entryId2 === "string") {
|
|
200870
|
+
ids.set(index, entryId2);
|
|
199332
200871
|
continue;
|
|
199333
200872
|
}
|
|
199334
200873
|
if (includeMessageIdFallback) {
|
|
@@ -199402,6 +200941,17 @@ function clearContextHandlerSession(sessionId) {
|
|
|
199402
200941
|
firstContextPassSeenBySession.delete(sessionId);
|
|
199403
200942
|
commitSeenLastPass.delete(sessionId);
|
|
199404
200943
|
liveModelBySession.delete(sessionId);
|
|
200944
|
+
taggedStableMessageIdsBySession.delete(sessionId);
|
|
200945
|
+
const tagger = taggersBySession.get(sessionId);
|
|
200946
|
+
if (tagger) {
|
|
200947
|
+
tagger.cleanup(sessionId);
|
|
200948
|
+
taggersBySession.delete(sessionId);
|
|
200949
|
+
}
|
|
200950
|
+
piMessageTokenCacheBySession.delete(sessionId);
|
|
200951
|
+
piTagTextTokenCacheBySession.delete(sessionId);
|
|
200952
|
+
piTagToolTokenCacheBySession.delete(sessionId);
|
|
200953
|
+
piBranchProjectionBySession.delete(sessionId);
|
|
200954
|
+
clearPiInjectionTokenCountCache(sessionId);
|
|
199405
200955
|
clearPiChannel1State(sessionId);
|
|
199406
200956
|
lastHeuristicsTurnIdBySession.delete(sessionId);
|
|
199407
200957
|
lastSeenProjectIdentityBySession.delete(sessionId);
|
|
@@ -201837,9 +203387,8 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
201837
203387
|
const compartments = getCompartments(db, sessionId);
|
|
201838
203388
|
let historyBlockTokens = 0;
|
|
201839
203389
|
for (const c of compartments) {
|
|
201840
|
-
historyBlockTokens += estimateTokens(
|
|
203390
|
+
historyBlockTokens += estimateTokens(`## ${c.startMessage}-${c.endMessage} · ${c.title}
|
|
201841
203391
|
${c.content}
|
|
201842
|
-
</compartment>
|
|
201843
203392
|
`);
|
|
201844
203393
|
}
|
|
201845
203394
|
const budgetTokens = historyBudgetPercentage && displayContextLimit > 0 ? Math.floor(displayContextLimit * (Math.min(executeThresholdPercentage, 80) / 100) * historyBudgetPercentage) : null;
|
|
@@ -201891,9 +203440,8 @@ function computeM0BlockTokens(db, sessionId, args) {
|
|
|
201891
203440
|
try {
|
|
201892
203441
|
const compRows = db.prepare("SELECT content, title, start_message, end_message FROM compartments WHERE session_id = ?").all(sessionId);
|
|
201893
203442
|
for (const c of compRows) {
|
|
201894
|
-
compartmentTokens += estimateTokens(
|
|
203443
|
+
compartmentTokens += estimateTokens(`## ${c.start_message}-${c.end_message} · ${c.title}
|
|
201895
203444
|
${c.content}
|
|
201896
|
-
</compartment>
|
|
201897
203445
|
`);
|
|
201898
203446
|
}
|
|
201899
203447
|
} catch {}
|
|
@@ -201923,7 +203471,7 @@ function formatThresholdPercent(value) {
|
|
|
201923
203471
|
// package.json
|
|
201924
203472
|
var package_default = {
|
|
201925
203473
|
name: "@cortexkit/pi-magic-context",
|
|
201926
|
-
version: "0.
|
|
203474
|
+
version: "0.32.0",
|
|
201927
203475
|
type: "module",
|
|
201928
203476
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
201929
203477
|
main: "dist/index.js",
|
|
@@ -202902,9 +204450,9 @@ function stripTagPrefixFromAssistantMessage(message) {
|
|
|
202902
204450
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
202903
204451
|
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
202904
204452
|
|
|
202905
|
-
Older parts of this session are summarized
|
|
204453
|
+
Older parts of this session are summarized under \`## start-end · date · title\` headings inside <session-history> — e.g. \`## 120-245 · … · Fixed tagger collision\`. Each heading replaces the raw messages in that ordinal range with a summary. When the summary isn't enough — you need exact wording, a specific value, an error message, or the reasoning behind a decision — expand the range:
|
|
202906
204454
|
|
|
202907
|
-
ctx_expand(start=120, end=245) ← the
|
|
204455
|
+
ctx_expand(start=120, end=245) ← the heading's start/end range
|
|
202908
204456
|
|
|
202909
204457
|
Returns the raw transcript as [N] U:/A: lines, capped at ~15K tokens; an oversized range returns the head and tells you where to continue. Also works with ordinals from ctx_search message results — expand a window around a hit (e.g. start=N-10, end=N+5). Ranges after the last compartment are your live tail — already visible in context, not expandable.
|
|
202910
204458
|
|
|
@@ -208447,6 +209995,8 @@ var STATUS_COLOR = {
|
|
|
208447
209995
|
cancelled: "error"
|
|
208448
209996
|
};
|
|
208449
209997
|
var snapshotsBySession = new Map;
|
|
209998
|
+
var MAX_TODOWRITE_RENDER_CACHE_ENTRIES = 50;
|
|
209999
|
+
var cachedTodowriteTodosByToolCallId = new Map;
|
|
208450
210000
|
function isTodoStatus2(value) {
|
|
208451
210001
|
return TODO_STATUSES.includes(value);
|
|
208452
210002
|
}
|
|
@@ -208456,6 +210006,27 @@ function isTodoPriority2(value) {
|
|
|
208456
210006
|
function cloneTodos(todos) {
|
|
208457
210007
|
return todos.map((todo) => ({ ...todo }));
|
|
208458
210008
|
}
|
|
210009
|
+
function rememberTodowriteToolCallTodos(toolCallId, todos) {
|
|
210010
|
+
if (!toolCallId)
|
|
210011
|
+
return;
|
|
210012
|
+
cachedTodowriteTodosByToolCallId.delete(toolCallId);
|
|
210013
|
+
cachedTodowriteTodosByToolCallId.set(toolCallId, cloneTodos(todos));
|
|
210014
|
+
while (cachedTodowriteTodosByToolCallId.size > MAX_TODOWRITE_RENDER_CACHE_ENTRIES) {
|
|
210015
|
+
const oldestKey = cachedTodowriteTodosByToolCallId.keys().next().value;
|
|
210016
|
+
if (typeof oldestKey !== "string")
|
|
210017
|
+
break;
|
|
210018
|
+
cachedTodowriteTodosByToolCallId.delete(oldestKey);
|
|
210019
|
+
}
|
|
210020
|
+
}
|
|
210021
|
+
function getCachedTodowriteToolCallTodos(toolCallId) {
|
|
210022
|
+
if (!toolCallId)
|
|
210023
|
+
return null;
|
|
210024
|
+
const todos = cachedTodowriteTodosByToolCallId.get(toolCallId);
|
|
210025
|
+
return todos ? cloneTodos(todos) : null;
|
|
210026
|
+
}
|
|
210027
|
+
function clearTodowriteToolCallTodos() {
|
|
210028
|
+
cachedTodowriteTodosByToolCallId.clear();
|
|
210029
|
+
}
|
|
208459
210030
|
function parseTodos(input) {
|
|
208460
210031
|
if (!Array.isArray(input))
|
|
208461
210032
|
return null;
|
|
@@ -208592,25 +210163,27 @@ function capTodoRows(rows) {
|
|
|
208592
210163
|
hiddenCount: rows.length - visibleCount
|
|
208593
210164
|
};
|
|
208594
210165
|
}
|
|
208595
|
-
function renderTodowriteCall(args, theme) {
|
|
208596
|
-
const todos = parseTodos(args.todos) ?? [];
|
|
210166
|
+
function renderTodowriteCall(args, theme, context) {
|
|
210167
|
+
const todos = getCachedTodowriteToolCallTodos(context?.toolCallId) ?? parseTodos(args.todos) ?? [];
|
|
208597
210168
|
const active = activeTitleCount(todos);
|
|
208598
210169
|
const activeColor = active > 0 ? "warning" : "success";
|
|
208599
210170
|
const line = `${theme.fg("toolTitle", theme.bold("Todos"))} ${theme.fg("muted", "—")} ${theme.fg(activeColor, `${active} active`)}`;
|
|
208600
210171
|
return lineComponent((width) => [truncateToWidth2(line, width, "…")]);
|
|
208601
210172
|
}
|
|
208602
|
-
function renderTodowriteResult(result, theme) {
|
|
210173
|
+
function renderTodowriteResult(result, theme, context) {
|
|
208603
210174
|
const detailsTodos = result.details?.todos;
|
|
208604
210175
|
let todos = parseTodos(detailsTodos);
|
|
208605
|
-
if (todos === null && Array.isArray(result.content)) {
|
|
210176
|
+
if ((todos === null || todos.length === 0) && Array.isArray(result.content)) {
|
|
208606
210177
|
const text = result.content.find((part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string")?.text;
|
|
208607
210178
|
if (text) {
|
|
208608
210179
|
try {
|
|
208609
|
-
|
|
210180
|
+
const parsed = parseTodos(JSON.parse(text));
|
|
210181
|
+
if (parsed !== null)
|
|
210182
|
+
todos = parsed;
|
|
208610
210183
|
} catch {}
|
|
208611
210184
|
}
|
|
208612
210185
|
}
|
|
208613
|
-
const renderedTodos = todos ?? [];
|
|
210186
|
+
const renderedTodos = todos !== null && todos.length > 0 ? todos : getCachedTodowriteToolCallTodos(context?.toolCallId) ?? todos ?? [];
|
|
208614
210187
|
return lineComponent((width) => {
|
|
208615
210188
|
if (renderedTodos.length === 0)
|
|
208616
210189
|
return [theme.fg("dim", "No todos")];
|
|
@@ -208811,6 +210384,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
208811
210384
|
overlay.hideCompletedTasksFromPreviousTurn();
|
|
208812
210385
|
});
|
|
208813
210386
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
210387
|
+
clearTodowriteToolCallTodos();
|
|
208814
210388
|
const sessionId = getSessionId(ctx);
|
|
208815
210389
|
if (!sessionId)
|
|
208816
210390
|
return;
|
|
@@ -208818,6 +210392,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
208818
210392
|
overlay.disposeSession(sessionId);
|
|
208819
210393
|
});
|
|
208820
210394
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
210395
|
+
clearTodowriteToolCallTodos();
|
|
208821
210396
|
const sessionId = getSessionId(ctx);
|
|
208822
210397
|
if (!sessionId)
|
|
208823
210398
|
return;
|
|
@@ -208834,11 +210409,13 @@ function registerTodoStateLifecycle(pi, deps) {
|
|
|
208834
210409
|
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
208835
210410
|
});
|
|
208836
210411
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
210412
|
+
clearTodowriteToolCallTodos();
|
|
208837
210413
|
const sessionId = getSessionId(ctx);
|
|
208838
210414
|
if (sessionId)
|
|
208839
210415
|
clearTodoSnapshot(sessionId);
|
|
208840
210416
|
});
|
|
208841
210417
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
210418
|
+
clearTodowriteToolCallTodos();
|
|
208842
210419
|
const sessionId = getSessionId(ctx);
|
|
208843
210420
|
if (sessionId)
|
|
208844
210421
|
clearTodoSnapshot(sessionId);
|
|
@@ -208889,11 +210466,11 @@ function createTodowriteTool() {
|
|
|
208889
210466
|
}
|
|
208890
210467
|
};
|
|
208891
210468
|
},
|
|
208892
|
-
renderCall(args, theme) {
|
|
208893
|
-
return renderTodowriteCall(args, theme);
|
|
210469
|
+
renderCall(args, theme, context) {
|
|
210470
|
+
return renderTodowriteCall(args, theme, context);
|
|
208894
210471
|
},
|
|
208895
|
-
renderResult(result, _opts, theme) {
|
|
208896
|
-
return renderTodowriteResult(result, theme);
|
|
210472
|
+
renderResult(result, _opts, theme, context) {
|
|
210473
|
+
return renderTodowriteResult(result, theme, context);
|
|
208897
210474
|
}
|
|
208898
210475
|
};
|
|
208899
210476
|
}
|
|
@@ -208971,9 +210548,13 @@ function getCompatiblePiTodoCapture(todos) {
|
|
|
208971
210548
|
const normalized = normalizeTodoStateJson(todos);
|
|
208972
210549
|
if (normalized === null)
|
|
208973
210550
|
return null;
|
|
208974
|
-
|
|
210551
|
+
const parsed = parseTodos(todos);
|
|
210552
|
+
if (parsed === null)
|
|
210553
|
+
return null;
|
|
210554
|
+
return { normalized, todos: parsed };
|
|
208975
210555
|
}
|
|
208976
210556
|
function applyCompatiblePiTodoCapture(args) {
|
|
210557
|
+
rememberTodowriteToolCallTodos(args.toolCallId, args.capture.todos);
|
|
208977
210558
|
if (args.todowriteEnabled) {
|
|
208978
210559
|
setTodoSnapshot(args.sessionId, args.capture.todos);
|
|
208979
210560
|
args.todoOverlay?.update(args.sessionId);
|
|
@@ -209118,7 +210699,7 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
209118
210699
|
}
|
|
209119
210700
|
var PLUGIN_VERSION = (() => {
|
|
209120
210701
|
try {
|
|
209121
|
-
const req =
|
|
210702
|
+
const req = createRequire4(import.meta.url);
|
|
209122
210703
|
return req("../package.json").version;
|
|
209123
210704
|
} catch {
|
|
209124
210705
|
return "0.0.0";
|
|
@@ -209290,11 +210871,11 @@ async function src_default2(pi) {
|
|
|
209290
210871
|
projectIdentity: identity,
|
|
209291
210872
|
memoryEnabled: cfg.memory.enabled
|
|
209292
210873
|
}, sessionId, dir, identity, (text) => {
|
|
209293
|
-
pi
|
|
209294
|
-
|
|
209295
|
-
|
|
209296
|
-
|
|
209297
|
-
}
|
|
210874
|
+
sendCtxStatusMessage(pi, {
|
|
210875
|
+
title: "/ctx-embed",
|
|
210876
|
+
text,
|
|
210877
|
+
level: "info"
|
|
210878
|
+
});
|
|
209298
210879
|
});
|
|
209299
210880
|
}
|
|
209300
210881
|
});
|
|
@@ -209362,6 +210943,12 @@ async function src_default2(pi) {
|
|
|
209362
210943
|
todowriteEnabled
|
|
209363
210944
|
});
|
|
209364
210945
|
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)");
|
|
210946
|
+
pi.on("session_start", async (event, ctx) => {
|
|
210947
|
+
await handlePiCloneSessionStart(event, ctx, {
|
|
210948
|
+
db,
|
|
210949
|
+
signalPendingMarker: signalPiDeferredCompactionMarkerDrain
|
|
210950
|
+
});
|
|
210951
|
+
});
|
|
209365
210952
|
const readLastTodoState = (sessionId) => getOrCreateSessionMeta(db, sessionId).lastTodoState;
|
|
209366
210953
|
if (todowriteEnabled) {
|
|
209367
210954
|
registerTodoStateLifecycle(pi, { readLastTodoState });
|
|
@@ -209375,6 +210962,8 @@ async function src_default2(pi) {
|
|
|
209375
210962
|
info(bootProjectDeps.autoSearchConfig.enabled ? `registered auto-search hint (threshold=${bootProjectDeps.autoSearchConfig.scoreThreshold}, minChars=${bootProjectDeps.autoSearchConfig.minPromptChars})` : "registered auto-search hint: DISABLED (memory.auto_search.enabled=false)");
|
|
209376
210963
|
registerCtxAugCommand(pi, (ctx) => resolveCurrentProjectDeps(ctx).sidekickConfig);
|
|
209377
210964
|
info(bootProjectDeps.sidekickConfig ? `registered /ctx-aug (sidekick model=${bootProjectDeps.sidekickConfig.model})` : "registered /ctx-aug (sidekick disabled — set sidekick.disable=false and sidekick.model in config)");
|
|
210965
|
+
const statusEntryRendererAvailable = registerCtxStatusEntryRenderer(pi);
|
|
210966
|
+
info(statusEntryRendererAvailable ? "registered model-invisible ctx-status entry renderer" : "ctx-status entry renderer unavailable; using legacy visible-message fallback");
|
|
209378
210967
|
const recompRunner = new PiSubagentRunner;
|
|
209379
210968
|
const wrapupRunner = new PiSubagentRunner;
|
|
209380
210969
|
const upgradeRunner = new PiSubagentRunner;
|
|
@@ -209702,6 +211291,7 @@ ${block}` : event.systemPrompt;
|
|
|
209702
211291
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
209703
211292
|
if (event.toolName === "todowrite") {
|
|
209704
211293
|
const todoArgs = event.args;
|
|
211294
|
+
const toolCallId = typeof event.toolCallId === "string" ? event.toolCallId : undefined;
|
|
209705
211295
|
const todos = todoArgs?.todos;
|
|
209706
211296
|
const sessionMeta = Array.isArray(todos) ? getOrCreateSessionMeta(db, sessionId) : null;
|
|
209707
211297
|
capturePiTodowriteArgsIfCompatible({
|
|
@@ -209710,7 +211300,8 @@ ${block}` : event.systemPrompt;
|
|
|
209710
211300
|
todos,
|
|
209711
211301
|
todowriteEnabled,
|
|
209712
211302
|
todoOverlay,
|
|
209713
|
-
persist: Boolean(sessionMeta && !sessionMeta.isSubagent)
|
|
211303
|
+
persist: Boolean(sessionMeta && !sessionMeta.isSubagent),
|
|
211304
|
+
toolCallId
|
|
209714
211305
|
});
|
|
209715
211306
|
if (Array.isArray(todos) && todos.length > 0 && todos.every((t) => t.status === "completed" || t.status === "cancelled")) {
|
|
209716
211307
|
if (sessionMeta && !sessionMeta.isSubagent) {
|