@earendil-works/pi-coding-agent 0.80.10 → 0.81.1
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/CHANGELOG.md +60 -0
- package/README.md +6 -3
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +13 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +22 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +75 -56
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +7 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +8 -11
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +19 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +63 -26
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +6 -17
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +13 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +2 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +31 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +16 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +17 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +7 -2
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +41 -18
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +1 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +4 -4
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +26 -7
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +1 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +6 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +9 -4
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +99 -23
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/usage-totals.d.ts +19 -0
- package/dist/core/usage-totals.d.ts.map +1 -0
- package/dist/core/usage-totals.js +52 -0
- package/dist/core/usage-totals.js.map +1 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +61 -0
- package/dist/extensions/llama/client.d.ts.map +1 -0
- package/dist/extensions/llama/client.js +302 -0
- package/dist/extensions/llama/client.js.map +1 -0
- package/dist/extensions/llama/huggingface.d.ts +23 -0
- package/dist/extensions/llama/huggingface.d.ts.map +1 -0
- package/dist/extensions/llama/huggingface.js +141 -0
- package/dist/extensions/llama/huggingface.js.map +1 -0
- package/dist/extensions/llama/index.d.ts +3 -0
- package/dist/extensions/llama/index.d.ts.map +1 -0
- package/dist/extensions/llama/index.js +208 -0
- package/dist/extensions/llama/index.js.map +1 -0
- package/dist/extensions/llama/provider.d.ts +10 -0
- package/dist/extensions/llama/provider.d.ts.map +1 -0
- package/dist/extensions/llama/provider.js +102 -0
- package/dist/extensions/llama/provider.js.map +1 -0
- package/dist/extensions/llama/ui.d.ts +42 -0
- package/dist/extensions/llama/ui.d.ts.map +1 -0
- package/dist/extensions/llama/ui.js +416 -0
- package/dist/extensions/llama/ui.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +10 -4
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +24 -23
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +48 -26
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +4 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +7 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +4 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +11 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/compaction.md +8 -3
- package/docs/custom-provider.md +28 -0
- package/docs/extensions.md +51 -9
- package/docs/index.md +1 -0
- package/docs/json.md +5 -1
- package/docs/llama-cpp.md +99 -0
- package/docs/prompt-templates.md +1 -0
- package/docs/providers.md +11 -0
- package/docs/rpc.md +81 -2
- package/docs/sdk.md +3 -0
- package/docs/session-format.md +17 -3
- package/docs/tui.md +41 -26
- package/docs/usage.md +2 -1
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-compaction.ts +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +16 -31
- package/package.json +4 -4
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
16
|
import { basename, dirname } from "node:path";
|
|
17
|
+
import { contentText } from "@earendil-works/pi-ai";
|
|
17
18
|
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
18
19
|
import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
|
|
19
20
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
@@ -35,6 +36,7 @@ import { buildSystemPrompt } from "./system-prompt.js";
|
|
|
35
36
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
36
37
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
37
38
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
39
|
+
import { addUsageToTotals, createUsageTotals } from "./usage-totals.js";
|
|
38
40
|
/**
|
|
39
41
|
* Parse a skill block from message text.
|
|
40
42
|
* Returns null if the text doesn't contain a skill block.
|
|
@@ -188,7 +190,7 @@ export class AgentSession {
|
|
|
188
190
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
189
191
|
}
|
|
190
192
|
async _getSummarizationRequestAuth(model) {
|
|
191
|
-
if (this.agent.
|
|
193
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
192
194
|
return this._getRequiredRequestAuth(model);
|
|
193
195
|
}
|
|
194
196
|
try {
|
|
@@ -243,6 +245,7 @@ export class AgentSession {
|
|
|
243
245
|
content: result.content,
|
|
244
246
|
details: result.details,
|
|
245
247
|
isError,
|
|
248
|
+
usage: result.usage,
|
|
246
249
|
});
|
|
247
250
|
if (!hookResult) {
|
|
248
251
|
return undefined;
|
|
@@ -251,6 +254,7 @@ export class AgentSession {
|
|
|
251
254
|
content: hookResult.content,
|
|
252
255
|
details: hookResult.details,
|
|
253
256
|
isError: hookResult.isError ?? isError,
|
|
257
|
+
usage: hookResult.usage,
|
|
254
258
|
};
|
|
255
259
|
};
|
|
256
260
|
}
|
|
@@ -325,7 +329,7 @@ export class AgentSession {
|
|
|
325
329
|
// This ensures the UI sees the updated queue state
|
|
326
330
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
327
331
|
this._overflowRecoveryAttempted = false;
|
|
328
|
-
const messageText =
|
|
332
|
+
const messageText = contentText(event.message.content, "");
|
|
329
333
|
if (messageText) {
|
|
330
334
|
// Check steering queue first
|
|
331
335
|
const steeringIndex = this._steeringMessages.indexOf(messageText);
|
|
@@ -394,16 +398,6 @@ export class AgentSession {
|
|
|
394
398
|
}
|
|
395
399
|
return false;
|
|
396
400
|
}
|
|
397
|
-
/** Extract text content from a message */
|
|
398
|
-
_getUserMessageText(message) {
|
|
399
|
-
if (message.role !== "user")
|
|
400
|
-
return "";
|
|
401
|
-
const content = message.content;
|
|
402
|
-
if (typeof content === "string")
|
|
403
|
-
return content;
|
|
404
|
-
const textBlocks = content.filter((c) => c.type === "text");
|
|
405
|
-
return textBlocks.map((c) => c.text).join("");
|
|
406
|
-
}
|
|
407
401
|
/** Find the last assistant message in agent state (including aborted ones) */
|
|
408
402
|
_findLastAssistantMessage() {
|
|
409
403
|
const messages = this.agent.state.messages;
|
|
@@ -1414,26 +1408,29 @@ export class AgentSession {
|
|
|
1414
1408
|
let summary;
|
|
1415
1409
|
let firstKeptEntryId;
|
|
1416
1410
|
let tokensBefore;
|
|
1411
|
+
let usage;
|
|
1417
1412
|
let details;
|
|
1418
1413
|
if (extensionCompaction) {
|
|
1419
1414
|
// Extension provided compaction content
|
|
1420
1415
|
summary = extensionCompaction.summary;
|
|
1421
1416
|
firstKeptEntryId = extensionCompaction.firstKeptEntryId;
|
|
1422
1417
|
tokensBefore = extensionCompaction.tokensBefore;
|
|
1418
|
+
usage = extensionCompaction.usage;
|
|
1423
1419
|
details = extensionCompaction.details;
|
|
1424
1420
|
}
|
|
1425
1421
|
else {
|
|
1426
1422
|
// Generate compaction result
|
|
1427
|
-
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.
|
|
1423
|
+
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason: "manual" }));
|
|
1428
1424
|
summary = result.summary;
|
|
1429
1425
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
1430
1426
|
tokensBefore = result.tokensBefore;
|
|
1427
|
+
usage = result.usage;
|
|
1431
1428
|
details = result.details;
|
|
1432
1429
|
}
|
|
1433
1430
|
if (this._compactionAbortController.signal.aborted) {
|
|
1434
1431
|
throw new Error("Compaction cancelled");
|
|
1435
1432
|
}
|
|
1436
|
-
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
|
|
1433
|
+
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1437
1434
|
const newEntries = this.sessionManager.getEntries();
|
|
1438
1435
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1439
1436
|
this.agent.state.messages = sessionContext.messages;
|
|
@@ -1454,6 +1451,7 @@ export class AgentSession {
|
|
|
1454
1451
|
firstKeptEntryId,
|
|
1455
1452
|
tokensBefore,
|
|
1456
1453
|
estimatedTokensAfter,
|
|
1454
|
+
usage,
|
|
1457
1455
|
details,
|
|
1458
1456
|
};
|
|
1459
1457
|
this._emit({
|
|
@@ -1600,7 +1598,7 @@ export class AgentSession {
|
|
|
1600
1598
|
let apiKey;
|
|
1601
1599
|
let headers;
|
|
1602
1600
|
let env;
|
|
1603
|
-
if (this.agent.
|
|
1601
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
1604
1602
|
const authResult = await this._modelRuntime.getAuth(this.model);
|
|
1605
1603
|
if (!authResult?.auth.apiKey)
|
|
1606
1604
|
return false;
|
|
@@ -1649,20 +1647,23 @@ export class AgentSession {
|
|
|
1649
1647
|
let summary;
|
|
1650
1648
|
let firstKeptEntryId;
|
|
1651
1649
|
let tokensBefore;
|
|
1650
|
+
let usage;
|
|
1652
1651
|
let details;
|
|
1653
1652
|
if (extensionCompaction) {
|
|
1654
1653
|
// Extension provided compaction content
|
|
1655
1654
|
summary = extensionCompaction.summary;
|
|
1656
1655
|
firstKeptEntryId = extensionCompaction.firstKeptEntryId;
|
|
1657
1656
|
tokensBefore = extensionCompaction.tokensBefore;
|
|
1657
|
+
usage = extensionCompaction.usage;
|
|
1658
1658
|
details = extensionCompaction.details;
|
|
1659
1659
|
}
|
|
1660
1660
|
else {
|
|
1661
1661
|
// Generate compaction result
|
|
1662
|
-
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.
|
|
1662
|
+
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }));
|
|
1663
1663
|
summary = compactResult.summary;
|
|
1664
1664
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
1665
1665
|
tokensBefore = compactResult.tokensBefore;
|
|
1666
|
+
usage = compactResult.usage;
|
|
1666
1667
|
details = compactResult.details;
|
|
1667
1668
|
}
|
|
1668
1669
|
if (this._autoCompactionAbortController.signal.aborted) {
|
|
@@ -1675,7 +1676,7 @@ export class AgentSession {
|
|
|
1675
1676
|
});
|
|
1676
1677
|
return false;
|
|
1677
1678
|
}
|
|
1678
|
-
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
|
|
1679
|
+
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1679
1680
|
const newEntries = this.sessionManager.getEntries();
|
|
1680
1681
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1681
1682
|
this.agent.state.messages = sessionContext.messages;
|
|
@@ -1696,6 +1697,7 @@ export class AgentSession {
|
|
|
1696
1697
|
firstKeptEntryId,
|
|
1697
1698
|
tokensBefore,
|
|
1698
1699
|
estimatedTokensAfter,
|
|
1700
|
+
usage,
|
|
1699
1701
|
details,
|
|
1700
1702
|
};
|
|
1701
1703
|
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
@@ -1929,6 +1931,10 @@ export class AgentSession {
|
|
|
1929
1931
|
this._modelRuntime.registerProvider(name, config);
|
|
1930
1932
|
this._refreshCurrentModelFromRegistry();
|
|
1931
1933
|
},
|
|
1934
|
+
registerNativeProvider: (provider) => {
|
|
1935
|
+
this._modelRuntime.registerNativeProvider(provider);
|
|
1936
|
+
this._refreshCurrentModelFromRegistry();
|
|
1937
|
+
},
|
|
1932
1938
|
unregisterProvider: (name) => {
|
|
1933
1939
|
this._modelRuntime.unregisterProvider(name);
|
|
1934
1940
|
this._refreshCurrentModelFromRegistry();
|
|
@@ -2082,6 +2088,34 @@ export class AgentSession {
|
|
|
2082
2088
|
return false;
|
|
2083
2089
|
return isRetryableAssistantError(message);
|
|
2084
2090
|
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Retry policy + callbacks shared by compaction and branch-summary summarization calls.
|
|
2093
|
+
* Uses the same `settings.retry` budget/backoff as agent-turn retries so a single transient
|
|
2094
|
+
* stream drop no longer fails the whole operation. `source` carries the context
|
|
2095
|
+
* the TUI needs to render the retry and recreate the underlying indicator.
|
|
2096
|
+
*/
|
|
2097
|
+
_summarizationRetryCallbacks(source) {
|
|
2098
|
+
return {
|
|
2099
|
+
onRetryScheduled: (attempt, maxAttempts, delayMs, errorMessage) => {
|
|
2100
|
+
this._emit({
|
|
2101
|
+
type: "summarization_retry_scheduled",
|
|
2102
|
+
attempt,
|
|
2103
|
+
maxAttempts,
|
|
2104
|
+
delayMs,
|
|
2105
|
+
errorMessage,
|
|
2106
|
+
});
|
|
2107
|
+
},
|
|
2108
|
+
onRetryAttemptStart: () => {
|
|
2109
|
+
this._emit({
|
|
2110
|
+
type: "summarization_retry_attempt_start",
|
|
2111
|
+
...source,
|
|
2112
|
+
});
|
|
2113
|
+
},
|
|
2114
|
+
onRetryFinished: () => {
|
|
2115
|
+
this._emit({ type: "summarization_retry_finished" });
|
|
2116
|
+
},
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2085
2119
|
/**
|
|
2086
2120
|
* Prepare a retryable error for continuation with exponential backoff.
|
|
2087
2121
|
* @returns true if the caller should continue the agent, false otherwise
|
|
@@ -2327,6 +2361,7 @@ export class AgentSession {
|
|
|
2327
2361
|
// Run default summarizer if needed
|
|
2328
2362
|
let summaryText;
|
|
2329
2363
|
let summaryDetails;
|
|
2364
|
+
let summaryUsage;
|
|
2330
2365
|
if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
|
|
2331
2366
|
const model = this.model;
|
|
2332
2367
|
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
|
|
@@ -2340,7 +2375,9 @@ export class AgentSession {
|
|
|
2340
2375
|
customInstructions,
|
|
2341
2376
|
replaceInstructions,
|
|
2342
2377
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
2343
|
-
streamFn: this.agent.
|
|
2378
|
+
streamFn: this.agent.streamFunction,
|
|
2379
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
2380
|
+
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
2344
2381
|
});
|
|
2345
2382
|
if (result.aborted) {
|
|
2346
2383
|
return { cancelled: true, aborted: true };
|
|
@@ -2349,6 +2386,7 @@ export class AgentSession {
|
|
|
2349
2386
|
throw new Error(result.error);
|
|
2350
2387
|
}
|
|
2351
2388
|
summaryText = result.summary;
|
|
2389
|
+
summaryUsage = result.usage;
|
|
2352
2390
|
summaryDetails = {
|
|
2353
2391
|
readFiles: result.readFiles || [],
|
|
2354
2392
|
modifiedFiles: result.modifiedFiles || [],
|
|
@@ -2357,6 +2395,7 @@ export class AgentSession {
|
|
|
2357
2395
|
else if (extensionSummary) {
|
|
2358
2396
|
summaryText = extensionSummary.summary;
|
|
2359
2397
|
summaryDetails = extensionSummary.details;
|
|
2398
|
+
summaryUsage = extensionSummary.usage;
|
|
2360
2399
|
}
|
|
2361
2400
|
// Determine the new leaf position based on target type
|
|
2362
2401
|
let newLeafId;
|
|
@@ -2364,18 +2403,12 @@ export class AgentSession {
|
|
|
2364
2403
|
if (targetEntry.type === "message" && targetEntry.message.role === "user") {
|
|
2365
2404
|
// User message: leaf = parent (null if root), text goes to editor
|
|
2366
2405
|
newLeafId = targetEntry.parentId;
|
|
2367
|
-
editorText =
|
|
2406
|
+
editorText = contentText(targetEntry.message.content, "");
|
|
2368
2407
|
}
|
|
2369
2408
|
else if (targetEntry.type === "custom_message") {
|
|
2370
2409
|
// Custom message: leaf = parent (null if root), text goes to editor
|
|
2371
2410
|
newLeafId = targetEntry.parentId;
|
|
2372
|
-
editorText =
|
|
2373
|
-
typeof targetEntry.content === "string"
|
|
2374
|
-
? targetEntry.content
|
|
2375
|
-
: targetEntry.content
|
|
2376
|
-
.filter((c) => c.type === "text")
|
|
2377
|
-
.map((c) => c.text)
|
|
2378
|
-
.join("");
|
|
2411
|
+
editorText = contentText(targetEntry.content, "");
|
|
2379
2412
|
}
|
|
2380
2413
|
else {
|
|
2381
2414
|
// Non-user message: leaf = selected node
|
|
@@ -2386,7 +2419,7 @@ export class AgentSession {
|
|
|
2386
2419
|
let summaryEntry;
|
|
2387
2420
|
if (summaryText) {
|
|
2388
2421
|
// Create summary at target position (can be null for root)
|
|
2389
|
-
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension);
|
|
2422
|
+
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension, summaryUsage);
|
|
2390
2423
|
summaryEntry = this.sessionManager.getEntry(summaryId);
|
|
2391
2424
|
// Attach label to the summary entry
|
|
2392
2425
|
if (label) {
|
|
@@ -2434,24 +2467,13 @@ export class AgentSession {
|
|
|
2434
2467
|
continue;
|
|
2435
2468
|
if (entry.message.role !== "user")
|
|
2436
2469
|
continue;
|
|
2437
|
-
const text =
|
|
2470
|
+
const text = contentText(entry.message.content, "");
|
|
2438
2471
|
if (text) {
|
|
2439
2472
|
result.push({ entryId: entry.id, text });
|
|
2440
2473
|
}
|
|
2441
2474
|
}
|
|
2442
2475
|
return result;
|
|
2443
2476
|
}
|
|
2444
|
-
_extractUserMessageText(content) {
|
|
2445
|
-
if (typeof content === "string")
|
|
2446
|
-
return content;
|
|
2447
|
-
if (Array.isArray(content)) {
|
|
2448
|
-
return content
|
|
2449
|
-
.filter((c) => c.type === "text")
|
|
2450
|
-
.map((c) => c.text)
|
|
2451
|
-
.join("");
|
|
2452
|
-
}
|
|
2453
|
-
return "";
|
|
2454
|
-
}
|
|
2455
2477
|
/**
|
|
2456
2478
|
* Get session statistics. Aggregates over ALL session entries (including
|
|
2457
2479
|
* history that was compacted away), so token/cost totals reflect what was
|
|
@@ -2463,12 +2485,11 @@ export class AgentSession {
|
|
|
2463
2485
|
let toolResults = 0;
|
|
2464
2486
|
let totalMessages = 0;
|
|
2465
2487
|
let toolCalls = 0;
|
|
2466
|
-
|
|
2467
|
-
let totalOutput = 0;
|
|
2468
|
-
let totalCacheRead = 0;
|
|
2469
|
-
let totalCacheWrite = 0;
|
|
2470
|
-
let totalCost = 0;
|
|
2488
|
+
const usageTotals = createUsageTotals();
|
|
2471
2489
|
for (const entry of this.sessionManager.getEntries()) {
|
|
2490
|
+
if ((entry.type === "branch_summary" || entry.type === "compaction") && entry.usage) {
|
|
2491
|
+
addUsageToTotals(usageTotals, entry.usage);
|
|
2492
|
+
}
|
|
2472
2493
|
if (entry.type !== "message")
|
|
2473
2494
|
continue;
|
|
2474
2495
|
totalMessages++;
|
|
@@ -2478,6 +2499,9 @@ export class AgentSession {
|
|
|
2478
2499
|
}
|
|
2479
2500
|
else if (message.role === "toolResult") {
|
|
2480
2501
|
toolResults++;
|
|
2502
|
+
if (message.usage) {
|
|
2503
|
+
addUsageToTotals(usageTotals, message.usage);
|
|
2504
|
+
}
|
|
2481
2505
|
}
|
|
2482
2506
|
else if (message.role === "assistant") {
|
|
2483
2507
|
assistantMessages++;
|
|
@@ -2485,12 +2509,7 @@ export class AgentSession {
|
|
|
2485
2509
|
if (Array.isArray(assistantMsg.content)) {
|
|
2486
2510
|
toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
|
|
2487
2511
|
}
|
|
2488
|
-
|
|
2489
|
-
totalInput += usage.input;
|
|
2490
|
-
totalOutput += usage.output;
|
|
2491
|
-
totalCacheRead += usage.cacheRead;
|
|
2492
|
-
totalCacheWrite += usage.cacheWrite;
|
|
2493
|
-
totalCost += usage.cost.total;
|
|
2512
|
+
addUsageToTotals(usageTotals, assistantMsg.usage);
|
|
2494
2513
|
}
|
|
2495
2514
|
}
|
|
2496
2515
|
return {
|
|
@@ -2502,13 +2521,13 @@ export class AgentSession {
|
|
|
2502
2521
|
toolResults,
|
|
2503
2522
|
totalMessages,
|
|
2504
2523
|
tokens: {
|
|
2505
|
-
input:
|
|
2506
|
-
output:
|
|
2507
|
-
cacheRead:
|
|
2508
|
-
cacheWrite:
|
|
2509
|
-
total:
|
|
2524
|
+
input: usageTotals.input,
|
|
2525
|
+
output: usageTotals.output,
|
|
2526
|
+
cacheRead: usageTotals.cacheRead,
|
|
2527
|
+
cacheWrite: usageTotals.cacheWrite,
|
|
2528
|
+
total: usageTotals.input + usageTotals.output + usageTotals.cacheRead + usageTotals.cacheWrite,
|
|
2510
2529
|
},
|
|
2511
|
-
cost:
|
|
2530
|
+
cost: usageTotals.cost,
|
|
2512
2531
|
contextUsage: this.getContextUsage(),
|
|
2513
2532
|
};
|
|
2514
2533
|
}
|