@cortexkit/pi-magic-context 0.44.0 → 0.44.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/historian-calibration-extension.js +17 -0
- package/dist/{index-tfzybajk.js → index-59dmj4zs.js} +4 -1
- package/dist/{index-jscq7067.js → index-5fw91enm.js} +1 -1
- package/dist/{index-mmkdxa5j.js → index-97e5fzy3.js} +1 -1
- package/dist/{index-8ytss1hp.js → index-esnhck8v.js} +14869 -14266
- package/dist/{index-2kj55q4e.js → index-gsff513e.js} +263 -51
- package/dist/index-n8kg008j.js +245 -0
- package/dist/index.js +1935 -877
- package/dist/{message-time-backfill-3rp0w2z9.js → message-time-backfill-5yrp95cx.js} +2 -2
- package/dist/{read-session-chunk-2s116ah5.js → read-session-chunk-zhtcx9f1.js} +4 -2
- package/dist/{safe-notification-target-pd09ybr0.js → safe-notification-target-y3hg2m7p.js} +2 -2
- package/dist/subagent-entry.js +22 -6
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getHarness,
|
|
3
|
+
harnessOwnsOpenCodeStore,
|
|
3
4
|
log
|
|
4
|
-
} from "./index-
|
|
5
|
+
} from "./index-59dmj4zs.js";
|
|
5
6
|
|
|
6
7
|
// ../plugin/src/features/magic-context/reclaim-protection.ts
|
|
7
8
|
var CTX_REDUCE_KEEP = 3;
|
|
@@ -2233,6 +2234,7 @@ function claimOpenCodeDbDiagnosticOnce(surface, resolution) {
|
|
|
2233
2234
|
}
|
|
2234
2235
|
|
|
2235
2236
|
// ../plugin/src/shared/sqlite.ts
|
|
2237
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2236
2238
|
var reportSlowPrivilegedWrite;
|
|
2237
2239
|
function registerSlowWriteReporter(reporter) {
|
|
2238
2240
|
reportSlowPrivilegedWrite = reporter;
|
|
@@ -2287,6 +2289,62 @@ var sqliteModule = await loadSqliteModule(detectedRuntime);
|
|
|
2287
2289
|
var DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
|
|
2288
2290
|
var trackedSqliteConnections = new Map;
|
|
2289
2291
|
var nextSqliteConnectionSequence = 1;
|
|
2292
|
+
function installTransactionRouting(db, readonly) {
|
|
2293
|
+
const nativeExec = db.exec.bind(db);
|
|
2294
|
+
Object.defineProperty(db, "exec", {
|
|
2295
|
+
configurable: true,
|
|
2296
|
+
writable: true,
|
|
2297
|
+
value: (sql) => {
|
|
2298
|
+
if (/^\s*BEGIN\s+(?:IMMEDIATE|EXCLUSIVE)(?:\s+TRANSACTION)?\s*;?\s*$/i.test(sql)) {
|
|
2299
|
+
retryAcquisition(() => nativeExec(sql), sql.trim());
|
|
2300
|
+
return db;
|
|
2301
|
+
}
|
|
2302
|
+
return nativeExec(sql);
|
|
2303
|
+
}
|
|
2304
|
+
});
|
|
2305
|
+
Object.defineProperty(db, "transaction", {
|
|
2306
|
+
configurable: true,
|
|
2307
|
+
writable: true,
|
|
2308
|
+
value: (fn) => {
|
|
2309
|
+
const make = (mode) => function(...args) {
|
|
2310
|
+
const nested = isInTransaction(db);
|
|
2311
|
+
const savepoint = "mc_tx_sp";
|
|
2312
|
+
db.exec(nested ? `SAVEPOINT ${savepoint}` : `BEGIN ${mode}`);
|
|
2313
|
+
try {
|
|
2314
|
+
const result = fn.apply(this, args);
|
|
2315
|
+
db.exec(nested ? `RELEASE ${savepoint}` : "COMMIT");
|
|
2316
|
+
return result;
|
|
2317
|
+
} catch (error) {
|
|
2318
|
+
if (isInTransaction(db)) {
|
|
2319
|
+
if (nested) {
|
|
2320
|
+
db.exec(`ROLLBACK TO ${savepoint}`);
|
|
2321
|
+
db.exec(`RELEASE ${savepoint}`);
|
|
2322
|
+
} else
|
|
2323
|
+
db.exec("ROLLBACK");
|
|
2324
|
+
}
|
|
2325
|
+
throw error;
|
|
2326
|
+
}
|
|
2327
|
+
};
|
|
2328
|
+
const defaultTransaction = make(readonly ? "DEFERRED" : "IMMEDIATE");
|
|
2329
|
+
const variants = {
|
|
2330
|
+
default: defaultTransaction,
|
|
2331
|
+
deferred: make("DEFERRED"),
|
|
2332
|
+
immediate: make("IMMEDIATE"),
|
|
2333
|
+
exclusive: make("EXCLUSIVE"),
|
|
2334
|
+
database: db
|
|
2335
|
+
};
|
|
2336
|
+
for (const transaction of [
|
|
2337
|
+
variants.default,
|
|
2338
|
+
variants.deferred,
|
|
2339
|
+
variants.immediate,
|
|
2340
|
+
variants.exclusive
|
|
2341
|
+
]) {
|
|
2342
|
+
Object.assign(transaction, variants);
|
|
2343
|
+
}
|
|
2344
|
+
return defaultTransaction;
|
|
2345
|
+
}
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2290
2348
|
function trackSqliteConnection(db, filename, options) {
|
|
2291
2349
|
const originalClose = db.close.bind(db);
|
|
2292
2350
|
const sequence = nextSqliteConnectionSequence++;
|
|
@@ -2295,6 +2353,7 @@ function trackSqliteConnection(db, filename, options) {
|
|
|
2295
2353
|
filename: typeof filename === "string" ? filename : Buffer.isBuffer(filename) ? "<buffer>" : ":memory:",
|
|
2296
2354
|
readonly: Boolean(options) && typeof options === "object" && (options.readonly === true || options.readOnly === true)
|
|
2297
2355
|
};
|
|
2356
|
+
installTransactionRouting(db, metadata.readonly);
|
|
2298
2357
|
Object.defineProperty(db, "close", {
|
|
2299
2358
|
configurable: true,
|
|
2300
2359
|
value: (...args) => {
|
|
@@ -2318,7 +2377,6 @@ var TrackedDatabase = new Proxy(DatabaseImpl, {
|
|
|
2318
2377
|
}
|
|
2319
2378
|
});
|
|
2320
2379
|
function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
2321
|
-
const SAVEPOINT = "mc_tx_sp";
|
|
2322
2380
|
|
|
2323
2381
|
class NodeSqliteDatabase extends DatabaseSync {
|
|
2324
2382
|
constructor(filename, options) {
|
|
@@ -2337,47 +2395,47 @@ function buildNodeSqliteDatabaseClass(DatabaseSync) {
|
|
|
2337
2395
|
}
|
|
2338
2396
|
return stmt;
|
|
2339
2397
|
}
|
|
2340
|
-
transaction(fn) {
|
|
2341
|
-
const self = this;
|
|
2342
|
-
const execute = (mode, receiver, args) => {
|
|
2343
|
-
const nested = self.isTransaction === true;
|
|
2344
|
-
self.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : `BEGIN${mode ? ` ${mode}` : ""}`);
|
|
2345
|
-
try {
|
|
2346
|
-
const result = fn.apply(receiver, args);
|
|
2347
|
-
self.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
|
|
2348
|
-
return result;
|
|
2349
|
-
} catch (error) {
|
|
2350
|
-
if (nested) {
|
|
2351
|
-
self.exec(`ROLLBACK TO ${SAVEPOINT}`);
|
|
2352
|
-
self.exec(`RELEASE ${SAVEPOINT}`);
|
|
2353
|
-
} else {
|
|
2354
|
-
self.exec("ROLLBACK");
|
|
2355
|
-
}
|
|
2356
|
-
throw error;
|
|
2357
|
-
}
|
|
2358
|
-
};
|
|
2359
|
-
const wrapped = function(...args) {
|
|
2360
|
-
return execute("", this, args);
|
|
2361
|
-
};
|
|
2362
|
-
wrapped.default = function(...args) {
|
|
2363
|
-
return execute("", this, args);
|
|
2364
|
-
};
|
|
2365
|
-
wrapped.deferred = function(...args) {
|
|
2366
|
-
return execute("DEFERRED", this, args);
|
|
2367
|
-
};
|
|
2368
|
-
wrapped.immediate = function(...args) {
|
|
2369
|
-
return execute("IMMEDIATE", this, args);
|
|
2370
|
-
};
|
|
2371
|
-
wrapped.exclusive = function(...args) {
|
|
2372
|
-
return execute("EXCLUSIVE", this, args);
|
|
2373
|
-
};
|
|
2374
|
-
return wrapped;
|
|
2375
|
-
}
|
|
2376
2398
|
}
|
|
2377
2399
|
return NodeSqliteDatabase;
|
|
2378
2400
|
}
|
|
2379
2401
|
var Database = TrackedDatabase;
|
|
2380
2402
|
var privilegeDepth = new WeakMap;
|
|
2403
|
+
var transformPassScope = new AsyncLocalStorage;
|
|
2404
|
+
function isTransientSqliteError(error) {
|
|
2405
|
+
if (!error || typeof error !== "object")
|
|
2406
|
+
return false;
|
|
2407
|
+
const value = error;
|
|
2408
|
+
return typeof value.code === "string" && /^(SQLITE_BUSY|SQLITE_LOCKED)(_|$)/.test(value.code) || typeof value.errcode === "number" && [5, 6].includes(value.errcode & 255);
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
class SqliteAcquisitionBusyError extends Error {
|
|
2412
|
+
code = "SQLITE_BUSY";
|
|
2413
|
+
stage;
|
|
2414
|
+
constructor(cause, stage = "BEGIN IMMEDIATE") {
|
|
2415
|
+
super("SQLite writer acquisition remained busy after 3 attempts", { cause });
|
|
2416
|
+
this.name = "SqliteAcquisitionBusyError";
|
|
2417
|
+
this.stage = stage;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
function retryAcquisition(acquire, stage) {
|
|
2421
|
+
if (!transformPassScope.getStore()?.active) {
|
|
2422
|
+
acquire();
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
const delays = [500, 1000];
|
|
2426
|
+
for (let attempt = 0;; attempt++) {
|
|
2427
|
+
try {
|
|
2428
|
+
acquire();
|
|
2429
|
+
return;
|
|
2430
|
+
} catch (error) {
|
|
2431
|
+
if (error instanceof SqliteAcquisitionBusyError || !isTransientSqliteError(error))
|
|
2432
|
+
throw error;
|
|
2433
|
+
if (attempt === delays.length)
|
|
2434
|
+
throw new SqliteAcquisitionBusyError(error, stage);
|
|
2435
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, delays[attempt]);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2381
2439
|
function isInTransaction(db) {
|
|
2382
2440
|
const candidate = db;
|
|
2383
2441
|
return candidate.inTransaction === true || candidate.isTransaction === true;
|
|
@@ -2390,7 +2448,7 @@ function withPrivilegedWriter(db, operation) {
|
|
|
2390
2448
|
if (nested) {
|
|
2391
2449
|
db.exec(`SAVEPOINT ${savepoint}`);
|
|
2392
2450
|
} else {
|
|
2393
|
-
db.exec("BEGIN IMMEDIATE");
|
|
2451
|
+
retryAcquisition(() => db.exec("BEGIN IMMEDIATE"), "BEGIN IMMEDIATE");
|
|
2394
2452
|
}
|
|
2395
2453
|
privilegeDepth.set(db, previousDepth + 1);
|
|
2396
2454
|
try {
|
|
@@ -2441,7 +2499,7 @@ function closeQuietly(db) {
|
|
|
2441
2499
|
|
|
2442
2500
|
// ../plugin/src/hooks/magic-context/read-session-db.ts
|
|
2443
2501
|
function openCodeDbExists() {
|
|
2444
|
-
return openCodeDbPathExists(resolveOpenCodeDbPath());
|
|
2502
|
+
return harnessOwnsOpenCodeStore() && openCodeDbPathExists(resolveOpenCodeDbPath());
|
|
2445
2503
|
}
|
|
2446
2504
|
var cachedReadOnlyDb = null;
|
|
2447
2505
|
function closeCachedReadOnlyDb() {
|
|
@@ -2457,6 +2515,9 @@ function closeCachedReadOnlyDb() {
|
|
|
2457
2515
|
}
|
|
2458
2516
|
}
|
|
2459
2517
|
function getReadOnlySessionDb() {
|
|
2518
|
+
if (!harnessOwnsOpenCodeStore()) {
|
|
2519
|
+
throw new Error("OpenCode session database is not readable from a Pi-compatible process; its history lives in Pi sessions");
|
|
2520
|
+
}
|
|
2460
2521
|
const resolution = resolveOpenCodeDbPath();
|
|
2461
2522
|
const dbPath = resolution.path;
|
|
2462
2523
|
if (!openCodeDbPathExists(resolution)) {
|
|
@@ -2499,7 +2560,7 @@ function logProbeFailureOnce(resolution, error) {
|
|
|
2499
2560
|
}
|
|
2500
2561
|
function getMessageTimesFromOpenCodeDb(sessionId, messageIds) {
|
|
2501
2562
|
const result = new Map;
|
|
2502
|
-
if (messageIds.length === 0)
|
|
2563
|
+
if (messageIds.length === 0 || !harnessOwnsOpenCodeStore())
|
|
2503
2564
|
return result;
|
|
2504
2565
|
try {
|
|
2505
2566
|
withReadOnlySessionDb((db) => {
|
|
@@ -2606,11 +2667,23 @@ function readRawSessionMessagesFromDb(db, sessionId) {
|
|
|
2606
2667
|
});
|
|
2607
2668
|
}
|
|
2608
2669
|
function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER) {
|
|
2670
|
+
const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark);
|
|
2671
|
+
if (messageRows.length === 0)
|
|
2672
|
+
return [];
|
|
2673
|
+
const placeholders = messageRows.map(() => "?").join(", ");
|
|
2674
|
+
const partRows = db.prepare(`SELECT message_id, data, time_updated
|
|
2675
|
+
FROM part
|
|
2676
|
+
WHERE +session_id = ?
|
|
2677
|
+
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
2678
|
+
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
2679
|
+
return assembleRawMessagePage(messageRows, partRows);
|
|
2680
|
+
}
|
|
2681
|
+
function readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark) {
|
|
2609
2682
|
const remaining = Math.max(0, Math.floor(finalWatermark) - Math.floor(afterOrdinal));
|
|
2610
2683
|
const pageSize = Math.min(Math.max(1, Math.floor(limit)), remaining);
|
|
2611
2684
|
if (pageSize === 0)
|
|
2612
2685
|
return [];
|
|
2613
|
-
|
|
2686
|
+
return db.prepare(`SELECT id, data, time_created, time_updated
|
|
2614
2687
|
FROM message
|
|
2615
2688
|
WHERE session_id = ?
|
|
2616
2689
|
AND NOT (
|
|
@@ -2626,14 +2699,8 @@ function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, fin
|
|
|
2626
2699
|
...row,
|
|
2627
2700
|
ordinal: Math.floor(afterOrdinal) + index + 1
|
|
2628
2701
|
}));
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
const placeholders = messageRows.map(() => "?").join(", ");
|
|
2632
|
-
const partRows = db.prepare(`SELECT message_id, data, time_updated
|
|
2633
|
-
FROM part
|
|
2634
|
-
WHERE +session_id = ?
|
|
2635
|
-
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
2636
|
-
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
2702
|
+
}
|
|
2703
|
+
function assembleRawMessagePage(messageRows, partRows) {
|
|
2637
2704
|
const partsByMessageId = new Map;
|
|
2638
2705
|
for (const part of partRows) {
|
|
2639
2706
|
const list = partsByMessageId.get(part.message_id) ?? [];
|
|
@@ -2652,6 +2719,49 @@ function readRawSessionMessagePageFromDb(db, sessionId, afterOrdinal, limit, fin
|
|
|
2652
2719
|
};
|
|
2653
2720
|
});
|
|
2654
2721
|
}
|
|
2722
|
+
var RAW_SUMMARY_TEXT_MAX_CHARS = 8192;
|
|
2723
|
+
var RAW_SUMMARY_ARG_MAX_CHARS = 512;
|
|
2724
|
+
var RAW_SUMMARY_TOOL_INPUT_KEYS = [
|
|
2725
|
+
"description",
|
|
2726
|
+
"filePath",
|
|
2727
|
+
"path",
|
|
2728
|
+
"pattern",
|
|
2729
|
+
"query",
|
|
2730
|
+
"symbol",
|
|
2731
|
+
"module",
|
|
2732
|
+
"action"
|
|
2733
|
+
];
|
|
2734
|
+
function summaryStringField(jsonPath) {
|
|
2735
|
+
return `CASE WHEN json_type(data, '${jsonPath}') = 'text' THEN substr(json_extract(data, '${jsonPath}'), 1, ${RAW_SUMMARY_ARG_MAX_CHARS}) END`;
|
|
2736
|
+
}
|
|
2737
|
+
var RAW_SUMMARY_PART_DATA_SQL = `CASE
|
|
2738
|
+
WHEN json_extract(data, '$.type') = 'text'
|
|
2739
|
+
THEN json_set(data, '$.text', substr(json_extract(data, '$.text'), 1, ${RAW_SUMMARY_TEXT_MAX_CHARS}))
|
|
2740
|
+
ELSE json_object(
|
|
2741
|
+
'type', 'tool',
|
|
2742
|
+
'tool', ${summaryStringField("$.tool")},
|
|
2743
|
+
'callID', ${summaryStringField("$.callID")},
|
|
2744
|
+
'state', json_object(
|
|
2745
|
+
'status', ${summaryStringField("$.state.status")},
|
|
2746
|
+
'input', json_object(${RAW_SUMMARY_TOOL_INPUT_KEYS.map((key) => `'${key}', ${summaryStringField(`$.state.input.${key}`)}`).join(", ")}),
|
|
2747
|
+
'metadata', json_object('description', ${summaryStringField("$.state.metadata.description")})
|
|
2748
|
+
)
|
|
2749
|
+
)
|
|
2750
|
+
END`;
|
|
2751
|
+
function readRawSessionMessageSummaryPageFromDb(db, sessionId, afterOrdinal, limit, finalWatermark = Number.MAX_SAFE_INTEGER) {
|
|
2752
|
+
const messageRows = readRawMessagePageRows(db, sessionId, afterOrdinal, limit, finalWatermark);
|
|
2753
|
+
if (messageRows.length === 0)
|
|
2754
|
+
return [];
|
|
2755
|
+
const placeholders = messageRows.map(() => "?").join(", ");
|
|
2756
|
+
const partRows = db.prepare(`SELECT message_id, ${RAW_SUMMARY_PART_DATA_SQL} AS data, time_updated
|
|
2757
|
+
FROM part
|
|
2758
|
+
WHERE +session_id = ?
|
|
2759
|
+
AND likelihood(message_id IN (${placeholders}), 0.000001)
|
|
2760
|
+
AND json_valid(data) = 1
|
|
2761
|
+
AND json_extract(data, '$.type') IN ('text', 'tool')
|
|
2762
|
+
ORDER BY message_id ASC, time_created ASC, id ASC`).all(sessionId, ...messageRows.map((row) => row.id)).filter(isRawPartRow);
|
|
2763
|
+
return assembleRawMessagePage(messageRows, partRows);
|
|
2764
|
+
}
|
|
2655
2765
|
function countRawSessionMessageOrdinalsFromDb(db, sessionId) {
|
|
2656
2766
|
const row = db.prepare(`SELECT COUNT(*) AS count
|
|
2657
2767
|
FROM message
|
|
@@ -3340,6 +3450,69 @@ function isFilePart(part) {
|
|
|
3340
3450
|
return p.type === "file" && typeof p.url === "string";
|
|
3341
3451
|
}
|
|
3342
3452
|
|
|
3453
|
+
// ../plugin/src/features/magic-context/dreamer/token-budget.ts
|
|
3454
|
+
class DreamTokenBudgetExceeded extends Error {
|
|
3455
|
+
sessionId;
|
|
3456
|
+
spent;
|
|
3457
|
+
constructor(sessionId, spent) {
|
|
3458
|
+
super(`Dreamer child ${sessionId} spent ${spent} prompt tokens (token_budget)`);
|
|
3459
|
+
this.sessionId = sessionId;
|
|
3460
|
+
this.spent = spent;
|
|
3461
|
+
this.name = "DreamTokenBudgetExceeded";
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
var TOKEN_BUDGET_FINALIZE_MESSAGE = "You're out of token budget. Stop investigating: make no more tool calls and output your result now, covering only what you've already checked; leave the rest out.";
|
|
3465
|
+
var TOKEN_BUDGET_TOOL_REFUSAL = "Out of token budget: no more tool calls. Output your result now.";
|
|
3466
|
+
var finalizingChildren = new Map;
|
|
3467
|
+
function registerBudgetFinalizeChild(sessionId, guard) {
|
|
3468
|
+
finalizingChildren.set(sessionId, guard);
|
|
3469
|
+
}
|
|
3470
|
+
function releaseBudgetFinalizeChild(sessionId) {
|
|
3471
|
+
finalizingChildren.delete(sessionId);
|
|
3472
|
+
}
|
|
3473
|
+
function createDreamTokenBudget(budget) {
|
|
3474
|
+
if (!Number.isSafeInteger(budget) || budget <= 0)
|
|
3475
|
+
throw new Error("Invalid token budget");
|
|
3476
|
+
let spent = 0;
|
|
3477
|
+
let finalizeFired = false;
|
|
3478
|
+
let refusedCalls = 0;
|
|
3479
|
+
let forcedStop = false;
|
|
3480
|
+
const snapshot = () => ({
|
|
3481
|
+
budget,
|
|
3482
|
+
spent,
|
|
3483
|
+
finalizeFired,
|
|
3484
|
+
refusedCalls,
|
|
3485
|
+
hardStopped: forcedStop || spent >= budget || refusedCalls >= 2
|
|
3486
|
+
});
|
|
3487
|
+
return {
|
|
3488
|
+
snapshot,
|
|
3489
|
+
charge(input, cacheRead, cacheWrite, completed = false, canFinalize = true) {
|
|
3490
|
+
for (const value of [input, cacheRead, cacheWrite]) {
|
|
3491
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
3492
|
+
throw new Error("Invalid prompt usage");
|
|
3493
|
+
}
|
|
3494
|
+
spent += input + cacheRead + cacheWrite;
|
|
3495
|
+
if (spent >= budget)
|
|
3496
|
+
return "stop";
|
|
3497
|
+
if (!completed && !finalizeFired && spent >= budget * 0.8) {
|
|
3498
|
+
if (!canFinalize) {
|
|
3499
|
+
forcedStop = true;
|
|
3500
|
+
return "stop";
|
|
3501
|
+
}
|
|
3502
|
+
finalizeFired = true;
|
|
3503
|
+
return "finalize";
|
|
3504
|
+
}
|
|
3505
|
+
return "continue";
|
|
3506
|
+
},
|
|
3507
|
+
refuseTool() {
|
|
3508
|
+
if (!finalizeFired)
|
|
3509
|
+
return null;
|
|
3510
|
+
refusedCalls += 1;
|
|
3511
|
+
return { message: TOKEN_BUDGET_TOOL_REFUSAL, hardStopped: snapshot().hardStopped };
|
|
3512
|
+
}
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3343
3516
|
// ../plugin/src/hooks/magic-context/dropped-input-guard.ts
|
|
3344
3517
|
var LEGACY_TRUNCATED_VALUE = /^[\s\S]{0,5}\.\.\.\[truncated\]$/;
|
|
3345
3518
|
var MAX_QUOTED_ARGUMENTS = 160;
|
|
@@ -4239,6 +4412,45 @@ function readRawSessionMessageRangeFromSource(sessionId, fromOrdinal, toOrdinal)
|
|
|
4239
4412
|
}
|
|
4240
4413
|
return messages;
|
|
4241
4414
|
}
|
|
4415
|
+
var RAW_MESSAGE_VISIT_PAGE_SIZE = 50;
|
|
4416
|
+
function visitRawSessionMessages2(sessionId, fromOrdinal, toOrdinal, visit, options = {}) {
|
|
4417
|
+
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
4418
|
+
const to = Math.floor(toOrdinal);
|
|
4419
|
+
if (to < from)
|
|
4420
|
+
return;
|
|
4421
|
+
const provider = sessionProviders.get(sessionId);
|
|
4422
|
+
if (provider && !provider.readMessagePage) {
|
|
4423
|
+
for (const message of provider.readMessages()) {
|
|
4424
|
+
if (message.ordinal < from || message.ordinal > to)
|
|
4425
|
+
continue;
|
|
4426
|
+
if (!visit(message))
|
|
4427
|
+
return;
|
|
4428
|
+
}
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
4431
|
+
if (!provider && !openCodeDbExists())
|
|
4432
|
+
return;
|
|
4433
|
+
const pageSize = Math.max(1, Math.floor(options.pageSize ?? RAW_MESSAGE_VISIT_PAGE_SIZE));
|
|
4434
|
+
let afterOrdinal = from - 1;
|
|
4435
|
+
while (afterOrdinal < to) {
|
|
4436
|
+
const limit = Math.min(pageSize, to - afterOrdinal);
|
|
4437
|
+
const cursor = afterOrdinal;
|
|
4438
|
+
const page = provider?.readMessagePage ? provider.readMessagePage(cursor, limit, to) : withReadOnlySessionDb((db) => options.summary ? readRawSessionMessageSummaryPageFromDb(db, sessionId, cursor, limit, to) : readRawSessionMessagePageFromDb(db, sessionId, cursor, limit, to));
|
|
4439
|
+
if (page.length === 0)
|
|
4440
|
+
return;
|
|
4441
|
+
let nextOrdinal = afterOrdinal;
|
|
4442
|
+
for (const message of page) {
|
|
4443
|
+
if (message.ordinal < from || message.ordinal > to)
|
|
4444
|
+
continue;
|
|
4445
|
+
if (!visit(message))
|
|
4446
|
+
return;
|
|
4447
|
+
nextOrdinal = Math.max(nextOrdinal, message.ordinal);
|
|
4448
|
+
}
|
|
4449
|
+
if (nextOrdinal <= afterOrdinal)
|
|
4450
|
+
return;
|
|
4451
|
+
afterOrdinal = nextOrdinal;
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4242
4454
|
function readRawSessionMessageRange2(sessionId, fromOrdinal, toOrdinal) {
|
|
4243
4455
|
const from = Math.max(1, Math.floor(fromOrdinal));
|
|
4244
4456
|
const to = Math.floor(toOrdinal);
|
|
@@ -4777,4 +4989,4 @@ function readSessionChunk2(sessionId, tokenBudget, offset = 1, eligibleEndOrdina
|
|
|
4777
4989
|
toolResultBoundaries
|
|
4778
4990
|
};
|
|
4779
4991
|
}
|
|
4780
|
-
export { CTX_REDUCE_KEEP, newestCtxReduceTagNumbers, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isRecord, stableStringify, estimateImageTokensFromDataUrl, TODO_STATUSES, TODO_PRIORITIES, TITLE_DONE_STATUSES, normalizeTodoStateJson, buildSyntheticTodoPart, stripChannel1ReminderSpans, compareMeasuredTailPrefix, formatTailHygienePrefixMismatch, freezeTailHygieneMeasurement, effectiveTailHygiene, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, planEmergencyDrop, measureEmergencyTag, updateTagByteSize, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, updateTagInputByteSize, updateTagTokenCount, getPersistedToolTagAccounting, getAllStatusTagTokenTotalsFlat, updateTagInputTokenCount, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, getInertWhitespaceAssistantTags, updateTagDropMode, updateCavemanDepth, hasPiFallbackMessageTags, findAdoptableFallbackTags, hasPiFallbackToolOwnerTags, findPiFallbackToolOwnerTags, adoptPiFallbackToolOwnerTag, adoptPiFallbackMessageTag, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTagsForPendingOperations, getTagsByNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, retreatPastHostUnservedRows, resolveOpenCodeDbPath, hasV1MessageTables, assertOpenCodeStoreGeneration, openCodeDbPathExists, getOpenCodeDbProbeDescriptions, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, registerSlowWriteReporter, detectSqliteRuntime, Database, withPrivilegedWriter, closeQuietly, withReadOnlySessionDb, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, droppedInputMarker, createDroppedInputGuard, isEditTool, applyEditMarkerToInput, setDatabase, loadToolDefinitionMeasurements, resolveDecisionCalibration, providerMass, localBudget, calibrationForModelKey, historyLocalBudget, SKELETON_REAL_INPUT_MAX_BYTES, toolInputStringBytes, resolveHostServedBoundaryId2, hasRawMessageProvider2, setRawMessageProvider2, withRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, readRawSessionMessageRange2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };
|
|
4992
|
+
export { CTX_REDUCE_KEEP, newestCtxReduceTagNumbers, textMentionsRecentCommit, removeSystemReminders, hasMeaningfulUserText2, extractTexts2, extractToolCallSummaries, preloadTokenizer, estimateTokens, normalizeText, stripWellFormedLeadingTagPrefix, stripPersistedAssistantText, byteSize, stripTagPrefix, peelLeadingMcTagNotation, prependTag, isRecord, stableStringify, estimateImageTokensFromDataUrl, TODO_STATUSES, TODO_PRIORITIES, TITLE_DONE_STATUSES, normalizeTodoStateJson, buildSyntheticTodoPart, stripChannel1ReminderSpans, compareMeasuredTailPrefix, formatTailHygienePrefixMismatch, freezeTailHygieneMeasurement, effectiveTailHygiene, CHANNEL1_SENTINEL, CHANNEL1_FLOOR_TOKENS, decideChannel1, evaluateChannel2, reclaimableToolOutputCount, buildChannel2Reminder, buildChannel1Reminder, planEmergencyDrop, measureEmergencyTag, updateTagByteSize, getRecentTagOwnerMessageIds, AGE_RECLAIM_MIN_TOKENS, getOldestActiveUnprotectedToolTags, getActiveToolTagsForAgeReclaim, getTriggerTagTokenUpperBound, updateTagInputByteSize, updateTagTokenCount, getPersistedToolTagAccounting, getAllStatusTagTokenTotalsFlat, updateTagInputTokenCount, tagTokenCountIsNull, backfillTagTokenCounts, insertTag, updateTagStatus, getInertWhitespaceAssistantTags, updateTagDropMode, updateCavemanDepth, hasPiFallbackMessageTags, findAdoptableFallbackTags, hasPiFallbackToolOwnerTags, findPiFallbackToolOwnerTags, adoptPiFallbackToolOwnerTag, adoptPiFallbackMessageTag, getMaxTagNumberBySession, getTagNumberByMessageId, getAssignableTagNumberByMessageId, deriveTagLoadFloor, TAG_SELECT_COLUMNS, getTagsBySession, getActiveTagsBySession, getTagsForPendingOperations, getTagsByNumbers, getDroppedTagsByNumbers, getMaxDroppedTagNumber, getToolTagNumberByOwner, getNullOwnerToolTag, adoptNullOwnerToolTag, retreatPastHostUnservedRows, resolveOpenCodeDbPath, hasV1MessageTables, assertOpenCodeStoreGeneration, openCodeDbPathExists, getOpenCodeDbProbeDescriptions, recordOpenCodeDbReadFailure, clearOpenCodeDbReadFailure, claimOpenCodeDbDiagnosticOnce, registerSlowWriteReporter, detectSqliteRuntime, Database, withPrivilegedWriter, closeQuietly, withReadOnlySessionDb, RAW_SUMMARY_TEXT_MAX_CHARS, completedToolArcCrossesBoundary, estimateTrueRawMessageTokens, buildToolArcs, fenceBoundaryForCompletedToolArcs, fenceBoundaryForToolArcs, buildTrueRawTokenIndex, computeRawRangeFingerprint, invalidateTrueRawTokenCache, DreamTokenBudgetExceeded, TOKEN_BUDGET_FINALIZE_MESSAGE, TOKEN_BUDGET_TOOL_REFUSAL, registerBudgetFinalizeChild, releaseBudgetFinalizeChild, createDreamTokenBudget, droppedInputMarker, createDroppedInputGuard, isEditTool, applyEditMarkerToInput, setDatabase, loadToolDefinitionMeasurements, resolveDecisionCalibration, providerMass, localBudget, calibrationForModelKey, historyLocalBudget, SKELETON_REAL_INPUT_MAX_BYTES, toolInputStringBytes, resolveHostServedBoundaryId2, hasRawMessageProvider2, setRawMessageProvider2, withRawMessageProvider2, cleanUserText2, withRawSessionMessageCache2, readRawSessionMessages2, readRawSessionMessagePage2, getRawSessionMessageOrdinalCount2, visitRawSessionMessages2, readRawSessionMessageRange2, primeTailRawMessageCache2, getCachedAbsoluteMessageCount2, primeInMemoryTailRawMessageCache2, readRawSessionMessageIdOrdinalsForRange2, hasRawSessionMessageById2, readRawSessionMessageOrdinalById2, compareRawSessionMessageOrder2, getRawSessionMessageCount2, getRawSessionTagKeysThrough2, getLegacyProtectedTailStartOrdinal2, readSessionChunk2 };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// src/subagent-telemetry.ts
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
|
|
4
|
+
// ../plugin/src/agents/permissions.ts
|
|
5
|
+
function applyDisallowedTools(defaults, disallowed) {
|
|
6
|
+
if (disallowed.includes("*"))
|
|
7
|
+
return [];
|
|
8
|
+
return defaults.filter((t) => !disallowed.includes(t));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// ../plugin/src/agents/hidden-agent-registrations.ts
|
|
12
|
+
var HIDDEN_AGENT_DESCRIPTION = "Internal Magic Context maintenance agent. Not for general tasks — do not select for user work.";
|
|
13
|
+
function buildHiddenAgentRegistrations(args) {
|
|
14
|
+
const historianAllowedTools = applyDisallowedTools(["read", "aft_outline", "aft_zoom", "aft_search"], args.historianDisallowed);
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
id: "dreamer",
|
|
18
|
+
mode: "primary",
|
|
19
|
+
hidden: true,
|
|
20
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
21
|
+
prompt: args.dreamerPrompt,
|
|
22
|
+
allowedTools: ["ctx_memory"],
|
|
23
|
+
maxSteps: 150,
|
|
24
|
+
overrides: args.dreamerOverrides,
|
|
25
|
+
lockPermissions: true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "dreamer-docs",
|
|
29
|
+
mode: "primary",
|
|
30
|
+
hidden: true,
|
|
31
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
32
|
+
prompt: args.dreamerPrompt,
|
|
33
|
+
allowedTools: ["read", "grep", "glob", "aft_outline", "aft_zoom", "aft_search"],
|
|
34
|
+
maxSteps: 60,
|
|
35
|
+
overrides: args.dreamerOverrides,
|
|
36
|
+
lockPermissions: true
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "dreamer-reviewer",
|
|
40
|
+
mode: "primary",
|
|
41
|
+
hidden: true,
|
|
42
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
43
|
+
prompt: args.dreamerPrompt,
|
|
44
|
+
allowedTools: [],
|
|
45
|
+
maxSteps: 4,
|
|
46
|
+
overrides: args.dreamerOverrides,
|
|
47
|
+
lockPermissions: true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: "dreamer-retrospective",
|
|
51
|
+
mode: "primary",
|
|
52
|
+
hidden: true,
|
|
53
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
54
|
+
prompt: args.dreamerPrompt,
|
|
55
|
+
allowedTools: ["ctx_search"],
|
|
56
|
+
maxSteps: 40,
|
|
57
|
+
overrides: args.dreamerOverrides,
|
|
58
|
+
lockPermissions: true
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "dreamer-primer-investigator",
|
|
62
|
+
mode: "primary",
|
|
63
|
+
hidden: true,
|
|
64
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
65
|
+
prompt: args.dreamerPrompt,
|
|
66
|
+
allowedTools: [
|
|
67
|
+
"read",
|
|
68
|
+
"grep",
|
|
69
|
+
"glob",
|
|
70
|
+
"aft_outline",
|
|
71
|
+
"aft_zoom",
|
|
72
|
+
"aft_search",
|
|
73
|
+
"ctx_search"
|
|
74
|
+
],
|
|
75
|
+
maxSteps: 40,
|
|
76
|
+
overrides: args.dreamerOverrides,
|
|
77
|
+
lockPermissions: true
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "dreamer-memory-mapper",
|
|
81
|
+
mode: "primary",
|
|
82
|
+
hidden: true,
|
|
83
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
84
|
+
prompt: args.dreamerPrompt,
|
|
85
|
+
allowedTools: ["read", "grep", "glob", "aft_outline", "aft_zoom", "aft_search"],
|
|
86
|
+
maxSteps: 60,
|
|
87
|
+
overrides: args.dreamerOverrides,
|
|
88
|
+
lockPermissions: true
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "dreamer-classifier",
|
|
92
|
+
mode: "primary",
|
|
93
|
+
hidden: true,
|
|
94
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
95
|
+
prompt: args.dreamerPrompt,
|
|
96
|
+
allowedTools: [],
|
|
97
|
+
maxSteps: 4,
|
|
98
|
+
overrides: args.dreamerOverrides,
|
|
99
|
+
lockPermissions: true
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "smart-note-compiler",
|
|
103
|
+
mode: "primary",
|
|
104
|
+
hidden: true,
|
|
105
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
106
|
+
prompt: args.smartNoteCompilerPrompt,
|
|
107
|
+
allowedTools: [],
|
|
108
|
+
maxSteps: 8,
|
|
109
|
+
overrides: args.dreamerOverrides,
|
|
110
|
+
lockPermissions: true
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "historian",
|
|
114
|
+
mode: "primary",
|
|
115
|
+
hidden: true,
|
|
116
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
117
|
+
prompt: args.historianPrompt,
|
|
118
|
+
allowedTools: historianAllowedTools,
|
|
119
|
+
maxSteps: 40,
|
|
120
|
+
overrides: args.historianOverrides
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "historian-recomp",
|
|
124
|
+
mode: "primary",
|
|
125
|
+
hidden: true,
|
|
126
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
127
|
+
prompt: args.historianRecompPrompt ?? args.historianPrompt,
|
|
128
|
+
allowedTools: historianAllowedTools,
|
|
129
|
+
maxSteps: 40,
|
|
130
|
+
overrides: args.historianOverrides
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "historian-editor",
|
|
134
|
+
mode: "primary",
|
|
135
|
+
hidden: true,
|
|
136
|
+
description: HIDDEN_AGENT_DESCRIPTION,
|
|
137
|
+
prompt: args.historianEditorPrompt,
|
|
138
|
+
allowedTools: historianAllowedTools,
|
|
139
|
+
maxSteps: 40,
|
|
140
|
+
overrides: args.historianOverrides
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/subagent-telemetry.ts
|
|
146
|
+
var stepCaps = new Map(buildHiddenAgentRegistrations({
|
|
147
|
+
dreamerPrompt: undefined,
|
|
148
|
+
historianPrompt: undefined,
|
|
149
|
+
historianEditorPrompt: undefined,
|
|
150
|
+
historianDisallowed: []
|
|
151
|
+
}).map(({ id, maxSteps }) => [id, maxSteps]));
|
|
152
|
+
function subagentStepCap(agent) {
|
|
153
|
+
return stepCaps.get(agent.replace(/^magic-context-/, ""));
|
|
154
|
+
}
|
|
155
|
+
function promptFingerprint(prompt) {
|
|
156
|
+
return {
|
|
157
|
+
bytes: Buffer.byteLength(prompt, "utf8"),
|
|
158
|
+
sha256: createHash("sha256").update(prompt).digest("hex")
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function record(value) {
|
|
162
|
+
return value !== null && typeof value === "object" ? value : {};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
class SubagentTelemetry {
|
|
166
|
+
log;
|
|
167
|
+
steps = 0;
|
|
168
|
+
intended;
|
|
169
|
+
effective = null;
|
|
170
|
+
tools = Object.create(null);
|
|
171
|
+
promptTokens = {
|
|
172
|
+
first: null,
|
|
173
|
+
last: null,
|
|
174
|
+
max: null
|
|
175
|
+
};
|
|
176
|
+
warned = false;
|
|
177
|
+
streamedSteps = 0;
|
|
178
|
+
terminalSeen = false;
|
|
179
|
+
results = new Set;
|
|
180
|
+
constructor(prompt, log) {
|
|
181
|
+
this.log = log;
|
|
182
|
+
this.intended = promptFingerprint(prompt);
|
|
183
|
+
}
|
|
184
|
+
observe(value) {
|
|
185
|
+
const event = record(value);
|
|
186
|
+
if (event.type === "mc_system_prompt" && typeof event.bytes === "number" && typeof event.sha256 === "string" && /^[a-f0-9]{64}$/.test(event.sha256)) {
|
|
187
|
+
this.effective = { bytes: event.bytes, sha256: event.sha256 };
|
|
188
|
+
if (!this.warned && event.sha256 !== this.intended.sha256) {
|
|
189
|
+
this.warned = true;
|
|
190
|
+
this.log(`subagent_system_prompt_${event.containsIntended === true ? "extended" : "replaced"} ${JSON.stringify({ intended: this.intended, effective: this.effective, extension: null })}`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (event.type === "message_end") {
|
|
194
|
+
if (record(event.message).role === "assistant") {
|
|
195
|
+
this.streamedSteps++;
|
|
196
|
+
this.assistant(event.message);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (event.type === "agent_end" && Array.isArray(event.messages) && !this.terminalSeen) {
|
|
200
|
+
this.terminalSeen = true;
|
|
201
|
+
const assistants = event.messages.filter((message) => record(message).role === "assistant");
|
|
202
|
+
for (const message of assistants.slice(this.streamedSteps))
|
|
203
|
+
this.assistant(message);
|
|
204
|
+
}
|
|
205
|
+
if (event.type === "tool_execution_end" && typeof event.toolCallId === "string" && typeof event.toolName === "string" && !this.results.has(event.toolCallId)) {
|
|
206
|
+
this.results.add(event.toolCallId);
|
|
207
|
+
const tool = this.tool(event.toolName);
|
|
208
|
+
const content = record(event.result).content;
|
|
209
|
+
if (Array.isArray(content))
|
|
210
|
+
for (const part of content) {
|
|
211
|
+
const block = record(part);
|
|
212
|
+
const text = typeof block.text === "string" ? block.text : typeof block.data === "string" ? block.data : "";
|
|
213
|
+
tool.outputBytes += Buffer.byteLength(text, "utf8");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
tool(name) {
|
|
218
|
+
this.tools[name] ??= { calls: 0, outputBytes: 0 };
|
|
219
|
+
return this.tools[name];
|
|
220
|
+
}
|
|
221
|
+
assistant(value) {
|
|
222
|
+
const message = record(value);
|
|
223
|
+
this.steps++;
|
|
224
|
+
const usage = record(message.usage);
|
|
225
|
+
const fields = [usage.input, usage.cacheRead, usage.cacheWrite];
|
|
226
|
+
const known = fields.some((value) => typeof value === "number" && Number.isFinite(value));
|
|
227
|
+
const tokens = known ? fields.reduce((sum, value) => sum + (typeof value === "number" && Number.isFinite(value) ? value : 0), 0) : null;
|
|
228
|
+
if (this.steps === 1)
|
|
229
|
+
this.promptTokens.first = tokens;
|
|
230
|
+
this.promptTokens.last = tokens;
|
|
231
|
+
if (tokens !== null)
|
|
232
|
+
this.promptTokens.max = Math.max(this.promptTokens.max ?? 0, tokens);
|
|
233
|
+
if (Array.isArray(message.content))
|
|
234
|
+
for (const part of message.content) {
|
|
235
|
+
const call = record(part);
|
|
236
|
+
if (call.type === "toolCall" && typeof call.name === "string")
|
|
237
|
+
this.tool(call.name).calls++;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
finish(agent, outcome, cap) {
|
|
241
|
+
this.log(`subagent_telemetry ${JSON.stringify({ agent, outcome, cap, steps: this.steps, tools: this.tools, promptTokens: this.promptTokens, intended: this.intended, effective: this.effective, provenanceSource: this.effective ? "pi_context_system_prompt" : "unavailable" })}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export { subagentStepCap, promptFingerprint, SubagentTelemetry };
|