agents 0.17.0 → 0.17.3
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/{agent-tool-types-Cd1TZPfB.d.ts → agent-tool-types-CNyE1iz_.d.ts} +86 -3
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-_E8wxUIK.d.ts → agent-tools-BeOheFBK.d.ts} +17 -3
- package/dist/{agent-tools-BXlsuX0d.js → agent-tools-y7zLfw4Q.js} +2 -2
- package/dist/agent-tools-y7zLfw4Q.js.map +1 -0
- package/dist/agent-tools.d.ts +1 -1
- package/dist/chat/index.d.ts +123 -13
- package/dist/chat/index.js +109 -11
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.js +13 -2
- package/dist/chat/react.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/{index-CcbnKkNh.d.ts → index-BRnybD6X.d.ts} +10 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +135 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{retries-CwlpAGet.d.ts → retries-CvHJwSuh.d.ts} +15 -6
- package/dist/retries.d.ts +8 -6
- package/dist/retries.js +44 -1
- package/dist/retries.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sub-routing.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/docs/chat-agents.md +22 -13
- package/package.json +4 -4
- package/dist/agent-tools-BXlsuX0d.js.map +0 -1
package/dist/chat/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as normalizeToolInput, n as getPartialStreamText, r as isReplayChunk, t as applyChunkToParts } from "../message-builder-BymO4N_D.js";
|
|
2
|
-
import { i as interceptAgentToolBroadcast, n as applyAgentToolEvent, r as createAgentToolEventState, t as AgentToolProgressEmitter } from "../agent-tools-
|
|
2
|
+
import { i as interceptAgentToolBroadcast, n as applyAgentToolEvent, r as createAgentToolEventState, t as AgentToolProgressEmitter } from "../agent-tools-y7zLfw4Q.js";
|
|
3
3
|
import { t as truncateToolOutput } from "../tool-output-truncation-CNnnGZQ3.js";
|
|
4
4
|
import { n as transition, r as StreamAccumulator, t as MessageType } from "../wire-types-nflOzNuU.js";
|
|
5
5
|
import { jsonSchema, tool } from "ai";
|
|
@@ -2445,12 +2445,42 @@ const CHAT_LAST_TERMINAL_KEY = "cf:chat:last-terminal";
|
|
|
2445
2445
|
*/
|
|
2446
2446
|
const DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS = 10;
|
|
2447
2447
|
/**
|
|
2448
|
-
* Runaway-loop guard default
|
|
2449
|
-
*
|
|
2450
|
-
*
|
|
2451
|
-
*
|
|
2452
|
-
|
|
2453
|
-
|
|
2448
|
+
* Runaway-loop guard default — the framework-imposed backstop on cumulative
|
|
2449
|
+
* recovery WORK (produced content/tool units) since an incident opened.
|
|
2450
|
+
*
|
|
2451
|
+
* Originally `Infinity` (rfc-chat-recovery-work-budget): the SDK shipped the
|
|
2452
|
+
* *mechanism* but no default cap, so a progressing turn was never terminated on
|
|
2453
|
+
* its own. Production issue #1825 showed that this is a footgun: an isolate that
|
|
2454
|
+
* OOMs mid-stream still credits a little progress before it dies, which resets
|
|
2455
|
+
* BOTH progress-keyed bounds (the attempt cap and the no-progress window) on
|
|
2456
|
+
* every wake — and a fast crash loop (each attempt inside the alarm-debounce
|
|
2457
|
+
* window) pins the attempt counter too. With `maxRecoveryWork = Infinity` the
|
|
2458
|
+
* ONLY instrument whose meter still climbs across such a loop is disabled, so
|
|
2459
|
+
* recovery re-runs the turn (and its LLM calls) forever.
|
|
2460
|
+
*
|
|
2461
|
+
* A finite default closes that loop out of the box: work climbs regardless of
|
|
2462
|
+
* debounce/progress resets, so a content-emitting runaway is always sealed with
|
|
2463
|
+
* `reason="work_budget_exceeded"`. The value is deliberately generous — it
|
|
2464
|
+
* bounds wasted re-run cost without clipping a normal interrupted turn (work
|
|
2465
|
+
* only accrues from the first interruption until the turn completes, after which
|
|
2466
|
+
* the incident is deleted). A very long agentic turn under heavy interruption
|
|
2467
|
+
* that legitimately needs more should raise `maxRecoveryWork` (or set it to
|
|
2468
|
+
* `Infinity` to restore the pre-#1825 unbounded behavior).
|
|
2469
|
+
*/
|
|
2470
|
+
const DEFAULT_CHAT_RECOVERY_MAX_WORK = 1e3;
|
|
2471
|
+
/**
|
|
2472
|
+
* Tight, OOM-specific retry budget (#1825). A Durable Object memory-limit reset
|
|
2473
|
+
* (`isDurableObjectMemoryLimitReset`) is usually deterministic — the turn's
|
|
2474
|
+
* working set no longer fits in the isolate's 128 MB — so re-running it re-OOMs.
|
|
2475
|
+
* But a single OOM CAN be a transient spike (the isolate's 128 MB is shared
|
|
2476
|
+
* across the global scope / noisy neighbors), so recovery retries a small number
|
|
2477
|
+
* of times before sealing with `reason="out_of_memory"` rather than abandoning a
|
|
2478
|
+
* turn that one more attempt might have completed. Far tighter than the generic
|
|
2479
|
+
* `maxRecoveryWork` backstop because an OOM is attributable and re-running it is
|
|
2480
|
+
* expensive (it re-runs the model). Counts attempts that ended in an OOM, not
|
|
2481
|
+
* total attempts, so a turn interrupted by deploys (no OOM) is unaffected.
|
|
2482
|
+
*/
|
|
2483
|
+
const DEFAULT_CHAT_RECOVERY_MAX_OOM_RETRIES = 3;
|
|
2454
2484
|
const DEFAULT_CHAT_RECOVERY_STABLE_TIMEOUT_MS = 1e4;
|
|
2455
2485
|
/**
|
|
2456
2486
|
* Delay before retrying a recovery that timed out waiting for stable state.
|
|
@@ -2497,6 +2527,7 @@ function resolveChatRecoveryConfig(raw) {
|
|
|
2497
2527
|
terminalMessage: custom?.terminalMessage ?? "The assistant was interrupted and could not recover. Please try again.",
|
|
2498
2528
|
noProgressTimeoutMs: Math.max(0, Math.floor(custom?.noProgressTimeoutMs ?? 3e5)),
|
|
2499
2529
|
maxRecoveryWork: typeof custom?.maxRecoveryWork === "number" && custom.maxRecoveryWork >= 0 ? custom.maxRecoveryWork : DEFAULT_CHAT_RECOVERY_MAX_WORK,
|
|
2530
|
+
maxOomRetries: typeof custom?.maxOomRetries === "number" && custom.maxOomRetries >= 0 ? Math.floor(custom.maxOomRetries) : 3,
|
|
2500
2531
|
...custom?.shouldKeepRecovering ? { shouldKeepRecovering: custom.shouldKeepRecovering } : {},
|
|
2501
2532
|
...custom?.onExhausted ? { onExhausted: custom.onExhausted } : {}
|
|
2502
2533
|
};
|
|
@@ -2539,6 +2570,22 @@ async function sweepStaleChatRecoveryIncidents(storage, now) {
|
|
|
2539
2570
|
for (let i = 0; i < staleKeys.length; i += 128) await storage.delete(staleKeys.slice(i, i + 128));
|
|
2540
2571
|
}
|
|
2541
2572
|
/**
|
|
2573
|
+
* List the persisted recovery incidents that are still live (status
|
|
2574
|
+
* `detected` / `scheduled` / `attempting`) — i.e. NOT yet terminalized
|
|
2575
|
+
* (`exhausted` / `failed`). Used by the alarm-boundary OOM circuit breaker
|
|
2576
|
+
* (#1825) to find the incident(s) it must seal when the in-DO budgets could not.
|
|
2577
|
+
* Lists by the incident key prefix so the storage layout stays encapsulated.
|
|
2578
|
+
*/
|
|
2579
|
+
async function listActiveChatRecoveryIncidents(storage) {
|
|
2580
|
+
const entries = await storage.list({ prefix: CHAT_RECOVERY_INCIDENT_KEY_PREFIX });
|
|
2581
|
+
const active = [];
|
|
2582
|
+
for (const [key, incident] of entries) if (incident && (incident.status === "detected" || incident.status === "scheduled" || incident.status === "attempting")) active.push({
|
|
2583
|
+
key,
|
|
2584
|
+
incident
|
|
2585
|
+
});
|
|
2586
|
+
return active;
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2542
2589
|
* Summarize a child agent's persisted recovery incidents for the parent's
|
|
2543
2590
|
* agent-tool reattach decision: `"in-progress"` if any incident is still live
|
|
2544
2591
|
* (detected/scheduled/attempting), else `"failed"` if any terminalized
|
|
@@ -2725,10 +2772,12 @@ async function evaluateChatRecoveryIncident(input) {
|
|
|
2725
2772
|
const progress = Math.max(prevProgress, currentProgress);
|
|
2726
2773
|
const work = progress - workBaseline;
|
|
2727
2774
|
const workBudgetExceeded = existing != null && Number.isFinite(config.maxRecoveryWork) && work > config.maxRecoveryWork;
|
|
2775
|
+
const oomAttempts = existing?.oomAttempts ?? 0;
|
|
2776
|
+
const oomBudgetExceeded = existing != null && !awaitingClientInteraction && oomAttempts > config.maxOomRetries;
|
|
2728
2777
|
const debounced = existing != null && !madeProgress && now - existing.lastAttemptAt < 3e4;
|
|
2729
2778
|
const attempt = madeProgress ? 1 : debounced ? existing?.attempt ?? 1 : (existing?.attempt ?? 0) + 1;
|
|
2730
2779
|
let abortedByCaller = false;
|
|
2731
|
-
if (existing != null && !awaitingClientInteraction && config.shouldKeepRecovering && !noProgressExceeded && !workBudgetExceeded && attempt <= config.maxAttempts) try {
|
|
2780
|
+
if (existing != null && !awaitingClientInteraction && config.shouldKeepRecovering && !noProgressExceeded && !workBudgetExceeded && !oomBudgetExceeded && attempt <= config.maxAttempts) try {
|
|
2732
2781
|
const ctx = {
|
|
2733
2782
|
incidentId,
|
|
2734
2783
|
requestId: identity.requestId,
|
|
@@ -2743,7 +2792,7 @@ async function evaluateChatRecoveryIncident(input) {
|
|
|
2743
2792
|
} catch (error) {
|
|
2744
2793
|
input.onShouldKeepRecoveringError?.(error);
|
|
2745
2794
|
}
|
|
2746
|
-
const exhausted = !awaitingClientInteraction && (noProgressExceeded || workBudgetExceeded || abortedByCaller || attempt > config.maxAttempts);
|
|
2795
|
+
const exhausted = !awaitingClientInteraction && (oomBudgetExceeded || noProgressExceeded || workBudgetExceeded || abortedByCaller || attempt > config.maxAttempts);
|
|
2747
2796
|
const incident = {
|
|
2748
2797
|
incidentId,
|
|
2749
2798
|
requestId: identity.requestId,
|
|
@@ -2757,7 +2806,8 @@ async function evaluateChatRecoveryIncident(input) {
|
|
|
2757
2806
|
lastProgressAt,
|
|
2758
2807
|
progress,
|
|
2759
2808
|
workBaseline,
|
|
2760
|
-
...
|
|
2809
|
+
...oomAttempts > 0 ? { oomAttempts } : {},
|
|
2810
|
+
...exhausted ? { reason: oomBudgetExceeded ? "out_of_memory" : workBudgetExceeded ? "work_budget_exceeded" : noProgressExceeded ? "no_progress_timeout" : abortedByCaller ? "recovery_aborted" : "max_attempts_exceeded" } : {}
|
|
2761
2811
|
};
|
|
2762
2812
|
const events = [];
|
|
2763
2813
|
if (!existing) events.push({
|
|
@@ -3031,6 +3081,54 @@ var ChatRecoveryEngine = class {
|
|
|
3031
3081
|
return true;
|
|
3032
3082
|
}
|
|
3033
3083
|
/**
|
|
3084
|
+
* Record that a recovery callback observed a Durable Object memory-limit reset
|
|
3085
|
+
* (the isolate exceeded its 128 MB limit — `isDurableObjectMemoryLimitReset`)
|
|
3086
|
+
* and decide what to do next (#1825).
|
|
3087
|
+
*
|
|
3088
|
+
* Bumps the incident's durable `oomAttempts` counter, then:
|
|
3089
|
+
* - if it is still within `maxOomRetries`, issues a delayed, NON-idempotent
|
|
3090
|
+
* reschedule of the SAME callback (same machinery as
|
|
3091
|
+
* {@link rescheduleAfterStableTimeout}: the executing one-shot row is
|
|
3092
|
+
* deleted only after the callback returns, so an idempotent reschedule
|
|
3093
|
+
* would dedup onto that doomed row) and returns `"rescheduled"`. The small
|
|
3094
|
+
* delay lets a transient memory spike clear before the re-run;
|
|
3095
|
+
* - otherwise leaves the incremented count persisted (so a begin-path
|
|
3096
|
+
* re-evaluation agrees) and returns `"exhausted"` — the caller then
|
|
3097
|
+
* terminalizes via the give-up path with `reason="out_of_memory"`.
|
|
3098
|
+
*
|
|
3099
|
+
* Returns `"exhausted"` when there is no incident to track against (no id /
|
|
3100
|
+
* record gone): an OOM we cannot bound must seal rather than loop. Unlike a
|
|
3101
|
+
* stable-state retry this is gated by the OOM-specific budget, NOT the generic
|
|
3102
|
+
* attempt cap — re-running an OOM streams a little "progress" that would
|
|
3103
|
+
* otherwise reset the attempt cap forever (the #1825 loop).
|
|
3104
|
+
*/
|
|
3105
|
+
async recordOomAndDecide(input) {
|
|
3106
|
+
const { adapter } = this;
|
|
3107
|
+
if (!input.incidentId) return "exhausted";
|
|
3108
|
+
const key = chatRecoveryIncidentKey(input.incidentId);
|
|
3109
|
+
const incident = await adapter.getIncident(key);
|
|
3110
|
+
if (!incident) return "exhausted";
|
|
3111
|
+
const oomAttempts = (incident.oomAttempts ?? 0) + 1;
|
|
3112
|
+
if (oomAttempts > input.maxOomRetries) {
|
|
3113
|
+
await adapter.putIncident(key, {
|
|
3114
|
+
...incident,
|
|
3115
|
+
oomAttempts,
|
|
3116
|
+
lastAttemptAt: adapter.now(),
|
|
3117
|
+
reason: "out_of_memory"
|
|
3118
|
+
});
|
|
3119
|
+
return "exhausted";
|
|
3120
|
+
}
|
|
3121
|
+
await adapter.putIncident(key, {
|
|
3122
|
+
...incident,
|
|
3123
|
+
oomAttempts,
|
|
3124
|
+
status: "scheduled",
|
|
3125
|
+
lastAttemptAt: adapter.now(),
|
|
3126
|
+
reason: "oom_retry"
|
|
3127
|
+
});
|
|
3128
|
+
await adapter.scheduleRecovery(input.callback, input.data ?? {}, "stable_timeout_retry", 3);
|
|
3129
|
+
return "rescheduled";
|
|
3130
|
+
}
|
|
3131
|
+
/**
|
|
3034
3132
|
* Give up on a recovery turn whose retry budget drained, terminalizing it so
|
|
3035
3133
|
* it can never become an eternal spinner (#1645). The shared spine both
|
|
3036
3134
|
* packages repeated verbatim:
|
|
@@ -3305,6 +3403,6 @@ async function* iterateWithStallWatchdog(source, timeoutMs, onStall) {
|
|
|
3305
3403
|
}
|
|
3306
3404
|
}
|
|
3307
3405
|
//#endregion
|
|
3308
|
-
export { AGENT_TOOL_STREAM_PROGRESS_BUMP_THROTTLE_MS, AbortRegistry, AgentToolProgressEmitter, AgentToolStreamProgressThrottle, AutoContinuationController, CHAT_LAST_TERMINAL_KEY, CHAT_MESSAGE_TYPES, CHAT_RECOVERING_FLAG_TTL_MS, CHAT_RECOVERING_KEY, CHAT_RECOVERY_ALARM_DEBOUNCE_MS, CHAT_RECOVERY_INCIDENT_KEY_PREFIX, CHAT_RECOVERY_INCIDENT_TTL_MS, CHAT_RECOVERY_PROGRESS_KEY, CHAT_RECOVERY_STABLE_RETRY_DELAY_SECONDS, CHAT_STREAM_PROGRESS_CREDIT_THROTTLE_MS, ChatRecoveryEngine, ChatStreamStalledError, ContinuationState, DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS, DEFAULT_CHAT_RECOVERY_MAX_WORK, DEFAULT_CHAT_RECOVERY_NO_PROGRESS_TIMEOUT_MS, DEFAULT_CHAT_RECOVERY_STABLE_TIMEOUT_MS, DEFAULT_CHAT_RECOVERY_TERMINAL_MESSAGE, KV_DELETE_MAX_KEYS, MAX_BOUND_PARAMS, MessageType, PreStreamTurns, ROW_MAX_BYTES, ResumableStream, ResumeHandshake, STREAM_CLEANUP_DELAY_SECONDS, StreamAccumulator, StreamProgressCreditThrottle, SubmitConcurrencyController, TIMED_OUT, TurnQueue, aiSdkRecoveryCodec, applyAgentToolEvent, applyChunkToParts, applyToolUpdate, awaitWithDeadline, transition as broadcastTransition, buildChatRecoveringFrame, buildInClauseStrings, bumpChatRecoveryProgress, byteLength, chatRecoverySchedulePolicy, classifyAgentToolChildRecovery, cleanupStreamBuffers, clearChatTerminal, clientResolvableToolNames, createAgentToolEventState, createChatFiberSnapshot, createToolsFromClientSchemas, crossMessageToolResultUpdate, drainInteractionApplies, enforceRowSizeLimit, hasIncompleteToolBatch, interceptAgentToolBroadcast, isReplayChunk, iterateWithStallWatchdog, normalizeToolInput, parseProtocolMessage, partAwaitsClientInteraction, pausedExecutionUpdate, pendingChatTerminal, persistReconstructedOrphan, readChatRecoveryProgress, reconcileMessages, reconcileOrphanPartial, recordChatTerminal, repairInterruptedToolParts, resolveChatRecoveryConfig, resolveToolMergeId, runChatRecoveryExhaustion, sanitizeMessage, sendIfOpen, setChatRecovering, shouldCreditStreamProgress, sweepStaleChatRecoveryIncidents, toolApprovalUpdate, toolPartHasSettledResult, toolResultUpdate, unwrapChatFiberSnapshot, wrapChatFiberSnapshot };
|
|
3406
|
+
export { AGENT_TOOL_STREAM_PROGRESS_BUMP_THROTTLE_MS, AbortRegistry, AgentToolProgressEmitter, AgentToolStreamProgressThrottle, AutoContinuationController, CHAT_LAST_TERMINAL_KEY, CHAT_MESSAGE_TYPES, CHAT_RECOVERING_FLAG_TTL_MS, CHAT_RECOVERING_KEY, CHAT_RECOVERY_ALARM_DEBOUNCE_MS, CHAT_RECOVERY_INCIDENT_KEY_PREFIX, CHAT_RECOVERY_INCIDENT_TTL_MS, CHAT_RECOVERY_PROGRESS_KEY, CHAT_RECOVERY_STABLE_RETRY_DELAY_SECONDS, CHAT_STREAM_PROGRESS_CREDIT_THROTTLE_MS, ChatRecoveryEngine, ChatStreamStalledError, ContinuationState, DEFAULT_CHAT_RECOVERY_MAX_ATTEMPTS, DEFAULT_CHAT_RECOVERY_MAX_OOM_RETRIES, DEFAULT_CHAT_RECOVERY_MAX_WORK, DEFAULT_CHAT_RECOVERY_NO_PROGRESS_TIMEOUT_MS, DEFAULT_CHAT_RECOVERY_STABLE_TIMEOUT_MS, DEFAULT_CHAT_RECOVERY_TERMINAL_MESSAGE, KV_DELETE_MAX_KEYS, MAX_BOUND_PARAMS, MessageType, PreStreamTurns, ROW_MAX_BYTES, ResumableStream, ResumeHandshake, STREAM_CLEANUP_DELAY_SECONDS, StreamAccumulator, StreamProgressCreditThrottle, SubmitConcurrencyController, TIMED_OUT, TurnQueue, aiSdkRecoveryCodec, applyAgentToolEvent, applyChunkToParts, applyToolUpdate, awaitWithDeadline, transition as broadcastTransition, buildChatRecoveringFrame, buildInClauseStrings, bumpChatRecoveryProgress, byteLength, chatRecoverySchedulePolicy, classifyAgentToolChildRecovery, cleanupStreamBuffers, clearChatTerminal, clientResolvableToolNames, createAgentToolEventState, createChatFiberSnapshot, createToolsFromClientSchemas, crossMessageToolResultUpdate, drainInteractionApplies, enforceRowSizeLimit, hasIncompleteToolBatch, interceptAgentToolBroadcast, isReplayChunk, iterateWithStallWatchdog, listActiveChatRecoveryIncidents, normalizeToolInput, parseProtocolMessage, partAwaitsClientInteraction, pausedExecutionUpdate, pendingChatTerminal, persistReconstructedOrphan, readChatRecoveryProgress, reconcileMessages, reconcileOrphanPartial, recordChatTerminal, repairInterruptedToolParts, resolveChatRecoveryConfig, resolveToolMergeId, runChatRecoveryExhaustion, sanitizeMessage, sendIfOpen, setChatRecovering, shouldCreditStreamProgress, sweepStaleChatRecoveryIncidents, toolApprovalUpdate, toolPartHasSettledResult, toolResultUpdate, unwrapChatFiberSnapshot, wrapChatFiberSnapshot };
|
|
3309
3407
|
|
|
3310
3408
|
//# sourceMappingURL=index.js.map
|