@prestyj/agent 5.7.0 → 5.8.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 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +51 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StreamOptions, Message, Tool, ToolResultContent, ServerToolDefinition,
|
|
1
|
+
import { StreamOptions, Message, Tool, ToolResultContent, ServerToolDefinition, Usage, StopReason, AssistantMessage } from '@prestyj/ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
interface StructuredToolResult {
|
|
@@ -136,6 +136,14 @@ interface AgentFollowUpMessageEvent {
|
|
|
136
136
|
content: Message["content"];
|
|
137
137
|
}
|
|
138
138
|
type AgentEvent = AgentTextDeltaEvent | AgentThinkingDeltaEvent | AgentToolCallStartEvent | AgentToolCallUpdateEvent | AgentToolCallEndEvent | AgentToolCallDeltaEvent | AgentServerToolCallEvent | AgentServerToolResultEvent | AgentSteeringMessageEvent | AgentFollowUpMessageEvent | AgentRetryEvent | AgentTurnEndEvent | AgentDoneEvent | AgentMaxTurnsEvent | AgentErrorEvent;
|
|
139
|
+
interface TransformContextOptions {
|
|
140
|
+
/** Force a transform after the provider reports context overflow. */
|
|
141
|
+
force?: boolean;
|
|
142
|
+
/** Latest successful provider usage, anchored at its assistant message. */
|
|
143
|
+
usage?: Usage;
|
|
144
|
+
/** Messages appended after that usage sample and not yet seen by the provider. */
|
|
145
|
+
pendingMessages: Message[];
|
|
146
|
+
}
|
|
139
147
|
interface AgentOptions {
|
|
140
148
|
provider: StreamOptions["provider"];
|
|
141
149
|
model: string;
|
|
@@ -180,6 +188,10 @@ interface AgentOptions {
|
|
|
180
188
|
clearToolUses?: boolean;
|
|
181
189
|
/** Max characters for a single tool result. Results exceeding this are truncated with a notice. */
|
|
182
190
|
maxToolResultChars?: number;
|
|
191
|
+
/** Aggregate budget for ALL tool results in one assistant turn. Protects
|
|
192
|
+
* against parallel fan-outs injecting huge uncached context in one turn;
|
|
193
|
+
* the largest results are trimmed (water-filling) with a re-run notice. */
|
|
194
|
+
maxTurnToolResultChars?: number;
|
|
183
195
|
/** Max consecutive pause_turn continuations before stopping (default: 5).
|
|
184
196
|
* Prevents infinite loops when server-side tools keep pausing. */
|
|
185
197
|
maxContinuations?: number;
|
|
@@ -188,12 +200,12 @@ interface AgentOptions {
|
|
|
188
200
|
* the messages array (e.g. compaction, truncation). Return the same array
|
|
189
201
|
* for no-op, or a new array to replace the conversation context.
|
|
190
202
|
*
|
|
203
|
+
* The latest provider usage is authoritative for the history through its
|
|
204
|
+
* assistant response. `pendingMessages` contains context appended afterward.
|
|
191
205
|
* When `options.force` is true, the caller should compact unconditionally
|
|
192
206
|
* (e.g. after a context overflow error from the API).
|
|
193
207
|
*/
|
|
194
|
-
transformContext?: (messages: Message[], options
|
|
195
|
-
force?: boolean;
|
|
196
|
-
}) => Message[] | Promise<Message[]>;
|
|
208
|
+
transformContext?: (messages: Message[], options: TransformContextOptions) => Message[] | Promise<Message[]>;
|
|
197
209
|
/**
|
|
198
210
|
* Polled after tool execution completes each turn. Returns user messages
|
|
199
211
|
* to inject into the conversation before the next LLM call (steering).
|
|
@@ -299,4 +311,4 @@ declare function isBillingError(err: unknown): boolean;
|
|
|
299
311
|
declare function isUsageLimitError(err: unknown): boolean;
|
|
300
312
|
declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
|
|
301
313
|
|
|
302
|
-
export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
|
|
314
|
+
export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, type TransformContextOptions, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StreamOptions, Message, Tool, ToolResultContent, ServerToolDefinition,
|
|
1
|
+
import { StreamOptions, Message, Tool, ToolResultContent, ServerToolDefinition, Usage, StopReason, AssistantMessage } from '@prestyj/ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
interface StructuredToolResult {
|
|
@@ -136,6 +136,14 @@ interface AgentFollowUpMessageEvent {
|
|
|
136
136
|
content: Message["content"];
|
|
137
137
|
}
|
|
138
138
|
type AgentEvent = AgentTextDeltaEvent | AgentThinkingDeltaEvent | AgentToolCallStartEvent | AgentToolCallUpdateEvent | AgentToolCallEndEvent | AgentToolCallDeltaEvent | AgentServerToolCallEvent | AgentServerToolResultEvent | AgentSteeringMessageEvent | AgentFollowUpMessageEvent | AgentRetryEvent | AgentTurnEndEvent | AgentDoneEvent | AgentMaxTurnsEvent | AgentErrorEvent;
|
|
139
|
+
interface TransformContextOptions {
|
|
140
|
+
/** Force a transform after the provider reports context overflow. */
|
|
141
|
+
force?: boolean;
|
|
142
|
+
/** Latest successful provider usage, anchored at its assistant message. */
|
|
143
|
+
usage?: Usage;
|
|
144
|
+
/** Messages appended after that usage sample and not yet seen by the provider. */
|
|
145
|
+
pendingMessages: Message[];
|
|
146
|
+
}
|
|
139
147
|
interface AgentOptions {
|
|
140
148
|
provider: StreamOptions["provider"];
|
|
141
149
|
model: string;
|
|
@@ -180,6 +188,10 @@ interface AgentOptions {
|
|
|
180
188
|
clearToolUses?: boolean;
|
|
181
189
|
/** Max characters for a single tool result. Results exceeding this are truncated with a notice. */
|
|
182
190
|
maxToolResultChars?: number;
|
|
191
|
+
/** Aggregate budget for ALL tool results in one assistant turn. Protects
|
|
192
|
+
* against parallel fan-outs injecting huge uncached context in one turn;
|
|
193
|
+
* the largest results are trimmed (water-filling) with a re-run notice. */
|
|
194
|
+
maxTurnToolResultChars?: number;
|
|
183
195
|
/** Max consecutive pause_turn continuations before stopping (default: 5).
|
|
184
196
|
* Prevents infinite loops when server-side tools keep pausing. */
|
|
185
197
|
maxContinuations?: number;
|
|
@@ -188,12 +200,12 @@ interface AgentOptions {
|
|
|
188
200
|
* the messages array (e.g. compaction, truncation). Return the same array
|
|
189
201
|
* for no-op, or a new array to replace the conversation context.
|
|
190
202
|
*
|
|
203
|
+
* The latest provider usage is authoritative for the history through its
|
|
204
|
+
* assistant response. `pendingMessages` contains context appended afterward.
|
|
191
205
|
* When `options.force` is true, the caller should compact unconditionally
|
|
192
206
|
* (e.g. after a context overflow error from the API).
|
|
193
207
|
*/
|
|
194
|
-
transformContext?: (messages: Message[], options
|
|
195
|
-
force?: boolean;
|
|
196
|
-
}) => Message[] | Promise<Message[]>;
|
|
208
|
+
transformContext?: (messages: Message[], options: TransformContextOptions) => Message[] | Promise<Message[]>;
|
|
197
209
|
/**
|
|
198
210
|
* Polled after tool execution completes each turn. Returns user messages
|
|
199
211
|
* to inject into the conversation before the next LLM call (steering).
|
|
@@ -299,4 +311,4 @@ declare function isBillingError(err: unknown): boolean;
|
|
|
299
311
|
declare function isUsageLimitError(err: unknown): boolean;
|
|
300
312
|
declare function agentLoop(messages: Message[], options: AgentOptions): AsyncGenerator<AgentEvent, AgentResult>;
|
|
301
313
|
|
|
302
|
-
export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
|
|
314
|
+
export { Agent, type AgentDoneEvent, type AgentErrorEvent, type AgentEvent, type AgentFollowUpMessageEvent, type AgentOptions, type AgentResult, type AgentRetryEvent, type AgentServerToolCallEvent, type AgentServerToolResultEvent, type AgentSteeringMessageEvent, AgentStream, type AgentTextDeltaEvent, type AgentThinkingDeltaEvent, type AgentTool, type AgentToolCallDeltaEvent, type AgentToolCallEndEvent, type AgentToolCallStartEvent, type AgentToolCallUpdateEvent, type AgentTurnEndEvent, type AgentTurnTiming, type StreamDiagnosticFn, type StructuredToolResult, type ToolContext, type ToolExecuteResult, type ToolExecutionMode, type TransformContextOptions, agentLoop, isAbortError, isBillingError, isContextOverflow, isUsageLimitError, setStreamDiagnostic };
|
package/dist/index.js
CHANGED
|
@@ -127,7 +127,7 @@ function classifyOverload(err) {
|
|
|
127
127
|
if (statusCode === 529 || msg.includes("overloaded") || msg.includes("529")) {
|
|
128
128
|
return "overloaded";
|
|
129
129
|
}
|
|
130
|
-
if (statusCode === 500 || statusCode === 502 || statusCode === 503 || statusCode === 504 || msg.includes("api_error") || msg.includes("server_error") || msg.includes("internal server error") || msg.includes("bad gateway") || msg.includes("service unavailable") || msg.includes("gateway timeout")) {
|
|
130
|
+
if (statusCode === 500 || statusCode === 502 || statusCode === 503 || statusCode === 504 || statusCode === 507 || msg.includes("api_error") || msg.includes("server_error") || msg.includes("internal server error") || msg.includes("bad gateway") || msg.includes("service unavailable") || msg.includes("gateway timeout") || msg.includes("exceeded request buffer limit while retrying upstream")) {
|
|
131
131
|
return "provider_error";
|
|
132
132
|
}
|
|
133
133
|
if (isOpaqueProviderMessage(err.message)) {
|
|
@@ -233,6 +233,8 @@ async function* agentLoop(messages, options) {
|
|
|
233
233
|
const maxContinuations = options.maxContinuations ?? 5;
|
|
234
234
|
let toolMap = new Map((options.tools ?? []).map((t) => [t.name, t]));
|
|
235
235
|
const totalUsage = { inputTokens: 0, outputTokens: 0 };
|
|
236
|
+
let latestProviderUsage;
|
|
237
|
+
let usageAnchorIndex;
|
|
236
238
|
let turn = 0;
|
|
237
239
|
let hitMaxTurns = false;
|
|
238
240
|
let firstTurn = true;
|
|
@@ -309,7 +311,11 @@ async function* agentLoop(messages, options) {
|
|
|
309
311
|
firstTurn = false;
|
|
310
312
|
if (options.transformContext) {
|
|
311
313
|
diag("transform_start");
|
|
312
|
-
const
|
|
314
|
+
const pendingMessages = usageAnchorIndex === void 0 ? [] : messages.slice(usageAnchorIndex + 1);
|
|
315
|
+
const transformed = await options.transformContext(messages, {
|
|
316
|
+
usage: latestProviderUsage,
|
|
317
|
+
pendingMessages
|
|
318
|
+
});
|
|
313
319
|
if (transformed !== messages) {
|
|
314
320
|
diag("transform_compacted", {
|
|
315
321
|
before: messages.length,
|
|
@@ -317,6 +323,8 @@ async function* agentLoop(messages, options) {
|
|
|
317
323
|
});
|
|
318
324
|
messages.length = 0;
|
|
319
325
|
messages.push(...transformed);
|
|
326
|
+
latestProviderUsage = void 0;
|
|
327
|
+
usageAnchorIndex = void 0;
|
|
320
328
|
}
|
|
321
329
|
diag("transform_end");
|
|
322
330
|
}
|
|
@@ -577,10 +585,17 @@ async function* agentLoop(messages, options) {
|
|
|
577
585
|
...overflowDetails
|
|
578
586
|
});
|
|
579
587
|
try {
|
|
580
|
-
const
|
|
588
|
+
const pendingMessages = usageAnchorIndex === void 0 ? [] : messages.slice(usageAnchorIndex + 1);
|
|
589
|
+
const compacted = await options.transformContext(messages, {
|
|
590
|
+
force: true,
|
|
591
|
+
usage: latestProviderUsage,
|
|
592
|
+
pendingMessages
|
|
593
|
+
});
|
|
581
594
|
if (compacted !== messages && compacted.length < messages.length) {
|
|
582
595
|
messages.length = 0;
|
|
583
596
|
messages.push(...compacted);
|
|
597
|
+
latestProviderUsage = void 0;
|
|
598
|
+
usageAnchorIndex = void 0;
|
|
584
599
|
diag("overflow_compact_success", {
|
|
585
600
|
attempt: overflowCompactionAttempts,
|
|
586
601
|
messages: messages.length,
|
|
@@ -786,6 +801,8 @@ async function* agentLoop(messages, options) {
|
|
|
786
801
|
totalUsage.cacheWrite = (totalUsage.cacheWrite ?? 0) + response.usage.cacheWrite;
|
|
787
802
|
}
|
|
788
803
|
messages.push(response.message);
|
|
804
|
+
latestProviderUsage = response.usage;
|
|
805
|
+
usageAnchorIndex = messages.length - 1;
|
|
789
806
|
const completedAt = Date.now();
|
|
790
807
|
const outputTokensPerSecond = providerDurationMs > 0 && response.usage.outputTokens > 0 ? response.usage.outputTokens / (providerDurationMs / 1e3) : void 0;
|
|
791
808
|
const timing = {
|
|
@@ -873,6 +890,7 @@ async function* agentLoop(messages, options) {
|
|
|
873
890
|
const executionOptions = {
|
|
874
891
|
signal: options.signal,
|
|
875
892
|
maxToolResultChars: options.maxToolResultChars,
|
|
893
|
+
maxTurnToolResultChars: options.maxTurnToolResultChars,
|
|
876
894
|
toolMap,
|
|
877
895
|
invalidToolArgumentCounts,
|
|
878
896
|
markFatalToolArgumentError
|
|
@@ -1112,6 +1130,7 @@ async function* executeToolCallsMixed(toolCalls, initialToolResults, options) {
|
|
|
1112
1130
|
}
|
|
1113
1131
|
const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
|
|
1114
1132
|
capToolResults(toolResults, options.maxToolResultChars);
|
|
1133
|
+
capTurnToolResults(toolResults, options.maxTurnToolResultChars);
|
|
1115
1134
|
return { toolResults, aborted };
|
|
1116
1135
|
}
|
|
1117
1136
|
async function* executeToolCallsParallel(toolCalls, initialToolResults, options) {
|
|
@@ -1151,6 +1170,7 @@ async function* executeToolCallsParallel(toolCalls, initialToolResults, options)
|
|
|
1151
1170
|
}
|
|
1152
1171
|
const toolResults = buildToolResults(initialToolResults, toolCalls, resultsById);
|
|
1153
1172
|
capToolResults(toolResults, options.maxToolResultChars);
|
|
1173
|
+
capTurnToolResults(toolResults, options.maxTurnToolResultChars);
|
|
1154
1174
|
return { toolResults, aborted };
|
|
1155
1175
|
}
|
|
1156
1176
|
function buildToolResults(initialToolResults, toolCalls, resultsById) {
|
|
@@ -1193,6 +1213,34 @@ function capToolResults(toolResults, maxToolResultChars) {
|
|
|
1193
1213
|
` + tail;
|
|
1194
1214
|
}
|
|
1195
1215
|
}
|
|
1216
|
+
function capTurnToolResults(toolResults, maxTurnToolResultChars) {
|
|
1217
|
+
if (!maxTurnToolResultChars) return;
|
|
1218
|
+
const textResults = toolResults.filter(
|
|
1219
|
+
(toolResult) => typeof toolResult.content === "string"
|
|
1220
|
+
);
|
|
1221
|
+
const total = textResults.reduce((sum, toolResult) => sum + toolResult.content.length, 0);
|
|
1222
|
+
if (total <= maxTurnToolResultChars) return;
|
|
1223
|
+
const bySize = [...textResults].sort((a, b) => a.content.length - b.content.length);
|
|
1224
|
+
let remaining = maxTurnToolResultChars;
|
|
1225
|
+
let left = bySize.length;
|
|
1226
|
+
for (const toolResult of bySize) {
|
|
1227
|
+
const fairShare = Math.floor(remaining / left);
|
|
1228
|
+
left--;
|
|
1229
|
+
if (toolResult.content.length <= fairShare) {
|
|
1230
|
+
remaining -= toolResult.content.length;
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
remaining -= fairShare;
|
|
1234
|
+
const headChars = Math.floor(fairShare * 0.7);
|
|
1235
|
+
const tailChars = fairShare - headChars;
|
|
1236
|
+
const omitted = toolResult.content.length - fairShare;
|
|
1237
|
+
toolResult.content = toolResult.content.slice(0, headChars) + `
|
|
1238
|
+
|
|
1239
|
+
[... ${omitted} characters trimmed: this turn's combined tool results exceeded the per-turn budget. Re-run this call alone with narrower filters or offset/limit if you need the omitted content ...]
|
|
1240
|
+
|
|
1241
|
+
` + (tailChars > 0 ? toolResult.content.slice(-tailChars) : "");
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1196
1244
|
function normalizeToolResult(raw) {
|
|
1197
1245
|
return typeof raw === "string" ? { content: raw } : raw;
|
|
1198
1246
|
}
|