@cortexkit/pi-magic-context 0.21.7 → 0.21.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +433 -22
- package/dist/subagent-entry.js +92 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -142834,6 +142834,49 @@ var MIGRATIONS = [
|
|
|
142834
142834
|
ON compartment_state_lease(expires_at);
|
|
142835
142835
|
`);
|
|
142836
142836
|
}
|
|
142837
|
+
},
|
|
142838
|
+
{
|
|
142839
|
+
version: 20,
|
|
142840
|
+
description: "Add subagent invocation token accounting",
|
|
142841
|
+
up: (db) => {
|
|
142842
|
+
db.exec(`
|
|
142843
|
+
CREATE TABLE IF NOT EXISTS subagent_invocations (
|
|
142844
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142845
|
+
session_id TEXT NOT NULL,
|
|
142846
|
+
harness TEXT NOT NULL,
|
|
142847
|
+
subagent TEXT NOT NULL,
|
|
142848
|
+
task TEXT,
|
|
142849
|
+
provider_id TEXT,
|
|
142850
|
+
model_id TEXT,
|
|
142851
|
+
started_at INTEGER NOT NULL,
|
|
142852
|
+
ended_at INTEGER,
|
|
142853
|
+
status TEXT NOT NULL,
|
|
142854
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142855
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142856
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142857
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142858
|
+
error TEXT,
|
|
142859
|
+
parent_invocation_id INTEGER
|
|
142860
|
+
);
|
|
142861
|
+
CREATE INDEX IF NOT EXISTS idx_sai_session_started
|
|
142862
|
+
ON subagent_invocations(session_id, started_at DESC);
|
|
142863
|
+
CREATE INDEX IF NOT EXISTS idx_sai_subagent
|
|
142864
|
+
ON subagent_invocations(subagent, started_at DESC);
|
|
142865
|
+
`);
|
|
142866
|
+
}
|
|
142867
|
+
},
|
|
142868
|
+
{
|
|
142869
|
+
version: 21,
|
|
142870
|
+
description: "Add session lifetime work metrics",
|
|
142871
|
+
up: (db) => {
|
|
142872
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
142873
|
+
if (!cols.some((c) => c.name === "new_work_tokens")) {
|
|
142874
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN new_work_tokens INTEGER NOT NULL DEFAULT 0");
|
|
142875
|
+
}
|
|
142876
|
+
if (!cols.some((c) => c.name === "total_input_tokens")) {
|
|
142877
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN total_input_tokens INTEGER NOT NULL DEFAULT 0");
|
|
142878
|
+
}
|
|
142879
|
+
}
|
|
142837
142880
|
}
|
|
142838
142881
|
];
|
|
142839
142882
|
function ensureMigrationsTable(db) {
|
|
@@ -143494,12 +143537,37 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143494
143537
|
-- is a valid JSON blob written via setPendingPiCompactionMarkerState.
|
|
143495
143538
|
-- Excluded from healNullTextColumns.
|
|
143496
143539
|
pending_pi_compaction_marker_state TEXT,
|
|
143540
|
+
new_work_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143541
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143497
143542
|
-- deferred_execute_state: intentionally NULLABLE without a default.
|
|
143498
143543
|
-- Absence is SQL NULL; presence is a JSON blob written via
|
|
143499
143544
|
-- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
|
|
143500
143545
|
deferred_execute_state TEXT
|
|
143501
143546
|
);
|
|
143502
143547
|
|
|
143548
|
+
CREATE TABLE IF NOT EXISTS subagent_invocations (
|
|
143549
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
143550
|
+
session_id TEXT NOT NULL,
|
|
143551
|
+
harness TEXT NOT NULL,
|
|
143552
|
+
subagent TEXT NOT NULL,
|
|
143553
|
+
task TEXT,
|
|
143554
|
+
provider_id TEXT,
|
|
143555
|
+
model_id TEXT,
|
|
143556
|
+
started_at INTEGER NOT NULL,
|
|
143557
|
+
ended_at INTEGER,
|
|
143558
|
+
status TEXT NOT NULL,
|
|
143559
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143560
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143561
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143562
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
143563
|
+
error TEXT,
|
|
143564
|
+
parent_invocation_id INTEGER
|
|
143565
|
+
);
|
|
143566
|
+
CREATE INDEX IF NOT EXISTS idx_sai_session_started
|
|
143567
|
+
ON subagent_invocations(session_id, started_at DESC);
|
|
143568
|
+
CREATE INDEX IF NOT EXISTS idx_sai_subagent
|
|
143569
|
+
ON subagent_invocations(subagent, started_at DESC);
|
|
143570
|
+
|
|
143503
143571
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
143504
143572
|
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
143505
143573
|
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
@@ -143591,6 +143659,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
143591
143659
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
143592
143660
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
143593
143661
|
ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
|
|
143662
|
+
ensureColumn(db, "session_meta", "new_work_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
143663
|
+
ensureColumn(db, "session_meta", "total_input_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
143594
143664
|
ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
|
|
143595
143665
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
143596
143666
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -143654,7 +143724,9 @@ function healNullIntegerColumns(db) {
|
|
|
143654
143724
|
["tool_call_tokens", 0],
|
|
143655
143725
|
["note_nudge_trigger_pending", 0],
|
|
143656
143726
|
["observed_safe_input_tokens", 0],
|
|
143657
|
-
["cache_alert_sent", 0]
|
|
143727
|
+
["cache_alert_sent", 0],
|
|
143728
|
+
["new_work_tokens", 0],
|
|
143729
|
+
["total_input_tokens", 0]
|
|
143658
143730
|
];
|
|
143659
143731
|
for (const [column, fallback] of columns) {
|
|
143660
143732
|
try {
|
|
@@ -144264,6 +144336,12 @@ function clearDeferredExecutePendingIfMatches(db, sessionId, expected) {
|
|
|
144264
144336
|
WHERE session_id = ? AND deferred_execute_state = ?`).run(sessionId, expectedBlob);
|
|
144265
144337
|
return result.changes > 0;
|
|
144266
144338
|
}
|
|
144339
|
+
function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
144340
|
+
ensureSessionMetaRow(db, sessionId);
|
|
144341
|
+
db.prepare(`UPDATE session_meta
|
|
144342
|
+
SET new_work_tokens = ?, total_input_tokens = ?
|
|
144343
|
+
WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
|
|
144344
|
+
}
|
|
144267
144345
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
144268
144346
|
init_logger();
|
|
144269
144347
|
await init_read_session_db();
|
|
@@ -144579,6 +144657,19 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
144579
144657
|
}
|
|
144580
144658
|
return sources;
|
|
144581
144659
|
}
|
|
144660
|
+
// ../plugin/src/features/magic-context/storage-subagent-invocations.ts
|
|
144661
|
+
function clampToken(value) {
|
|
144662
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
144663
|
+
}
|
|
144664
|
+
function recordSubagentInvocation(db, input) {
|
|
144665
|
+
const result = db.prepare(`INSERT INTO subagent_invocations (
|
|
144666
|
+
session_id, harness, subagent, task, provider_id, model_id,
|
|
144667
|
+
started_at, ended_at, status,
|
|
144668
|
+
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
144669
|
+
error, parent_invocation_id
|
|
144670
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.harness, input.subagent, input.task ?? null, input.providerId ?? null, input.modelId ?? null, input.startedAt, input.endedAt, input.status, clampToken(input.inputTokens), clampToken(input.outputTokens), clampToken(input.cacheReadTokens), clampToken(input.cacheWriteTokens), input.error ?? null, input.parentInvocationId ?? null);
|
|
144671
|
+
return Number(result.lastInsertRowid);
|
|
144672
|
+
}
|
|
144582
144673
|
// ../plugin/src/features/magic-context/storage-tags.ts
|
|
144583
144674
|
var insertTagStatements = new WeakMap;
|
|
144584
144675
|
var updateTagStatusStatements = new WeakMap;
|
|
@@ -145563,6 +145654,97 @@ import { createRequire as createRequire3 } from "node:module";
|
|
|
145563
145654
|
import { dirname as dirname3, join as join9, resolve as resolvePath } from "node:path";
|
|
145564
145655
|
import { createInterface } from "node:readline";
|
|
145565
145656
|
import { fileURLToPath } from "node:url";
|
|
145657
|
+
|
|
145658
|
+
// ../plugin/src/features/magic-context/subagent-token-capture.ts
|
|
145659
|
+
init_logger();
|
|
145660
|
+
function asNumber(value) {
|
|
145661
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
145662
|
+
}
|
|
145663
|
+
function tokenObjectFromMessage(message) {
|
|
145664
|
+
const info = message.info;
|
|
145665
|
+
if (info && typeof info === "object") {
|
|
145666
|
+
const tokens2 = info.tokens;
|
|
145667
|
+
if (tokens2 && typeof tokens2 === "object")
|
|
145668
|
+
return tokens2;
|
|
145669
|
+
}
|
|
145670
|
+
const tokens = message.tokens;
|
|
145671
|
+
if (tokens && typeof tokens === "object")
|
|
145672
|
+
return tokens;
|
|
145673
|
+
return null;
|
|
145674
|
+
}
|
|
145675
|
+
function isAssistantMessage(message) {
|
|
145676
|
+
if (!message || typeof message !== "object")
|
|
145677
|
+
return false;
|
|
145678
|
+
const record = message;
|
|
145679
|
+
const info = record.info;
|
|
145680
|
+
if (info && typeof info === "object") {
|
|
145681
|
+
return info.role === "assistant";
|
|
145682
|
+
}
|
|
145683
|
+
return record.role === "assistant";
|
|
145684
|
+
}
|
|
145685
|
+
function modelFromMessage(message) {
|
|
145686
|
+
const info = message.info;
|
|
145687
|
+
const source = info && typeof info === "object" ? info : message;
|
|
145688
|
+
return {
|
|
145689
|
+
providerId: typeof source.providerID === "string" ? source.providerID : typeof source.providerId === "string" ? source.providerId : null,
|
|
145690
|
+
modelId: typeof source.modelID === "string" ? source.modelID : typeof source.modelId === "string" ? source.modelId : null
|
|
145691
|
+
};
|
|
145692
|
+
}
|
|
145693
|
+
function emptyTokenTotals() {
|
|
145694
|
+
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
145695
|
+
}
|
|
145696
|
+
function sumTokensFromChildMessages(messages) {
|
|
145697
|
+
const totals = emptyTokenTotals();
|
|
145698
|
+
for (const message of messages) {
|
|
145699
|
+
if (!isAssistantMessage(message))
|
|
145700
|
+
continue;
|
|
145701
|
+
const tokens = tokenObjectFromMessage(message);
|
|
145702
|
+
if (!tokens)
|
|
145703
|
+
continue;
|
|
145704
|
+
const cache = tokens.cache && typeof tokens.cache === "object" ? tokens.cache : {};
|
|
145705
|
+
totals.input += asNumber(tokens.input);
|
|
145706
|
+
totals.output += asNumber(tokens.output);
|
|
145707
|
+
totals.cacheRead += asNumber(cache.read ?? tokens.cacheRead ?? tokens.cache_read);
|
|
145708
|
+
totals.cacheWrite += asNumber(cache.write ?? tokens.cacheWrite ?? tokens.cache_write);
|
|
145709
|
+
}
|
|
145710
|
+
return totals;
|
|
145711
|
+
}
|
|
145712
|
+
function findLastAssistantModel(messages) {
|
|
145713
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
145714
|
+
const message = messages[index];
|
|
145715
|
+
if (isAssistantMessage(message))
|
|
145716
|
+
return modelFromMessage(message);
|
|
145717
|
+
}
|
|
145718
|
+
return { providerId: null, modelId: null };
|
|
145719
|
+
}
|
|
145720
|
+
function recordChildInvocation(input) {
|
|
145721
|
+
const tokens = input.tokens ?? sumTokensFromChildMessages(input.messages ?? []);
|
|
145722
|
+
const model = input.providerId !== undefined || input.modelId !== undefined ? { providerId: input.providerId ?? null, modelId: input.modelId ?? null } : findLastAssistantModel(input.messages ?? []);
|
|
145723
|
+
try {
|
|
145724
|
+
return recordSubagentInvocation(input.db, {
|
|
145725
|
+
sessionId: input.parentSessionId,
|
|
145726
|
+
harness: input.harness,
|
|
145727
|
+
subagent: input.subagent,
|
|
145728
|
+
task: input.task ?? null,
|
|
145729
|
+
providerId: model.providerId,
|
|
145730
|
+
modelId: model.modelId,
|
|
145731
|
+
startedAt: input.startedAt,
|
|
145732
|
+
endedAt: input.endedAt ?? Date.now(),
|
|
145733
|
+
status: input.status,
|
|
145734
|
+
inputTokens: tokens.input,
|
|
145735
|
+
outputTokens: tokens.output,
|
|
145736
|
+
cacheReadTokens: tokens.cacheRead,
|
|
145737
|
+
cacheWriteTokens: tokens.cacheWrite,
|
|
145738
|
+
error: input.error ? describeError(input.error).brief : null,
|
|
145739
|
+
parentInvocationId: input.parentInvocationId ?? null
|
|
145740
|
+
});
|
|
145741
|
+
} catch (error) {
|
|
145742
|
+
sessionLog(input.parentSessionId, "subagent token accounting failed:", describeError(error).brief);
|
|
145743
|
+
return null;
|
|
145744
|
+
}
|
|
145745
|
+
}
|
|
145746
|
+
|
|
145747
|
+
// src/subagent-runner.ts
|
|
145566
145748
|
function resolveBundledPiCli() {
|
|
145567
145749
|
try {
|
|
145568
145750
|
const require_ = createRequire3(import.meta.url);
|
|
@@ -145592,6 +145774,17 @@ var DREAMER_ACTION_AGENTS = new Set([
|
|
|
145592
145774
|
"dreamer",
|
|
145593
145775
|
"magic-context-dreamer"
|
|
145594
145776
|
]);
|
|
145777
|
+
function inferAccountingSubagent(agent) {
|
|
145778
|
+
if (agent.includes("sidekick"))
|
|
145779
|
+
return "sidekick";
|
|
145780
|
+
if (agent.includes("dreamer"))
|
|
145781
|
+
return "dreamer";
|
|
145782
|
+
if (agent.includes("compressor"))
|
|
145783
|
+
return "compressor";
|
|
145784
|
+
if (agent.includes("recomp"))
|
|
145785
|
+
return "recomp";
|
|
145786
|
+
return "historian";
|
|
145787
|
+
}
|
|
145595
145788
|
|
|
145596
145789
|
class PiSubagentRunner {
|
|
145597
145790
|
harness = "pi";
|
|
@@ -145633,21 +145826,45 @@ class PiSubagentRunner {
|
|
|
145633
145826
|
}
|
|
145634
145827
|
async runOnce(options) {
|
|
145635
145828
|
const startTime = Date.now();
|
|
145829
|
+
let recordedAccounting = false;
|
|
145830
|
+
const recordAccounting = (result, messages = []) => {
|
|
145831
|
+
if (!options.accountingSessionId || recordedAccounting)
|
|
145832
|
+
return;
|
|
145833
|
+
recordedAccounting = true;
|
|
145834
|
+
recordChildInvocation({
|
|
145835
|
+
db: openDatabase(),
|
|
145836
|
+
parentSessionId: options.accountingSessionId,
|
|
145837
|
+
harness: "pi",
|
|
145838
|
+
subagent: options.accountingSubagent ?? inferAccountingSubagent(options.agent),
|
|
145839
|
+
task: options.accountingTask ?? null,
|
|
145840
|
+
startedAt: startTime,
|
|
145841
|
+
status: result.ok ? "completed" : result.reason === "abort" ? "aborted" : "failed",
|
|
145842
|
+
messages,
|
|
145843
|
+
providerId: typeof options.model === "string" ? options.model.split("/")[0] : null,
|
|
145844
|
+
modelId: typeof options.model === "string" ? options.model.split("/").slice(1).join("/") : null,
|
|
145845
|
+
error: result.ok ? null : result.error,
|
|
145846
|
+
parentInvocationId: options.accountingParentInvocationId ?? null
|
|
145847
|
+
});
|
|
145848
|
+
};
|
|
145636
145849
|
if (options.signal?.aborted) {
|
|
145637
|
-
|
|
145850
|
+
const result = {
|
|
145638
145851
|
ok: false,
|
|
145639
145852
|
reason: "abort",
|
|
145640
145853
|
error: "pi subagent aborted by caller",
|
|
145641
145854
|
durationMs: Date.now() - startTime
|
|
145642
145855
|
};
|
|
145856
|
+
recordAccounting(result);
|
|
145857
|
+
return result;
|
|
145643
145858
|
}
|
|
145644
145859
|
const args = buildArgs(options);
|
|
145645
145860
|
return new Promise((resolve2) => {
|
|
145861
|
+
let accountingMessages = [];
|
|
145646
145862
|
let settled = false;
|
|
145647
145863
|
const settle = (result) => {
|
|
145648
145864
|
if (settled)
|
|
145649
145865
|
return;
|
|
145650
145866
|
settled = true;
|
|
145867
|
+
recordAccounting(result, accountingMessages);
|
|
145651
145868
|
resolve2(result);
|
|
145652
145869
|
};
|
|
145653
145870
|
const emitProgress = (event) => {
|
|
@@ -145717,6 +145934,7 @@ class PiSubagentRunner {
|
|
|
145717
145934
|
let lastEventType = null;
|
|
145718
145935
|
let lastEventTimestamp = 0;
|
|
145719
145936
|
const accumulatedMessages = [];
|
|
145937
|
+
accountingMessages = accumulatedMessages;
|
|
145720
145938
|
rl.on("line", (line) => {
|
|
145721
145939
|
if (line.length === 0)
|
|
145722
145940
|
return;
|
|
@@ -146069,7 +146287,9 @@ function registerCtxAugCommand(pi, config) {
|
|
|
146069
146287
|
timeoutMs: config.timeoutMs ?? 30000,
|
|
146070
146288
|
cwd: ctx.cwd,
|
|
146071
146289
|
signal: ctx.signal,
|
|
146072
|
-
thinkingLevel: config.thinking_level
|
|
146290
|
+
thinkingLevel: config.thinking_level,
|
|
146291
|
+
accountingSessionId: sessionLabel,
|
|
146292
|
+
accountingSubagent: "sidekick"
|
|
146073
146293
|
});
|
|
146074
146294
|
if (!result.ok) {
|
|
146075
146295
|
log(`[magic-context][pi] /ctx-aug: sidekick failed (${result.reason}): ${result.error}`);
|
|
@@ -148067,6 +148287,23 @@ Return valid JSON (no markdown fencing):
|
|
|
148067
148287
|
|
|
148068
148288
|
If no promotions are warranted, return empty arrays. Always consume reviewed candidates so they don't accumulate indefinitely.`;
|
|
148069
148289
|
let agentSessionId = null;
|
|
148290
|
+
const startedAt = Date.now();
|
|
148291
|
+
let invocationRecorded = false;
|
|
148292
|
+
const recordInvocation = (params) => {
|
|
148293
|
+
if (!args.parentSessionId || invocationRecorded)
|
|
148294
|
+
return;
|
|
148295
|
+
invocationRecorded = true;
|
|
148296
|
+
recordChildInvocation({
|
|
148297
|
+
db: args.db,
|
|
148298
|
+
parentSessionId: args.parentSessionId,
|
|
148299
|
+
harness: "opencode",
|
|
148300
|
+
subagent: "user_memory_review",
|
|
148301
|
+
startedAt,
|
|
148302
|
+
status: params.status,
|
|
148303
|
+
messages: params.messages,
|
|
148304
|
+
error: params.error
|
|
148305
|
+
});
|
|
148306
|
+
};
|
|
148070
148307
|
const abortController = new AbortController;
|
|
148071
148308
|
const leaseInterval = setInterval(() => {
|
|
148072
148309
|
try {
|
|
@@ -148088,8 +148325,11 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
148088
148325
|
});
|
|
148089
148326
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
148090
148327
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
148091
|
-
if (!agentSessionId)
|
|
148092
|
-
|
|
148328
|
+
if (!agentSessionId) {
|
|
148329
|
+
const error = new Error("Could not create user memory review session.");
|
|
148330
|
+
recordInvocation({ status: "failed", error });
|
|
148331
|
+
throw error;
|
|
148332
|
+
}
|
|
148093
148333
|
log(`[dreamer] user-memories: child session created ${agentSessionId}`);
|
|
148094
148334
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
148095
148335
|
await promptSyncWithModelSuggestionRetry(args.client, {
|
|
@@ -148113,6 +148353,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
|
|
|
148113
148353
|
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
148114
148354
|
preferResponseOnMissingData: true
|
|
148115
148355
|
});
|
|
148356
|
+
recordInvocation({ status: "completed", messages });
|
|
148116
148357
|
const responseText = extractLatestAssistantText(messages);
|
|
148117
148358
|
if (!responseText) {
|
|
148118
148359
|
log("[dreamer] user-memories: no response from review agent");
|
|
@@ -148352,6 +148593,24 @@ async function runDream(args) {
|
|
|
148352
148593
|
log(`[dreamer] starting task: ${taskName}`);
|
|
148353
148594
|
const taskStartedAt = Date.now();
|
|
148354
148595
|
let agentSessionId = null;
|
|
148596
|
+
const invocationStartedAt = Date.now();
|
|
148597
|
+
let invocationRecorded = false;
|
|
148598
|
+
const recordInvocation = (params) => {
|
|
148599
|
+
if (!parentSessionId || invocationRecorded)
|
|
148600
|
+
return;
|
|
148601
|
+
invocationRecorded = true;
|
|
148602
|
+
recordChildInvocation({
|
|
148603
|
+
db: args.db,
|
|
148604
|
+
parentSessionId,
|
|
148605
|
+
harness: "opencode",
|
|
148606
|
+
subagent: "dreamer",
|
|
148607
|
+
task: taskName,
|
|
148608
|
+
startedAt: invocationStartedAt,
|
|
148609
|
+
status: params.status,
|
|
148610
|
+
messages: params.messages,
|
|
148611
|
+
error: params.error
|
|
148612
|
+
});
|
|
148613
|
+
};
|
|
148355
148614
|
const taskAbortController = new AbortController;
|
|
148356
148615
|
const leaseRenewalInterval = setInterval(() => {
|
|
148357
148616
|
try {
|
|
@@ -148392,7 +148651,9 @@ async function runDream(args) {
|
|
|
148392
148651
|
const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
148393
148652
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
148394
148653
|
if (!agentSessionId) {
|
|
148395
|
-
|
|
148654
|
+
const error = new Error("Dreamer could not create its child session.");
|
|
148655
|
+
recordInvocation({ status: "failed", error });
|
|
148656
|
+
throw error;
|
|
148396
148657
|
}
|
|
148397
148658
|
log(`[dreamer] task ${taskName}: child session created ${agentSessionId}`);
|
|
148398
148659
|
await promptSyncWithModelSuggestionRetry(args.client, {
|
|
@@ -148419,6 +148680,7 @@ async function runDream(args) {
|
|
|
148419
148680
|
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
148420
148681
|
preferResponseOnMissingData: true
|
|
148421
148682
|
});
|
|
148683
|
+
recordInvocation({ status: "completed", messages });
|
|
148422
148684
|
const taskResult = extractLatestAssistantText(messages);
|
|
148423
148685
|
if (!taskResult) {
|
|
148424
148686
|
throw new Error("Dreamer returned no assistant output.");
|
|
@@ -148433,6 +148695,7 @@ async function runDream(args) {
|
|
|
148433
148695
|
lastErrorSignature = null;
|
|
148434
148696
|
consecutiveSameErrorFailures = 0;
|
|
148435
148697
|
} catch (error) {
|
|
148698
|
+
recordInvocation({ status: lostLease ? "aborted" : "failed", error });
|
|
148436
148699
|
const durationMs = Date.now() - taskStartedAt;
|
|
148437
148700
|
const errorDescription = describeError(error);
|
|
148438
148701
|
logWithStackHead(`[dreamer] task ${taskName}: failed after ${(durationMs / 1000).toFixed(1)}s — ${errorDescription.brief}`, errorDescription.stackHead);
|
|
@@ -148702,6 +148965,24 @@ ${noteDescriptions}
|
|
|
148702
148965
|
Only include notes whose conditions you could definitively evaluate against external signals. Skip notes where you cannot determine the status (they will be re-evaluated next run, or eventually archived as stale).`;
|
|
148703
148966
|
const taskStartedAt = Date.now();
|
|
148704
148967
|
let agentSessionId = null;
|
|
148968
|
+
const startedAt = Date.now();
|
|
148969
|
+
let invocationRecorded = false;
|
|
148970
|
+
const recordInvocation = (params) => {
|
|
148971
|
+
if (!args.parentSessionId || invocationRecorded)
|
|
148972
|
+
return;
|
|
148973
|
+
invocationRecorded = true;
|
|
148974
|
+
recordChildInvocation({
|
|
148975
|
+
db: args.db,
|
|
148976
|
+
parentSessionId: args.parentSessionId,
|
|
148977
|
+
harness: "opencode",
|
|
148978
|
+
subagent: "dreamer",
|
|
148979
|
+
task: "smart-notes",
|
|
148980
|
+
startedAt,
|
|
148981
|
+
status: params.status,
|
|
148982
|
+
messages: params.messages,
|
|
148983
|
+
error: params.error
|
|
148984
|
+
});
|
|
148985
|
+
};
|
|
148705
148986
|
const abortController = new AbortController;
|
|
148706
148987
|
const leaseInterval = setInterval(() => {
|
|
148707
148988
|
try {
|
|
@@ -148725,8 +149006,11 @@ Only include notes whose conditions you could definitively evaluate against exte
|
|
|
148725
149006
|
});
|
|
148726
149007
|
const created = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
148727
149008
|
agentSessionId = typeof created?.id === "string" ? created.id : null;
|
|
148728
|
-
if (!agentSessionId)
|
|
148729
|
-
|
|
149009
|
+
if (!agentSessionId) {
|
|
149010
|
+
const error = new Error("Could not create smart note evaluation session.");
|
|
149011
|
+
recordInvocation({ status: "failed", error });
|
|
149012
|
+
throw error;
|
|
149013
|
+
}
|
|
148730
149014
|
log(`[dreamer] smart notes: child session created ${agentSessionId}`);
|
|
148731
149015
|
const remainingMs = Math.max(0, args.deadline - Date.now());
|
|
148732
149016
|
await promptSyncWithModelSuggestionRetry(args.client, {
|
|
@@ -148750,6 +149034,7 @@ Only include notes whose conditions you could definitively evaluate against exte
|
|
|
148750
149034
|
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
148751
149035
|
preferResponseOnMissingData: true
|
|
148752
149036
|
});
|
|
149037
|
+
recordInvocation({ status: "completed", messages });
|
|
148753
149038
|
const output = extractLatestAssistantText(messages);
|
|
148754
149039
|
if (!output)
|
|
148755
149040
|
throw new Error("Smart note evaluation returned no output.");
|
|
@@ -166118,6 +166403,57 @@ function createTagger() {
|
|
|
166118
166403
|
};
|
|
166119
166404
|
}
|
|
166120
166405
|
|
|
166406
|
+
// ../plugin/src/features/magic-context/work-metrics.ts
|
|
166407
|
+
function asNumber2(value) {
|
|
166408
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
166409
|
+
}
|
|
166410
|
+
function getPiUsage(entry) {
|
|
166411
|
+
if (!entry || typeof entry !== "object")
|
|
166412
|
+
return null;
|
|
166413
|
+
const record2 = entry;
|
|
166414
|
+
const message = record2.message && typeof record2.message === "object" ? record2.message : record2;
|
|
166415
|
+
if (message.role !== "assistant")
|
|
166416
|
+
return null;
|
|
166417
|
+
if (!message.usage || typeof message.usage !== "object")
|
|
166418
|
+
return null;
|
|
166419
|
+
const usage = message.usage;
|
|
166420
|
+
return {
|
|
166421
|
+
input: asNumber2(usage.input),
|
|
166422
|
+
output: asNumber2(usage.output),
|
|
166423
|
+
cacheRead: asNumber2(usage.cacheRead ?? usage.cache_read),
|
|
166424
|
+
cacheWrite: asNumber2(usage.cacheWrite ?? usage.cache_write)
|
|
166425
|
+
};
|
|
166426
|
+
}
|
|
166427
|
+
function computePiWorkMetrics(sessionEntries) {
|
|
166428
|
+
let previousPrompt = 0;
|
|
166429
|
+
let phasePeak = 0;
|
|
166430
|
+
let newWorkTokens = 0;
|
|
166431
|
+
let totalInputTokens = 0;
|
|
166432
|
+
let lastOutput = 0;
|
|
166433
|
+
let sawAssistant = false;
|
|
166434
|
+
for (const entry of sessionEntries) {
|
|
166435
|
+
const usage = getPiUsage(entry);
|
|
166436
|
+
if (!usage)
|
|
166437
|
+
continue;
|
|
166438
|
+
const prompt = usage.input + usage.cacheRead + usage.cacheWrite;
|
|
166439
|
+
if (sawAssistant && prompt < previousPrompt) {
|
|
166440
|
+
totalInputTokens += phasePeak;
|
|
166441
|
+
phasePeak = prompt;
|
|
166442
|
+
} else {
|
|
166443
|
+
phasePeak = Math.max(phasePeak, prompt);
|
|
166444
|
+
}
|
|
166445
|
+
newWorkTokens += Math.max(0, prompt - previousPrompt);
|
|
166446
|
+
previousPrompt = prompt;
|
|
166447
|
+
lastOutput = usage.output;
|
|
166448
|
+
sawAssistant = true;
|
|
166449
|
+
}
|
|
166450
|
+
if (sawAssistant) {
|
|
166451
|
+
totalInputTokens += phasePeak;
|
|
166452
|
+
newWorkTokens += lastOutput;
|
|
166453
|
+
}
|
|
166454
|
+
return { newWorkTokens, totalInputTokens };
|
|
166455
|
+
}
|
|
166456
|
+
|
|
166121
166457
|
// ../plugin/src/hooks/magic-context/apply-operations.ts
|
|
166122
166458
|
var USER_DROP_PREVIEW_CHARS = 250;
|
|
166123
166459
|
function buildReplacementContent(tagId, target) {
|
|
@@ -168879,12 +169215,12 @@ function createAssistantNudgeMessage(text, messages) {
|
|
|
168879
169215
|
function findLatestAssistantMessage(messages) {
|
|
168880
169216
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
168881
169217
|
const message = messages[i];
|
|
168882
|
-
if (
|
|
169218
|
+
if (isAssistantMessage2(message))
|
|
168883
169219
|
return message;
|
|
168884
169220
|
}
|
|
168885
169221
|
return;
|
|
168886
169222
|
}
|
|
168887
|
-
function
|
|
169223
|
+
function isAssistantMessage2(message) {
|
|
168888
169224
|
return getRole(message) === "assistant";
|
|
168889
169225
|
}
|
|
168890
169226
|
function createZeroUsage() {
|
|
@@ -169495,7 +169831,9 @@ async function runCompressorPass(args) {
|
|
|
169495
169831
|
fallbackModels: args.fallbackModels,
|
|
169496
169832
|
timeoutMs: args.historianTimeoutMs ?? DEFAULT_HISTORIAN_TIMEOUT_MS,
|
|
169497
169833
|
cwd: args.directory,
|
|
169498
|
-
thinkingLevel: args.thinkingLevel
|
|
169834
|
+
thinkingLevel: args.thinkingLevel,
|
|
169835
|
+
accountingSessionId: args.sessionId,
|
|
169836
|
+
accountingSubagent: "compressor"
|
|
169499
169837
|
});
|
|
169500
169838
|
if (!result.ok) {
|
|
169501
169839
|
sessionLog(args.sessionId, `compressor: subagent failed (${result.reason}): ${result.error}`);
|
|
@@ -170239,7 +170577,9 @@ ${chunk.text}`, { stateFilePath });
|
|
|
170239
170577
|
timeoutMs: historianTimeoutMs,
|
|
170240
170578
|
cwd: directory,
|
|
170241
170579
|
thinkingLevel,
|
|
170242
|
-
onProgress: buildProgressLogger("first")
|
|
170580
|
+
onProgress: buildProgressLogger("first"),
|
|
170581
|
+
accountingSessionId: sessionId,
|
|
170582
|
+
accountingSubagent: "historian"
|
|
170243
170583
|
});
|
|
170244
170584
|
let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
170245
170585
|
let validatedDraftText = firstResult.ok ? firstResult.assistantText : null;
|
|
@@ -170255,7 +170595,9 @@ ${chunk.text}`, { stateFilePath });
|
|
|
170255
170595
|
timeoutMs: historianTimeoutMs,
|
|
170256
170596
|
cwd: directory,
|
|
170257
170597
|
thinkingLevel,
|
|
170258
|
-
onProgress: buildProgressLogger("repair")
|
|
170598
|
+
onProgress: buildProgressLogger("repair"),
|
|
170599
|
+
accountingSessionId: sessionId,
|
|
170600
|
+
accountingSubagent: "historian"
|
|
170259
170601
|
});
|
|
170260
170602
|
validatedPass = await validateHistorianResult(repairResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
170261
170603
|
if (validatedPass.kind === "ok" && repairResult.ok) {
|
|
@@ -170281,7 +170623,9 @@ ${chunk.text}`, { stateFilePath });
|
|
|
170281
170623
|
timeoutMs: historianTimeoutMs,
|
|
170282
170624
|
cwd: directory,
|
|
170283
170625
|
thinkingLevel,
|
|
170284
|
-
onProgress: buildProgressLogger("editor")
|
|
170626
|
+
onProgress: buildProgressLogger("editor"),
|
|
170627
|
+
accountingSessionId: sessionId,
|
|
170628
|
+
accountingSubagent: "historian_editor"
|
|
170285
170629
|
});
|
|
170286
170630
|
const editorPass = await validateHistorianResult(editorResult, sessionId, chunk, priorCompartments, sequenceOffset);
|
|
170287
170631
|
if (editorPass.kind === "ok") {
|
|
@@ -172403,6 +172747,12 @@ function registerPiContextHandler(pi, options) {
|
|
|
172403
172747
|
} catch (err) {
|
|
172404
172748
|
sessionLog(sessionId, `synthetic todowrite injection failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
172405
172749
|
}
|
|
172750
|
+
try {
|
|
172751
|
+
const metrics = computePiWorkMetrics(outputMessages);
|
|
172752
|
+
setSessionWorkMetrics(options.db, sessionId, metrics.newWorkTokens, metrics.totalInputTokens);
|
|
172753
|
+
} catch (err) {
|
|
172754
|
+
sessionLog(sessionId, `work-metrics update failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
172755
|
+
}
|
|
172406
172756
|
logTransformTiming(sessionId, "postTransformPhase", tPostTransform);
|
|
172407
172757
|
sessionLog(sessionId, `transform completed in ${(performance.now() - transformStartTime).toFixed(1)}ms (${outputMessages.length} messages, ${result.targetCount} targets, watermark: ${result.reasoningWatermark})`);
|
|
172408
172758
|
clearLastTransformErrorIfSet(options.db, sessionId);
|
|
@@ -173828,6 +174178,27 @@ async function runCompressorPass2(args) {
|
|
|
173828
174178
|
} = args;
|
|
173829
174179
|
const prompt = buildCompressorPrompt(compartments, currentTokens, targetTokens, outputDepth, outputCount);
|
|
173830
174180
|
let agentSessionId = null;
|
|
174181
|
+
const startedAt = Date.now();
|
|
174182
|
+
let invocationRecorded = false;
|
|
174183
|
+
const recordInvocation = (params) => {
|
|
174184
|
+
if (invocationRecorded)
|
|
174185
|
+
return;
|
|
174186
|
+
invocationRecorded = true;
|
|
174187
|
+
try {
|
|
174188
|
+
recordChildInvocation({
|
|
174189
|
+
db: openDatabase(),
|
|
174190
|
+
parentSessionId: sessionId,
|
|
174191
|
+
harness: "opencode",
|
|
174192
|
+
subagent: "compressor",
|
|
174193
|
+
startedAt,
|
|
174194
|
+
status: params.status,
|
|
174195
|
+
messages: params.messages,
|
|
174196
|
+
error: params.error
|
|
174197
|
+
});
|
|
174198
|
+
} catch (error51) {
|
|
174199
|
+
sessionLog(sessionId, "subagent token accounting unavailable", getErrorMessage(error51));
|
|
174200
|
+
}
|
|
174201
|
+
};
|
|
173831
174202
|
try {
|
|
173832
174203
|
const createResponse = await client.session.create({
|
|
173833
174204
|
body: { parentID: sessionId, title: "magic-context-compressor" },
|
|
@@ -173837,6 +174208,7 @@ async function runCompressorPass2(args) {
|
|
|
173837
174208
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
173838
174209
|
if (!agentSessionId) {
|
|
173839
174210
|
sessionLog(sessionId, "compressor: could not create child session");
|
|
174211
|
+
recordInvocation({ status: "failed", error: "could not create child session" });
|
|
173840
174212
|
return null;
|
|
173841
174213
|
}
|
|
173842
174214
|
await promptSyncWithModelSuggestionRetry(client, {
|
|
@@ -173858,6 +174230,7 @@ async function runCompressorPass2(args) {
|
|
|
173858
174230
|
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
173859
174231
|
preferResponseOnMissingData: true
|
|
173860
174232
|
});
|
|
174233
|
+
recordInvocation({ status: "completed", messages });
|
|
173861
174234
|
const result = extractLatestAssistantText(messages);
|
|
173862
174235
|
if (!result) {
|
|
173863
174236
|
sessionLog(sessionId, "compressor: historian returned no output");
|
|
@@ -173878,6 +174251,7 @@ async function runCompressorPass2(args) {
|
|
|
173878
174251
|
}
|
|
173879
174252
|
return snapped.result;
|
|
173880
174253
|
} catch (error51) {
|
|
174254
|
+
recordInvocation({ status: "failed", error: error51 });
|
|
173881
174255
|
sessionLog(sessionId, "compressor: historian call failed:", getErrorMessage(error51));
|
|
173882
174256
|
return null;
|
|
173883
174257
|
} finally {
|
|
@@ -173916,7 +174290,8 @@ async function runValidatedHistorianPass(args) {
|
|
|
173916
174290
|
...args,
|
|
173917
174291
|
draftXml: firstRun.result,
|
|
173918
174292
|
draftValidation: firstValidation,
|
|
173919
|
-
draftDumpPath: firstRun.dumpPath
|
|
174293
|
+
draftDumpPath: firstRun.dumpPath,
|
|
174294
|
+
draftInvocationId: firstRun.invocationId ?? null
|
|
173920
174295
|
}) : firstValidation;
|
|
173921
174296
|
cleanupHistorianDump(args.parentSessionId, firstRun.dumpPath);
|
|
173922
174297
|
return finalResult;
|
|
@@ -173942,7 +174317,8 @@ async function runValidatedHistorianPass(args) {
|
|
|
173942
174317
|
...args,
|
|
173943
174318
|
draftXml: repairRun.result,
|
|
173944
174319
|
draftValidation: repairValidation,
|
|
173945
|
-
draftDumpPath: repairRun.dumpPath
|
|
174320
|
+
draftDumpPath: repairRun.dumpPath,
|
|
174321
|
+
draftInvocationId: repairRun.invocationId ?? null
|
|
173946
174322
|
}) : repairValidation;
|
|
173947
174323
|
cleanupHistorianDump(args.parentSessionId, repairRun.dumpPath);
|
|
173948
174324
|
return finalResult;
|
|
@@ -173963,7 +174339,8 @@ async function runEditorPassOrFallback(args) {
|
|
|
173963
174339
|
prompt: buildHistorianEditorPrompt(args.draftXml),
|
|
173964
174340
|
timeoutMs: args.timeoutMs,
|
|
173965
174341
|
dumpLabel: `${args.dumpLabelBase}-editor`,
|
|
173966
|
-
agentId: HISTORIAN_EDITOR_AGENT
|
|
174342
|
+
agentId: HISTORIAN_EDITOR_AGENT,
|
|
174343
|
+
parentInvocationId: args.draftInvocationId ?? null
|
|
173967
174344
|
});
|
|
173968
174345
|
if (!editorRun.ok || !editorRun.result) {
|
|
173969
174346
|
sessionLog(args.parentSessionId, "historian two-pass: editor call failed", {
|
|
@@ -173990,9 +174367,29 @@ async function runHistorianPrompt(args) {
|
|
|
173990
174367
|
dumpLabel,
|
|
173991
174368
|
modelOverride,
|
|
173992
174369
|
agentId = HISTORIAN_AGENT,
|
|
173993
|
-
fallbackModels
|
|
174370
|
+
fallbackModels,
|
|
174371
|
+
subagentKind,
|
|
174372
|
+
parentInvocationId
|
|
173994
174373
|
} = args;
|
|
173995
174374
|
let agentSessionId = null;
|
|
174375
|
+
const startedAt = Date.now();
|
|
174376
|
+
let invocationRecorded = false;
|
|
174377
|
+
const recordInvocation = (params) => {
|
|
174378
|
+
if (invocationRecorded)
|
|
174379
|
+
return null;
|
|
174380
|
+
invocationRecorded = true;
|
|
174381
|
+
return recordChildInvocation({
|
|
174382
|
+
db: openDatabase(),
|
|
174383
|
+
parentSessionId,
|
|
174384
|
+
harness: "opencode",
|
|
174385
|
+
subagent: agentId === HISTORIAN_EDITOR_AGENT ? "historian_editor" : subagentKind ?? "historian",
|
|
174386
|
+
startedAt,
|
|
174387
|
+
status: params.status,
|
|
174388
|
+
messages: params.messages,
|
|
174389
|
+
error: params.error,
|
|
174390
|
+
parentInvocationId: agentId === HISTORIAN_EDITOR_AGENT ? parentInvocationId ?? null : null
|
|
174391
|
+
});
|
|
174392
|
+
};
|
|
173996
174393
|
try {
|
|
173997
174394
|
sessionLog(parentSessionId, `historian: creating child session (agent=${agentId}, model=${modelOverride ? `${modelOverride.providerID}/${modelOverride.modelID}` : `agent:${agentId}`})`);
|
|
173998
174395
|
const createResponse = await client.session.create({
|
|
@@ -174005,6 +174402,10 @@ async function runHistorianPrompt(args) {
|
|
|
174005
174402
|
const createdSession = normalizeSDKResponse(createResponse, null, { preferResponseOnMissingData: true });
|
|
174006
174403
|
agentSessionId = typeof createdSession?.id === "string" ? createdSession.id : null;
|
|
174007
174404
|
if (!agentSessionId) {
|
|
174405
|
+
recordInvocation({
|
|
174406
|
+
status: "failed",
|
|
174407
|
+
error: "Historian could not create its child session."
|
|
174408
|
+
});
|
|
174008
174409
|
return { ok: false, error: "Historian could not create its child session." };
|
|
174009
174410
|
}
|
|
174010
174411
|
for (let retryIndex = 0;retryIndex <= MAX_HISTORIAN_RETRIES; retryIndex += 1) {
|
|
@@ -174043,15 +174444,21 @@ async function runHistorianPrompt(args) {
|
|
|
174043
174444
|
const messages = normalizeSDKResponse(messagesResponse, [], {
|
|
174044
174445
|
preferResponseOnMissingData: true
|
|
174045
174446
|
});
|
|
174447
|
+
const invocationId = recordInvocation({ status: "completed", messages });
|
|
174046
174448
|
const result = extractLatestAssistantText(messages);
|
|
174047
174449
|
if (!result) {
|
|
174048
|
-
return {
|
|
174450
|
+
return {
|
|
174451
|
+
ok: false,
|
|
174452
|
+
error: "Historian returned no assistant output.",
|
|
174453
|
+
invocationId: invocationId ?? undefined
|
|
174454
|
+
};
|
|
174049
174455
|
}
|
|
174050
174456
|
const dumpPath = dumpHistorianResponse(parentSessionId, sessionDirectory, dumpLabel ?? "historian-response", result);
|
|
174051
|
-
return { ok: true, result, dumpPath };
|
|
174457
|
+
return { ok: true, result, dumpPath, invocationId: invocationId ?? undefined };
|
|
174052
174458
|
} catch (modelError) {
|
|
174053
174459
|
const desc = describeError(modelError);
|
|
174054
174460
|
sessionLog(parentSessionId, `historian prompt failed: ${desc.brief} promptLength=${prompt.length}${desc.stackHead ? ` stackHead="${desc.stackHead}"` : ""}`);
|
|
174461
|
+
recordInvocation({ status: "failed", error: modelError });
|
|
174055
174462
|
return {
|
|
174056
174463
|
ok: false,
|
|
174057
174464
|
error: `Historian failed while processing this session: ${desc.brief}`
|
|
@@ -174712,6 +175119,7 @@ Historian pass ${passCount + 1}, attempt ${passAttempt} started for messages ${c
|
|
|
174712
175119
|
fallbackModelId: deps.fallbackModelId,
|
|
174713
175120
|
fallbackModels: deps.fallbackModels,
|
|
174714
175121
|
twoPass: deps.historianTwoPass,
|
|
175122
|
+
subagentKind: "recomp",
|
|
174715
175123
|
callbacks: {
|
|
174716
175124
|
onRepairRetry: async (error51) => {
|
|
174717
175125
|
await sendIgnoredMessage(client, sessionId, `## Magic Recomp
|
|
@@ -175078,6 +175486,7 @@ Historian recomp started. Rebuilding compartments and facts from raw Pi session
|
|
|
175078
175486
|
timeoutMs: deps.historianTimeoutMs,
|
|
175079
175487
|
thinkingLevel: deps.historianThinkingLevel,
|
|
175080
175488
|
directory: ctx.cwd,
|
|
175489
|
+
accountingSessionId: sessionId,
|
|
175081
175490
|
notify: (text) => {
|
|
175082
175491
|
sendCtxStatusMessage(pi, {
|
|
175083
175492
|
title: "/ctx-recomp",
|
|
@@ -175264,7 +175673,9 @@ function createPiRecompClient(args) {
|
|
|
175264
175673
|
fallbackModels: args.fallbackModels,
|
|
175265
175674
|
timeoutMs: args.timeoutMs,
|
|
175266
175675
|
cwd: args.directory,
|
|
175267
|
-
thinkingLevel: args.thinkingLevel
|
|
175676
|
+
thinkingLevel: args.thinkingLevel,
|
|
175677
|
+
accountingSessionId: args.accountingSessionId,
|
|
175678
|
+
accountingSubagent: "recomp"
|
|
175268
175679
|
});
|
|
175269
175680
|
if (!result.ok) {
|
|
175270
175681
|
throw new Error(`Pi recomp historian failed (${result.reason}): ${result.error}`);
|
|
@@ -175460,7 +175871,7 @@ function formatThresholdPercent(value) {
|
|
|
175460
175871
|
// package.json
|
|
175461
175872
|
var package_default = {
|
|
175462
175873
|
name: "@cortexkit/pi-magic-context",
|
|
175463
|
-
version: "0.21.
|
|
175874
|
+
version: "0.21.8",
|
|
175464
175875
|
type: "module",
|
|
175465
175876
|
description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
|
|
175466
175877
|
main: "dist/index.js",
|
package/dist/subagent-entry.js
CHANGED
|
@@ -8925,6 +8925,49 @@ var MIGRATIONS = [
|
|
|
8925
8925
|
ON compartment_state_lease(expires_at);
|
|
8926
8926
|
`);
|
|
8927
8927
|
}
|
|
8928
|
+
},
|
|
8929
|
+
{
|
|
8930
|
+
version: 20,
|
|
8931
|
+
description: "Add subagent invocation token accounting",
|
|
8932
|
+
up: (db) => {
|
|
8933
|
+
db.exec(`
|
|
8934
|
+
CREATE TABLE IF NOT EXISTS subagent_invocations (
|
|
8935
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8936
|
+
session_id TEXT NOT NULL,
|
|
8937
|
+
harness TEXT NOT NULL,
|
|
8938
|
+
subagent TEXT NOT NULL,
|
|
8939
|
+
task TEXT,
|
|
8940
|
+
provider_id TEXT,
|
|
8941
|
+
model_id TEXT,
|
|
8942
|
+
started_at INTEGER NOT NULL,
|
|
8943
|
+
ended_at INTEGER,
|
|
8944
|
+
status TEXT NOT NULL,
|
|
8945
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
8946
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
8947
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
8948
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
8949
|
+
error TEXT,
|
|
8950
|
+
parent_invocation_id INTEGER
|
|
8951
|
+
);
|
|
8952
|
+
CREATE INDEX IF NOT EXISTS idx_sai_session_started
|
|
8953
|
+
ON subagent_invocations(session_id, started_at DESC);
|
|
8954
|
+
CREATE INDEX IF NOT EXISTS idx_sai_subagent
|
|
8955
|
+
ON subagent_invocations(subagent, started_at DESC);
|
|
8956
|
+
`);
|
|
8957
|
+
}
|
|
8958
|
+
},
|
|
8959
|
+
{
|
|
8960
|
+
version: 21,
|
|
8961
|
+
description: "Add session lifetime work metrics",
|
|
8962
|
+
up: (db) => {
|
|
8963
|
+
const cols = db.prepare("PRAGMA table_info(session_meta)").all();
|
|
8964
|
+
if (!cols.some((c) => c.name === "new_work_tokens")) {
|
|
8965
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN new_work_tokens INTEGER NOT NULL DEFAULT 0");
|
|
8966
|
+
}
|
|
8967
|
+
if (!cols.some((c) => c.name === "total_input_tokens")) {
|
|
8968
|
+
db.exec("ALTER TABLE session_meta ADD COLUMN total_input_tokens INTEGER NOT NULL DEFAULT 0");
|
|
8969
|
+
}
|
|
8970
|
+
}
|
|
8928
8971
|
}
|
|
8929
8972
|
];
|
|
8930
8973
|
function ensureMigrationsTable(db) {
|
|
@@ -142177,12 +142220,37 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142177
142220
|
-- is a valid JSON blob written via setPendingPiCompactionMarkerState.
|
|
142178
142221
|
-- Excluded from healNullTextColumns.
|
|
142179
142222
|
pending_pi_compaction_marker_state TEXT,
|
|
142223
|
+
new_work_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142224
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142180
142225
|
-- deferred_execute_state: intentionally NULLABLE without a default.
|
|
142181
142226
|
-- Absence is SQL NULL; presence is a JSON blob written via
|
|
142182
142227
|
-- setDeferredExecutePendingIfAbsent. Excluded from healNullTextColumns.
|
|
142183
142228
|
deferred_execute_state TEXT
|
|
142184
142229
|
);
|
|
142185
142230
|
|
|
142231
|
+
CREATE TABLE IF NOT EXISTS subagent_invocations (
|
|
142232
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
142233
|
+
session_id TEXT NOT NULL,
|
|
142234
|
+
harness TEXT NOT NULL,
|
|
142235
|
+
subagent TEXT NOT NULL,
|
|
142236
|
+
task TEXT,
|
|
142237
|
+
provider_id TEXT,
|
|
142238
|
+
model_id TEXT,
|
|
142239
|
+
started_at INTEGER NOT NULL,
|
|
142240
|
+
ended_at INTEGER,
|
|
142241
|
+
status TEXT NOT NULL,
|
|
142242
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142243
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142244
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142245
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
142246
|
+
error TEXT,
|
|
142247
|
+
parent_invocation_id INTEGER
|
|
142248
|
+
);
|
|
142249
|
+
CREATE INDEX IF NOT EXISTS idx_sai_session_started
|
|
142250
|
+
ON subagent_invocations(session_id, started_at DESC);
|
|
142251
|
+
CREATE INDEX IF NOT EXISTS idx_sai_subagent
|
|
142252
|
+
ON subagent_invocations(subagent, started_at DESC);
|
|
142253
|
+
|
|
142186
142254
|
CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
|
|
142187
142255
|
CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
|
|
142188
142256
|
CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
|
|
@@ -142274,6 +142342,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
|
|
|
142274
142342
|
ensureColumn(db, "session_meta", "needs_emergency_recovery", "INTEGER DEFAULT 0");
|
|
142275
142343
|
ensureColumn(db, "session_meta", "pending_compaction_marker_state", "TEXT");
|
|
142276
142344
|
ensureColumn(db, "session_meta", "pending_pi_compaction_marker_state", "TEXT");
|
|
142345
|
+
ensureColumn(db, "session_meta", "new_work_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
142346
|
+
ensureColumn(db, "session_meta", "total_input_tokens", "INTEGER NOT NULL DEFAULT 0");
|
|
142277
142347
|
ensureColumn(db, "session_meta", "deferred_execute_state", "TEXT");
|
|
142278
142348
|
ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
142279
142349
|
ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
|
|
@@ -142337,7 +142407,9 @@ function healNullIntegerColumns(db) {
|
|
|
142337
142407
|
["tool_call_tokens", 0],
|
|
142338
142408
|
["note_nudge_trigger_pending", 0],
|
|
142339
142409
|
["observed_safe_input_tokens", 0],
|
|
142340
|
-
["cache_alert_sent", 0]
|
|
142410
|
+
["cache_alert_sent", 0],
|
|
142411
|
+
["new_work_tokens", 0],
|
|
142412
|
+
["total_input_tokens", 0]
|
|
142341
142413
|
];
|
|
142342
142414
|
for (const [column, fallback] of columns) {
|
|
142343
142415
|
try {
|
|
@@ -165296,6 +165368,12 @@ function clearDeferredExecutePendingIfMatches(db, sessionId, expected) {
|
|
|
165296
165368
|
WHERE session_id = ? AND deferred_execute_state = ?`).run(sessionId, expectedBlob);
|
|
165297
165369
|
return result.changes > 0;
|
|
165298
165370
|
}
|
|
165371
|
+
function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
|
|
165372
|
+
ensureSessionMetaRow(db, sessionId);
|
|
165373
|
+
db.prepare(`UPDATE session_meta
|
|
165374
|
+
SET new_work_tokens = ?, total_input_tokens = ?
|
|
165375
|
+
WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
|
|
165376
|
+
}
|
|
165299
165377
|
// ../plugin/src/features/magic-context/resolve-subagent-fallback.ts
|
|
165300
165378
|
init_logger();
|
|
165301
165379
|
await init_read_session_db();
|
|
@@ -165611,6 +165689,19 @@ function getSourceContents(db, sessionId, tagIds) {
|
|
|
165611
165689
|
}
|
|
165612
165690
|
return sources;
|
|
165613
165691
|
}
|
|
165692
|
+
// ../plugin/src/features/magic-context/storage-subagent-invocations.ts
|
|
165693
|
+
function clampToken(value) {
|
|
165694
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
165695
|
+
}
|
|
165696
|
+
function recordSubagentInvocation(db, input) {
|
|
165697
|
+
const result = db.prepare(`INSERT INTO subagent_invocations (
|
|
165698
|
+
session_id, harness, subagent, task, provider_id, model_id,
|
|
165699
|
+
started_at, ended_at, status,
|
|
165700
|
+
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
165701
|
+
error, parent_invocation_id
|
|
165702
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(input.sessionId, input.harness, input.subagent, input.task ?? null, input.providerId ?? null, input.modelId ?? null, input.startedAt, input.endedAt, input.status, clampToken(input.inputTokens), clampToken(input.outputTokens), clampToken(input.cacheReadTokens), clampToken(input.cacheWriteTokens), input.error ?? null, input.parentInvocationId ?? null);
|
|
165703
|
+
return Number(result.lastInsertRowid);
|
|
165704
|
+
}
|
|
165614
165705
|
// ../plugin/src/features/magic-context/storage-tags.ts
|
|
165615
165706
|
var insertTagStatements = new WeakMap;
|
|
165616
165707
|
var updateTagStatusStatements = new WeakMap;
|
package/package.json
CHANGED