@averyyy/pi-coding-agent 0.80.10-piclient.2 → 0.82.0-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 +101 -0
- package/README.md +19 -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/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.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 +33 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +91 -59
- 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 +83 -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 +35 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +20 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.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 +19 -4
- 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 +9 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +7 -3
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +42 -21
- 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 +21 -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/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.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/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.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 +101 -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/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.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/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +2 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -68
- 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 +5 -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/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +3 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +9 -4
- package/docs/custom-provider.md +33 -2
- package/docs/environment-variables.md +88 -0
- package/docs/extensions.md +61 -11
- package/docs/index.md +2 -0
- package/docs/json.md +5 -1
- package/docs/llama-cpp.md +99 -0
- package/docs/models.md +6 -2
- package/docs/prompt-templates.md +1 -0
- package/docs/providers.md +19 -1
- package/docs/rpc.md +104 -8
- package/docs/sdk.md +3 -0
- package/docs/session-format.md +17 -3
- package/docs/settings.md +1 -1
- package/docs/tui.md +41 -26
- package/docs/usage.md +2 -14
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/custom-compaction.ts +4 -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/handoff.ts +9 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +3 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +5 -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
|
|
@@ -2647,6 +2690,7 @@ export class AgentSession {
|
|
|
2647
2690
|
* @param command The bash command to execute
|
|
2648
2691
|
* @param onChunk Optional streaming callback for output
|
|
2649
2692
|
* @param options.excludeFromContext If true, command output won't be sent to LLM (!! prefix)
|
|
2693
|
+
* @param options.id Optional identifier included in bash execution update events
|
|
2650
2694
|
* @param options.operations Custom BashOperations for remote execution
|
|
2651
2695
|
*/
|
|
2652
2696
|
async executeBash(command, onChunk, options) {
|
|
@@ -2657,7 +2701,10 @@ export class AgentSession {
|
|
|
2657
2701
|
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
|
2658
2702
|
try {
|
|
2659
2703
|
const result = await executeBashWithOperations(resolvedCommand, this.sessionManager.getCwd(), options?.operations ?? createLocalBashOperations({ shellPath }), {
|
|
2660
|
-
onChunk
|
|
2704
|
+
onChunk: (delta) => {
|
|
2705
|
+
onChunk?.(delta);
|
|
2706
|
+
this._emit({ type: "bash_execution_update", id: options?.id, delta });
|
|
2707
|
+
},
|
|
2661
2708
|
signal: this._bashAbortController.signal,
|
|
2662
2709
|
});
|
|
2663
2710
|
this.recordBashResult(command, result, options);
|
|
@@ -2813,6 +2860,7 @@ export class AgentSession {
|
|
|
2813
2860
|
// Run default summarizer if needed
|
|
2814
2861
|
let summaryText;
|
|
2815
2862
|
let summaryDetails;
|
|
2863
|
+
let summaryUsage;
|
|
2816
2864
|
if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
|
|
2817
2865
|
const model = this.model;
|
|
2818
2866
|
const { apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
|
|
@@ -2826,7 +2874,9 @@ export class AgentSession {
|
|
|
2826
2874
|
customInstructions,
|
|
2827
2875
|
replaceInstructions,
|
|
2828
2876
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
2829
|
-
streamFn: this.agent.
|
|
2877
|
+
streamFn: this.agent.streamFunction,
|
|
2878
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
2879
|
+
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
2830
2880
|
});
|
|
2831
2881
|
if (result.aborted) {
|
|
2832
2882
|
return { cancelled: true, aborted: true };
|
|
@@ -2835,6 +2885,7 @@ export class AgentSession {
|
|
|
2835
2885
|
throw new Error(result.error);
|
|
2836
2886
|
}
|
|
2837
2887
|
summaryText = result.summary;
|
|
2888
|
+
summaryUsage = result.usage;
|
|
2838
2889
|
summaryDetails = {
|
|
2839
2890
|
readFiles: result.readFiles || [],
|
|
2840
2891
|
modifiedFiles: result.modifiedFiles || [],
|
|
@@ -2843,6 +2894,7 @@ export class AgentSession {
|
|
|
2843
2894
|
else if (extensionSummary) {
|
|
2844
2895
|
summaryText = extensionSummary.summary;
|
|
2845
2896
|
summaryDetails = extensionSummary.details;
|
|
2897
|
+
summaryUsage = extensionSummary.usage;
|
|
2846
2898
|
}
|
|
2847
2899
|
// Determine the new leaf position based on target type
|
|
2848
2900
|
let newLeafId;
|
|
@@ -2850,18 +2902,12 @@ export class AgentSession {
|
|
|
2850
2902
|
if (targetEntry.type === "message" && targetEntry.message.role === "user") {
|
|
2851
2903
|
// User message: leaf = parent (null if root), text goes to editor
|
|
2852
2904
|
newLeafId = targetEntry.parentId;
|
|
2853
|
-
editorText =
|
|
2905
|
+
editorText = contentText(targetEntry.message.content, "");
|
|
2854
2906
|
}
|
|
2855
2907
|
else if (targetEntry.type === "custom_message") {
|
|
2856
2908
|
// Custom message: leaf = parent (null if root), text goes to editor
|
|
2857
2909
|
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("");
|
|
2910
|
+
editorText = contentText(targetEntry.content, "");
|
|
2865
2911
|
}
|
|
2866
2912
|
else {
|
|
2867
2913
|
// Non-user message: leaf = selected node
|
|
@@ -2872,7 +2918,7 @@ export class AgentSession {
|
|
|
2872
2918
|
let summaryEntry;
|
|
2873
2919
|
if (summaryText) {
|
|
2874
2920
|
// Create summary at target position (can be null for root)
|
|
2875
|
-
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension);
|
|
2921
|
+
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension, summaryUsage);
|
|
2876
2922
|
summaryEntry = this.sessionManager.getEntry(summaryId);
|
|
2877
2923
|
// Attach label to the summary entry
|
|
2878
2924
|
if (label) {
|
|
@@ -2927,24 +2973,13 @@ export class AgentSession {
|
|
|
2927
2973
|
continue;
|
|
2928
2974
|
if (entry.message.role !== "user")
|
|
2929
2975
|
continue;
|
|
2930
|
-
const text =
|
|
2976
|
+
const text = contentText(entry.message.content, "");
|
|
2931
2977
|
if (text) {
|
|
2932
2978
|
result.push({ entryId: entry.id, text });
|
|
2933
2979
|
}
|
|
2934
2980
|
}
|
|
2935
2981
|
return result;
|
|
2936
2982
|
}
|
|
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
2983
|
/**
|
|
2949
2984
|
* Get session statistics. Aggregates over ALL session entries (including
|
|
2950
2985
|
* history that was compacted away), so token/cost totals reflect what was
|
|
@@ -2956,12 +2991,11 @@ export class AgentSession {
|
|
|
2956
2991
|
let toolResults = 0;
|
|
2957
2992
|
let totalMessages = 0;
|
|
2958
2993
|
let toolCalls = 0;
|
|
2959
|
-
|
|
2960
|
-
let totalOutput = 0;
|
|
2961
|
-
let totalCacheRead = 0;
|
|
2962
|
-
let totalCacheWrite = 0;
|
|
2963
|
-
let totalCost = 0;
|
|
2994
|
+
const usageTotals = createUsageTotals();
|
|
2964
2995
|
for (const entry of this.sessionManager.getEntries()) {
|
|
2996
|
+
if ((entry.type === "branch_summary" || entry.type === "compaction") && entry.usage) {
|
|
2997
|
+
addUsageToTotals(usageTotals, entry.usage);
|
|
2998
|
+
}
|
|
2965
2999
|
if (entry.type !== "message")
|
|
2966
3000
|
continue;
|
|
2967
3001
|
totalMessages++;
|
|
@@ -2971,6 +3005,9 @@ export class AgentSession {
|
|
|
2971
3005
|
}
|
|
2972
3006
|
else if (message.role === "toolResult") {
|
|
2973
3007
|
toolResults++;
|
|
3008
|
+
if (message.usage) {
|
|
3009
|
+
addUsageToTotals(usageTotals, message.usage);
|
|
3010
|
+
}
|
|
2974
3011
|
}
|
|
2975
3012
|
else if (message.role === "assistant") {
|
|
2976
3013
|
assistantMessages++;
|
|
@@ -2978,12 +3015,7 @@ export class AgentSession {
|
|
|
2978
3015
|
if (Array.isArray(assistantMsg.content)) {
|
|
2979
3016
|
toolCalls += assistantMsg.content.filter((c) => c.type === "toolCall").length;
|
|
2980
3017
|
}
|
|
2981
|
-
|
|
2982
|
-
totalInput += usage.input;
|
|
2983
|
-
totalOutput += usage.output;
|
|
2984
|
-
totalCacheRead += usage.cacheRead;
|
|
2985
|
-
totalCacheWrite += usage.cacheWrite;
|
|
2986
|
-
totalCost += usage.cost.total;
|
|
3018
|
+
addUsageToTotals(usageTotals, assistantMsg.usage);
|
|
2987
3019
|
}
|
|
2988
3020
|
}
|
|
2989
3021
|
return {
|
|
@@ -2995,13 +3027,13 @@ export class AgentSession {
|
|
|
2995
3027
|
toolResults,
|
|
2996
3028
|
totalMessages,
|
|
2997
3029
|
tokens: {
|
|
2998
|
-
input:
|
|
2999
|
-
output:
|
|
3000
|
-
cacheRead:
|
|
3001
|
-
cacheWrite:
|
|
3002
|
-
total:
|
|
3030
|
+
input: usageTotals.input,
|
|
3031
|
+
output: usageTotals.output,
|
|
3032
|
+
cacheRead: usageTotals.cacheRead,
|
|
3033
|
+
cacheWrite: usageTotals.cacheWrite,
|
|
3034
|
+
total: usageTotals.input + usageTotals.output + usageTotals.cacheRead + usageTotals.cacheWrite,
|
|
3003
3035
|
},
|
|
3004
|
-
cost:
|
|
3036
|
+
cost: usageTotals.cost,
|
|
3005
3037
|
contextUsage: this.getContextUsage(),
|
|
3006
3038
|
};
|
|
3007
3039
|
}
|