@cortexkit/pi-magic-context 0.31.4 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2298 -707
- package/dist/subagent-entry.js +482 -114
- package/package.json +1 -1
package/dist/subagent-entry.js
CHANGED
|
@@ -159849,8 +159849,11 @@ var MagicContextConfigSchema = exports_external.object({
|
|
|
159849
159849
|
provider: "local",
|
|
159850
159850
|
model: DEFAULT_LOCAL_EMBEDDING_MODEL
|
|
159851
159851
|
}).describe("Embedding provider configuration"),
|
|
159852
|
-
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
|
|
159852
|
+
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).'),
|
|
159853
159853
|
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."),
|
|
159854
|
+
shadow_transform: exports_external.object({
|
|
159855
|
+
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.")
|
|
159856
|
+
}).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."),
|
|
159854
159857
|
todowrite: exports_external.object({
|
|
159855
159858
|
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."),
|
|
159856
159859
|
overlay: exports_external.boolean().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
|
|
@@ -160007,6 +160010,10 @@ function stripUnsafeProjectConfigFields(projectRaw) {
|
|
|
160007
160010
|
delete projectRaw.sqlite;
|
|
160008
160011
|
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).");
|
|
160009
160012
|
}
|
|
160013
|
+
if ("shadow_transform" in projectRaw) {
|
|
160014
|
+
delete projectRaw.shadow_transform;
|
|
160015
|
+
warnings.push("Ignoring shadow_transform from project config (security: this developer-only mirror lane is user-level only).");
|
|
160016
|
+
}
|
|
160010
160017
|
const embedding = projectRaw.embedding;
|
|
160011
160018
|
if (isPlainObject3(embedding)) {
|
|
160012
160019
|
const removed = [];
|
|
@@ -160679,6 +160686,9 @@ function loadPiConfigDetailed(opts = {}) {
|
|
|
160679
160686
|
};
|
|
160680
160687
|
}
|
|
160681
160688
|
|
|
160689
|
+
// src/embedding-bootstrap.ts
|
|
160690
|
+
import { statSync as statSync3 } from "node:fs";
|
|
160691
|
+
|
|
160682
160692
|
// ../plugin/src/features/magic-context/memory/embedding.ts
|
|
160683
160693
|
init_logger();
|
|
160684
160694
|
|
|
@@ -163471,8 +163481,38 @@ function handleUntrustedLoad(db, projectIdentity, directory, detailed) {
|
|
|
163471
163481
|
}
|
|
163472
163482
|
|
|
163473
163483
|
// src/embedding-bootstrap.ts
|
|
163484
|
+
var registrationFingerprintsByDatabase = new WeakMap;
|
|
163485
|
+
function configCandidatePaths(directory, loadedPaths) {
|
|
163486
|
+
const projectBase = cortexKitProjectConfigBasePath(directory);
|
|
163487
|
+
const userBase = cortexKitUserConfigBasePath();
|
|
163488
|
+
return [
|
|
163489
|
+
`${projectBase}.jsonc`,
|
|
163490
|
+
`${projectBase}.json`,
|
|
163491
|
+
`${userBase}.jsonc`,
|
|
163492
|
+
`${userBase}.json`,
|
|
163493
|
+
...loadedPaths
|
|
163494
|
+
].filter((path4, index, paths) => paths.indexOf(path4) === index);
|
|
163495
|
+
}
|
|
163496
|
+
function configFingerprint(paths) {
|
|
163497
|
+
return paths.map((path4) => {
|
|
163498
|
+
try {
|
|
163499
|
+
const stat2 = statSync3(path4);
|
|
163500
|
+
return `${path4}:${stat2.size}:${stat2.mtimeMs}`;
|
|
163501
|
+
} catch {
|
|
163502
|
+
return `${path4}:missing`;
|
|
163503
|
+
}
|
|
163504
|
+
}).join("|");
|
|
163505
|
+
}
|
|
163474
163506
|
async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
163475
163507
|
const projectIdentity = resolveProjectIdentity(directory);
|
|
163508
|
+
let registrationFingerprints = registrationFingerprintsByDatabase.get(db);
|
|
163509
|
+
if (!registrationFingerprints) {
|
|
163510
|
+
registrationFingerprints = new Map;
|
|
163511
|
+
registrationFingerprintsByDatabase.set(db, registrationFingerprints);
|
|
163512
|
+
}
|
|
163513
|
+
const cached2 = registrationFingerprints.get(projectIdentity);
|
|
163514
|
+
if (cached2 && configFingerprint(cached2.paths) === cached2.fingerprint)
|
|
163515
|
+
return;
|
|
163476
163516
|
const detailed = loadPiConfigDetailed({ cwd: directory });
|
|
163477
163517
|
if (isConfigLoadUntrusted(detailed)) {
|
|
163478
163518
|
handleUntrustedLoad(db, projectIdentity, directory, detailed);
|
|
@@ -163483,6 +163523,11 @@ async function ensureProjectRegisteredFromPiDirectory(directory, db) {
|
|
|
163483
163523
|
gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
|
|
163484
163524
|
};
|
|
163485
163525
|
registerProjectEmbedding(db, projectIdentity, detailed.config.embedding, features, directory);
|
|
163526
|
+
const fingerprintPaths = configCandidatePaths(directory, detailed.loadedFromPaths);
|
|
163527
|
+
registrationFingerprints.set(projectIdentity, {
|
|
163528
|
+
paths: fingerprintPaths,
|
|
163529
|
+
fingerprint: configFingerprint(fingerprintPaths)
|
|
163530
|
+
});
|
|
163486
163531
|
}
|
|
163487
163532
|
// ../plugin/src/features/magic-context/compartment-lease.ts
|
|
163488
163533
|
var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
|
|
@@ -164102,6 +164147,12 @@ function parseJsonRecord(value) {
|
|
|
164102
164147
|
return null;
|
|
164103
164148
|
}
|
|
164104
164149
|
}
|
|
164150
|
+
function isRawCompactionSummaryInfo(info) {
|
|
164151
|
+
if (info === null || typeof info !== "object" || Array.isArray(info))
|
|
164152
|
+
return false;
|
|
164153
|
+
const candidate = info;
|
|
164154
|
+
return candidate.summary === true && candidate.finish === "stop";
|
|
164155
|
+
}
|
|
164105
164156
|
function parseJsonUnknown(value) {
|
|
164106
164157
|
try {
|
|
164107
164158
|
return JSON.parse(value);
|
|
@@ -164124,7 +164175,7 @@ function attachRawPartVersion(value, timeUpdated) {
|
|
|
164124
164175
|
return value;
|
|
164125
164176
|
}
|
|
164126
164177
|
function readRawSessionMessagesFromDb(db, sessionId) {
|
|
164127
|
-
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);
|
|
164178
|
+
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);
|
|
164128
164179
|
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);
|
|
164129
164180
|
const partsByMessageId = new Map;
|
|
164130
164181
|
for (const part of partRows) {
|
|
@@ -164132,10 +164183,7 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
164132
164183
|
list.push(attachRawPartVersion(parseJsonUnknown(part.data), part.time_updated));
|
|
164133
164184
|
partsByMessageId.set(part.message_id, list);
|
|
164134
164185
|
}
|
|
164135
|
-
const filtered = messageRows.filter((row) =>
|
|
164136
|
-
const info = parseJsonRecord(row.data);
|
|
164137
|
-
return !(info?.summary === true && info?.finish === "stop");
|
|
164138
|
-
});
|
|
164186
|
+
const filtered = messageRows.filter((row) => !isRawCompactionSummaryInfo(parseJsonRecord(row.data)));
|
|
164139
164187
|
return filtered.flatMap((row, index) => {
|
|
164140
164188
|
const info = parseJsonRecord(row.data);
|
|
164141
164189
|
if (!info)
|
|
@@ -164146,6 +164194,7 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
164146
164194
|
id: row.id,
|
|
164147
164195
|
role,
|
|
164148
164196
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
164197
|
+
createdAt: row.time_created ?? null,
|
|
164149
164198
|
version: row.time_updated ?? null
|
|
164150
164199
|
};
|
|
164151
164200
|
});
|
|
@@ -164160,7 +164209,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
164160
164209
|
const anchorInfo = parseJsonRecord(anchorRow.data ?? "");
|
|
164161
164210
|
if (anchorInfo?.summary === true && anchorInfo?.finish === "stop")
|
|
164162
164211
|
return null;
|
|
164163
|
-
const messageRows = db.prepare(`SELECT id, data, time_updated FROM message
|
|
164212
|
+
const messageRows = db.prepare(`SELECT id, data, time_created, time_updated FROM message
|
|
164164
164213
|
WHERE session_id = ?
|
|
164165
164214
|
AND (time_created > ? OR (time_created = ? AND id >= ?))
|
|
164166
164215
|
ORDER BY time_created ASC, id ASC`).all(sessionId, anchorRow.time_created, anchorRow.time_created, anchorRow.id).filter(isRawMessageRow);
|
|
@@ -164196,6 +164245,7 @@ function readRawSessionTailFromDb(db, sessionId, baseOrdinal, anchorMessageId) {
|
|
|
164196
164245
|
id: row.id,
|
|
164197
164246
|
role: typeof info.role === "string" ? info.role : "unknown",
|
|
164198
164247
|
parts: partsByMessageId.get(row.id) ?? [],
|
|
164248
|
+
createdAt: row.time_created ?? null,
|
|
164199
164249
|
version: row.time_updated ?? null
|
|
164200
164250
|
});
|
|
164201
164251
|
ord += 1;
|
|
@@ -164714,9 +164764,9 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
164714
164764
|
// ../plugin/src/tools/ctx-expand/constants.ts
|
|
164715
164765
|
var CTX_EXPAND_DESCRIPTION = `Recover the original conversation from your compacted history.
|
|
164716
164766
|
|
|
164717
|
-
Older parts of this session are summarized
|
|
164767
|
+
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:
|
|
164718
164768
|
|
|
164719
|
-
ctx_expand(start=120, end=245) ← the
|
|
164769
|
+
ctx_expand(start=120, end=245) ← the heading's start/end range
|
|
164720
164770
|
|
|
164721
164771
|
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.
|
|
164722
164772
|
|
|
@@ -169128,7 +169178,7 @@ function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
|
|
|
169128
169178
|
const role = m.role ?? "unknown";
|
|
169129
169179
|
return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
|
|
169130
169180
|
}
|
|
169131
|
-
function isMidTurnPi(event, _sessionId) {
|
|
169181
|
+
function isMidTurnPi(event, _sessionId, branchEntries) {
|
|
169132
169182
|
const messages = event?.messages;
|
|
169133
169183
|
if (!Array.isArray(messages))
|
|
169134
169184
|
return false;
|
|
@@ -169147,7 +169197,7 @@ function isMidTurnPi(event, _sessionId) {
|
|
|
169147
169197
|
}
|
|
169148
169198
|
if (latestAssistant === null)
|
|
169149
169199
|
return false;
|
|
169150
|
-
if (hasRealUserAfter(messages, latestAssistantIndex))
|
|
169200
|
+
if (hasRealUserAfter(messages, latestAssistantIndex, branchEntries))
|
|
169151
169201
|
return false;
|
|
169152
169202
|
if (latestAssistant.stopReason === "toolUse")
|
|
169153
169203
|
return true;
|
|
@@ -169171,12 +169221,27 @@ function isMidTurnPi(event, _sessionId) {
|
|
|
169171
169221
|
}
|
|
169172
169222
|
return false;
|
|
169173
169223
|
}
|
|
169174
|
-
function hasRealUserAfter(messages, latestAssistantIndex) {
|
|
169175
|
-
|
|
169176
|
-
|
|
169224
|
+
function hasRealUserAfter(messages, latestAssistantIndex, branchEntries) {
|
|
169225
|
+
if (!branchEntries)
|
|
169226
|
+
return false;
|
|
169227
|
+
const genuineUserMessages = new Set;
|
|
169228
|
+
for (const entry of branchEntries) {
|
|
169229
|
+
if (entry === null || typeof entry !== "object")
|
|
169177
169230
|
continue;
|
|
169178
|
-
|
|
169231
|
+
const record4 = entry;
|
|
169232
|
+
if (record4.type !== "message")
|
|
169233
|
+
continue;
|
|
169234
|
+
const message = record4.message;
|
|
169235
|
+
if (message === null || typeof message !== "object")
|
|
169236
|
+
continue;
|
|
169237
|
+
if (message.role === "user") {
|
|
169238
|
+
genuineUserMessages.add(message);
|
|
169239
|
+
}
|
|
169240
|
+
}
|
|
169241
|
+
for (const msg of messages.slice(latestAssistantIndex + 1)) {
|
|
169242
|
+
if (msg !== null && typeof msg === "object" && genuineUserMessages.has(msg)) {
|
|
169179
169243
|
return true;
|
|
169244
|
+
}
|
|
169180
169245
|
}
|
|
169181
169246
|
return false;
|
|
169182
169247
|
}
|
|
@@ -170406,7 +170471,7 @@ function getMemoryVerifications(db, memoryIds) {
|
|
|
170406
170471
|
}
|
|
170407
170472
|
// ../plugin/src/features/magic-context/memory/verification-paths.ts
|
|
170408
170473
|
import { execFile } from "node:child_process";
|
|
170409
|
-
import { existsSync as existsSync9, realpathSync as realpathSync2, statSync as
|
|
170474
|
+
import { existsSync as existsSync9, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
|
|
170410
170475
|
import path4 from "node:path";
|
|
170411
170476
|
import { promisify } from "node:util";
|
|
170412
170477
|
var execFileAsync = promisify(execFile);
|
|
@@ -170548,7 +170613,7 @@ async function normalizeVerificationFiles(args) {
|
|
|
170548
170613
|
}
|
|
170549
170614
|
if (existsSync9(candidate)) {
|
|
170550
170615
|
try {
|
|
170551
|
-
if (
|
|
170616
|
+
if (statSync4(candidate).isDirectory()) {
|
|
170552
170617
|
warnings.push(`Skipped verification path "${value}" because it is a directory.`);
|
|
170553
170618
|
continue;
|
|
170554
170619
|
}
|
|
@@ -170798,7 +170863,7 @@ function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal,
|
|
|
170798
170863
|
}
|
|
170799
170864
|
// ../plugin/src/features/magic-context/project-docs-hash.ts
|
|
170800
170865
|
import { createHash as createHash7 } from "node:crypto";
|
|
170801
|
-
import { lstatSync, readFileSync as readFileSync5, statSync as
|
|
170866
|
+
import { lstatSync, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
|
|
170802
170867
|
import path5 from "node:path";
|
|
170803
170868
|
var PROJECT_DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
170804
170869
|
var PROJECT_DOCS_DELIMITER = `
|
|
@@ -170829,7 +170894,7 @@ function fingerprintFile(filePath) {
|
|
|
170829
170894
|
}
|
|
170830
170895
|
function readDirectoryMtimeMs(projectDirectory) {
|
|
170831
170896
|
try {
|
|
170832
|
-
return
|
|
170897
|
+
return statSync5(projectDirectory).mtimeMs;
|
|
170833
170898
|
} catch {
|
|
170834
170899
|
return 0;
|
|
170835
170900
|
}
|
|
@@ -170919,6 +170984,160 @@ function readProjectDocsCanonical(projectDirectory) {
|
|
|
170919
170984
|
});
|
|
170920
170985
|
return { renderedBlock, canonicalHash };
|
|
170921
170986
|
}
|
|
170987
|
+
// ../plugin/src/features/magic-context/storage-clone.ts
|
|
170988
|
+
function runImmediate2(db, body) {
|
|
170989
|
+
db.exec("BEGIN IMMEDIATE");
|
|
170990
|
+
let committed = false;
|
|
170991
|
+
try {
|
|
170992
|
+
const result = body();
|
|
170993
|
+
db.exec("COMMIT");
|
|
170994
|
+
committed = true;
|
|
170995
|
+
return result;
|
|
170996
|
+
} finally {
|
|
170997
|
+
if (!committed) {
|
|
170998
|
+
try {
|
|
170999
|
+
db.exec("ROLLBACK");
|
|
171000
|
+
} catch {}
|
|
171001
|
+
}
|
|
171002
|
+
}
|
|
171003
|
+
}
|
|
171004
|
+
function countRows(db, table, sessionId) {
|
|
171005
|
+
const row = db.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE session_id = ?`).get(sessionId);
|
|
171006
|
+
return typeof row?.count === "number" ? row.count : 0;
|
|
171007
|
+
}
|
|
171008
|
+
function filterIdBlob(raw, includeMessageId) {
|
|
171009
|
+
if (!raw)
|
|
171010
|
+
return "";
|
|
171011
|
+
try {
|
|
171012
|
+
const value = JSON.parse(raw);
|
|
171013
|
+
if (!Array.isArray(value))
|
|
171014
|
+
return "";
|
|
171015
|
+
const filtered = value.filter((id) => typeof id === "string" && includeMessageId(id));
|
|
171016
|
+
return filtered.length > 0 ? JSON.stringify(filtered) : "";
|
|
171017
|
+
} catch {
|
|
171018
|
+
return "";
|
|
171019
|
+
}
|
|
171020
|
+
}
|
|
171021
|
+
function clampWatermark(value, maxCopiedTag) {
|
|
171022
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
171023
|
+
return 0;
|
|
171024
|
+
return Math.min(Math.floor(value), maxCopiedTag);
|
|
171025
|
+
}
|
|
171026
|
+
function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
|
|
171027
|
+
return runImmediate2(db, () => {
|
|
171028
|
+
if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0) {
|
|
171029
|
+
return {
|
|
171030
|
+
kind: "destination-not-empty",
|
|
171031
|
+
compartmentsCopied: 0,
|
|
171032
|
+
tagsCopied: 0,
|
|
171033
|
+
pendingOpsCopied: 0,
|
|
171034
|
+
pendingMarkerMigrated: false
|
|
171035
|
+
};
|
|
171036
|
+
}
|
|
171037
|
+
const sourceCompartments = db.prepare(`SELECT sequence, start_message, end_message, start_message_id, end_message_id,
|
|
171038
|
+
title, content, p1, p2, p3, p4, importance, episode_type, legacy,
|
|
171039
|
+
created_at, harness
|
|
171040
|
+
FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sourceSessionId);
|
|
171041
|
+
const insertCompartment = db.prepare(`INSERT INTO compartments
|
|
171042
|
+
(session_id, sequence, start_message, end_message, start_message_id,
|
|
171043
|
+
end_message_id, title, content, p1, p2, p3, p4, importance,
|
|
171044
|
+
episode_type, legacy, created_at, harness)
|
|
171045
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
171046
|
+
const copiedCompartments = [];
|
|
171047
|
+
for (const row of sourceCompartments) {
|
|
171048
|
+
const startMessage = filter.resolveBoundaryOrdinal(row.start_message_id);
|
|
171049
|
+
const endMessage = filter.resolveBoundaryOrdinal(row.end_message_id);
|
|
171050
|
+
if (startMessage === undefined || endMessage === undefined)
|
|
171051
|
+
continue;
|
|
171052
|
+
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);
|
|
171053
|
+
copiedCompartments.push({
|
|
171054
|
+
sequence: row.sequence,
|
|
171055
|
+
startMessage,
|
|
171056
|
+
endMessage,
|
|
171057
|
+
startMessageId: row.start_message_id,
|
|
171058
|
+
endMessageId: row.end_message_id
|
|
171059
|
+
});
|
|
171060
|
+
}
|
|
171061
|
+
const sourceTags = db.prepare(`SELECT message_id, type, status, byte_size, tag_number, harness,
|
|
171062
|
+
entry_fingerprint, token_count, input_token_count,
|
|
171063
|
+
reasoning_token_count, reasoning_byte_size, drop_mode, tool_name,
|
|
171064
|
+
input_byte_size, caveman_depth, tool_owner_message_id
|
|
171065
|
+
FROM tags WHERE session_id = ? ORDER BY tag_number ASC`).all(sourceSessionId);
|
|
171066
|
+
const insertTag = db.prepare(`INSERT INTO tags
|
|
171067
|
+
(session_id, message_id, type, status, byte_size, tag_number, harness,
|
|
171068
|
+
entry_fingerprint, token_count, input_token_count, reasoning_token_count,
|
|
171069
|
+
reasoning_byte_size, drop_mode, tool_name, input_byte_size,
|
|
171070
|
+
caveman_depth, tool_owner_message_id)
|
|
171071
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
171072
|
+
const copiedTagNumbers = [];
|
|
171073
|
+
for (const row of sourceTags) {
|
|
171074
|
+
if (!filter.includeTag({
|
|
171075
|
+
messageId: row.message_id,
|
|
171076
|
+
type: row.type,
|
|
171077
|
+
tagNumber: row.tag_number,
|
|
171078
|
+
toolOwnerMessageId: row.tool_owner_message_id
|
|
171079
|
+
})) {
|
|
171080
|
+
continue;
|
|
171081
|
+
}
|
|
171082
|
+
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);
|
|
171083
|
+
copiedTagNumbers.push(row.tag_number);
|
|
171084
|
+
}
|
|
171085
|
+
if (copiedTagNumbers.length > 0) {
|
|
171086
|
+
const placeholders3 = copiedTagNumbers.map(() => "?").join(", ");
|
|
171087
|
+
db.prepare(`INSERT INTO source_contents (tag_id, session_id, content, created_at, harness)
|
|
171088
|
+
SELECT tag_id, ?, content, created_at, harness
|
|
171089
|
+
FROM source_contents
|
|
171090
|
+
WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
171091
|
+
db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
|
|
171092
|
+
SELECT ?, tag_id, operation, queued_at, harness
|
|
171093
|
+
FROM pending_ops
|
|
171094
|
+
WHERE session_id = ? AND tag_id IN (${placeholders3})`).run(destinationSessionId, sourceSessionId, ...copiedTagNumbers);
|
|
171095
|
+
}
|
|
171096
|
+
const meta3 = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
|
|
171097
|
+
pi_stable_id_scheme, stripped_placeholder_ids,
|
|
171098
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
171099
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
171100
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
171101
|
+
todo_synthetic_state_json
|
|
171102
|
+
FROM session_meta WHERE session_id = ?`).get(sourceSessionId);
|
|
171103
|
+
const maxCopiedTag = copiedTagNumbers.reduce((max, value) => Math.max(max, value), 0);
|
|
171104
|
+
const pendingMarker = filter.selectPendingPiMarker(meta3?.pending_pi_compaction_marker_state ?? null, copiedCompartments);
|
|
171105
|
+
const todoAnchor = meta3?.todo_synthetic_anchor_message_id ?? "";
|
|
171106
|
+
const migrateTodo = todoAnchor.length > 0 && filter.includeMessageId(todoAnchor);
|
|
171107
|
+
db.prepare(`INSERT INTO session_meta
|
|
171108
|
+
(session_id, harness, counter, cleared_reasoning_through_tag,
|
|
171109
|
+
tool_reclaim_watermark, pi_stable_id_scheme, stripped_placeholder_ids,
|
|
171110
|
+
stale_reduce_stripped_ids, processed_image_stripped_ids,
|
|
171111
|
+
pending_pi_compaction_marker_state, last_todo_state,
|
|
171112
|
+
todo_synthetic_call_id, todo_synthetic_anchor_message_id,
|
|
171113
|
+
todo_synthetic_state_json)
|
|
171114
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
171115
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
171116
|
+
harness = excluded.harness,
|
|
171117
|
+
counter = excluded.counter,
|
|
171118
|
+
cleared_reasoning_through_tag = excluded.cleared_reasoning_through_tag,
|
|
171119
|
+
tool_reclaim_watermark = excluded.tool_reclaim_watermark,
|
|
171120
|
+
pi_stable_id_scheme = excluded.pi_stable_id_scheme,
|
|
171121
|
+
stripped_placeholder_ids = excluded.stripped_placeholder_ids,
|
|
171122
|
+
stale_reduce_stripped_ids = excluded.stale_reduce_stripped_ids,
|
|
171123
|
+
processed_image_stripped_ids = excluded.processed_image_stripped_ids,
|
|
171124
|
+
pending_pi_compaction_marker_state = excluded.pending_pi_compaction_marker_state,
|
|
171125
|
+
last_todo_state = excluded.last_todo_state,
|
|
171126
|
+
todo_synthetic_call_id = excluded.todo_synthetic_call_id,
|
|
171127
|
+
todo_synthetic_anchor_message_id = excluded.todo_synthetic_anchor_message_id,
|
|
171128
|
+
todo_synthetic_state_json = excluded.todo_synthetic_state_json,
|
|
171129
|
+
cached_m0_bytes = NULL,
|
|
171130
|
+
cached_m1_bytes = NULL`).run(destinationSessionId, getHarness(), maxCopiedTag, clampWatermark(meta3?.cleared_reasoning_through_tag ?? null, maxCopiedTag), clampWatermark(meta3?.tool_reclaim_watermark ?? null, maxCopiedTag), typeof meta3?.pi_stable_id_scheme === "number" && Number.isFinite(meta3.pi_stable_id_scheme) ? meta3.pi_stable_id_scheme : null, filterIdBlob(meta3?.stripped_placeholder_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.stale_reduce_stripped_ids ?? null, filter.includeMessageId), filterIdBlob(meta3?.processed_image_stripped_ids ?? null, filter.includeMessageId), pendingMarker, migrateTodo ? meta3?.last_todo_state ?? "" : "", migrateTodo ? meta3?.todo_synthetic_call_id ?? "" : "", migrateTodo ? todoAnchor : "", migrateTodo ? meta3?.todo_synthetic_state_json ?? "" : "");
|
|
171131
|
+
const pendingOpsRow = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?").get(destinationSessionId);
|
|
171132
|
+
return {
|
|
171133
|
+
kind: "migrated",
|
|
171134
|
+
compartmentsCopied: copiedCompartments.length,
|
|
171135
|
+
tagsCopied: copiedTagNumbers.length,
|
|
171136
|
+
pendingOpsCopied: typeof pendingOpsRow?.count === "number" ? pendingOpsRow.count : 0,
|
|
171137
|
+
pendingMarkerMigrated: pendingMarker !== null
|
|
171138
|
+
};
|
|
171139
|
+
});
|
|
171140
|
+
}
|
|
170922
171141
|
// ../plugin/src/features/magic-context/storage-m0-mutation-log.ts
|
|
170923
171142
|
var M0_MUTATION_TYPES = new Set([
|
|
170924
171143
|
"compartment_delete",
|
|
@@ -171885,6 +172104,36 @@ function parseStrippedBlob(raw) {
|
|
|
171885
172104
|
} catch {}
|
|
171886
172105
|
return [];
|
|
171887
172106
|
}
|
|
172107
|
+
function getProcessedImageStrippedIds(db, sessionId) {
|
|
172108
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
172109
|
+
return new Set(parseStrippedBlob(row?.processed_image_stripped_ids));
|
|
172110
|
+
}
|
|
172111
|
+
function addProcessedImageStrippedIds(db, sessionId, ids) {
|
|
172112
|
+
const add = [...ids];
|
|
172113
|
+
if (add.length === 0)
|
|
172114
|
+
return true;
|
|
172115
|
+
ensureSessionMetaRow(db, sessionId);
|
|
172116
|
+
for (let attempt = 0;attempt < CAS_RETRY_LIMIT; attempt += 1) {
|
|
172117
|
+
const row = db.prepare("SELECT processed_image_stripped_ids FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
172118
|
+
const rawStored = row ? row.processed_image_stripped_ids ?? null : null;
|
|
172119
|
+
const current = new Set(parseStrippedBlob(rawStored));
|
|
172120
|
+
let changed = false;
|
|
172121
|
+
for (const id of add) {
|
|
172122
|
+
if (!current.has(id)) {
|
|
172123
|
+
current.add(id);
|
|
172124
|
+
changed = true;
|
|
172125
|
+
}
|
|
172126
|
+
}
|
|
172127
|
+
if (!changed)
|
|
172128
|
+
return true;
|
|
172129
|
+
const nextBlob = JSON.stringify([...current]);
|
|
172130
|
+
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);
|
|
172131
|
+
if (result.changes > 0)
|
|
172132
|
+
return true;
|
|
172133
|
+
}
|
|
172134
|
+
sessionLog(sessionId, `processed_image_stripped_ids CAS: ${CAS_RETRY_LIMIT} retries exhausted`);
|
|
172135
|
+
return false;
|
|
172136
|
+
}
|
|
171888
172137
|
function isPendingCompactionMarker(value) {
|
|
171889
172138
|
return typeof value === "object" && value !== null && typeof value.ordinal === "number" && typeof value.endMessageId === "string" && typeof value.publishedAt === "number";
|
|
171890
172139
|
}
|
|
@@ -172607,6 +172856,7 @@ var getTagNumbersByMessageIdStatements = new WeakMap;
|
|
|
172607
172856
|
var deleteTagsByMessageIdStatements = new WeakMap;
|
|
172608
172857
|
var getMaxTagNumberBySessionStatements = new WeakMap;
|
|
172609
172858
|
var getTagNumberByMessageIdStatements = new WeakMap;
|
|
172859
|
+
var hasPiFallbackMessageTagStatements = new WeakMap;
|
|
172610
172860
|
function getInsertTagStatement(db) {
|
|
172611
172861
|
let stmt = insertTagStatements.get(db);
|
|
172612
172862
|
if (!stmt) {
|
|
@@ -172750,6 +173000,18 @@ function getUpdateTagInputTokenCountStatement(db) {
|
|
|
172750
173000
|
function updateTagTokenCount(db, sessionId, tagNumber, newTokenCount) {
|
|
172751
173001
|
getUpdateTagTokenCountStatement(db).run(newTokenCount, sessionId, tagNumber);
|
|
172752
173002
|
}
|
|
173003
|
+
function getPersistedToolTagAccounting(db, sessionId, tagNumber) {
|
|
173004
|
+
const row = db.prepare(`SELECT byte_size AS byteSize,
|
|
173005
|
+
token_count AS tokenCount,
|
|
173006
|
+
input_byte_size AS inputByteSize,
|
|
173007
|
+
input_token_count AS inputTokenCount
|
|
173008
|
+
FROM tags
|
|
173009
|
+
WHERE session_id = ? AND tag_number = ? AND type = 'tool'`).get(sessionId, tagNumber);
|
|
173010
|
+
if (!row || typeof row.byteSize !== "number" || row.tokenCount !== null && typeof row.tokenCount !== "number" || typeof row.inputByteSize !== "number" || row.inputTokenCount !== null && typeof row.inputTokenCount !== "number") {
|
|
173011
|
+
return null;
|
|
173012
|
+
}
|
|
173013
|
+
return row;
|
|
173014
|
+
}
|
|
172753
173015
|
function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
|
|
172754
173016
|
const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
|
|
172755
173017
|
FROM tags
|
|
@@ -172851,6 +173113,19 @@ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
|
172851
173113
|
function updateCavemanDepth(db, sessionId, tagNumber, depth) {
|
|
172852
173114
|
db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
|
|
172853
173115
|
}
|
|
173116
|
+
function hasPiFallbackMessageTags(db, sessionId) {
|
|
173117
|
+
let statement = hasPiFallbackMessageTagStatements.get(db);
|
|
173118
|
+
if (!statement) {
|
|
173119
|
+
statement = db.prepare(`SELECT 1
|
|
173120
|
+
FROM tags
|
|
173121
|
+
WHERE session_id = ?
|
|
173122
|
+
AND type = 'message'
|
|
173123
|
+
AND message_id LIKE 'pi-msg-%'
|
|
173124
|
+
LIMIT 1`);
|
|
173125
|
+
hasPiFallbackMessageTagStatements.set(db, statement);
|
|
173126
|
+
}
|
|
173127
|
+
return statement.get(sessionId) != null;
|
|
173128
|
+
}
|
|
172854
173129
|
function findAdoptableFallbackTags(db, sessionId, entryFingerprint) {
|
|
172855
173130
|
const rows = db.prepare(`SELECT tag_number AS tagNumber, message_id AS messageId
|
|
172856
173131
|
FROM tags
|
|
@@ -173021,27 +173296,24 @@ function adoptPiFallbackToolOwnerTag(db, sessionId, tagNumber, callId, oldOwnerM
|
|
|
173021
173296
|
}
|
|
173022
173297
|
const existing = getPiFallbackToolFoldTagRowByOwner(db, sessionId, callId, newOwnerMessageId);
|
|
173023
173298
|
if (existing === null) {
|
|
173024
|
-
const
|
|
173299
|
+
const result = db.prepare(`UPDATE tags
|
|
173025
173300
|
SET tool_owner_message_id = ?
|
|
173026
173301
|
WHERE session_id = ?
|
|
173027
173302
|
AND tag_number = ?
|
|
173028
173303
|
AND type = 'tool'
|
|
173029
173304
|
AND message_id = ?
|
|
173030
173305
|
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
173031
|
-
return (
|
|
173306
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
173032
173307
|
}
|
|
173033
173308
|
if (existing.tagNumber === tagNumber) {
|
|
173034
173309
|
return { action: "skipped" };
|
|
173035
173310
|
}
|
|
173036
|
-
foldDuplicateIntoSurvivor(db, sessionId,
|
|
173037
|
-
|
|
173038
|
-
|
|
173039
|
-
|
|
173040
|
-
|
|
173041
|
-
|
|
173042
|
-
AND message_id = ?
|
|
173043
|
-
AND tool_owner_message_id = ?`).run(newOwnerMessageId, sessionId, tagNumber, callId, oldOwnerMessageId);
|
|
173044
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers: [existing.tagNumber] } : { action: "skipped" };
|
|
173311
|
+
foldDuplicateIntoSurvivor(db, sessionId, existing, survivor);
|
|
173312
|
+
return {
|
|
173313
|
+
action: "folded",
|
|
173314
|
+
tagNumber: existing.tagNumber,
|
|
173315
|
+
deletedTagNumbers: [tagNumber]
|
|
173316
|
+
};
|
|
173045
173317
|
}
|
|
173046
173318
|
function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageId, newRealMessageId) {
|
|
173047
173319
|
const survivor = getPiFallbackFoldTagRowByNumber(db, sessionId, tagNumber);
|
|
@@ -173050,26 +173322,28 @@ function adoptPiFallbackMessageTag(db, sessionId, tagNumber, oldFallbackMessageI
|
|
|
173050
173322
|
}
|
|
173051
173323
|
const duplicates = getPiFallbackMessageFoldTagRowsByMessageId(db, sessionId, newRealMessageId).filter((row) => row.tagNumber !== tagNumber);
|
|
173052
173324
|
if (duplicates.length === 0) {
|
|
173053
|
-
const
|
|
173325
|
+
const result = db.prepare(`UPDATE tags
|
|
173054
173326
|
SET message_id = ?
|
|
173055
173327
|
WHERE session_id = ?
|
|
173056
173328
|
AND tag_number = ?
|
|
173057
173329
|
AND type = 'message'
|
|
173058
173330
|
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
173059
|
-
return (
|
|
173331
|
+
return (result.changes ?? 0) === 1 ? { action: "rekeyed", tagNumber } : { action: "skipped" };
|
|
173060
173332
|
}
|
|
173061
|
-
const
|
|
173062
|
-
|
|
173063
|
-
|
|
173333
|
+
const realSurvivor = duplicates[0];
|
|
173334
|
+
if (!realSurvivor)
|
|
173335
|
+
return { action: "skipped" };
|
|
173336
|
+
const deletedTagNumbers = [tagNumber];
|
|
173337
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, survivor);
|
|
173338
|
+
for (const duplicate of duplicates.slice(1)) {
|
|
173339
|
+
foldDuplicateIntoSurvivor(db, sessionId, realSurvivor, duplicate);
|
|
173064
173340
|
deletedTagNumbers.push(duplicate.tagNumber);
|
|
173065
173341
|
}
|
|
173066
|
-
|
|
173067
|
-
|
|
173068
|
-
|
|
173069
|
-
|
|
173070
|
-
|
|
173071
|
-
AND message_id = ?`).run(newRealMessageId, sessionId, tagNumber, oldFallbackMessageId);
|
|
173072
|
-
return (result.changes ?? 0) === 1 ? { action: "folded", tagNumber, deletedTagNumbers } : { action: "skipped" };
|
|
173342
|
+
return {
|
|
173343
|
+
action: "folded",
|
|
173344
|
+
tagNumber: realSurvivor.tagNumber,
|
|
173345
|
+
deletedTagNumbers
|
|
173346
|
+
};
|
|
173073
173347
|
}
|
|
173074
173348
|
var getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
173075
173349
|
function getMaxTagNumberBySession(db, sessionId) {
|
|
@@ -173141,10 +173415,40 @@ function getActiveTagsBySessionStatement(db) {
|
|
|
173141
173415
|
}
|
|
173142
173416
|
return stmt;
|
|
173143
173417
|
}
|
|
173418
|
+
function getMaxDroppedTagNumberStatement(db) {
|
|
173419
|
+
let stmt = getMaxDroppedTagNumberStatements.get(db);
|
|
173420
|
+
if (!stmt) {
|
|
173421
|
+
stmt = db.prepare("SELECT COALESCE(MAX(tag_number), 0) AS max_tag_number FROM tags WHERE session_id = ? AND status = 'dropped'");
|
|
173422
|
+
getMaxDroppedTagNumberStatements.set(db, stmt);
|
|
173423
|
+
}
|
|
173424
|
+
return stmt;
|
|
173425
|
+
}
|
|
173144
173426
|
function getActiveTagsBySession(db, sessionId) {
|
|
173145
173427
|
const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
|
|
173146
173428
|
return rows.map(toTagEntry);
|
|
173147
173429
|
}
|
|
173430
|
+
function getTagsForPendingOperations(db, sessionId, pendingTagNumbers, protectedTags, recentToolWindow) {
|
|
173431
|
+
const byNumber = new Map;
|
|
173432
|
+
for (const tag of getTagsByNumbers(db, sessionId, pendingTagNumbers)) {
|
|
173433
|
+
byNumber.set(tag.tagNumber, tag);
|
|
173434
|
+
}
|
|
173435
|
+
const addRows = (sql, limit) => {
|
|
173436
|
+
if (limit <= 0)
|
|
173437
|
+
return;
|
|
173438
|
+
const rows = db.prepare(sql).all(sessionId, limit).filter(isTagRow);
|
|
173439
|
+
for (const row of rows) {
|
|
173440
|
+
const tag = toTagEntry(row);
|
|
173441
|
+
byNumber.set(tag.tagNumber, tag);
|
|
173442
|
+
}
|
|
173443
|
+
};
|
|
173444
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
173445
|
+
WHERE session_id = ? AND status = 'active'
|
|
173446
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, protectedTags);
|
|
173447
|
+
addRows(`SELECT ${TAG_SELECT_COLUMNS} FROM tags
|
|
173448
|
+
WHERE session_id = ? AND type = 'tool'
|
|
173449
|
+
ORDER BY tag_number DESC, id DESC LIMIT ?`, recentToolWindow);
|
|
173450
|
+
return [...byNumber.values()].sort((left, right) => left.tagNumber - right.tagNumber);
|
|
173451
|
+
}
|
|
173148
173452
|
function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
173149
173453
|
if (tagNumbers.length === 0)
|
|
173150
173454
|
return [];
|
|
@@ -173159,6 +173463,10 @@ function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
|
173159
173463
|
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders4}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
173160
173464
|
return rows.map(toTagEntry);
|
|
173161
173465
|
}
|
|
173466
|
+
function getMaxDroppedTagNumber(db, sessionId) {
|
|
173467
|
+
const row = getMaxDroppedTagNumberStatement(db).get(sessionId);
|
|
173468
|
+
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
173469
|
+
}
|
|
173162
173470
|
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
173163
173471
|
var getNullOwnerToolTagStatements = new WeakMap;
|
|
173164
173472
|
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
@@ -175517,12 +175825,26 @@ function computeBudgetPressure(compartments, historyBudget) {
|
|
|
175517
175825
|
|
|
175518
175826
|
// ../plugin/src/hooks/magic-context/decay-render.ts
|
|
175519
175827
|
var DEFAULT_HISTORY_BUDGET_TOKENS = 60000;
|
|
175520
|
-
function escapeXmlAttr2(s) {
|
|
175521
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
175522
|
-
}
|
|
175523
175828
|
function escapeXmlContent2(s) {
|
|
175524
175829
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
175525
175830
|
}
|
|
175831
|
+
function formatDateRange(startDate, endDate) {
|
|
175832
|
+
if (!startDate || !endDate)
|
|
175833
|
+
return "";
|
|
175834
|
+
if (startDate === endDate)
|
|
175835
|
+
return startDate;
|
|
175836
|
+
if (startDate.slice(0, 7) === endDate.slice(0, 7))
|
|
175837
|
+
return `${startDate}→${endDate.slice(8)}`;
|
|
175838
|
+
return `${startDate}→${endDate}`;
|
|
175839
|
+
}
|
|
175840
|
+
function compartmentHeading(c) {
|
|
175841
|
+
const dateRange = formatDateRange(c.startDate, c.endDate);
|
|
175842
|
+
const dateSegment = dateRange ? ` · ${dateRange}` : "";
|
|
175843
|
+
return `## ${c.startMessage}-${c.endMessage}${dateSegment} · ${c.title}`;
|
|
175844
|
+
}
|
|
175845
|
+
function guardCompartmentBody(body) {
|
|
175846
|
+
return body.replace(/^## /gm, " ## ");
|
|
175847
|
+
}
|
|
175526
175848
|
function isTieredRow(c) {
|
|
175527
175849
|
return typeof c.p1 === "string" && c.p1.length > 0;
|
|
175528
175850
|
}
|
|
@@ -175552,25 +175874,22 @@ function renderCompartmentAtTier(c, tier2) {
|
|
|
175552
175874
|
return renderOneCompartment(c, tier2);
|
|
175553
175875
|
}
|
|
175554
175876
|
function renderOneCompartment(c, tier2) {
|
|
175555
|
-
const baseAttrs = `start="${c.startMessage}" end="${c.endMessage}" title="${escapeXmlAttr2(c.title)}"`;
|
|
175556
175877
|
if (tier2 >= 5)
|
|
175557
175878
|
return "";
|
|
175879
|
+
const heading = compartmentHeading(c);
|
|
175558
175880
|
if (c.legacy === 1 || !isTieredRow(c)) {
|
|
175559
175881
|
const flat = (c.content ?? "").trim();
|
|
175560
175882
|
if (tier2 >= 4 || flat.length === 0)
|
|
175561
|
-
return
|
|
175562
|
-
|
|
175563
|
-
|
|
175564
|
-
|
|
175565
|
-
"</compartment>"
|
|
175566
|
-
].join(`
|
|
175567
|
-
`);
|
|
175883
|
+
return heading;
|
|
175884
|
+
const body2 = guardCompartmentBody(escapeXmlContent2(legacyBodyForTier(flat, tier2)));
|
|
175885
|
+
return `${heading}
|
|
175886
|
+
${body2}`;
|
|
175568
175887
|
}
|
|
175569
175888
|
const body = tierBody(c, tier2);
|
|
175570
175889
|
if (body.length === 0)
|
|
175571
|
-
return
|
|
175572
|
-
return
|
|
175573
|
-
|
|
175890
|
+
return heading;
|
|
175891
|
+
return `${heading}
|
|
175892
|
+
${guardCompartmentBody(escapeXmlContent2(body))}`;
|
|
175574
175893
|
}
|
|
175575
175894
|
function computeTiers(compartments, historyBudgetTokens) {
|
|
175576
175895
|
const v2Compartments = compartments.map((c, originalIndex) => ({ c, originalIndex })).filter(({ c }) => c.legacy !== 1);
|
|
@@ -175693,33 +176012,9 @@ function getVisibleMemoryIds(db, sessionId) {
|
|
|
175693
176012
|
}
|
|
175694
176013
|
}
|
|
175695
176014
|
function renderMemoryBlock(memories) {
|
|
175696
|
-
|
|
175697
|
-
for (const m of memories) {
|
|
175698
|
-
const existing = byCategory.get(m.category);
|
|
175699
|
-
if (existing) {
|
|
175700
|
-
existing.push(m);
|
|
175701
|
-
} else {
|
|
175702
|
-
byCategory.set(m.category, [m]);
|
|
175703
|
-
}
|
|
175704
|
-
}
|
|
175705
|
-
const sections = [];
|
|
175706
|
-
for (const category of CATEGORY_PRIORITY) {
|
|
175707
|
-
const categoryMemories = byCategory.get(category);
|
|
175708
|
-
if (!categoryMemories || categoryMemories.length === 0) {
|
|
175709
|
-
continue;
|
|
175710
|
-
}
|
|
175711
|
-
sections.push(`<${category}>`, ...categoryMemories.map((m) => `- ${escapeXmlContent(m.content)}`), `</${category}>`);
|
|
175712
|
-
}
|
|
175713
|
-
if (sections.length === 0) {
|
|
175714
|
-
return null;
|
|
175715
|
-
}
|
|
175716
|
-
return `<project-memory>
|
|
175717
|
-
${sections.join(`
|
|
175718
|
-
`)}
|
|
175719
|
-
</project-memory>`;
|
|
176015
|
+
return renderMemoryBlockV2(memories) || null;
|
|
175720
176016
|
}
|
|
175721
176017
|
var DEFAULT_MEMORY_BUDGET_TOKENS = 8000;
|
|
175722
|
-
var MEMORY_BLOCK_WRAPPER_TOKENS = 6;
|
|
175723
176018
|
var DEFAULT_USER_PROFILE_BUDGET_TOKENS = 4000;
|
|
175724
176019
|
function memoryCanonicalIdentity(memory2, workspace) {
|
|
175725
176020
|
return resolveStoredPathWorkspaceIdentity(memory2.projectPath, workspace.identities, workspace.canonicalIdentityByStoredPath);
|
|
@@ -175737,11 +176032,18 @@ function memorySelectionOrder(left, right) {
|
|
|
175737
176032
|
return left.id - right.id;
|
|
175738
176033
|
}
|
|
175739
176034
|
function memoryRenderOrder(left, right) {
|
|
175740
|
-
const
|
|
175741
|
-
const
|
|
175742
|
-
|
|
175743
|
-
|
|
175744
|
-
|
|
176035
|
+
const leftPriority = V2_MEMORY_CATEGORIES.indexOf(left.category);
|
|
176036
|
+
const rightPriority = V2_MEMORY_CATEGORIES.indexOf(right.category);
|
|
176037
|
+
if (leftPriority >= 0 || rightPriority >= 0) {
|
|
176038
|
+
if (leftPriority < 0)
|
|
176039
|
+
return 1;
|
|
176040
|
+
if (rightPriority < 0)
|
|
176041
|
+
return -1;
|
|
176042
|
+
if (leftPriority !== rightPriority)
|
|
176043
|
+
return leftPriority - rightPriority;
|
|
176044
|
+
} else if (left.category !== right.category) {
|
|
176045
|
+
return left.category < right.category ? -1 : 1;
|
|
176046
|
+
}
|
|
175745
176047
|
return left.id - right.id;
|
|
175746
176048
|
}
|
|
175747
176049
|
var maxCompartmentSeqStatements = new WeakMap;
|
|
@@ -175752,13 +176054,13 @@ var newCompartmentStatements = new WeakMap;
|
|
|
175752
176054
|
function trimMemoriesToBudgetV2(sessionId, memories, budgetTokens, renderOptions = {}) {
|
|
175753
176055
|
const selectionOrder = [...memories].sort(memorySelectionOrder);
|
|
175754
176056
|
const selected = [];
|
|
175755
|
-
|
|
176057
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
175756
176058
|
for (const memory2 of selectionOrder) {
|
|
175757
|
-
const
|
|
175758
|
-
if (usedTokens +
|
|
176059
|
+
const cost = accounting.candidateCost(memory2);
|
|
176060
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175759
176061
|
continue;
|
|
176062
|
+
accounting.admit(memory2, cost);
|
|
175760
176063
|
selected.push(memory2);
|
|
175761
|
-
usedTokens += memoryTokens;
|
|
175762
176064
|
}
|
|
175763
176065
|
if (selected.length < memories.length) {
|
|
175764
176066
|
sessionLog(sessionId, `v2 trimmed memories from ${memories.length} to ${selected.length} to fit injection budget of ${budgetTokens} tokens`);
|
|
@@ -175772,23 +176074,22 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
175772
176074
|
}
|
|
175773
176075
|
const selected = [];
|
|
175774
176076
|
const selectedIds = new Set;
|
|
175775
|
-
|
|
175776
|
-
const tokenCost = (memory2) => estimateTokens(renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id)));
|
|
176077
|
+
const accounting = createMemoryBlockAccounting(renderOptions);
|
|
175777
176078
|
const trySelect = (memory2) => {
|
|
175778
176079
|
if (selectedIds.has(memory2.id))
|
|
175779
176080
|
return false;
|
|
175780
|
-
const
|
|
175781
|
-
if (usedTokens +
|
|
176081
|
+
const cost = accounting.candidateCost(memory2);
|
|
176082
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175782
176083
|
return false;
|
|
175783
176084
|
selected.push(memory2);
|
|
175784
176085
|
selectedIds.add(memory2.id);
|
|
175785
|
-
|
|
176086
|
+
accounting.admit(memory2, cost);
|
|
175786
176087
|
return true;
|
|
175787
176088
|
};
|
|
175788
176089
|
for (const memory2 of memories.filter((candidate) => candidate.status === "permanent").sort(memorySelectionOrder)) {
|
|
175789
176090
|
trySelect(memory2);
|
|
175790
176091
|
}
|
|
175791
|
-
const remainingAfterPermanent = Math.max(0, budgetTokens - usedTokens);
|
|
176092
|
+
const remainingAfterPermanent = Math.max(0, budgetTokens - accounting.usedTokens);
|
|
175792
176093
|
const floorTokens = remainingAfterPermanent / Math.max(1, workspace.identities.length);
|
|
175793
176094
|
const byIdentity = new Map;
|
|
175794
176095
|
for (const memory2 of memories) {
|
|
@@ -175807,15 +176108,15 @@ function trimWorkspaceMemoriesToBudgetV2(sessionId, memories, budgetTokens, work
|
|
|
175807
176108
|
for (const memory2 of candidates2) {
|
|
175808
176109
|
if (selectedIds.has(memory2.id))
|
|
175809
176110
|
continue;
|
|
175810
|
-
const
|
|
175811
|
-
if (memberTokens +
|
|
176111
|
+
const cost = accounting.candidateCost(memory2);
|
|
176112
|
+
if (memberTokens + cost > floorTokens)
|
|
175812
176113
|
continue;
|
|
175813
|
-
if (usedTokens +
|
|
176114
|
+
if (accounting.usedTokens + cost > budgetTokens)
|
|
175814
176115
|
continue;
|
|
175815
176116
|
selected.push(memory2);
|
|
175816
176117
|
selectedIds.add(memory2.id);
|
|
175817
|
-
|
|
175818
|
-
memberTokens +=
|
|
176118
|
+
accounting.admit(memory2, cost);
|
|
176119
|
+
memberTokens += cost;
|
|
175819
176120
|
}
|
|
175820
176121
|
}
|
|
175821
176122
|
const remaining = memories.filter((memory2) => !selectedIds.has(memory2.id)).sort(memorySelectionOrder);
|
|
@@ -175839,17 +176140,55 @@ function trimUserMemoriesToBudget(memories, budgetTokens) {
|
|
|
175839
176140
|
}
|
|
175840
176141
|
return selected;
|
|
175841
176142
|
}
|
|
176143
|
+
function createMemoryBlockAccounting(renderOptions) {
|
|
176144
|
+
const seenCategories = new Set;
|
|
176145
|
+
const categoryCost = new Map;
|
|
176146
|
+
return {
|
|
176147
|
+
usedTokens: estimateTokens(`<project-memory>
|
|
176148
|
+
</project-memory>`),
|
|
176149
|
+
candidateCost(memory2) {
|
|
176150
|
+
const line = renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id));
|
|
176151
|
+
let cost = estimateTokens(`${line}
|
|
176152
|
+
`);
|
|
176153
|
+
if (!seenCategories.has(memory2.category)) {
|
|
176154
|
+
let tags = categoryCost.get(memory2.category);
|
|
176155
|
+
if (tags === undefined) {
|
|
176156
|
+
tags = estimateTokens(`<${escapeXmlAttr(memory2.category)}>
|
|
176157
|
+
</${escapeXmlAttr(memory2.category)}>
|
|
176158
|
+
`);
|
|
176159
|
+
categoryCost.set(memory2.category, tags);
|
|
176160
|
+
}
|
|
176161
|
+
cost += tags;
|
|
176162
|
+
}
|
|
176163
|
+
return cost;
|
|
176164
|
+
},
|
|
176165
|
+
admit(memory2, cost) {
|
|
176166
|
+
this.usedTokens += cost;
|
|
176167
|
+
seenCategories.add(memory2.category);
|
|
176168
|
+
}
|
|
176169
|
+
};
|
|
176170
|
+
}
|
|
175842
176171
|
function renderMemoryLineV2(memory2, sourceName) {
|
|
175843
|
-
const
|
|
175844
|
-
return
|
|
176172
|
+
const source = sourceName ? ` [${escapeXmlContent(sourceName)}]` : "";
|
|
176173
|
+
return `#${memory2.id}${source}: ${escapeXmlContent(memory2.content)}`;
|
|
175845
176174
|
}
|
|
175846
176175
|
function renderMemoryBlockV2(memories, wrapper = "project-memory", renderOptions = {}) {
|
|
175847
176176
|
if (memories.length === 0)
|
|
175848
176177
|
return "";
|
|
176178
|
+
const ordered = [...memories].sort(memoryRenderOrder);
|
|
175849
176179
|
const lines = [`<${wrapper}>`];
|
|
175850
|
-
|
|
176180
|
+
let openCategory;
|
|
176181
|
+
for (const memory2 of ordered) {
|
|
176182
|
+
if (memory2.category !== openCategory) {
|
|
176183
|
+
if (openCategory !== undefined)
|
|
176184
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
176185
|
+
openCategory = memory2.category;
|
|
176186
|
+
lines.push(`<${escapeXmlAttr(openCategory)}>`);
|
|
176187
|
+
}
|
|
175851
176188
|
lines.push(renderMemoryLineV2(memory2, renderOptions.sourceNameByMemoryId?.get(memory2.id)));
|
|
175852
176189
|
}
|
|
176190
|
+
if (openCategory !== undefined)
|
|
176191
|
+
lines.push(`</${escapeXmlAttr(openCategory)}>`);
|
|
175853
176192
|
lines.push(`</${wrapper}>`);
|
|
175854
176193
|
return lines.join(`
|
|
175855
176194
|
`);
|
|
@@ -176163,6 +176502,8 @@ var STATUS_COLOR = {
|
|
|
176163
176502
|
cancelled: "error"
|
|
176164
176503
|
};
|
|
176165
176504
|
var snapshotsBySession = new Map;
|
|
176505
|
+
var MAX_TODOWRITE_RENDER_CACHE_ENTRIES = 50;
|
|
176506
|
+
var cachedTodowriteTodosByToolCallId = new Map;
|
|
176166
176507
|
function isTodoStatus2(value) {
|
|
176167
176508
|
return TODO_STATUSES.includes(value);
|
|
176168
176509
|
}
|
|
@@ -176172,6 +176513,27 @@ function isTodoPriority2(value) {
|
|
|
176172
176513
|
function cloneTodos(todos) {
|
|
176173
176514
|
return todos.map((todo) => ({ ...todo }));
|
|
176174
176515
|
}
|
|
176516
|
+
function rememberTodowriteToolCallTodos(toolCallId, todos) {
|
|
176517
|
+
if (!toolCallId)
|
|
176518
|
+
return;
|
|
176519
|
+
cachedTodowriteTodosByToolCallId.delete(toolCallId);
|
|
176520
|
+
cachedTodowriteTodosByToolCallId.set(toolCallId, cloneTodos(todos));
|
|
176521
|
+
while (cachedTodowriteTodosByToolCallId.size > MAX_TODOWRITE_RENDER_CACHE_ENTRIES) {
|
|
176522
|
+
const oldestKey = cachedTodowriteTodosByToolCallId.keys().next().value;
|
|
176523
|
+
if (typeof oldestKey !== "string")
|
|
176524
|
+
break;
|
|
176525
|
+
cachedTodowriteTodosByToolCallId.delete(oldestKey);
|
|
176526
|
+
}
|
|
176527
|
+
}
|
|
176528
|
+
function getCachedTodowriteToolCallTodos(toolCallId) {
|
|
176529
|
+
if (!toolCallId)
|
|
176530
|
+
return null;
|
|
176531
|
+
const todos = cachedTodowriteTodosByToolCallId.get(toolCallId);
|
|
176532
|
+
return todos ? cloneTodos(todos) : null;
|
|
176533
|
+
}
|
|
176534
|
+
function clearTodowriteToolCallTodos() {
|
|
176535
|
+
cachedTodowriteTodosByToolCallId.clear();
|
|
176536
|
+
}
|
|
176175
176537
|
function parseTodos(input) {
|
|
176176
176538
|
if (!Array.isArray(input))
|
|
176177
176539
|
return null;
|
|
@@ -176308,25 +176670,27 @@ function capTodoRows(rows) {
|
|
|
176308
176670
|
hiddenCount: rows.length - visibleCount
|
|
176309
176671
|
};
|
|
176310
176672
|
}
|
|
176311
|
-
function renderTodowriteCall(args, theme) {
|
|
176312
|
-
const todos = parseTodos(args.todos) ?? [];
|
|
176673
|
+
function renderTodowriteCall(args, theme, context) {
|
|
176674
|
+
const todos = getCachedTodowriteToolCallTodos(context?.toolCallId) ?? parseTodos(args.todos) ?? [];
|
|
176313
176675
|
const active = activeTitleCount(todos);
|
|
176314
176676
|
const activeColor = active > 0 ? "warning" : "success";
|
|
176315
176677
|
const line = `${theme.fg("toolTitle", theme.bold("Todos"))} ${theme.fg("muted", "—")} ${theme.fg(activeColor, `${active} active`)}`;
|
|
176316
176678
|
return lineComponent((width) => [truncateToWidth(line, width, "…")]);
|
|
176317
176679
|
}
|
|
176318
|
-
function renderTodowriteResult(result, theme) {
|
|
176680
|
+
function renderTodowriteResult(result, theme, context) {
|
|
176319
176681
|
const detailsTodos = result.details?.todos;
|
|
176320
176682
|
let todos = parseTodos(detailsTodos);
|
|
176321
|
-
if (todos === null && Array.isArray(result.content)) {
|
|
176683
|
+
if ((todos === null || todos.length === 0) && Array.isArray(result.content)) {
|
|
176322
176684
|
const text = result.content.find((part) => part !== null && typeof part === "object" && part.type === "text" && typeof part.text === "string")?.text;
|
|
176323
176685
|
if (text) {
|
|
176324
176686
|
try {
|
|
176325
|
-
|
|
176687
|
+
const parsed = parseTodos(JSON.parse(text));
|
|
176688
|
+
if (parsed !== null)
|
|
176689
|
+
todos = parsed;
|
|
176326
176690
|
} catch {}
|
|
176327
176691
|
}
|
|
176328
176692
|
}
|
|
176329
|
-
const renderedTodos = todos ?? [];
|
|
176693
|
+
const renderedTodos = todos !== null && todos.length > 0 ? todos : getCachedTodowriteToolCallTodos(context?.toolCallId) ?? todos ?? [];
|
|
176330
176694
|
return lineComponent((width) => {
|
|
176331
176695
|
if (renderedTodos.length === 0)
|
|
176332
176696
|
return [theme.fg("dim", "No todos")];
|
|
@@ -176527,6 +176891,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
176527
176891
|
overlay.hideCompletedTasksFromPreviousTurn();
|
|
176528
176892
|
});
|
|
176529
176893
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
176894
|
+
clearTodowriteToolCallTodos();
|
|
176530
176895
|
const sessionId = getSessionId(ctx);
|
|
176531
176896
|
if (!sessionId)
|
|
176532
176897
|
return;
|
|
@@ -176534,6 +176899,7 @@ function registerTodoOverlay(pi, deps) {
|
|
|
176534
176899
|
overlay.disposeSession(sessionId);
|
|
176535
176900
|
});
|
|
176536
176901
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
176902
|
+
clearTodowriteToolCallTodos();
|
|
176537
176903
|
const sessionId = getSessionId(ctx);
|
|
176538
176904
|
if (!sessionId)
|
|
176539
176905
|
return;
|
|
@@ -176550,11 +176916,13 @@ function registerTodoStateLifecycle(pi, deps) {
|
|
|
176550
176916
|
seedTodoSnapshotFromStateJson(sessionId, deps.readLastTodoState(sessionId));
|
|
176551
176917
|
});
|
|
176552
176918
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
176919
|
+
clearTodowriteToolCallTodos();
|
|
176553
176920
|
const sessionId = getSessionId(ctx);
|
|
176554
176921
|
if (sessionId)
|
|
176555
176922
|
clearTodoSnapshot(sessionId);
|
|
176556
176923
|
});
|
|
176557
176924
|
pi.on("session_before_switch", async (_event, ctx) => {
|
|
176925
|
+
clearTodowriteToolCallTodos();
|
|
176558
176926
|
const sessionId = getSessionId(ctx);
|
|
176559
176927
|
if (sessionId)
|
|
176560
176928
|
clearTodoSnapshot(sessionId);
|
|
@@ -176605,11 +176973,11 @@ function createTodowriteTool() {
|
|
|
176605
176973
|
}
|
|
176606
176974
|
};
|
|
176607
176975
|
},
|
|
176608
|
-
renderCall(args, theme) {
|
|
176609
|
-
return renderTodowriteCall(args, theme);
|
|
176976
|
+
renderCall(args, theme, context) {
|
|
176977
|
+
return renderTodowriteCall(args, theme, context);
|
|
176610
176978
|
},
|
|
176611
|
-
renderResult(result, _opts, theme) {
|
|
176612
|
-
return renderTodowriteResult(result, theme);
|
|
176979
|
+
renderResult(result, _opts, theme, context) {
|
|
176980
|
+
return renderTodowriteResult(result, theme, context);
|
|
176613
176981
|
}
|
|
176614
176982
|
};
|
|
176615
176983
|
}
|