@cortexkit/pi-magic-context 0.31.5 → 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 +2225 -701
- 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",
|
|
@@ -173479,8 +174187,11 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
173479
174187
|
provider: "local",
|
|
173480
174188
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
173481
174189
|
}).describe("Embedding provider configuration"),
|
|
173482
|
-
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).'),
|
|
173483
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."),
|
|
173484
174195
|
todowrite: exports_external.object({
|
|
173485
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."),
|
|
173486
174197
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
@@ -175198,7 +175909,7 @@ var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
|
|
|
175198
175909
|
var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
175199
175910
|
var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
|
|
175200
175911
|
var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
|
|
175201
|
-
function
|
|
175912
|
+
function runImmediate2(db, body) {
|
|
175202
175913
|
db.exec("BEGIN IMMEDIATE");
|
|
175203
175914
|
let committed = false;
|
|
175204
175915
|
try {
|
|
@@ -175231,7 +175942,7 @@ function getGitSweepCoordinatorState(db, projectPath) {
|
|
|
175231
175942
|
function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
|
|
175232
175943
|
const cooldownMs = options.cooldownMs ?? GIT_SWEEP_COOLDOWN_MS;
|
|
175233
175944
|
const leaseTtlMs = options.leaseTtlMs ?? GIT_SWEEP_LEASE_TTL_MS;
|
|
175234
|
-
return
|
|
175945
|
+
return runImmediate2(db, () => {
|
|
175235
175946
|
const now = Date.now();
|
|
175236
175947
|
const row = getGitSweepCoordinatorState(db, projectPath);
|
|
175237
175948
|
if (row?.leaseHolder && row.leaseExpiresAt !== null && row.leaseExpiresAt > now) {
|
|
@@ -175279,7 +175990,7 @@ function acquireGitSweepLease(db, projectPath, holderId, options = {}) {
|
|
|
175279
175990
|
});
|
|
175280
175991
|
}
|
|
175281
175992
|
function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LEASE_TTL_MS) {
|
|
175282
|
-
return
|
|
175993
|
+
return runImmediate2(db, () => {
|
|
175283
175994
|
const now = Date.now();
|
|
175284
175995
|
const leaseExpiresAt = now + leaseTtlMs;
|
|
175285
175996
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -175291,7 +176002,7 @@ function renewGitSweepLease(db, projectPath, holderId, leaseTtlMs = GIT_SWEEP_LE
|
|
|
175291
176002
|
});
|
|
175292
176003
|
}
|
|
175293
176004
|
function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
175294
|
-
return
|
|
176005
|
+
return runImmediate2(db, () => {
|
|
175295
176006
|
const now = Date.now();
|
|
175296
176007
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
175297
176008
|
SET lease_holder = NULL,
|
|
@@ -175304,7 +176015,7 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
|
|
|
175304
176015
|
});
|
|
175305
176016
|
}
|
|
175306
176017
|
function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
|
|
175307
|
-
return
|
|
176018
|
+
return runImmediate2(db, () => {
|
|
175308
176019
|
const now = Date.now();
|
|
175309
176020
|
const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
|
|
175310
176021
|
const result = db.prepare(`UPDATE git_sweep_coordinator
|
|
@@ -175318,7 +176029,7 @@ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWE
|
|
|
175318
176029
|
});
|
|
175319
176030
|
}
|
|
175320
176031
|
function releaseGitSweepLease(db, projectPath, holderId) {
|
|
175321
|
-
|
|
176032
|
+
runImmediate2(db, () => {
|
|
175322
176033
|
db.prepare(`UPDATE git_sweep_coordinator
|
|
175323
176034
|
SET lease_holder = NULL,
|
|
175324
176035
|
lease_expires_at = NULL
|
|
@@ -177315,7 +178026,7 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
|
|
|
177315
178026
|
const expiry = Number(expiryStr);
|
|
177316
178027
|
return Number.isFinite(expiry) && expiry >= Date.now();
|
|
177317
178028
|
}
|
|
177318
|
-
function
|
|
178029
|
+
function runImmediate3(db, body) {
|
|
177319
178030
|
db.exec("BEGIN IMMEDIATE");
|
|
177320
178031
|
let committed = false;
|
|
177321
178032
|
try {
|
|
@@ -177333,7 +178044,7 @@ function runImmediate2(db, body) {
|
|
|
177333
178044
|
}
|
|
177334
178045
|
function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177335
178046
|
const keys = rowKeys(leaseKey);
|
|
177336
|
-
return
|
|
178047
|
+
return runImmediate3(db, () => {
|
|
177337
178048
|
if (isLeaseActive(db, leaseKey)) {
|
|
177338
178049
|
const existingHolder = getLeaseHolder(db, leaseKey);
|
|
177339
178050
|
if (existingHolder && existingHolder !== holderId) {
|
|
@@ -177349,7 +178060,7 @@ function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
|
177349
178060
|
}
|
|
177350
178061
|
function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177351
178062
|
const keys = rowKeys(leaseKey);
|
|
177352
|
-
return
|
|
178063
|
+
return runImmediate3(db, () => {
|
|
177353
178064
|
if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
|
|
177354
178065
|
return false;
|
|
177355
178066
|
}
|
|
@@ -177360,7 +178071,7 @@ function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
|
177360
178071
|
});
|
|
177361
178072
|
}
|
|
177362
178073
|
function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
|
|
177363
|
-
return
|
|
178074
|
+
return runImmediate3(db, () => {
|
|
177364
178075
|
if (!peekLeaseHolderAndExpiry(db, holderId, leaseKey)) {
|
|
177365
178076
|
throw new Error("Dream lease lost before guarded write");
|
|
177366
178077
|
}
|
|
@@ -177414,7 +178125,7 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
|
|
|
177414
178125
|
}
|
|
177415
178126
|
function releaseLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
|
|
177416
178127
|
const keys = rowKeys(leaseKey);
|
|
177417
|
-
|
|
178128
|
+
runImmediate3(db, () => {
|
|
177418
178129
|
if (getLeaseHolder(db, leaseKey) !== holderId) {
|
|
177419
178130
|
return;
|
|
177420
178131
|
}
|
|
@@ -183387,6 +184098,9 @@ async function sweepGitCommits(args) {
|
|
|
183387
184098
|
}
|
|
183388
184099
|
}
|
|
183389
184100
|
|
|
184101
|
+
// src/embedding-bootstrap.ts
|
|
184102
|
+
import { statSync as statSync7 } from "node:fs";
|
|
184103
|
+
|
|
183390
184104
|
// ../plugin/src/plugin/embedding-bootstrap-helpers.ts
|
|
183391
184105
|
import { createHash as createHash11 } from "node:crypto";
|
|
183392
184106
|
init_logger();
|
|
@@ -183934,6 +184648,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
183934
184648
|
delete projectRaw.sqlite;
|
|
183935
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).");
|
|
183936
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
|
+
}
|
|
183937
184655
|
const embedding2 = projectRaw.embedding;
|
|
183938
184656
|
if (isPlainObject3(embedding2)) {
|
|
183939
184657
|
const removed = [];
|
|
@@ -184607,8 +185325,38 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
184607
185325
|
}
|
|
184608
185326
|
|
|
184609
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
|
+
}
|
|
184610
185350
|
async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
184611
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;
|
|
184612
185360
|
const detailed = loadPiConfigDetailed({ cwd: directory });
|
|
184613
185361
|
if (isConfigLoadUntrusted(detailed)) {
|
|
184614
185362
|
handleUntrustedLoad(db, projectIdentity, directory, detailed);
|
|
@@ -184619,315 +185367,65 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
184619
185367
|
gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
|
|
184620
185368
|
};
|
|
184621
185369
|
registerProjectEmbedding(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
184622
|
-
|
|
184623
|
-
|
|
184624
|
-
|
|
184625
|
-
|
|
184626
|
-
function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
|
|
184627
|
-
if (!msg || typeof msg !== "object")
|
|
184628
|
-
return;
|
|
184629
|
-
const byRef = entryIdByRef?.get(msg);
|
|
184630
|
-
if (typeof byRef === "string" && byRef.length > 0)
|
|
184631
|
-
return byRef;
|
|
184632
|
-
const positional = entryIds?.[index];
|
|
184633
|
-
if (typeof positional === "string" && positional.length > 0)
|
|
184634
|
-
return positional;
|
|
184635
|
-
const m = msg;
|
|
184636
|
-
const role = m.role ?? "unknown";
|
|
184637
|
-
return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
|
|
184638
|
-
}
|
|
184639
|
-
function isMidTurnPi(event, _sessionId) {
|
|
184640
|
-
const messages = event?.messages;
|
|
184641
|
-
if (!Array.isArray(messages))
|
|
184642
|
-
return false;
|
|
184643
|
-
let latestAssistantIndex = -1;
|
|
184644
|
-
let latestAssistant = null;
|
|
184645
|
-
for (let i = messages.length - 1;i >= 0; i--) {
|
|
184646
|
-
const msg = messages[i];
|
|
184647
|
-
if (msg !== null && typeof msg === "object") {
|
|
184648
|
-
const record2 = msg;
|
|
184649
|
-
if (record2.role === "assistant") {
|
|
184650
|
-
latestAssistantIndex = i;
|
|
184651
|
-
latestAssistant = record2;
|
|
184652
|
-
break;
|
|
184653
|
-
}
|
|
184654
|
-
}
|
|
184655
|
-
}
|
|
184656
|
-
if (latestAssistant === null)
|
|
184657
|
-
return false;
|
|
184658
|
-
if (hasRealUserAfter(messages, latestAssistantIndex))
|
|
184659
|
-
return false;
|
|
184660
|
-
if (latestAssistant.stopReason === "toolUse")
|
|
184661
|
-
return true;
|
|
184662
|
-
const toolCallIds = getToolCallIds(latestAssistant.content);
|
|
184663
|
-
if (toolCallIds.size === 0)
|
|
184664
|
-
return false;
|
|
184665
|
-
const pairedToolResultIds = new Set;
|
|
184666
|
-
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
184667
|
-
if (msg === null || typeof msg !== "object")
|
|
184668
|
-
continue;
|
|
184669
|
-
const record2 = msg;
|
|
184670
|
-
if (record2.role !== "toolResult")
|
|
184671
|
-
continue;
|
|
184672
|
-
if (typeof record2.toolCallId === "string") {
|
|
184673
|
-
pairedToolResultIds.add(record2.toolCallId);
|
|
184674
|
-
}
|
|
184675
|
-
}
|
|
184676
|
-
for (const id of toolCallIds) {
|
|
184677
|
-
if (!pairedToolResultIds.has(id))
|
|
184678
|
-
return true;
|
|
184679
|
-
}
|
|
184680
|
-
return false;
|
|
184681
|
-
}
|
|
184682
|
-
function hasRealUserAfter(messages, latestAssistantIndex) {
|
|
184683
|
-
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
184684
|
-
if (msg === null || typeof msg !== "object")
|
|
184685
|
-
continue;
|
|
184686
|
-
if (msg.role === "user")
|
|
184687
|
-
return true;
|
|
184688
|
-
}
|
|
184689
|
-
return false;
|
|
184690
|
-
}
|
|
184691
|
-
function getToolCallIds(content) {
|
|
184692
|
-
const ids = new Set;
|
|
184693
|
-
if (!Array.isArray(content))
|
|
184694
|
-
return ids;
|
|
184695
|
-
for (const item of content) {
|
|
184696
|
-
if (item === null || typeof item !== "object")
|
|
184697
|
-
continue;
|
|
184698
|
-
const record2 = item;
|
|
184699
|
-
if (record2.type === "toolCall" && typeof record2.id === "string") {
|
|
184700
|
-
ids.add(record2.id);
|
|
184701
|
-
}
|
|
184702
|
-
}
|
|
184703
|
-
return ids;
|
|
184704
|
-
}
|
|
184705
|
-
function readPiSessionMessages(ctx) {
|
|
184706
|
-
const sm = ctx.sessionManager;
|
|
184707
|
-
if (sm === undefined)
|
|
184708
|
-
return [];
|
|
184709
|
-
const getBranch = sm.getBranch;
|
|
184710
|
-
if (typeof getBranch !== "function")
|
|
184711
|
-
return [];
|
|
184712
|
-
let entries;
|
|
184713
|
-
try {
|
|
184714
|
-
entries = getBranch.call(sm);
|
|
184715
|
-
} catch {
|
|
184716
|
-
return [];
|
|
184717
|
-
}
|
|
184718
|
-
if (!Array.isArray(entries))
|
|
184719
|
-
return [];
|
|
184720
|
-
return convertEntriesToRawMessages(entries);
|
|
184721
|
-
}
|
|
184722
|
-
function findLastModelKeyFromBranch(entries) {
|
|
184723
|
-
if (!Array.isArray(entries))
|
|
184724
|
-
return;
|
|
184725
|
-
for (let i = entries.length - 1;i >= 0; i--) {
|
|
184726
|
-
const e = entries[i];
|
|
184727
|
-
if (!e || typeof e !== "object")
|
|
184728
|
-
continue;
|
|
184729
|
-
const v = e;
|
|
184730
|
-
if (v.type !== "model_change")
|
|
184731
|
-
continue;
|
|
184732
|
-
if (typeof v.provider === "string" && v.provider.length > 0 && typeof v.modelId === "string" && v.modelId.length > 0) {
|
|
184733
|
-
return `${v.provider}/${v.modelId}`;
|
|
184734
|
-
}
|
|
184735
|
-
}
|
|
184736
|
-
return;
|
|
184737
|
-
}
|
|
184738
|
-
function rawEntryVersion(entry) {
|
|
184739
|
-
const record2 = entry;
|
|
184740
|
-
const updated = record2.updatedAt ?? record2.updated_at ?? record2.timestamp;
|
|
184741
|
-
return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
|
|
184742
|
-
}
|
|
184743
|
-
function attachPiPartVersion(parts, version2) {
|
|
184744
|
-
return parts.map((part) => {
|
|
184745
|
-
if (part === null || typeof part !== "object" || Array.isArray(part))
|
|
184746
|
-
return part;
|
|
184747
|
-
try {
|
|
184748
|
-
Object.defineProperty(part, "__magicContextPartUpdatedAt", {
|
|
184749
|
-
value: version2,
|
|
184750
|
-
enumerable: false,
|
|
184751
|
-
configurable: true
|
|
184752
|
-
});
|
|
184753
|
-
} catch {}
|
|
184754
|
-
return part;
|
|
185370
|
+
const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
|
|
185371
|
+
registrationFingerprints.set(projectIdentity, {
|
|
185372
|
+
paths: fingerprintPaths,
|
|
185373
|
+
fingerprint: configFingerprint(fingerprintPaths)
|
|
184755
185374
|
});
|
|
184756
185375
|
}
|
|
184757
|
-
|
|
184758
|
-
|
|
184759
|
-
|
|
184760
|
-
|
|
184761
|
-
|
|
184762
|
-
|
|
184763
|
-
|
|
184764
|
-
|
|
184765
|
-
|
|
184766
|
-
|
|
184767
|
-
|
|
184768
|
-
|
|
184769
|
-
|
|
184770
|
-
|
|
184771
|
-
|
|
184772
|
-
|
|
184773
|
-
pendingFirstRealId = entry.id;
|
|
184774
|
-
pendingFirstRealVersion = version2;
|
|
184775
|
-
}
|
|
184776
|
-
continue;
|
|
184777
|
-
}
|
|
184778
|
-
if (role === "user") {
|
|
184779
|
-
const version2 = rawEntryVersion(entry);
|
|
184780
|
-
const parts = [
|
|
184781
|
-
...pendingToolParts,
|
|
184782
|
-
...attachPiPartVersion(synthesizeUserParts(msg), version2)
|
|
184783
|
-
];
|
|
184784
|
-
pendingToolParts = [];
|
|
184785
|
-
pendingFirstRealId = "";
|
|
184786
|
-
pendingFirstRealVersion = "";
|
|
184787
|
-
result.push({
|
|
184788
|
-
ordinal: nextOrdinal++,
|
|
184789
|
-
id: entry.id,
|
|
184790
|
-
role: "user",
|
|
184791
|
-
parts,
|
|
184792
|
-
version: version2
|
|
184793
|
-
});
|
|
184794
|
-
continue;
|
|
184795
|
-
}
|
|
184796
|
-
if (role === "assistant") {
|
|
184797
|
-
if (pendingToolParts.length > 0) {
|
|
184798
|
-
result.push({
|
|
184799
|
-
ordinal: nextOrdinal++,
|
|
184800
|
-
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
184801
|
-
role: "user",
|
|
184802
|
-
parts: pendingToolParts,
|
|
184803
|
-
version: pendingFirstRealVersion
|
|
184804
|
-
});
|
|
184805
|
-
pendingToolParts = [];
|
|
184806
|
-
pendingFirstRealId = "";
|
|
184807
|
-
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");
|
|
184808
185392
|
}
|
|
184809
|
-
const
|
|
184810
|
-
|
|
184811
|
-
|
|
184812
|
-
id: entry.id,
|
|
184813
|
-
role: "assistant",
|
|
184814
|
-
parts: attachPiPartVersion(synthesizeAssistantParts(msg), version2),
|
|
184815
|
-
version: version2
|
|
184816
|
-
});
|
|
184817
|
-
continue;
|
|
185393
|
+
const require2 = createRequire3(process.argv[1]);
|
|
185394
|
+
const resolved = require2.resolve(PI_CODING_AGENT_MODULE);
|
|
185395
|
+
return await import(pathToFileURL2(resolved).href);
|
|
184818
185396
|
}
|
|
184819
|
-
result.push({
|
|
184820
|
-
ordinal: nextOrdinal++,
|
|
184821
|
-
id: entry.id,
|
|
184822
|
-
role: typeof role === "string" ? role : "unknown",
|
|
184823
|
-
parts: [],
|
|
184824
|
-
version: rawEntryVersion(entry)
|
|
184825
|
-
});
|
|
184826
|
-
}
|
|
184827
|
-
if (pendingToolParts.length > 0) {
|
|
184828
|
-
result.push({
|
|
184829
|
-
ordinal: nextOrdinal,
|
|
184830
|
-
id: `${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`,
|
|
184831
|
-
role: "user",
|
|
184832
|
-
parts: pendingToolParts,
|
|
184833
|
-
version: pendingFirstRealVersion
|
|
184834
|
-
});
|
|
184835
|
-
}
|
|
184836
|
-
return result;
|
|
184837
|
-
}
|
|
184838
|
-
function isMessageEntry(value) {
|
|
184839
|
-
if (value === null || typeof value !== "object")
|
|
184840
|
-
return false;
|
|
184841
|
-
const v = value;
|
|
184842
|
-
if (v.type !== "message")
|
|
184843
|
-
return false;
|
|
184844
|
-
if (typeof v.id !== "string")
|
|
184845
|
-
return false;
|
|
184846
|
-
if (v.message === null || typeof v.message !== "object")
|
|
184847
|
-
return false;
|
|
184848
|
-
return true;
|
|
184849
|
-
}
|
|
184850
|
-
function synthesizeUserParts(msg) {
|
|
184851
|
-
const m = msg;
|
|
184852
|
-
if (typeof m.content === "string") {
|
|
184853
|
-
if (m.content.trim().length === 0)
|
|
184854
|
-
return [];
|
|
184855
|
-
return [{ type: "text", text: m.content }];
|
|
184856
185397
|
}
|
|
184857
|
-
|
|
184858
|
-
|
|
184859
|
-
|
|
184860
|
-
|
|
184861
|
-
|
|
184862
|
-
|
|
184863
|
-
|
|
184864
|
-
|
|
184865
|
-
|
|
184866
|
-
|
|
184867
|
-
|
|
184868
|
-
|
|
184869
|
-
}
|
|
184870
|
-
|
|
184871
|
-
const m = msg;
|
|
184872
|
-
if (!Array.isArray(m.content))
|
|
184873
|
-
return [];
|
|
184874
|
-
const parts = [];
|
|
184875
|
-
for (const c of m.content) {
|
|
184876
|
-
if (c === null || typeof c !== "object")
|
|
184877
|
-
continue;
|
|
184878
|
-
const cc = c;
|
|
184879
|
-
if (cc.type === "text" && typeof cc.text === "string") {
|
|
184880
|
-
parts.push({ type: "text", text: cc.text });
|
|
184881
|
-
} else if (cc.type === "toolCall" && typeof cc.id === "string") {
|
|
184882
|
-
parts.push({
|
|
184883
|
-
type: "tool",
|
|
184884
|
-
tool: typeof cc.name === "string" ? cc.name : "unknown",
|
|
184885
|
-
callID: cc.id,
|
|
184886
|
-
state: {
|
|
184887
|
-
input: cc.arguments ?? {}
|
|
184888
|
-
}
|
|
184889
|
-
});
|
|
184890
|
-
}
|
|
184891
|
-
}
|
|
184892
|
-
return parts;
|
|
184893
|
-
}
|
|
184894
|
-
function synthesizeToolResultParts(msg) {
|
|
184895
|
-
const m = msg;
|
|
184896
|
-
const callID = typeof m.toolCallId === "string" ? m.toolCallId : "";
|
|
184897
|
-
const tool = typeof m.toolName === "string" ? m.toolName : "unknown";
|
|
184898
|
-
if (!callID)
|
|
184899
|
-
return [];
|
|
184900
|
-
let output = "";
|
|
184901
|
-
if (Array.isArray(m.content)) {
|
|
184902
|
-
const fragments = [];
|
|
184903
|
-
for (const c of m.content) {
|
|
184904
|
-
if (c === null || typeof c !== "object")
|
|
184905
|
-
continue;
|
|
184906
|
-
const cc = c;
|
|
184907
|
-
if (cc.type === "text" && typeof cc.text === "string") {
|
|
184908
|
-
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);
|
|
184909
185412
|
}
|
|
184910
185413
|
}
|
|
184911
|
-
|
|
184912
|
-
`)
|
|
184913
|
-
|
|
184914
|
-
|
|
184915
|
-
|
|
184916
|
-
|
|
184917
|
-
|
|
184918
|
-
|
|
184919
|
-
|
|
184920
|
-
output
|
|
184921
|
-
}
|
|
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;
|
|
184922
185423
|
}
|
|
184923
|
-
|
|
185424
|
+
});
|
|
185425
|
+
return promise2;
|
|
184924
185426
|
}
|
|
184925
|
-
|
|
184926
|
-
|
|
184927
|
-
import { readFileSync as readFileSync9 } from "node:fs";
|
|
184928
|
-
var PI_CODING_AGENT_MODULE = "@earendil-works/pi-coding-agent";
|
|
184929
|
-
async function loadDefaultPiSessionApi() {
|
|
184930
|
-
const mod = await import(PI_CODING_AGENT_MODULE);
|
|
185427
|
+
async function loadDefaultPiSessionApi(loaders) {
|
|
185428
|
+
const mod = await resolvePiCodingAgentModule(loaders);
|
|
184931
185429
|
const listSessions = mod.SessionManager?.listAll;
|
|
184932
185430
|
if (typeof listSessions !== "function") {
|
|
184933
185431
|
throw new Error("Pi session APIs unavailable: expected SessionManager.listAll on pi-coding-agent");
|
|
@@ -185328,6 +185826,8 @@ function makeMessage(role, parts) {
|
|
|
185328
185826
|
}
|
|
185329
185827
|
|
|
185330
185828
|
// src/commands/pi-command-utils.ts
|
|
185829
|
+
init_logger();
|
|
185830
|
+
import { Box, Text } from "@earendil-works/pi-tui";
|
|
185331
185831
|
var CTX_STATUS_CUSTOM_TYPE = "ctx-status";
|
|
185332
185832
|
function resolveSessionId(ctx) {
|
|
185333
185833
|
const sm = ctx.sessionManager;
|
|
@@ -185341,13 +185841,49 @@ function resolveSessionId(ctx) {
|
|
|
185341
185841
|
return;
|
|
185342
185842
|
}
|
|
185343
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
|
+
}
|
|
185344
185878
|
function sendCtxStatusMessage(pi, content, details) {
|
|
185345
|
-
|
|
185346
|
-
|
|
185347
|
-
|
|
185348
|
-
|
|
185349
|
-
|
|
185350
|
-
|
|
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}`);
|
|
185351
185887
|
}
|
|
185352
185888
|
|
|
185353
185889
|
// src/commands/ctx-dream.ts
|
|
@@ -185807,8 +186343,8 @@ function makeToolCompositeKey(ownerMsgId, callId) {
|
|
|
185807
186343
|
return `${ownerMsgId}${TOOL_COMPOSITE_KEY_SEP}${callId}`;
|
|
185808
186344
|
}
|
|
185809
186345
|
var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
|
|
185810
|
-
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
185811
|
-
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";
|
|
185812
186348
|
var PROBE_DATA_VERSION_SQL = "PRAGMA main.data_version";
|
|
185813
186349
|
var probeDataVersionStatements = new WeakMap;
|
|
185814
186350
|
function getProbeDataVersionStatement(db) {
|
|
@@ -185832,6 +186368,14 @@ function isAssignmentRow(row) {
|
|
|
185832
186368
|
return false;
|
|
185833
186369
|
if (candidate.tool_owner_message_id !== null && typeof candidate.tool_owner_message_id !== "string")
|
|
185834
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;
|
|
185835
186379
|
return true;
|
|
185836
186380
|
}
|
|
185837
186381
|
var UPSERT_COUNTER_SQL = `
|
|
@@ -185866,6 +186410,7 @@ var MAX_TAG_ALLOC_RETRIES = 5;
|
|
|
185866
186410
|
function createTagger() {
|
|
185867
186411
|
const counters = new Map;
|
|
185868
186412
|
const assignments = new Map;
|
|
186413
|
+
const toolAccountingBySession = new Map;
|
|
185869
186414
|
const loadSignatures = new Map;
|
|
185870
186415
|
function getSessionAssignments(sessionId) {
|
|
185871
186416
|
let map2 = assignments.get(sessionId);
|
|
@@ -185875,6 +186420,14 @@ function createTagger() {
|
|
|
185875
186420
|
}
|
|
185876
186421
|
return map2;
|
|
185877
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
|
+
}
|
|
185878
186431
|
function isUniqueConstraintError(error51) {
|
|
185879
186432
|
return error51 instanceof Error && "code" in error51 && error51.code === "SQLITE_CONSTRAINT_UNIQUE";
|
|
185880
186433
|
}
|
|
@@ -185928,6 +186481,14 @@ function createTagger() {
|
|
|
185928
186481
|
}
|
|
185929
186482
|
counters.set(sessionId, next);
|
|
185930
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
|
+
}
|
|
185931
186492
|
return next;
|
|
185932
186493
|
}
|
|
185933
186494
|
throw new Error(`tagger.allocateTag: failed to allocate tag for session=${sessionId} key=${mapKey} after ${MAX_TAG_ALLOC_RETRIES} retries`);
|
|
@@ -185988,6 +186549,13 @@ function createTagger() {
|
|
|
185988
186549
|
function getToolTag(sessionId, callId, ownerMsgId) {
|
|
185989
186550
|
return assignments.get(sessionId)?.get(makeToolCompositeKey(ownerMsgId, callId));
|
|
185990
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
|
+
}
|
|
185991
186559
|
function bindTag(sessionId, messageId, tagNumber) {
|
|
185992
186560
|
getSessionAssignments(sessionId).set(messageId, tagNumber);
|
|
185993
186561
|
}
|
|
@@ -186006,6 +186574,7 @@ function createTagger() {
|
|
|
186006
186574
|
function resetCounter(sessionId, db) {
|
|
186007
186575
|
counters.set(sessionId, 0);
|
|
186008
186576
|
assignments.delete(sessionId);
|
|
186577
|
+
toolAccountingBySession.delete(sessionId);
|
|
186009
186578
|
loadSignatures.delete(sessionId);
|
|
186010
186579
|
getResetCounterStatement(db).run(sessionId, getHarness());
|
|
186011
186580
|
}
|
|
@@ -186028,11 +186597,19 @@ function createTagger() {
|
|
|
186028
186597
|
const assignmentRows = (floor > 0 ? db.prepare(GET_ASSIGNMENTS_SCOPED_SQL).all(sessionId, floor) : db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId)).filter(isAssignmentRow);
|
|
186029
186598
|
const sessionAssignments = getSessionAssignments(sessionId);
|
|
186030
186599
|
sessionAssignments.clear();
|
|
186600
|
+
const sessionToolAccounting = getSessionToolAccounting(sessionId);
|
|
186601
|
+
sessionToolAccounting.clear();
|
|
186031
186602
|
let maxTagNumber = 0;
|
|
186032
186603
|
for (const assignment of assignmentRows) {
|
|
186033
186604
|
if (assignment.type === "tool") {
|
|
186034
186605
|
if (assignment.tool_owner_message_id !== null) {
|
|
186035
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
|
+
});
|
|
186036
186613
|
}
|
|
186037
186614
|
} else {
|
|
186038
186615
|
sessionAssignments.set(assignment.message_id, assignment.tag_number);
|
|
@@ -186052,6 +186629,7 @@ function createTagger() {
|
|
|
186052
186629
|
function cleanup(sessionId) {
|
|
186053
186630
|
counters.delete(sessionId);
|
|
186054
186631
|
assignments.delete(sessionId);
|
|
186632
|
+
toolAccountingBySession.delete(sessionId);
|
|
186055
186633
|
loadSignatures.delete(sessionId);
|
|
186056
186634
|
}
|
|
186057
186635
|
return {
|
|
@@ -186059,6 +186637,8 @@ function createTagger() {
|
|
|
186059
186637
|
assignToolTag,
|
|
186060
186638
|
getTag,
|
|
186061
186639
|
getToolTag,
|
|
186640
|
+
getToolTagAccounting,
|
|
186641
|
+
setToolTagAccounting,
|
|
186062
186642
|
bindTag,
|
|
186063
186643
|
unbindTag,
|
|
186064
186644
|
bindToolTag,
|
|
@@ -188034,26 +188614,28 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
188034
188614
|
sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
|
|
188035
188615
|
return { shouldFire: false };
|
|
188036
188616
|
}
|
|
188037
|
-
|
|
188617
|
+
const lazyInMemoryTail = typeof inMemoryTail === "function" ? inMemoryTail : undefined;
|
|
188618
|
+
let resolvedInMemoryTail = typeof inMemoryTail === "function" ? undefined : inMemoryTail;
|
|
188619
|
+
if (resolvedInMemoryTail) {
|
|
188038
188620
|
try {
|
|
188039
188621
|
const policyVersion = loadProtectedTailMeta(db, sessionId).protectedTailPolicyVersion;
|
|
188040
188622
|
if (policyVersion < 3)
|
|
188041
|
-
|
|
188623
|
+
resolvedInMemoryTail = undefined;
|
|
188042
188624
|
} catch {
|
|
188043
|
-
|
|
188625
|
+
resolvedInMemoryTail = undefined;
|
|
188044
188626
|
}
|
|
188045
188627
|
}
|
|
188046
|
-
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;
|
|
188047
188629
|
const proactiveFloorForGate = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
|
|
188048
188630
|
if (usage.percentage < proactiveFloorForGate) {
|
|
188049
188631
|
try {
|
|
188050
|
-
const boundFloor =
|
|
188632
|
+
const boundFloor = resolvedInMemoryTail || lazyInMemoryTail ? taggerFloor : 0;
|
|
188051
188633
|
const { bound: persistedBound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId, boundFloor);
|
|
188052
188634
|
if (nullCount === 0) {
|
|
188053
|
-
const untaggedUpperBound =
|
|
188635
|
+
const untaggedUpperBound = resolvedInMemoryTail ? estimateUntaggedInMemoryTailUpperBound(db, sessionId, resolvedInMemoryTail, taggerFloor) : 0;
|
|
188054
188636
|
const eligibleUpperBound = persistedBound + untaggedUpperBound;
|
|
188055
188637
|
if (eligibleUpperBound < triggerBudget) {
|
|
188056
|
-
const memorySuffix =
|
|
188638
|
+
const memorySuffix = resolvedInMemoryTail ? ` (persisted=${persistedBound}, untagged-memory≤${untaggedUpperBound})` : "";
|
|
188057
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`);
|
|
188058
188640
|
return { shouldFire: false };
|
|
188059
188641
|
}
|
|
@@ -188062,7 +188644,16 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
188062
188644
|
sessionLog(sessionId, `compartment trigger: cheap-gate skipped (falling through to full read): ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
188063
188645
|
}
|
|
188064
188646
|
}
|
|
188065
|
-
|
|
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);
|
|
188066
188657
|
if (!tailInfo.hasNewRawHistory) {
|
|
188067
188658
|
try {
|
|
188068
188659
|
const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
|
|
@@ -188089,11 +188680,11 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
|
|
|
188089
188680
|
}
|
|
188090
188681
|
const scale = usage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE ? 0.25 : 0.5;
|
|
188091
188682
|
const scaledBoundary = withRawSessionMessageCache(() => {
|
|
188092
|
-
if (
|
|
188683
|
+
if (resolvedInMemoryTail) {
|
|
188093
188684
|
primeInMemoryTailRawMessageCache({
|
|
188094
188685
|
sessionId,
|
|
188095
|
-
messages:
|
|
188096
|
-
absoluteMessageCount:
|
|
188686
|
+
messages: resolvedInMemoryTail.messages,
|
|
188687
|
+
absoluteMessageCount: resolvedInMemoryTail.absoluteMessageCount
|
|
188097
188688
|
});
|
|
188098
188689
|
}
|
|
188099
188690
|
return resolveOpenCodeProtectedTailBoundary({
|
|
@@ -188380,12 +188971,26 @@ function computeBudgetPressure(compartments, historyBudget) {
|
|
|
188380
188971
|
|
|
188381
188972
|
// ../plugin/src/hooks/magic-context/decay-render.ts
|
|
188382
188973
|
var DEFAULT_HISTORY_BUDGET_TOKENS = 60000;
|
|
188383
|
-
function escapeXmlAttr2(s) {
|
|
188384
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
188385
|
-
}
|
|
188386
188974
|
function escapeXmlContent2(s) {
|
|
188387
188975
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
188388
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
|
+
}
|
|
188389
188994
|
function isTieredRow(c) {
|
|
188390
188995
|
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
188391
188996
|
}
|
|
@@ -188415,25 +189020,22 @@ function renderCompartmentAtTier(c, tier2) {
|
|
|
188415
189020
|
return renderOneCompartment(c, tier2);
|
|
188416
189021
|
}
|
|
188417
189022
|
function renderOneCompartment(c, tier2) {
|
|
188418
|
-
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
188419
189023
|
if (tier2 >= 5)
|
|
188420
189024
|
return "";
|
|
189025
|
+
const heading = compartmentHeading(c);
|
|
188421
189026
|
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
188422
189027
|
const flat = (c.content ?? "").trim();
|
|
188423
189028
|
if (tier2 >= 4 || flat.length === 0)
|
|
188424
|
-
return
|
|
188425
|
-
|
|
188426
|
-
|
|
188427
|
-
|
|
188428
|
-
"</compartment>"
|
|
188429
|
-
].join(`
|
|
188430
|
-
`);
|
|
189029
|
+
return heading;
|
|
189030
|
+
const body2 = guardCompartmentBody(escapeXmlContent2(legacyBodyForTier(flat, tier2)));
|
|
189031
|
+
return `${heading}
|
|
189032
|
+
${body2}`;
|
|
188431
189033
|
}
|
|
188432
189034
|
const body = tierBody(c, tier2);
|
|
188433
189035
|
if (body.length === 0)
|
|
188434
|
-
return
|
|
188435
|
-
return
|
|
188436
|
-
|
|
189036
|
+
return heading;
|
|
189037
|
+
return `${heading}
|
|
189038
|
+
${guardCompartmentBody(escapeXmlContent2(body))}`;
|
|
188437
189039
|
}
|
|
188438
189040
|
function computeTiers(compartments, historyBudgetTokens) {
|
|
188439
189041
|
const v2Compartments = compartments.map((c, originalIndex) => ({ c, originalIndex })).filter(({ c }) => c.legacy !== 1);
|
|
@@ -188556,33 +189158,9 @@ function getVisibleMemoryIds(db, sessionId) {
|
|
|
188556
189158
|
}
|
|
188557
189159
|
}
|
|
188558
189160
|
function renderMemoryBlock(memories) {
|
|
188559
|
-
|
|
188560
|
-
for (const m of memories) {
|
|
188561
|
-
const existing = byCategory.get(m.category);
|
|
188562
|
-
if (existing) {
|
|
188563
|
-
existing.push(m);
|
|
188564
|
-
} else {
|
|
188565
|
-
byCategory.set(m.category, [m]);
|
|
188566
|
-
}
|
|
188567
|
-
}
|
|
188568
|
-
const sections = [];
|
|
188569
|
-
for (const category of CATEGORY_PRIORITY) {
|
|
188570
|
-
const categoryMemories = byCategory.get(category);
|
|
188571
|
-
if (!categoryMemories || categoryMemories.length === 0) {
|
|
188572
|
-
continue;
|
|
188573
|
-
}
|
|
188574
|
-
sections.push(`<${category}>`, ...categoryMemories.map((m) => `- ${escapeXmlContent(m.content)}`), `</${category}>`);
|
|
188575
|
-
}
|
|
188576
|
-
if (sections.length === 0) {
|
|
188577
|
-
return null;
|
|
188578
|
-
}
|
|
188579
|
-
return `<project-memory>
|
|
188580
|
-
${sections.join(`
|
|
188581
|
-
`)}
|
|
188582
|
-
</project-memory>`;
|
|
189161
|
+
return renderMemoryBlockV2(memories) || null;
|
|
188583
189162
|
}
|
|
188584
189163
|
var DEFAULT_MEMORY_BUDGET_TOKENS = 8000;
|
|
188585
|
-
var MEMORY_BLOCK_WRAPPER_TOKENS = 6;
|
|
188586
189164
|
var DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000;
|
|
188587
189165
|
function memoryCanonicalIdentity(memory, workspace) {
|
|
188588
189166
|
return resolveStoredPathWorkspaceIdentity(memory.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
@@ -188600,11 +189178,18 @@ function memorySelectionOrder(left, right) {
|
|
|
188600
189178
|
return left.id - right.id;
|
|
188601
189179
|
}
|
|
188602
189180
|
function memoryRenderOrder(left, right) {
|
|
188603
|
-
const
|
|
188604
|
-
const
|
|
188605
|
-
|
|
188606
|
-
|
|
188607
|
-
|
|
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
|
+
}
|
|
188608
189193
|
return left.id - right.id;
|
|
188609
189194
|
}
|
|
188610
189195
|
var maxCompartmentSeqStatements = new WeakMap;
|
|
@@ -188615,13 +189200,13 @@ var newCompartmentStatements = new WeakMap;
|
|
|
188615
189200
|
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
188616
189201
|
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
188617
189202
|
const selected = [];
|
|
188618
|
-
|
|
189203
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
188619
189204
|
for (const memory of selectionOrder) {
|
|
188620
|
-
const
|
|
188621
|
-
if (usedTokens +
|
|
189205
|
+
const cost = accounting.candidateCost(memory);
|
|
189206
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188622
189207
|
continue;
|
|
189208
|
+
accounting.admit(memory, cost);
|
|
188623
189209
|
selected.push(memory);
|
|
188624
|
-
usedTokens += memoryTokens;
|
|
188625
189210
|
}
|
|
188626
189211
|
if (selected.length < memories.length) {
|
|
188627
189212
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
@@ -188635,23 +189220,22 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
188635
189220
|
}
|
|
188636
189221
|
const selected = [];
|
|
188637
189222
|
const selectedIds = new Set;
|
|
188638
|
-
|
|
188639
|
-
const tokenCost = (memory) => estimateTokens(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
189223
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
188640
189224
|
const trySelect = (memory) => {
|
|
188641
189225
|
if (selectedIds.has(memory.id))
|
|
188642
189226
|
return false;
|
|
188643
|
-
const
|
|
188644
|
-
if (usedTokens +
|
|
189227
|
+
const cost = accounting.candidateCost(memory);
|
|
189228
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188645
189229
|
return false;
|
|
188646
189230
|
selected.push(memory);
|
|
188647
189231
|
selectedIds.add(memory.id);
|
|
188648
|
-
|
|
189232
|
+
accounting.admit(memory, cost);
|
|
188649
189233
|
return true;
|
|
188650
189234
|
};
|
|
188651
189235
|
for (const memory of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
188652
189236
|
trySelect(memory);
|
|
188653
189237
|
}
|
|
188654
|
-
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
189238
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - accounting.usedTokens);
|
|
188655
189239
|
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
188656
189240
|
const byIdentity = new Map;
|
|
188657
189241
|
for (const memory of memories) {
|
|
@@ -188670,15 +189254,15 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
188670
189254
|
for (const memory of candidates) {
|
|
188671
189255
|
if (selectedIds.has(memory.id))
|
|
188672
189256
|
continue;
|
|
188673
|
-
const
|
|
188674
|
-
if (memberTokens +
|
|
189257
|
+
const cost = accounting.candidateCost(memory);
|
|
189258
|
+
if (memberTokens + cost > floorTokens)
|
|
188675
189259
|
continue;
|
|
188676
|
-
if (usedTokens +
|
|
189260
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
188677
189261
|
continue;
|
|
188678
189262
|
selected.push(memory);
|
|
188679
189263
|
selectedIds.add(memory.id);
|
|
188680
|
-
|
|
188681
|
-
memberTokens +=
|
|
189264
|
+
accounting.admit(memory, cost);
|
|
189265
|
+
memberTokens += cost;
|
|
188682
189266
|
}
|
|
188683
189267
|
}
|
|
188684
189268
|
const remaining = memories.filter((memory) => !selectedIds.has(memory.id)).sort(memorySelectionOrder);
|
|
@@ -188702,17 +189286,55 @@ function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
|
188702
189286
|
}
|
|
188703
189287
|
return selected;
|
|
188704
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
|
+
}
|
|
188705
189317
|
function renderMemoryLineV2(memory, sourceName) {
|
|
188706
|
-
const
|
|
188707
|
-
return
|
|
189318
|
+
const source = sourceName ? ` [${escapeXmlContent(sourceName)}]` : "";
|
|
189319
|
+
return `#${memory.id}${source}: ${escapeXmlContent(memory.content)}`;
|
|
188708
189320
|
}
|
|
188709
189321
|
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
188710
189322
|
if (memories.length === 0)
|
|
188711
189323
|
return "";
|
|
189324
|
+
const ordered = [...memories].sort(memoryRenderOrder);
|
|
188712
189325
|
const lines = [`<${wrapper}>`];
|
|
188713
|
-
|
|
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
|
+
}
|
|
188714
189334
|
lines.push(renderMemoryLineV2(memory, renderOptions.sourceNameByMemoryId?.get(memory.id)));
|
|
188715
189335
|
}
|
|
189336
|
+
if (openCategory !== undefined)
|
|
189337
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
188716
189338
|
lines.push(`</${wrapper}>`);
|
|
188717
189339
|
return lines.join(`
|
|
188718
189340
|
`);
|
|
@@ -189006,6 +189628,7 @@ function readUint32BE(b, offset) {
|
|
|
189006
189628
|
function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
189007
189629
|
const skipPrefixInjection = options.skipPrefixInjection === true;
|
|
189008
189630
|
const targets = new Map;
|
|
189631
|
+
const timing = options.onTiming ? { identity: 0, prefix: 0, targets: 0, tokenCounting: 0 } : undefined;
|
|
189009
189632
|
const toolAggregates = new Map;
|
|
189010
189633
|
const openToolAggregateKeysByCallId = new Map;
|
|
189011
189634
|
let activeToolResultRun;
|
|
@@ -189015,6 +189638,7 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189015
189638
|
continue;
|
|
189016
189639
|
activeToolResultRun = undefined;
|
|
189017
189640
|
const messageId = message.info.id;
|
|
189641
|
+
const reuseIdentity = messageId !== undefined && options.reuseMessageIds?.has(messageId) === true;
|
|
189018
189642
|
let textOrdinal = 0;
|
|
189019
189643
|
const parts = message.parts;
|
|
189020
189644
|
for (let partIndex = 0;partIndex < parts.length; partIndex += 1) {
|
|
@@ -189040,7 +189664,10 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189040
189664
|
db,
|
|
189041
189665
|
targets,
|
|
189042
189666
|
skipPrefixInjection,
|
|
189043
|
-
entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null
|
|
189667
|
+
entryFingerprint: options.entryFingerprintByMessageId?.get(messageId) ?? null,
|
|
189668
|
+
reuseIdentity,
|
|
189669
|
+
timing,
|
|
189670
|
+
textTokenCache: options.textTokenCache
|
|
189044
189671
|
});
|
|
189045
189672
|
textOrdinal += 1;
|
|
189046
189673
|
continue;
|
|
@@ -189050,12 +189677,8 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189050
189677
|
activeToolResultRun = undefined;
|
|
189051
189678
|
continue;
|
|
189052
189679
|
}
|
|
189680
|
+
const identityStart = timing ? performance.now() : 0;
|
|
189053
189681
|
const callId = part.id;
|
|
189054
|
-
const text = part.getText() ?? "";
|
|
189055
|
-
const toolByteSize = getToolPartByteSize(part, text);
|
|
189056
|
-
const toolTokenCount = getToolPartTokenCount(part, text);
|
|
189057
|
-
const meta3 = part.getToolMetadata();
|
|
189058
|
-
const inputTokenCount = meta3.inputTokenCount;
|
|
189059
189682
|
if (typeof callId !== "string" || callId.length === 0) {
|
|
189060
189683
|
activeToolResultRun = undefined;
|
|
189061
189684
|
tagToolPart({
|
|
@@ -189068,7 +189691,9 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189068
189691
|
tagger,
|
|
189069
189692
|
db,
|
|
189070
189693
|
targets,
|
|
189071
|
-
skipPrefixInjection
|
|
189694
|
+
skipPrefixInjection,
|
|
189695
|
+
reuseIdentity,
|
|
189696
|
+
timing
|
|
189072
189697
|
});
|
|
189073
189698
|
continue;
|
|
189074
189699
|
}
|
|
@@ -189084,79 +189709,234 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
189084
189709
|
const aggregateKey = existingKey ?? makeToolCompositeKey(messageId, callId);
|
|
189085
189710
|
const existing = toolAggregates.get(aggregateKey);
|
|
189086
189711
|
if (existing) {
|
|
189087
|
-
existing.occurrences.push({
|
|
189088
|
-
|
|
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,
|
|
189089
189767
|
part,
|
|
189090
|
-
|
|
189768
|
+
text: text2,
|
|
189769
|
+
tagId: existing.tagId,
|
|
189770
|
+
aggregate: existing,
|
|
189771
|
+
targets,
|
|
189772
|
+
timing
|
|
189091
189773
|
});
|
|
189092
|
-
if (part.kind === "tool_result" && toolByteSize > existing.maxByteSize) {
|
|
189093
|
-
existing.maxByteSize = toolByteSize;
|
|
189094
|
-
existing.maxTokenCount = toolTokenCount;
|
|
189095
|
-
updateTagByteSize(db, sessionId, existing.tagId, toolByteSize);
|
|
189096
|
-
updateTagTokenCount(db, sessionId, existing.tagId, toolTokenCount);
|
|
189097
|
-
}
|
|
189098
|
-
if (existing.toolName === null && meta3.toolName) {
|
|
189099
|
-
existing.toolName = meta3.toolName;
|
|
189100
|
-
}
|
|
189101
|
-
if (existing.inputByteSize === 0 && part.kind === "tool_use" && meta3.inputByteSize > 0) {
|
|
189102
|
-
existing.inputByteSize = meta3.inputByteSize;
|
|
189103
|
-
updateTagInputByteSize(db, sessionId, existing.tagId, meta3.inputByteSize);
|
|
189104
|
-
}
|
|
189105
|
-
if (!existing.inputTokenStored && part.kind === "tool_use" && inputTokenCount > 0) {
|
|
189106
|
-
existing.inputTokenStored = true;
|
|
189107
|
-
updateTagInputTokenCount(db, sessionId, existing.tagId, inputTokenCount);
|
|
189108
|
-
}
|
|
189109
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
189110
|
-
part.setText(prependTag(existing.tagId, text));
|
|
189111
|
-
}
|
|
189112
|
-
targets.set(existing.tagId, buildAggregateTarget(existing.tagId, existing.occurrences));
|
|
189113
189774
|
if (part.kind === "tool_result") {
|
|
189114
189775
|
markToolAggregateResolved(callId, aggregateKey, openToolAggregateKeysByCallId);
|
|
189115
189776
|
activeToolResultRun = { callId, aggregateKey };
|
|
189116
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;
|
|
189117
189813
|
} else {
|
|
189118
|
-
const
|
|
189119
|
-
|
|
189120
|
-
const
|
|
189121
|
-
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, () => ({
|
|
189122
189820
|
tokenCount: outputTokenCount,
|
|
189123
189821
|
inputTokenCount: firstInputTokenCount,
|
|
189124
189822
|
reasoningTokenCount: null
|
|
189125
189823
|
}));
|
|
189126
|
-
const
|
|
189824
|
+
const persistedAccounting = tagger.getToolTagAccounting(sessionId, callId, messageId);
|
|
189825
|
+
aggregate = {
|
|
189127
189826
|
callId,
|
|
189128
189827
|
tagId,
|
|
189129
|
-
|
|
189130
|
-
|
|
189131
|
-
|
|
189132
|
-
|
|
189133
|
-
|
|
189134
|
-
|
|
189135
|
-
|
|
189136
|
-
maxByteSize: outputByteSize,
|
|
189137
|
-
maxTokenCount: outputTokenCount,
|
|
189138
|
-
toolName: meta3.toolName ?? null,
|
|
189139
|
-
inputByteSize: part.kind === "tool_use" ? meta3.inputByteSize : 0,
|
|
189140
|
-
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)
|
|
189141
189835
|
};
|
|
189142
|
-
toolAggregates.set(aggregateKey, aggregate);
|
|
189143
|
-
if (part.kind === "tool_use") {
|
|
189144
|
-
openToolAggregateKeysByCallId.set(callId, [...pendingKeys, aggregateKey]);
|
|
189145
|
-
}
|
|
189146
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
189147
|
-
part.setText(prependTag(tagId, text));
|
|
189148
|
-
}
|
|
189149
|
-
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
189150
189836
|
if (part.kind === "tool_result") {
|
|
189151
|
-
|
|
189152
|
-
|
|
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
|
+
});
|
|
189153
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 };
|
|
189154
189869
|
}
|
|
189155
189870
|
}
|
|
189156
189871
|
}
|
|
189157
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
|
+
}
|
|
189158
189879
|
return { targets };
|
|
189159
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
|
+
}
|
|
189160
189940
|
function findLastUnresolvedToolAggregateKey(pendingKeys, toolAggregates) {
|
|
189161
189941
|
for (let i = pendingKeys.length - 1;i >= 0; i -= 1) {
|
|
189162
189942
|
const key = pendingKeys[i];
|
|
@@ -189207,6 +189987,15 @@ function getToolPartTokenCount(part, text) {
|
|
|
189207
189987
|
}
|
|
189208
189988
|
return 0;
|
|
189209
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
|
+
}
|
|
189210
189999
|
function getNonTextToolResultByteSize(part) {
|
|
189211
190000
|
const raw = part.rawByteSize?.();
|
|
189212
190001
|
if (typeof raw === "number" && raw > 0)
|
|
@@ -189227,39 +190016,97 @@ function isRecord2(value) {
|
|
|
189227
190016
|
return typeof value === "object" && value !== null;
|
|
189228
190017
|
}
|
|
189229
190018
|
function tagTextPart(args) {
|
|
190019
|
+
const identityStart = args.timing ? performance.now() : 0;
|
|
189230
190020
|
const text = args.part.getText() ?? "";
|
|
189231
190021
|
const contentId = `${args.messageId}:p${args.textOrdinal}`;
|
|
189232
|
-
const
|
|
189233
|
-
|
|
189234
|
-
|
|
189235
|
-
|
|
189236
|
-
|
|
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
|
+
});
|
|
189237
190045
|
const sourceContent = stripTagPrefix(text);
|
|
189238
190046
|
if (sourceContent.trim().length > 0) {
|
|
189239
190047
|
saveSourceContent(args.db, args.sessionId, tagId, sourceContent);
|
|
189240
190048
|
}
|
|
190049
|
+
if (args.timing)
|
|
190050
|
+
args.timing.identity += performance.now() - identityStart;
|
|
190051
|
+
applyTextPrefixAndTarget(args, tagId, text);
|
|
190052
|
+
}
|
|
190053
|
+
function applyTextPrefixAndTarget(args, tagId, text) {
|
|
189241
190054
|
if (!args.skipPrefixInjection) {
|
|
190055
|
+
const prefixStart = args.timing ? performance.now() : 0;
|
|
189242
190056
|
args.part.setText(prependTag(tagId, text));
|
|
190057
|
+
if (args.timing)
|
|
190058
|
+
args.timing.prefix += performance.now() - prefixStart;
|
|
189243
190059
|
}
|
|
190060
|
+
const targetStart = args.timing ? performance.now() : 0;
|
|
189244
190061
|
args.targets.set(tagId, buildTextTarget(args.part, args.message));
|
|
190062
|
+
if (args.timing)
|
|
190063
|
+
args.timing.targets += performance.now() - targetStart;
|
|
189245
190064
|
}
|
|
189246
190065
|
function tagToolPart(args) {
|
|
190066
|
+
const identityStart = args.timing ? performance.now() : 0;
|
|
189247
190067
|
const stableId = args.part.id;
|
|
189248
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
|
+
}
|
|
189249
190077
|
const text = args.part.getText() ?? "";
|
|
189250
190078
|
const toolByteSize = getToolPartByteSize(args.part, text);
|
|
189251
|
-
const toolTokenCount = getToolPartTokenCount(args.part, text);
|
|
189252
190079
|
const meta3 = args.part.getToolMetadata();
|
|
189253
|
-
const
|
|
189254
|
-
|
|
189255
|
-
|
|
189256
|
-
|
|
189257
|
-
|
|
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) {
|
|
189258
190100
|
if (!args.skipPrefixInjection && args.part.kind === "tool_result") {
|
|
189259
|
-
const
|
|
189260
|
-
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;
|
|
189261
190105
|
}
|
|
190106
|
+
const targetStart = args.timing ? performance.now() : 0;
|
|
189262
190107
|
args.targets.set(tagId, buildToolTarget(args.part, args.message, tagId));
|
|
190108
|
+
if (args.timing)
|
|
190109
|
+
args.timing.targets += performance.now() - targetStart;
|
|
189263
190110
|
}
|
|
189264
190111
|
function setToolContentOrText(part, content) {
|
|
189265
190112
|
try {
|
|
@@ -190539,6 +191386,7 @@ async function runAutoSearchHintForPi(args) {
|
|
|
190539
191386
|
sessionLog(sessionId, "Pi auto-search: strict entry-id resolution failed; replayed persisted decisions only");
|
|
190540
191387
|
return messages;
|
|
190541
191388
|
}
|
|
191389
|
+
await args.ensureProjectRegistered?.();
|
|
190542
191390
|
const writeNoHintAndReconcile = (reason) => {
|
|
190543
191391
|
const outcome2 = appendAutoSearchHintDecision(db, sessionId, {
|
|
190544
191392
|
messageId: userMsgId,
|
|
@@ -190686,8 +191534,17 @@ function getEntryId(entry) {
|
|
|
190686
191534
|
const id = entry.id;
|
|
190687
191535
|
return typeof id === "string" ? id : null;
|
|
190688
191536
|
}
|
|
190689
|
-
function findEntryIndex(branchEntries,
|
|
190690
|
-
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);
|
|
190691
191548
|
}
|
|
190692
191549
|
|
|
190693
191550
|
// src/ctx-reduce-nudge-pi.ts
|
|
@@ -191386,7 +192243,7 @@ init_logger();
|
|
|
191386
192243
|
function resolveStableId(msg, index, entryIds) {
|
|
191387
192244
|
return resolvePiStableId(msg, index, entryIds) ?? "";
|
|
191388
192245
|
}
|
|
191389
|
-
function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId) {
|
|
192246
|
+
function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId, trimMutableEntryIds = false) {
|
|
191390
192247
|
if (cutoffMessageId.length === 0)
|
|
191391
192248
|
return 0;
|
|
191392
192249
|
const effectiveCutoffId = cutoffMessageId.startsWith(SYNTH_USER_ID_PREFIX) ? cutoffMessageId.slice(SYNTH_USER_ID_PREFIX.length) : cutoffMessageId;
|
|
@@ -191453,6 +192310,10 @@ function trimPiMessagesToBoundary(piMessages, entryIds, cutoffMessageId) {
|
|
|
191453
192310
|
const kept = piMessages.filter((_, index) => !remove.has(index));
|
|
191454
192311
|
const removed = piMessages.length - kept.length;
|
|
191455
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
|
+
}
|
|
191456
192317
|
return removed;
|
|
191457
192318
|
}
|
|
191458
192319
|
function toolPairKey(callId, assistantIndex) {
|
|
@@ -191563,6 +192424,23 @@ var EMPTY_PI_HARD_SIGNALS = {
|
|
|
191563
192424
|
cacheExpired: false,
|
|
191564
192425
|
lastResponseTime: 0
|
|
191565
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
|
+
}
|
|
191566
192444
|
function decodeCachedM0(value) {
|
|
191567
192445
|
if (!value)
|
|
191568
192446
|
return null;
|
|
@@ -191581,6 +192459,20 @@ function getCachedBoundary(db, sessionId) {
|
|
|
191581
192459
|
const row = db.prepare("SELECT cached_m0_last_baseline_end_message_id AS boundary FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
191582
192460
|
return typeof row?.boundary === "string" && row.boundary.length > 0 ? row.boundary : null;
|
|
191583
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
|
+
}
|
|
191584
192476
|
function setCachedBoundary(db, sessionId, boundary) {
|
|
191585
192477
|
db.prepare("UPDATE session_meta SET cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(boundary, sessionId);
|
|
191586
192478
|
}
|
|
@@ -191650,7 +192542,7 @@ function readCurrentMarkersFromCompartments(db, state, compartments, projectDocs
|
|
|
191650
192542
|
function mustMaterializePi(state, db, currentCompartmentsOverride) {
|
|
191651
192543
|
const meta3 = getOrCreateSessionMeta(db, state.sessionId);
|
|
191652
192544
|
const currentCompartments = currentCompartmentsOverride ?? getCompartments(db, state.sessionId);
|
|
191653
|
-
const current = readCurrentMarkersFromCompartments(db, state, currentCompartments);
|
|
192545
|
+
const current = readCurrentMarkersFromCompartments(db, state, currentCompartments, meta3.cachedM0ProjectDocsHash ?? undefined);
|
|
191654
192546
|
if (!meta3.cachedM0Bytes)
|
|
191655
192547
|
return { value: true, reason: "first_render" };
|
|
191656
192548
|
if (!meta3.cachedM1Bytes)
|
|
@@ -192284,8 +193176,7 @@ function injectM0M1Pi(state, db, piMessages, entryIds, recomputeM1ThisPass = fal
|
|
|
192284
193176
|
const M1_ABSOLUTE_CAP_RATIO = 0.2;
|
|
192285
193177
|
const m1AbsoluteBudget = (state.historyBudgetTokens ?? DEFAULT_HISTORY_BUDGET_TOKENS) * M1_ABSOLUTE_CAP_RATIO;
|
|
192286
193178
|
const m1HasContent = m1 !== PI_M1_PLACEHOLDER;
|
|
192287
|
-
const m1Tokens =
|
|
192288
|
-
const m0Tokens = estimateTokens(m0);
|
|
193179
|
+
const { m0Tokens, m1Tokens } = cachedInjectionTokenCounts(state.sessionId, m0, m1);
|
|
192289
193180
|
const m1OverAbsoluteCap = m1HasContent && m1Tokens > m1AbsoluteBudget;
|
|
192290
193181
|
if (!materialized && !contentionExhausted && m1Recomputed && recomputeM1ThisPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1HasContent && m0Tokens >= M0_DRIFT_RATIO_FLOOR_TOKENS && m1Tokens > m0Tokens * M1_DRIFT_RATIO)) {
|
|
192291
193182
|
decision = { value: true, reason: "drift" };
|
|
@@ -196711,7 +197602,6 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196711
197602
|
const { db, sessionId, messages, isCacheBusting, stableIdByRef } = args;
|
|
196712
197603
|
const persistedIds = getStrippedPlaceholderIds(db, sessionId);
|
|
196713
197604
|
const idsToStrip = new Set(persistedIds);
|
|
196714
|
-
let discovered = 0;
|
|
196715
197605
|
const idOf = (msg, index) => {
|
|
196716
197606
|
const m = msg && typeof msg === "object" ? msg : undefined;
|
|
196717
197607
|
const carried = m ? stableIdByRef?.get(m) : undefined;
|
|
@@ -196730,15 +197620,36 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196730
197620
|
if (!id)
|
|
196731
197621
|
continue;
|
|
196732
197622
|
presentIds?.add(id);
|
|
196733
|
-
if (
|
|
196734
|
-
continue;
|
|
196735
|
-
if (!idsToStrip.has(id)) {
|
|
196736
|
-
idsToStrip.add(id);
|
|
197623
|
+
if (messageIsPlaceholderOnly(messages[i]) && !persistedIds.has(id)) {
|
|
196737
197624
|
discoveredIds.push(id);
|
|
196738
|
-
discovered++;
|
|
196739
197625
|
}
|
|
196740
197626
|
}
|
|
196741
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
|
+
}
|
|
196742
197653
|
let removed = 0;
|
|
196743
197654
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
196744
197655
|
const id = idOf(messages[i], i);
|
|
@@ -196747,29 +197658,76 @@ function stripPiDroppedPlaceholderMessages(args) {
|
|
|
196747
197658
|
messages.splice(i, 1);
|
|
196748
197659
|
removed++;
|
|
196749
197660
|
}
|
|
196750
|
-
let pruned = 0;
|
|
196751
|
-
if (presentIds) {
|
|
196752
|
-
const removedIds = [];
|
|
196753
|
-
for (const id of persistedIds) {
|
|
196754
|
-
if (!presentIds.has(id))
|
|
196755
|
-
removedIds.push(id);
|
|
196756
|
-
}
|
|
196757
|
-
pruned = removedIds.length;
|
|
196758
|
-
if (discoveredIds.length > 0 || removedIds.length > 0) {
|
|
196759
|
-
applyStrippedPlaceholderDelta(db, sessionId, {
|
|
196760
|
-
add: discoveredIds,
|
|
196761
|
-
remove: removedIds
|
|
196762
|
-
});
|
|
196763
|
-
}
|
|
196764
|
-
} else if (discoveredIds.length > 0) {
|
|
196765
|
-
applyStrippedPlaceholderDelta(db, sessionId, { add: discoveredIds });
|
|
196766
|
-
}
|
|
196767
197661
|
if (removed > 0 || discovered > 0 || pruned > 0) {
|
|
196768
197662
|
sessionLog(sessionId, `placeholder strip: removed=${removed} discovered=${discovered} pruned=${pruned}`);
|
|
196769
197663
|
}
|
|
196770
197664
|
return { removed, discovered };
|
|
196771
197665
|
}
|
|
196772
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
|
+
|
|
196773
197731
|
// src/system-prompt.ts
|
|
196774
197732
|
import { createHash as createHash12 } from "node:crypto";
|
|
196775
197733
|
|
|
@@ -196790,6 +197748,7 @@ Context is managed for you entirely automatically — there's nothing to prune a
|
|
|
196790
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).`;
|
|
196791
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.`;
|
|
196792
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.
|
|
196793
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:
|
|
196794
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")\`
|
|
196795
197754
|
- Discovered a non-obvious build/test command → \`ctx_memory(action="write", category="PROJECT_RULES", content="Always use scripts/release.sh for releases")\`
|
|
@@ -196803,7 +197762,7 @@ Use \`ctx_reduce\` to mark spent tagged content as discardable and reclaim space
|
|
|
196803
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.
|
|
196804
197763
|
${CTX_NOTE_GUIDANCE}
|
|
196805
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.
|
|
196806
|
-
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).
|
|
196807
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:
|
|
196808
197767
|
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
196809
197768
|
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
@@ -196818,7 +197777,7 @@ NEVER drop assistant text messages unless they are exceptionally large. Your con
|
|
|
196818
197777
|
Before your turn finishes, consider using \`ctx_reduce\` to drop large tool outputs you no longer need.`;
|
|
196819
197778
|
var BASE_INTRO_NO_REDUCE = (memoryEnabled) => `${CTX_NOTE_GUIDANCE}
|
|
196820
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.
|
|
196821
|
-
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).
|
|
196822
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:
|
|
196823
197782
|
- Can't remember where a related codebase or dependency lives → \`ctx_search(query="opencode source code path")\`
|
|
196824
197783
|
- Forgot a prior architectural decision or constraint → \`ctx_search(query="why did we choose SQLite over postgres")\`
|
|
@@ -197018,74 +197977,222 @@ function withTimeout(p, ms) {
|
|
|
197018
197977
|
}
|
|
197019
197978
|
|
|
197020
197979
|
// src/tokenize-pi-messages.ts
|
|
197021
|
-
function tokenizePiMessages(messages) {
|
|
197980
|
+
function tokenizePiMessages(messages, options) {
|
|
197022
197981
|
let conversation = 0;
|
|
197023
197982
|
let toolCall = 0;
|
|
197983
|
+
let cacheValidationMs = 0;
|
|
197984
|
+
let bpeMs = 0;
|
|
197985
|
+
const liveIds = options ? new Set : undefined;
|
|
197024
197986
|
for (const raw of messages) {
|
|
197025
197987
|
if (!raw || typeof raw !== "object")
|
|
197026
197988
|
continue;
|
|
197027
|
-
const
|
|
197028
|
-
const
|
|
197029
|
-
|
|
197030
|
-
|
|
197031
|
-
|
|
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;
|
|
197032
198000
|
continue;
|
|
197033
198001
|
}
|
|
197034
|
-
|
|
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
|
+
}
|
|
197035
198048
|
continue;
|
|
197036
|
-
|
|
197037
|
-
|
|
198049
|
+
}
|
|
198050
|
+
if (msg.role === "toolResult") {
|
|
198051
|
+
if (typeof content === "string") {
|
|
198052
|
+
toolCall += estimateTokens(content);
|
|
197038
198053
|
continue;
|
|
197039
|
-
const p = part;
|
|
197040
|
-
switch (p.type) {
|
|
197041
|
-
case "text":
|
|
197042
|
-
if (typeof p.text === "string")
|
|
197043
|
-
conversation += estimateTokens(p.text);
|
|
197044
|
-
if (typeof p.textSignature === "string")
|
|
197045
|
-
conversation += estimateTokens(p.textSignature);
|
|
197046
|
-
break;
|
|
197047
|
-
case "thinking":
|
|
197048
|
-
if (typeof p.thinking === "string")
|
|
197049
|
-
conversation += estimateTokens(p.thinking);
|
|
197050
|
-
if (typeof p.thinkingSignature === "string")
|
|
197051
|
-
conversation += estimateTokens(p.thinkingSignature);
|
|
197052
|
-
break;
|
|
197053
|
-
case "image":
|
|
197054
|
-
conversation += 1200;
|
|
197055
|
-
break;
|
|
197056
|
-
case "toolCall":
|
|
197057
|
-
if (typeof p.name === "string")
|
|
197058
|
-
toolCall += estimateTokens(p.name);
|
|
197059
|
-
if (p.arguments !== undefined) {
|
|
197060
|
-
const s = typeof p.arguments === "string" ? p.arguments : safeJsonStringify2(p.arguments);
|
|
197061
|
-
if (s)
|
|
197062
|
-
toolCall += estimateTokens(s);
|
|
197063
|
-
}
|
|
197064
|
-
break;
|
|
197065
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");
|
|
197066
198118
|
}
|
|
197067
198119
|
continue;
|
|
197068
198120
|
}
|
|
197069
|
-
|
|
197070
|
-
|
|
197071
|
-
|
|
197072
|
-
|
|
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;
|
|
197073
198135
|
}
|
|
197074
|
-
|
|
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")
|
|
197075
198182
|
continue;
|
|
197076
|
-
|
|
197077
|
-
|
|
197078
|
-
|
|
197079
|
-
|
|
197080
|
-
|
|
197081
|
-
toolCall += estimateTokens(p.text);
|
|
197082
|
-
} else if (p.type === "image") {
|
|
197083
|
-
toolCall += 1200;
|
|
197084
|
-
}
|
|
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;
|
|
197085
198188
|
}
|
|
198189
|
+
if (!isPlainJsonData(descriptor.value, seen))
|
|
198190
|
+
return false;
|
|
197086
198191
|
}
|
|
198192
|
+
return true;
|
|
198193
|
+
} finally {
|
|
198194
|
+
seen.delete(value);
|
|
197087
198195
|
}
|
|
197088
|
-
return { conversation, toolCall };
|
|
197089
198196
|
}
|
|
197090
198197
|
function safeJsonStringify2(value) {
|
|
197091
198198
|
try {
|
|
@@ -197589,6 +198696,9 @@ function applyForwardPressureFloor(trailingPercentage, trailingInputTokens, piUs
|
|
|
197589
198696
|
} : { percentage: trailingPercentage, inputTokens: trailingInputTokens };
|
|
197590
198697
|
}
|
|
197591
198698
|
var injectM0M1PiForRun = injectM0M1Pi;
|
|
198699
|
+
var persistReasoningWatermarkForRun = updateSessionMeta;
|
|
198700
|
+
var persistStableIdSchemeForRun = updateSessionMeta;
|
|
198701
|
+
var afterFallbackAdoptionForTests;
|
|
197592
198702
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
197593
198703
|
var PI_STABLE_ID_SCHEME = 1;
|
|
197594
198704
|
var lastEmergencyNotificationAtMs = new Map;
|
|
@@ -197606,9 +198716,26 @@ var activeContextHandlerSessions = new Set;
|
|
|
197606
198716
|
var lastHeuristicsTurnIdBySession = new Map;
|
|
197607
198717
|
var firstContextPassSeenBySession = new Set;
|
|
197608
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;
|
|
197609
198734
|
function logTransformTiming(sessionId, stage, start, extra) {
|
|
197610
|
-
const
|
|
198735
|
+
const elapsedMs = performance.now() - start;
|
|
198736
|
+
const elapsed = elapsedMs.toFixed(1);
|
|
197611
198737
|
const suffix = extra ? ` ${extra}` : "";
|
|
198738
|
+
recordPiTransformTiming({ sessionId, stage, elapsedMs, extra });
|
|
197612
198739
|
sessionLog(sessionId, `transform stage: stage=${stage} elapsed=${elapsed}ms${suffix}`);
|
|
197613
198740
|
}
|
|
197614
198741
|
function resolvePiContextModelKey(ctx) {
|
|
@@ -197625,6 +198752,35 @@ function resolvePiContextModelKey(ctx) {
|
|
|
197625
198752
|
function readPiSessionMessageById(ctx, messageId) {
|
|
197626
198753
|
return readPiSessionMessages(ctx).find((message) => message.id === messageId) ?? null;
|
|
197627
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
|
+
}
|
|
197628
198784
|
function signalPiHistoryRefresh(sessionId) {
|
|
197629
198785
|
historyRefreshSessions.add(sessionId);
|
|
197630
198786
|
}
|
|
@@ -197776,29 +198932,7 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197776
198932
|
return null;
|
|
197777
198933
|
}
|
|
197778
198934
|
}
|
|
197779
|
-
const
|
|
197780
|
-
const entryIdsByFingerprint = new Map;
|
|
197781
|
-
for (const entry of entries) {
|
|
197782
|
-
if (!entry || typeof entry !== "object")
|
|
197783
|
-
continue;
|
|
197784
|
-
const e = entry;
|
|
197785
|
-
if (e.type !== "message")
|
|
197786
|
-
continue;
|
|
197787
|
-
if (typeof e.id !== "string")
|
|
197788
|
-
continue;
|
|
197789
|
-
if (!e.message || typeof e.message !== "object")
|
|
197790
|
-
continue;
|
|
197791
|
-
const message = e.message;
|
|
197792
|
-
entryIdByMsgRef.set(message, e.id);
|
|
197793
|
-
const fingerprint = piMessageEntryFingerprint(e.message);
|
|
197794
|
-
if (fingerprint) {
|
|
197795
|
-
const bucket = entryIdsByFingerprint.get(fingerprint);
|
|
197796
|
-
if (bucket)
|
|
197797
|
-
bucket.push(e.id);
|
|
197798
|
-
else
|
|
197799
|
-
entryIdsByFingerprint.set(fingerprint, [e.id]);
|
|
197800
|
-
}
|
|
197801
|
-
}
|
|
198935
|
+
const { entryIdByMessageRef, entryIdsByFingerprint } = getPiBranchEntryLookup(entries);
|
|
197802
198936
|
const result = new Array(messages.length);
|
|
197803
198937
|
let resolved = 0;
|
|
197804
198938
|
let fingerprintResolved = 0;
|
|
@@ -197809,7 +198943,7 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197809
198943
|
result[i] = undefined;
|
|
197810
198944
|
continue;
|
|
197811
198945
|
}
|
|
197812
|
-
const id =
|
|
198946
|
+
const id = entryIdByMessageRef.get(msg);
|
|
197813
198947
|
if (typeof id === "string") {
|
|
197814
198948
|
result[i] = id;
|
|
197815
198949
|
resolved += 1;
|
|
@@ -197828,38 +198962,183 @@ function collectMessageEntryIdsByRef(ctx, messages, sessionId, preloadedBranchEn
|
|
|
197828
198962
|
}
|
|
197829
198963
|
}
|
|
197830
198964
|
if (resolved < messages.length) {
|
|
197831
|
-
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`);
|
|
197832
198966
|
}
|
|
197833
198967
|
return result;
|
|
197834
198968
|
}
|
|
197835
|
-
function
|
|
197836
|
-
|
|
197837
|
-
|
|
197838
|
-
|
|
197839
|
-
|
|
197840
|
-
|
|
197841
|
-
|
|
197842
|
-
|
|
197843
|
-
|
|
197844
|
-
|
|
197845
|
-
|
|
197846
|
-
|
|
197847
|
-
|
|
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")
|
|
197848
199000
|
continue;
|
|
197849
|
-
|
|
199001
|
+
compactionIndex = index;
|
|
199002
|
+
firstKeptEntryId = typeof row.firstKeptEntryId === "string" ? row.firstKeptEntryId : undefined;
|
|
199003
|
+
break;
|
|
197850
199004
|
}
|
|
197851
|
-
|
|
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;
|
|
197852
199043
|
}
|
|
197853
199044
|
function readPiBranchEntriesForContext(ctx, sessionId) {
|
|
197854
199045
|
const sm = ctx.sessionManager;
|
|
197855
|
-
|
|
197856
|
-
|
|
197857
|
-
|
|
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;
|
|
197858
199065
|
const entries = sm.getBranch.call(sm);
|
|
197859
|
-
|
|
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);
|
|
197860
199134
|
} catch (error51) {
|
|
197861
|
-
sessionLog(sessionId, `Pi branch
|
|
197862
|
-
|
|
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
|
+
}
|
|
197863
199142
|
}
|
|
197864
199143
|
}
|
|
197865
199144
|
function piMessageEntryFingerprint(message) {
|
|
@@ -197893,13 +199172,15 @@ function firstPiTextContent(content) {
|
|
|
197893
199172
|
}
|
|
197894
199173
|
return null;
|
|
197895
199174
|
}
|
|
197896
|
-
function buildEntryFingerprintMap(messages, resolveStableId2) {
|
|
199175
|
+
function buildEntryFingerprintMap(messages, resolveStableId2, reusableMessageIds, includeReusable = true) {
|
|
197897
199176
|
const map2 = new Map;
|
|
197898
199177
|
for (let i = 0;i < messages.length; i++) {
|
|
197899
199178
|
const msg = messages[i];
|
|
197900
199179
|
const id = resolveStableId2(msg, i);
|
|
197901
199180
|
if (!id)
|
|
197902
199181
|
continue;
|
|
199182
|
+
if (!includeReusable && reusableMessageIds?.has(id))
|
|
199183
|
+
continue;
|
|
197903
199184
|
const fp = piMessageEntryFingerprint(msg);
|
|
197904
199185
|
if (fp)
|
|
197905
199186
|
map2.set(id, fp);
|
|
@@ -197983,8 +199264,10 @@ function hasAdoptablePiFallbackMessageTags(db, sessionId, fingerprintById) {
|
|
|
197983
199264
|
return false;
|
|
197984
199265
|
}
|
|
197985
199266
|
function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {}) {
|
|
197986
|
-
const
|
|
197987
|
-
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);
|
|
197988
199271
|
if (!shouldRunMessageMigration && !shouldRunToolOwnerMigration)
|
|
197989
199272
|
return;
|
|
197990
199273
|
runImmediateTransaction(db, () => {
|
|
@@ -198037,14 +199320,13 @@ function adoptPiFallbackTags(db, sessionId, tagger, fingerprintById, options = {
|
|
|
198037
199320
|
tagger.unbindToolTag(sessionId, realOwnerId, row.callId);
|
|
198038
199321
|
}
|
|
198039
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
|
+
}
|
|
198040
199327
|
}
|
|
198041
199328
|
}
|
|
198042
199329
|
}
|
|
198043
|
-
if (options.stampStableIdScheme !== undefined) {
|
|
198044
|
-
updateSessionMeta(db, sessionId, {
|
|
198045
|
-
piStableIdScheme: options.stampStableIdScheme
|
|
198046
|
-
});
|
|
198047
|
-
}
|
|
198048
199330
|
});
|
|
198049
199331
|
}
|
|
198050
199332
|
function registerPiContextHandler(pi, baseOptions) {
|
|
@@ -198077,12 +199359,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198077
199359
|
}
|
|
198078
199360
|
sessionIdForError = sessionId;
|
|
198079
199361
|
const projectDirectory = ctx.cwd;
|
|
199362
|
+
const fullWireMessageCount = event.messages.length;
|
|
198080
199363
|
const options = baseOptions.resolveForProject?.(projectDirectory) ?? baseOptions;
|
|
198081
199364
|
const schedulerConfig = options.scheduler ?? DEFAULT_SCHEDULER_CONFIG;
|
|
198082
199365
|
const scheduler = schedulerFor(options);
|
|
198083
199366
|
const projectIdentity = resolveProjectIdentity(projectDirectory);
|
|
198084
199367
|
updateSessionProjectTracking(sessionId, projectIdentity, options.db);
|
|
198085
199368
|
logTransformTiming(sessionId, "findSessionId", tFindSession, `messages=${event.messages.length}`);
|
|
199369
|
+
const tEntryBranch = performance.now();
|
|
198086
199370
|
const branchEntries = readPiBranchEntriesForContext(ctx, sessionId);
|
|
198087
199371
|
schedulePiTransformDecisionResolve({
|
|
198088
199372
|
db: options.db,
|
|
@@ -198097,15 +199381,39 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198097
199381
|
const unregisterRaw = setRawMessageProvider(sessionId, rawMessageProvider);
|
|
198098
199382
|
rawMessageProviderUnregistersBySession.set(sessionId, unregisterRaw);
|
|
198099
199383
|
scheduleReconciliation(options.db, sessionId, readRawSessionMessages);
|
|
198100
|
-
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
|
+
}
|
|
198101
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}`);
|
|
198102
199405
|
const tLastUser = performance.now();
|
|
198103
199406
|
const latestUser = findLatestUserMessageIdPi(event.messages, buildPiMessageIdByIndex(event.messages, strictEntryIds));
|
|
198104
199407
|
logTransformTiming(sessionId, "findLastUserMessageId", tLastUser);
|
|
199408
|
+
const tMessageIndexScheduling = performance.now();
|
|
198105
199409
|
if (latestUser) {
|
|
198106
|
-
|
|
199410
|
+
const located = branchEntries ? convertLocatedPiUserEntry(branchEntries, latestUser.messageId) : null;
|
|
199411
|
+
scheduleIncrementalIndex(options.db, sessionId, latestUser.messageId, located ?? ((_sessionId, messageId) => readPiSessionMessageById(ctx, messageId)));
|
|
198107
199412
|
}
|
|
198108
|
-
|
|
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);
|
|
198109
199417
|
const isFirstContextPassForSession = !firstContextPassSeenBySession.has(sessionId);
|
|
198110
199418
|
firstContextPassSeenBySession.add(sessionId);
|
|
198111
199419
|
const piUsage = ctx.getContextUsage?.();
|
|
@@ -198209,7 +199517,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198209
199517
|
schedulerDecision = "defer";
|
|
198210
199518
|
}
|
|
198211
199519
|
logTransformTiming(sessionId, "schedulerAndUsage", tScheduler);
|
|
198212
|
-
const piMessageCount =
|
|
199520
|
+
const piMessageCount = fullWireMessageCount;
|
|
198213
199521
|
const looksLikeImportedSession = schedulerDecision === "defer" && usagePercentage === 0 && sessionMeta.lastResponseTime === 0 && piMessageCount >= 50;
|
|
198214
199522
|
if (looksLikeImportedSession) {
|
|
198215
199523
|
schedulerDecision = "execute";
|
|
@@ -198227,8 +199535,9 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198227
199535
|
signalPiPendingMaterialization(sessionId);
|
|
198228
199536
|
sessionLog(sessionId, `stable-id scheme cutover: stored=${storedStableIdScheme} < current=${PI_STABLE_ID_SCHEME} — forcing execute+materialize this pass`);
|
|
198229
199537
|
}
|
|
199538
|
+
const tBoundaryChecks = performance.now();
|
|
198230
199539
|
const schedulerDecisionEarly = schedulerDecision;
|
|
198231
|
-
const midTurn = isMidTurnPi(event, sessionId);
|
|
199540
|
+
const midTurn = isMidTurnPi(event, sessionId, branchEntries);
|
|
198232
199541
|
const bypassReason = detectMidTurnBypassReason({
|
|
198233
199542
|
contextUsage: { percentage: usagePercentage },
|
|
198234
199543
|
sessionMeta,
|
|
@@ -198276,6 +199585,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198276
199585
|
}
|
|
198277
199586
|
}
|
|
198278
199587
|
const isCacheBusting = historyRefreshSessions.has(sessionId);
|
|
199588
|
+
logTransformTiming(sessionId, "boundaryTriggerChecks", tBoundaryChecks);
|
|
198279
199589
|
sessionLog(sessionId, `transform: usage=${usagePercentage.toFixed(1)}% (${usageInputTokens} tokens, limit=${usageContextLimit ?? "?"}) decision=${schedulerDecision}${forceMaterialization ? " force=true" : ""}${isEmergency ? " EMERGENCY=true" : ""}${isCacheBusting ? " busting=true" : ""}`);
|
|
198280
199590
|
logTransformTiming(sessionId, "emergencyRecoveryBlock", tEmergencyRecovery);
|
|
198281
199591
|
const entryIds = strictEntryIds ?? undefined;
|
|
@@ -198284,12 +199594,15 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198284
199594
|
contextLimit: usageContextLimit,
|
|
198285
199595
|
sessionId
|
|
198286
199596
|
}) / 100)) : undefined;
|
|
199597
|
+
logTransformTiming(sessionId, "prePipelineTotal", transformStartTime);
|
|
199598
|
+
const tRunPipeline = performance.now();
|
|
198287
199599
|
const result = await runPipeline({
|
|
198288
199600
|
db: options.db,
|
|
198289
199601
|
tagger,
|
|
198290
199602
|
sessionId,
|
|
198291
199603
|
projectIdentity,
|
|
198292
199604
|
projectDirectory,
|
|
199605
|
+
sessionMeta,
|
|
198293
199606
|
messages: event.messages,
|
|
198294
199607
|
smartDrops: options.smartDrops === true,
|
|
198295
199608
|
protectedTags: options.protectedTags ?? 20,
|
|
@@ -198310,6 +199623,7 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198310
199623
|
} : undefined,
|
|
198311
199624
|
entryIds,
|
|
198312
199625
|
entryIdByRef,
|
|
199626
|
+
reusableMessageIds,
|
|
198313
199627
|
stableIdSchemeCutover,
|
|
198314
199628
|
schedulerDecision,
|
|
198315
199629
|
forceMaterialization: forceMaterialization || isEmergency,
|
|
@@ -198327,8 +199641,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198327
199641
|
readBranchEntries: resolvePiReadBranchEntries(ctx),
|
|
198328
199642
|
isSubagent: sessionMeta.isSubagent
|
|
198329
199643
|
});
|
|
198330
|
-
|
|
198331
|
-
|
|
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) {
|
|
198332
199652
|
recordPendingPiTransformDecision(sessionId, {
|
|
198333
199653
|
tsMs: Date.now(),
|
|
198334
199654
|
decision: schedulerDecision,
|
|
@@ -198341,6 +199661,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198341
199661
|
bustedThisPass: true
|
|
198342
199662
|
}, piDecisionSnapshotNewestAssistant);
|
|
198343
199663
|
}
|
|
199664
|
+
logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
|
|
199665
|
+
const tHistorianScheduling = performance.now();
|
|
198344
199666
|
if (options.historian) {
|
|
198345
199667
|
maybeFireHistorian({
|
|
198346
199668
|
pi,
|
|
@@ -198350,11 +199672,14 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198350
199672
|
historian: options.historian,
|
|
198351
199673
|
isFirstContextPassForSession,
|
|
198352
199674
|
activeTags: result.activeTags,
|
|
198353
|
-
rawMessageProvider
|
|
199675
|
+
rawMessageProvider,
|
|
199676
|
+
taggerFloor
|
|
198354
199677
|
});
|
|
198355
199678
|
}
|
|
199679
|
+
logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
|
|
198356
199680
|
const tPostTransform = performance.now();
|
|
198357
199681
|
let outputMessages = result.messages;
|
|
199682
|
+
const tNoteNudges = performance.now();
|
|
198358
199683
|
try {
|
|
198359
199684
|
outputMessages = applyNoteNudges({
|
|
198360
199685
|
sessionId,
|
|
@@ -198369,15 +199694,17 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198369
199694
|
} catch (err) {
|
|
198370
199695
|
sessionLog(sessionId, `note nudges failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198371
199696
|
}
|
|
199697
|
+
logTransformTiming(sessionId, "noteNudges", tNoteNudges);
|
|
199698
|
+
const tAutoSearch = performance.now();
|
|
198372
199699
|
if (options.autoSearch?.enabled) {
|
|
198373
199700
|
try {
|
|
198374
|
-
await ensureProjectRegisteredFromPiDirectory(projectDirectory, options.db);
|
|
198375
199701
|
outputMessages = await runAutoSearchHintForPi({
|
|
198376
199702
|
sessionId,
|
|
198377
199703
|
db: options.db,
|
|
198378
199704
|
messages: outputMessages,
|
|
198379
199705
|
entryIds: strictEntryIds,
|
|
198380
199706
|
entryIdByRef: result.postCommitEntryIdByRef,
|
|
199707
|
+
ensureProjectRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDirectory, options.db),
|
|
198381
199708
|
options: {
|
|
198382
199709
|
enabled: true,
|
|
198383
199710
|
scoreThreshold: options.autoSearch.scoreThreshold,
|
|
@@ -198390,6 +199717,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198390
199717
|
sessionLog(sessionId, `auto-search failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198391
199718
|
}
|
|
198392
199719
|
}
|
|
199720
|
+
logTransformTiming(sessionId, "autoSearch", tAutoSearch);
|
|
199721
|
+
const tTodoCapture = performance.now();
|
|
198393
199722
|
try {
|
|
198394
199723
|
const sessionMetaForTodo = getOrCreateSessionMeta(options.db, sessionId);
|
|
198395
199724
|
if (!sessionMetaForTodo.isSubagent && sessionMetaForTodo.lastTodoState !== "") {
|
|
@@ -198406,6 +199735,8 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198406
199735
|
} catch (err) {
|
|
198407
199736
|
sessionLog(sessionId, `synthetic todowrite injection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198408
199737
|
}
|
|
199738
|
+
logTransformTiming(sessionId, "todoCapture", tTodoCapture);
|
|
199739
|
+
const tChannelAccounting = performance.now();
|
|
198409
199740
|
try {
|
|
198410
199741
|
const sessionMetaForCh1 = getOrCreateSessionMeta(options.db, sessionId);
|
|
198411
199742
|
if (!sessionMetaForCh1.isSubagent) {
|
|
@@ -198465,16 +199796,39 @@ function registerPiContextHandler(pi, baseOptions) {
|
|
|
198465
199796
|
} catch (err) {
|
|
198466
199797
|
sessionLog(sessionId, `channel1 baseline / channel2 trigger failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198467
199798
|
}
|
|
199799
|
+
logTransformTiming(sessionId, "channelNudgeAccounting", tChannelAccounting);
|
|
199800
|
+
const tWorkMetrics = performance.now();
|
|
198468
199801
|
try {
|
|
198469
199802
|
const metrics = computePiWorkMetrics(outputMessages);
|
|
198470
199803
|
setSessionWorkMetrics(options.db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
|
|
198471
199804
|
} catch (err) {
|
|
198472
199805
|
sessionLog(sessionId, `work-metrics update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
198473
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);
|
|
198474
199820
|
logTransformTiming(sessionId, "postTransformPhase", tPostTransform);
|
|
198475
|
-
sessionLog(sessionId, `transform completed in ${(performance.now() - transformStartTime).toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
198476
199821
|
clearLastTransformErrorIfSet(options.db, sessionId);
|
|
198477
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})`);
|
|
198478
199832
|
return { messages: outputMessages };
|
|
198479
199833
|
} catch (err) {
|
|
198480
199834
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -198775,7 +200129,7 @@ function maybeFireHistorian(args) {
|
|
|
198775
200129
|
}
|
|
198776
200130
|
return snapshot;
|
|
198777
200131
|
};
|
|
198778
|
-
|
|
200132
|
+
let boundarySnapshot;
|
|
198779
200133
|
let triggered = false;
|
|
198780
200134
|
try {
|
|
198781
200135
|
if (isFirstContextPassForSession) {
|
|
@@ -198785,7 +200139,10 @@ function maybeFireHistorian(args) {
|
|
|
198785
200139
|
sessionLog(sessionId, "historian: cleared stale compartmentInProgress flag on first context pass after restart");
|
|
198786
200140
|
}
|
|
198787
200141
|
const failureState = getHistorianFailureState(db, sessionId);
|
|
198788
|
-
|
|
200142
|
+
if (failureState.failureCount > 0) {
|
|
200143
|
+
boundarySnapshot = resolveRunnablePiBoundarySnapshot();
|
|
200144
|
+
}
|
|
200145
|
+
const shouldRecoverOnFirstPass = failureState.failureCount > 0 && boundarySnapshot !== undefined && hasEligiblePiCompartmentHistory(db, sessionId, boundarySnapshot);
|
|
198789
200146
|
if (shouldRecoverOnFirstPass) {
|
|
198790
200147
|
triggered = true;
|
|
198791
200148
|
sessionLog(sessionId, `historian recovery triggered on session load after ${failureState.failureCount} failure(s)`);
|
|
@@ -198808,12 +200165,18 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
198808
200165
|
return;
|
|
198809
200166
|
}
|
|
198810
200167
|
}
|
|
198811
|
-
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);
|
|
198812
200172
|
if (!trigger.shouldFire) {
|
|
198813
200173
|
sessionLog(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
|
|
198814
200174
|
try {
|
|
198815
200175
|
const overflowState = getOverflowState(db, sessionId);
|
|
198816
|
-
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)) {
|
|
198817
200180
|
clearEmergencyRecovery(db, sessionId);
|
|
198818
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)`);
|
|
198819
200182
|
}
|
|
@@ -198833,7 +200196,7 @@ Historian previously failed ${failureState.failureCount} time(s), so Magic Conte
|
|
|
198833
200196
|
provider: provider2,
|
|
198834
200197
|
unregister,
|
|
198835
200198
|
boundarySnapshot: selectPiHistorianRunBoundarySnapshot({
|
|
198836
|
-
resolvedBoundarySnapshot: boundarySnapshot,
|
|
200199
|
+
resolvedBoundarySnapshot: boundarySnapshot ?? trigger.boundarySnapshot ?? resolveRunnablePiBoundarySnapshot(),
|
|
198837
200200
|
triggerBoundarySnapshot: trigger.boundarySnapshot
|
|
198838
200201
|
}),
|
|
198839
200202
|
refreshBoundarySnapshot: resolveRunnablePiBoundarySnapshot,
|
|
@@ -198856,6 +200219,44 @@ function pendingPiMarkerCoveredByRenderedBoundary(pending, injection) {
|
|
|
198856
200219
|
return true;
|
|
198857
200220
|
return boundary.ordinal !== null && pending.ordinal <= boundary.ordinal;
|
|
198858
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
|
+
}
|
|
198859
200260
|
async function runPipeline(args) {
|
|
198860
200261
|
let executedWorkThisPass = false;
|
|
198861
200262
|
let historyWasConsumedThisPass = false;
|
|
@@ -198884,7 +200285,9 @@ async function runPipeline(args) {
|
|
|
198884
200285
|
}
|
|
198885
200286
|
logTransformTiming(args.sessionId, "injectTemporalMarkers", tTemporal);
|
|
198886
200287
|
}
|
|
200288
|
+
const tTranscriptBuild = performance.now();
|
|
198887
200289
|
const transcript = createPiTranscript(args.messages, args.sessionId, args.entryIds);
|
|
200290
|
+
logTransformTiming(args.sessionId, "transcriptBuild", tTranscriptBuild);
|
|
198888
200291
|
const workingMessages = transcript.getWorkingMessages();
|
|
198889
200292
|
const stableIdResolver = (msg, index) => resolvePiStableId(msg, index, args.entryIds, args.entryIdByRef ?? undefined);
|
|
198890
200293
|
const currentTurnId = (() => {
|
|
@@ -198892,12 +200295,11 @@ async function runPipeline(args) {
|
|
|
198892
200295
|
return findLatestUserMessageIdPi(args.messages, ids)?.messageId ?? null;
|
|
198893
200296
|
})();
|
|
198894
200297
|
const alreadyRanHeuristicsThisTurn = currentTurnId !== null && lastHeuristicsTurnIdBySession.get(args.sessionId) === currentTurnId;
|
|
198895
|
-
const
|
|
198896
|
-
const ctxReduceCallable = !sessionMetaForAvailability.isSubagent;
|
|
200298
|
+
const ctxReduceCallable = !args.sessionMeta.isSubagent;
|
|
198897
200299
|
const canConsumeDeferredLate = args.schedulerDecision === "execute" || args.forceMaterialization === true || args.contextUsage.percentage >= FORCE_MATERIALIZATION_PERCENTAGE;
|
|
198898
200300
|
const deferredMaterializeEligible = canConsumeDeferredLate && deferredMaterializationSessions.has(args.sessionId);
|
|
198899
200301
|
const piHardSignals = args.injection ? (() => {
|
|
198900
|
-
const hardMeta =
|
|
200302
|
+
const hardMeta = args.sessionMeta;
|
|
198901
200303
|
let piTtlMs = 5 * 60 * 1000;
|
|
198902
200304
|
try {
|
|
198903
200305
|
piTtlMs = parseCacheTtl(hardMeta.cacheTtl);
|
|
@@ -198922,28 +200324,44 @@ async function runPipeline(args) {
|
|
|
198922
200324
|
const bypassHistorianGate = args.forceMaterialization === true || m0HardFoldThisPass;
|
|
198923
200325
|
const hasPendingMaterializeSignal = hasPendingMaterialization(args.sessionId);
|
|
198924
200326
|
const shouldRunHeuristics = args.heuristics !== undefined && (!historianRunning || bypassHistorianGate) && (args.forceMaterialization === true || hasPendingMaterializeSignal || deferredMaterializeEligible || m0HardFoldThisPass || args.schedulerDecision === "execute" && !alreadyRanHeuristicsThisTurn);
|
|
198925
|
-
const
|
|
200327
|
+
const tFallbackIdentity = performance.now();
|
|
200328
|
+
const hasFallbackMessageTags = hasPiFallbackMessageTags(args.db, args.sessionId);
|
|
200329
|
+
const entryFingerprintByMessageId = buildEntryFingerprintMap(args.messages, stableIdResolver, args.reusableMessageIds, hasFallbackMessageTags);
|
|
198926
200330
|
adoptPiFallbackTags(args.db, args.sessionId, args.tagger, entryFingerprintByMessageId, {
|
|
198927
200331
|
messages: args.messages,
|
|
198928
200332
|
resolveStableId: stableIdResolver,
|
|
198929
|
-
|
|
200333
|
+
hasFallbackMessageTags
|
|
198930
200334
|
});
|
|
198931
|
-
|
|
198932
|
-
|
|
198933
|
-
sessionId: args.sessionId,
|
|
198934
|
-
reason: "pi.stable-id-scheme.changed"
|
|
198935
|
-
});
|
|
198936
|
-
sessionLog(args.sessionId, `stable-id scheme cutover complete — stamped scheme=${PI_STABLE_ID_SCHEME}`);
|
|
198937
|
-
}
|
|
200335
|
+
logTransformTiming(args.sessionId, "fallbackIdentityAndAdoption", tFallbackIdentity);
|
|
200336
|
+
afterFallbackAdoptionForTests?.(args.stableIdSchemeCutover === true);
|
|
198938
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
|
+
}
|
|
198939
200348
|
const { targets } = tagTranscript(args.sessionId, transcript, args.tagger, args.db, {
|
|
198940
200349
|
skipPrefixInjection: !ctxReduceCallable,
|
|
198941
|
-
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
|
|
198942
200361
|
});
|
|
198943
200362
|
logTransformTiming(args.sessionId, "tagMessages", tTag);
|
|
198944
200363
|
try {
|
|
198945
|
-
|
|
198946
|
-
if (!sessionMeta.isSubagent) {
|
|
200364
|
+
if (!args.sessionMeta.isSubagent) {
|
|
198947
200365
|
const hasRecentCommit = detectRecentCommit(args.messages);
|
|
198948
200366
|
const hadPriorCommitState = commitSeenLastPass.has(args.sessionId);
|
|
198949
200367
|
const sawCommitLastPass = commitSeenLastPass.get(args.sessionId) ?? false;
|
|
@@ -198958,6 +200376,7 @@ async function runPipeline(args) {
|
|
|
198958
200376
|
const deferredMaterializationWasPending = deferredMaterializationSessions.has(args.sessionId);
|
|
198959
200377
|
const deferredHistoryRefreshWasPending = deferredHistoryWasPendingAtPassStart;
|
|
198960
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);
|
|
198961
200380
|
const baseShouldApplyPendingOps = args.schedulerDecision === "execute" || args.forceMaterialization || hasPendingMaterializeSignal || m0HardFoldThisPass;
|
|
198962
200381
|
const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
|
|
198963
200382
|
const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
|
|
@@ -198967,7 +200386,7 @@ async function runPipeline(args) {
|
|
|
198967
200386
|
sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
|
|
198968
200387
|
try {
|
|
198969
200388
|
const tApplyPending = performance.now();
|
|
198970
|
-
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags,
|
|
200389
|
+
pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, targets, args.protectedTags, pendingOperationTags, pendingOps);
|
|
198971
200390
|
if (pendingOpsDidMutate) {
|
|
198972
200391
|
droppedCount += pendingOps.length;
|
|
198973
200392
|
}
|
|
@@ -199023,6 +200442,7 @@ async function runPipeline(args) {
|
|
|
199023
200442
|
}
|
|
199024
200443
|
}
|
|
199025
200444
|
if (args.heuristics?.caveman?.enabled && !args.isSubagent) {
|
|
200445
|
+
const tCavemanReplay = performance.now();
|
|
199026
200446
|
try {
|
|
199027
200447
|
const tags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
|
|
199028
200448
|
const replayed = replayCavemanCompression(args.sessionId, args.db, targets, tags);
|
|
@@ -199032,6 +200452,7 @@ async function runPipeline(args) {
|
|
|
199032
200452
|
} catch (err) {
|
|
199033
200453
|
sessionLog(args.sessionId, `caveman replay failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
199034
200454
|
}
|
|
200455
|
+
logTransformTiming(args.sessionId, "cavemanReplay", tCavemanReplay);
|
|
199035
200456
|
}
|
|
199036
200457
|
let heuristicsExecuted = false;
|
|
199037
200458
|
let heuristicsResult = null;
|
|
@@ -199082,10 +200503,10 @@ async function runPipeline(args) {
|
|
|
199082
200503
|
}
|
|
199083
200504
|
}
|
|
199084
200505
|
if (args.reasoningClearing && shouldRunHeuristics) {
|
|
200506
|
+
const rollbackReasoning = captureReasoningMutationRollback(workingMessages);
|
|
199085
200507
|
try {
|
|
199086
200508
|
const tClearReasoning = performance.now();
|
|
199087
|
-
const
|
|
199088
|
-
const prevWatermark = meta3.clearedReasoningThroughTag ?? 0;
|
|
200509
|
+
const prevWatermark = args.sessionMeta.clearedReasoningThroughTag ?? 0;
|
|
199089
200510
|
const clearOutcome = clearOldReasoningPi({
|
|
199090
200511
|
messages: workingMessages,
|
|
199091
200512
|
messageIdToMaxTag,
|
|
@@ -199100,9 +200521,10 @@ async function runPipeline(args) {
|
|
|
199100
200521
|
});
|
|
199101
200522
|
const combinedWatermark = Math.max(clearOutcome.newWatermark, stripOutcome.newWatermark);
|
|
199102
200523
|
if (combinedWatermark > prevWatermark) {
|
|
199103
|
-
|
|
200524
|
+
persistReasoningWatermarkForRun(args.db, args.sessionId, {
|
|
199104
200525
|
clearedReasoningThroughTag: combinedWatermark
|
|
199105
200526
|
});
|
|
200527
|
+
args.sessionMeta.clearedReasoningThroughTag = combinedWatermark;
|
|
199106
200528
|
sessionLog(args.sessionId, `reasoning cleanup: cleared=${clearOutcome.cleared} inlineStripped=${stripOutcome.stripped} watermark=${prevWatermark}→${combinedWatermark}`);
|
|
199107
200529
|
}
|
|
199108
200530
|
logTransformTiming(args.sessionId, "clearOldReasoning", tClearReasoning);
|
|
@@ -199115,7 +200537,8 @@ async function runPipeline(args) {
|
|
|
199115
200537
|
executedWorkThisPass = true;
|
|
199116
200538
|
}
|
|
199117
200539
|
} catch (err) {
|
|
199118
|
-
|
|
200540
|
+
rollbackReasoning();
|
|
200541
|
+
sessionLog(args.sessionId, `reasoning clearing failed; restored original reasoning: ${err instanceof Error ? err.message : String(err)}`);
|
|
199119
200542
|
}
|
|
199120
200543
|
}
|
|
199121
200544
|
const toolReclaimExecutePass = args.schedulerDecision === "execute";
|
|
@@ -199124,7 +200547,7 @@ async function runPipeline(args) {
|
|
|
199124
200547
|
let autoReclaimTargetCount = 0;
|
|
199125
200548
|
let autoReclaimDidMutate = false;
|
|
199126
200549
|
if (toolReclaimExecutePass && alreadyMutatingThisPass && !emergencyDropEligible) {
|
|
199127
|
-
const reclaimMeta =
|
|
200550
|
+
const reclaimMeta = args.sessionMeta;
|
|
199128
200551
|
const syntheticPendingOps = buildSyntheticToolReclaimOps({
|
|
199129
200552
|
db: args.db,
|
|
199130
200553
|
sessionId: args.sessionId,
|
|
@@ -199170,13 +200593,38 @@ async function runPipeline(args) {
|
|
|
199170
200593
|
}
|
|
199171
200594
|
}
|
|
199172
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();
|
|
199173
200619
|
transcript.commit();
|
|
200620
|
+
logTransformTiming(args.sessionId, "transcriptCommit", tTranscriptCommit);
|
|
199174
200621
|
if (toolReclaimExecutePass) {
|
|
199175
200622
|
advanceToolReclaimWatermarkToCurrentMax(args.db, args.sessionId);
|
|
199176
200623
|
}
|
|
199177
200624
|
if (autoReclaimTargetCount > 0) {
|
|
199178
200625
|
sessionLog(args.sessionId, `tool reclaim auto-drop: targets=${autoReclaimTargetCount} mutated=${autoReclaimDidMutate}`);
|
|
199179
200626
|
}
|
|
200627
|
+
const tPostCommitStableIdMaps = performance.now();
|
|
199180
200628
|
const postCommitStableIdByRef = new Map;
|
|
199181
200629
|
const postCommitEntryIdByRef = new Map;
|
|
199182
200630
|
for (let i = 0;i < args.messages.length; i++) {
|
|
@@ -199191,6 +200639,7 @@ async function runPipeline(args) {
|
|
|
199191
200639
|
postCommitEntryIdByRef.set(m, realId);
|
|
199192
200640
|
}
|
|
199193
200641
|
}
|
|
200642
|
+
logTransformTiming(args.sessionId, "postCommitStableIdMaps", tPostCommitStableIdMaps);
|
|
199194
200643
|
let injectionResult = null;
|
|
199195
200644
|
if (args.injection) {
|
|
199196
200645
|
try {
|
|
@@ -199218,6 +200667,7 @@ async function runPipeline(args) {
|
|
|
199218
200667
|
sessionLog(args.sessionId, `compartment injection failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
199219
200668
|
}
|
|
199220
200669
|
}
|
|
200670
|
+
const tDroppedPlaceholders = performance.now();
|
|
199221
200671
|
stripPiDroppedPlaceholderMessages({
|
|
199222
200672
|
db: args.db,
|
|
199223
200673
|
sessionId: args.sessionId,
|
|
@@ -199226,6 +200676,7 @@ async function runPipeline(args) {
|
|
|
199226
200676
|
stableIdByRef: postCommitStableIdByRef,
|
|
199227
200677
|
forceDiscovery: args.stableIdSchemeCutover === true
|
|
199228
200678
|
});
|
|
200679
|
+
logTransformTiming(args.sessionId, "stripDroppedPlaceholders", tDroppedPlaceholders);
|
|
199229
200680
|
const deferredHistoryDrainEligible = historyWasConsumedThisPass && materializationSatisfiedThisPass && (deferredHistoryWasPendingAtPassStart || hasPendingMaterializeSignal) && !suppressDeferredHistoryDrain && !casLost;
|
|
199230
200681
|
let preserveDeferredMaterializationForMarkerDrain = false;
|
|
199231
200682
|
if (deferredHistoryDrainEligible) {
|
|
@@ -199282,11 +200733,28 @@ async function runPipeline(args) {
|
|
|
199282
200733
|
logTransformTiming(args.sessionId, "batchFinalize:heuristics", performance.now());
|
|
199283
200734
|
const outputMessages = transcript.getOutputMessages();
|
|
199284
200735
|
try {
|
|
199285
|
-
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
|
+
});
|
|
199286
200753
|
updateSessionMeta(args.db, args.sessionId, {
|
|
199287
200754
|
conversationTokens: counts.conversation,
|
|
199288
200755
|
toolCallTokens: counts.toolCall
|
|
199289
200756
|
});
|
|
200757
|
+
logTransformTiming(args.sessionId, "tokenAccounting", tTokenAccounting);
|
|
199290
200758
|
} catch (err) {
|
|
199291
200759
|
sessionLog(args.sessionId, `token accounting failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
199292
200760
|
}
|
|
@@ -199308,15 +200776,18 @@ async function runPipeline(args) {
|
|
|
199308
200776
|
emergency,
|
|
199309
200777
|
bustedThisPass,
|
|
199310
200778
|
targetCount: targets.size,
|
|
199311
|
-
reasoningWatermark:
|
|
200779
|
+
reasoningWatermark: args.sessionMeta.clearedReasoningThroughTag ?? 0,
|
|
199312
200780
|
activeTags,
|
|
199313
200781
|
postCommitEntryIdByRef
|
|
199314
200782
|
};
|
|
199315
200783
|
}
|
|
199316
200784
|
function applyNoteNudges(args) {
|
|
199317
200785
|
const { sessionId, db, messages, projectIdentity, entryIds, entryIdByRef } = args;
|
|
200786
|
+
const tNoteIndexMaps = performance.now();
|
|
199318
200787
|
const messageIdByIndex = buildPiMessageIdByIndex(messages, entryIds, false, entryIdByRef);
|
|
199319
200788
|
const replayMessageIdByIndex = buildPiMessageIdByIndex(messages, entryIds, true, entryIdByRef);
|
|
200789
|
+
logTransformTiming(sessionId, "noteIndexMaps", tNoteIndexMaps);
|
|
200790
|
+
const tStickyReplay = performance.now();
|
|
199320
200791
|
for (const anchor of getNoteNudgeAnchors(db, sessionId)) {
|
|
199321
200792
|
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, anchor.messageId, anchor.text);
|
|
199322
200793
|
}
|
|
@@ -199325,6 +200796,7 @@ function applyNoteNudges(args) {
|
|
|
199325
200796
|
appendReminderToUserMessageByIdPi(messages, replayMessageIdByIndex, decision.messageId, decision.text);
|
|
199326
200797
|
}
|
|
199327
200798
|
}
|
|
200799
|
+
logTransformTiming(sessionId, "stickyReplayDecisions", tStickyReplay);
|
|
199328
200800
|
const latestUser = findLatestUserMessageIdPi(messages, messageIdByIndex);
|
|
199329
200801
|
const latestUserId = latestUser?.messageId ?? null;
|
|
199330
200802
|
const noteReadStillVisible = hasVisibleNoteReadCallPi(messages);
|
|
@@ -199393,9 +200865,9 @@ function buildPiMessageIdByIndex(messages, entryIds, includeMessageIdFallback =
|
|
|
199393
200865
|
}
|
|
199394
200866
|
continue;
|
|
199395
200867
|
}
|
|
199396
|
-
const
|
|
199397
|
-
if (typeof
|
|
199398
|
-
ids.set(index,
|
|
200868
|
+
const entryId2 = entryIds?.[index];
|
|
200869
|
+
if (typeof entryId2 === "string") {
|
|
200870
|
+
ids.set(index, entryId2);
|
|
199399
200871
|
continue;
|
|
199400
200872
|
}
|
|
199401
200873
|
if (includeMessageIdFallback) {
|
|
@@ -199469,6 +200941,17 @@ function clearContextHandlerSession(sessionId) {
|
|
|
199469
200941
|
firstContextPassSeenBySession.delete(sessionId);
|
|
199470
200942
|
commitSeenLastPass.delete(sessionId);
|
|
199471
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);
|
|
199472
200955
|
clearPiChannel1State(sessionId);
|
|
199473
200956
|
lastHeuristicsTurnIdBySession.delete(sessionId);
|
|
199474
200957
|
lastSeenProjectIdentityBySession.delete(sessionId);
|
|
@@ -201904,9 +203387,8 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
|
|
|
201904
203387
|
const compartments = getCompartments(db, sessionId);
|
|
201905
203388
|
let historyBlockTokens = 0;
|
|
201906
203389
|
for (const c of compartments) {
|
|
201907
|
-
historyBlockTokens += estimateTokens(
|
|
203390
|
+
historyBlockTokens += estimateTokens(`## ${c.startMessage}-${c.endMessage} · ${c.title}
|
|
201908
203391
|
${c.content}
|
|
201909
|
-
</compartment>
|
|
201910
203392
|
`);
|
|
201911
203393
|
}
|
|
201912
203394
|
const budgetTokens = historyBudgetPercentage && displayContextLimit > 0 ? Math.floor(displayContextLimit * (Math.min(executeThresholdPercentage, 80) / 100) * historyBudgetPercentage) : null;
|
|
@@ -201958,9 +203440,8 @@ function computeM0BlockTokens(db, sessionId, args) {
|
|
|
201958
203440
|
try {
|
|
201959
203441
|
const compRows = db.prepare("SELECT content, title, start_message, end_message FROM compartments WHERE session_id = ?").all(sessionId);
|
|
201960
203442
|
for (const c of compRows) {
|
|
201961
|
-
compartmentTokens += estimateTokens(
|
|
203443
|
+
compartmentTokens += estimateTokens(`## ${c.start_message}-${c.end_message} · ${c.title}
|
|
201962
203444
|
${c.content}
|
|
201963
|
-
</compartment>
|
|
201964
203445
|
`);
|
|
201965
203446
|
}
|
|
201966
203447
|
} catch {}
|
|
@@ -201990,7 +203471,7 @@ function formatThresholdPercent(value) {
|
|
|
201990
203471
|
// package.json
|
|
201991
203472
|
var package_default = {
|
|
201992
203473
|
name: "@cortexkit/pi-magic-context",
|
|
201993
|
-
version: "0.
|
|
203474
|
+
version: "0.32.0",
|
|
201994
203475
|
type: "module",
|
|
201995
203476
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
201996
203477
|
main: "dist/index.js",
|
|
@@ -202969,9 +204450,9 @@ function stripTagPrefixFromAssistantMessage(message) {
|
|
|
202969
204450
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
202970
204451
|
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
202971
204452
|
|
|
202972
|
-
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:
|
|
202973
204454
|
|
|
202974
|
-
ctx_expand(start=120, end=245) ← the
|
|
204455
|
+
ctx_expand(start=120, end=245) ← the heading's start/end range
|
|
202975
204456
|
|
|
202976
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.
|
|
202977
204458
|
|
|
@@ -208514,6 +209995,8 @@ var STATUS_COLOR = {
|
|
|
208514
209995
|
cancelled: "error"
|
|
208515
209996
|
};
|
|
208516
209997
|
var snapshotsBySession = new Map;
|
|
209998
|
+
var MAX_TODOWRITE_RENDER_CACHE_ENTRIES = 50;
|
|
209999
|
+
var cachedTodowriteTodosByToolCallId = new Map;
|
|
208517
210000
|
function isTodoStatus2(value) {
|
|
208518
210001
|
return TODO_STATUSES.includes(value);
|
|
208519
210002
|
}
|
|
@@ -208523,6 +210006,27 @@ function isTodoPriority2(value) {
|
|
|
208523
210006
|
function cloneTodos(todos) {
|
|
208524
210007
|
return todos.map((todo) => ({ ...todo }));
|
|
208525
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
|
+
}
|
|
208526
210030
|
function parseTodos(input) {
|
|
208527
210031
|
if (!Array.isArray(input))
|
|
208528
210032
|
return null;
|
|
@@ -208659,25 +210163,27 @@ function capTodoRows(rows) {
|
|
|
208659
210163
|
hiddenCount: rows.length - visibleCount
|
|
208660
210164
|
};
|
|
208661
210165
|
}
|
|
208662
|
-
function renderTodowriteCall(args, theme) {
|
|
208663
|
-
const todos = parseTodos(args.todos) ?? [];
|
|
210166
|
+
function renderTodowriteCall(args, theme, context) {
|
|
210167
|
+
const todos = getCachedTodowriteToolCallTodos(context?.toolCallId) ?? parseTodos(args.todos) ?? [];
|
|
208664
210168
|
const active = activeTitleCount(todos);
|
|
208665
210169
|
const activeColor = active > 0 ? "warning" : "success";
|
|
208666
210170
|
const line = `${theme.fg("toolTitle", theme.bold("Todos"))} ${theme.fg("muted", "—")} ${theme.fg(activeColor, `${active} active`)}`;
|
|
208667
210171
|
return lineComponent((width) => [truncateToWidth2(line, width, "…")]);
|
|
208668
210172
|
}
|
|
208669
|
-
function renderTodowriteResult(result, theme) {
|
|
210173
|
+
function renderTodowriteResult(result, theme, context) {
|
|
208670
210174
|
const detailsTodos = result.details?.todos;
|
|
208671
210175
|
let todos = parseTodos(detailsTodos);
|
|
208672
|
-
if (todos === null && Array.isArray(result.content)) {
|
|
210176
|
+
if ((todos === null || todos.length === 0) && Array.isArray(result.content)) {
|
|
208673
210177
|
const text = result.content.find((part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string")?.text;
|
|
208674
210178
|
if (text) {
|
|
208675
210179
|
try {
|
|
208676
|
-
|
|
210180
|
+
const parsed = parseTodos(JSON.parse(text));
|
|
210181
|
+
if (parsed !== null)
|
|
210182
|
+
todos = parsed;
|
|
208677
210183
|
} catch {}
|
|
208678
210184
|
}
|
|
208679
210185
|
}
|
|
208680
|
-
const renderedTodos = todos ?? [];
|
|
210186
|
+
const renderedTodos = todos !== null && todos.length > 0 ? todos : getCachedTodowriteToolCallTodos(context?.toolCallId) ?? todos ?? [];
|
|
208681
210187
|
return lineComponent((width) => {
|
|
208682
210188
|
if (renderedTodos.length === 0)
|
|
208683
210189
|
return [theme.fg("dim", "No todos")];
|
|
@@ -208878,6 +210384,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
208878
210384
|
overlay.hideCompletedTasksFromPreviousTurn();
|
|
208879
210385
|
});
|
|
208880
210386
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
210387
|
+
clearTodowriteToolCallTodos();
|
|
208881
210388
|
const sessionId = getSessionId(ctx);
|
|
208882
210389
|
if (!sessionId)
|
|
208883
210390
|
return;
|
|
@@ -208885,6 +210392,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
208885
210392
|
overlay.disposeSession(sessionId);
|
|
208886
210393
|
});
|
|
208887
210394
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
210395
|
+
clearTodowriteToolCallTodos();
|
|
208888
210396
|
const sessionId = getSessionId(ctx);
|
|
208889
210397
|
if (!sessionId)
|
|
208890
210398
|
return;
|
|
@@ -208901,11 +210409,13 @@ function registerTodoStateLifecycle(pi, deps) {
|
|
|
208901
210409
|
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
208902
210410
|
});
|
|
208903
210411
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
210412
|
+
clearTodowriteToolCallTodos();
|
|
208904
210413
|
const sessionId = getSessionId(ctx);
|
|
208905
210414
|
if (sessionId)
|
|
208906
210415
|
clearTodoSnapshot(sessionId);
|
|
208907
210416
|
});
|
|
208908
210417
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
210418
|
+
clearTodowriteToolCallTodos();
|
|
208909
210419
|
const sessionId = getSessionId(ctx);
|
|
208910
210420
|
if (sessionId)
|
|
208911
210421
|
clearTodoSnapshot(sessionId);
|
|
@@ -208956,11 +210466,11 @@ function createTodowriteTool() {
|
|
|
208956
210466
|
}
|
|
208957
210467
|
};
|
|
208958
210468
|
},
|
|
208959
|
-
renderCall(args, theme) {
|
|
208960
|
-
return renderTodowriteCall(args, theme);
|
|
210469
|
+
renderCall(args, theme, context) {
|
|
210470
|
+
return renderTodowriteCall(args, theme, context);
|
|
208961
210471
|
},
|
|
208962
|
-
renderResult(result, _opts, theme) {
|
|
208963
|
-
return renderTodowriteResult(result, theme);
|
|
210472
|
+
renderResult(result, _opts, theme, context) {
|
|
210473
|
+
return renderTodowriteResult(result, theme, context);
|
|
208964
210474
|
}
|
|
208965
210475
|
};
|
|
208966
210476
|
}
|
|
@@ -209038,9 +210548,13 @@ function getCompatiblePiTodoCapture(todos) {
|
|
|
209038
210548
|
const normalized = normalizeTodoStateJson(todos);
|
|
209039
210549
|
if (normalized === null)
|
|
209040
210550
|
return null;
|
|
209041
|
-
|
|
210551
|
+
const parsed = parseTodos(todos);
|
|
210552
|
+
if (parsed === null)
|
|
210553
|
+
return null;
|
|
210554
|
+
return { normalized, todos: parsed };
|
|
209042
210555
|
}
|
|
209043
210556
|
function applyCompatiblePiTodoCapture(args) {
|
|
210557
|
+
rememberTodowriteToolCallTodos(args.toolCallId, args.capture.todos);
|
|
209044
210558
|
if (args.todowriteEnabled) {
|
|
209045
210559
|
setTodoSnapshot(args.sessionId, args.capture.todos);
|
|
209046
210560
|
args.todoOverlay?.update(args.sessionId);
|
|
@@ -209185,7 +210699,7 @@ async function persistPiPressureFromMessageEnd(args) {
|
|
|
209185
210699
|
}
|
|
209186
210700
|
var PLUGIN_VERSION = (() => {
|
|
209187
210701
|
try {
|
|
209188
|
-
const req =
|
|
210702
|
+
const req = createRequire4(import.meta.url);
|
|
209189
210703
|
return req("../package.json").version;
|
|
209190
210704
|
} catch {
|
|
209191
210705
|
return "0.0.0";
|
|
@@ -209357,11 +210871,11 @@ async function src_default2(pi) {
|
|
|
209357
210871
|
projectIdentity: identity,
|
|
209358
210872
|
memoryEnabled: cfg.memory.enabled
|
|
209359
210873
|
}, sessionId, dir, identity, (text) => {
|
|
209360
|
-
pi
|
|
209361
|
-
|
|
209362
|
-
|
|
209363
|
-
|
|
209364
|
-
}
|
|
210874
|
+
sendCtxStatusMessage(pi, {
|
|
210875
|
+
title: "/ctx-embed",
|
|
210876
|
+
text,
|
|
210877
|
+
level: "info"
|
|
210878
|
+
});
|
|
209365
210879
|
});
|
|
209366
210880
|
}
|
|
209367
210881
|
});
|
|
@@ -209429,6 +210943,12 @@ async function src_default2(pi) {
|
|
|
209429
210943
|
todowriteEnabled
|
|
209430
210944
|
});
|
|
209431
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
|
+
});
|
|
209432
210952
|
const readLastTodoState = (sessionId) => getOrCreateSessionMeta(db, sessionId).lastTodoState;
|
|
209433
210953
|
if (todowriteEnabled) {
|
|
209434
210954
|
registerTodoStateLifecycle(pi, { readLastTodoState });
|
|
@@ -209442,6 +210962,8 @@ async function src_default2(pi) {
|
|
|
209442
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)");
|
|
209443
210963
|
registerCtxAugCommand(pi, (ctx) => resolveCurrentProjectDeps(ctx).sidekickConfig);
|
|
209444
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");
|
|
209445
210967
|
const recompRunner = new PiSubagentRunner;
|
|
209446
210968
|
const wrapupRunner = new PiSubagentRunner;
|
|
209447
210969
|
const upgradeRunner = new PiSubagentRunner;
|
|
@@ -209769,6 +211291,7 @@ ${block}` : event.systemPrompt;
|
|
|
209769
211291
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
209770
211292
|
if (event.toolName === "todowrite") {
|
|
209771
211293
|
const todoArgs = event.args;
|
|
211294
|
+
const toolCallId = typeof event.toolCallId === "string" ? event.toolCallId : undefined;
|
|
209772
211295
|
const todos = todoArgs?.todos;
|
|
209773
211296
|
const sessionMeta = Array.isArray(todos) ? getOrCreateSessionMeta(db, sessionId) : null;
|
|
209774
211297
|
capturePiTodowriteArgsIfCompatible({
|
|
@@ -209777,7 +211300,8 @@ ${block}` : event.systemPrompt;
|
|
|
209777
211300
|
todos,
|
|
209778
211301
|
todowriteEnabled,
|
|
209779
211302
|
todoOverlay,
|
|
209780
|
-
persist: Boolean(sessionMeta && !sessionMeta.isSubagent)
|
|
211303
|
+
persist: Boolean(sessionMeta && !sessionMeta.isSubagent),
|
|
211304
|
+
toolCallId
|
|
209781
211305
|
});
|
|
209782
211306
|
if (Array.isArray(todos) && todos.length > 0 && todos.every((t) => t.status === "completed" || t.status === "cancelled")) {
|
|
209783
211307
|
if (sessionMeta && !sessionMeta.isSubagent) {
|