@cydm/pie 1.0.14 → 1.0.16
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/builtin/extensions/ask-user/index.js +3 -2
- package/dist/builtin/extensions/plan-mode/index.js +3 -2
- package/dist/builtin/extensions/subagent/index.js +4 -3
- package/dist/builtin/extensions/todo/index.js +3 -2
- package/dist/chunks/{chunk-D7NAXU7F.js → chunk-5DA2D3K2.js} +79 -1097
- package/dist/chunks/{chunk-EFG2MQFD.js → chunk-62XU6P2H.js} +2 -2
- package/dist/chunks/{chunk-LF5Q7BVU.js → chunk-7GAYJ6AF.js} +726 -89
- package/dist/chunks/chunk-VE2HDCNB.js +1029 -0
- package/dist/chunks/{src-LZC56DRG.js → src-6WPNVGT2.js} +2 -1
- package/dist/chunks/test-stream-ZSKNLUEJ.js +94 -0
- package/dist/cli.js +572 -140
- package/package.json +2 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
|
-
Agent
|
|
3
|
+
Agent
|
|
4
|
+
} from "./chunk-VE2HDCNB.js";
|
|
5
|
+
import {
|
|
4
6
|
FileSystemGateway,
|
|
5
7
|
Type,
|
|
6
8
|
completeSimple,
|
|
@@ -8,7 +10,7 @@ import {
|
|
|
8
10
|
getFileSystem,
|
|
9
11
|
getPlatformConfig,
|
|
10
12
|
streamSimple
|
|
11
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-5DA2D3K2.js";
|
|
12
14
|
import {
|
|
13
15
|
__require
|
|
14
16
|
} from "./chunk-TG2EQLX2.js";
|
|
@@ -1469,36 +1471,66 @@ var DEFAULT_COMPACTION_CONFIG = {
|
|
|
1469
1471
|
compactPrompt: COMPACT_PROMPT,
|
|
1470
1472
|
summaryPrefix: SUMMARY_PREFIX
|
|
1471
1473
|
};
|
|
1474
|
+
var APPROX_BYTES_PER_TOKEN = 4;
|
|
1475
|
+
var RESIZED_IMAGE_BYTES_ESTIMATE = 7373;
|
|
1472
1476
|
function estimateTokens(message) {
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
return Math.ceil(chars / 4);
|
|
1477
|
+
return approximateBytesAsTokens(estimateModelVisibleBytes(message));
|
|
1478
|
+
}
|
|
1479
|
+
function calculateTotalTokens(messages) {
|
|
1480
|
+
return messages.reduce((sum, m) => sum + estimateTokens(m), 0);
|
|
1481
|
+
}
|
|
1482
|
+
function calculateContextTokens(usage) {
|
|
1483
|
+
return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
1484
|
+
}
|
|
1485
|
+
function getAssistantUsage(message) {
|
|
1486
|
+
if (message.role !== "assistant") {
|
|
1487
|
+
return void 0;
|
|
1485
1488
|
}
|
|
1486
|
-
if (message.
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1489
|
+
if (message.stopReason === "aborted" || message.stopReason === "error") {
|
|
1490
|
+
return void 0;
|
|
1491
|
+
}
|
|
1492
|
+
if (calculateContextTokens(message.usage) <= 0) {
|
|
1493
|
+
return void 0;
|
|
1494
|
+
}
|
|
1495
|
+
return message.usage;
|
|
1496
|
+
}
|
|
1497
|
+
function estimateContextTokens(messages) {
|
|
1498
|
+
const localTokens = calculateTotalTokens(messages);
|
|
1499
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1500
|
+
const usage = getAssistantUsage(messages[i]);
|
|
1501
|
+
if (!usage) {
|
|
1502
|
+
continue;
|
|
1494
1503
|
}
|
|
1495
|
-
|
|
1504
|
+
const providerTokens = calculateContextTokens(usage);
|
|
1505
|
+
const trailingTokens = calculateTotalTokens(messages.slice(i + 1));
|
|
1506
|
+
const usageTokens = providerTokens;
|
|
1507
|
+
return {
|
|
1508
|
+
tokens: Math.max(providerTokens + trailingTokens, localTokens),
|
|
1509
|
+
usageTokens,
|
|
1510
|
+
providerTokens,
|
|
1511
|
+
localTokens,
|
|
1512
|
+
trailingTokens,
|
|
1513
|
+
lastUsageIndex: i
|
|
1514
|
+
};
|
|
1496
1515
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1516
|
+
return {
|
|
1517
|
+
tokens: localTokens,
|
|
1518
|
+
usageTokens: 0,
|
|
1519
|
+
providerTokens: 0,
|
|
1520
|
+
localTokens,
|
|
1521
|
+
trailingTokens: localTokens,
|
|
1522
|
+
lastUsageIndex: null
|
|
1523
|
+
};
|
|
1499
1524
|
}
|
|
1500
|
-
function
|
|
1501
|
-
|
|
1525
|
+
function getAutoCompactTokenLimit(contextWindow, reserveTokens, autoCompactTokenLimit) {
|
|
1526
|
+
const explicitLimit = autoCompactTokenLimit !== void 0 && autoCompactTokenLimit > 0 ? Math.floor(autoCompactTokenLimit) : void 0;
|
|
1527
|
+
if (!contextWindow || contextWindow <= 0) {
|
|
1528
|
+
return explicitLimit;
|
|
1529
|
+
}
|
|
1530
|
+
const reserveLimit = reserveTokens >= contextWindow ? Math.floor(contextWindow * 0.8) : contextWindow - reserveTokens;
|
|
1531
|
+
const windowLimit = Math.floor(contextWindow * 0.9);
|
|
1532
|
+
const defaultLimit = Math.max(1, Math.min(reserveLimit, windowLimit));
|
|
1533
|
+
return explicitLimit !== void 0 ? Math.min(defaultLimit, explicitLimit) : defaultLimit;
|
|
1502
1534
|
}
|
|
1503
1535
|
function isCompactSummaryMessage(message, summaryPrefix = SUMMARY_PREFIX) {
|
|
1504
1536
|
return message.startsWith(`${summaryPrefix}
|
|
@@ -1690,6 +1722,138 @@ function appendFileOperationsToSummary(summary, messages) {
|
|
|
1690
1722
|
const { readFiles, modifiedFiles } = computeFileLists(fileOps);
|
|
1691
1723
|
return `${summary}${formatFileOperations(readFiles, modifiedFiles)}`;
|
|
1692
1724
|
}
|
|
1725
|
+
function estimateModelVisibleBytes(message) {
|
|
1726
|
+
const visibleMessage = normalizeModelVisibleMessage(message);
|
|
1727
|
+
const wrapperBytes = utf8ByteLength(safeStringify(visibleMessage));
|
|
1728
|
+
return wrapperBytes + estimateMessageMediaBytes(message);
|
|
1729
|
+
}
|
|
1730
|
+
function normalizeModelVisibleMessage(message) {
|
|
1731
|
+
if (message.role === "user") {
|
|
1732
|
+
return {
|
|
1733
|
+
role: "user",
|
|
1734
|
+
content: typeof message.content === "string" ? message.content : message.content.map(normalizeUserContentBlock)
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
if (message.role === "assistant") {
|
|
1738
|
+
return {
|
|
1739
|
+
role: "assistant",
|
|
1740
|
+
content: message.content.map((block) => {
|
|
1741
|
+
if (block.type === "text") {
|
|
1742
|
+
return {
|
|
1743
|
+
type: "text",
|
|
1744
|
+
text: block.text,
|
|
1745
|
+
...block.textSignature ? { textSignature: block.textSignature } : {}
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
if (block.type === "thinking") {
|
|
1749
|
+
return {
|
|
1750
|
+
type: "thinking",
|
|
1751
|
+
thinking: block.thinking,
|
|
1752
|
+
...block.thinkingSignature ? { thinkingSignature: block.thinkingSignature } : {}
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
if (block.type === "toolCall") {
|
|
1756
|
+
return {
|
|
1757
|
+
type: "toolCall",
|
|
1758
|
+
id: block.id,
|
|
1759
|
+
name: block.name,
|
|
1760
|
+
arguments: block.arguments ?? {},
|
|
1761
|
+
...block.thoughtSignature ? { thoughtSignature: block.thoughtSignature } : {}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
return block;
|
|
1765
|
+
})
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
if (message.role === "toolResult") {
|
|
1769
|
+
return {
|
|
1770
|
+
role: "toolResult",
|
|
1771
|
+
toolCallId: message.toolCallId,
|
|
1772
|
+
toolName: message.toolName,
|
|
1773
|
+
isError: message.isError,
|
|
1774
|
+
content: message.content.map(normalizeUserContentBlock)
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
return {
|
|
1778
|
+
role: String(message.role ?? "unknown"),
|
|
1779
|
+
content: getMessageText(message)
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
function normalizeUserContentBlock(block) {
|
|
1783
|
+
if (block.type === "text") {
|
|
1784
|
+
return { type: "text", text: block.text };
|
|
1785
|
+
}
|
|
1786
|
+
if (block.type === "image") {
|
|
1787
|
+
return { type: "image", mimeType: block.mimeType };
|
|
1788
|
+
}
|
|
1789
|
+
if (block.type === "audio") {
|
|
1790
|
+
return { type: "audio", mimeType: block.mimeType };
|
|
1791
|
+
}
|
|
1792
|
+
if (block.type === "video") {
|
|
1793
|
+
return { type: "video", mimeType: block.mimeType };
|
|
1794
|
+
}
|
|
1795
|
+
if (block.type === "fileRef") {
|
|
1796
|
+
return {
|
|
1797
|
+
type: "fileRef",
|
|
1798
|
+
url: block.url,
|
|
1799
|
+
mimeType: block.mimeType,
|
|
1800
|
+
modality: block.modality
|
|
1801
|
+
};
|
|
1802
|
+
}
|
|
1803
|
+
return block;
|
|
1804
|
+
}
|
|
1805
|
+
function estimateMessageMediaBytes(message) {
|
|
1806
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
1807
|
+
return message.content.reduce((sum, block) => sum + estimateUserContentBlockMediaBytes(block), 0);
|
|
1808
|
+
}
|
|
1809
|
+
if (message.role === "toolResult") {
|
|
1810
|
+
return message.content.reduce((sum, block) => sum + estimateUserContentBlockMediaBytes(block), 0);
|
|
1811
|
+
}
|
|
1812
|
+
return 0;
|
|
1813
|
+
}
|
|
1814
|
+
function estimateUserContentBlockMediaBytes(block) {
|
|
1815
|
+
if (block.type === "image") {
|
|
1816
|
+
return estimateImageContentBytes(block);
|
|
1817
|
+
}
|
|
1818
|
+
if (block.type === "audio") {
|
|
1819
|
+
return estimateInlineDataBytes(block);
|
|
1820
|
+
}
|
|
1821
|
+
if (block.type === "video") {
|
|
1822
|
+
return estimateInlineDataBytes(block);
|
|
1823
|
+
}
|
|
1824
|
+
return 0;
|
|
1825
|
+
}
|
|
1826
|
+
function estimateImageContentBytes(block) {
|
|
1827
|
+
return Math.max(RESIZED_IMAGE_BYTES_ESTIMATE, estimateInlineDataBytes(block));
|
|
1828
|
+
}
|
|
1829
|
+
function estimateInlineDataBytes(block) {
|
|
1830
|
+
return utf8ByteLength(block.data || "");
|
|
1831
|
+
}
|
|
1832
|
+
function approximateBytesAsTokens(bytes) {
|
|
1833
|
+
return Math.ceil(bytes / APPROX_BYTES_PER_TOKEN);
|
|
1834
|
+
}
|
|
1835
|
+
function safeStringify(value) {
|
|
1836
|
+
try {
|
|
1837
|
+
return JSON.stringify(value) ?? "";
|
|
1838
|
+
} catch {
|
|
1839
|
+
return String(value ?? "");
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
var utf8Encoder = typeof globalThis.TextEncoder === "function" ? new globalThis.TextEncoder() : void 0;
|
|
1843
|
+
function utf8ByteLength(text) {
|
|
1844
|
+
if (utf8Encoder) {
|
|
1845
|
+
return utf8Encoder.encode(text).length;
|
|
1846
|
+
}
|
|
1847
|
+
let bytes = 0;
|
|
1848
|
+
for (const char of text) {
|
|
1849
|
+
const codePoint = char.codePointAt(0) ?? 0;
|
|
1850
|
+
if (codePoint <= 127) bytes += 1;
|
|
1851
|
+
else if (codePoint <= 2047) bytes += 2;
|
|
1852
|
+
else if (codePoint <= 65535) bytes += 3;
|
|
1853
|
+
else bytes += 4;
|
|
1854
|
+
}
|
|
1855
|
+
return bytes;
|
|
1856
|
+
}
|
|
1693
1857
|
function isSyntheticUserEnvelope(text) {
|
|
1694
1858
|
const trimmed = text.trimStart();
|
|
1695
1859
|
return trimmed.startsWith("<environment_context>") || trimmed.startsWith("<turn_aborted>") || trimmed.startsWith("# AGENTS.md instructions") || trimmed.startsWith("## Project Context\nProject-specific instructions from AGENTS.md");
|
|
@@ -2805,13 +2969,20 @@ var AgentSessionAutoCompactScheduler = class {
|
|
|
2805
2969
|
options;
|
|
2806
2970
|
autoCompactTimer;
|
|
2807
2971
|
pendingAutoCompact;
|
|
2972
|
+
runningAutoCompact;
|
|
2973
|
+
pendingWait;
|
|
2974
|
+
resolvePendingWait;
|
|
2808
2975
|
get hasPendingAutoCompact() {
|
|
2809
|
-
return this.autoCompactTimer !== void 0;
|
|
2976
|
+
return this.autoCompactTimer !== void 0 || this.pendingAutoCompact !== void 0 || this.runningAutoCompact !== void 0;
|
|
2977
|
+
}
|
|
2978
|
+
waitForAutoCompact() {
|
|
2979
|
+
return this.pendingWait ?? Promise.resolve();
|
|
2810
2980
|
}
|
|
2811
2981
|
schedule(decision, delayMs = 0) {
|
|
2812
2982
|
if (this.options.getRuntimeGuardTriggered()) {
|
|
2813
2983
|
return;
|
|
2814
2984
|
}
|
|
2985
|
+
this.ensurePendingWait();
|
|
2815
2986
|
this.pendingAutoCompact = decision;
|
|
2816
2987
|
if (this.autoCompactTimer !== void 0) {
|
|
2817
2988
|
return;
|
|
@@ -2822,6 +2993,7 @@ var AgentSessionAutoCompactScheduler = class {
|
|
|
2822
2993
|
const pending = this.pendingAutoCompact;
|
|
2823
2994
|
this.pendingAutoCompact = void 0;
|
|
2824
2995
|
if (!pending || this.options.getDisposed()) {
|
|
2996
|
+
this.resolvePending();
|
|
2825
2997
|
return;
|
|
2826
2998
|
}
|
|
2827
2999
|
if (this.options.isStreaming()) {
|
|
@@ -2829,17 +3001,33 @@ var AgentSessionAutoCompactScheduler = class {
|
|
|
2829
3001
|
this.schedule(pending, 100);
|
|
2830
3002
|
return;
|
|
2831
3003
|
}
|
|
2832
|
-
|
|
3004
|
+
this.runningAutoCompact = this.options.runAutoCompact(pending).catch(() => {
|
|
3005
|
+
}).finally(() => {
|
|
3006
|
+
this.runningAutoCompact = void 0;
|
|
3007
|
+
this.resolvePending();
|
|
3008
|
+
});
|
|
2833
3009
|
}, delayMs);
|
|
2834
3010
|
}
|
|
2835
3011
|
cancel() {
|
|
2836
|
-
if (this.autoCompactTimer
|
|
2837
|
-
|
|
3012
|
+
if (this.autoCompactTimer !== void 0) {
|
|
3013
|
+
const clearTimer = this.options.retry?.clearTimeout ?? defaultClearTimeout;
|
|
3014
|
+
clearTimer(this.autoCompactTimer);
|
|
3015
|
+
this.autoCompactTimer = void 0;
|
|
2838
3016
|
}
|
|
2839
|
-
const clearTimer = this.options.retry?.clearTimeout ?? defaultClearTimeout;
|
|
2840
|
-
clearTimer(this.autoCompactTimer);
|
|
2841
|
-
this.autoCompactTimer = void 0;
|
|
2842
3017
|
this.pendingAutoCompact = void 0;
|
|
3018
|
+
this.resolvePending();
|
|
3019
|
+
}
|
|
3020
|
+
ensurePendingWait() {
|
|
3021
|
+
if (this.pendingWait) return;
|
|
3022
|
+
this.pendingWait = new Promise((resolve2) => {
|
|
3023
|
+
this.resolvePendingWait = resolve2;
|
|
3024
|
+
});
|
|
3025
|
+
}
|
|
3026
|
+
resolvePending() {
|
|
3027
|
+
const resolve2 = this.resolvePendingWait;
|
|
3028
|
+
this.pendingWait = void 0;
|
|
3029
|
+
this.resolvePendingWait = void 0;
|
|
3030
|
+
resolve2?.();
|
|
2843
3031
|
}
|
|
2844
3032
|
};
|
|
2845
3033
|
|
|
@@ -2856,15 +3044,24 @@ var AgentSessionAutoContinueController = class {
|
|
|
2856
3044
|
}
|
|
2857
3045
|
options;
|
|
2858
3046
|
autoContinueTimer;
|
|
3047
|
+
pendingAutoContinue;
|
|
3048
|
+
resolvePendingAutoContinue;
|
|
3049
|
+
get hasPendingAutoContinue() {
|
|
3050
|
+
return this.autoContinueTimer !== void 0 || this.pendingAutoContinue !== void 0;
|
|
3051
|
+
}
|
|
3052
|
+
waitForAutoContinue() {
|
|
3053
|
+
return this.pendingAutoContinue ?? Promise.resolve();
|
|
3054
|
+
}
|
|
2859
3055
|
schedule(messages) {
|
|
2860
3056
|
if (!this.options.getAutoContinueMessage || this.options.getDisposed() || this.autoContinueTimer !== void 0) {
|
|
2861
3057
|
return;
|
|
2862
3058
|
}
|
|
3059
|
+
this.ensurePending();
|
|
2863
3060
|
const setTimer = this.options.retry?.setTimeout ?? defaultSetTimeout2;
|
|
2864
3061
|
const snapshot = messages.slice();
|
|
2865
3062
|
this.autoContinueTimer = setTimer(() => {
|
|
2866
3063
|
this.autoContinueTimer = void 0;
|
|
2867
|
-
void this.maybeScheduleAutoContinue(snapshot);
|
|
3064
|
+
void this.maybeScheduleAutoContinue(snapshot).finally(() => this.resolvePending());
|
|
2868
3065
|
}, 0);
|
|
2869
3066
|
}
|
|
2870
3067
|
cancel() {
|
|
@@ -2874,9 +3071,10 @@ var AgentSessionAutoContinueController = class {
|
|
|
2874
3071
|
const clearTimer = this.options.retry?.clearTimeout ?? defaultClearTimeout2;
|
|
2875
3072
|
clearTimer(this.autoContinueTimer);
|
|
2876
3073
|
this.autoContinueTimer = void 0;
|
|
3074
|
+
this.resolvePending();
|
|
2877
3075
|
}
|
|
2878
3076
|
async maybeScheduleAutoContinue(messages) {
|
|
2879
|
-
if (!this.options.getAutoContinueMessage || this.options.getDisposed() || this.options.getRuntimeGuardTriggered() || this.options.hasQueuedMessages() || this.options.isStreaming()) {
|
|
3077
|
+
if (!this.options.getAutoContinueMessage || this.options.getDisposed() || this.options.getRuntimeGuardTriggered() || this.options.isBlockedByRuntimePolicy() || this.options.hasQueuedMessages() || this.options.isStreaming()) {
|
|
2880
3078
|
if (this.options.hasQueuedMessages()) {
|
|
2881
3079
|
this.options.emit({ type: "auto_continue_skipped", reason: "queued_messages" });
|
|
2882
3080
|
}
|
|
@@ -2900,21 +3098,36 @@ var AgentSessionAutoContinueController = class {
|
|
|
2900
3098
|
this.options.emit({ type: "auto_continue_skipped", reason: reason ?? "no_message" });
|
|
2901
3099
|
return;
|
|
2902
3100
|
}
|
|
2903
|
-
if (this.options.hasQueuedMessages() || this.options.isStreaming()) {
|
|
3101
|
+
if (this.options.hasQueuedMessages() || this.options.isStreaming() || this.options.isBlockedByRuntimePolicy()) {
|
|
2904
3102
|
this.options.emit({ type: "auto_continue_skipped", reason: "runtime_busy" });
|
|
2905
3103
|
return;
|
|
2906
3104
|
}
|
|
2907
3105
|
this.options.emit({ type: "auto_continue_scheduled", reason });
|
|
2908
3106
|
this.options.agent.followUp(message);
|
|
2909
3107
|
const setTimer = this.options.retry?.setTimeout ?? defaultSetTimeout2;
|
|
2910
|
-
|
|
2911
|
-
this.autoContinueTimer =
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
3108
|
+
await new Promise((resolve2) => {
|
|
3109
|
+
this.autoContinueTimer = setTimer(() => {
|
|
3110
|
+
this.autoContinueTimer = void 0;
|
|
3111
|
+
if (this.options.getDisposed()) {
|
|
3112
|
+
resolve2();
|
|
3113
|
+
return;
|
|
3114
|
+
}
|
|
3115
|
+
void this.options.continueTurn().catch(() => {
|
|
3116
|
+
}).finally(resolve2);
|
|
3117
|
+
}, 0);
|
|
3118
|
+
});
|
|
3119
|
+
}
|
|
3120
|
+
ensurePending() {
|
|
3121
|
+
if (this.pendingAutoContinue) return;
|
|
3122
|
+
this.pendingAutoContinue = new Promise((resolve2) => {
|
|
3123
|
+
this.resolvePendingAutoContinue = resolve2;
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3126
|
+
resolvePending() {
|
|
3127
|
+
const resolve2 = this.resolvePendingAutoContinue;
|
|
3128
|
+
this.pendingAutoContinue = void 0;
|
|
3129
|
+
this.resolvePendingAutoContinue = void 0;
|
|
3130
|
+
resolve2?.();
|
|
2918
3131
|
}
|
|
2919
3132
|
};
|
|
2920
3133
|
|
|
@@ -2932,7 +3145,7 @@ async function runAgentSessionCompaction(params) {
|
|
|
2932
3145
|
}
|
|
2933
3146
|
params.emit({ type: "auto_compaction_start", reason: params.reason, willRetry: params.willRetry });
|
|
2934
3147
|
try {
|
|
2935
|
-
if (params.
|
|
3148
|
+
if (params.willRetry) {
|
|
2936
3149
|
params.removeTrailingAssistantError();
|
|
2937
3150
|
}
|
|
2938
3151
|
const result = await params.compaction.compact({
|
|
@@ -3026,6 +3239,27 @@ async function preparePromptMessages(params) {
|
|
|
3026
3239
|
};
|
|
3027
3240
|
}
|
|
3028
3241
|
|
|
3242
|
+
// ../../packages/agent-framework/src/session/controller/pre-request-policy.ts
|
|
3243
|
+
async function runPreRequestAutoCompact(params) {
|
|
3244
|
+
if (params.disposed || params.runtimeGuardTriggered || params.isStreaming || params.recoveryActive || params.agent.state.messages.length === 0) {
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
const decision = params.getAutoCompactDecision?.({
|
|
3248
|
+
agent: params.agent,
|
|
3249
|
+
sessionManager: params.sessionManager,
|
|
3250
|
+
cwd: params.cwd,
|
|
3251
|
+
messages: params.agent.state.messages.slice()
|
|
3252
|
+
});
|
|
3253
|
+
if (decision?.reason !== "threshold") {
|
|
3254
|
+
return;
|
|
3255
|
+
}
|
|
3256
|
+
try {
|
|
3257
|
+
await params.runAutoCompact();
|
|
3258
|
+
} catch {
|
|
3259
|
+
params.setRecoveryState("none");
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3029
3263
|
// ../../packages/agent-framework/src/session/controller/queue.ts
|
|
3030
3264
|
function cloneQueuedInput(input) {
|
|
3031
3265
|
return {
|
|
@@ -3184,14 +3418,23 @@ var AgentSessionQueueDispatcher = class {
|
|
|
3184
3418
|
}
|
|
3185
3419
|
options;
|
|
3186
3420
|
dispatchTimer;
|
|
3421
|
+
pendingDispatch;
|
|
3422
|
+
resolvePendingDispatch;
|
|
3423
|
+
get hasPendingDispatch() {
|
|
3424
|
+
return this.dispatchTimer !== void 0 || this.pendingDispatch !== void 0;
|
|
3425
|
+
}
|
|
3426
|
+
waitForDispatch() {
|
|
3427
|
+
return this.pendingDispatch ?? Promise.resolve();
|
|
3428
|
+
}
|
|
3187
3429
|
schedule(delayMs = 0) {
|
|
3188
3430
|
if (this.options.getDisposed() || this.options.getRuntimeGuardTriggered() || this.dispatchTimer !== void 0) {
|
|
3189
3431
|
return;
|
|
3190
3432
|
}
|
|
3433
|
+
this.ensurePending();
|
|
3191
3434
|
const setTimer = this.options.retry?.setTimeout ?? defaultSetTimeout3;
|
|
3192
3435
|
this.dispatchTimer = setTimer(() => {
|
|
3193
3436
|
this.dispatchTimer = void 0;
|
|
3194
|
-
void this.dispatchNext();
|
|
3437
|
+
void this.dispatchNext().finally(() => this.resolvePending());
|
|
3195
3438
|
}, delayMs);
|
|
3196
3439
|
}
|
|
3197
3440
|
cancel() {
|
|
@@ -3201,6 +3444,7 @@ var AgentSessionQueueDispatcher = class {
|
|
|
3201
3444
|
const clearTimer = this.options.retry?.clearTimeout ?? defaultClearTimeout3;
|
|
3202
3445
|
clearTimer(this.dispatchTimer);
|
|
3203
3446
|
this.dispatchTimer = void 0;
|
|
3447
|
+
this.resolvePending();
|
|
3204
3448
|
}
|
|
3205
3449
|
async dispatchNext() {
|
|
3206
3450
|
if (this.options.getDisposed() || this.options.isStreaming() || this.options.isBlockedByRuntimePolicy()) {
|
|
@@ -3228,6 +3472,11 @@ var AgentSessionQueueDispatcher = class {
|
|
|
3228
3472
|
}
|
|
3229
3473
|
return false;
|
|
3230
3474
|
}
|
|
3475
|
+
await this.options.runPreRequestAutoCompact();
|
|
3476
|
+
if (this.options.getDisposed() || this.options.isStreaming() || this.options.isBlockedByRuntimePolicy()) {
|
|
3477
|
+
this.schedule(100);
|
|
3478
|
+
return false;
|
|
3479
|
+
}
|
|
3231
3480
|
const dispatched = this.options.queue.shift();
|
|
3232
3481
|
if (!dispatched) {
|
|
3233
3482
|
return false;
|
|
@@ -3257,8 +3506,56 @@ var AgentSessionQueueDispatcher = class {
|
|
|
3257
3506
|
}
|
|
3258
3507
|
return true;
|
|
3259
3508
|
}
|
|
3509
|
+
ensurePending() {
|
|
3510
|
+
if (this.pendingDispatch) return;
|
|
3511
|
+
this.pendingDispatch = new Promise((resolve2) => {
|
|
3512
|
+
this.resolvePendingDispatch = resolve2;
|
|
3513
|
+
});
|
|
3514
|
+
}
|
|
3515
|
+
resolvePending() {
|
|
3516
|
+
const resolve2 = this.resolvePendingDispatch;
|
|
3517
|
+
this.pendingDispatch = void 0;
|
|
3518
|
+
this.resolvePendingDispatch = void 0;
|
|
3519
|
+
resolve2?.();
|
|
3520
|
+
}
|
|
3260
3521
|
};
|
|
3261
3522
|
|
|
3523
|
+
// ../../packages/agent-framework/src/session/controller/failure-classification.ts
|
|
3524
|
+
function isAssistantFailureMessage(message) {
|
|
3525
|
+
return message?.role === "assistant" && (message.stopReason === "error" || message.stopReason === "aborted");
|
|
3526
|
+
}
|
|
3527
|
+
function isAssistantTerminalCompletion(message) {
|
|
3528
|
+
if (message?.role !== "assistant") return false;
|
|
3529
|
+
if (message.stopReason === "error" || message.stopReason === "aborted") return false;
|
|
3530
|
+
if (message.stopReason === "toolUse") return false;
|
|
3531
|
+
return !message.content.some((block) => block.type === "toolCall");
|
|
3532
|
+
}
|
|
3533
|
+
function createFailureClassification(context, retry, classifyFailure) {
|
|
3534
|
+
const hostClassification = classifyFailure?.(context);
|
|
3535
|
+
if (hostClassification) {
|
|
3536
|
+
return hostClassification;
|
|
3537
|
+
}
|
|
3538
|
+
const retryable = retry?.isRetryableError(context.errorMessage) === true;
|
|
3539
|
+
const userAbort = context.message?.role === "assistant" && context.message.stopReason === "aborted";
|
|
3540
|
+
return {
|
|
3541
|
+
kind: userAbort ? "user_abort" : retryable ? "provider_transient" : "unknown",
|
|
3542
|
+
retryable: retryable && !userAbort,
|
|
3543
|
+
compactable: false,
|
|
3544
|
+
userAbort,
|
|
3545
|
+
terminal: !retryable || userAbort,
|
|
3546
|
+
message: context.errorMessage
|
|
3547
|
+
};
|
|
3548
|
+
}
|
|
3549
|
+
function asTerminalFailure(failure, message = failure.message) {
|
|
3550
|
+
return {
|
|
3551
|
+
...failure,
|
|
3552
|
+
retryable: false,
|
|
3553
|
+
compactable: false,
|
|
3554
|
+
terminal: true,
|
|
3555
|
+
message
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3262
3559
|
// ../../packages/agent-framework/src/session/controller/retry-policy.ts
|
|
3263
3560
|
function defaultSetTimeout4(callback, delay) {
|
|
3264
3561
|
return setTimeout(callback, delay);
|
|
@@ -3267,59 +3564,99 @@ function defaultClearTimeout4(handle) {
|
|
|
3267
3564
|
clearTimeout(handle);
|
|
3268
3565
|
}
|
|
3269
3566
|
var AgentSessionRetryController = class {
|
|
3270
|
-
constructor(retry, emit, removeTrailingAssistantError2, continueTurn) {
|
|
3567
|
+
constructor(retry, emit, removeTrailingAssistantError2, continueTurn, setRecoveryState) {
|
|
3271
3568
|
this.retry = retry;
|
|
3272
3569
|
this.emit = emit;
|
|
3273
3570
|
this.removeTrailingAssistantError = removeTrailingAssistantError2;
|
|
3274
3571
|
this.continueTurn = continueTurn;
|
|
3572
|
+
this.setRecoveryState = setRecoveryState;
|
|
3275
3573
|
}
|
|
3276
3574
|
retry;
|
|
3277
3575
|
emit;
|
|
3278
3576
|
removeTrailingAssistantError;
|
|
3279
3577
|
continueTurn;
|
|
3578
|
+
setRecoveryState;
|
|
3280
3579
|
retryAttempt = 0;
|
|
3281
3580
|
retryTimer;
|
|
3581
|
+
pendingRetry;
|
|
3582
|
+
resolvePendingRetry;
|
|
3583
|
+
get policy() {
|
|
3584
|
+
return this.retry;
|
|
3585
|
+
}
|
|
3282
3586
|
get hasPendingRetry() {
|
|
3283
|
-
return this.retryTimer !== void 0;
|
|
3587
|
+
return this.retryTimer !== void 0 || this.pendingRetry !== void 0;
|
|
3284
3588
|
}
|
|
3285
|
-
|
|
3589
|
+
waitForRetry() {
|
|
3590
|
+
return this.pendingRetry ?? Promise.resolve();
|
|
3591
|
+
}
|
|
3592
|
+
async handleTurnEnd(message, failure) {
|
|
3286
3593
|
if (!this.retry || !message || message.role !== "assistant") {
|
|
3287
3594
|
return;
|
|
3288
3595
|
}
|
|
3289
|
-
|
|
3290
|
-
if (!errorMessage) {
|
|
3596
|
+
if (!failure) {
|
|
3291
3597
|
if (this.retryAttempt > 0) {
|
|
3292
3598
|
this.emit({ type: "retry_succeeded", attempts: this.retryAttempt });
|
|
3599
|
+
this.emit({ type: "turn_retry_succeeded", attempts: this.retryAttempt });
|
|
3293
3600
|
this.retryAttempt = 0;
|
|
3601
|
+
this.setRecoveryState("none");
|
|
3602
|
+
this.resolvePending();
|
|
3294
3603
|
}
|
|
3295
3604
|
return;
|
|
3296
3605
|
}
|
|
3297
|
-
if (!
|
|
3606
|
+
if (!failure.retryable) {
|
|
3607
|
+
if (this.retryAttempt > 0) {
|
|
3608
|
+
this.retryAttempt = 0;
|
|
3609
|
+
this.setRecoveryState("none");
|
|
3610
|
+
this.resolvePending();
|
|
3611
|
+
}
|
|
3298
3612
|
return;
|
|
3299
3613
|
}
|
|
3300
3614
|
const maxRetries = this.retry.maxRetries ?? 3;
|
|
3301
3615
|
this.retryAttempt += 1;
|
|
3302
3616
|
if (this.retryAttempt > maxRetries) {
|
|
3303
|
-
|
|
3617
|
+
const terminalFailure = asTerminalFailure(failure);
|
|
3618
|
+
this.emit({ type: "retry_exhausted", errorMessage: failure.message, maxRetries });
|
|
3619
|
+
this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
|
|
3620
|
+
this.emit({ type: "turn_settled" });
|
|
3304
3621
|
this.retryAttempt = 0;
|
|
3622
|
+
this.setRecoveryState("terminal");
|
|
3623
|
+
this.resolvePending();
|
|
3305
3624
|
return;
|
|
3306
3625
|
}
|
|
3307
3626
|
const attempt = this.retryAttempt;
|
|
3308
3627
|
const delayMs = (this.retry.baseDelayMs ?? 2e3) * 2 ** (attempt - 1);
|
|
3309
|
-
this.
|
|
3628
|
+
this.ensurePending();
|
|
3629
|
+
this.setRecoveryState("retry_pending");
|
|
3630
|
+
this.emit({ type: "turn_recovery_pending", recovery: "retry", failure, attempt, maxRetries, delayMs });
|
|
3631
|
+
this.emit({ type: "retry_scheduled", errorMessage: failure.message, attempt, maxRetries, delayMs });
|
|
3310
3632
|
this.cancelTimerOnly();
|
|
3311
3633
|
const setTimer = this.retry.setTimeout ?? defaultSetTimeout4;
|
|
3312
3634
|
this.retryTimer = setTimer(() => {
|
|
3313
3635
|
this.retryTimer = void 0;
|
|
3636
|
+
this.setRecoveryState("retrying");
|
|
3314
3637
|
this.emit({ type: "retry_start", attempt, maxRetries });
|
|
3638
|
+
this.emit({ type: "turn_retry_started", attempt, maxRetries, failure });
|
|
3315
3639
|
this.removeTrailingAssistantError();
|
|
3316
|
-
void this.continueTurn().catch(() => {
|
|
3640
|
+
void this.continueTurn().catch((error) => {
|
|
3641
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3642
|
+
const terminalFailure = asTerminalFailure(failure, errorMessage);
|
|
3643
|
+
this.emit({
|
|
3644
|
+
type: "retry_exhausted",
|
|
3645
|
+
errorMessage,
|
|
3646
|
+
maxRetries
|
|
3647
|
+
});
|
|
3648
|
+
this.emit({ type: "turn_failed_terminal", failure: terminalFailure, message });
|
|
3649
|
+
this.emit({ type: "turn_settled" });
|
|
3650
|
+
this.retryAttempt = 0;
|
|
3651
|
+
this.setRecoveryState("terminal");
|
|
3652
|
+
this.resolvePending();
|
|
3317
3653
|
});
|
|
3318
3654
|
}, delayMs);
|
|
3319
3655
|
}
|
|
3320
3656
|
cancel() {
|
|
3321
3657
|
this.cancelTimerOnly();
|
|
3322
3658
|
this.retryAttempt = 0;
|
|
3659
|
+
this.resolvePending();
|
|
3323
3660
|
}
|
|
3324
3661
|
cancelTimerOnly() {
|
|
3325
3662
|
if (this.retryTimer === void 0) {
|
|
@@ -3329,6 +3666,20 @@ var AgentSessionRetryController = class {
|
|
|
3329
3666
|
clearTimer(this.retryTimer);
|
|
3330
3667
|
this.retryTimer = void 0;
|
|
3331
3668
|
}
|
|
3669
|
+
ensurePending() {
|
|
3670
|
+
if (this.pendingRetry) {
|
|
3671
|
+
return;
|
|
3672
|
+
}
|
|
3673
|
+
this.pendingRetry = new Promise((resolve2) => {
|
|
3674
|
+
this.resolvePendingRetry = resolve2;
|
|
3675
|
+
});
|
|
3676
|
+
}
|
|
3677
|
+
resolvePending() {
|
|
3678
|
+
const resolve2 = this.resolvePendingRetry;
|
|
3679
|
+
this.pendingRetry = void 0;
|
|
3680
|
+
this.resolvePendingRetry = void 0;
|
|
3681
|
+
resolve2?.();
|
|
3682
|
+
}
|
|
3332
3683
|
};
|
|
3333
3684
|
|
|
3334
3685
|
// ../../packages/agent-framework/src/session/controller/runtime-guard.ts
|
|
@@ -3428,6 +3779,33 @@ var AgentSessionRuntimeGuard = class {
|
|
|
3428
3779
|
}
|
|
3429
3780
|
};
|
|
3430
3781
|
|
|
3782
|
+
// ../../packages/agent-framework/src/session/controller/runtime-phase-policy.ts
|
|
3783
|
+
function classifyControllerRuntimeError(params) {
|
|
3784
|
+
const errorMessage = params.error instanceof Error ? params.error.message : String(params.error);
|
|
3785
|
+
return createFailureClassification({ errorMessage, phase: params.phase }, params.retry, params.classifyFailure);
|
|
3786
|
+
}
|
|
3787
|
+
async function runAgentSessionRuntimePhase(params) {
|
|
3788
|
+
try {
|
|
3789
|
+
return await params.action();
|
|
3790
|
+
} catch (error) {
|
|
3791
|
+
const failure = classifyControllerRuntimeError({
|
|
3792
|
+
error,
|
|
3793
|
+
phase: params.phase,
|
|
3794
|
+
retry: params.retry,
|
|
3795
|
+
classifyFailure: params.classifyFailure
|
|
3796
|
+
});
|
|
3797
|
+
if (failure.userAbort) {
|
|
3798
|
+
params.setRecoveryState("cancelled");
|
|
3799
|
+
params.emit({ type: "turn_cancelled", reason: failure.message });
|
|
3800
|
+
} else {
|
|
3801
|
+
params.setRecoveryState("terminal");
|
|
3802
|
+
params.emit({ type: "turn_failed_terminal", failure: asTerminalFailure(failure) });
|
|
3803
|
+
}
|
|
3804
|
+
params.emit({ type: "turn_settled" });
|
|
3805
|
+
throw error;
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3431
3809
|
// ../../packages/agent-framework/src/session/controller/session-sync.ts
|
|
3432
3810
|
function getConversationMessages(messages) {
|
|
3433
3811
|
return messages.filter(
|
|
@@ -3532,6 +3910,161 @@ function reduceAgentSessionLifecycle(state, input) {
|
|
|
3532
3910
|
}
|
|
3533
3911
|
}
|
|
3534
3912
|
|
|
3913
|
+
// ../../packages/agent-framework/src/session/controller/turn-lifecycle-policy.ts
|
|
3914
|
+
function isAgentSessionRecoveryActive(state) {
|
|
3915
|
+
return state === "retry_pending" || state === "retrying" || state === "compacting";
|
|
3916
|
+
}
|
|
3917
|
+
function createRuntimeGuardFailure(reason) {
|
|
3918
|
+
return {
|
|
3919
|
+
kind: "runtime_guard",
|
|
3920
|
+
retryable: false,
|
|
3921
|
+
compactable: false,
|
|
3922
|
+
userAbort: false,
|
|
3923
|
+
terminal: true,
|
|
3924
|
+
message: reason
|
|
3925
|
+
};
|
|
3926
|
+
}
|
|
3927
|
+
function classifyControllerTurnFailure(params) {
|
|
3928
|
+
if (!isAssistantFailureMessage(params.message)) {
|
|
3929
|
+
return void 0;
|
|
3930
|
+
}
|
|
3931
|
+
const errorMessage = params.message.errorMessage || (params.message.stopReason === "aborted" ? "Request was aborted" : "assistant response failed");
|
|
3932
|
+
return createFailureClassification(
|
|
3933
|
+
{ errorMessage, message: params.message, phase: "stream" },
|
|
3934
|
+
params.retry,
|
|
3935
|
+
params.classifyFailure
|
|
3936
|
+
);
|
|
3937
|
+
}
|
|
3938
|
+
async function handleAgentSessionTurnEndRuntimePolicies(params) {
|
|
3939
|
+
if (params.disposed || params.runtimeGuardTriggered) {
|
|
3940
|
+
return;
|
|
3941
|
+
}
|
|
3942
|
+
const failure = classifyControllerTurnFailure({
|
|
3943
|
+
message: params.message,
|
|
3944
|
+
retry: params.retry,
|
|
3945
|
+
classifyFailure: params.classifyFailure
|
|
3946
|
+
});
|
|
3947
|
+
if (failure?.userAbort) {
|
|
3948
|
+
params.cancelRetry();
|
|
3949
|
+
params.setRecoveryState("cancelled");
|
|
3950
|
+
params.emit({ type: "turn_cancelled", reason: failure.message, message: params.message });
|
|
3951
|
+
params.emit({ type: "turn_settled" });
|
|
3952
|
+
return;
|
|
3953
|
+
}
|
|
3954
|
+
const compactDecision = params.getAutoCompactDecision?.({
|
|
3955
|
+
agent: params.agent,
|
|
3956
|
+
sessionManager: params.sessionManager,
|
|
3957
|
+
cwd: params.cwd,
|
|
3958
|
+
message: params.message,
|
|
3959
|
+
messages: params.agent.state.messages.slice()
|
|
3960
|
+
});
|
|
3961
|
+
if (failure?.compactable) {
|
|
3962
|
+
params.scheduleAutoCompact(compactDecision ?? { reason: "overflow", willRetry: true }, failure);
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
if (failure && compactDecision?.reason === "overflow") {
|
|
3966
|
+
params.scheduleAutoCompact(compactDecision, failure);
|
|
3967
|
+
return;
|
|
3968
|
+
}
|
|
3969
|
+
if (failure?.retryable && compactDecision?.reason === "threshold") {
|
|
3970
|
+
params.scheduleAutoCompact({ reason: "threshold", willRetry: true }, failure);
|
|
3971
|
+
return;
|
|
3972
|
+
}
|
|
3973
|
+
if (failure) {
|
|
3974
|
+
if (failure.retryable) {
|
|
3975
|
+
await params.handleRetryTurnEnd(params.message, failure);
|
|
3976
|
+
return;
|
|
3977
|
+
}
|
|
3978
|
+
await params.handleRetryTurnEnd(params.message, failure);
|
|
3979
|
+
params.setRecoveryState("terminal");
|
|
3980
|
+
params.emit({ type: "turn_failed_terminal", failure: asTerminalFailure(failure), message: params.message });
|
|
3981
|
+
params.emit({ type: "turn_settled" });
|
|
3982
|
+
return;
|
|
3983
|
+
}
|
|
3984
|
+
await params.handleRetryTurnEnd(params.message);
|
|
3985
|
+
if (isAssistantTerminalCompletion(params.message)) {
|
|
3986
|
+
params.emit({ type: "turn_completed", message: params.message, toolResults: params.toolResults });
|
|
3987
|
+
const postTurnCompactDecision = compactDecision ?? params.getAutoCompactDecision?.({
|
|
3988
|
+
agent: params.agent,
|
|
3989
|
+
sessionManager: params.sessionManager,
|
|
3990
|
+
cwd: params.cwd,
|
|
3991
|
+
message: params.message,
|
|
3992
|
+
messages: params.agent.state.messages.slice()
|
|
3993
|
+
});
|
|
3994
|
+
if (postTurnCompactDecision?.reason === "threshold") {
|
|
3995
|
+
params.scheduleAutoCompact(postTurnCompactDecision);
|
|
3996
|
+
return;
|
|
3997
|
+
}
|
|
3998
|
+
params.setRecoveryState("none");
|
|
3999
|
+
params.emit({ type: "turn_settled" });
|
|
4000
|
+
}
|
|
4001
|
+
}
|
|
4002
|
+
async function runAgentSessionControllerAutoCompact(params) {
|
|
4003
|
+
const emitSettled = params.emitSettled ?? true;
|
|
4004
|
+
const runAfterAgentEndHook = params.runAfterAgentEndHook ?? true;
|
|
4005
|
+
const cancelOnAbort = params.cancelOnAbort ?? true;
|
|
4006
|
+
params.setRecoveryState("compacting");
|
|
4007
|
+
params.emit({ type: "turn_compaction_started", reason: params.reason, willRetry: params.willRetry });
|
|
4008
|
+
try {
|
|
4009
|
+
const result = await runAgentSessionCompaction({
|
|
4010
|
+
reason: params.reason,
|
|
4011
|
+
willRetry: params.willRetry,
|
|
4012
|
+
compaction: params.compaction,
|
|
4013
|
+
agent: params.agent,
|
|
4014
|
+
sessionManager: params.sessionManager,
|
|
4015
|
+
cwd: params.cwd,
|
|
4016
|
+
emit: params.emit,
|
|
4017
|
+
removeTrailingAssistantError: params.removeTrailingAssistantError,
|
|
4018
|
+
replaceMessagesAndMarkSynced: params.replaceMessagesAndMarkSynced,
|
|
4019
|
+
markSyncedToAgentState: params.markSyncedToAgentState,
|
|
4020
|
+
continueTurn: params.continueTurn
|
|
4021
|
+
});
|
|
4022
|
+
if (!params.willRetry || result?.aborted) {
|
|
4023
|
+
params.setRecoveryState(result?.aborted && cancelOnAbort ? "cancelled" : "none");
|
|
4024
|
+
if (result?.aborted) {
|
|
4025
|
+
params.cancelRetry();
|
|
4026
|
+
if (cancelOnAbort) {
|
|
4027
|
+
params.emit({ type: "turn_cancelled", reason: "compaction_aborted" });
|
|
4028
|
+
}
|
|
4029
|
+
}
|
|
4030
|
+
if (emitSettled) {
|
|
4031
|
+
params.emit({ type: "turn_settled" });
|
|
4032
|
+
}
|
|
4033
|
+
if (!result?.aborted && runAfterAgentEndHook) {
|
|
4034
|
+
void params.handleAgentEndHook(params.agent.state.messages.slice());
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
return result;
|
|
4038
|
+
} catch (error) {
|
|
4039
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4040
|
+
if (!params.willRetry && params.reason !== "overflow") {
|
|
4041
|
+
params.setRecoveryState("none");
|
|
4042
|
+
if (emitSettled) {
|
|
4043
|
+
params.emit({ type: "turn_settled" });
|
|
4044
|
+
}
|
|
4045
|
+
if (runAfterAgentEndHook) {
|
|
4046
|
+
void params.handleAgentEndHook(params.agent.state.messages.slice());
|
|
4047
|
+
}
|
|
4048
|
+
throw error;
|
|
4049
|
+
}
|
|
4050
|
+
const failure = asTerminalFailure(params.pendingFailure ?? {
|
|
4051
|
+
kind: "internal_error",
|
|
4052
|
+
retryable: false,
|
|
4053
|
+
compactable: false,
|
|
4054
|
+
userAbort: false,
|
|
4055
|
+
terminal: true,
|
|
4056
|
+
message: errorMessage
|
|
4057
|
+
}, errorMessage);
|
|
4058
|
+
params.cancelRetry();
|
|
4059
|
+
params.setRecoveryState("terminal");
|
|
4060
|
+
params.emit({ type: "turn_failed_terminal", failure });
|
|
4061
|
+
params.emit({ type: "turn_settled" });
|
|
4062
|
+
throw error;
|
|
4063
|
+
} finally {
|
|
4064
|
+
params.clearPendingFailure();
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
|
|
3535
4068
|
// ../../packages/agent-framework/src/session/controller.ts
|
|
3536
4069
|
var AgentSessionController = class {
|
|
3537
4070
|
agent;
|
|
@@ -3553,6 +4086,9 @@ var AgentSessionController = class {
|
|
|
3553
4086
|
prepareTurn;
|
|
3554
4087
|
afterAgentEnd;
|
|
3555
4088
|
getAutoCompactDecision;
|
|
4089
|
+
classifyFailure;
|
|
4090
|
+
recoveryState = "none";
|
|
4091
|
+
pendingCompactionFailure;
|
|
3556
4092
|
lifecycleState = createInitialAgentSessionLifecycleState();
|
|
3557
4093
|
constructor(options) {
|
|
3558
4094
|
this.agent = options.agent;
|
|
@@ -3563,6 +4099,7 @@ var AgentSessionController = class {
|
|
|
3563
4099
|
this.prepareTurn = options.prepareTurn;
|
|
3564
4100
|
this.afterAgentEnd = options.afterAgentEnd;
|
|
3565
4101
|
this.getAutoCompactDecision = options.getAutoCompactDecision;
|
|
4102
|
+
this.classifyFailure = options.classifyFailure;
|
|
3566
4103
|
if (options.onEvent) {
|
|
3567
4104
|
this.listeners.add(options.onEvent);
|
|
3568
4105
|
}
|
|
@@ -3578,7 +4115,10 @@ var AgentSessionController = class {
|
|
|
3578
4115
|
options.retry,
|
|
3579
4116
|
(event) => this.emit(event),
|
|
3580
4117
|
() => this.removeTrailingAssistantError(),
|
|
3581
|
-
() => this.continue()
|
|
4118
|
+
() => this.continue(),
|
|
4119
|
+
(state) => {
|
|
4120
|
+
this.recoveryState = state;
|
|
4121
|
+
}
|
|
3582
4122
|
);
|
|
3583
4123
|
this.autoCompact = new AgentSessionAutoCompactScheduler({
|
|
3584
4124
|
retry: options.retry,
|
|
@@ -3598,6 +4138,7 @@ var AgentSessionController = class {
|
|
|
3598
4138
|
emit: (event) => this.emit(event),
|
|
3599
4139
|
getDisposed: () => this.disposed,
|
|
3600
4140
|
getRuntimeGuardTriggered: () => this.runtimeGuard.triggered,
|
|
4141
|
+
isBlockedByRuntimePolicy: () => this.isBlockedByRuntimePolicy(),
|
|
3601
4142
|
hasQueuedMessages: () => this.hasQueuedMessages,
|
|
3602
4143
|
isStreaming: () => this.isStreaming,
|
|
3603
4144
|
continueTurn: () => this.continue()
|
|
@@ -3613,7 +4154,8 @@ var AgentSessionController = class {
|
|
|
3613
4154
|
getDisposed: () => this.disposed,
|
|
3614
4155
|
getRuntimeGuardTriggered: () => this.runtimeGuard.triggered,
|
|
3615
4156
|
isStreaming: () => this.isStreaming,
|
|
3616
|
-
isBlockedByRuntimePolicy: () => this.
|
|
4157
|
+
isBlockedByRuntimePolicy: () => this.isBlockedByRuntimePolicy(),
|
|
4158
|
+
runPreRequestAutoCompact: () => this.runPreRequestAutoCompactIfNeeded(),
|
|
3617
4159
|
preparePromptMessages: (messages, promptOptions) => this.preparePromptMessages(messages, promptOptions),
|
|
3618
4160
|
continueTurn: () => this.continue(),
|
|
3619
4161
|
syncNewAgentMessages: () => this.syncNewAgentMessages()
|
|
@@ -3636,6 +4178,9 @@ var AgentSessionController = class {
|
|
|
3636
4178
|
get queuedInputsSnapshot() {
|
|
3637
4179
|
return this.queue.snapshot;
|
|
3638
4180
|
}
|
|
4181
|
+
get turnRecoveryState() {
|
|
4182
|
+
return this.recoveryState;
|
|
4183
|
+
}
|
|
3639
4184
|
get activeSessionMetadata() {
|
|
3640
4185
|
const metadata = this.sessionManager.getActiveSession()?.metadata;
|
|
3641
4186
|
return metadata ? { ...metadata } : void 0;
|
|
@@ -3644,10 +4189,7 @@ var AgentSessionController = class {
|
|
|
3644
4189
|
return this.lastSyncedMessageCount;
|
|
3645
4190
|
}
|
|
3646
4191
|
get runtimeContext() {
|
|
3647
|
-
return {
|
|
3648
|
-
systemPrompt: this.agent.state.systemPrompt,
|
|
3649
|
-
tools: this.agent.state.tools.slice()
|
|
3650
|
-
};
|
|
4192
|
+
return { systemPrompt: this.agent.state.systemPrompt, tools: this.agent.state.tools.slice() };
|
|
3651
4193
|
}
|
|
3652
4194
|
getRuntimeSnapshot() {
|
|
3653
4195
|
return {
|
|
@@ -3694,6 +4236,17 @@ var AgentSessionController = class {
|
|
|
3694
4236
|
}
|
|
3695
4237
|
async prompt(input, options) {
|
|
3696
4238
|
const messages = normalizePromptInput(input);
|
|
4239
|
+
if (this.isRecoveryActive()) {
|
|
4240
|
+
this.queue.enqueue(messages, options?.streamingBehavior ?? "followUp", {
|
|
4241
|
+
...options,
|
|
4242
|
+
streamingBehavior: options?.streamingBehavior ?? "followUp"
|
|
4243
|
+
});
|
|
4244
|
+
this.recordLifecycle({ type: "queued_input_added" });
|
|
4245
|
+
return;
|
|
4246
|
+
}
|
|
4247
|
+
if (this.recoveryState === "terminal" || this.recoveryState === "cancelled") {
|
|
4248
|
+
this.recoveryState = "none";
|
|
4249
|
+
}
|
|
3697
4250
|
if (options?.streamingBehavior) {
|
|
3698
4251
|
this.queue.enqueue(messages, options.streamingBehavior, options);
|
|
3699
4252
|
this.recordLifecycle({ type: "queued_input_added" });
|
|
@@ -3705,7 +4258,8 @@ var AgentSessionController = class {
|
|
|
3705
4258
|
if (this.isStreaming) {
|
|
3706
4259
|
throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
|
|
3707
4260
|
}
|
|
3708
|
-
|
|
4261
|
+
await this.runPreRequestAutoCompactIfNeeded();
|
|
4262
|
+
const prepared = await this.runRuntimePhase("prepare", () => this.preparePromptMessages(messages, options));
|
|
3709
4263
|
if (prepared.handled) {
|
|
3710
4264
|
return;
|
|
3711
4265
|
}
|
|
@@ -3713,41 +4267,69 @@ var AgentSessionController = class {
|
|
|
3713
4267
|
if (prepared.systemPrompt !== void 0) {
|
|
3714
4268
|
this.agent.setSystemPrompt(prepared.systemPrompt);
|
|
3715
4269
|
}
|
|
3716
|
-
await this.agent.prompt(prepared.messages);
|
|
3717
|
-
await this.syncNewAgentMessages();
|
|
4270
|
+
await this.runRuntimePhase("request", () => this.agent.prompt(prepared.messages));
|
|
4271
|
+
await this.runRuntimePhase("post_turn", () => this.syncNewAgentMessages());
|
|
3718
4272
|
}
|
|
3719
4273
|
async continue() {
|
|
3720
4274
|
if (this.isStreaming) {
|
|
3721
4275
|
throw new Error("Agent is already processing. Wait for completion before continuing.");
|
|
3722
4276
|
}
|
|
4277
|
+
await this.runPreRequestAutoCompactIfNeeded();
|
|
3723
4278
|
this.recordLifecycle({ type: "prompt_started" });
|
|
3724
|
-
await this.agent.continue();
|
|
3725
|
-
await this.syncNewAgentMessages();
|
|
4279
|
+
await this.runRuntimePhase("request", () => this.agent.continue());
|
|
4280
|
+
await this.runRuntimePhase("post_turn", () => this.syncNewAgentMessages());
|
|
3726
4281
|
}
|
|
3727
4282
|
abort() {
|
|
3728
4283
|
this.recordLifecycle({ type: "abort" });
|
|
4284
|
+
const cancelPendingRecovery = this.isRecoveryActive() && !this.isStreaming;
|
|
3729
4285
|
this.retryController.cancel();
|
|
3730
4286
|
this.autoCompact.cancel();
|
|
3731
4287
|
this.queueDispatcher.cancel();
|
|
3732
4288
|
this.autoContinue.cancel();
|
|
4289
|
+
if (cancelPendingRecovery) {
|
|
4290
|
+
this.recoveryState = "cancelled";
|
|
4291
|
+
this.emit({ type: "turn_cancelled", reason: "user_abort" });
|
|
4292
|
+
this.emit({ type: "turn_settled" });
|
|
4293
|
+
}
|
|
3733
4294
|
this.agent.abort();
|
|
3734
4295
|
}
|
|
3735
4296
|
waitForIdle() {
|
|
3736
4297
|
return this.agent.waitForIdle();
|
|
3737
4298
|
}
|
|
3738
|
-
async
|
|
3739
|
-
|
|
4299
|
+
async waitForSettled() {
|
|
4300
|
+
while (true) {
|
|
4301
|
+
await this.agent.waitForIdle();
|
|
4302
|
+
if (!this.hasPendingRuntimePolicy()) {
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
await Promise.all([this.retryController.waitForRetry(), this.autoCompact.waitForAutoCompact(), this.autoContinue.waitForAutoContinue(), this.queueDispatcher.waitForDispatch()]);
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
async runAutoCompact(reason, willRetry = false, options) {
|
|
4309
|
+
return runAgentSessionControllerAutoCompact({
|
|
3740
4310
|
reason,
|
|
3741
4311
|
willRetry,
|
|
3742
4312
|
compaction: this.compaction,
|
|
3743
4313
|
agent: this.agent,
|
|
3744
4314
|
sessionManager: this.sessionManager,
|
|
3745
4315
|
cwd: this.cwd,
|
|
4316
|
+
pendingFailure: this.pendingCompactionFailure,
|
|
3746
4317
|
emit: (event) => this.emit(event),
|
|
4318
|
+
setRecoveryState: (state) => {
|
|
4319
|
+
this.recoveryState = state;
|
|
4320
|
+
},
|
|
4321
|
+
cancelRetry: () => this.retryController.cancel(),
|
|
4322
|
+
clearPendingFailure: () => {
|
|
4323
|
+
this.pendingCompactionFailure = void 0;
|
|
4324
|
+
},
|
|
3747
4325
|
removeTrailingAssistantError: () => this.removeTrailingAssistantError(),
|
|
3748
|
-
replaceMessagesAndMarkSynced: (messages,
|
|
4326
|
+
replaceMessagesAndMarkSynced: (messages, options2) => this.replaceMessagesAndMarkSynced(messages, options2),
|
|
3749
4327
|
markSyncedToAgentState: () => this.markSyncedToAgentState(),
|
|
3750
|
-
continueTurn: () => this.continue()
|
|
4328
|
+
continueTurn: () => this.continue(),
|
|
4329
|
+
handleAgentEndHook: (messages) => this.handleAgentEndHook(messages),
|
|
4330
|
+
emitSettled: options?.emitSettled,
|
|
4331
|
+
runAfterAgentEndHook: options?.runAfterAgentEndHook,
|
|
4332
|
+
cancelOnAbort: options?.cancelOnAbort
|
|
3751
4333
|
});
|
|
3752
4334
|
}
|
|
3753
4335
|
dispose() {
|
|
@@ -3769,9 +4351,23 @@ var AgentSessionController = class {
|
|
|
3769
4351
|
this.queue.replaceText(search, replacement);
|
|
3770
4352
|
}
|
|
3771
4353
|
requestQueueDispatch() {
|
|
3772
|
-
if (this.queue.length > 0)
|
|
3773
|
-
|
|
3774
|
-
|
|
4354
|
+
if (this.queue.length > 0) this.queueDispatcher.schedule();
|
|
4355
|
+
}
|
|
4356
|
+
async runPreRequestAutoCompactIfNeeded() {
|
|
4357
|
+
return runPreRequestAutoCompact({
|
|
4358
|
+
disposed: this.disposed,
|
|
4359
|
+
runtimeGuardTriggered: this.runtimeGuard.triggered,
|
|
4360
|
+
isStreaming: this.isStreaming,
|
|
4361
|
+
recoveryActive: this.isRecoveryActive(),
|
|
4362
|
+
agent: this.agent,
|
|
4363
|
+
sessionManager: this.sessionManager,
|
|
4364
|
+
cwd: this.cwd,
|
|
4365
|
+
getAutoCompactDecision: this.getAutoCompactDecision,
|
|
4366
|
+
runAutoCompact: () => this.runAutoCompact("threshold", false, { emitSettled: false, runAfterAgentEndHook: false, cancelOnAbort: false }).then(() => void 0),
|
|
4367
|
+
setRecoveryState: (state) => {
|
|
4368
|
+
this.recoveryState = state;
|
|
4369
|
+
}
|
|
4370
|
+
});
|
|
3775
4371
|
}
|
|
3776
4372
|
handleAgentEvent(event) {
|
|
3777
4373
|
this.emit({ type: "agent_event", event });
|
|
@@ -3792,7 +4388,7 @@ var AgentSessionController = class {
|
|
|
3792
4388
|
if (event.type === "turn_end") {
|
|
3793
4389
|
void this.syncNewAgentMessages();
|
|
3794
4390
|
this.recordLifecycle({ type: "turn_end_success" });
|
|
3795
|
-
void this.handleTurnEndRuntimePolicies(event.message);
|
|
4391
|
+
void this.handleTurnEndRuntimePolicies(event.message, event.toolResults);
|
|
3796
4392
|
}
|
|
3797
4393
|
if (event.type === "agent_end") {
|
|
3798
4394
|
this.recordLifecycle({ type: "agent_end" });
|
|
@@ -3829,25 +4425,29 @@ var AgentSessionController = class {
|
|
|
3829
4425
|
replaceMessagesAndMarkSynced: (messages, options) => this.replaceMessagesAndMarkSynced(messages, options)
|
|
3830
4426
|
});
|
|
3831
4427
|
}
|
|
3832
|
-
async handleTurnEndRuntimePolicies(message) {
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
4428
|
+
async handleTurnEndRuntimePolicies(message, toolResults = []) {
|
|
4429
|
+
return handleAgentSessionTurnEndRuntimePolicies({
|
|
4430
|
+
disposed: this.disposed,
|
|
4431
|
+
runtimeGuardTriggered: this.runtimeGuard.triggered,
|
|
4432
|
+
message,
|
|
4433
|
+
toolResults,
|
|
3837
4434
|
agent: this.agent,
|
|
3838
4435
|
sessionManager: this.sessionManager,
|
|
3839
4436
|
cwd: this.cwd,
|
|
3840
|
-
|
|
3841
|
-
|
|
4437
|
+
getAutoCompactDecision: this.getAutoCompactDecision,
|
|
4438
|
+
classifyFailure: this.classifyFailure,
|
|
4439
|
+
retry: this.retryController.policy,
|
|
4440
|
+
emit: (event) => this.emit(event),
|
|
4441
|
+
setRecoveryState: (state) => {
|
|
4442
|
+
this.recoveryState = state;
|
|
4443
|
+
},
|
|
4444
|
+
handleRetryTurnEnd: (turnMessage, failure) => this.retryController.handleTurnEnd(turnMessage, failure),
|
|
4445
|
+
cancelRetry: () => this.retryController.cancel(),
|
|
4446
|
+
scheduleAutoCompact: (decision, failure) => this.scheduleAutoCompact(decision, failure)
|
|
3842
4447
|
});
|
|
3843
|
-
if (compactDecision) {
|
|
3844
|
-
this.scheduleAutoCompact(compactDecision);
|
|
3845
|
-
return;
|
|
3846
|
-
}
|
|
3847
|
-
await this.retryController.handleTurnEnd(message);
|
|
3848
4448
|
}
|
|
3849
4449
|
async handleAgentEndHook(messages) {
|
|
3850
|
-
if (this.disposed || this.runtimeGuard.triggered) {
|
|
4450
|
+
if (this.disposed || this.runtimeGuard.triggered || this.isBlockedByRuntimePolicy()) {
|
|
3851
4451
|
return;
|
|
3852
4452
|
}
|
|
3853
4453
|
if (this.afterAgentEnd) {
|
|
@@ -3882,8 +4482,36 @@ var AgentSessionController = class {
|
|
|
3882
4482
|
recordToolExecutionEndForGuard(event) {
|
|
3883
4483
|
this.runtimeGuard.recordToolExecutionEnd(event);
|
|
3884
4484
|
}
|
|
3885
|
-
|
|
4485
|
+
async runRuntimePhase(phase, action) {
|
|
4486
|
+
return runAgentSessionRuntimePhase({
|
|
4487
|
+
phase,
|
|
4488
|
+
action,
|
|
4489
|
+
retry: this.retryController.policy,
|
|
4490
|
+
classifyFailure: this.classifyFailure,
|
|
4491
|
+
emit: (event) => this.emit(event),
|
|
4492
|
+
setRecoveryState: (state) => {
|
|
4493
|
+
this.recoveryState = state;
|
|
4494
|
+
}
|
|
4495
|
+
});
|
|
4496
|
+
}
|
|
4497
|
+
isRecoveryActive() {
|
|
4498
|
+
return isAgentSessionRecoveryActive(this.recoveryState);
|
|
4499
|
+
}
|
|
4500
|
+
isBlockedByRuntimePolicy() {
|
|
4501
|
+
return this.recoveryState !== "none" || this.retryController.hasPendingRetry || this.autoCompact.hasPendingAutoCompact;
|
|
4502
|
+
}
|
|
4503
|
+
hasPendingRuntimePolicy() {
|
|
4504
|
+
return this.retryController.hasPendingRetry || this.autoCompact.hasPendingAutoCompact || this.autoContinue.hasPendingAutoContinue || this.queueDispatcher.hasPendingDispatch;
|
|
4505
|
+
}
|
|
4506
|
+
scheduleAutoCompact(decision, failure) {
|
|
3886
4507
|
this.recordLifecycle({ type: "auto_compact_scheduled" });
|
|
4508
|
+
if (failure) {
|
|
4509
|
+
this.pendingCompactionFailure = failure;
|
|
4510
|
+
this.recoveryState = "compacting";
|
|
4511
|
+
this.emit({ type: "turn_recovery_pending", recovery: "compaction", failure });
|
|
4512
|
+
} else if (decision.reason === "threshold") {
|
|
4513
|
+
this.recoveryState = "compacting";
|
|
4514
|
+
}
|
|
3887
4515
|
this.autoCompact.schedule(decision);
|
|
3888
4516
|
}
|
|
3889
4517
|
triggerRuntimeGuard(toolName, repeatCount, reason) {
|
|
@@ -3895,7 +4523,13 @@ var AgentSessionController = class {
|
|
|
3895
4523
|
this.autoCompact.cancel();
|
|
3896
4524
|
this.queueDispatcher.cancel();
|
|
3897
4525
|
this.autoContinue.cancel();
|
|
4526
|
+
this.recoveryState = "terminal";
|
|
3898
4527
|
this.emit({ type: "runtime_guard_triggered", toolName, repeatCount, reason });
|
|
4528
|
+
this.emit({
|
|
4529
|
+
type: "turn_failed_terminal",
|
|
4530
|
+
failure: createRuntimeGuardFailure(reason)
|
|
4531
|
+
});
|
|
4532
|
+
this.emit({ type: "turn_settled" });
|
|
3899
4533
|
this.agent.abort();
|
|
3900
4534
|
}
|
|
3901
4535
|
emit(event) {
|
|
@@ -8972,7 +9606,10 @@ export {
|
|
|
8972
9606
|
ManageTodoListParamsSchema,
|
|
8973
9607
|
executeManageTodoList,
|
|
8974
9608
|
maybeAdvanceTodoExecutionState,
|
|
9609
|
+
estimateTokens,
|
|
8975
9610
|
calculateTotalTokens,
|
|
9611
|
+
estimateContextTokens,
|
|
9612
|
+
getAutoCompactTokenLimit,
|
|
8976
9613
|
findFirstKeptEntryId,
|
|
8977
9614
|
createCompactionSummary,
|
|
8978
9615
|
createSessionManager,
|