@averyyy/pi-coding-agent 0.80.10-piclient.2 → 0.81.1-piclient.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 +86 -58
- 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 +6 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +23 -4
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +75 -29
- 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/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";
|
|
@@ -36,6 +37,7 @@ import { buildSystemPrompt } from "./system-prompt.js";
|
|
|
36
37
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
37
38
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
38
39
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
40
|
+
import { addUsageToTotals, createUsageTotals } from "./usage-totals.js";
|
|
39
41
|
/**
|
|
40
42
|
* Parse a skill block from message text.
|
|
41
43
|
* Returns null if the text doesn't contain a skill block.
|
|
@@ -286,7 +288,7 @@ export class AgentSession {
|
|
|
286
288
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
287
289
|
}
|
|
288
290
|
async _getSummarizationRequestAuth(model) {
|
|
289
|
-
if (this.agent.
|
|
291
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
290
292
|
return this._getRequiredRequestAuth(model);
|
|
291
293
|
}
|
|
292
294
|
try {
|
|
@@ -404,6 +406,7 @@ export class AgentSession {
|
|
|
404
406
|
content: result.content,
|
|
405
407
|
details: result.details,
|
|
406
408
|
isError,
|
|
409
|
+
usage: result.usage,
|
|
407
410
|
})
|
|
408
411
|
: undefined;
|
|
409
412
|
const finalContent = hookResult?.content ?? result.content;
|
|
@@ -416,6 +419,7 @@ export class AgentSession {
|
|
|
416
419
|
content: hookResult.content,
|
|
417
420
|
details: hookResult.details,
|
|
418
421
|
isError: hookResult.isError ?? isError,
|
|
422
|
+
usage: hookResult.usage,
|
|
419
423
|
};
|
|
420
424
|
};
|
|
421
425
|
}
|
|
@@ -492,7 +496,7 @@ export class AgentSession {
|
|
|
492
496
|
// This ensures the UI sees the updated queue state
|
|
493
497
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
494
498
|
this._overflowRecoveryAttempted = false;
|
|
495
|
-
const messageText =
|
|
499
|
+
const messageText = contentText(event.message.content, "");
|
|
496
500
|
if (messageText) {
|
|
497
501
|
// Check steering queue first
|
|
498
502
|
const steeringIndex = this._steeringMessages.indexOf(messageText);
|
|
@@ -568,16 +572,6 @@ export class AgentSession {
|
|
|
568
572
|
}
|
|
569
573
|
return false;
|
|
570
574
|
}
|
|
571
|
-
/** Extract text content from a message */
|
|
572
|
-
_getUserMessageText(message) {
|
|
573
|
-
if (message.role !== "user")
|
|
574
|
-
return "";
|
|
575
|
-
const content = message.content;
|
|
576
|
-
if (typeof content === "string")
|
|
577
|
-
return content;
|
|
578
|
-
const textBlocks = content.filter((c) => c.type === "text");
|
|
579
|
-
return textBlocks.map((c) => c.text).join("");
|
|
580
|
-
}
|
|
581
575
|
/** Find the last assistant message in agent state (including aborted ones) */
|
|
582
576
|
_findLastAssistantMessage() {
|
|
583
577
|
const messages = this.agent.state.messages;
|
|
@@ -1042,7 +1036,7 @@ export class AgentSession {
|
|
|
1042
1036
|
if (!model || !transcript)
|
|
1043
1037
|
return;
|
|
1044
1038
|
try {
|
|
1045
|
-
const stream = await this.agent.
|
|
1039
|
+
const stream = await this.agent.streamFunction(model, {
|
|
1046
1040
|
systemPrompt: this.systemPrompt,
|
|
1047
1041
|
messages: [
|
|
1048
1042
|
{
|
|
@@ -1691,8 +1685,17 @@ export class AgentSession {
|
|
|
1691
1685
|
this.sessionManager.replaceTree(result.entries, result.leafId);
|
|
1692
1686
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1693
1687
|
this.agent.state.messages = sessionContext.messages;
|
|
1688
|
+
const firstKeptEntryId = result.compaction.firstKeptEntryId;
|
|
1689
|
+
if (!firstKeptEntryId) {
|
|
1690
|
+
throw new Error("Pi-server compaction result is missing firstKeptEntryId");
|
|
1691
|
+
}
|
|
1692
|
+
const compaction = result.compaction;
|
|
1694
1693
|
const compactionResult = {
|
|
1695
|
-
|
|
1694
|
+
summary: compaction.summary,
|
|
1695
|
+
firstKeptEntryId,
|
|
1696
|
+
tokensBefore: compaction.tokensBefore,
|
|
1697
|
+
usage: compaction.usage,
|
|
1698
|
+
details: compaction.details,
|
|
1696
1699
|
estimatedTokensAfter: estimateMessagesTokens(sessionContext.messages),
|
|
1697
1700
|
};
|
|
1698
1701
|
const savedCompactionEntry = this.sessionManager.getEntry(result.compactionEntry.id);
|
|
@@ -1784,26 +1787,29 @@ export class AgentSession {
|
|
|
1784
1787
|
let summary;
|
|
1785
1788
|
let firstKeptEntryId;
|
|
1786
1789
|
let tokensBefore;
|
|
1790
|
+
let usage;
|
|
1787
1791
|
let details;
|
|
1788
1792
|
if (extensionCompaction) {
|
|
1789
1793
|
// Extension provided compaction content
|
|
1790
1794
|
summary = extensionCompaction.summary;
|
|
1791
1795
|
firstKeptEntryId = extensionCompaction.firstKeptEntryId;
|
|
1792
1796
|
tokensBefore = extensionCompaction.tokensBefore;
|
|
1797
|
+
usage = extensionCompaction.usage;
|
|
1793
1798
|
details = extensionCompaction.details;
|
|
1794
1799
|
}
|
|
1795
1800
|
else {
|
|
1796
1801
|
// Generate compaction result
|
|
1797
|
-
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.
|
|
1802
|
+
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" }));
|
|
1798
1803
|
summary = result.summary;
|
|
1799
1804
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
1800
1805
|
tokensBefore = result.tokensBefore;
|
|
1806
|
+
usage = result.usage;
|
|
1801
1807
|
details = result.details;
|
|
1802
1808
|
}
|
|
1803
1809
|
if (this._compactionAbortController.signal.aborted) {
|
|
1804
1810
|
throw new Error("Compaction cancelled");
|
|
1805
1811
|
}
|
|
1806
|
-
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
|
|
1812
|
+
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1807
1813
|
const newEntries = this.sessionManager.getEntries();
|
|
1808
1814
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1809
1815
|
this.agent.state.messages = sessionContext.messages;
|
|
@@ -1824,6 +1830,7 @@ export class AgentSession {
|
|
|
1824
1830
|
firstKeptEntryId,
|
|
1825
1831
|
tokensBefore,
|
|
1826
1832
|
estimatedTokensAfter,
|
|
1833
|
+
usage,
|
|
1827
1834
|
details,
|
|
1828
1835
|
};
|
|
1829
1836
|
this._emit({
|
|
@@ -1980,7 +1987,7 @@ export class AgentSession {
|
|
|
1980
1987
|
let apiKey;
|
|
1981
1988
|
let headers;
|
|
1982
1989
|
let env;
|
|
1983
|
-
if (this.agent.
|
|
1990
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
1984
1991
|
const authResult = await this._modelRuntime.getAuth(this.model);
|
|
1985
1992
|
if (!authResult?.auth.apiKey)
|
|
1986
1993
|
return false;
|
|
@@ -2054,20 +2061,23 @@ export class AgentSession {
|
|
|
2054
2061
|
let summary;
|
|
2055
2062
|
let firstKeptEntryId;
|
|
2056
2063
|
let tokensBefore;
|
|
2064
|
+
let usage;
|
|
2057
2065
|
let details;
|
|
2058
2066
|
if (extensionCompaction) {
|
|
2059
2067
|
// Extension provided compaction content
|
|
2060
2068
|
summary = extensionCompaction.summary;
|
|
2061
2069
|
firstKeptEntryId = extensionCompaction.firstKeptEntryId;
|
|
2062
2070
|
tokensBefore = extensionCompaction.tokensBefore;
|
|
2071
|
+
usage = extensionCompaction.usage;
|
|
2063
2072
|
details = extensionCompaction.details;
|
|
2064
2073
|
}
|
|
2065
2074
|
else {
|
|
2066
2075
|
// Generate compaction result
|
|
2067
|
-
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.
|
|
2076
|
+
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 }));
|
|
2068
2077
|
summary = compactResult.summary;
|
|
2069
2078
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
2070
2079
|
tokensBefore = compactResult.tokensBefore;
|
|
2080
|
+
usage = compactResult.usage;
|
|
2071
2081
|
details = compactResult.details;
|
|
2072
2082
|
}
|
|
2073
2083
|
if (this._autoCompactionAbortController.signal.aborted) {
|
|
@@ -2080,7 +2090,7 @@ export class AgentSession {
|
|
|
2080
2090
|
});
|
|
2081
2091
|
return false;
|
|
2082
2092
|
}
|
|
2083
|
-
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
|
|
2093
|
+
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
2084
2094
|
const newEntries = this.sessionManager.getEntries();
|
|
2085
2095
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2086
2096
|
this.agent.state.messages = sessionContext.messages;
|
|
@@ -2101,6 +2111,7 @@ export class AgentSession {
|
|
|
2101
2111
|
firstKeptEntryId,
|
|
2102
2112
|
tokensBefore,
|
|
2103
2113
|
estimatedTokensAfter,
|
|
2114
|
+
usage,
|
|
2104
2115
|
details,
|
|
2105
2116
|
};
|
|
2106
2117
|
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
@@ -2388,6 +2399,10 @@ export class AgentSession {
|
|
|
2388
2399
|
this._modelRuntime.registerProvider(name, config);
|
|
2389
2400
|
this._refreshCurrentModelFromRegistry();
|
|
2390
2401
|
},
|
|
2402
|
+
registerNativeProvider: (provider) => {
|
|
2403
|
+
this._modelRuntime.registerNativeProvider(provider);
|
|
2404
|
+
this._refreshCurrentModelFromRegistry();
|
|
2405
|
+
},
|
|
2391
2406
|
unregisterProvider: (name) => {
|
|
2392
2407
|
this._modelRuntime.unregisterProvider(name);
|
|
2393
2408
|
this._refreshCurrentModelFromRegistry();
|
|
@@ -2551,6 +2566,34 @@ export class AgentSession {
|
|
|
2551
2566
|
return false;
|
|
2552
2567
|
return isRetryableAssistantError(message);
|
|
2553
2568
|
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Retry policy + callbacks shared by compaction and branch-summary summarization calls.
|
|
2571
|
+
* Uses the same `settings.retry` budget/backoff as agent-turn retries so a single transient
|
|
2572
|
+
* stream drop no longer fails the whole operation. `source` carries the context
|
|
2573
|
+
* the TUI needs to render the retry and recreate the underlying indicator.
|
|
2574
|
+
*/
|
|
2575
|
+
_summarizationRetryCallbacks(source) {
|
|
2576
|
+
return {
|
|
2577
|
+
onRetryScheduled: (attempt, maxAttempts, delayMs, errorMessage) => {
|
|
2578
|
+
this._emit({
|
|
2579
|
+
type: "summarization_retry_scheduled",
|
|
2580
|
+
attempt,
|
|
2581
|
+
maxAttempts,
|
|
2582
|
+
delayMs,
|
|
2583
|
+
errorMessage,
|
|
2584
|
+
});
|
|
2585
|
+
},
|
|
2586
|
+
onRetryAttemptStart: () => {
|
|
2587
|
+
this._emit({
|
|
2588
|
+
type: "summarization_retry_attempt_start",
|
|
2589
|
+
...source,
|
|
2590
|
+
});
|
|
2591
|
+
},
|
|
2592
|
+
onRetryFinished: () => {
|
|
2593
|
+
this._emit({ type: "summarization_retry_finished" });
|
|
2594
|
+
},
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2554
2597
|
/**
|
|
2555
2598
|
* Prepare a retryable error for continuation with exponential backoff.
|
|
2556
2599
|
* @returns true if the caller should continue the agent, false otherwise
|
|
@@ -2813,6 +2856,7 @@ export class AgentSession {
|
|
|
2813
2856
|
// Run default summarizer if needed
|
|
2814
2857
|
let summaryText;
|
|
2815
2858
|
let summaryDetails;
|
|
2859
|
+
let summaryUsage;
|
|
2816
2860
|
if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
|
|
2817
2861
|
const model = this.model;
|
|
2818
2862
|
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
|
|
@@ -2826,7 +2870,9 @@ export class AgentSession {
|
|
|
2826
2870
|
customInstructions,
|
|
2827
2871
|
replaceInstructions,
|
|
2828
2872
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
2829
|
-
streamFn: this.agent.
|
|
2873
|
+
streamFn: this.agent.streamFunction,
|
|
2874
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
2875
|
+
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
2830
2876
|
});
|
|
2831
2877
|
if (result.aborted) {
|
|
2832
2878
|
return { cancelled: true, aborted: true };
|
|
@@ -2835,6 +2881,7 @@ export class AgentSession {
|
|
|
2835
2881
|
throw new Error(result.error);
|
|
2836
2882
|
}
|
|
2837
2883
|
summaryText = result.summary;
|
|
2884
|
+
summaryUsage = result.usage;
|
|
2838
2885
|
summaryDetails = {
|
|
2839
2886
|
readFiles: result.readFiles || [],
|
|
2840
2887
|
modifiedFiles: result.modifiedFiles || [],
|
|
@@ -2843,6 +2890,7 @@ export class AgentSession {
|
|
|
2843
2890
|
else if (extensionSummary) {
|
|
2844
2891
|
summaryText = extensionSummary.summary;
|
|
2845
2892
|
summaryDetails = extensionSummary.details;
|
|
2893
|
+
summaryUsage = extensionSummary.usage;
|
|
2846
2894
|
}
|
|
2847
2895
|
// Determine the new leaf position based on target type
|
|
2848
2896
|
let newLeafId;
|
|
@@ -2850,18 +2898,12 @@ export class AgentSession {
|
|
|
2850
2898
|
if (targetEntry.type === "message" && targetEntry.message.role === "user") {
|
|
2851
2899
|
// User message: leaf = parent (null if root), text goes to editor
|
|
2852
2900
|
newLeafId = targetEntry.parentId;
|
|
2853
|
-
editorText =
|
|
2901
|
+
editorText = contentText(targetEntry.message.content, "");
|
|
2854
2902
|
}
|
|
2855
2903
|
else if (targetEntry.type === "custom_message") {
|
|
2856
2904
|
// Custom message: leaf = parent (null if root), text goes to editor
|
|
2857
2905
|
newLeafId = targetEntry.parentId;
|
|
2858
|
-
editorText =
|
|
2859
|
-
typeof targetEntry.content === "string"
|
|
2860
|
-
? targetEntry.content
|
|
2861
|
-
: targetEntry.content
|
|
2862
|
-
.filter((c) => c.type === "text")
|
|
2863
|
-
.map((c) => c.text)
|
|
2864
|
-
.join("");
|
|
2906
|
+
editorText = contentText(targetEntry.content, "");
|
|
2865
2907
|
}
|
|
2866
2908
|
else {
|
|
2867
2909
|
// Non-user message: leaf = selected node
|
|
@@ -2872,7 +2914,7 @@ export class AgentSession {
|
|
|
2872
2914
|
let summaryEntry;
|
|
2873
2915
|
if (summaryText) {
|
|
2874
2916
|
// Create summary at target position (can be null for root)
|
|
2875
|
-
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension);
|
|
2917
|
+
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension, summaryUsage);
|
|
2876
2918
|
summaryEntry = this.sessionManager.getEntry(summaryId);
|
|
2877
2919
|
// Attach label to the summary entry
|
|
2878
2920
|
if (label) {
|
|
@@ -2927,24 +2969,13 @@ export class AgentSession {
|
|
|
2927
2969
|
continue;
|
|
2928
2970
|
if (entry.message.role !== "user")
|
|
2929
2971
|
continue;
|
|
2930
|
-
const text =
|
|
2972
|
+
const text = contentText(entry.message.content, "");
|
|
2931
2973
|
if (text) {
|
|
2932
2974
|
result.push({ entryId: entry.id, text });
|
|
2933
2975
|
}
|
|
2934
2976
|
}
|
|
2935
2977
|
return result;
|
|
2936
2978
|
}
|
|
2937
|
-
_extractUserMessageText(content) {
|
|
2938
|
-
if (typeof content === "string")
|
|
2939
|
-
return content;
|
|
2940
|
-
if (Array.isArray(content)) {
|
|
2941
|
-
return content
|
|
2942
|
-
.filter((c) => c.type === "text")
|
|
2943
|
-
.map((c) => c.text)
|
|
2944
|
-
.join("");
|
|
2945
|
-
}
|
|
2946
|
-
return "";
|
|
2947
|
-
}
|
|
2948
2979
|
/**
|
|
2949
2980
|
* Get session statistics. Aggregates over ALL session entries (including
|
|
2950
2981
|
* history that was compacted away), so token/cost totals reflect what was
|
|
@@ -2956,12 +2987,11 @@ export class AgentSession {
|
|
|
2956
2987
|
let toolResults = 0;
|
|
2957
2988
|
let totalMessages = 0;
|
|
2958
2989
|
let toolCalls = 0;
|
|
2959
|
-
|
|
2960
|
-
let totalOutput = 0;
|
|
2961
|
-
let totalCacheRead = 0;
|
|
2962
|
-
let totalCacheWrite = 0;
|
|
2963
|
-
let totalCost = 0;
|
|
2990
|
+
const usageTotals = createUsageTotals();
|
|
2964
2991
|
for (const entry of this.sessionManager.getEntries()) {
|
|
2992
|
+
if ((entry.type === "branch_summary" || entry.type === "compaction") && entry.usage) {
|
|
2993
|
+
addUsageToTotals(usageTotals, entry.usage);
|
|
2994
|
+
}
|
|
2965
2995
|
if (entry.type !== "message")
|
|
2966
2996
|
continue;
|
|
2967
2997
|
totalMessages++;
|
|
@@ -2971,6 +3001,9 @@ export class AgentSession {
|
|
|
2971
3001
|
}
|
|
2972
3002
|
else if (message.role === "toolResult") {
|
|
2973
3003
|
toolResults++;
|
|
3004
|
+
if (message.usage) {
|
|
3005
|
+
addUsageToTotals(usageTotals, message.usage);
|
|
3006
|
+
}
|
|
2974
3007
|
}
|
|
2975
3008
|
else if (message.role === "assistant") {
|
|
2976
3009
|
assistantMessages++;
|
|
@@ -2978,12 +3011,7 @@ export class AgentSession {
|
|
|
2978
3011
|
if (Array.isArray(assistantMsg.content)) {
|
|
2979
3012
|
toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
|
|
2980
3013
|
}
|
|
2981
|
-
|
|
2982
|
-
totalInput += usage.input;
|
|
2983
|
-
totalOutput += usage.output;
|
|
2984
|
-
totalCacheRead += usage.cacheRead;
|
|
2985
|
-
totalCacheWrite += usage.cacheWrite;
|
|
2986
|
-
totalCost += usage.cost.total;
|
|
3014
|
+
addUsageToTotals(usageTotals, assistantMsg.usage);
|
|
2987
3015
|
}
|
|
2988
3016
|
}
|
|
2989
3017
|
return {
|
|
@@ -2995,13 +3023,13 @@ export class AgentSession {
|
|
|
2995
3023
|
toolResults,
|
|
2996
3024
|
totalMessages,
|
|
2997
3025
|
tokens: {
|
|
2998
|
-
input:
|
|
2999
|
-
output:
|
|
3000
|
-
cacheRead:
|
|
3001
|
-
cacheWrite:
|
|
3002
|
-
total:
|
|
3026
|
+
input: usageTotals.input,
|
|
3027
|
+
output: usageTotals.output,
|
|
3028
|
+
cacheRead: usageTotals.cacheRead,
|
|
3029
|
+
cacheWrite: usageTotals.cacheWrite,
|
|
3030
|
+
total: usageTotals.input + usageTotals.output + usageTotals.cacheRead + usageTotals.cacheWrite,
|
|
3003
3031
|
},
|
|
3004
|
-
cost:
|
|
3032
|
+
cost: usageTotals.cost,
|
|
3005
3033
|
contextUsage: this.getContextUsage(),
|
|
3006
3034
|
};
|
|
3007
3035
|
}
|