@cortexkit/pi-magic-context 0.16.2 → 0.17.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/README.md +2 -2
- package/dist/index.js +1865 -789
- package/dist/subagent-entry.js +1682 -793
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15043,14 +15043,334 @@ var init_embedding = __esm(() => {
|
|
|
15043
15043
|
SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
|
|
15044
15044
|
});
|
|
15045
15045
|
|
|
15046
|
+
// ../../node_modules/.bun/nanotar@0.3.0/node_modules/nanotar/dist/index.mjs
|
|
15047
|
+
function parseTar(data, opts) {
|
|
15048
|
+
const buffer2 = data.buffer || data;
|
|
15049
|
+
const files = [];
|
|
15050
|
+
let offset = 0;
|
|
15051
|
+
let nextExtendedHeader;
|
|
15052
|
+
let globalExtendedHeader;
|
|
15053
|
+
while (offset < buffer2.byteLength - 512) {
|
|
15054
|
+
let name = _readString(buffer2, offset, 100);
|
|
15055
|
+
if (name.length === 0) {
|
|
15056
|
+
break;
|
|
15057
|
+
}
|
|
15058
|
+
if (nextExtendedHeader) {
|
|
15059
|
+
const longName = nextExtendedHeader.path || nextExtendedHeader.linkpath;
|
|
15060
|
+
if (longName) {
|
|
15061
|
+
name = longName;
|
|
15062
|
+
}
|
|
15063
|
+
}
|
|
15064
|
+
const mode = _readString(buffer2, offset + 100, 8).trim();
|
|
15065
|
+
const uid = Number.parseInt(_readString(buffer2, offset + 108, 8));
|
|
15066
|
+
const gid = Number.parseInt(_readString(buffer2, offset + 116, 8));
|
|
15067
|
+
const size = _readNumber(buffer2, offset + 124, 12);
|
|
15068
|
+
const seek = 512 + 512 * Math.trunc(size / 512) + (size % 512 ? 512 : 0);
|
|
15069
|
+
const mtime = _readNumber(buffer2, offset + 136, 12);
|
|
15070
|
+
const _type = _readString(buffer2, offset + 156, 1) || "0";
|
|
15071
|
+
const type = tarItemTypeMap[_type] || _type;
|
|
15072
|
+
switch (type) {
|
|
15073
|
+
case "extendedHeader":
|
|
15074
|
+
case "globalExtendedHeader": {
|
|
15075
|
+
const headers = _parseExtendedHeaders(new Uint8Array(buffer2, offset + 512, size));
|
|
15076
|
+
if (type === "extendedHeader") {
|
|
15077
|
+
nextExtendedHeader = headers;
|
|
15078
|
+
} else {
|
|
15079
|
+
nextExtendedHeader = undefined;
|
|
15080
|
+
globalExtendedHeader = {
|
|
15081
|
+
...globalExtendedHeader,
|
|
15082
|
+
...headers
|
|
15083
|
+
};
|
|
15084
|
+
}
|
|
15085
|
+
offset += seek;
|
|
15086
|
+
continue;
|
|
15087
|
+
}
|
|
15088
|
+
case "gnuLongFileName":
|
|
15089
|
+
case "gnuOldLongFileName":
|
|
15090
|
+
case "gnuLongLinkName": {
|
|
15091
|
+
nextExtendedHeader = { path: _readString(buffer2, offset + 512, size) };
|
|
15092
|
+
offset += seek;
|
|
15093
|
+
continue;
|
|
15094
|
+
}
|
|
15095
|
+
}
|
|
15096
|
+
const user = _readString(buffer2, offset + 265, 32);
|
|
15097
|
+
const group = _readString(buffer2, offset + 297, 32);
|
|
15098
|
+
name = _sanitizePath(name);
|
|
15099
|
+
const meta3 = {
|
|
15100
|
+
name,
|
|
15101
|
+
type,
|
|
15102
|
+
size,
|
|
15103
|
+
attrs: {
|
|
15104
|
+
...globalExtendedHeader,
|
|
15105
|
+
...nextExtendedHeader,
|
|
15106
|
+
mode,
|
|
15107
|
+
uid,
|
|
15108
|
+
gid,
|
|
15109
|
+
mtime,
|
|
15110
|
+
user,
|
|
15111
|
+
group
|
|
15112
|
+
}
|
|
15113
|
+
};
|
|
15114
|
+
nextExtendedHeader = undefined;
|
|
15115
|
+
if (opts?.filter && !opts.filter(meta3)) {
|
|
15116
|
+
offset += seek;
|
|
15117
|
+
continue;
|
|
15118
|
+
}
|
|
15119
|
+
if (opts?.metaOnly) {
|
|
15120
|
+
files.push(meta3);
|
|
15121
|
+
offset += seek;
|
|
15122
|
+
continue;
|
|
15123
|
+
}
|
|
15124
|
+
const data2 = size === 0 ? undefined : new Uint8Array(buffer2, offset + 512, size);
|
|
15125
|
+
files.push({
|
|
15126
|
+
...meta3,
|
|
15127
|
+
data: data2,
|
|
15128
|
+
get text() {
|
|
15129
|
+
return new TextDecoder().decode(this.data);
|
|
15130
|
+
}
|
|
15131
|
+
});
|
|
15132
|
+
offset += seek;
|
|
15133
|
+
}
|
|
15134
|
+
return files;
|
|
15135
|
+
}
|
|
15136
|
+
async function parseTarGzip(data, opts = {}) {
|
|
15137
|
+
const stream = new ReadableStream({
|
|
15138
|
+
start(controller) {
|
|
15139
|
+
controller.enqueue(new Uint8Array(data));
|
|
15140
|
+
controller.close();
|
|
15141
|
+
}
|
|
15142
|
+
}).pipeThrough(new DecompressionStream(opts.compression ?? "gzip"));
|
|
15143
|
+
const decompressedData = await new Response(stream).arrayBuffer();
|
|
15144
|
+
return parseTar(decompressedData, opts);
|
|
15145
|
+
}
|
|
15146
|
+
function _sanitizePath(path4) {
|
|
15147
|
+
let normalized = path4.replace(/\\/g, "/");
|
|
15148
|
+
normalized = normalized.replace(/^[a-zA-Z]:\//, "");
|
|
15149
|
+
normalized = normalized.replace(/^\/+/, "");
|
|
15150
|
+
const hasLeadingDotSlash = normalized.startsWith("./");
|
|
15151
|
+
const parts = normalized.split("/");
|
|
15152
|
+
const resolved = [];
|
|
15153
|
+
for (const part of parts) {
|
|
15154
|
+
if (part === "..") {
|
|
15155
|
+
resolved.pop();
|
|
15156
|
+
} else if (part !== "." && part !== "") {
|
|
15157
|
+
resolved.push(part);
|
|
15158
|
+
}
|
|
15159
|
+
}
|
|
15160
|
+
let result = resolved.join("/");
|
|
15161
|
+
if (hasLeadingDotSlash && !result.startsWith("./")) {
|
|
15162
|
+
result = "./" + result;
|
|
15163
|
+
}
|
|
15164
|
+
if (path4.endsWith("/") && !result.endsWith("/")) {
|
|
15165
|
+
result += "/";
|
|
15166
|
+
}
|
|
15167
|
+
return result;
|
|
15168
|
+
}
|
|
15169
|
+
function _readString(buffer2, offset, size) {
|
|
15170
|
+
const view = new Uint8Array(buffer2, offset, size);
|
|
15171
|
+
const i = view.indexOf(0);
|
|
15172
|
+
const td = new TextDecoder;
|
|
15173
|
+
return td.decode(i === -1 ? view : view.slice(0, i));
|
|
15174
|
+
}
|
|
15175
|
+
function _readNumber(buffer2, offset, size) {
|
|
15176
|
+
const view = new Uint8Array(buffer2, offset, size);
|
|
15177
|
+
let str = "";
|
|
15178
|
+
for (let i = 0;i < size; i++) {
|
|
15179
|
+
str += String.fromCodePoint(view[i]);
|
|
15180
|
+
}
|
|
15181
|
+
return Number.parseInt(str, 8);
|
|
15182
|
+
}
|
|
15183
|
+
function _parseExtendedHeaders(data) {
|
|
15184
|
+
const dataStr = new TextDecoder().decode(data);
|
|
15185
|
+
const headers = {};
|
|
15186
|
+
for (const line of dataStr.split(`
|
|
15187
|
+
`)) {
|
|
15188
|
+
const s = line.split(" ")[1]?.split("=");
|
|
15189
|
+
if (s) {
|
|
15190
|
+
headers[s[0]] = s[1];
|
|
15191
|
+
}
|
|
15192
|
+
}
|
|
15193
|
+
return headers;
|
|
15194
|
+
}
|
|
15195
|
+
var tarItemTypeMap;
|
|
15196
|
+
var init_dist = __esm(() => {
|
|
15197
|
+
tarItemTypeMap = {
|
|
15198
|
+
"0": "file",
|
|
15199
|
+
"1": "hardLink",
|
|
15200
|
+
"2": "symbolicLink",
|
|
15201
|
+
"3": "characterDevice",
|
|
15202
|
+
"4": "blockDevice",
|
|
15203
|
+
"5": "directory",
|
|
15204
|
+
"6": "fifo",
|
|
15205
|
+
"7": "contiguousFile",
|
|
15206
|
+
g: "globalExtendedHeader",
|
|
15207
|
+
x: "extendedHeader",
|
|
15208
|
+
D: "gnuDirectory",
|
|
15209
|
+
I: "gnuInodeMetadata",
|
|
15210
|
+
K: "gnuLongLinkName",
|
|
15211
|
+
L: "gnuLongFileName",
|
|
15212
|
+
N: "gnuOldLongFileName",
|
|
15213
|
+
M: "gnuMultiVolume",
|
|
15214
|
+
S: "gnuSparseFile",
|
|
15215
|
+
E: "gnuExtendedSparse",
|
|
15216
|
+
A: "solarisAcl",
|
|
15217
|
+
V: "solarisVolumeLabel",
|
|
15218
|
+
X: "solarisOldExtendedHeader"
|
|
15219
|
+
};
|
|
15220
|
+
});
|
|
15221
|
+
|
|
15222
|
+
// ../plugin/src/shared/native-binding.ts
|
|
15223
|
+
var exports_native_binding = {};
|
|
15224
|
+
__export(exports_native_binding, {
|
|
15225
|
+
resolveBetterSqliteNativeBinding: () => resolveBetterSqliteNativeBinding
|
|
15226
|
+
});
|
|
15227
|
+
import { existsSync, mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
|
|
15228
|
+
import { createRequire } from "node:module";
|
|
15229
|
+
import * as path4 from "node:path";
|
|
15230
|
+
function logInfo(message) {
|
|
15231
|
+
log(`${PREFIX} ${message}`);
|
|
15232
|
+
}
|
|
15233
|
+
function logWarn(message) {
|
|
15234
|
+
log(`${PREFIX} WARN ${message}`);
|
|
15235
|
+
}
|
|
15236
|
+
function probeAbi(binaryPath) {
|
|
15237
|
+
const expected = process.versions.modules;
|
|
15238
|
+
try {
|
|
15239
|
+
const sandbox = { exports: {} };
|
|
15240
|
+
process.dlopen(sandbox, binaryPath);
|
|
15241
|
+
return { ok: true };
|
|
15242
|
+
} catch (err) {
|
|
15243
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
15244
|
+
const pair = message.match(/NODE_MODULE_VERSION (\d+).*NODE_MODULE_VERSION (\d+)/s);
|
|
15245
|
+
if (pair?.[1] && pair[2]) {
|
|
15246
|
+
return { ok: false, expected: pair[2], actual: pair[1] };
|
|
15247
|
+
}
|
|
15248
|
+
const single = message.match(/NODE_MODULE_VERSION[ =:]+(\d+)/);
|
|
15249
|
+
if (single?.[1]) {
|
|
15250
|
+
return { ok: false, expected, actual: single[1] };
|
|
15251
|
+
}
|
|
15252
|
+
logWarn(`could not parse ABI from dlopen error: ${message}`);
|
|
15253
|
+
return { ok: false, expected, actual: null };
|
|
15254
|
+
}
|
|
15255
|
+
}
|
|
15256
|
+
function resolveBetterSqlite3OnDisk(requireFn) {
|
|
15257
|
+
try {
|
|
15258
|
+
const pkgJsonPath = requireFn.resolve("better-sqlite3/package.json");
|
|
15259
|
+
const pkgDir = path4.dirname(pkgJsonPath);
|
|
15260
|
+
const pkgJson = requireFn(pkgJsonPath);
|
|
15261
|
+
const binaryPath = path4.join(pkgDir, "build", "Release", "better_sqlite3.node");
|
|
15262
|
+
return { binaryPath, pkgVersion: pkgJson.version };
|
|
15263
|
+
} catch (err) {
|
|
15264
|
+
logWarn(`could not resolve better-sqlite3 in node_modules: ${err instanceof Error ? err.message : String(err)}`);
|
|
15265
|
+
return null;
|
|
15266
|
+
}
|
|
15267
|
+
}
|
|
15268
|
+
function getCachedBinaryPath(pkgVersion, abi) {
|
|
15269
|
+
return path4.join(getCacheDir(), "cortexkit", "native-bindings", "better-sqlite3", `v${pkgVersion}`, `electron-v${abi}-${process.platform}-${process.arch}`, "better_sqlite3.node");
|
|
15270
|
+
}
|
|
15271
|
+
async function downloadElectronPrebuild(pkgVersion, abi) {
|
|
15272
|
+
const filename = `better-sqlite3-v${pkgVersion}-electron-v${abi}-${process.platform}-${process.arch}.tar.gz`;
|
|
15273
|
+
const url2 = `https://github.com/WiseLibs/better-sqlite3/releases/download/v${pkgVersion}/${filename}`;
|
|
15274
|
+
logInfo(`downloading ${url2}`);
|
|
15275
|
+
const response = await fetch(url2, {
|
|
15276
|
+
redirect: "follow",
|
|
15277
|
+
headers: { "User-Agent": "magic-context-plugin/native-binding" }
|
|
15278
|
+
});
|
|
15279
|
+
if (!response.ok) {
|
|
15280
|
+
throw new Error(`failed to download Electron prebuild (HTTP ${response.status} ${response.statusText}) from ${url2}`);
|
|
15281
|
+
}
|
|
15282
|
+
const tarballBytes = new Uint8Array(await response.arrayBuffer());
|
|
15283
|
+
logInfo(`downloaded ${(tarballBytes.length / 1024).toFixed(1)} KB; extracting`);
|
|
15284
|
+
const files = await parseTarGzip(tarballBytes);
|
|
15285
|
+
const nodeFile = files.find((f) => f.name.endsWith("better_sqlite3.node"));
|
|
15286
|
+
if (!nodeFile?.data) {
|
|
15287
|
+
const names = files.map((f) => f.name).join(", ");
|
|
15288
|
+
throw new Error(`Electron prebuild tarball did not contain better_sqlite3.node; got: [${names}]`);
|
|
15289
|
+
}
|
|
15290
|
+
return nodeFile.data instanceof Uint8Array ? nodeFile.data : new Uint8Array(nodeFile.data);
|
|
15291
|
+
}
|
|
15292
|
+
async function resolveBetterSqliteNativeBinding() {
|
|
15293
|
+
if (!process.versions.electron) {
|
|
15294
|
+
return null;
|
|
15295
|
+
}
|
|
15296
|
+
if (inFlight) {
|
|
15297
|
+
return inFlight;
|
|
15298
|
+
}
|
|
15299
|
+
const promise2 = (async () => {
|
|
15300
|
+
const expected = process.versions.modules;
|
|
15301
|
+
logInfo(`Electron detected (v${process.versions.electron}, NODE_MODULE_VERSION ${expected}); verifying better-sqlite3 binding`);
|
|
15302
|
+
const requireFn = createRequire(import.meta.url);
|
|
15303
|
+
const resolved = resolveBetterSqlite3OnDisk(requireFn);
|
|
15304
|
+
if (!resolved) {
|
|
15305
|
+
return null;
|
|
15306
|
+
}
|
|
15307
|
+
const { binaryPath: diskPath, pkgVersion } = resolved;
|
|
15308
|
+
if (existsSync(diskPath)) {
|
|
15309
|
+
const diskProbe = probeAbi(diskPath);
|
|
15310
|
+
if (diskProbe.ok) {
|
|
15311
|
+
logInfo(`on-disk binary already matches Electron ABI v${expected}; using default bindings() lookup`);
|
|
15312
|
+
return null;
|
|
15313
|
+
}
|
|
15314
|
+
logInfo(`on-disk binary ABI ${diskProbe.actual ?? "unknown"} != required ${expected}; will use Electron prebuild`);
|
|
15315
|
+
} else {
|
|
15316
|
+
logWarn(`expected better-sqlite3 binary not found at ${diskPath}; will fetch Electron prebuild anyway`);
|
|
15317
|
+
}
|
|
15318
|
+
const cachedPath = getCachedBinaryPath(pkgVersion, expected);
|
|
15319
|
+
if (existsSync(cachedPath)) {
|
|
15320
|
+
const cachedProbe = probeAbi(cachedPath);
|
|
15321
|
+
if (cachedProbe.ok) {
|
|
15322
|
+
logInfo(`using cached Electron prebuild at ${cachedPath}`);
|
|
15323
|
+
return cachedPath;
|
|
15324
|
+
}
|
|
15325
|
+
logWarn(`cached binary at ${cachedPath} has wrong ABI (${cachedProbe.actual ?? "unknown"} != ${expected}); refetching`);
|
|
15326
|
+
}
|
|
15327
|
+
mkdirSync2(path4.dirname(cachedPath), { recursive: true });
|
|
15328
|
+
const nodeFileBytes = await downloadElectronPrebuild(pkgVersion, expected);
|
|
15329
|
+
writeFileSync(cachedPath, nodeFileBytes);
|
|
15330
|
+
logInfo(`cached Electron prebuild at ${cachedPath} (${(nodeFileBytes.length / 1024).toFixed(1)} KB)`);
|
|
15331
|
+
const finalProbe = probeAbi(cachedPath);
|
|
15332
|
+
if (!finalProbe.ok) {
|
|
15333
|
+
throw new Error(`downloaded Electron prebuild has wrong ABI (${finalProbe.actual ?? "unknown"} != ${expected}); refusing to use`);
|
|
15334
|
+
}
|
|
15335
|
+
return cachedPath;
|
|
15336
|
+
})();
|
|
15337
|
+
inFlight = promise2;
|
|
15338
|
+
try {
|
|
15339
|
+
return await promise2;
|
|
15340
|
+
} finally {
|
|
15341
|
+
if (inFlight === promise2) {
|
|
15342
|
+
inFlight = null;
|
|
15343
|
+
}
|
|
15344
|
+
}
|
|
15345
|
+
}
|
|
15346
|
+
var PREFIX = "[native-binding]", inFlight = null;
|
|
15347
|
+
var init_native_binding = __esm(() => {
|
|
15348
|
+
init_dist();
|
|
15349
|
+
init_data_path();
|
|
15350
|
+
init_logger();
|
|
15351
|
+
});
|
|
15352
|
+
|
|
15046
15353
|
// ../plugin/src/shared/sqlite.ts
|
|
15047
|
-
var isBun, bunSpec, betterSpec, sqliteModule, DatabaseImpl, Database;
|
|
15354
|
+
var isBun, bunSpec, betterSpec, electronNativeBinding, sqliteModule, RawDatabaseImpl, DatabaseImpl, Database;
|
|
15048
15355
|
var init_sqlite = __esm(async () => {
|
|
15049
15356
|
isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
|
|
15050
15357
|
bunSpec = "bun:" + "sqlite";
|
|
15051
15358
|
betterSpec = "better-" + "sqlite3";
|
|
15359
|
+
electronNativeBinding = isBun ? null : await (async () => {
|
|
15360
|
+
const mod = await Promise.resolve().then(() => (init_native_binding(), exports_native_binding));
|
|
15361
|
+
return mod.resolveBetterSqliteNativeBinding();
|
|
15362
|
+
})();
|
|
15052
15363
|
sqliteModule = isBun ? await import(bunSpec) : await import(betterSpec);
|
|
15053
|
-
|
|
15364
|
+
RawDatabaseImpl = isBun ? sqliteModule.Database : sqliteModule.default;
|
|
15365
|
+
DatabaseImpl = electronNativeBinding == null ? RawDatabaseImpl : class DatabaseWithElectronBinding extends RawDatabaseImpl {
|
|
15366
|
+
constructor(filename, options) {
|
|
15367
|
+
const fallback = electronNativeBinding;
|
|
15368
|
+
super(filename, {
|
|
15369
|
+
...options,
|
|
15370
|
+
nativeBinding: options?.nativeBinding ?? fallback
|
|
15371
|
+
});
|
|
15372
|
+
}
|
|
15373
|
+
};
|
|
15054
15374
|
Database = DatabaseImpl;
|
|
15055
15375
|
});
|
|
15056
15376
|
|
|
@@ -15072,9 +15392,9 @@ __export(exports_read_session_db, {
|
|
|
15072
15392
|
findLastAssistantModelFromOpenCodeDb: () => findLastAssistantModelFromOpenCodeDb,
|
|
15073
15393
|
closeReadOnlySessionDb: () => closeReadOnlySessionDb
|
|
15074
15394
|
});
|
|
15075
|
-
import { join as
|
|
15395
|
+
import { join as join5 } from "node:path";
|
|
15076
15396
|
function getOpenCodeDbPath() {
|
|
15077
|
-
return
|
|
15397
|
+
return join5(getDataDir(), "opencode", "opencode.db");
|
|
15078
15398
|
}
|
|
15079
15399
|
function closeCachedReadOnlyDb() {
|
|
15080
15400
|
if (!cachedReadOnlyDb) {
|
|
@@ -15133,7 +15453,8 @@ function findLastAssistantModelFromOpenCodeDb(sessionId) {
|
|
|
15133
15453
|
try {
|
|
15134
15454
|
return withReadOnlySessionDb((db) => {
|
|
15135
15455
|
const row = db.prepare(`SELECT json_extract(data, '$.providerID') as providerID,
|
|
15136
|
-
json_extract(data, '$.modelID') as modelID
|
|
15456
|
+
json_extract(data, '$.modelID') as modelID,
|
|
15457
|
+
json_extract(data, '$.agent') as agent
|
|
15137
15458
|
FROM message
|
|
15138
15459
|
WHERE session_id = ?
|
|
15139
15460
|
AND json_extract(data, '$.role') = 'assistant'
|
|
@@ -15144,7 +15465,12 @@ function findLastAssistantModelFromOpenCodeDb(sessionId) {
|
|
|
15144
15465
|
if (!row || typeof row.providerID !== "string" || typeof row.modelID !== "string") {
|
|
15145
15466
|
return null;
|
|
15146
15467
|
}
|
|
15147
|
-
|
|
15468
|
+
const agent = typeof row.agent === "string" && row.agent.length > 0 ? row.agent : undefined;
|
|
15469
|
+
return {
|
|
15470
|
+
providerID: row.providerID,
|
|
15471
|
+
modelID: row.modelID,
|
|
15472
|
+
...agent ? { agent } : {}
|
|
15473
|
+
};
|
|
15148
15474
|
});
|
|
15149
15475
|
} catch (error48) {
|
|
15150
15476
|
log("[magic-context] failed to recover live model from OpenCode DB:", error48);
|
|
@@ -22792,10 +23118,10 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
22792
23118
|
replacer = null;
|
|
22793
23119
|
indent = EMPTY;
|
|
22794
23120
|
};
|
|
22795
|
-
var
|
|
23121
|
+
var join13 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one, gap)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two, gap)), gap) : EMPTY;
|
|
22796
23122
|
var join_content = (inside, value, gap) => {
|
|
22797
23123
|
const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
|
|
22798
|
-
return
|
|
23124
|
+
return join13(comment, inside, gap);
|
|
22799
23125
|
};
|
|
22800
23126
|
var stringify_string = (holder, key, value) => {
|
|
22801
23127
|
const raw = get_raw_string_literal(holder, key);
|
|
@@ -22817,13 +23143,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
22817
23143
|
if (i !== 0) {
|
|
22818
23144
|
inside += COMMA;
|
|
22819
23145
|
}
|
|
22820
|
-
const before =
|
|
23146
|
+
const before = join13(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
|
|
22821
23147
|
inside += before || LF + deeper_gap;
|
|
22822
23148
|
inside += stringify(i, value, deeper_gap) || STR_NULL;
|
|
22823
23149
|
inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
|
|
22824
23150
|
after_comma = process_comments(value, AFTER(i), deeper_gap);
|
|
22825
23151
|
}
|
|
22826
|
-
inside +=
|
|
23152
|
+
inside += join13(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
22827
23153
|
return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
|
|
22828
23154
|
};
|
|
22829
23155
|
var object_stringify = (value, gap) => {
|
|
@@ -22844,13 +23170,13 @@ var require_stringify = __commonJS((exports, module) => {
|
|
|
22844
23170
|
inside += COMMA;
|
|
22845
23171
|
}
|
|
22846
23172
|
first = false;
|
|
22847
|
-
const before =
|
|
23173
|
+
const before = join13(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
|
|
22848
23174
|
inside += before || LF + deeper_gap;
|
|
22849
23175
|
inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
|
|
22850
23176
|
after_comma = process_comments(value, AFTER(key), deeper_gap);
|
|
22851
23177
|
};
|
|
22852
23178
|
keys.forEach(iteratee);
|
|
22853
|
-
inside +=
|
|
23179
|
+
inside += join13(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
|
|
22854
23180
|
return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
|
|
22855
23181
|
};
|
|
22856
23182
|
function stringify(key, holder, gap) {
|
|
@@ -22944,8 +23270,8 @@ var require_src2 = __commonJS((exports, module) => {
|
|
|
22944
23270
|
|
|
22945
23271
|
// src/index.ts
|
|
22946
23272
|
init_embedding();
|
|
22947
|
-
import { createRequire } from "node:module";
|
|
22948
|
-
import { join as
|
|
23273
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
23274
|
+
import { join as join15 } from "node:path";
|
|
22949
23275
|
|
|
22950
23276
|
// ../plugin/src/features/magic-context/memory/project-identity.ts
|
|
22951
23277
|
import { execSync } from "node:child_process";
|
|
@@ -22985,422 +23311,9 @@ function resolveProjectIdentity(directory) {
|
|
|
22985
23311
|
return identity;
|
|
22986
23312
|
}
|
|
22987
23313
|
|
|
22988
|
-
// ../plugin/src/features/magic-context/
|
|
22989
|
-
|
|
22990
|
-
/prompt is too long/i,
|
|
22991
|
-
/input is too long for requested model/i,
|
|
22992
|
-
/exceeds the context window/i,
|
|
22993
|
-
/input token count.*exceeds the maximum/i,
|
|
22994
|
-
/maximum prompt length is \d+/i,
|
|
22995
|
-
/reduce the length of the messages/i,
|
|
22996
|
-
/maximum context length is \d+ tokens/i,
|
|
22997
|
-
/exceeds the limit of \d+/i,
|
|
22998
|
-
/exceeds the available context size/i,
|
|
22999
|
-
/greater than the context length/i,
|
|
23000
|
-
/context window exceeds limit/i,
|
|
23001
|
-
/exceeded model token limit/i,
|
|
23002
|
-
/context[_ ]length[_ ]exceeded/i,
|
|
23003
|
-
/request entity too large/i,
|
|
23004
|
-
/context length is only \d+ tokens/i,
|
|
23005
|
-
/input length.*exceeds.*context length/i,
|
|
23006
|
-
/prompt too long; exceeded (?:max )?context length/i,
|
|
23007
|
-
/too large for model with \d+ maximum context length/i,
|
|
23008
|
-
/model_context_window_exceeded/i,
|
|
23009
|
-
/context size has been exceeded/i
|
|
23010
|
-
];
|
|
23011
|
-
var LIMIT_EXTRACTION_PATTERNS = [
|
|
23012
|
-
/maximum prompt length is (\d+)/i,
|
|
23013
|
-
/maximum context length is (\d+) tokens?/i,
|
|
23014
|
-
/context length is only (\d+) tokens?/i,
|
|
23015
|
-
/exceeds the limit of (\d+)/i,
|
|
23016
|
-
/too large for model with (\d+) maximum context length/i,
|
|
23017
|
-
/context size.*(\d+) tokens?/i,
|
|
23018
|
-
/exceeds? the context length of (\d+)/i,
|
|
23019
|
-
/max(?:imum)?.*context.*?(\d+)/i
|
|
23020
|
-
];
|
|
23021
|
-
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
23022
|
-
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
23023
|
-
function extractErrorMessage(error48) {
|
|
23024
|
-
if (!error48)
|
|
23025
|
-
return "";
|
|
23026
|
-
if (typeof error48 === "string")
|
|
23027
|
-
return error48;
|
|
23028
|
-
if (typeof error48 === "object") {
|
|
23029
|
-
const obj = error48;
|
|
23030
|
-
const nested = obj.error;
|
|
23031
|
-
if (nested && typeof nested.message === "string" && nested.message.length > 0) {
|
|
23032
|
-
return nested.message;
|
|
23033
|
-
}
|
|
23034
|
-
}
|
|
23035
|
-
if (error48 instanceof Error)
|
|
23036
|
-
return error48.message;
|
|
23037
|
-
if (typeof error48 === "object") {
|
|
23038
|
-
const obj = error48;
|
|
23039
|
-
if (typeof obj.message === "string")
|
|
23040
|
-
return obj.message;
|
|
23041
|
-
if (typeof obj.responseBody === "string")
|
|
23042
|
-
return obj.responseBody;
|
|
23043
|
-
try {
|
|
23044
|
-
return JSON.stringify(error48);
|
|
23045
|
-
} catch {
|
|
23046
|
-
return String(error48);
|
|
23047
|
-
}
|
|
23048
|
-
}
|
|
23049
|
-
return String(error48);
|
|
23050
|
-
}
|
|
23051
|
-
function detectOverflow(error48) {
|
|
23052
|
-
const message = extractErrorMessage(error48);
|
|
23053
|
-
if (!message) {
|
|
23054
|
-
return { isOverflow: false };
|
|
23055
|
-
}
|
|
23056
|
-
const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
|
|
23057
|
-
let matched;
|
|
23058
|
-
for (const pattern of OVERFLOW_PATTERNS) {
|
|
23059
|
-
if (pattern.test(message)) {
|
|
23060
|
-
matched = pattern;
|
|
23061
|
-
break;
|
|
23062
|
-
}
|
|
23063
|
-
}
|
|
23064
|
-
if (!matched && !hasStatus413) {
|
|
23065
|
-
return { isOverflow: false };
|
|
23066
|
-
}
|
|
23067
|
-
const reportedLimit = parseReportedLimit(message);
|
|
23068
|
-
return {
|
|
23069
|
-
isOverflow: true,
|
|
23070
|
-
reportedLimit,
|
|
23071
|
-
matchedPattern: matched?.source
|
|
23072
|
-
};
|
|
23073
|
-
}
|
|
23074
|
-
function parseReportedLimit(message) {
|
|
23075
|
-
if (!message)
|
|
23076
|
-
return;
|
|
23077
|
-
for (const pattern of LIMIT_EXTRACTION_PATTERNS) {
|
|
23078
|
-
const match = message.match(pattern);
|
|
23079
|
-
if (!match)
|
|
23080
|
-
continue;
|
|
23081
|
-
const raw = match[1];
|
|
23082
|
-
if (!raw)
|
|
23083
|
-
continue;
|
|
23084
|
-
const value = Number.parseInt(raw, 10);
|
|
23085
|
-
if (!Number.isFinite(value))
|
|
23086
|
-
continue;
|
|
23087
|
-
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
23088
|
-
continue;
|
|
23089
|
-
return value;
|
|
23090
|
-
}
|
|
23091
|
-
return;
|
|
23092
|
-
}
|
|
23093
|
-
|
|
23094
|
-
// ../plugin/src/shared/harness.ts
|
|
23095
|
-
var currentHarness = "opencode";
|
|
23096
|
-
var harnessLocked = false;
|
|
23097
|
-
function setHarness(value) {
|
|
23098
|
-
if (harnessLocked && currentHarness !== value) {
|
|
23099
|
-
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
23100
|
-
}
|
|
23101
|
-
currentHarness = value;
|
|
23102
|
-
harnessLocked = true;
|
|
23103
|
-
}
|
|
23104
|
-
function getHarness() {
|
|
23105
|
-
return currentHarness;
|
|
23106
|
-
}
|
|
23314
|
+
// ../plugin/src/features/magic-context/message-index-async.ts
|
|
23315
|
+
init_logger();
|
|
23107
23316
|
|
|
23108
|
-
// ../plugin/src/features/magic-context/compartment-storage.ts
|
|
23109
|
-
var insertCompartmentStatements = new WeakMap;
|
|
23110
|
-
var insertFactStatements = new WeakMap;
|
|
23111
|
-
function getInsertCompartmentStatement(db) {
|
|
23112
|
-
let stmt = insertCompartmentStatements.get(db);
|
|
23113
|
-
if (!stmt) {
|
|
23114
|
-
stmt = db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
23115
|
-
insertCompartmentStatements.set(db, stmt);
|
|
23116
|
-
}
|
|
23117
|
-
return stmt;
|
|
23118
|
-
}
|
|
23119
|
-
function getInsertFactStatement(db) {
|
|
23120
|
-
let stmt = insertFactStatements.get(db);
|
|
23121
|
-
if (!stmt) {
|
|
23122
|
-
stmt = db.prepare("INSERT INTO session_facts (session_id, category, content, created_at, updated_at, harness) VALUES (?, ?, ?, ?, ?, ?)");
|
|
23123
|
-
insertFactStatements.set(db, stmt);
|
|
23124
|
-
}
|
|
23125
|
-
return stmt;
|
|
23126
|
-
}
|
|
23127
|
-
function isCompartmentRow(row) {
|
|
23128
|
-
if (row === null || typeof row !== "object")
|
|
23129
|
-
return false;
|
|
23130
|
-
const candidate = row;
|
|
23131
|
-
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number";
|
|
23132
|
-
}
|
|
23133
|
-
function isSessionFactRow(row) {
|
|
23134
|
-
if (row === null || typeof row !== "object")
|
|
23135
|
-
return false;
|
|
23136
|
-
const candidate = row;
|
|
23137
|
-
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.category === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number";
|
|
23138
|
-
}
|
|
23139
|
-
function insertCompartmentRows(db, sessionId, compartments, now) {
|
|
23140
|
-
const stmt = getInsertCompartmentStatement(db);
|
|
23141
|
-
for (const compartment of compartments) {
|
|
23142
|
-
stmt.run(sessionId, compartment.sequence, compartment.startMessage, compartment.endMessage, compartment.startMessageId, compartment.endMessageId, compartment.title, compartment.content, now, getHarness());
|
|
23143
|
-
}
|
|
23144
|
-
}
|
|
23145
|
-
function insertFactRows(db, sessionId, facts, now) {
|
|
23146
|
-
const stmt = getInsertFactStatement(db);
|
|
23147
|
-
for (const fact of facts) {
|
|
23148
|
-
stmt.run(sessionId, fact.category, fact.content, now, now, getHarness());
|
|
23149
|
-
}
|
|
23150
|
-
}
|
|
23151
|
-
function toCompartment(row) {
|
|
23152
|
-
return {
|
|
23153
|
-
id: row.id,
|
|
23154
|
-
sessionId: row.session_id,
|
|
23155
|
-
sequence: row.sequence,
|
|
23156
|
-
startMessage: row.start_message,
|
|
23157
|
-
endMessage: row.end_message,
|
|
23158
|
-
startMessageId: row.start_message_id,
|
|
23159
|
-
endMessageId: row.end_message_id,
|
|
23160
|
-
title: row.title,
|
|
23161
|
-
content: row.content,
|
|
23162
|
-
createdAt: row.created_at
|
|
23163
|
-
};
|
|
23164
|
-
}
|
|
23165
|
-
function toSessionFact(row) {
|
|
23166
|
-
return {
|
|
23167
|
-
id: row.id,
|
|
23168
|
-
sessionId: row.session_id,
|
|
23169
|
-
category: row.category,
|
|
23170
|
-
content: row.content,
|
|
23171
|
-
createdAt: row.created_at,
|
|
23172
|
-
updatedAt: row.updated_at
|
|
23173
|
-
};
|
|
23174
|
-
}
|
|
23175
|
-
function getCompartments(db, sessionId) {
|
|
23176
|
-
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
|
|
23177
|
-
return rows.map(toCompartment);
|
|
23178
|
-
}
|
|
23179
|
-
function getLastCompartmentEndMessage(db, sessionId) {
|
|
23180
|
-
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
23181
|
-
return row?.max_end ?? -1;
|
|
23182
|
-
}
|
|
23183
|
-
function appendCompartments(db, sessionId, compartments) {
|
|
23184
|
-
if (compartments.length === 0)
|
|
23185
|
-
return;
|
|
23186
|
-
const now = Date.now();
|
|
23187
|
-
db.transaction(() => {
|
|
23188
|
-
insertCompartmentRows(db, sessionId, compartments, now);
|
|
23189
|
-
})();
|
|
23190
|
-
}
|
|
23191
|
-
function replaceSessionFacts(db, sessionId, facts) {
|
|
23192
|
-
const now = Date.now();
|
|
23193
|
-
db.transaction(() => {
|
|
23194
|
-
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
23195
|
-
insertFactRows(db, sessionId, facts, now);
|
|
23196
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
23197
|
-
})();
|
|
23198
|
-
}
|
|
23199
|
-
function getSessionFacts(db, sessionId) {
|
|
23200
|
-
const rows = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY category ASC, id ASC").all(sessionId).filter(isSessionFactRow);
|
|
23201
|
-
return rows.map(toSessionFact);
|
|
23202
|
-
}
|
|
23203
|
-
function replaceAllCompartmentState(db, sessionId, compartments, facts) {
|
|
23204
|
-
const now = Date.now();
|
|
23205
|
-
db.transaction(() => {
|
|
23206
|
-
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
23207
|
-
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
23208
|
-
insertCompartmentRows(db, sessionId, compartments, now);
|
|
23209
|
-
insertFactRows(db, sessionId, facts, now);
|
|
23210
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
23211
|
-
})();
|
|
23212
|
-
}
|
|
23213
|
-
function buildCompartmentBlock(compartments, facts, memoryBlock, dateRanges) {
|
|
23214
|
-
const lines = [];
|
|
23215
|
-
if (memoryBlock) {
|
|
23216
|
-
lines.push(memoryBlock);
|
|
23217
|
-
lines.push("");
|
|
23218
|
-
}
|
|
23219
|
-
for (const c of compartments) {
|
|
23220
|
-
const dates = dateRanges?.byId.get(c.id);
|
|
23221
|
-
const dateAttr = dates ? ` start-date="${dates.start}" end-date="${dates.end}"` : "";
|
|
23222
|
-
lines.push(`<compartment start="${c.startMessage}" end="${c.endMessage}"${dateAttr} title="${escapeXmlAttr(c.title)}">`);
|
|
23223
|
-
lines.push(escapeXmlContent(c.content));
|
|
23224
|
-
lines.push("</compartment>");
|
|
23225
|
-
lines.push("");
|
|
23226
|
-
}
|
|
23227
|
-
const factsByCategory = new Map;
|
|
23228
|
-
for (const f of facts) {
|
|
23229
|
-
const existing = factsByCategory.get(f.category) ?? [];
|
|
23230
|
-
existing.push(f.content);
|
|
23231
|
-
factsByCategory.set(f.category, existing);
|
|
23232
|
-
}
|
|
23233
|
-
for (const [category, items] of factsByCategory) {
|
|
23234
|
-
lines.push(`${category}:`);
|
|
23235
|
-
for (const item of items) {
|
|
23236
|
-
lines.push(`* ${escapeXmlContent(item)}`);
|
|
23237
|
-
}
|
|
23238
|
-
lines.push("");
|
|
23239
|
-
}
|
|
23240
|
-
return lines.join(`
|
|
23241
|
-
`).trimEnd();
|
|
23242
|
-
}
|
|
23243
|
-
function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
|
|
23244
|
-
const now = Date.now();
|
|
23245
|
-
db.transaction(() => {
|
|
23246
|
-
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
23247
|
-
const compartmentStmt = db.prepare("INSERT OR REPLACE INTO recomp_compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, pass_number, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
23248
|
-
for (const c of compartments) {
|
|
23249
|
-
compartmentStmt.run(sessionId, c.sequence, c.startMessage, c.endMessage, c.startMessageId, c.endMessageId, c.title, c.content, passNumber, now, getHarness());
|
|
23250
|
-
}
|
|
23251
|
-
const factStmt = db.prepare("INSERT INTO recomp_facts (session_id, category, content, pass_number, created_at, harness) VALUES (?, ?, ?, ?, ?, ?)");
|
|
23252
|
-
for (const f of facts) {
|
|
23253
|
-
factStmt.run(sessionId, f.category, f.content, passNumber, now, getHarness());
|
|
23254
|
-
}
|
|
23255
|
-
})();
|
|
23256
|
-
}
|
|
23257
|
-
function getRecompStaging(db, sessionId) {
|
|
23258
|
-
const compartmentRows = db.prepare("SELECT * FROM recomp_compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isRecompCompartmentRow);
|
|
23259
|
-
if (compartmentRows.length === 0)
|
|
23260
|
-
return null;
|
|
23261
|
-
const compartments = compartmentRows.map((row) => ({
|
|
23262
|
-
sequence: row.sequence,
|
|
23263
|
-
startMessage: row.start_message,
|
|
23264
|
-
endMessage: row.end_message,
|
|
23265
|
-
startMessageId: row.start_message_id,
|
|
23266
|
-
endMessageId: row.end_message_id,
|
|
23267
|
-
title: row.title,
|
|
23268
|
-
content: row.content
|
|
23269
|
-
}));
|
|
23270
|
-
const factRows = db.prepare("SELECT category, content FROM recomp_facts WHERE session_id = ?").all(sessionId).filter(isRecompFactRow);
|
|
23271
|
-
const maxPass = compartmentRows.reduce((m, r) => Math.max(m, r.pass_number), 0);
|
|
23272
|
-
const lastEnd = compartmentRows[compartmentRows.length - 1]?.end_message ?? 0;
|
|
23273
|
-
return {
|
|
23274
|
-
compartments,
|
|
23275
|
-
facts: factRows,
|
|
23276
|
-
passCount: maxPass,
|
|
23277
|
-
lastEndMessage: lastEnd
|
|
23278
|
-
};
|
|
23279
|
-
}
|
|
23280
|
-
function promoteRecompStaging(db, sessionId) {
|
|
23281
|
-
const now = Date.now();
|
|
23282
|
-
return db.transaction(() => {
|
|
23283
|
-
const staging = getRecompStaging(db, sessionId);
|
|
23284
|
-
if (!staging || staging.compartments.length === 0)
|
|
23285
|
-
return null;
|
|
23286
|
-
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
23287
|
-
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
23288
|
-
insertCompartmentRows(db, sessionId, staging.compartments, now);
|
|
23289
|
-
insertFactRows(db, sessionId, staging.facts, now);
|
|
23290
|
-
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
23291
|
-
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
23292
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE session_id = ?").run(sessionId);
|
|
23293
|
-
return { compartments: staging.compartments, facts: staging.facts };
|
|
23294
|
-
})();
|
|
23295
|
-
}
|
|
23296
|
-
function invalidateAllMemoryBlockCaches(db) {
|
|
23297
|
-
try {
|
|
23298
|
-
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE memory_block_cache != '' OR memory_block_ids != ''").run();
|
|
23299
|
-
} catch {}
|
|
23300
|
-
}
|
|
23301
|
-
function clearRecompStaging(db, sessionId) {
|
|
23302
|
-
db.transaction(() => {
|
|
23303
|
-
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
23304
|
-
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
23305
|
-
try {
|
|
23306
|
-
db.prepare("UPDATE session_meta SET recomp_partial_range_start = 0, recomp_partial_range_end = 0 WHERE session_id = ?").run(sessionId);
|
|
23307
|
-
} catch {}
|
|
23308
|
-
})();
|
|
23309
|
-
}
|
|
23310
|
-
function getRecompPartialRange(db, sessionId) {
|
|
23311
|
-
try {
|
|
23312
|
-
const row = db.prepare("SELECT recomp_partial_range_start AS start, recomp_partial_range_end AS end FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
23313
|
-
const start = typeof row?.start === "number" ? row.start : 0;
|
|
23314
|
-
const end = typeof row?.end === "number" ? row.end : 0;
|
|
23315
|
-
if (start <= 0 || end <= 0)
|
|
23316
|
-
return null;
|
|
23317
|
-
return { start, end };
|
|
23318
|
-
} catch {
|
|
23319
|
-
return null;
|
|
23320
|
-
}
|
|
23321
|
-
}
|
|
23322
|
-
function setRecompPartialRange(db, sessionId, range) {
|
|
23323
|
-
const start = range ? range.start : 0;
|
|
23324
|
-
const end = range ? range.end : 0;
|
|
23325
|
-
db.prepare("INSERT OR IGNORE INTO session_meta (session_id) VALUES (?)").run(sessionId);
|
|
23326
|
-
db.prepare("UPDATE session_meta SET recomp_partial_range_start = ?, recomp_partial_range_end = ? WHERE session_id = ?").run(start, end, sessionId);
|
|
23327
|
-
}
|
|
23328
|
-
function isRecompCompartmentRow(row) {
|
|
23329
|
-
if (row === null || typeof row !== "object")
|
|
23330
|
-
return false;
|
|
23331
|
-
const candidate = row;
|
|
23332
|
-
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && typeof candidate.pass_number === "number" && typeof candidate.created_at === "number";
|
|
23333
|
-
}
|
|
23334
|
-
function isRecompFactRow(row) {
|
|
23335
|
-
if (row === null || typeof row !== "object")
|
|
23336
|
-
return false;
|
|
23337
|
-
const candidate = row;
|
|
23338
|
-
return typeof candidate.category === "string" && typeof candidate.content === "string";
|
|
23339
|
-
}
|
|
23340
|
-
function escapeXmlAttr(s) {
|
|
23341
|
-
return s.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
23342
|
-
}
|
|
23343
|
-
function escapeXmlContent(s) {
|
|
23344
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
23345
|
-
}
|
|
23346
|
-
// ../plugin/src/features/magic-context/compression-depth-storage.ts
|
|
23347
|
-
var incrementDepthStatements = new WeakMap;
|
|
23348
|
-
var totalDepthStatements = new WeakMap;
|
|
23349
|
-
var maxDepthStatements = new WeakMap;
|
|
23350
|
-
var clearDepthStatements = new WeakMap;
|
|
23351
|
-
function getIncrementDepthStatement(db) {
|
|
23352
|
-
let stmt = incrementDepthStatements.get(db);
|
|
23353
|
-
if (!stmt) {
|
|
23354
|
-
stmt = db.prepare("INSERT INTO compression_depth (session_id, message_ordinal, depth, harness) VALUES (?, ?, 1, ?) ON CONFLICT(session_id, message_ordinal) DO UPDATE SET depth = depth + 1");
|
|
23355
|
-
incrementDepthStatements.set(db, stmt);
|
|
23356
|
-
}
|
|
23357
|
-
return stmt;
|
|
23358
|
-
}
|
|
23359
|
-
function getTotalDepthStatement(db) {
|
|
23360
|
-
let stmt = totalDepthStatements.get(db);
|
|
23361
|
-
if (!stmt) {
|
|
23362
|
-
stmt = db.prepare("SELECT COALESCE(SUM(depth), 0) AS total_depth FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?");
|
|
23363
|
-
totalDepthStatements.set(db, stmt);
|
|
23364
|
-
}
|
|
23365
|
-
return stmt;
|
|
23366
|
-
}
|
|
23367
|
-
function getClearDepthStatement(db) {
|
|
23368
|
-
let stmt = clearDepthStatements.get(db);
|
|
23369
|
-
if (!stmt) {
|
|
23370
|
-
stmt = db.prepare("DELETE FROM compression_depth WHERE session_id = ?");
|
|
23371
|
-
clearDepthStatements.set(db, stmt);
|
|
23372
|
-
}
|
|
23373
|
-
return stmt;
|
|
23374
|
-
}
|
|
23375
|
-
function incrementCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
|
|
23376
|
-
if (endOrdinal < startOrdinal) {
|
|
23377
|
-
return;
|
|
23378
|
-
}
|
|
23379
|
-
db.transaction(() => {
|
|
23380
|
-
const stmt = getIncrementDepthStatement(db);
|
|
23381
|
-
for (let ordinal = startOrdinal;ordinal <= endOrdinal; ordinal += 1) {
|
|
23382
|
-
stmt.run(sessionId, ordinal, getHarness());
|
|
23383
|
-
}
|
|
23384
|
-
})();
|
|
23385
|
-
}
|
|
23386
|
-
function getAverageCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
|
|
23387
|
-
if (endOrdinal < startOrdinal) {
|
|
23388
|
-
return 0;
|
|
23389
|
-
}
|
|
23390
|
-
const row = getTotalDepthStatement(db).get(sessionId, startOrdinal, endOrdinal);
|
|
23391
|
-
const totalDepth = typeof row?.total_depth === "number" ? row.total_depth : 0;
|
|
23392
|
-
const messageCount = endOrdinal - startOrdinal + 1;
|
|
23393
|
-
return totalDepth / messageCount;
|
|
23394
|
-
}
|
|
23395
|
-
function clearCompressionDepth(db, sessionId) {
|
|
23396
|
-
getClearDepthStatement(db).run(sessionId);
|
|
23397
|
-
}
|
|
23398
|
-
function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
|
|
23399
|
-
if (endOrdinal < startOrdinal) {
|
|
23400
|
-
return;
|
|
23401
|
-
}
|
|
23402
|
-
db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?").run(sessionId, startOrdinal, endOrdinal);
|
|
23403
|
-
}
|
|
23404
23317
|
// ../plugin/src/shared/internal-initiator-marker.ts
|
|
23405
23318
|
var OMO_INTERNAL_INITIATOR_MARKER = "<!-- OMO_INTERNAL_INITIATOR -->";
|
|
23406
23319
|
|
|
@@ -156078,21 +155991,85 @@ function isTextPart(part) {
|
|
|
156078
155991
|
const p = part;
|
|
156079
155992
|
return p.type === "text" && typeof p.text === "string";
|
|
156080
155993
|
}
|
|
156081
|
-
function
|
|
155994
|
+
function isFilePart(part) {
|
|
156082
155995
|
if (part === null || typeof part !== "object")
|
|
156083
155996
|
return false;
|
|
156084
155997
|
const p = part;
|
|
156085
|
-
|
|
155998
|
+
return p.type === "file" && typeof p.url === "string";
|
|
155999
|
+
}
|
|
156000
|
+
|
|
156001
|
+
// ../plugin/src/shared/record-type-guard.ts
|
|
156002
|
+
function isRecord(value) {
|
|
156003
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
156004
|
+
}
|
|
156005
|
+
|
|
156006
|
+
// ../plugin/src/hooks/magic-context/tool-drop-target.ts
|
|
156007
|
+
var IGNORE_PART_TYPES = new Set([
|
|
156008
|
+
"thinking",
|
|
156009
|
+
"reasoning",
|
|
156010
|
+
"redacted_thinking",
|
|
156011
|
+
"meta",
|
|
156012
|
+
"step-start",
|
|
156013
|
+
"step-finish"
|
|
156014
|
+
]);
|
|
156015
|
+
function isToolCallId(value) {
|
|
156016
|
+
return typeof value === "string" && value.length > 0;
|
|
156017
|
+
}
|
|
156018
|
+
function hasMeaningfulPart(part) {
|
|
156019
|
+
if (!isRecord(part))
|
|
156086
156020
|
return false;
|
|
156087
|
-
|
|
156021
|
+
const type = part.type;
|
|
156022
|
+
if (type === "text") {
|
|
156023
|
+
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
156024
|
+
}
|
|
156025
|
+
if (typeof type !== "string")
|
|
156088
156026
|
return false;
|
|
156089
|
-
|
|
156090
|
-
}
|
|
156091
|
-
function isFilePart(part) {
|
|
156092
|
-
if (part === null || typeof part !== "object")
|
|
156027
|
+
if (IGNORE_PART_TYPES.has(type))
|
|
156093
156028
|
return false;
|
|
156094
|
-
|
|
156095
|
-
|
|
156029
|
+
return true;
|
|
156030
|
+
}
|
|
156031
|
+
function extractToolCallObservation(part) {
|
|
156032
|
+
if (!isRecord(part))
|
|
156033
|
+
return null;
|
|
156034
|
+
if (part.type === "tool" && isToolCallId(part.callID)) {
|
|
156035
|
+
return { callId: part.callID, kind: "result" };
|
|
156036
|
+
}
|
|
156037
|
+
if (part.type === "tool-invocation" && isToolCallId(part.callID)) {
|
|
156038
|
+
return { callId: part.callID, kind: "invocation" };
|
|
156039
|
+
}
|
|
156040
|
+
if (part.type === "tool_use" && isToolCallId(part.id)) {
|
|
156041
|
+
return { callId: part.id, kind: "invocation" };
|
|
156042
|
+
}
|
|
156043
|
+
if (part.type === "tool_result" && isToolCallId(part.tool_use_id)) {
|
|
156044
|
+
return { callId: part.tool_use_id, kind: "result" };
|
|
156045
|
+
}
|
|
156046
|
+
return null;
|
|
156047
|
+
}
|
|
156048
|
+
class ToolMutationBatch {
|
|
156049
|
+
partsToRemove = new Set;
|
|
156050
|
+
affectedMessages = new Set;
|
|
156051
|
+
messages;
|
|
156052
|
+
constructor(messages) {
|
|
156053
|
+
this.messages = messages;
|
|
156054
|
+
}
|
|
156055
|
+
markForRemoval(occurrence) {
|
|
156056
|
+
this.partsToRemove.add(occurrence.part);
|
|
156057
|
+
this.affectedMessages.add(occurrence.message);
|
|
156058
|
+
}
|
|
156059
|
+
finalize() {
|
|
156060
|
+
if (this.partsToRemove.size === 0)
|
|
156061
|
+
return;
|
|
156062
|
+
for (const message of this.affectedMessages) {
|
|
156063
|
+
message.parts = message.parts.filter((p) => !this.partsToRemove.has(p));
|
|
156064
|
+
}
|
|
156065
|
+
for (let i = this.messages.length - 1;i >= 0; i -= 1) {
|
|
156066
|
+
if (!this.messages[i].parts.some(hasMeaningfulPart)) {
|
|
156067
|
+
this.messages.splice(i, 1);
|
|
156068
|
+
}
|
|
156069
|
+
}
|
|
156070
|
+
this.partsToRemove.clear();
|
|
156071
|
+
this.affectedMessages.clear();
|
|
156072
|
+
}
|
|
156096
156073
|
}
|
|
156097
156074
|
|
|
156098
156075
|
// ../plugin/src/hooks/magic-context/read-session-chunk.ts
|
|
@@ -156159,23 +156136,47 @@ function getRawSessionMessageCount(sessionId) {
|
|
|
156159
156136
|
}
|
|
156160
156137
|
function getRawSessionTagKeysThrough(sessionId, upToMessageIndex) {
|
|
156161
156138
|
const messages = readRawSessionMessages(sessionId);
|
|
156162
|
-
const
|
|
156139
|
+
const messageFileKeys = new Set;
|
|
156140
|
+
const toolObservations = new Map;
|
|
156141
|
+
const unpairedInvocations = new Map;
|
|
156163
156142
|
for (const message of messages) {
|
|
156164
156143
|
if (message.ordinal > upToMessageIndex)
|
|
156165
156144
|
break;
|
|
156166
156145
|
for (const [partIndex, part] of message.parts.entries()) {
|
|
156167
156146
|
if (isTextPart(part)) {
|
|
156168
|
-
|
|
156147
|
+
messageFileKeys.add(`${message.id}:p${partIndex}`);
|
|
156148
|
+
continue;
|
|
156169
156149
|
}
|
|
156170
156150
|
if (isFilePart(part)) {
|
|
156171
|
-
|
|
156151
|
+
messageFileKeys.add(`${message.id}:file${partIndex}`);
|
|
156152
|
+
continue;
|
|
156172
156153
|
}
|
|
156173
|
-
|
|
156174
|
-
|
|
156154
|
+
const obs = extractToolCallObservation(part);
|
|
156155
|
+
if (!obs)
|
|
156156
|
+
continue;
|
|
156157
|
+
let ownerMsgId;
|
|
156158
|
+
if (obs.kind === "invocation") {
|
|
156159
|
+
ownerMsgId = message.id;
|
|
156160
|
+
const queue = unpairedInvocations.get(obs.callId) ?? [];
|
|
156161
|
+
queue.push(message.id);
|
|
156162
|
+
unpairedInvocations.set(obs.callId, queue);
|
|
156163
|
+
} else {
|
|
156164
|
+
const queue = unpairedInvocations.get(obs.callId);
|
|
156165
|
+
if (queue && queue.length > 0) {
|
|
156166
|
+
const popped = queue.shift();
|
|
156167
|
+
if (queue.length === 0)
|
|
156168
|
+
unpairedInvocations.delete(obs.callId);
|
|
156169
|
+
ownerMsgId = popped ?? message.id;
|
|
156170
|
+
} else {
|
|
156171
|
+
ownerMsgId = message.id;
|
|
156172
|
+
}
|
|
156175
156173
|
}
|
|
156174
|
+
const owners = toolObservations.get(obs.callId) ?? new Set;
|
|
156175
|
+
owners.add(ownerMsgId);
|
|
156176
|
+
toolObservations.set(obs.callId, owners);
|
|
156176
156177
|
}
|
|
156177
156178
|
}
|
|
156178
|
-
return
|
|
156179
|
+
return { messageFileKeys, toolObservations };
|
|
156179
156180
|
}
|
|
156180
156181
|
var PROTECTED_TAIL_USER_TURNS = 5;
|
|
156181
156182
|
function getProtectedTailStartOrdinal(sessionId) {
|
|
@@ -156324,6 +156325,79 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
|
|
|
156324
156325
|
};
|
|
156325
156326
|
}
|
|
156326
156327
|
|
|
156328
|
+
// ../plugin/src/shared/harness.ts
|
|
156329
|
+
var currentHarness = "opencode";
|
|
156330
|
+
var harnessLocked = false;
|
|
156331
|
+
function setHarness(value) {
|
|
156332
|
+
if (harnessLocked && currentHarness !== value) {
|
|
156333
|
+
throw new Error(`Magic Context: harness already locked to "${currentHarness}"; cannot change to "${value}"`);
|
|
156334
|
+
}
|
|
156335
|
+
currentHarness = value;
|
|
156336
|
+
harnessLocked = true;
|
|
156337
|
+
}
|
|
156338
|
+
function getHarness() {
|
|
156339
|
+
return currentHarness;
|
|
156340
|
+
}
|
|
156341
|
+
|
|
156342
|
+
// ../plugin/src/features/magic-context/compression-depth-storage.ts
|
|
156343
|
+
var incrementDepthStatements = new WeakMap;
|
|
156344
|
+
var totalDepthStatements = new WeakMap;
|
|
156345
|
+
var maxDepthStatements = new WeakMap;
|
|
156346
|
+
var clearDepthStatements = new WeakMap;
|
|
156347
|
+
function getIncrementDepthStatement(db) {
|
|
156348
|
+
let stmt = incrementDepthStatements.get(db);
|
|
156349
|
+
if (!stmt) {
|
|
156350
|
+
stmt = db.prepare("INSERT INTO compression_depth (session_id, message_ordinal, depth, harness) VALUES (?, ?, 1, ?) ON CONFLICT(session_id, message_ordinal) DO UPDATE SET depth = depth + 1");
|
|
156351
|
+
incrementDepthStatements.set(db, stmt);
|
|
156352
|
+
}
|
|
156353
|
+
return stmt;
|
|
156354
|
+
}
|
|
156355
|
+
function getTotalDepthStatement(db) {
|
|
156356
|
+
let stmt = totalDepthStatements.get(db);
|
|
156357
|
+
if (!stmt) {
|
|
156358
|
+
stmt = db.prepare("SELECT COALESCE(SUM(depth), 0) AS total_depth FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?");
|
|
156359
|
+
totalDepthStatements.set(db, stmt);
|
|
156360
|
+
}
|
|
156361
|
+
return stmt;
|
|
156362
|
+
}
|
|
156363
|
+
function getClearDepthStatement(db) {
|
|
156364
|
+
let stmt = clearDepthStatements.get(db);
|
|
156365
|
+
if (!stmt) {
|
|
156366
|
+
stmt = db.prepare("DELETE FROM compression_depth WHERE session_id = ?");
|
|
156367
|
+
clearDepthStatements.set(db, stmt);
|
|
156368
|
+
}
|
|
156369
|
+
return stmt;
|
|
156370
|
+
}
|
|
156371
|
+
function incrementCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
|
|
156372
|
+
if (endOrdinal < startOrdinal) {
|
|
156373
|
+
return;
|
|
156374
|
+
}
|
|
156375
|
+
db.transaction(() => {
|
|
156376
|
+
const stmt = getIncrementDepthStatement(db);
|
|
156377
|
+
for (let ordinal = startOrdinal;ordinal <= endOrdinal; ordinal += 1) {
|
|
156378
|
+
stmt.run(sessionId, ordinal, getHarness());
|
|
156379
|
+
}
|
|
156380
|
+
})();
|
|
156381
|
+
}
|
|
156382
|
+
function getAverageCompressionDepth(db, sessionId, startOrdinal, endOrdinal) {
|
|
156383
|
+
if (endOrdinal < startOrdinal) {
|
|
156384
|
+
return 0;
|
|
156385
|
+
}
|
|
156386
|
+
const row = getTotalDepthStatement(db).get(sessionId, startOrdinal, endOrdinal);
|
|
156387
|
+
const totalDepth = typeof row?.total_depth === "number" ? row.total_depth : 0;
|
|
156388
|
+
const messageCount = endOrdinal - startOrdinal + 1;
|
|
156389
|
+
return totalDepth / messageCount;
|
|
156390
|
+
}
|
|
156391
|
+
function clearCompressionDepth(db, sessionId) {
|
|
156392
|
+
getClearDepthStatement(db).run(sessionId);
|
|
156393
|
+
}
|
|
156394
|
+
function clearCompressionDepthRange(db, sessionId, startOrdinal, endOrdinal) {
|
|
156395
|
+
if (endOrdinal < startOrdinal) {
|
|
156396
|
+
return;
|
|
156397
|
+
}
|
|
156398
|
+
db.prepare("DELETE FROM compression_depth WHERE session_id = ? AND message_ordinal BETWEEN ? AND ?").run(sessionId, startOrdinal, endOrdinal);
|
|
156399
|
+
}
|
|
156400
|
+
|
|
156327
156401
|
// ../plugin/src/features/magic-context/message-index.ts
|
|
156328
156402
|
var lastIndexedStatements = new WeakMap;
|
|
156329
156403
|
var insertMessageStatements = new WeakMap;
|
|
@@ -156331,6 +156405,7 @@ var upsertIndexStatements = new WeakMap;
|
|
|
156331
156405
|
var deleteFtsStatements = new WeakMap;
|
|
156332
156406
|
var deleteIndexStatements = new WeakMap;
|
|
156333
156407
|
var countIndexedMessageStatements = new WeakMap;
|
|
156408
|
+
var indexedMessageIdStatements = new WeakMap;
|
|
156334
156409
|
function normalizeIndexText(text) {
|
|
156335
156410
|
return text.replace(/\s+/g, " ").trim();
|
|
156336
156411
|
}
|
|
@@ -156374,10 +156449,34 @@ function getDeleteIndexStatement(db) {
|
|
|
156374
156449
|
}
|
|
156375
156450
|
return stmt;
|
|
156376
156451
|
}
|
|
156452
|
+
function getCountIndexedMessageStatement(db) {
|
|
156453
|
+
let stmt = countIndexedMessageStatements.get(db);
|
|
156454
|
+
if (!stmt) {
|
|
156455
|
+
stmt = db.prepare("SELECT COUNT(*) AS count FROM message_history_fts WHERE session_id = ? AND message_id = ?");
|
|
156456
|
+
countIndexedMessageStatements.set(db, stmt);
|
|
156457
|
+
}
|
|
156458
|
+
return stmt;
|
|
156459
|
+
}
|
|
156460
|
+
function getIndexedMessageIdStatement(db) {
|
|
156461
|
+
let stmt = indexedMessageIdStatements.get(db);
|
|
156462
|
+
if (!stmt) {
|
|
156463
|
+
stmt = db.prepare("SELECT message_id AS messageId FROM message_history_fts WHERE session_id = ?");
|
|
156464
|
+
indexedMessageIdStatements.set(db, stmt);
|
|
156465
|
+
}
|
|
156466
|
+
return stmt;
|
|
156467
|
+
}
|
|
156377
156468
|
function getLastIndexedOrdinal(db, sessionId) {
|
|
156378
156469
|
const row = getLastIndexedStatement(db).get(sessionId);
|
|
156379
156470
|
return typeof row?.last_indexed_ordinal === "number" ? row.last_indexed_ordinal : 0;
|
|
156380
156471
|
}
|
|
156472
|
+
function isMessageAlreadyIndexed(db, sessionId, messageId) {
|
|
156473
|
+
const row = getCountIndexedMessageStatement(db).get(sessionId, messageId);
|
|
156474
|
+
return (typeof row?.count === "number" ? row.count : 0) > 0;
|
|
156475
|
+
}
|
|
156476
|
+
function advanceIndexWatermark(db, sessionId, ordinal, now) {
|
|
156477
|
+
const current = getLastIndexedOrdinal(db, sessionId);
|
|
156478
|
+
getUpsertIndexStatement(db).run(sessionId, Math.max(current, ordinal), now, getHarness());
|
|
156479
|
+
}
|
|
156381
156480
|
function clearIndexedMessages(db, sessionId) {
|
|
156382
156481
|
db.transaction(() => {
|
|
156383
156482
|
getDeleteFtsStatement(db).run(sessionId);
|
|
@@ -156397,39 +156496,510 @@ function getIndexableContent(role, parts) {
|
|
|
156397
156496
|
}
|
|
156398
156497
|
return "";
|
|
156399
156498
|
}
|
|
156400
|
-
function
|
|
156401
|
-
|
|
156402
|
-
|
|
156403
|
-
|
|
156499
|
+
function indexSingleMessageInTransaction(db, sessionId, message, now) {
|
|
156500
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
156501
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
156502
|
+
return false;
|
|
156503
|
+
}
|
|
156504
|
+
const content = getIndexableContent(message.role, message.parts);
|
|
156505
|
+
if (content.length === 0) {
|
|
156506
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
156507
|
+
return false;
|
|
156508
|
+
}
|
|
156509
|
+
if (isMessageAlreadyIndexed(db, sessionId, message.id)) {
|
|
156510
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
156511
|
+
return false;
|
|
156512
|
+
}
|
|
156513
|
+
getInsertMessageStatement(db).run(sessionId, message.ordinal, message.id, message.role, content);
|
|
156514
|
+
advanceIndexWatermark(db, sessionId, message.ordinal, now);
|
|
156515
|
+
return true;
|
|
156516
|
+
}
|
|
156517
|
+
function indexSingleMessage(db, sessionId, message) {
|
|
156518
|
+
return db.transaction(() => indexSingleMessageInTransaction(db, sessionId, message, Date.now()))();
|
|
156519
|
+
}
|
|
156520
|
+
function indexMessagesAfterOrdinal(db, sessionId, messages, lastIndexedOrdinal, finalWatermark = messages.length) {
|
|
156521
|
+
const now = Date.now();
|
|
156522
|
+
let inserted = 0;
|
|
156523
|
+
db.transaction(() => {
|
|
156524
|
+
const existingMessageIds = new Set(getIndexedMessageIdStatement(db).all(sessionId).map((row) => row.messageId).filter((messageId) => typeof messageId === "string"));
|
|
156525
|
+
const insertMessage = getInsertMessageStatement(db);
|
|
156526
|
+
for (const message of messages) {
|
|
156527
|
+
if (message.ordinal <= lastIndexedOrdinal) {
|
|
156528
|
+
continue;
|
|
156529
|
+
}
|
|
156530
|
+
if (message.role !== "user" && message.role !== "assistant") {
|
|
156531
|
+
continue;
|
|
156532
|
+
}
|
|
156533
|
+
const content = getIndexableContent(message.role, message.parts);
|
|
156534
|
+
if (content.length === 0 || existingMessageIds.has(message.id)) {
|
|
156535
|
+
continue;
|
|
156536
|
+
}
|
|
156537
|
+
insertMessage.run(sessionId, message.ordinal, message.id, message.role, content);
|
|
156538
|
+
existingMessageIds.add(message.id);
|
|
156539
|
+
inserted++;
|
|
156540
|
+
}
|
|
156541
|
+
getUpsertIndexStatement(db).run(sessionId, finalWatermark, now, getHarness());
|
|
156542
|
+
})();
|
|
156543
|
+
return inserted;
|
|
156544
|
+
}
|
|
156545
|
+
|
|
156546
|
+
// ../plugin/src/features/magic-context/message-index-async.ts
|
|
156547
|
+
var INCREMENTAL_DEBOUNCE_MS = 100;
|
|
156548
|
+
var reconciledSessions = new Set;
|
|
156549
|
+
var reconciliationScheduledSessions = new Set;
|
|
156550
|
+
var sessionLocks = new Map;
|
|
156551
|
+
var incrementalTimers = new Map;
|
|
156552
|
+
var pendingIncrementalKeys = new Set;
|
|
156553
|
+
function defer(fn) {
|
|
156554
|
+
const immediate = globalThis.setImmediate;
|
|
156555
|
+
if (typeof immediate === "function") {
|
|
156556
|
+
immediate(fn);
|
|
156404
156557
|
return;
|
|
156405
156558
|
}
|
|
156406
|
-
|
|
156407
|
-
|
|
156408
|
-
|
|
156409
|
-
|
|
156559
|
+
setTimeout(fn, 0);
|
|
156560
|
+
}
|
|
156561
|
+
function runWithSessionLock(sessionId, operation) {
|
|
156562
|
+
const previous = sessionLocks.get(sessionId) ?? Promise.resolve();
|
|
156563
|
+
const run = previous.catch(() => {
|
|
156564
|
+
return;
|
|
156565
|
+
}).then(async () => {
|
|
156566
|
+
await operation();
|
|
156567
|
+
});
|
|
156568
|
+
sessionLocks.set(sessionId, run);
|
|
156569
|
+
run.finally(() => {
|
|
156570
|
+
if (sessionLocks.get(sessionId) === run) {
|
|
156571
|
+
sessionLocks.delete(sessionId);
|
|
156572
|
+
}
|
|
156573
|
+
}).catch(() => {
|
|
156574
|
+
return;
|
|
156575
|
+
});
|
|
156576
|
+
return run;
|
|
156577
|
+
}
|
|
156578
|
+
function logIndexingError(sessionId, action, error48) {
|
|
156579
|
+
sessionLog(sessionId, `message FTS async ${action} failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
156580
|
+
log(`[message-index-async] ${action} failed for ${sessionId}:`, error48);
|
|
156581
|
+
}
|
|
156582
|
+
async function reconcileSessionIndex(db, sessionId, readMessages) {
|
|
156583
|
+
await runWithSessionLock(sessionId, () => {
|
|
156584
|
+
if (reconciledSessions.has(sessionId)) {
|
|
156585
|
+
return;
|
|
156586
|
+
}
|
|
156587
|
+
const messages = readMessages(sessionId);
|
|
156588
|
+
if (messages.length === 0) {
|
|
156589
|
+
clearIndexedMessages(db, sessionId);
|
|
156590
|
+
reconciledSessions.add(sessionId);
|
|
156591
|
+
return;
|
|
156592
|
+
}
|
|
156593
|
+
let lastIndexedOrdinal = getLastIndexedOrdinal(db, sessionId);
|
|
156594
|
+
if (lastIndexedOrdinal > messages.length) {
|
|
156595
|
+
clearIndexedMessages(db, sessionId);
|
|
156596
|
+
lastIndexedOrdinal = 0;
|
|
156597
|
+
}
|
|
156598
|
+
const watermark = Math.min(lastIndexedOrdinal, messages.length);
|
|
156599
|
+
indexMessagesAfterOrdinal(db, sessionId, messages, watermark, messages.length);
|
|
156600
|
+
reconciledSessions.add(sessionId);
|
|
156601
|
+
});
|
|
156602
|
+
}
|
|
156603
|
+
function scheduleReconciliation(db, sessionId, readMessages) {
|
|
156604
|
+
if (reconciledSessions.has(sessionId) || reconciliationScheduledSessions.has(sessionId)) {
|
|
156605
|
+
return;
|
|
156410
156606
|
}
|
|
156411
|
-
|
|
156607
|
+
reconciliationScheduledSessions.add(sessionId);
|
|
156608
|
+
defer(() => {
|
|
156609
|
+
reconcileSessionIndex(db, sessionId, readMessages).catch((error48) => {
|
|
156610
|
+
reconciliationScheduledSessions.delete(sessionId);
|
|
156611
|
+
logIndexingError(sessionId, "reconciliation", error48);
|
|
156612
|
+
});
|
|
156613
|
+
});
|
|
156614
|
+
}
|
|
156615
|
+
function scheduleIncrementalIndex(db, sessionId, messageId, readSingleMessage) {
|
|
156616
|
+
const key = `${sessionId}\x00${messageId}`;
|
|
156617
|
+
if (incrementalTimers.has(key) || pendingIncrementalKeys.has(key)) {
|
|
156412
156618
|
return;
|
|
156413
156619
|
}
|
|
156414
|
-
const
|
|
156415
|
-
|
|
156416
|
-
|
|
156417
|
-
|
|
156418
|
-
|
|
156419
|
-
|
|
156620
|
+
const timer = setTimeout(() => {
|
|
156621
|
+
incrementalTimers.delete(key);
|
|
156622
|
+
pendingIncrementalKeys.add(key);
|
|
156623
|
+
runWithSessionLock(sessionId, () => {
|
|
156624
|
+
const message = readSingleMessage(sessionId, messageId);
|
|
156625
|
+
if (!message) {
|
|
156626
|
+
return;
|
|
156627
|
+
}
|
|
156628
|
+
indexSingleMessage(db, sessionId, message);
|
|
156629
|
+
}).catch((error48) => {
|
|
156630
|
+
logIndexingError(sessionId, `incremental index for ${messageId}`, error48);
|
|
156631
|
+
}).finally(() => {
|
|
156632
|
+
pendingIncrementalKeys.delete(key);
|
|
156633
|
+
});
|
|
156634
|
+
}, INCREMENTAL_DEBOUNCE_MS);
|
|
156635
|
+
incrementalTimers.set(key, timer);
|
|
156636
|
+
}
|
|
156637
|
+
function clearSessionTracking(sessionId) {
|
|
156638
|
+
reconciledSessions.delete(sessionId);
|
|
156639
|
+
reconciliationScheduledSessions.delete(sessionId);
|
|
156640
|
+
sessionLocks.delete(sessionId);
|
|
156641
|
+
const prefix = `${sessionId}\x00`;
|
|
156642
|
+
for (const [key, timer] of incrementalTimers) {
|
|
156643
|
+
if (key.startsWith(prefix)) {
|
|
156644
|
+
clearTimeout(timer);
|
|
156645
|
+
incrementalTimers.delete(key);
|
|
156646
|
+
}
|
|
156647
|
+
}
|
|
156648
|
+
for (const key of pendingIncrementalKeys) {
|
|
156649
|
+
if (key.startsWith(prefix)) {
|
|
156650
|
+
pendingIncrementalKeys.delete(key);
|
|
156651
|
+
}
|
|
156652
|
+
}
|
|
156653
|
+
}
|
|
156654
|
+
|
|
156655
|
+
// ../plugin/src/features/magic-context/overflow-detection.ts
|
|
156656
|
+
var OVERFLOW_PATTERNS = [
|
|
156657
|
+
/prompt is too long/i,
|
|
156658
|
+
/input is too long for requested model/i,
|
|
156659
|
+
/exceeds the context window/i,
|
|
156660
|
+
/input token count.*exceeds the maximum/i,
|
|
156661
|
+
/maximum prompt length is \d+/i,
|
|
156662
|
+
/reduce the length of the messages/i,
|
|
156663
|
+
/maximum context length is \d+ tokens/i,
|
|
156664
|
+
/exceeds the limit of \d+/i,
|
|
156665
|
+
/exceeds the available context size/i,
|
|
156666
|
+
/greater than the context length/i,
|
|
156667
|
+
/context window exceeds limit/i,
|
|
156668
|
+
/exceeded model token limit/i,
|
|
156669
|
+
/context[_ ]length[_ ]exceeded/i,
|
|
156670
|
+
/request entity too large/i,
|
|
156671
|
+
/context length is only \d+ tokens/i,
|
|
156672
|
+
/input length.*exceeds.*context length/i,
|
|
156673
|
+
/prompt too long; exceeded (?:max )?context length/i,
|
|
156674
|
+
/too large for model with \d+ maximum context length/i,
|
|
156675
|
+
/model_context_window_exceeded/i,
|
|
156676
|
+
/context size has been exceeded/i
|
|
156677
|
+
];
|
|
156678
|
+
var LIMIT_EXTRACTION_PATTERNS = [
|
|
156679
|
+
/maximum prompt length is (\d+)/i,
|
|
156680
|
+
/maximum context length is (\d+) tokens?/i,
|
|
156681
|
+
/context length is only (\d+) tokens?/i,
|
|
156682
|
+
/exceeds the limit of (\d+)/i,
|
|
156683
|
+
/too large for model with (\d+) maximum context length/i,
|
|
156684
|
+
/context size.*(\d+) tokens?/i,
|
|
156685
|
+
/exceeds? the context length of (\d+)/i,
|
|
156686
|
+
/max(?:imum)?.*context.*?(\d+)/i
|
|
156687
|
+
];
|
|
156688
|
+
var MIN_PLAUSIBLE_LIMIT = 1024;
|
|
156689
|
+
var MAX_PLAUSIBLE_LIMIT = 1e7;
|
|
156690
|
+
function extractErrorMessage(error48) {
|
|
156691
|
+
if (!error48)
|
|
156692
|
+
return "";
|
|
156693
|
+
if (typeof error48 === "string")
|
|
156694
|
+
return error48;
|
|
156695
|
+
if (typeof error48 === "object") {
|
|
156696
|
+
const obj = error48;
|
|
156697
|
+
const nested = obj.error;
|
|
156698
|
+
if (nested && typeof nested.message === "string" && nested.message.length > 0) {
|
|
156699
|
+
return nested.message;
|
|
156700
|
+
}
|
|
156701
|
+
}
|
|
156702
|
+
if (error48 instanceof Error)
|
|
156703
|
+
return error48.message;
|
|
156704
|
+
if (typeof error48 === "object") {
|
|
156705
|
+
const obj = error48;
|
|
156706
|
+
if (typeof obj.message === "string")
|
|
156707
|
+
return obj.message;
|
|
156708
|
+
if (typeof obj.responseBody === "string")
|
|
156709
|
+
return obj.responseBody;
|
|
156710
|
+
try {
|
|
156711
|
+
return JSON.stringify(error48);
|
|
156712
|
+
} catch {
|
|
156713
|
+
return String(error48);
|
|
156714
|
+
}
|
|
156715
|
+
}
|
|
156716
|
+
return String(error48);
|
|
156717
|
+
}
|
|
156718
|
+
function detectOverflow(error48) {
|
|
156719
|
+
const message = extractErrorMessage(error48);
|
|
156720
|
+
if (!message) {
|
|
156721
|
+
return { isOverflow: false };
|
|
156722
|
+
}
|
|
156723
|
+
const hasStatus413 = /\b413\b/.test(message) && /(entity|payload|context|prompt)/i.test(message);
|
|
156724
|
+
let matched;
|
|
156725
|
+
for (const pattern of OVERFLOW_PATTERNS) {
|
|
156726
|
+
if (pattern.test(message)) {
|
|
156727
|
+
matched = pattern;
|
|
156728
|
+
break;
|
|
156729
|
+
}
|
|
156730
|
+
}
|
|
156731
|
+
if (!matched && !hasStatus413) {
|
|
156732
|
+
return { isOverflow: false };
|
|
156733
|
+
}
|
|
156734
|
+
const reportedLimit = parseReportedLimit(message);
|
|
156735
|
+
return {
|
|
156736
|
+
isOverflow: true,
|
|
156737
|
+
reportedLimit,
|
|
156738
|
+
matchedPattern: matched?.source
|
|
156739
|
+
};
|
|
156740
|
+
}
|
|
156741
|
+
function parseReportedLimit(message) {
|
|
156742
|
+
if (!message)
|
|
156743
|
+
return;
|
|
156744
|
+
for (const pattern of LIMIT_EXTRACTION_PATTERNS) {
|
|
156745
|
+
const match = message.match(pattern);
|
|
156746
|
+
if (!match)
|
|
156747
|
+
continue;
|
|
156748
|
+
const raw = match[1];
|
|
156749
|
+
if (!raw)
|
|
156750
|
+
continue;
|
|
156751
|
+
const value = Number.parseInt(raw, 10);
|
|
156752
|
+
if (!Number.isFinite(value))
|
|
156753
|
+
continue;
|
|
156754
|
+
if (value < MIN_PLAUSIBLE_LIMIT || value > MAX_PLAUSIBLE_LIMIT)
|
|
156755
|
+
continue;
|
|
156756
|
+
return value;
|
|
156757
|
+
}
|
|
156758
|
+
return;
|
|
156759
|
+
}
|
|
156760
|
+
|
|
156761
|
+
// ../plugin/src/features/magic-context/compartment-storage.ts
|
|
156762
|
+
var insertCompartmentStatements = new WeakMap;
|
|
156763
|
+
var insertFactStatements = new WeakMap;
|
|
156764
|
+
function getInsertCompartmentStatement(db) {
|
|
156765
|
+
let stmt = insertCompartmentStatements.get(db);
|
|
156766
|
+
if (!stmt) {
|
|
156767
|
+
stmt = db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
156768
|
+
insertCompartmentStatements.set(db, stmt);
|
|
156769
|
+
}
|
|
156770
|
+
return stmt;
|
|
156771
|
+
}
|
|
156772
|
+
function getInsertFactStatement(db) {
|
|
156773
|
+
let stmt = insertFactStatements.get(db);
|
|
156774
|
+
if (!stmt) {
|
|
156775
|
+
stmt = db.prepare("INSERT INTO session_facts (session_id, category, content, created_at, updated_at, harness) VALUES (?, ?, ?, ?, ?, ?)");
|
|
156776
|
+
insertFactStatements.set(db, stmt);
|
|
156777
|
+
}
|
|
156778
|
+
return stmt;
|
|
156779
|
+
}
|
|
156780
|
+
function isCompartmentRow(row) {
|
|
156781
|
+
if (row === null || typeof row !== "object")
|
|
156782
|
+
return false;
|
|
156783
|
+
const candidate = row;
|
|
156784
|
+
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number";
|
|
156785
|
+
}
|
|
156786
|
+
function isSessionFactRow(row) {
|
|
156787
|
+
if (row === null || typeof row !== "object")
|
|
156788
|
+
return false;
|
|
156789
|
+
const candidate = row;
|
|
156790
|
+
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.category === "string" && typeof candidate.content === "string" && typeof candidate.created_at === "number" && typeof candidate.updated_at === "number";
|
|
156791
|
+
}
|
|
156792
|
+
function insertCompartmentRows(db, sessionId, compartments, now) {
|
|
156793
|
+
const stmt = getInsertCompartmentStatement(db);
|
|
156794
|
+
for (const compartment of compartments) {
|
|
156795
|
+
stmt.run(sessionId, compartment.sequence, compartment.startMessage, compartment.endMessage, compartment.startMessageId, compartment.endMessageId, compartment.title, compartment.content, now, getHarness());
|
|
156796
|
+
}
|
|
156797
|
+
}
|
|
156798
|
+
function insertFactRows(db, sessionId, facts, now) {
|
|
156799
|
+
const stmt = getInsertFactStatement(db);
|
|
156800
|
+
for (const fact of facts) {
|
|
156801
|
+
stmt.run(sessionId, fact.category, fact.content, now, now, getHarness());
|
|
156802
|
+
}
|
|
156803
|
+
}
|
|
156804
|
+
function toCompartment(row) {
|
|
156805
|
+
return {
|
|
156806
|
+
id: row.id,
|
|
156807
|
+
sessionId: row.session_id,
|
|
156808
|
+
sequence: row.sequence,
|
|
156809
|
+
startMessage: row.start_message,
|
|
156810
|
+
endMessage: row.end_message,
|
|
156811
|
+
startMessageId: row.start_message_id,
|
|
156812
|
+
endMessageId: row.end_message_id,
|
|
156813
|
+
title: row.title,
|
|
156814
|
+
content: row.content,
|
|
156815
|
+
createdAt: row.created_at
|
|
156816
|
+
};
|
|
156817
|
+
}
|
|
156818
|
+
function toSessionFact(row) {
|
|
156819
|
+
return {
|
|
156820
|
+
id: row.id,
|
|
156821
|
+
sessionId: row.session_id,
|
|
156822
|
+
category: row.category,
|
|
156823
|
+
content: row.content,
|
|
156824
|
+
createdAt: row.created_at,
|
|
156825
|
+
updatedAt: row.updated_at
|
|
156826
|
+
};
|
|
156827
|
+
}
|
|
156828
|
+
function getCompartments(db, sessionId) {
|
|
156829
|
+
const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
|
|
156830
|
+
return rows.map(toCompartment);
|
|
156831
|
+
}
|
|
156832
|
+
function getLastCompartmentEndMessage(db, sessionId) {
|
|
156833
|
+
const row = db.prepare("SELECT MAX(end_message) as max_end FROM compartments WHERE session_id = ?").get(sessionId);
|
|
156834
|
+
return row?.max_end ?? -1;
|
|
156835
|
+
}
|
|
156836
|
+
function appendCompartments(db, sessionId, compartments) {
|
|
156837
|
+
if (compartments.length === 0)
|
|
156838
|
+
return;
|
|
156420
156839
|
const now = Date.now();
|
|
156421
156840
|
db.transaction(() => {
|
|
156422
|
-
|
|
156423
|
-
|
|
156424
|
-
|
|
156841
|
+
insertCompartmentRows(db, sessionId, compartments, now);
|
|
156842
|
+
})();
|
|
156843
|
+
}
|
|
156844
|
+
function replaceSessionFacts(db, sessionId, facts) {
|
|
156845
|
+
const now = Date.now();
|
|
156846
|
+
db.transaction(() => {
|
|
156847
|
+
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
156848
|
+
insertFactRows(db, sessionId, facts, now);
|
|
156849
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
156850
|
+
})();
|
|
156851
|
+
}
|
|
156852
|
+
function getSessionFacts(db, sessionId) {
|
|
156853
|
+
const rows = db.prepare("SELECT * FROM session_facts WHERE session_id = ? ORDER BY category ASC, id ASC").all(sessionId).filter(isSessionFactRow);
|
|
156854
|
+
return rows.map(toSessionFact);
|
|
156855
|
+
}
|
|
156856
|
+
function replaceAllCompartmentState(db, sessionId, compartments, facts) {
|
|
156857
|
+
const now = Date.now();
|
|
156858
|
+
db.transaction(() => {
|
|
156859
|
+
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
156860
|
+
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
156861
|
+
insertCompartmentRows(db, sessionId, compartments, now);
|
|
156862
|
+
insertFactRows(db, sessionId, facts, now);
|
|
156863
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE session_id = ?").run(sessionId);
|
|
156864
|
+
})();
|
|
156865
|
+
}
|
|
156866
|
+
function buildCompartmentBlock(compartments, facts, memoryBlock, dateRanges) {
|
|
156867
|
+
const lines = [];
|
|
156868
|
+
if (memoryBlock) {
|
|
156869
|
+
lines.push(memoryBlock);
|
|
156870
|
+
lines.push("");
|
|
156871
|
+
}
|
|
156872
|
+
for (const c of compartments) {
|
|
156873
|
+
const dates = dateRanges?.byId.get(c.id);
|
|
156874
|
+
const dateAttr = dates ? ` start-date="${dates.start}" end-date="${dates.end}"` : "";
|
|
156875
|
+
lines.push(`<compartment start="${c.startMessage}" end="${c.endMessage}"${dateAttr} title="${escapeXmlAttr(c.title)}">`);
|
|
156876
|
+
lines.push(escapeXmlContent(c.content));
|
|
156877
|
+
lines.push("</compartment>");
|
|
156878
|
+
lines.push("");
|
|
156879
|
+
}
|
|
156880
|
+
const factsByCategory = new Map;
|
|
156881
|
+
for (const f of facts) {
|
|
156882
|
+
const existing = factsByCategory.get(f.category) ?? [];
|
|
156883
|
+
existing.push(f.content);
|
|
156884
|
+
factsByCategory.set(f.category, existing);
|
|
156885
|
+
}
|
|
156886
|
+
for (const [category, items] of factsByCategory) {
|
|
156887
|
+
lines.push(`${category}:`);
|
|
156888
|
+
for (const item of items) {
|
|
156889
|
+
lines.push(`* ${escapeXmlContent(item)}`);
|
|
156890
|
+
}
|
|
156891
|
+
lines.push("");
|
|
156892
|
+
}
|
|
156893
|
+
return lines.join(`
|
|
156894
|
+
`).trimEnd();
|
|
156895
|
+
}
|
|
156896
|
+
function saveRecompStagingPass(db, sessionId, passNumber, compartments, facts) {
|
|
156897
|
+
const now = Date.now();
|
|
156898
|
+
db.transaction(() => {
|
|
156899
|
+
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
156900
|
+
const compartmentStmt = db.prepare("INSERT OR REPLACE INTO recomp_compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, pass_number, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
156901
|
+
for (const c of compartments) {
|
|
156902
|
+
compartmentStmt.run(sessionId, c.sequence, c.startMessage, c.endMessage, c.startMessageId, c.endMessageId, c.title, c.content, passNumber, now, getHarness());
|
|
156903
|
+
}
|
|
156904
|
+
const factStmt = db.prepare("INSERT INTO recomp_facts (session_id, category, content, pass_number, created_at, harness) VALUES (?, ?, ?, ?, ?, ?)");
|
|
156905
|
+
for (const f of facts) {
|
|
156906
|
+
factStmt.run(sessionId, f.category, f.content, passNumber, now, getHarness());
|
|
156425
156907
|
}
|
|
156426
|
-
getUpsertIndexStatement(db).run(sessionId, messages.length, now, getHarness());
|
|
156427
156908
|
})();
|
|
156428
156909
|
}
|
|
156910
|
+
function getRecompStaging(db, sessionId) {
|
|
156911
|
+
const compartmentRows = db.prepare("SELECT * FROM recomp_compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isRecompCompartmentRow);
|
|
156912
|
+
if (compartmentRows.length === 0)
|
|
156913
|
+
return null;
|
|
156914
|
+
const compartments = compartmentRows.map((row) => ({
|
|
156915
|
+
sequence: row.sequence,
|
|
156916
|
+
startMessage: row.start_message,
|
|
156917
|
+
endMessage: row.end_message,
|
|
156918
|
+
startMessageId: row.start_message_id,
|
|
156919
|
+
endMessageId: row.end_message_id,
|
|
156920
|
+
title: row.title,
|
|
156921
|
+
content: row.content
|
|
156922
|
+
}));
|
|
156923
|
+
const factRows = db.prepare("SELECT category, content FROM recomp_facts WHERE session_id = ?").all(sessionId).filter(isRecompFactRow);
|
|
156924
|
+
const maxPass = compartmentRows.reduce((m, r) => Math.max(m, r.pass_number), 0);
|
|
156925
|
+
const lastEnd = compartmentRows[compartmentRows.length - 1]?.end_message ?? 0;
|
|
156926
|
+
return {
|
|
156927
|
+
compartments,
|
|
156928
|
+
facts: factRows,
|
|
156929
|
+
passCount: maxPass,
|
|
156930
|
+
lastEndMessage: lastEnd
|
|
156931
|
+
};
|
|
156932
|
+
}
|
|
156933
|
+
function promoteRecompStaging(db, sessionId) {
|
|
156934
|
+
const now = Date.now();
|
|
156935
|
+
return db.transaction(() => {
|
|
156936
|
+
const staging = getRecompStaging(db, sessionId);
|
|
156937
|
+
if (!staging || staging.compartments.length === 0)
|
|
156938
|
+
return null;
|
|
156939
|
+
db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
|
|
156940
|
+
db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
|
|
156941
|
+
insertCompartmentRows(db, sessionId, staging.compartments, now);
|
|
156942
|
+
insertFactRows(db, sessionId, staging.facts, now);
|
|
156943
|
+
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
156944
|
+
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
156945
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '' WHERE session_id = ?").run(sessionId);
|
|
156946
|
+
return { compartments: staging.compartments, facts: staging.facts };
|
|
156947
|
+
})();
|
|
156948
|
+
}
|
|
156949
|
+
function invalidateAllMemoryBlockCaches(db) {
|
|
156950
|
+
try {
|
|
156951
|
+
db.prepare("UPDATE session_meta SET memory_block_cache = '', memory_block_ids = '' WHERE memory_block_cache != '' OR memory_block_ids != ''").run();
|
|
156952
|
+
} catch {}
|
|
156953
|
+
}
|
|
156954
|
+
function clearRecompStaging(db, sessionId) {
|
|
156955
|
+
db.transaction(() => {
|
|
156956
|
+
db.prepare("DELETE FROM recomp_compartments WHERE session_id = ?").run(sessionId);
|
|
156957
|
+
db.prepare("DELETE FROM recomp_facts WHERE session_id = ?").run(sessionId);
|
|
156958
|
+
try {
|
|
156959
|
+
db.prepare("UPDATE session_meta SET recomp_partial_range_start = 0, recomp_partial_range_end = 0 WHERE session_id = ?").run(sessionId);
|
|
156960
|
+
} catch {}
|
|
156961
|
+
})();
|
|
156962
|
+
}
|
|
156963
|
+
function getRecompPartialRange(db, sessionId) {
|
|
156964
|
+
try {
|
|
156965
|
+
const row = db.prepare("SELECT recomp_partial_range_start AS start, recomp_partial_range_end AS end FROM session_meta WHERE session_id = ?").get(sessionId);
|
|
156966
|
+
const start = typeof row?.start === "number" ? row.start : 0;
|
|
156967
|
+
const end = typeof row?.end === "number" ? row.end : 0;
|
|
156968
|
+
if (start <= 0 || end <= 0)
|
|
156969
|
+
return null;
|
|
156970
|
+
return { start, end };
|
|
156971
|
+
} catch {
|
|
156972
|
+
return null;
|
|
156973
|
+
}
|
|
156974
|
+
}
|
|
156975
|
+
function setRecompPartialRange(db, sessionId, range) {
|
|
156976
|
+
const start = range ? range.start : 0;
|
|
156977
|
+
const end = range ? range.end : 0;
|
|
156978
|
+
db.prepare("INSERT OR IGNORE INTO session_meta (session_id) VALUES (?)").run(sessionId);
|
|
156979
|
+
db.prepare("UPDATE session_meta SET recomp_partial_range_start = ?, recomp_partial_range_end = ? WHERE session_id = ?").run(start, end, sessionId);
|
|
156980
|
+
}
|
|
156981
|
+
function isRecompCompartmentRow(row) {
|
|
156982
|
+
if (row === null || typeof row !== "object")
|
|
156983
|
+
return false;
|
|
156984
|
+
const candidate = row;
|
|
156985
|
+
return typeof candidate.id === "number" && typeof candidate.session_id === "string" && typeof candidate.sequence === "number" && typeof candidate.start_message === "number" && typeof candidate.end_message === "number" && typeof candidate.start_message_id === "string" && typeof candidate.end_message_id === "string" && typeof candidate.title === "string" && typeof candidate.content === "string" && typeof candidate.pass_number === "number" && typeof candidate.created_at === "number";
|
|
156986
|
+
}
|
|
156987
|
+
function isRecompFactRow(row) {
|
|
156988
|
+
if (row === null || typeof row !== "object")
|
|
156989
|
+
return false;
|
|
156990
|
+
const candidate = row;
|
|
156991
|
+
return typeof candidate.category === "string" && typeof candidate.content === "string";
|
|
156992
|
+
}
|
|
156993
|
+
function escapeXmlAttr(s) {
|
|
156994
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">");
|
|
156995
|
+
}
|
|
156996
|
+
function escapeXmlContent(s) {
|
|
156997
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
156998
|
+
}
|
|
156429
156999
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
156430
157000
|
init_data_path();
|
|
156431
|
-
import { copyFileSync, cpSync, existsSync, mkdirSync as
|
|
156432
|
-
import { join as
|
|
157001
|
+
import { copyFileSync, cpSync, existsSync as existsSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
157002
|
+
import { join as join7 } from "node:path";
|
|
156433
157003
|
|
|
156434
157004
|
// ../plugin/src/shared/error-message.ts
|
|
156435
157005
|
function getErrorMessage(error48) {
|
|
@@ -156714,6 +157284,58 @@ var MIGRATIONS = [
|
|
|
156714
157284
|
db.exec("ALTER TABLE notes ADD COLUMN harness TEXT NOT NULL DEFAULT 'opencode'");
|
|
156715
157285
|
}
|
|
156716
157286
|
}
|
|
157287
|
+
},
|
|
157288
|
+
{
|
|
157289
|
+
version: 8,
|
|
157290
|
+
description: "Add partial indexes on tags(session_id, tag_number) for active and dropped",
|
|
157291
|
+
up: (db) => {
|
|
157292
|
+
db.exec(`
|
|
157293
|
+
CREATE INDEX IF NOT EXISTS idx_tags_active_session_tag_number
|
|
157294
|
+
ON tags(session_id, tag_number)
|
|
157295
|
+
WHERE status = 'active';
|
|
157296
|
+
|
|
157297
|
+
CREATE INDEX IF NOT EXISTS idx_tags_dropped_session_tag_number
|
|
157298
|
+
ON tags(session_id, tag_number)
|
|
157299
|
+
WHERE status = 'dropped';
|
|
157300
|
+
`);
|
|
157301
|
+
db.exec("ANALYZE tags;");
|
|
157302
|
+
}
|
|
157303
|
+
},
|
|
157304
|
+
{
|
|
157305
|
+
version: 9,
|
|
157306
|
+
description: "Persist tool_definition_measurements across plugin restarts",
|
|
157307
|
+
up: (db) => {
|
|
157308
|
+
db.exec(`
|
|
157309
|
+
CREATE TABLE IF NOT EXISTS tool_definition_measurements (
|
|
157310
|
+
provider_id TEXT NOT NULL,
|
|
157311
|
+
model_id TEXT NOT NULL,
|
|
157312
|
+
agent_name TEXT NOT NULL,
|
|
157313
|
+
tool_id TEXT NOT NULL,
|
|
157314
|
+
token_count INTEGER NOT NULL,
|
|
157315
|
+
recorded_at INTEGER NOT NULL,
|
|
157316
|
+
PRIMARY KEY (provider_id, model_id, agent_name, tool_id)
|
|
157317
|
+
);
|
|
157318
|
+
`);
|
|
157319
|
+
}
|
|
157320
|
+
},
|
|
157321
|
+
{
|
|
157322
|
+
version: 10,
|
|
157323
|
+
description: "Add tool_owner_message_id column to tags + composite identity indexes",
|
|
157324
|
+
up: (db) => {
|
|
157325
|
+
const cols = db.prepare("PRAGMA table_info(tags)").all();
|
|
157326
|
+
if (!cols.some((c) => c.name === "tool_owner_message_id")) {
|
|
157327
|
+
db.exec("ALTER TABLE tags ADD COLUMN tool_owner_message_id TEXT DEFAULT NULL");
|
|
157328
|
+
}
|
|
157329
|
+
db.exec(`
|
|
157330
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_tags_tool_composite
|
|
157331
|
+
ON tags(session_id, message_id, tool_owner_message_id)
|
|
157332
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NOT NULL;
|
|
157333
|
+
|
|
157334
|
+
CREATE INDEX IF NOT EXISTS idx_tags_tool_null_owner
|
|
157335
|
+
ON tags(session_id, message_id)
|
|
157336
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL;
|
|
157337
|
+
`);
|
|
157338
|
+
}
|
|
156717
157339
|
}
|
|
156718
157340
|
];
|
|
156719
157341
|
function ensureMigrationsTable(db) {
|
|
@@ -156729,22 +157351,51 @@ function getCurrentVersion(db) {
|
|
|
156729
157351
|
const row = db.prepare("SELECT MAX(version) as version FROM schema_migrations").get();
|
|
156730
157352
|
return row?.version ?? 0;
|
|
156731
157353
|
}
|
|
157354
|
+
function isSiblingMigrationConflict(error48, version2) {
|
|
157355
|
+
if (!(error48 instanceof Error))
|
|
157356
|
+
return false;
|
|
157357
|
+
const code = error48.code;
|
|
157358
|
+
if (code !== "SQLITE_CONSTRAINT_PRIMARYKEY" && code !== "SQLITE_CONSTRAINT_UNIQUE") {
|
|
157359
|
+
return false;
|
|
157360
|
+
}
|
|
157361
|
+
const msg = error48.message;
|
|
157362
|
+
if (!msg.includes("schema_migrations"))
|
|
157363
|
+
return false;
|
|
157364
|
+
if (!msg.toLowerCase().includes("version"))
|
|
157365
|
+
return false;
|
|
157366
|
+
return true;
|
|
157367
|
+
}
|
|
156732
157368
|
function runMigrations(db) {
|
|
156733
157369
|
ensureMigrationsTable(db);
|
|
156734
|
-
|
|
156735
|
-
|
|
157370
|
+
let currentVersion = getCurrentVersion(db);
|
|
157371
|
+
let pendingMigrations = MIGRATIONS.filter((m) => m.version > currentVersion);
|
|
156736
157372
|
if (pendingMigrations.length === 0) {
|
|
156737
157373
|
return;
|
|
156738
157374
|
}
|
|
156739
157375
|
log(`[migrations] current schema version: ${currentVersion}, applying ${pendingMigrations.length} migration(s)`);
|
|
156740
|
-
|
|
157376
|
+
let migrationIndex = 0;
|
|
157377
|
+
while (migrationIndex < pendingMigrations.length) {
|
|
157378
|
+
const migration = pendingMigrations[migrationIndex];
|
|
156741
157379
|
try {
|
|
156742
157380
|
db.transaction(() => {
|
|
156743
157381
|
migration.up(db);
|
|
156744
157382
|
db.prepare("INSERT INTO schema_migrations (version, description, applied_at) VALUES (?, ?, ?)").run(migration.version, migration.description, Date.now());
|
|
156745
157383
|
})();
|
|
156746
157384
|
log(`[migrations] applied v${migration.version}: ${migration.description}`);
|
|
157385
|
+
migrationIndex += 1;
|
|
156747
157386
|
} catch (error48) {
|
|
157387
|
+
if (isSiblingMigrationConflict(error48, migration.version)) {
|
|
157388
|
+
log(`[migrations] v${migration.version} already applied by sibling instance — resuming with re-read version`);
|
|
157389
|
+
const reReadVersion = getCurrentVersion(db);
|
|
157390
|
+
if (reReadVersion <= currentVersion) {
|
|
157391
|
+
log(`[migrations] FAILED v${migration.version}: sibling-conflict shape but version not advanced (${reReadVersion} <= ${currentVersion}) — failing closed`);
|
|
157392
|
+
throw new Error(`Migration v${migration.version} failed: sibling conflict reported but version did not advance. Database may need manual repair.`);
|
|
157393
|
+
}
|
|
157394
|
+
currentVersion = reReadVersion;
|
|
157395
|
+
pendingMigrations = MIGRATIONS.filter((m) => m.version > currentVersion);
|
|
157396
|
+
migrationIndex = 0;
|
|
157397
|
+
continue;
|
|
157398
|
+
}
|
|
156748
157399
|
log(`[migrations] FAILED v${migration.version}: ${migration.description} — ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
156749
157400
|
throw new Error(`Migration v${migration.version} failed: ${error48 instanceof Error ? error48.message : String(error48)}. Database may need manual repair.`);
|
|
156750
157401
|
}
|
|
@@ -156752,27 +157403,300 @@ function runMigrations(db) {
|
|
|
156752
157403
|
log(`[migrations] schema version now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
|
|
156753
157404
|
}
|
|
156754
157405
|
|
|
157406
|
+
// ../plugin/src/features/magic-context/tool-definition-tokens.ts
|
|
157407
|
+
var measurements = new Map;
|
|
157408
|
+
var persistenceDb = null;
|
|
157409
|
+
function keyFor(providerID, modelID, agentName) {
|
|
157410
|
+
const agent = agentName && agentName.length > 0 ? agentName : "default";
|
|
157411
|
+
return `${providerID}/${modelID}/${agent}`;
|
|
157412
|
+
}
|
|
157413
|
+
function setDatabase(db) {
|
|
157414
|
+
persistenceDb = db;
|
|
157415
|
+
}
|
|
157416
|
+
function loadToolDefinitionMeasurements(db) {
|
|
157417
|
+
let rows = [];
|
|
157418
|
+
try {
|
|
157419
|
+
rows = db.prepare("SELECT provider_id, model_id, agent_name, tool_id, token_count FROM tool_definition_measurements").all();
|
|
157420
|
+
} catch {
|
|
157421
|
+
return;
|
|
157422
|
+
}
|
|
157423
|
+
for (const row of rows) {
|
|
157424
|
+
const key = keyFor(row.provider_id, row.model_id, row.agent_name);
|
|
157425
|
+
let inner = measurements.get(key);
|
|
157426
|
+
if (!inner) {
|
|
157427
|
+
inner = new Map;
|
|
157428
|
+
measurements.set(key, inner);
|
|
157429
|
+
}
|
|
157430
|
+
inner.set(row.tool_id, row.token_count);
|
|
157431
|
+
}
|
|
157432
|
+
}
|
|
157433
|
+
|
|
157434
|
+
// ../plugin/src/features/magic-context/tool-owner-backfill.ts
|
|
157435
|
+
init_data_path();
|
|
157436
|
+
init_logger();
|
|
157437
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
157438
|
+
import { join as join6 } from "node:path";
|
|
157439
|
+
var LEASE_DURATION_MS = 5 * 60 * 1000;
|
|
157440
|
+
var LEASE_RENEWAL_MS = 60 * 1000;
|
|
157441
|
+
function resolveOpencodeDbPath() {
|
|
157442
|
+
return join6(getDataDir(), "opencode", "opencode.db");
|
|
157443
|
+
}
|
|
157444
|
+
function ensureBackfillStateTable(db) {
|
|
157445
|
+
db.exec(`
|
|
157446
|
+
CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
|
|
157447
|
+
session_id TEXT PRIMARY KEY,
|
|
157448
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'completed', 'skipped')),
|
|
157449
|
+
started_at INTEGER,
|
|
157450
|
+
lease_expires_at INTEGER,
|
|
157451
|
+
completed_at INTEGER,
|
|
157452
|
+
last_error TEXT
|
|
157453
|
+
);
|
|
157454
|
+
CREATE INDEX IF NOT EXISTS idx_tool_owner_backfill_state_status
|
|
157455
|
+
ON tool_owner_backfill_state(status);
|
|
157456
|
+
`);
|
|
157457
|
+
}
|
|
157458
|
+
function runToolOwnerBackfill(db) {
|
|
157459
|
+
const startedAt = performance.now();
|
|
157460
|
+
ensureBackfillStateTable(db);
|
|
157461
|
+
const result = {
|
|
157462
|
+
sessionsProcessed: 0,
|
|
157463
|
+
sessionsSkippedNoOcDb: 0,
|
|
157464
|
+
sessionsSkippedNoMatches: 0,
|
|
157465
|
+
sessionsCompleted: 0,
|
|
157466
|
+
sessionsBlockedByLease: 0,
|
|
157467
|
+
sessionsErrored: 0,
|
|
157468
|
+
rowsUpdated: 0,
|
|
157469
|
+
rowsLeftNull: 0,
|
|
157470
|
+
durationMs: 0
|
|
157471
|
+
};
|
|
157472
|
+
if (!isToolOwnerBackfillNeeded(db)) {
|
|
157473
|
+
result.durationMs = performance.now() - startedAt;
|
|
157474
|
+
return result;
|
|
157475
|
+
}
|
|
157476
|
+
const opencodeDbPath = resolveOpencodeDbPath();
|
|
157477
|
+
if (!existsSync2(opencodeDbPath)) {
|
|
157478
|
+
log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
|
|
157479
|
+
markAllUnbackfilledSessionsSkipped(db);
|
|
157480
|
+
result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
|
|
157481
|
+
result.durationMs = performance.now() - startedAt;
|
|
157482
|
+
return result;
|
|
157483
|
+
}
|
|
157484
|
+
db.exec(`ATTACH '${opencodeDbPath}' AS oc_backfill`);
|
|
157485
|
+
try {
|
|
157486
|
+
backfillToolOwnersInChunks(db, result);
|
|
157487
|
+
} finally {
|
|
157488
|
+
try {
|
|
157489
|
+
db.exec("DETACH DATABASE oc_backfill");
|
|
157490
|
+
} catch (error48) {
|
|
157491
|
+
log(`[backfill] failed to detach oc_backfill database: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
157492
|
+
}
|
|
157493
|
+
}
|
|
157494
|
+
result.durationMs = performance.now() - startedAt;
|
|
157495
|
+
log(`[backfill] sessions=${result.sessionsProcessed} completed=${result.sessionsCompleted} skipped_no_oc=${result.sessionsSkippedNoOcDb} skipped_no_matches=${result.sessionsSkippedNoMatches} blocked_by_lease=${result.sessionsBlockedByLease} errored=${result.sessionsErrored} rows_updated=${result.rowsUpdated} rows_left_null=${result.rowsLeftNull} duration_ms=${Math.round(result.durationMs)}`);
|
|
157496
|
+
return result;
|
|
157497
|
+
}
|
|
157498
|
+
function isToolOwnerBackfillNeeded(db) {
|
|
157499
|
+
ensureBackfillStateTable(db);
|
|
157500
|
+
const row = db.prepare(`SELECT 1 AS hit
|
|
157501
|
+
FROM tags
|
|
157502
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL
|
|
157503
|
+
AND NOT EXISTS (
|
|
157504
|
+
SELECT 1 FROM tool_owner_backfill_state s
|
|
157505
|
+
WHERE s.session_id = tags.session_id
|
|
157506
|
+
AND s.status IN ('completed', 'skipped')
|
|
157507
|
+
)
|
|
157508
|
+
LIMIT 1`).get();
|
|
157509
|
+
return row !== null && row !== undefined;
|
|
157510
|
+
}
|
|
157511
|
+
function markAllUnbackfilledSessionsSkipped(db) {
|
|
157512
|
+
const now = Date.now();
|
|
157513
|
+
db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, started_at, completed_at, last_error)
|
|
157514
|
+
SELECT DISTINCT session_id, 'skipped', NULL, ?, NULL
|
|
157515
|
+
FROM tags
|
|
157516
|
+
WHERE type = 'tool' AND tool_owner_message_id IS NULL
|
|
157517
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
157518
|
+
status = 'skipped',
|
|
157519
|
+
completed_at = excluded.completed_at,
|
|
157520
|
+
last_error = NULL
|
|
157521
|
+
WHERE tool_owner_backfill_state.status NOT IN ('completed', 'running')`).run(now);
|
|
157522
|
+
}
|
|
157523
|
+
function countSessionsByStatus(db, status) {
|
|
157524
|
+
const row = db.prepare("SELECT COUNT(*) AS c FROM tool_owner_backfill_state WHERE status = ?").get(status);
|
|
157525
|
+
return row.c;
|
|
157526
|
+
}
|
|
157527
|
+
function acquireSessionLease(db, sessionId, now) {
|
|
157528
|
+
const expiresAt = now + LEASE_DURATION_MS;
|
|
157529
|
+
const result = db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, started_at, lease_expires_at)
|
|
157530
|
+
VALUES (?, 'running', ?, ?)
|
|
157531
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
157532
|
+
status = 'running',
|
|
157533
|
+
started_at = excluded.started_at,
|
|
157534
|
+
lease_expires_at = excluded.lease_expires_at,
|
|
157535
|
+
last_error = NULL
|
|
157536
|
+
WHERE tool_owner_backfill_state.status IN ('pending', 'skipped')
|
|
157537
|
+
OR (tool_owner_backfill_state.status = 'running'
|
|
157538
|
+
AND tool_owner_backfill_state.lease_expires_at < ?)`).run(sessionId, now, expiresAt, now);
|
|
157539
|
+
return (result.changes ?? 0) === 1;
|
|
157540
|
+
}
|
|
157541
|
+
function renewSessionLease(db, sessionId, now) {
|
|
157542
|
+
const expiresAt = now + LEASE_DURATION_MS;
|
|
157543
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
157544
|
+
SET lease_expires_at = ?
|
|
157545
|
+
WHERE session_id = ? AND status = 'running'`).run(expiresAt, sessionId);
|
|
157546
|
+
}
|
|
157547
|
+
function markSessionCompleted(db, sessionId, now) {
|
|
157548
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
157549
|
+
SET status = 'completed', completed_at = ?, lease_expires_at = NULL, last_error = NULL
|
|
157550
|
+
WHERE session_id = ?`).run(now, sessionId);
|
|
157551
|
+
}
|
|
157552
|
+
function markSessionSkipped(db, sessionId, now, reason) {
|
|
157553
|
+
db.prepare(`INSERT INTO tool_owner_backfill_state(session_id, status, completed_at, last_error)
|
|
157554
|
+
VALUES (?, 'skipped', ?, ?)
|
|
157555
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
157556
|
+
status = 'skipped',
|
|
157557
|
+
completed_at = excluded.completed_at,
|
|
157558
|
+
last_error = excluded.last_error,
|
|
157559
|
+
lease_expires_at = NULL`).run(sessionId, now, reason);
|
|
157560
|
+
}
|
|
157561
|
+
function markSessionErrored(db, sessionId, error48) {
|
|
157562
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
157563
|
+
db.prepare(`UPDATE tool_owner_backfill_state
|
|
157564
|
+
SET last_error = ?, lease_expires_at = NULL
|
|
157565
|
+
WHERE session_id = ?`).run(message, sessionId);
|
|
157566
|
+
}
|
|
157567
|
+
function getSessionsNeedingBackfill(db) {
|
|
157568
|
+
const rows = db.prepare(`SELECT DISTINCT t.session_id
|
|
157569
|
+
FROM tags t
|
|
157570
|
+
LEFT JOIN tool_owner_backfill_state s ON s.session_id = t.session_id
|
|
157571
|
+
WHERE t.type = 'tool' AND t.tool_owner_message_id IS NULL
|
|
157572
|
+
AND (s.status IS NULL OR s.status NOT IN ('completed', 'skipped'))
|
|
157573
|
+
ORDER BY t.session_id ASC`).all();
|
|
157574
|
+
return rows.map((r) => r.session_id);
|
|
157575
|
+
}
|
|
157576
|
+
function buildSessionOwnerMap(db, sessionId) {
|
|
157577
|
+
const rows = db.prepare(`SELECT
|
|
157578
|
+
COALESCE(
|
|
157579
|
+
CASE WHEN json_extract(p.data, '$.type') = 'tool_use'
|
|
157580
|
+
THEN json_extract(p.data, '$.id')
|
|
157581
|
+
END,
|
|
157582
|
+
json_extract(p.data, '$.callID')
|
|
157583
|
+
) AS callid,
|
|
157584
|
+
m.id AS owner_id,
|
|
157585
|
+
m.time_created AS owner_t_created,
|
|
157586
|
+
p.id AS part_id,
|
|
157587
|
+
p.time_created AS part_t_created
|
|
157588
|
+
FROM oc_backfill.message m
|
|
157589
|
+
INNER JOIN oc_backfill.part p ON p.message_id = m.id
|
|
157590
|
+
WHERE m.session_id = ?
|
|
157591
|
+
AND json_extract(m.data, '$.role') = 'assistant'
|
|
157592
|
+
AND (
|
|
157593
|
+
(json_extract(p.data, '$.type') IN ('tool', 'tool-invocation')
|
|
157594
|
+
AND json_extract(p.data, '$.callID') IS NOT NULL)
|
|
157595
|
+
OR (json_extract(p.data, '$.type') = 'tool_use'
|
|
157596
|
+
AND json_extract(p.data, '$.id') IS NOT NULL)
|
|
157597
|
+
)
|
|
157598
|
+
ORDER BY
|
|
157599
|
+
m.time_created ASC,
|
|
157600
|
+
m.id ASC,
|
|
157601
|
+
p.time_created ASC,
|
|
157602
|
+
p.id ASC`).all(sessionId);
|
|
157603
|
+
const oldestByCallId = new Map;
|
|
157604
|
+
for (const r of rows) {
|
|
157605
|
+
if (typeof r.callid !== "string" || r.callid.length === 0)
|
|
157606
|
+
continue;
|
|
157607
|
+
if (!oldestByCallId.has(r.callid)) {
|
|
157608
|
+
oldestByCallId.set(r.callid, r.owner_id);
|
|
157609
|
+
}
|
|
157610
|
+
}
|
|
157611
|
+
return oldestByCallId;
|
|
157612
|
+
}
|
|
157613
|
+
function applyOwnersForSession(db, sessionId, ownersByCallId) {
|
|
157614
|
+
if (ownersByCallId.size === 0) {
|
|
157615
|
+
const leftNull = db.prepare(`SELECT COUNT(*) AS c FROM tags
|
|
157616
|
+
WHERE session_id = ? AND type = 'tool'
|
|
157617
|
+
AND tool_owner_message_id IS NULL`).get(sessionId).c;
|
|
157618
|
+
return { rowsUpdated: 0, rowsLeftNull: leftNull };
|
|
157619
|
+
}
|
|
157620
|
+
const findOrphanStmt = db.prepare(`SELECT id FROM tags
|
|
157621
|
+
WHERE session_id = ? AND message_id = ? AND type = 'tool'
|
|
157622
|
+
AND tool_owner_message_id IS NULL
|
|
157623
|
+
ORDER BY tag_number ASC
|
|
157624
|
+
LIMIT 1`);
|
|
157625
|
+
const updateRowStmt = db.prepare(`UPDATE tags
|
|
157626
|
+
SET tool_owner_message_id = ?
|
|
157627
|
+
WHERE id = ? AND tool_owner_message_id IS NULL`);
|
|
157628
|
+
let rowsUpdated = 0;
|
|
157629
|
+
db.transaction(() => {
|
|
157630
|
+
for (const [callId, ownerId] of ownersByCallId) {
|
|
157631
|
+
const orphan = findOrphanStmt.get(sessionId, callId);
|
|
157632
|
+
if (!orphan)
|
|
157633
|
+
continue;
|
|
157634
|
+
const result = updateRowStmt.run(ownerId, orphan.id);
|
|
157635
|
+
rowsUpdated += result.changes ?? 0;
|
|
157636
|
+
}
|
|
157637
|
+
})();
|
|
157638
|
+
const rowsLeftNull = db.prepare(`SELECT COUNT(*) AS c FROM tags
|
|
157639
|
+
WHERE session_id = ? AND type = 'tool'
|
|
157640
|
+
AND tool_owner_message_id IS NULL`).get(sessionId).c;
|
|
157641
|
+
return { rowsUpdated, rowsLeftNull };
|
|
157642
|
+
}
|
|
157643
|
+
function backfillToolOwnersInChunks(db, result) {
|
|
157644
|
+
const sessionIds = getSessionsNeedingBackfill(db);
|
|
157645
|
+
let lastRenewedAt = Date.now();
|
|
157646
|
+
for (const sessionId of sessionIds) {
|
|
157647
|
+
const now = Date.now();
|
|
157648
|
+
result.sessionsProcessed += 1;
|
|
157649
|
+
const acquired = acquireSessionLease(db, sessionId, now);
|
|
157650
|
+
if (!acquired) {
|
|
157651
|
+
result.sessionsBlockedByLease += 1;
|
|
157652
|
+
continue;
|
|
157653
|
+
}
|
|
157654
|
+
try {
|
|
157655
|
+
const owners = buildSessionOwnerMap(db, sessionId);
|
|
157656
|
+
const { rowsUpdated, rowsLeftNull } = applyOwnersForSession(db, sessionId, owners);
|
|
157657
|
+
result.rowsUpdated += rowsUpdated;
|
|
157658
|
+
result.rowsLeftNull += rowsLeftNull;
|
|
157659
|
+
if (owners.size === 0) {
|
|
157660
|
+
markSessionSkipped(db, sessionId, Date.now(), "no_oc_matches");
|
|
157661
|
+
result.sessionsSkippedNoMatches += 1;
|
|
157662
|
+
} else {
|
|
157663
|
+
markSessionCompleted(db, sessionId, Date.now());
|
|
157664
|
+
result.sessionsCompleted += 1;
|
|
157665
|
+
}
|
|
157666
|
+
} catch (error48) {
|
|
157667
|
+
log(`[backfill] session=${sessionId} errored: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
157668
|
+
markSessionErrored(db, sessionId, error48);
|
|
157669
|
+
result.sessionsErrored += 1;
|
|
157670
|
+
}
|
|
157671
|
+
const sinceRenew = Date.now() - lastRenewedAt;
|
|
157672
|
+
if (sinceRenew > LEASE_RENEWAL_MS) {
|
|
157673
|
+
renewSessionLease(db, sessionId, Date.now());
|
|
157674
|
+
lastRenewedAt = Date.now();
|
|
157675
|
+
}
|
|
157676
|
+
}
|
|
157677
|
+
}
|
|
157678
|
+
|
|
156755
157679
|
// ../plugin/src/features/magic-context/storage-db.ts
|
|
156756
157680
|
var databases = new Map;
|
|
156757
157681
|
var persistenceByDatabase = new WeakMap;
|
|
156758
157682
|
var persistenceErrorByDatabase = new WeakMap;
|
|
156759
157683
|
function resolveDatabasePath() {
|
|
156760
157684
|
const dbDir = getMagicContextStorageDir();
|
|
156761
|
-
return { dbDir, dbPath:
|
|
157685
|
+
return { dbDir, dbPath: join7(dbDir, "context.db") };
|
|
156762
157686
|
}
|
|
156763
157687
|
function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
156764
|
-
if (
|
|
157688
|
+
if (existsSync3(targetDbPath))
|
|
156765
157689
|
return;
|
|
156766
157690
|
const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
|
|
156767
|
-
const legacyDbPath =
|
|
156768
|
-
if (!
|
|
157691
|
+
const legacyDbPath = join7(legacyDir, "context.db");
|
|
157692
|
+
if (!existsSync3(legacyDbPath))
|
|
156769
157693
|
return;
|
|
156770
157694
|
log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
|
|
156771
|
-
|
|
157695
|
+
mkdirSync3(targetDbDir, { recursive: true });
|
|
156772
157696
|
for (const suffix of ["", "-wal", "-shm"]) {
|
|
156773
157697
|
const src = `${legacyDbPath}${suffix}`;
|
|
156774
|
-
const dst =
|
|
156775
|
-
if (
|
|
157698
|
+
const dst = join7(targetDbDir, `context.db${suffix}`);
|
|
157699
|
+
if (existsSync3(src)) {
|
|
156776
157700
|
try {
|
|
156777
157701
|
copyFileSync(src, dst);
|
|
156778
157702
|
} catch (error48) {
|
|
@@ -156780,9 +157704,9 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
|
|
|
156780
157704
|
}
|
|
156781
157705
|
}
|
|
156782
157706
|
}
|
|
156783
|
-
const legacyModelsDir =
|
|
156784
|
-
const targetModelsDir =
|
|
156785
|
-
if (
|
|
157707
|
+
const legacyModelsDir = join7(legacyDir, "models");
|
|
157708
|
+
const targetModelsDir = join7(targetDbDir, "models");
|
|
157709
|
+
if (existsSync3(legacyModelsDir) && !existsSync3(targetModelsDir)) {
|
|
156786
157710
|
try {
|
|
156787
157711
|
cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
|
|
156788
157712
|
} catch (error48) {
|
|
@@ -157068,6 +157992,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
157068
157992
|
ensureColumn(db, "tags", "tool_name", "TEXT");
|
|
157069
157993
|
ensureColumn(db, "tags", "input_byte_size", "INTEGER DEFAULT 0");
|
|
157070
157994
|
ensureColumn(db, "tags", "caveman_depth", "INTEGER DEFAULT 0");
|
|
157995
|
+
ensureColumn(db, "tags", "tool_owner_message_id", "TEXT DEFAULT NULL");
|
|
157071
157996
|
ensureColumn(db, "session_meta", "system_prompt_tokens", "INTEGER DEFAULT 0");
|
|
157072
157997
|
ensureColumn(db, "session_meta", "compaction_marker_state", "TEXT DEFAULT ''");
|
|
157073
157998
|
ensureColumn(db, "session_meta", "key_files", "TEXT DEFAULT ''");
|
|
@@ -157162,10 +158087,17 @@ function openDatabase() {
|
|
|
157162
158087
|
}
|
|
157163
158088
|
try {
|
|
157164
158089
|
migrateLegacyStorageIfNeeded(dbPath, dbDir);
|
|
157165
|
-
|
|
158090
|
+
mkdirSync3(dbDir, { recursive: true });
|
|
157166
158091
|
const db = new Database(dbPath);
|
|
157167
158092
|
initializeDatabase(db);
|
|
157168
158093
|
runMigrations(db);
|
|
158094
|
+
try {
|
|
158095
|
+
runToolOwnerBackfill(db);
|
|
158096
|
+
} catch (error48) {
|
|
158097
|
+
log(`[magic-context] tool-owner backfill failed (continuing with lazy adoption fallback): ${getErrorMessage(error48)}`);
|
|
158098
|
+
}
|
|
158099
|
+
setDatabase(db);
|
|
158100
|
+
loadToolDefinitionMeasurements(db);
|
|
157169
158101
|
databases.set(dbPath, db);
|
|
157170
158102
|
persistenceByDatabase.set(db, true);
|
|
157171
158103
|
persistenceErrorByDatabase.delete(db);
|
|
@@ -157773,7 +158705,7 @@ var getTagNumberByMessageIdStatements = new WeakMap;
|
|
|
157773
158705
|
function getInsertTagStatement(db) {
|
|
157774
158706
|
let stmt = insertTagStatements.get(db);
|
|
157775
158707
|
if (!stmt) {
|
|
157776
|
-
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
158708
|
+
stmt = db.prepare("INSERT INTO tags (session_id, message_id, type, byte_size, reasoning_byte_size, tag_number, tool_name, input_byte_size, harness, tool_owner_message_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
157777
158709
|
insertTagStatements.set(db, stmt);
|
|
157778
158710
|
}
|
|
157779
158711
|
return stmt;
|
|
@@ -157854,7 +158786,8 @@ function toTagEntry(row) {
|
|
|
157854
158786
|
byteSize: row.byte_size,
|
|
157855
158787
|
reasoningByteSize: row.reasoning_byte_size ?? 0,
|
|
157856
158788
|
sessionId: row.session_id,
|
|
157857
|
-
cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0
|
|
158789
|
+
cavemanDepth: typeof row.caveman_depth === "number" && Number.isFinite(row.caveman_depth) ? row.caveman_depth : 0,
|
|
158790
|
+
toolOwnerMessageId: typeof row.tool_owner_message_id === "string" ? row.tool_owner_message_id : null
|
|
157858
158791
|
};
|
|
157859
158792
|
}
|
|
157860
158793
|
function isTagNumberRow(row) {
|
|
@@ -157869,8 +158802,8 @@ function isMaxTagNumberRow(row) {
|
|
|
157869
158802
|
const r = row;
|
|
157870
158803
|
return typeof r.max_tag_number === "number";
|
|
157871
158804
|
}
|
|
157872
|
-
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0) {
|
|
157873
|
-
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness());
|
|
158805
|
+
function insertTag(db, sessionId, messageId, type, byteSize2, tagNumber, reasoningByteSize = 0, toolName = null, inputByteSize = 0, toolOwnerMessageId = null) {
|
|
158806
|
+
getInsertTagStatement(db).run(sessionId, messageId, type, byteSize2, reasoningByteSize, tagNumber, toolName, inputByteSize, getHarness(), toolOwnerMessageId);
|
|
157874
158807
|
return tagNumber;
|
|
157875
158808
|
}
|
|
157876
158809
|
function updateTagStatus(db, sessionId, tagId, status) {
|
|
@@ -157882,6 +158815,7 @@ function updateTagDropMode(db, sessionId, tagNumber, dropMode) {
|
|
|
157882
158815
|
function updateCavemanDepth(db, sessionId, tagNumber, depth) {
|
|
157883
158816
|
db.prepare("UPDATE tags SET caveman_depth = ? WHERE session_id = ? AND tag_number = ?").run(depth, sessionId, tagNumber);
|
|
157884
158817
|
}
|
|
158818
|
+
var getOwnerScopedToolTagNumbersStatements = new WeakMap;
|
|
157885
158819
|
function getMaxTagNumberBySession(db, sessionId) {
|
|
157886
158820
|
const row = getMaxTagNumberBySessionStatement(db).get(sessionId);
|
|
157887
158821
|
return isMaxTagNumberRow(row) ? row.max_tag_number : 0;
|
|
@@ -157890,17 +158824,103 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
|
|
|
157890
158824
|
const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
|
|
157891
158825
|
return isTagNumberRow(row) ? row.tag_number : null;
|
|
157892
158826
|
}
|
|
158827
|
+
var TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id";
|
|
157893
158828
|
function getTagsBySession(db, sessionId) {
|
|
157894
|
-
const rows = db.prepare(
|
|
158829
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
|
|
158830
|
+
return rows.map(toTagEntry);
|
|
158831
|
+
}
|
|
158832
|
+
var getActiveTagsBySessionStatements = new WeakMap;
|
|
158833
|
+
var getMaxDroppedTagNumberStatements = new WeakMap;
|
|
158834
|
+
function getActiveTagsBySessionStatement(db) {
|
|
158835
|
+
let stmt = getActiveTagsBySessionStatements.get(db);
|
|
158836
|
+
if (!stmt) {
|
|
158837
|
+
stmt = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY tag_number ASC, id ASC`);
|
|
158838
|
+
getActiveTagsBySessionStatements.set(db, stmt);
|
|
158839
|
+
}
|
|
158840
|
+
return stmt;
|
|
158841
|
+
}
|
|
158842
|
+
function getActiveTagsBySession(db, sessionId) {
|
|
158843
|
+
const rows = getActiveTagsBySessionStatement(db).all(sessionId).filter(isTagRow);
|
|
158844
|
+
return rows.map(toTagEntry);
|
|
158845
|
+
}
|
|
158846
|
+
function getTagsByNumbers(db, sessionId, tagNumbers) {
|
|
158847
|
+
if (tagNumbers.length === 0)
|
|
158848
|
+
return [];
|
|
158849
|
+
if (tagNumbers.length > 900) {
|
|
158850
|
+
const all = [];
|
|
158851
|
+
for (let i = 0;i < tagNumbers.length; i += 900) {
|
|
158852
|
+
all.push(...getTagsByNumbers(db, sessionId, tagNumbers.slice(i, i + 900)));
|
|
158853
|
+
}
|
|
158854
|
+
return all;
|
|
158855
|
+
}
|
|
158856
|
+
const placeholders = tagNumbers.map(() => "?").join(",");
|
|
158857
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND tag_number IN (${placeholders}) ORDER BY tag_number ASC, id ASC`).all(sessionId, ...tagNumbers).filter(isTagRow);
|
|
157895
158858
|
return rows.map(toTagEntry);
|
|
157896
158859
|
}
|
|
157897
158860
|
function getTopNBySize(db, sessionId, n) {
|
|
157898
158861
|
if (n <= 0) {
|
|
157899
158862
|
return [];
|
|
157900
158863
|
}
|
|
157901
|
-
const rows = db.prepare(
|
|
158864
|
+
const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? AND status = 'active' ORDER BY byte_size DESC, tag_number ASC LIMIT ?`).all(sessionId, n).filter(isTagRow);
|
|
157902
158865
|
return rows.map(toTagEntry);
|
|
157903
158866
|
}
|
|
158867
|
+
var getToolTagNumberByOwnerStatements = new WeakMap;
|
|
158868
|
+
var getNullOwnerToolTagStatements = new WeakMap;
|
|
158869
|
+
var adoptNullOwnerToolTagStatements = new WeakMap;
|
|
158870
|
+
var deleteToolTagsByOwnerStatements = new WeakMap;
|
|
158871
|
+
function getGetToolTagNumberByOwnerStatement(db) {
|
|
158872
|
+
let stmt = getToolTagNumberByOwnerStatements.get(db);
|
|
158873
|
+
if (!stmt) {
|
|
158874
|
+
stmt = db.prepare(`SELECT tag_number FROM tags
|
|
158875
|
+
WHERE session_id = ? AND message_id = ?
|
|
158876
|
+
AND type = 'tool' AND tool_owner_message_id = ?
|
|
158877
|
+
LIMIT 1`);
|
|
158878
|
+
getToolTagNumberByOwnerStatements.set(db, stmt);
|
|
158879
|
+
}
|
|
158880
|
+
return stmt;
|
|
158881
|
+
}
|
|
158882
|
+
function getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId) {
|
|
158883
|
+
const row = getGetToolTagNumberByOwnerStatement(db).get(sessionId, callId, ownerMsgId);
|
|
158884
|
+
return isTagNumberRow(row) ? row.tag_number : null;
|
|
158885
|
+
}
|
|
158886
|
+
function isNullOwnerToolTagRow(row) {
|
|
158887
|
+
if (row === null || typeof row !== "object")
|
|
158888
|
+
return false;
|
|
158889
|
+
const r = row;
|
|
158890
|
+
return typeof r.id === "number" && typeof r.tag_number === "number";
|
|
158891
|
+
}
|
|
158892
|
+
function getGetNullOwnerToolTagStatement(db) {
|
|
158893
|
+
let stmt = getNullOwnerToolTagStatements.get(db);
|
|
158894
|
+
if (!stmt) {
|
|
158895
|
+
stmt = db.prepare(`SELECT id, tag_number FROM tags
|
|
158896
|
+
WHERE session_id = ? AND message_id = ?
|
|
158897
|
+
AND type = 'tool' AND tool_owner_message_id IS NULL
|
|
158898
|
+
ORDER BY tag_number ASC
|
|
158899
|
+
LIMIT 1`);
|
|
158900
|
+
getNullOwnerToolTagStatements.set(db, stmt);
|
|
158901
|
+
}
|
|
158902
|
+
return stmt;
|
|
158903
|
+
}
|
|
158904
|
+
function getNullOwnerToolTag(db, sessionId, callId) {
|
|
158905
|
+
const row = getGetNullOwnerToolTagStatement(db).get(sessionId, callId);
|
|
158906
|
+
if (!isNullOwnerToolTagRow(row))
|
|
158907
|
+
return null;
|
|
158908
|
+
return { id: row.id, tagNumber: row.tag_number };
|
|
158909
|
+
}
|
|
158910
|
+
function getAdoptNullOwnerToolTagStatement(db) {
|
|
158911
|
+
let stmt = adoptNullOwnerToolTagStatements.get(db);
|
|
158912
|
+
if (!stmt) {
|
|
158913
|
+
stmt = db.prepare(`UPDATE tags
|
|
158914
|
+
SET tool_owner_message_id = ?
|
|
158915
|
+
WHERE id = ? AND tool_owner_message_id IS NULL`);
|
|
158916
|
+
adoptNullOwnerToolTagStatements.set(db, stmt);
|
|
158917
|
+
}
|
|
158918
|
+
return stmt;
|
|
158919
|
+
}
|
|
158920
|
+
function adoptNullOwnerToolTag(db, rowId, ownerMsgId) {
|
|
158921
|
+
const result = getAdoptNullOwnerToolTagStatement(db).run(ownerMsgId, rowId);
|
|
158922
|
+
return (result.changes ?? 0) === 1;
|
|
158923
|
+
}
|
|
157904
158924
|
// ../plugin/src/agents/historian.ts
|
|
157905
158925
|
var HISTORIAN_AGENT = "historian";
|
|
157906
158926
|
var HISTORIAN_EDITOR_AGENT = "historian-editor";
|
|
@@ -157958,11 +158978,12 @@ function expandFallbackChain(chain) {
|
|
|
157958
158978
|
init_data_path();
|
|
157959
158979
|
init_logger();
|
|
157960
158980
|
import { createHash as createHash3 } from "node:crypto";
|
|
157961
|
-
import { existsSync as
|
|
158981
|
+
import { existsSync as existsSync4, readFileSync } from "node:fs";
|
|
157962
158982
|
import { homedir as homedir2, platform } from "node:os";
|
|
157963
|
-
import { join as
|
|
158983
|
+
import { join as join8 } from "node:path";
|
|
157964
158984
|
var RELOAD_INTERVAL_MS = 5 * 60 * 1000;
|
|
157965
158985
|
var apiCache = null;
|
|
158986
|
+
var recentlySeenApiSizes = new Set;
|
|
157966
158987
|
var fileCache = null;
|
|
157967
158988
|
var fileLastAttempt = 0;
|
|
157968
158989
|
function hashFast(input) {
|
|
@@ -157975,16 +158996,16 @@ function getModelsJsonPath() {
|
|
|
157975
158996
|
const cacheBase = getCacheDir();
|
|
157976
158997
|
const source = process.env.OPENCODE_MODELS_URL?.trim();
|
|
157977
158998
|
const filename = source && source !== "https://models.dev" ? `models-${hashFast(source)}.json` : "models.json";
|
|
157978
|
-
return
|
|
158999
|
+
return join8(cacheBase, "opencode", filename);
|
|
157979
159000
|
}
|
|
157980
159001
|
function getOpencodeConfigPath() {
|
|
157981
159002
|
const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
|
|
157982
|
-
const configDir = envDir ? envDir : platform() === "win32" ?
|
|
157983
|
-
const jsonc =
|
|
157984
|
-
if (
|
|
159003
|
+
const configDir = envDir ? envDir : platform() === "win32" ? join8(homedir2(), ".config", "opencode") : join8(process.env.XDG_CONFIG_HOME || join8(homedir2(), ".config"), "opencode");
|
|
159004
|
+
const jsonc = join8(configDir, "opencode.jsonc");
|
|
159005
|
+
if (existsSync4(jsonc))
|
|
157985
159006
|
return jsonc;
|
|
157986
|
-
const json2 =
|
|
157987
|
-
if (
|
|
159007
|
+
const json2 = join8(configDir, "opencode.json");
|
|
159008
|
+
if (existsSync4(json2))
|
|
157988
159009
|
return json2;
|
|
157989
159010
|
return null;
|
|
157990
159011
|
}
|
|
@@ -157997,23 +159018,12 @@ function resolveLimit(limit) {
|
|
|
157997
159018
|
return limit.context;
|
|
157998
159019
|
return;
|
|
157999
159020
|
}
|
|
158000
|
-
function resolveInterleavedField(interleaved) {
|
|
158001
|
-
if (interleaved && typeof interleaved === "object" && typeof interleaved.field === "string" && interleaved.field.length > 0) {
|
|
158002
|
-
return interleaved.field;
|
|
158003
|
-
}
|
|
158004
|
-
return;
|
|
158005
|
-
}
|
|
158006
159021
|
function setCachedModelMetadata(cache, key, model) {
|
|
158007
159022
|
const limit = resolveLimit(model?.limit);
|
|
158008
|
-
|
|
158009
|
-
if (limit === undefined && interleavedField === undefined) {
|
|
159023
|
+
if (limit === undefined) {
|
|
158010
159024
|
return;
|
|
158011
159025
|
}
|
|
158012
|
-
const value = {};
|
|
158013
|
-
if (limit !== undefined)
|
|
158014
|
-
value.limit = limit;
|
|
158015
|
-
if (interleavedField !== undefined)
|
|
158016
|
-
value.interleavedField = interleavedField;
|
|
159026
|
+
const value = { limit };
|
|
158017
159027
|
cache.set(key, value);
|
|
158018
159028
|
const modes = model?.experimental?.modes;
|
|
158019
159029
|
if (modes && typeof modes === "object") {
|
|
@@ -158027,7 +159037,7 @@ function loadModelsDevMetadataFromFile() {
|
|
|
158027
159037
|
const modelsJsonPath = getModelsJsonPath();
|
|
158028
159038
|
let fileFound = false;
|
|
158029
159039
|
try {
|
|
158030
|
-
if (
|
|
159040
|
+
if (existsSync4(modelsJsonPath)) {
|
|
158031
159041
|
fileFound = true;
|
|
158032
159042
|
const raw = readFileSync(modelsJsonPath, "utf-8");
|
|
158033
159043
|
const data = JSON.parse(raw);
|
|
@@ -158044,7 +159054,7 @@ function loadModelsDevMetadataFromFile() {
|
|
|
158044
159054
|
}
|
|
158045
159055
|
try {
|
|
158046
159056
|
const configPath = getOpencodeConfigPath();
|
|
158047
|
-
if (configPath &&
|
|
159057
|
+
if (configPath && existsSync4(configPath)) {
|
|
158048
159058
|
let raw = readFileSync(configPath, "utf-8");
|
|
158049
159059
|
raw = raw.replace(/"(?:[^"\\]|\\.)*"|\/\/.*$/gm, (match) => match.startsWith('"') ? match : "");
|
|
158050
159060
|
const config2 = JSON.parse(raw);
|
|
@@ -158078,22 +159088,6 @@ function getModelsDevContextLimit(providerID, modelID) {
|
|
|
158078
159088
|
}
|
|
158079
159089
|
return fileCache.get(key)?.limit;
|
|
158080
159090
|
}
|
|
158081
|
-
function getModelsDevInterleavedField(providerID, modelID) {
|
|
158082
|
-
const key = `${providerID}/${modelID}`;
|
|
158083
|
-
if (apiCache) {
|
|
158084
|
-
const fromApi = apiCache.get(key)?.interleavedField;
|
|
158085
|
-
if (typeof fromApi === "string" && fromApi.length > 0) {
|
|
158086
|
-
return fromApi;
|
|
158087
|
-
}
|
|
158088
|
-
}
|
|
158089
|
-
const now = Date.now();
|
|
158090
|
-
if (!fileCache || now - fileLastAttempt > RELOAD_INTERVAL_MS) {
|
|
158091
|
-
fileLastAttempt = now;
|
|
158092
|
-
fileCache = loadModelsDevMetadataFromFile();
|
|
158093
|
-
}
|
|
158094
|
-
const fromFile = fileCache.get(key)?.interleavedField;
|
|
158095
|
-
return typeof fromFile === "string" && fromFile.length > 0 ? fromFile : undefined;
|
|
158096
|
-
}
|
|
158097
159091
|
|
|
158098
159092
|
// ../plugin/src/hooks/magic-context/derive-budgets.ts
|
|
158099
159093
|
var TRIGGER_BUDGET_PERCENTAGE = 0.05;
|
|
@@ -158387,15 +159381,15 @@ init_logger();
|
|
|
158387
159381
|
|
|
158388
159382
|
// src/subagent-runner.ts
|
|
158389
159383
|
import * as childProcess from "node:child_process";
|
|
158390
|
-
import { existsSync as
|
|
158391
|
-
import { dirname, resolve as resolvePath } from "node:path";
|
|
159384
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
159385
|
+
import { dirname as dirname2, resolve as resolvePath } from "node:path";
|
|
158392
159386
|
import { createInterface } from "node:readline";
|
|
158393
159387
|
import { fileURLToPath } from "node:url";
|
|
158394
159388
|
function resolveSubagentEntryPath() {
|
|
158395
159389
|
try {
|
|
158396
|
-
const here =
|
|
159390
|
+
const here = dirname2(fileURLToPath(import.meta.url));
|
|
158397
159391
|
const candidate = resolvePath(here, "subagent-entry.js");
|
|
158398
|
-
if (
|
|
159392
|
+
if (existsSync5(candidate))
|
|
158399
159393
|
return candidate;
|
|
158400
159394
|
return;
|
|
158401
159395
|
} catch {
|
|
@@ -158941,7 +159935,7 @@ function deleteDreamState(db, key) {
|
|
|
158941
159935
|
var LEASE_HOLDER_KEY = "dreaming_lease_holder";
|
|
158942
159936
|
var LEASE_HEARTBEAT_KEY = "dreaming_lease_heartbeat";
|
|
158943
159937
|
var LEASE_EXPIRY_KEY = "dreaming_lease_expiry";
|
|
158944
|
-
var
|
|
159938
|
+
var LEASE_DURATION_MS2 = 2 * 60 * 1000;
|
|
158945
159939
|
function getLeaseExpiry(db) {
|
|
158946
159940
|
const value = getDreamState(db, LEASE_EXPIRY_KEY);
|
|
158947
159941
|
if (!value) {
|
|
@@ -158968,7 +159962,7 @@ function acquireLease(db, holderId) {
|
|
|
158968
159962
|
const now = Date.now();
|
|
158969
159963
|
setDreamState(db, LEASE_HOLDER_KEY, holderId);
|
|
158970
159964
|
setDreamState(db, LEASE_HEARTBEAT_KEY, String(now));
|
|
158971
|
-
setDreamState(db, LEASE_EXPIRY_KEY, String(now +
|
|
159965
|
+
setDreamState(db, LEASE_EXPIRY_KEY, String(now + LEASE_DURATION_MS2));
|
|
158972
159966
|
return true;
|
|
158973
159967
|
})();
|
|
158974
159968
|
}
|
|
@@ -158979,7 +159973,7 @@ function renewLease(db, holderId) {
|
|
|
158979
159973
|
}
|
|
158980
159974
|
const now = Date.now();
|
|
158981
159975
|
setDreamState(db, LEASE_HEARTBEAT_KEY, String(now));
|
|
158982
|
-
setDreamState(db, LEASE_EXPIRY_KEY, String(now +
|
|
159976
|
+
setDreamState(db, LEASE_EXPIRY_KEY, String(now + LEASE_DURATION_MS2));
|
|
158983
159977
|
return true;
|
|
158984
159978
|
})();
|
|
158985
159979
|
}
|
|
@@ -158994,8 +159988,8 @@ function releaseLease(db, holderId) {
|
|
|
158994
159988
|
})();
|
|
158995
159989
|
}
|
|
158996
159990
|
// ../plugin/src/features/magic-context/dreamer/runner.ts
|
|
158997
|
-
import { existsSync as
|
|
158998
|
-
import { join as
|
|
159991
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
159992
|
+
import { join as join9 } from "node:path";
|
|
158999
159993
|
|
|
159000
159994
|
// ../plugin/src/shared/index.ts
|
|
159001
159995
|
init_logger();
|
|
@@ -159126,11 +160120,6 @@ function normalizeSDKResponse(response, fallback, options) {
|
|
|
159126
160120
|
}
|
|
159127
160121
|
return fallback;
|
|
159128
160122
|
}
|
|
159129
|
-
// ../plugin/src/shared/record-type-guard.ts
|
|
159130
|
-
function isRecord(value) {
|
|
159131
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
159132
|
-
}
|
|
159133
|
-
|
|
159134
160123
|
// ../plugin/src/shared/assistant-message-extractor.ts
|
|
159135
160124
|
function asSessionMessage(value) {
|
|
159136
160125
|
if (!isRecord(value))
|
|
@@ -160393,11 +161382,11 @@ function countNewIds(beforeIds, afterIds) {
|
|
|
160393
161382
|
return count;
|
|
160394
161383
|
}
|
|
160395
161384
|
function getOpenCodeDbPath2() {
|
|
160396
|
-
return
|
|
161385
|
+
return join9(getDataDir(), "opencode", "opencode.db");
|
|
160397
161386
|
}
|
|
160398
161387
|
function openOpenCodeDb() {
|
|
160399
161388
|
const dbPath = getOpenCodeDbPath2();
|
|
160400
|
-
if (!
|
|
161389
|
+
if (!existsSync6(dbPath)) {
|
|
160401
161390
|
log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
|
|
160402
161391
|
return null;
|
|
160403
161392
|
}
|
|
@@ -160647,8 +161636,8 @@ async function runDream(args) {
|
|
|
160647
161636
|
try {
|
|
160648
161637
|
const docsDir = args.sessionDirectory ?? args.projectIdentity;
|
|
160649
161638
|
const existingDocs = taskName === "maintain-docs" ? {
|
|
160650
|
-
architecture:
|
|
160651
|
-
structure:
|
|
161639
|
+
architecture: existsSync6(join9(docsDir, "ARCHITECTURE.md")),
|
|
161640
|
+
structure: existsSync6(join9(docsDir, "STRUCTURE.md"))
|
|
160652
161641
|
} : undefined;
|
|
160653
161642
|
const userMemories = taskName === "archive-stale" ? getActiveUserMemories(args.db).map((um) => ({
|
|
160654
161643
|
id: um.id,
|
|
@@ -162158,14 +163147,46 @@ function createScheduler(config2) {
|
|
|
162158
163147
|
}
|
|
162159
163148
|
|
|
162160
163149
|
// ../plugin/src/features/magic-context/tagger.ts
|
|
163150
|
+
var TOOL_COMPOSITE_KEY_SEP = "\x00";
|
|
163151
|
+
function makeToolCompositeKey(ownerMsgId, callId) {
|
|
163152
|
+
return `${ownerMsgId}${TOOL_COMPOSITE_KEY_SEP}${callId}`;
|
|
163153
|
+
}
|
|
162161
163154
|
var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
|
|
162162
|
-
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
163155
|
+
var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
|
|
163156
|
+
var PROBE_DATA_VERSION_SQL = "PRAGMA main.data_version";
|
|
163157
|
+
var PROBE_TOTAL_CHANGES_SQL = "SELECT total_changes() AS tc";
|
|
163158
|
+
var probeDataVersionStatements = new WeakMap;
|
|
163159
|
+
var probeTotalChangesStatements = new WeakMap;
|
|
163160
|
+
function getProbeDataVersionStatement(db) {
|
|
163161
|
+
let stmt = probeDataVersionStatements.get(db);
|
|
163162
|
+
if (!stmt) {
|
|
163163
|
+
stmt = db.prepare(PROBE_DATA_VERSION_SQL);
|
|
163164
|
+
probeDataVersionStatements.set(db, stmt);
|
|
163165
|
+
}
|
|
163166
|
+
return stmt;
|
|
163167
|
+
}
|
|
163168
|
+
function getProbeTotalChangesStatement(db) {
|
|
163169
|
+
let stmt = probeTotalChangesStatements.get(db);
|
|
163170
|
+
if (!stmt) {
|
|
163171
|
+
stmt = db.prepare(PROBE_TOTAL_CHANGES_SQL);
|
|
163172
|
+
probeTotalChangesStatements.set(db, stmt);
|
|
163173
|
+
}
|
|
163174
|
+
return stmt;
|
|
163175
|
+
}
|
|
162163
163176
|
function isAssignmentRow(row) {
|
|
162164
163177
|
if (row === null || typeof row !== "object") {
|
|
162165
163178
|
return false;
|
|
162166
163179
|
}
|
|
162167
163180
|
const candidate = row;
|
|
162168
|
-
|
|
163181
|
+
if (typeof candidate.message_id !== "string")
|
|
163182
|
+
return false;
|
|
163183
|
+
if (typeof candidate.tag_number !== "number")
|
|
163184
|
+
return false;
|
|
163185
|
+
if (candidate.type !== "message" && candidate.type !== "tool" && candidate.type !== "file")
|
|
163186
|
+
return false;
|
|
163187
|
+
if (candidate.tool_owner_message_id !== null && typeof candidate.tool_owner_message_id !== "string")
|
|
163188
|
+
return false;
|
|
163189
|
+
return true;
|
|
162169
163190
|
}
|
|
162170
163191
|
var UPSERT_COUNTER_SQL = `
|
|
162171
163192
|
INSERT INTO session_meta (session_id, counter, harness)
|
|
@@ -162199,6 +163220,7 @@ var MAX_TAG_ALLOC_RETRIES = 5;
|
|
|
162199
163220
|
function createTagger() {
|
|
162200
163221
|
const counters = new Map;
|
|
162201
163222
|
const assignments = new Map;
|
|
163223
|
+
const loadSignatures = new Map;
|
|
162202
163224
|
function getSessionAssignments(sessionId) {
|
|
162203
163225
|
let map2 = assignments.get(sessionId);
|
|
162204
163226
|
if (!map2) {
|
|
@@ -162217,15 +163239,15 @@ function createTagger() {
|
|
|
162217
163239
|
counters.set(sessionId, next);
|
|
162218
163240
|
getUpsertCounterStatement(db).run(sessionId, next, getHarness());
|
|
162219
163241
|
}
|
|
162220
|
-
function
|
|
163242
|
+
function allocateTag(sessionId, messageId, type, byteSize2, db, reasoningByteSize, toolName, inputByteSize, toolOwnerMessageId, mapKey, dbExistingLookup) {
|
|
162221
163243
|
const sessionAssignments = getSessionAssignments(sessionId);
|
|
162222
|
-
const existing = sessionAssignments.get(
|
|
163244
|
+
const existing = sessionAssignments.get(mapKey);
|
|
162223
163245
|
if (existing !== undefined) {
|
|
162224
163246
|
return existing;
|
|
162225
163247
|
}
|
|
162226
|
-
const dbExisting =
|
|
163248
|
+
const dbExisting = dbExistingLookup();
|
|
162227
163249
|
if (dbExisting !== null) {
|
|
162228
|
-
sessionAssignments.set(
|
|
163250
|
+
sessionAssignments.set(mapKey, dbExisting);
|
|
162229
163251
|
syncCounterAtLeast(sessionId, db, dbExisting);
|
|
162230
163252
|
return dbExisting;
|
|
162231
163253
|
}
|
|
@@ -162235,16 +163257,16 @@ function createTagger() {
|
|
|
162235
163257
|
const next = Math.max(memCounter, dbMax) + 1;
|
|
162236
163258
|
try {
|
|
162237
163259
|
db.transaction(() => {
|
|
162238
|
-
insertTag(db, sessionId, messageId, type, byteSize2, next, reasoningByteSize, toolName, inputByteSize);
|
|
163260
|
+
insertTag(db, sessionId, messageId, type, byteSize2, next, reasoningByteSize, toolName, inputByteSize, toolOwnerMessageId);
|
|
162239
163261
|
getUpsertCounterStatement(db).run(sessionId, next, getHarness());
|
|
162240
163262
|
})();
|
|
162241
163263
|
} catch (error48) {
|
|
162242
163264
|
if (!isUniqueConstraintError(error48)) {
|
|
162243
163265
|
throw error48;
|
|
162244
163266
|
}
|
|
162245
|
-
const racedRow =
|
|
163267
|
+
const racedRow = dbExistingLookup();
|
|
162246
163268
|
if (racedRow !== null) {
|
|
162247
|
-
sessionAssignments.set(
|
|
163269
|
+
sessionAssignments.set(mapKey, racedRow);
|
|
162248
163270
|
syncCounterAtLeast(sessionId, db, racedRow);
|
|
162249
163271
|
return racedRow;
|
|
162250
163272
|
}
|
|
@@ -162253,51 +163275,124 @@ function createTagger() {
|
|
|
162253
163275
|
continue;
|
|
162254
163276
|
}
|
|
162255
163277
|
counters.set(sessionId, next);
|
|
162256
|
-
sessionAssignments.set(
|
|
163278
|
+
sessionAssignments.set(mapKey, next);
|
|
162257
163279
|
return next;
|
|
162258
163280
|
}
|
|
162259
|
-
throw new Error(`tagger.
|
|
163281
|
+
throw new Error(`tagger.allocateTag: failed to allocate tag for session=${sessionId} key=${mapKey} after ${MAX_TAG_ALLOC_RETRIES} retries`);
|
|
162260
163282
|
}
|
|
162261
|
-
function
|
|
163283
|
+
function assignTag(sessionId, messageId, type, byteSize2, db, reasoningByteSize = 0, toolName = null, inputByteSize = 0) {
|
|
163284
|
+
if (type === "tool") {
|
|
163285
|
+
throw new Error("tagger.assignTag: type='tool' is forbidden — use assignToolTag(sessionId, callId, ownerMsgId, ...)");
|
|
163286
|
+
}
|
|
163287
|
+
return allocateTag(sessionId, messageId, type, byteSize2, db, reasoningByteSize, toolName, inputByteSize, null, messageId, () => getTagNumberByMessageId(db, sessionId, messageId));
|
|
163288
|
+
}
|
|
163289
|
+
function assignToolTag(sessionId, callId, ownerMsgId, byteSize2, db, reasoningByteSize = 0, toolName = null, inputByteSize = 0) {
|
|
163290
|
+
const compositeKey = makeToolCompositeKey(ownerMsgId, callId);
|
|
163291
|
+
const sessionAssignments = getSessionAssignments(sessionId);
|
|
163292
|
+
const existing = sessionAssignments.get(compositeKey);
|
|
163293
|
+
if (existing !== undefined) {
|
|
163294
|
+
return existing;
|
|
163295
|
+
}
|
|
163296
|
+
const dbHit = getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId);
|
|
163297
|
+
if (dbHit !== null) {
|
|
163298
|
+
sessionAssignments.set(compositeKey, dbHit);
|
|
163299
|
+
syncCounterAtLeast(sessionId, db, dbHit);
|
|
163300
|
+
return dbHit;
|
|
163301
|
+
}
|
|
163302
|
+
for (let attempt = 0;attempt < MAX_TAG_ALLOC_RETRIES; attempt += 1) {
|
|
163303
|
+
const orphan = getNullOwnerToolTag(db, sessionId, callId);
|
|
163304
|
+
if (orphan === null)
|
|
163305
|
+
break;
|
|
163306
|
+
const claimed = adoptNullOwnerToolTag(db, orphan.id, ownerMsgId);
|
|
163307
|
+
if (claimed) {
|
|
163308
|
+
sessionAssignments.set(compositeKey, orphan.tagNumber);
|
|
163309
|
+
syncCounterAtLeast(sessionId, db, orphan.tagNumber);
|
|
163310
|
+
return orphan.tagNumber;
|
|
163311
|
+
}
|
|
163312
|
+
const recheck = getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId);
|
|
163313
|
+
if (recheck !== null) {
|
|
163314
|
+
sessionAssignments.set(compositeKey, recheck);
|
|
163315
|
+
syncCounterAtLeast(sessionId, db, recheck);
|
|
163316
|
+
return recheck;
|
|
163317
|
+
}
|
|
163318
|
+
}
|
|
163319
|
+
return allocateTag(sessionId, callId, "tool", byteSize2, db, reasoningByteSize, toolName, inputByteSize, ownerMsgId, compositeKey, () => getToolTagNumberByOwner(db, sessionId, callId, ownerMsgId));
|
|
163320
|
+
}
|
|
163321
|
+
function getTag(sessionId, messageId, _type) {
|
|
162262
163322
|
return assignments.get(sessionId)?.get(messageId);
|
|
162263
163323
|
}
|
|
163324
|
+
function getToolTag(sessionId, callId, ownerMsgId) {
|
|
163325
|
+
return assignments.get(sessionId)?.get(makeToolCompositeKey(ownerMsgId, callId));
|
|
163326
|
+
}
|
|
162264
163327
|
function bindTag(sessionId, messageId, tagNumber) {
|
|
162265
163328
|
getSessionAssignments(sessionId).set(messageId, tagNumber);
|
|
162266
163329
|
}
|
|
163330
|
+
function bindToolTag(sessionId, callId, ownerMsgId, tagNumber) {
|
|
163331
|
+
getSessionAssignments(sessionId).set(makeToolCompositeKey(ownerMsgId, callId), tagNumber);
|
|
163332
|
+
}
|
|
162267
163333
|
function getAssignments(sessionId) {
|
|
162268
163334
|
return getSessionAssignments(sessionId);
|
|
162269
163335
|
}
|
|
162270
163336
|
function resetCounter(sessionId, db) {
|
|
162271
163337
|
counters.set(sessionId, 0);
|
|
162272
163338
|
assignments.delete(sessionId);
|
|
163339
|
+
loadSignatures.delete(sessionId);
|
|
162273
163340
|
getResetCounterStatement(db).run(sessionId, getHarness());
|
|
162274
163341
|
}
|
|
162275
163342
|
function getCounter(sessionId) {
|
|
162276
163343
|
return counters.get(sessionId) ?? 0;
|
|
162277
163344
|
}
|
|
163345
|
+
function probeSignature(db) {
|
|
163346
|
+
const dvRow = getProbeDataVersionStatement(db).get();
|
|
163347
|
+
const tcRow = getProbeTotalChangesStatement(db).get();
|
|
163348
|
+
return {
|
|
163349
|
+
dataVersion: dvRow?.data_version ?? 0,
|
|
163350
|
+
totalChanges: tcRow?.tc ?? 0
|
|
163351
|
+
};
|
|
163352
|
+
}
|
|
162278
163353
|
function initFromDb(sessionId, db) {
|
|
163354
|
+
const probe = probeSignature(db);
|
|
163355
|
+
const cached2 = loadSignatures.get(sessionId);
|
|
163356
|
+
if (cached2 !== undefined && cached2.db === db && cached2.dataVersion === probe.dataVersion && cached2.totalChanges === probe.totalChanges) {
|
|
163357
|
+
return;
|
|
163358
|
+
}
|
|
162279
163359
|
const row = db.prepare(GET_COUNTER_SQL).get(sessionId);
|
|
162280
163360
|
const assignmentRows = db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId).filter(isAssignmentRow);
|
|
162281
163361
|
const sessionAssignments = getSessionAssignments(sessionId);
|
|
162282
163362
|
sessionAssignments.clear();
|
|
162283
163363
|
let maxTagNumber = 0;
|
|
162284
163364
|
for (const assignment of assignmentRows) {
|
|
162285
|
-
|
|
163365
|
+
if (assignment.type === "tool") {
|
|
163366
|
+
if (assignment.tool_owner_message_id !== null) {
|
|
163367
|
+
sessionAssignments.set(makeToolCompositeKey(assignment.tool_owner_message_id, assignment.message_id), assignment.tag_number);
|
|
163368
|
+
}
|
|
163369
|
+
} else {
|
|
163370
|
+
sessionAssignments.set(assignment.message_id, assignment.tag_number);
|
|
163371
|
+
}
|
|
162286
163372
|
if (assignment.tag_number > maxTagNumber) {
|
|
162287
163373
|
maxTagNumber = assignment.tag_number;
|
|
162288
163374
|
}
|
|
162289
163375
|
}
|
|
162290
163376
|
const counter = Math.max(row?.counter ?? 0, maxTagNumber, counters.get(sessionId) ?? 0);
|
|
162291
163377
|
counters.set(sessionId, counter);
|
|
163378
|
+
loadSignatures.set(sessionId, {
|
|
163379
|
+
db,
|
|
163380
|
+
dataVersion: probe.dataVersion,
|
|
163381
|
+
totalChanges: probe.totalChanges
|
|
163382
|
+
});
|
|
162292
163383
|
}
|
|
162293
163384
|
function cleanup(sessionId) {
|
|
162294
163385
|
counters.delete(sessionId);
|
|
162295
163386
|
assignments.delete(sessionId);
|
|
163387
|
+
loadSignatures.delete(sessionId);
|
|
162296
163388
|
}
|
|
162297
163389
|
return {
|
|
162298
163390
|
assignTag,
|
|
163391
|
+
assignToolTag,
|
|
162299
163392
|
getTag,
|
|
163393
|
+
getToolTag,
|
|
162300
163394
|
bindTag,
|
|
163395
|
+
bindToolTag,
|
|
162301
163396
|
getAssignments,
|
|
162302
163397
|
resetCounter,
|
|
162303
163398
|
getCounter,
|
|
@@ -163310,7 +164405,7 @@ function createNudger(config2) {
|
|
|
163310
164405
|
}
|
|
163311
164406
|
const largest = formatLargestTags(topNFn(db, sessionId, 3));
|
|
163312
164407
|
const protectedCount = config2.protected_tags;
|
|
163313
|
-
const activeTags =
|
|
164408
|
+
const activeTags = preloadedTags ? preloadedTags.filter((t) => t.status === "active") : getActiveTagsBySession(db, sessionId);
|
|
163314
164409
|
const highestProtected = activeTags.map((t) => t.tagNumber).sort((a, b) => b - a).slice(0, protectedCount)[0];
|
|
163315
164410
|
const protectedHint = highestProtected ? ` Tags §${highestProtected}§ and above are protected (last ${protectedCount}) — You MUST NOT try to reduce those.` : "";
|
|
163316
164411
|
const oldToolHint = formatOldToolTags(activeTags, protectedCount, 5);
|
|
@@ -163401,7 +164496,7 @@ function estimateProjectedPercentage(db, sessionId, contextUsage, preloadedTags)
|
|
|
163401
164496
|
if (pendingDrops.length === 0) {
|
|
163402
164497
|
return null;
|
|
163403
164498
|
}
|
|
163404
|
-
const activeTags =
|
|
164499
|
+
const activeTags = preloadedTags ? preloadedTags.filter((t) => t.status === "active") : getActiveTagsBySession(db, sessionId);
|
|
163405
164500
|
const totalActiveBytes = activeTags.reduce((sum, t) => sum + t.byteSize, 0);
|
|
163406
164501
|
if (totalActiveBytes === 0) {
|
|
163407
164502
|
return null;
|
|
@@ -163412,15 +164507,6 @@ function estimateProjectedPercentage(db, sessionId, contextUsage, preloadedTags)
|
|
|
163412
164507
|
return contextUsage.percentage * (1 - dropRatio);
|
|
163413
164508
|
}
|
|
163414
164509
|
|
|
163415
|
-
// ../plugin/src/hooks/magic-context/reasoning-capability.ts
|
|
163416
|
-
function modelRequiresInterleavedReasoning(model) {
|
|
163417
|
-
if (!model?.providerID || !model?.modelID) {
|
|
163418
|
-
return false;
|
|
163419
|
-
}
|
|
163420
|
-
const field = getModelsDevInterleavedField(model.providerID, model.modelID);
|
|
163421
|
-
return typeof field === "string" && field.length > 0;
|
|
163422
|
-
}
|
|
163423
|
-
|
|
163424
164510
|
// src/context-handler.ts
|
|
163425
164511
|
init_logger();
|
|
163426
164512
|
|
|
@@ -163429,107 +164515,105 @@ function tagTranscript(sessionId, transcript, tagger, db, options = {}) {
|
|
|
163429
164515
|
const skipPrefixInjection = options.skipPrefixInjection === true;
|
|
163430
164516
|
const targets = new Map;
|
|
163431
164517
|
const toolAggregates = new Map;
|
|
163432
|
-
|
|
163433
|
-
|
|
163434
|
-
|
|
163435
|
-
|
|
164518
|
+
for (let msgIndex = 0;msgIndex < transcript.messages.length; msgIndex += 1) {
|
|
164519
|
+
const message = transcript.messages[msgIndex];
|
|
164520
|
+
if (message === undefined)
|
|
164521
|
+
continue;
|
|
164522
|
+
const messageId = message.info.id;
|
|
164523
|
+
let textOrdinal = 0;
|
|
164524
|
+
for (let partIndex = 0;partIndex < message.parts.length; partIndex += 1) {
|
|
164525
|
+
const part = message.parts[partIndex];
|
|
164526
|
+
if (part === undefined)
|
|
163436
164527
|
continue;
|
|
163437
|
-
|
|
163438
|
-
|
|
163439
|
-
|
|
163440
|
-
const part = message.parts[partIndex];
|
|
163441
|
-
if (part === undefined)
|
|
164528
|
+
if (part.kind === "text") {
|
|
164529
|
+
if (messageId === undefined) {
|
|
164530
|
+
textOrdinal += 1;
|
|
163442
164531
|
continue;
|
|
163443
|
-
|
|
163444
|
-
|
|
163445
|
-
|
|
163446
|
-
|
|
163447
|
-
|
|
163448
|
-
|
|
164532
|
+
}
|
|
164533
|
+
tagTextPart({
|
|
164534
|
+
sessionId,
|
|
164535
|
+
message,
|
|
164536
|
+
messageId,
|
|
164537
|
+
msgIndex,
|
|
164538
|
+
textOrdinal,
|
|
164539
|
+
part,
|
|
164540
|
+
tagger,
|
|
164541
|
+
db,
|
|
164542
|
+
targets,
|
|
164543
|
+
skipPrefixInjection
|
|
164544
|
+
});
|
|
164545
|
+
textOrdinal += 1;
|
|
164546
|
+
continue;
|
|
164547
|
+
}
|
|
164548
|
+
if (part.kind === "tool_use" || part.kind === "tool_result") {
|
|
164549
|
+
if (messageId === undefined)
|
|
164550
|
+
continue;
|
|
164551
|
+
const callId = part.id;
|
|
164552
|
+
const text = part.getText() ?? "";
|
|
164553
|
+
const meta3 = part.getToolMetadata();
|
|
164554
|
+
if (typeof callId !== "string" || callId.length === 0) {
|
|
164555
|
+
tagToolPart({
|
|
163449
164556
|
sessionId,
|
|
163450
164557
|
message,
|
|
163451
164558
|
messageId,
|
|
163452
164559
|
msgIndex,
|
|
163453
|
-
|
|
164560
|
+
partIndex,
|
|
163454
164561
|
part,
|
|
163455
164562
|
tagger,
|
|
163456
164563
|
db,
|
|
163457
164564
|
targets,
|
|
163458
164565
|
skipPrefixInjection
|
|
163459
164566
|
});
|
|
163460
|
-
textOrdinal += 1;
|
|
163461
164567
|
continue;
|
|
163462
164568
|
}
|
|
163463
|
-
|
|
163464
|
-
|
|
163465
|
-
|
|
163466
|
-
|
|
163467
|
-
|
|
163468
|
-
|
|
163469
|
-
|
|
163470
|
-
|
|
163471
|
-
|
|
163472
|
-
|
|
163473
|
-
|
|
163474
|
-
msgIndex,
|
|
163475
|
-
partIndex,
|
|
163476
|
-
part,
|
|
163477
|
-
tagger,
|
|
163478
|
-
db,
|
|
163479
|
-
targets,
|
|
163480
|
-
skipPrefixInjection
|
|
163481
|
-
});
|
|
163482
|
-
continue;
|
|
164569
|
+
const existing = toolAggregates.get(callId);
|
|
164570
|
+
if (existing) {
|
|
164571
|
+
existing.occurrences.push({
|
|
164572
|
+
message,
|
|
164573
|
+
part,
|
|
164574
|
+
kind: part.kind
|
|
164575
|
+
});
|
|
164576
|
+
const newByteSize = byteSize(text);
|
|
164577
|
+
if (newByteSize > existing.maxByteSize) {
|
|
164578
|
+
existing.maxByteSize = newByteSize;
|
|
164579
|
+
updateTagByteSize(db, sessionId, existing.tagId, newByteSize);
|
|
163483
164580
|
}
|
|
163484
|
-
|
|
163485
|
-
|
|
163486
|
-
|
|
163487
|
-
|
|
163488
|
-
|
|
163489
|
-
|
|
163490
|
-
|
|
163491
|
-
|
|
163492
|
-
|
|
163493
|
-
|
|
163494
|
-
|
|
163495
|
-
|
|
163496
|
-
|
|
163497
|
-
|
|
163498
|
-
|
|
163499
|
-
|
|
163500
|
-
|
|
163501
|
-
|
|
163502
|
-
|
|
163503
|
-
|
|
163504
|
-
|
|
163505
|
-
|
|
163506
|
-
|
|
163507
|
-
|
|
163508
|
-
|
|
163509
|
-
|
|
163510
|
-
|
|
163511
|
-
|
|
163512
|
-
|
|
163513
|
-
|
|
163514
|
-
message,
|
|
163515
|
-
part,
|
|
163516
|
-
kind: part.kind
|
|
163517
|
-
}
|
|
163518
|
-
],
|
|
163519
|
-
maxByteSize: byteSize(text),
|
|
163520
|
-
toolName: meta3.toolName ?? null,
|
|
163521
|
-
inputByteSize: part.kind === "tool_use" ? meta3.inputByteSize : 0
|
|
163522
|
-
};
|
|
163523
|
-
toolAggregates.set(callId, aggregate);
|
|
163524
|
-
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
163525
|
-
part.setText(prependTag(tagId, text));
|
|
163526
|
-
}
|
|
163527
|
-
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
164581
|
+
if (existing.toolName === null && meta3.toolName) {
|
|
164582
|
+
existing.toolName = meta3.toolName;
|
|
164583
|
+
}
|
|
164584
|
+
if (existing.inputByteSize === 0 && part.kind === "tool_use" && meta3.inputByteSize > 0) {
|
|
164585
|
+
existing.inputByteSize = meta3.inputByteSize;
|
|
164586
|
+
updateTagInputByteSize(db, sessionId, existing.tagId, meta3.inputByteSize);
|
|
164587
|
+
}
|
|
164588
|
+
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
164589
|
+
part.setText(prependTag(existing.tagId, text));
|
|
164590
|
+
}
|
|
164591
|
+
targets.set(existing.tagId, buildAggregateTarget(existing.tagId, existing.occurrences));
|
|
164592
|
+
} else {
|
|
164593
|
+
const tagId = tagger.assignToolTag(sessionId, callId, messageId, byteSize(text), db, 0, meta3.toolName ?? null, meta3.inputByteSize);
|
|
164594
|
+
const aggregate = {
|
|
164595
|
+
callId,
|
|
164596
|
+
tagId,
|
|
164597
|
+
occurrences: [
|
|
164598
|
+
{
|
|
164599
|
+
message,
|
|
164600
|
+
part,
|
|
164601
|
+
kind: part.kind
|
|
164602
|
+
}
|
|
164603
|
+
],
|
|
164604
|
+
maxByteSize: byteSize(text),
|
|
164605
|
+
toolName: meta3.toolName ?? null,
|
|
164606
|
+
inputByteSize: part.kind === "tool_use" ? meta3.inputByteSize : 0
|
|
164607
|
+
};
|
|
164608
|
+
toolAggregates.set(callId, aggregate);
|
|
164609
|
+
if (!skipPrefixInjection && part.kind === "tool_result") {
|
|
164610
|
+
part.setText(prependTag(tagId, text));
|
|
163528
164611
|
}
|
|
164612
|
+
targets.set(tagId, buildAggregateTarget(tagId, aggregate.occurrences));
|
|
163529
164613
|
}
|
|
163530
164614
|
}
|
|
163531
164615
|
}
|
|
163532
|
-
}
|
|
164616
|
+
}
|
|
163533
164617
|
return { targets };
|
|
163534
164618
|
}
|
|
163535
164619
|
function tagTextPart(args) {
|
|
@@ -163550,7 +164634,7 @@ function tagToolPart(args) {
|
|
|
163550
164634
|
const contentId = stableId ?? `${args.messageId}:t${args.partIndex}`;
|
|
163551
164635
|
const text = args.part.getText() ?? "";
|
|
163552
164636
|
const meta3 = args.part.getToolMetadata();
|
|
163553
|
-
const tagId = args.tagger.
|
|
164637
|
+
const tagId = args.tagger.assignToolTag(args.sessionId, contentId, contentId, byteSize(text), args.db, 0, meta3.toolName ?? null, meta3.inputByteSize);
|
|
163554
164638
|
if (!args.skipPrefixInjection && args.part.kind === "tool_result") {
|
|
163555
164639
|
const tagged = prependTag(tagId, text);
|
|
163556
164640
|
args.part.setText(tagged);
|
|
@@ -163790,11 +164874,7 @@ function getMessageOrdinal(value) {
|
|
|
163790
164874
|
}
|
|
163791
164875
|
async function getSemanticScores(args) {
|
|
163792
164876
|
const semanticScores = new Map;
|
|
163793
|
-
if (!args.
|
|
163794
|
-
return semanticScores;
|
|
163795
|
-
}
|
|
163796
|
-
const queryEmbedding = await args.embedQuery(args.query, args.signal);
|
|
163797
|
-
if (!queryEmbedding) {
|
|
164877
|
+
if (!args.queryEmbedding || args.memories.length === 0) {
|
|
163798
164878
|
return semanticScores;
|
|
163799
164879
|
}
|
|
163800
164880
|
const cachedEmbeddings = getProjectEmbeddings(args.db, args.projectPath);
|
|
@@ -163808,7 +164888,7 @@ async function getSemanticScores(args) {
|
|
|
163808
164888
|
if (!memoryEmbedding) {
|
|
163809
164889
|
continue;
|
|
163810
164890
|
}
|
|
163811
|
-
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(queryEmbedding, memoryEmbedding)));
|
|
164891
|
+
semanticScores.set(memory.id, normalizeCosineScore(cosineSimilarity(args.queryEmbedding, memoryEmbedding)));
|
|
163812
164892
|
}
|
|
163813
164893
|
return semanticScores;
|
|
163814
164894
|
}
|
|
@@ -163904,12 +164984,8 @@ async function searchMemories(args) {
|
|
|
163904
164984
|
const semanticScores = await getSemanticScores({
|
|
163905
164985
|
db: args.db,
|
|
163906
164986
|
projectPath: args.projectPath,
|
|
163907
|
-
query: args.query,
|
|
163908
164987
|
memories: semanticCandidates,
|
|
163909
|
-
|
|
163910
|
-
embedQuery: args.embedQuery,
|
|
163911
|
-
isEmbeddingRuntimeEnabled: args.isEmbeddingRuntimeEnabled,
|
|
163912
|
-
signal: args.signal
|
|
164988
|
+
queryEmbedding: args.queryEmbedding
|
|
163913
164989
|
});
|
|
163914
164990
|
return mergeMemoryResults({
|
|
163915
164991
|
memories,
|
|
@@ -163925,7 +165001,6 @@ function linearDecayScore(rank, total) {
|
|
|
163925
165001
|
return Math.max(0, 1 - rank / total);
|
|
163926
165002
|
}
|
|
163927
165003
|
function searchMessages(args) {
|
|
163928
|
-
ensureMessagesIndexed(args.db, args.sessionId, args.readMessages);
|
|
163929
165004
|
const sanitizedQuery = sanitizeFtsQuery(args.query.trim());
|
|
163930
165005
|
if (sanitizedQuery.length === 0) {
|
|
163931
165006
|
return [];
|
|
@@ -163996,20 +165071,12 @@ function toGitCommitResult(hit) {
|
|
|
163996
165071
|
matchType: hit.matchType
|
|
163997
165072
|
};
|
|
163998
165073
|
}
|
|
163999
|
-
|
|
165074
|
+
function searchGitCommits(args) {
|
|
164000
165075
|
if (args.limit <= 0)
|
|
164001
165076
|
return [];
|
|
164002
|
-
let queryEmbedding = null;
|
|
164003
|
-
if (args.embeddingEnabled && args.isEmbeddingRuntimeEnabled()) {
|
|
164004
|
-
try {
|
|
164005
|
-
queryEmbedding = await args.embedQuery(args.query, args.signal);
|
|
164006
|
-
} catch (error48) {
|
|
164007
|
-
log(`[search] git commit query embedding failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
164008
|
-
}
|
|
164009
|
-
}
|
|
164010
165077
|
const hits = searchGitCommitsSync(args.db, args.projectPath, args.query, {
|
|
164011
165078
|
limit: args.limit,
|
|
164012
|
-
queryEmbedding
|
|
165079
|
+
queryEmbedding: args.queryEmbedding
|
|
164013
165080
|
});
|
|
164014
165081
|
return hits.map(toGitCommitResult);
|
|
164015
165082
|
}
|
|
@@ -164040,37 +165107,37 @@ async function unifiedSearch(db, sessionId, projectPath, query, options = {}) {
|
|
|
164040
165107
|
const runMemory = activeSources.has("memory") && (options.memoryEnabled ?? true);
|
|
164041
165108
|
const runMessages = activeSources.has("message");
|
|
164042
165109
|
const runGitCommits = activeSources.has("git_commit") && gitCommitsEnabled;
|
|
164043
|
-
const
|
|
165110
|
+
const needsEmbedding = (runMemory || runGitCommits) && embeddingEnabled && isEmbeddingRuntimeEnabled();
|
|
165111
|
+
const queryEmbeddingPromise = needsEmbedding ? embedQuery(trimmedQuery, options.signal).catch((error48) => {
|
|
165112
|
+
log(`[search] query embedding failed: ${error48 instanceof Error ? error48.message : String(error48)}`);
|
|
165113
|
+
return null;
|
|
165114
|
+
}) : Promise.resolve(null);
|
|
165115
|
+
await Promise.resolve();
|
|
165116
|
+
const messageResults = runMessages ? searchMessages({
|
|
165117
|
+
db,
|
|
165118
|
+
sessionId,
|
|
165119
|
+
query: trimmedQuery,
|
|
165120
|
+
limit: tierLimit,
|
|
165121
|
+
maxOrdinal: options.maxMessageOrdinal
|
|
165122
|
+
}) : [];
|
|
165123
|
+
const queryEmbedding = await queryEmbeddingPromise;
|
|
165124
|
+
const [memoryResults, gitCommitResults] = await Promise.all([
|
|
164044
165125
|
runMemory ? searchMemories({
|
|
164045
165126
|
db,
|
|
164046
165127
|
projectPath,
|
|
164047
165128
|
query: trimmedQuery,
|
|
164048
165129
|
limit: tierLimit,
|
|
164049
165130
|
memoryEnabled: true,
|
|
164050
|
-
|
|
164051
|
-
|
|
164052
|
-
isEmbeddingRuntimeEnabled,
|
|
164053
|
-
visibleMemoryIds: options.visibleMemoryIds,
|
|
164054
|
-
signal: options.signal
|
|
165131
|
+
queryEmbedding,
|
|
165132
|
+
visibleMemoryIds: options.visibleMemoryIds
|
|
164055
165133
|
}) : Promise.resolve([]),
|
|
164056
|
-
|
|
164057
|
-
db,
|
|
164058
|
-
sessionId,
|
|
164059
|
-
query: trimmedQuery,
|
|
164060
|
-
limit: tierLimit,
|
|
164061
|
-
readMessages: options.readMessages ?? readRawSessionMessages,
|
|
164062
|
-
maxOrdinal: options.maxMessageOrdinal
|
|
164063
|
-
})) : Promise.resolve([]),
|
|
164064
|
-
runGitCommits ? searchGitCommitsAsync({
|
|
165134
|
+
runGitCommits ? Promise.resolve(searchGitCommits({
|
|
164065
165135
|
db,
|
|
164066
165136
|
projectPath,
|
|
164067
165137
|
query: trimmedQuery,
|
|
164068
165138
|
limit: tierLimit,
|
|
164069
|
-
|
|
164070
|
-
|
|
164071
|
-
isEmbeddingRuntimeEnabled,
|
|
164072
|
-
signal: options.signal
|
|
164073
|
-
}) : Promise.resolve([])
|
|
165139
|
+
queryEmbedding
|
|
165140
|
+
})) : Promise.resolve([])
|
|
164074
165141
|
]);
|
|
164075
165142
|
const results = [...memoryResults, ...messageResults, ...gitCommitResults].sort(compareUnifiedResults).slice(0, limit);
|
|
164076
165143
|
const countRetrievals = options.countRetrievals ?? true;
|
|
@@ -164487,8 +165554,8 @@ function collectStaleReduceCallIds(messages, messageIdToMaxTag, toolAgeCutoff) {
|
|
|
164487
165554
|
return staleCallIds;
|
|
164488
165555
|
}
|
|
164489
165556
|
function applyPiHeuristicCleanup(sessionId, db, targets, piMessages, config2, preloadedTags) {
|
|
164490
|
-
const tags = preloadedTags ??
|
|
164491
|
-
const maxTag =
|
|
165557
|
+
const tags = preloadedTags ?? getActiveTagsBySession(db, sessionId);
|
|
165558
|
+
const maxTag = getMaxTagNumberBySession(db, sessionId);
|
|
164492
165559
|
const toolAgeCutoff = maxTag - config2.autoDropToolAge;
|
|
164493
165560
|
const protectedCutoff = maxTag - config2.protectedTags;
|
|
164494
165561
|
let droppedTools = 0;
|
|
@@ -165601,12 +166668,24 @@ function clearPiCompressorState(sessionId) {
|
|
|
165601
166668
|
init_logger();
|
|
165602
166669
|
function queueDropsForCompartmentalizedMessages(db, sessionId, upToMessageIndex) {
|
|
165603
166670
|
const tags = getTagsBySession(db, sessionId);
|
|
165604
|
-
const
|
|
166671
|
+
const { messageFileKeys, toolObservations } = getRawSessionTagKeysThrough(sessionId, upToMessageIndex);
|
|
165605
166672
|
let dropsQueued = 0;
|
|
165606
166673
|
for (const tag of tags) {
|
|
165607
166674
|
if (tag.status !== "active")
|
|
165608
166675
|
continue;
|
|
165609
|
-
if (
|
|
166676
|
+
if (tag.type === "tool") {
|
|
166677
|
+
const observedOwners = toolObservations.get(tag.messageId);
|
|
166678
|
+
if (!observedOwners)
|
|
166679
|
+
continue;
|
|
166680
|
+
if (tag.toolOwnerMessageId !== null) {
|
|
166681
|
+
if (!observedOwners.has(tag.toolOwnerMessageId))
|
|
166682
|
+
continue;
|
|
166683
|
+
}
|
|
166684
|
+
queuePendingOp(db, sessionId, tag.tagNumber, "drop");
|
|
166685
|
+
dropsQueued += 1;
|
|
166686
|
+
continue;
|
|
166687
|
+
}
|
|
166688
|
+
if (messageFileKeys.has(tag.messageId)) {
|
|
165610
166689
|
queuePendingOp(db, sessionId, tag.tagNumber, "drop");
|
|
165611
166690
|
dropsQueued += 1;
|
|
165612
166691
|
}
|
|
@@ -165812,28 +166891,28 @@ function getReducedRecompTokenBudget(currentBudget) {
|
|
|
165812
166891
|
}
|
|
165813
166892
|
|
|
165814
166893
|
// ../plugin/src/hooks/magic-context/historian-state-file.ts
|
|
165815
|
-
import { mkdirSync as
|
|
166894
|
+
import { mkdirSync as mkdirSync4, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
165816
166895
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
165817
|
-
import { join as
|
|
166896
|
+
import { join as join10 } from "node:path";
|
|
165818
166897
|
var HISTORIAN_STATE_INLINE_THRESHOLD = 30000;
|
|
165819
|
-
var HISTORIAN_STATE_DIR =
|
|
166898
|
+
var HISTORIAN_STATE_DIR = join10(tmpdir2(), "magic-context-historian");
|
|
165820
166899
|
function maybeWriteHistorianStateFile(sessionId, existingState) {
|
|
165821
166900
|
if (existingState.length <= HISTORIAN_STATE_INLINE_THRESHOLD)
|
|
165822
166901
|
return;
|
|
165823
166902
|
try {
|
|
165824
|
-
|
|
165825
|
-
const
|
|
165826
|
-
|
|
165827
|
-
return
|
|
166903
|
+
mkdirSync4(HISTORIAN_STATE_DIR, { recursive: true });
|
|
166904
|
+
const path5 = join10(HISTORIAN_STATE_DIR, `state-${sessionId}-${Date.now()}.xml`);
|
|
166905
|
+
writeFileSync2(path5, existingState, "utf8");
|
|
166906
|
+
return path5;
|
|
165828
166907
|
} catch {
|
|
165829
166908
|
return;
|
|
165830
166909
|
}
|
|
165831
166910
|
}
|
|
165832
|
-
function cleanupHistorianStateFile(
|
|
165833
|
-
if (!
|
|
166911
|
+
function cleanupHistorianStateFile(path5) {
|
|
166912
|
+
if (!path5)
|
|
165834
166913
|
return;
|
|
165835
166914
|
try {
|
|
165836
|
-
unlinkSync(
|
|
166915
|
+
unlinkSync(path5);
|
|
165837
166916
|
} catch {}
|
|
165838
166917
|
}
|
|
165839
166918
|
|
|
@@ -165932,24 +167011,12 @@ ${chunk.text}`, { stateFilePath });
|
|
|
165932
167011
|
const maxExistingSequence = priorCompartments.reduce((max, c) => c.sequence > max ? c.sequence : max, -1);
|
|
165933
167012
|
const sequenceOffset = priorCompartments.length === 0 ? 0 : maxExistingSequence + 1;
|
|
165934
167013
|
sessionLog(sessionId, `pi-historian: invoking subagent (model=${historianModel}, chunk=${chunk.startIndex}-${chunk.endIndex}, ${chunk.messageCount} msgs, ~${chunk.tokenEstimate} tokens)`);
|
|
167014
|
+
const traceRawEvents = process.env.MC_PI_HISTORIAN_TRACE === "1";
|
|
165935
167015
|
const buildProgressLogger = (passLabel) => {
|
|
165936
167016
|
return (event) => {
|
|
165937
167017
|
try {
|
|
165938
|
-
if (event.type === "
|
|
165939
|
-
let serialized;
|
|
165940
|
-
try {
|
|
165941
|
-
serialized = JSON.stringify(event.event);
|
|
165942
|
-
} catch {
|
|
165943
|
-
serialized = "[unserializable]";
|
|
165944
|
-
}
|
|
165945
|
-
if (serialized.length > 4000) {
|
|
165946
|
-
serialized = `${serialized.slice(0, 4000)}…[truncated ${serialized.length - 4000} chars]`;
|
|
165947
|
-
}
|
|
165948
|
-
sessionLog(sessionId, `pi-historian[${passLabel}] raw_event @${event.ms}ms type=${event.eventType ?? "?"}: ${serialized}`);
|
|
165949
|
-
} else if (event.type === "spawned") {
|
|
167018
|
+
if (event.type === "spawned") {
|
|
165950
167019
|
sessionLog(sessionId, `pi-historian[${passLabel}] spawned pid=${event.pid ?? "?"} argv=${event.argv.length} args`);
|
|
165951
|
-
} else if (event.type === "first_event") {
|
|
165952
|
-
sessionLog(sessionId, `pi-historian[${passLabel}] first_event @${event.ms}ms type=${event.eventType}`);
|
|
165953
167020
|
} else if (event.type === "terminal") {
|
|
165954
167021
|
sessionLog(sessionId, `pi-historian[${passLabel}] terminal @${event.ms}ms stopReason=${event.stopReason ?? "?"} textLen=${event.textLength} hasToolCall=${event.hasToolCall}`);
|
|
165955
167022
|
} else if (event.type === "stderr") {
|
|
@@ -165959,6 +167026,21 @@ ${chunk.text}`, { stateFilePath });
|
|
|
165959
167026
|
}
|
|
165960
167027
|
} else if (event.type === "child_exit") {
|
|
165961
167028
|
sessionLog(sessionId, `pi-historian[${passLabel}] child_exit @${event.ms}ms code=${event.code} signal=${event.signal}`);
|
|
167029
|
+
} else if (traceRawEvents) {
|
|
167030
|
+
if (event.type === "raw_event") {
|
|
167031
|
+
let serialized;
|
|
167032
|
+
try {
|
|
167033
|
+
serialized = JSON.stringify(event.event);
|
|
167034
|
+
} catch {
|
|
167035
|
+
serialized = "[unserializable]";
|
|
167036
|
+
}
|
|
167037
|
+
if (serialized.length > 4000) {
|
|
167038
|
+
serialized = `${serialized.slice(0, 4000)}…[truncated ${serialized.length - 4000} chars]`;
|
|
167039
|
+
}
|
|
167040
|
+
sessionLog(sessionId, `pi-historian[${passLabel}] raw_event @${event.ms}ms type=${event.eventType ?? "?"}: ${serialized}`);
|
|
167041
|
+
} else if (event.type === "first_event") {
|
|
167042
|
+
sessionLog(sessionId, `pi-historian[${passLabel}] first_event @${event.ms}ms type=${event.eventType}`);
|
|
167043
|
+
}
|
|
165962
167044
|
}
|
|
165963
167045
|
} catch {}
|
|
165964
167046
|
};
|
|
@@ -166373,16 +167455,7 @@ function clearOldReasoningPi(args) {
|
|
|
166373
167455
|
return { cleared, newWatermark };
|
|
166374
167456
|
}
|
|
166375
167457
|
function replayClearedReasoningPi(args) {
|
|
166376
|
-
const {
|
|
166377
|
-
db,
|
|
166378
|
-
sessionId,
|
|
166379
|
-
messages,
|
|
166380
|
-
messageIdToMaxTag,
|
|
166381
|
-
piMessageStableId,
|
|
166382
|
-
skipTypedReasoningCleanup
|
|
166383
|
-
} = args;
|
|
166384
|
-
if (skipTypedReasoningCleanup)
|
|
166385
|
-
return 0;
|
|
167458
|
+
const { db, sessionId, messages, messageIdToMaxTag, piMessageStableId } = args;
|
|
166386
167459
|
const meta3 = getOrCreateSessionMeta(db, sessionId);
|
|
166387
167460
|
const watermark = meta3.clearedReasoningThroughTag ?? 0;
|
|
166388
167461
|
if (watermark <= 0)
|
|
@@ -167082,19 +168155,6 @@ var TOOL_HEAVY_TURN_REMINDER_THRESHOLD = 5;
|
|
|
167082
168155
|
var TOOL_HEAVY_TURN_REMINDER_TEXT = `
|
|
167083
168156
|
|
|
167084
168157
|
<instruction name="ctx_reduce_turn_cleanup">Also drop via \`ctx_reduce\` things you don't need anymore from the last turn before continuing.</instruction>`;
|
|
167085
|
-
function resolveLiveModelId(ctx) {
|
|
167086
|
-
const model = ctx.model;
|
|
167087
|
-
if (!model)
|
|
167088
|
-
return;
|
|
167089
|
-
const providerID = model.provider;
|
|
167090
|
-
const modelID = model.id;
|
|
167091
|
-
if (typeof providerID !== "string" || typeof modelID !== "string") {
|
|
167092
|
-
return;
|
|
167093
|
-
}
|
|
167094
|
-
if (providerID.length === 0 || modelID.length === 0)
|
|
167095
|
-
return;
|
|
167096
|
-
return { providerID, modelID };
|
|
167097
|
-
}
|
|
167098
168158
|
var DEFAULT_CLEAR_REASONING_AGE = 50;
|
|
167099
168159
|
var lastEmergencyNotificationAtMs = new Map;
|
|
167100
168160
|
var EMERGENCY_NOTIFICATION_COOLDOWN_MS = 60000;
|
|
@@ -167107,6 +168167,9 @@ var recentReduceBySession = new Map;
|
|
|
167107
168167
|
var liveModelBySession = new Map;
|
|
167108
168168
|
var toolUsageSinceUserTurn = new Map;
|
|
167109
168169
|
var latestUserMessageBySession = new Map;
|
|
168170
|
+
function readPiSessionMessageById(ctx, messageId) {
|
|
168171
|
+
return readPiSessionMessages(ctx).find((message) => message.id === messageId) ?? null;
|
|
168172
|
+
}
|
|
167110
168173
|
function signalPiHistoryRefresh(sessionId) {
|
|
167111
168174
|
historyRefreshSessions.add(sessionId);
|
|
167112
168175
|
}
|
|
@@ -167307,8 +168370,15 @@ function registerPiContextHandler(pi, options) {
|
|
|
167307
168370
|
return;
|
|
167308
168371
|
}
|
|
167309
168372
|
sessionIdForError = sessionId;
|
|
168373
|
+
const rawMessageProvider = {
|
|
168374
|
+
readMessages: () => readPiSessionMessages(ctx),
|
|
168375
|
+
readMessageById: (messageId) => readPiSessionMessageById(ctx, messageId)
|
|
168376
|
+
};
|
|
168377
|
+
setRawMessageProvider(sessionId, rawMessageProvider);
|
|
168378
|
+
scheduleReconciliation(options.db, sessionId, readRawSessionMessages);
|
|
167310
168379
|
const latestUserId = findLatestUserMessageIdPi(event.messages);
|
|
167311
168380
|
if (latestUserId) {
|
|
168381
|
+
scheduleIncrementalIndex(options.db, sessionId, latestUserId, (_sessionId, messageId) => readPiSessionMessageById(ctx, messageId));
|
|
167312
168382
|
const previousUserId = latestUserMessageBySession.get(sessionId);
|
|
167313
168383
|
if (previousUserId !== latestUserId) {
|
|
167314
168384
|
onPiNewUserMessage({ db: options.db, sessionId });
|
|
@@ -167371,8 +168441,6 @@ function registerPiContextHandler(pi, options) {
|
|
|
167371
168441
|
}
|
|
167372
168442
|
const isCacheBusting = historyRefreshSessions.has(sessionId);
|
|
167373
168443
|
sessionLog(sessionId, `pi transform: usage=${usagePercentage.toFixed(1)}% (${usageInputTokens} tokens, limit=${usageContextLimit ?? "?"}) decision=${schedulerDecision}${forceMaterialization ? " force=true" : ""}${isEmergency ? " EMERGENCY=true" : ""}${isCacheBusting ? " busting=true" : ""}`);
|
|
167374
|
-
const liveModelId = resolveLiveModelId(ctx);
|
|
167375
|
-
const skipTypedReasoningCleanup = liveModelId ? modelRequiresInterleavedReasoning(liveModelId) : false;
|
|
167376
168444
|
const entryIds = collectMessageEntryIds(ctx, event.messages.length, sessionId);
|
|
167377
168445
|
const result = await runPipeline({
|
|
167378
168446
|
db: options.db,
|
|
@@ -167389,8 +168457,7 @@ function registerPiContextHandler(pi, options) {
|
|
|
167389
168457
|
forceMaterialization: forceMaterialization || isEmergency,
|
|
167390
168458
|
isCacheBusting,
|
|
167391
168459
|
reasoningClearing: {
|
|
167392
|
-
clearReasoningAge: options.heuristics?.clearReasoningAge ?? DEFAULT_CLEAR_REASONING_AGE
|
|
167393
|
-
skipTypedReasoningCleanup
|
|
168460
|
+
clearReasoningAge: options.heuristics?.clearReasoningAge ?? DEFAULT_CLEAR_REASONING_AGE
|
|
167394
168461
|
},
|
|
167395
168462
|
temporalAwareness: options.injection?.temporalAwareness === true
|
|
167396
168463
|
});
|
|
@@ -167738,7 +168805,10 @@ async function runPipeline(args) {
|
|
|
167738
168805
|
consumePendingMaterialization(args.sessionId);
|
|
167739
168806
|
}
|
|
167740
168807
|
}
|
|
167741
|
-
|
|
168808
|
+
const flushedSliceTags = getTagsByNumbers(args.db, args.sessionId, [
|
|
168809
|
+
...targets.keys()
|
|
168810
|
+
]);
|
|
168811
|
+
applyFlushedStatuses(args.sessionId, args.db, targets, flushedSliceTags);
|
|
167742
168812
|
const messageIdToMaxTag = buildMessageIdToMaxTag(targets);
|
|
167743
168813
|
if (args.reasoningClearing) {
|
|
167744
168814
|
try {
|
|
@@ -167747,8 +168817,7 @@ async function runPipeline(args) {
|
|
|
167747
168817
|
sessionId: args.sessionId,
|
|
167748
168818
|
messages: args.messages,
|
|
167749
168819
|
messageIdToMaxTag,
|
|
167750
|
-
piMessageStableId
|
|
167751
|
-
skipTypedReasoningCleanup: args.reasoningClearing.skipTypedReasoningCleanup
|
|
168820
|
+
piMessageStableId
|
|
167752
168821
|
});
|
|
167753
168822
|
const inlineReplay = replayStrippedInlineThinkingPi({
|
|
167754
168823
|
db: args.db,
|
|
@@ -167765,7 +168834,8 @@ async function runPipeline(args) {
|
|
|
167765
168834
|
}
|
|
167766
168835
|
}
|
|
167767
168836
|
try {
|
|
167768
|
-
const
|
|
168837
|
+
const targetTagNumbers = [...targets.keys()];
|
|
168838
|
+
const tags = getTagsByNumbers(args.db, args.sessionId, targetTagNumbers);
|
|
167769
168839
|
const replayed = replayCavemanCompression(args.sessionId, args.db, targets, tags);
|
|
167770
168840
|
if (replayed > 0) {
|
|
167771
168841
|
sessionLog(args.sessionId, `pi caveman replay: ${replayed} tags re-compressed from source`);
|
|
@@ -167790,7 +168860,7 @@ async function runPipeline(args) {
|
|
|
167790
168860
|
sessionLog(args.sessionId, `pi heuristic cleanup failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
|
|
167791
168861
|
}
|
|
167792
168862
|
}
|
|
167793
|
-
if (args.reasoningClearing &&
|
|
168863
|
+
if (args.reasoningClearing && (args.schedulerDecision === "execute" || args.forceMaterialization === true)) {
|
|
167794
168864
|
try {
|
|
167795
168865
|
const clearOutcome = clearOldReasoningPi({
|
|
167796
168866
|
messages: args.messages,
|
|
@@ -167859,7 +168929,7 @@ function applyRollingNudge(args) {
|
|
|
167859
168929
|
inputTokens: piUsage.tokens,
|
|
167860
168930
|
contextLimit: piUsage.contextWindow
|
|
167861
168931
|
};
|
|
167862
|
-
const tags =
|
|
168932
|
+
const tags = getActiveTagsBySession(db, sessionId);
|
|
167863
168933
|
const messagesSinceLastUser = countMessagesSinceLastUserPi(messages);
|
|
167864
168934
|
const nudge = nudgerFn(sessionId, usage, db, getTopNBySize, tags, messagesSinceLastUser, undefined);
|
|
167865
168935
|
if (!nudge)
|
|
@@ -167989,6 +169059,7 @@ function clearContextHandlerSession(sessionId) {
|
|
|
167989
169059
|
liveModelBySession.delete(sessionId);
|
|
167990
169060
|
toolUsageSinceUserTurn.delete(sessionId);
|
|
167991
169061
|
latestUserMessageBySession.delete(sessionId);
|
|
169062
|
+
clearSessionTracking(sessionId);
|
|
167992
169063
|
clearPiCompressorState(sessionId);
|
|
167993
169064
|
}
|
|
167994
169065
|
|
|
@@ -168038,7 +169109,7 @@ init_logger();
|
|
|
168038
169109
|
init_data_path();
|
|
168039
169110
|
init_logger();
|
|
168040
169111
|
await init_sqlite();
|
|
168041
|
-
import { join as
|
|
169112
|
+
import { join as join11 } from "node:path";
|
|
168042
169113
|
var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
168043
169114
|
function randomBase62(length) {
|
|
168044
169115
|
const chars = [];
|
|
@@ -168059,7 +169130,7 @@ function generatePartId(timestampMs, counter = 0n) {
|
|
|
168059
169130
|
return generateId("prt", timestampMs, counter);
|
|
168060
169131
|
}
|
|
168061
169132
|
function getOpenCodeDbPath3() {
|
|
168062
|
-
return
|
|
169133
|
+
return join11(getDataDir(), "opencode", "opencode.db");
|
|
168063
169134
|
}
|
|
168064
169135
|
var cachedWriteDb = null;
|
|
168065
169136
|
var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
|
|
@@ -168612,11 +169683,11 @@ async function runCompressorPass2(args) {
|
|
|
168612
169683
|
}
|
|
168613
169684
|
|
|
168614
169685
|
// ../plugin/src/hooks/magic-context/compartment-runner-historian.ts
|
|
168615
|
-
import { mkdirSync as
|
|
169686
|
+
import { mkdirSync as mkdirSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
168616
169687
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
168617
|
-
import { join as
|
|
169688
|
+
import { join as join12 } from "node:path";
|
|
168618
169689
|
init_magic_context();
|
|
168619
|
-
var HISTORIAN_RESPONSE_DUMP_DIR =
|
|
169690
|
+
var HISTORIAN_RESPONSE_DUMP_DIR = join12(tmpdir3(), "magic-context-historian");
|
|
168620
169691
|
var MAX_HISTORIAN_RETRIES = 2;
|
|
168621
169692
|
async function runValidatedHistorianPass(args) {
|
|
168622
169693
|
const firstRun = await runHistorianPrompt({
|
|
@@ -168857,11 +169928,11 @@ function cleanupHistorianDump(sessionId, dumpPath) {
|
|
|
168857
169928
|
}
|
|
168858
169929
|
function dumpHistorianResponse(sessionId, label, text) {
|
|
168859
169930
|
try {
|
|
168860
|
-
|
|
169931
|
+
mkdirSync5(HISTORIAN_RESPONSE_DUMP_DIR, { recursive: true });
|
|
168861
169932
|
const safeSessionId = sanitizeDumpName(sessionId);
|
|
168862
169933
|
const safeLabel = sanitizeDumpName(label);
|
|
168863
|
-
const dumpPath =
|
|
168864
|
-
|
|
169934
|
+
const dumpPath = join12(HISTORIAN_RESPONSE_DUMP_DIR, `${safeSessionId}-${safeLabel}-${Date.now()}.xml`);
|
|
169935
|
+
writeFileSync3(dumpPath, text, "utf8");
|
|
168865
169936
|
sessionLog(sessionId, "compartment agent: historian response dumped", {
|
|
168866
169937
|
label,
|
|
168867
169938
|
dumpPath
|
|
@@ -169872,8 +170943,8 @@ function createPiRecompClient(args) {
|
|
|
169872
170943
|
function readPathId(input) {
|
|
169873
170944
|
if (typeof input !== "object" || input === null)
|
|
169874
170945
|
return "";
|
|
169875
|
-
const
|
|
169876
|
-
return typeof
|
|
170946
|
+
const path5 = input.path;
|
|
170947
|
+
return typeof path5?.id === "string" ? path5.id : "";
|
|
169877
170948
|
}
|
|
169878
170949
|
function readBody(input) {
|
|
169879
170950
|
if (typeof input !== "object" || input === null)
|
|
@@ -170028,7 +171099,7 @@ import {
|
|
|
170028
171099
|
// package.json
|
|
170029
171100
|
var package_default = {
|
|
170030
171101
|
name: "@cortexkit/pi-magic-context",
|
|
170031
|
-
version: "0.
|
|
171102
|
+
version: "0.17.0",
|
|
170032
171103
|
type: "module",
|
|
170033
171104
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
170034
171105
|
main: "dist/index.js",
|
|
@@ -170565,14 +171636,14 @@ function readHistorianState(db, sessionId, meta3) {
|
|
|
170565
171636
|
|
|
170566
171637
|
// src/config/index.ts
|
|
170567
171638
|
init_magic_context();
|
|
170568
|
-
import { existsSync as
|
|
171639
|
+
import { existsSync as existsSync8, readFileSync as readFileSync3 } from "node:fs";
|
|
170569
171640
|
import { homedir as homedir4 } from "node:os";
|
|
170570
|
-
import { join as
|
|
171641
|
+
import { join as join13 } from "node:path";
|
|
170571
171642
|
|
|
170572
171643
|
// ../plugin/src/config/variable.ts
|
|
170573
|
-
import { existsSync as
|
|
171644
|
+
import { existsSync as existsSync7, readFileSync as readFileSync2 } from "node:fs";
|
|
170574
171645
|
import { homedir as homedir3 } from "node:os";
|
|
170575
|
-
import { dirname as
|
|
171646
|
+
import { dirname as dirname3, isAbsolute, resolve } from "node:path";
|
|
170576
171647
|
var ENV_PATTERN = /\{env:([^}]+)\}/g;
|
|
170577
171648
|
var FILE_PATTERN = /\{file:([^}]+)\}/g;
|
|
170578
171649
|
function substituteConfigVariables(input) {
|
|
@@ -170591,7 +171662,7 @@ function substituteConfigVariables(input) {
|
|
|
170591
171662
|
if (fileMatches.length === 0) {
|
|
170592
171663
|
return { text, warnings };
|
|
170593
171664
|
}
|
|
170594
|
-
const configDir = input.configPath ?
|
|
171665
|
+
const configDir = input.configPath ? dirname3(input.configPath) : process.cwd();
|
|
170595
171666
|
let output = "";
|
|
170596
171667
|
let cursor = 0;
|
|
170597
171668
|
for (const match of fileMatches) {
|
|
@@ -170613,7 +171684,7 @@ function substituteConfigVariables(input) {
|
|
|
170613
171684
|
} else if (!isAbsolute(filePath)) {
|
|
170614
171685
|
filePath = resolve(configDir, filePath);
|
|
170615
171686
|
}
|
|
170616
|
-
if (!
|
|
171687
|
+
if (!existsSync7(filePath)) {
|
|
170617
171688
|
warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
|
|
170618
171689
|
continue;
|
|
170619
171690
|
}
|
|
@@ -170635,38 +171706,38 @@ function substituteConfigVariables(input) {
|
|
|
170635
171706
|
var import_comment_json = __toESM(require_src2(), 1);
|
|
170636
171707
|
var CONFIG_FILE_NAME = "magic-context";
|
|
170637
171708
|
function getProjectConfigPaths(cwd) {
|
|
170638
|
-
const basePath =
|
|
171709
|
+
const basePath = join13(cwd, ".pi", CONFIG_FILE_NAME);
|
|
170639
171710
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
170640
171711
|
}
|
|
170641
171712
|
function getUserConfigPaths() {
|
|
170642
171713
|
const home = process.env.HOME ?? homedir4();
|
|
170643
|
-
const basePath =
|
|
171714
|
+
const basePath = join13(home, ".pi", "agent", CONFIG_FILE_NAME);
|
|
170644
171715
|
return [`${basePath}.jsonc`, `${basePath}.json`];
|
|
170645
171716
|
}
|
|
170646
171717
|
function resolveFirstExisting(paths) {
|
|
170647
|
-
return paths.find((
|
|
171718
|
+
return paths.find((path5) => existsSync8(path5));
|
|
170648
171719
|
}
|
|
170649
|
-
function loadConfigFile(
|
|
171720
|
+
function loadConfigFile(path5, scope) {
|
|
170650
171721
|
try {
|
|
170651
|
-
const rawText = readFileSync3(
|
|
171722
|
+
const rawText = readFileSync3(path5, "utf-8");
|
|
170652
171723
|
const substituted = substituteConfigVariables({
|
|
170653
171724
|
text: rawText,
|
|
170654
|
-
configPath:
|
|
171725
|
+
configPath: path5
|
|
170655
171726
|
});
|
|
170656
171727
|
return {
|
|
170657
|
-
path:
|
|
171728
|
+
path: path5,
|
|
170658
171729
|
scope,
|
|
170659
171730
|
config: import_comment_json.parse(substituted.text),
|
|
170660
|
-
warnings: substituted.warnings.map((warning) => `${
|
|
171731
|
+
warnings: substituted.warnings.map((warning) => `${path5}: ${warning}`)
|
|
170661
171732
|
};
|
|
170662
171733
|
} catch (error48) {
|
|
170663
171734
|
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
170664
171735
|
return {
|
|
170665
|
-
path:
|
|
171736
|
+
path: path5,
|
|
170666
171737
|
scope,
|
|
170667
171738
|
config: {},
|
|
170668
171739
|
warnings: [
|
|
170669
|
-
`${
|
|
171740
|
+
`${path5}: failed to load config: ${message}; using defaults for this file.`
|
|
170670
171741
|
]
|
|
170671
171742
|
};
|
|
170672
171743
|
}
|
|
@@ -170796,8 +171867,8 @@ function stripTagPrefixFromAssistantMessage(message) {
|
|
|
170796
171867
|
|
|
170797
171868
|
// src/system-prompt.ts
|
|
170798
171869
|
import { createHash as createHash4 } from "node:crypto";
|
|
170799
|
-
import { existsSync as
|
|
170800
|
-
import { join as
|
|
171870
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4, realpathSync } from "node:fs";
|
|
171871
|
+
import { join as join14, resolve as resolve2, sep } from "node:path";
|
|
170801
171872
|
|
|
170802
171873
|
// ../plugin/src/agents/magic-context-prompt.ts
|
|
170803
171874
|
function getToolHistoryGuidance(dropToolStructure) {
|
|
@@ -170899,9 +171970,9 @@ var DOC_FILES = ["ARCHITECTURE.md", "STRUCTURE.md"];
|
|
|
170899
171970
|
function readProjectDocs(directory) {
|
|
170900
171971
|
const sections = [];
|
|
170901
171972
|
for (const filename of DOC_FILES) {
|
|
170902
|
-
const filePath =
|
|
171973
|
+
const filePath = join14(directory, filename);
|
|
170903
171974
|
try {
|
|
170904
|
-
if (
|
|
171975
|
+
if (existsSync9(filePath)) {
|
|
170905
171976
|
const content = readFileSync4(filePath, "utf-8").trim();
|
|
170906
171977
|
if (content.length > 0) {
|
|
170907
171978
|
sections.push(`<${filename}>
|
|
@@ -170945,7 +172016,7 @@ function buildKeyFilesBlock(db, sessionId, directory, tokenBudget) {
|
|
|
170945
172016
|
log(`[magic-context-pi] key file path escapes project root, skipping: ${entry.filePath}`);
|
|
170946
172017
|
continue;
|
|
170947
172018
|
}
|
|
170948
|
-
if (!
|
|
172019
|
+
if (!existsSync9(absPath))
|
|
170949
172020
|
continue;
|
|
170950
172021
|
let realPath;
|
|
170951
172022
|
try {
|
|
@@ -176022,7 +177093,7 @@ function registerMagicContextTools(pi, opts) {
|
|
|
176022
177093
|
}
|
|
176023
177094
|
|
|
176024
177095
|
// src/index.ts
|
|
176025
|
-
var
|
|
177096
|
+
var PREFIX2 = "[magic-context][pi]";
|
|
176026
177097
|
function persistPiMessageEndModelMeta(args) {
|
|
176027
177098
|
if (!args.message || typeof args.message !== "object")
|
|
176028
177099
|
return;
|
|
@@ -176039,14 +177110,14 @@ function persistPiMessageEndModelMeta(args) {
|
|
|
176039
177110
|
}
|
|
176040
177111
|
}
|
|
176041
177112
|
function info(message, data) {
|
|
176042
|
-
log(`${
|
|
177113
|
+
log(`${PREFIX2} ${message}`, data);
|
|
176043
177114
|
}
|
|
176044
177115
|
function warn(message, data) {
|
|
176045
|
-
log(`${
|
|
177116
|
+
log(`${PREFIX2} WARN ${message}`, data);
|
|
176046
177117
|
}
|
|
176047
177118
|
var PLUGIN_VERSION = (() => {
|
|
176048
177119
|
try {
|
|
176049
|
-
const req =
|
|
177120
|
+
const req = createRequire2(import.meta.url);
|
|
176050
177121
|
return req("../package.json").version;
|
|
176051
177122
|
} catch {
|
|
176052
177123
|
return "0.0.0";
|
|
@@ -176127,7 +177198,7 @@ function resolveDreamerFromConfig(config2) {
|
|
|
176127
177198
|
}
|
|
176128
177199
|
async function src_default2(pi) {
|
|
176129
177200
|
const storageDir = getMagicContextStorageDir();
|
|
176130
|
-
const dbPath =
|
|
177201
|
+
const dbPath = join15(storageDir, "context.db");
|
|
176131
177202
|
let db;
|
|
176132
177203
|
try {
|
|
176133
177204
|
db = openDatabase();
|
|
@@ -176381,6 +177452,11 @@ ${block}` : event.systemPrompt;
|
|
|
176381
177452
|
const sessionId = sm?.getSessionId?.();
|
|
176382
177453
|
if (typeof sessionId !== "string" || sessionId.length === 0)
|
|
176383
177454
|
return;
|
|
177455
|
+
const rawMessages = readPiSessionMessages(ctx);
|
|
177456
|
+
const latest = rawMessages[rawMessages.length - 1];
|
|
177457
|
+
if (latest?.role === "assistant" && latest.id.length > 0) {
|
|
177458
|
+
scheduleIncrementalIndex(db, sessionId, latest.id, () => latest);
|
|
177459
|
+
}
|
|
176384
177460
|
persistPiMessageEndModelMeta({
|
|
176385
177461
|
db,
|
|
176386
177462
|
sessionId,
|