@prestyj/agent 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +51 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +52 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -60,9 +60,21 @@ interface AgentDoneEvent {
|
|
|
60
60
|
totalTurns: number;
|
|
61
61
|
totalUsage: Usage;
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Terminal signal emitted when the loop stops because it exhausted its turn
|
|
65
|
+
* budget (`maxTurns`) mid-task — i.e. the model still wanted to run tools but
|
|
66
|
+
* ran out of turns. Distinguishes a hard cut-off from a clean completion so
|
|
67
|
+
* callers (e.g. the subagent spawner) can tell the parent the output may be
|
|
68
|
+
* incomplete. Yielded immediately before the final `agent_done`.
|
|
69
|
+
*/
|
|
70
|
+
interface AgentMaxTurnsEvent {
|
|
71
|
+
type: "max_turns";
|
|
72
|
+
totalTurns: number;
|
|
73
|
+
maxTurns: number;
|
|
74
|
+
}
|
|
63
75
|
interface AgentRetryEvent {
|
|
64
76
|
type: "retry";
|
|
65
|
-
reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact";
|
|
77
|
+
reason: "overloaded" | "rate_limit" | "provider_error" | "empty_response" | "stream_stall" | "overflow_compact" | "tool_argument_glitch";
|
|
66
78
|
attempt: number;
|
|
67
79
|
maxAttempts: number;
|
|
68
80
|
delayMs: number;
|
|
@@ -101,7 +113,7 @@ interface AgentFollowUpMessageEvent {
|
|
|
101
113
|
type: "follow_up_message";
|
|
102
114
|
content: Message["content"];
|
|
103
115
|
}
|
|
104
|
-
type AgentEvent = AgentTextDeltaEvent | AgentThinkingDeltaEvent | AgentToolCallStartEvent | AgentToolCallUpdateEvent | AgentToolCallEndEvent | AgentToolCallDeltaEvent | AgentServerToolCallEvent | AgentServerToolResultEvent | AgentSteeringMessageEvent | AgentFollowUpMessageEvent | AgentRetryEvent | AgentTurnEndEvent | AgentDoneEvent | AgentErrorEvent;
|
|
116
|
+
type AgentEvent = AgentTextDeltaEvent | AgentThinkingDeltaEvent | AgentToolCallStartEvent | AgentToolCallUpdateEvent | AgentToolCallEndEvent | AgentToolCallDeltaEvent | AgentServerToolCallEvent | AgentServerToolResultEvent | AgentSteeringMessageEvent | AgentFollowUpMessageEvent | AgentRetryEvent | AgentTurnEndEvent | AgentDoneEvent | AgentMaxTurnsEvent | AgentErrorEvent;
|
|
105
117
|
interface AgentOptions {
|
|
106
118
|
provider: StreamOptions["provider"];
|
|
107
119
|
model: string;
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { ZodError, prettifyError } from "zod";
|
|
|
6
6
|
import {
|
|
7
7
|
stream,
|
|
8
8
|
EventStream,
|
|
9
|
+
EZCoderAIError,
|
|
9
10
|
isHardBillingMessage
|
|
10
11
|
} from "@prestyj/ai";
|
|
11
12
|
var DEFAULT_MAX_TURNS = 300;
|
|
@@ -232,6 +233,7 @@ async function* agentLoop(messages, options) {
|
|
|
232
233
|
const toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
233
234
|
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
234
235
|
let turn = 0;
|
|
236
|
+
let hitMaxTurns = false;
|
|
235
237
|
let firstTurn = true;
|
|
236
238
|
let consecutivePauses = 0;
|
|
237
239
|
let toolPairingRepaired = false;
|
|
@@ -242,6 +244,7 @@ async function* agentLoop(messages, options) {
|
|
|
242
244
|
let overflowCompactionAttempts = 0;
|
|
243
245
|
let toolResultTruncationAttempted = false;
|
|
244
246
|
const invalidToolArgumentCounts = /* @__PURE__ */ new Map();
|
|
247
|
+
let toolArgumentAutoContinueUsed = false;
|
|
245
248
|
let useNonStreamingFallback = false;
|
|
246
249
|
const MAX_OVERLOAD_RETRIES = 10;
|
|
247
250
|
const MAX_EMPTY_RESPONSE_RETRIES = 2;
|
|
@@ -814,8 +817,12 @@ async function* agentLoop(messages, options) {
|
|
|
814
817
|
}
|
|
815
818
|
}
|
|
816
819
|
let fatalToolArgumentError = null;
|
|
817
|
-
|
|
820
|
+
let fatalToolArgumentRecoverable = false;
|
|
821
|
+
let fatalToolArgumentToolName = "";
|
|
822
|
+
const markFatalToolArgumentError = (error, recoverable, toolName) => {
|
|
818
823
|
fatalToolArgumentError = error;
|
|
824
|
+
fatalToolArgumentRecoverable = recoverable;
|
|
825
|
+
fatalToolArgumentToolName = toolName;
|
|
819
826
|
};
|
|
820
827
|
const executionOptions = {
|
|
821
828
|
signal: options.signal,
|
|
@@ -831,8 +838,24 @@ async function* agentLoop(messages, options) {
|
|
|
831
838
|
messages.push({ role: "tool", content: executionResult.toolResults });
|
|
832
839
|
const toolsAborted = executionResult.aborted;
|
|
833
840
|
if (fatalToolArgumentError) {
|
|
834
|
-
|
|
835
|
-
|
|
841
|
+
if (fatalToolArgumentRecoverable && !toolArgumentAutoContinueUsed) {
|
|
842
|
+
toolArgumentAutoContinueUsed = true;
|
|
843
|
+
for (const key of invalidToolArgumentCounts.keys()) {
|
|
844
|
+
if (key.startsWith(`${fatalToolArgumentToolName}:`))
|
|
845
|
+
invalidToolArgumentCounts.delete(key);
|
|
846
|
+
}
|
|
847
|
+
yield {
|
|
848
|
+
type: "retry",
|
|
849
|
+
reason: "tool_argument_glitch",
|
|
850
|
+
attempt: 1,
|
|
851
|
+
maxAttempts: 1,
|
|
852
|
+
delayMs: 0,
|
|
853
|
+
silent: false
|
|
854
|
+
};
|
|
855
|
+
} else {
|
|
856
|
+
yield { type: "error", error: fatalToolArgumentError };
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
836
859
|
}
|
|
837
860
|
if (toolsAborted) break;
|
|
838
861
|
if (options.getSteeringMessages) {
|
|
@@ -844,6 +867,9 @@ async function* agentLoop(messages, options) {
|
|
|
844
867
|
}
|
|
845
868
|
}
|
|
846
869
|
}
|
|
870
|
+
if (turn >= maxTurns) {
|
|
871
|
+
hitMaxTurns = true;
|
|
872
|
+
}
|
|
847
873
|
}
|
|
848
874
|
} finally {
|
|
849
875
|
sanitizeOrphanedServerTools(messages);
|
|
@@ -855,6 +881,19 @@ async function* agentLoop(messages, options) {
|
|
|
855
881
|
break;
|
|
856
882
|
}
|
|
857
883
|
}
|
|
884
|
+
if (hitMaxTurns) {
|
|
885
|
+
diag("max_turns_reached", {
|
|
886
|
+
turn,
|
|
887
|
+
maxTurns,
|
|
888
|
+
provider: options.provider,
|
|
889
|
+
model: options.model
|
|
890
|
+
});
|
|
891
|
+
yield {
|
|
892
|
+
type: "max_turns",
|
|
893
|
+
totalTurns: turn,
|
|
894
|
+
maxTurns
|
|
895
|
+
};
|
|
896
|
+
}
|
|
858
897
|
yield {
|
|
859
898
|
type: "agent_done",
|
|
860
899
|
totalTurns: turn,
|
|
@@ -920,10 +959,17 @@ async function executeSingleToolCall(toolCall, options, pushEvent) {
|
|
|
920
959
|
resultContent = `Invalid arguments for tool \`${toolCall.name}\`:
|
|
921
960
|
` + prettyError + "\nRe-issue the call with each field as the correct type.";
|
|
922
961
|
if (failureCount >= 3) {
|
|
962
|
+
const recoverable = Object.keys(toolCall.args ?? {}).length === 0;
|
|
923
963
|
options.markFatalToolArgumentError(
|
|
924
|
-
new
|
|
925
|
-
`The model repeatedly issued invalid arguments for tool \`${toolCall.name}\`. This is usually an upstream model/tool-calling bug
|
|
926
|
-
|
|
964
|
+
new EZCoderAIError(
|
|
965
|
+
`The model repeatedly issued invalid arguments for tool \`${toolCall.name}\`. This is usually an upstream model/tool-calling bug` + (recoverable ? " (the provider's stream returned empty tool-call arguments)" : "") + `. Your conversation is preserved; send another message or switch models to continue.`,
|
|
966
|
+
{
|
|
967
|
+
source: "provider",
|
|
968
|
+
hint: "This is the model/provider's fault, not a ezcoder bug. " + (recoverable ? "ezcoder already retried automatically once; if it recurs, send another message or switch models." : "Send another message or switch models to continue.")
|
|
969
|
+
}
|
|
970
|
+
),
|
|
971
|
+
recoverable,
|
|
972
|
+
toolCall.name
|
|
927
973
|
);
|
|
928
974
|
}
|
|
929
975
|
} else {
|