@alvin0/ai-agent-sdk-core 0.1.7 → 0.1.9
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/README.md +6 -0
- package/dist/agent/define/session/config.js +1 -1
- package/dist/agent/define/session/config.js.map +1 -1
- package/dist/agent/define/session/types.d.ts +14 -0
- package/dist/agent/define/session/types.d.ts.map +1 -1
- package/dist/agent/define/session.d.ts.map +1 -1
- package/dist/agent/define/session.js +1 -1
- package/dist/agent/define/session.js.map +1 -1
- package/dist/agent/loop/events.d.ts +24 -1
- package/dist/agent/loop/events.d.ts.map +1 -1
- package/dist/agent/loop/run-turn.d.ts.map +1 -1
- package/dist/agent/loop/run-turn.js +1 -1
- package/dist/agent/loop/run-turn.js.map +1 -1
- package/dist/agent/loop/schedule.d.ts +5 -0
- package/dist/agent/loop/schedule.d.ts.map +1 -1
- package/dist/agent/loop/schedule.js +1 -1
- package/dist/agent/loop/schedule.js.map +1 -1
- package/dist/agent/loop/turn/config.js +1 -1
- package/dist/agent/loop/turn/config.js.map +1 -1
- package/dist/agent/loop/turn/model-request-boundary.js +1 -1
- package/dist/agent/loop/turn/model-request-boundary.js.map +1 -1
- package/dist/agent/loop/turn/model-round.js +1 -1
- package/dist/agent/loop/turn/model-round.js.map +1 -1
- package/dist/agent/loop/turn/types.d.ts +35 -2
- package/dist/agent/loop/turn/types.d.ts.map +1 -1
- package/dist/agent/loop/types.d.ts +16 -0
- package/dist/agent/loop/types.d.ts.map +1 -1
- package/dist/agent/mode/run-agent.d.ts +9 -0
- package/dist/agent/mode/run-agent.d.ts.map +1 -1
- package/dist/agent/mode/run-agent.js +2 -2
- package/dist/agent/mode/run-agent.js.map +1 -1
- package/dist/agent/mode/user-input.d.ts.map +1 -1
- package/dist/agent/mode/user-input.js +1 -1
- package/dist/agent/mode/user-input.js.map +1 -1
- package/dist/agent/team/managed.d.ts.map +1 -1
- package/dist/agent/team/managed.js +1 -1
- package/dist/agent/team/managed.js.map +1 -1
- package/dist/agent/tool/capture.js +1 -1
- package/dist/agent/tool/capture.js.map +1 -1
- package/dist/agent/tool/definition.d.ts +7 -0
- package/dist/agent/tool/definition.d.ts.map +1 -1
- package/dist/agent/tool/definition.js.map +1 -1
- package/dist/agent.js +1 -1
- package/dist/composition/agent/public-event.d.ts +19 -0
- package/dist/composition/agent/public-event.d.ts.map +1 -0
- package/dist/composition/agent/public-event.js +2 -0
- package/dist/composition/agent/public-event.js.map +1 -0
- package/dist/composition/agent/session.js +1 -1
- package/dist/composition/agent/session.js.map +1 -1
- package/dist/composition/agent/types.d.ts +11 -1
- package/dist/composition/agent/types.d.ts.map +1 -1
- package/dist/composition/embedding/retry.js +1 -1
- package/dist/composition/embedding/retry.js.map +1 -1
- package/dist/embedding/errors.d.ts +5 -1
- package/dist/embedding/errors.d.ts.map +1 -1
- package/dist/embedding/errors.js +1 -1
- package/dist/embedding/errors.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/observability/bus.js +1 -1
- package/dist/primitives/version.d.ts +1 -1
- package/dist/primitives/version.js +1 -1
- package/dist/primitives/version.js.map +1 -1
- package/dist/runtime/registry.js +1 -1
- package/dist/runtime/with-retry.d.ts +15 -0
- package/dist/runtime/with-retry.d.ts.map +1 -1
- package/dist/runtime/with-retry.js +1 -1
- package/dist/runtime/with-retry.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"with-retry.js","names":[],"sources":["../../src/runtime/with-retry.ts"],"sourcesContent":["/**\n * Retry as an adapter DECORATOR.\n *\n * In deepseek-harness this was a plugin on the agent loop's failed-step hook,\n * which let it restart a whole step and recover its attempt count from a durable\n * session log. A standalone SDK has neither, so retry moves down to the adapter\n * and holds its attempt count in the call's own closure.\n *\n * That relocation brings one hard constraint, and it is the thing to understand\n * about this module: a retry may only happen before response content is yielded.\n * Provisional usage snapshots are the only exception. Once a text delta has reached the consumer, re-running the\n * request would replay those tokens and the consumer would render them twice.\n * So a failure that arrives mid-stream is forwarded, not retried Erecovering\n * from it requires re-running the whole turn, which only the caller can decide.\n *\n * @module ai-agent-sdk/core/runtime/with-retry\n */\n\nimport { ModelAdapter, type PreparedAdapterCall } from '../contract/adapter.ts'\nimport type { GenerateOptions } from '../contract/generate-options.ts'\nimport type { ModelInfo, ResolvedModelInfo } from '../contract/model-info.ts'\nimport {\n backoffDelayMs,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type RetryPolicyConfig,\n} from '../contract/retry-policy.ts'\nimport { normalizeModelFailure, type ModelFailure } from '../errors/failure.ts'\nimport { MODEL_ERROR_CODES, ModelError } from '../errors/model-error.ts'\nimport type { StreamChunk } from '../stream/chunk.ts'\nimport type { ModelInvocationContext } from '../observation/report.ts'\nimport { waitForSettlement } from '../async/settlement.ts'\n\n/** One retry that is about to be waited out. */\nexport interface RetryAttempt {\n /** The route whose call failed. */\n readonly provider: string\n /** 1-based retry number. */\n readonly attempt: number\n /** Retry ceiling, or `undefined` under an `always` policy. */\n readonly maxRetries: number | undefined\n /** The failure being recovered from. */\n readonly failure: ModelFailure\n /** How long the decorator will wait before re-dispatching. */\n readonly delayMs: number\n}\n\n/** Options for {@link withRetry}. */\nexport interface WithRetryOptions {\n /**\n * Policy to apply. Omission uses the wrapped adapter's own per-route policy,\n * falling back to the shared defaults.\n */\n policy?: RetryPolicyConfig\n /** Sample in `[0, 1)` for jitter; injectable so tests can be deterministic. */\n random?: () => number\n /** Observe each scheduled retry Ethe hook for logging and metrics. */\n onRetry?: (attempt: RetryAttempt) => void\n /** Maximum wait while closing an unsuccessful attempt. Defaults to 30s. */\n teardownTimeoutMs?: number\n}\n\n/** Resolve a delay that honours a provider-requested `retry-after` when sane. */\nfunction delayFor(\n policy: ResolvedRetryPolicy,\n failure: ModelFailure,\n attempt: number,\n random: () => number,\n): number | 'give-up' {\n const requested = failure.providerRetryAfterMs\n if (requested !== undefined && Number.isFinite(requested) && requested > 0) {\n if (requested <= policy.maxDelayMs) return requested\n // The provider asked for longer than this policy is willing to wait. Under a\n // bounded policy that is a refusal: sleeping less than asked would just earn\n // another rate-limit response. An `always` policy has nowhere to give up to,\n // so it falls back to local backoff and keeps trying.\n return policy.mode === 'always' ? backoffDelayMs(policy, attempt, random) : 'give-up'\n }\n return backoffDelayMs(policy, attempt, random)\n}\n\n/** Sleep, resolving early and reporting false if the signal aborts first. */\nfunction cancellableDelay(delayMs: number, signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted === true) return Promise.resolve(false)\n return new Promise((resolve) => {\n const onAbort = (): void => {\n clearTimeout(timer)\n resolve(false)\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve(true)\n }, delayMs)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nclass RetryingAdapter extends ModelAdapter {\n private readonly inner: ModelAdapter\n private readonly options: WithRetryOptions\n\n // Explicit fields rather than constructor parameter properties: Node's\n // strip-only TypeScript mode rejects those, and this package is meant to run\n // under `node file.ts` without a build step.\n constructor(inner: ModelAdapter, options: WithRetryOptions) {\n super()\n this.inner = inner\n this.options = options\n }\n\n override providerInfo(provider: string): ReturnType<ModelAdapter['providerInfo']> {\n return this.inner.providerInfo(provider)\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.inner.providerRetryPolicy(provider)\n }\n\n override listModels(provider: string): Promise<readonly ModelInfo[]> {\n return this.inner.listModels(provider)\n }\n\n override resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<ResolvedModelInfo> {\n return this.inner.resolveModel(provider, model, signal)\n }\n\n override async prepareCall(\n provider: string,\n model: string,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<PreparedAdapterCall> {\n const prepared = await this.inner.prepareCall(provider, model, signal, context)\n const policy = this.policyFor(provider)\n return {\n model: prepared.model,\n // Retries reuse the SAME prepared generation. Re-preparing mid-retry could\n // pair a fresh endpoint with capabilities resolved against the old one,\n // which is exactly what the prepare/dispatch binding exists to prevent.\n stream: (options, invocation = context) => this.retryStream(options, request => prepared.stream(request, invocation), policy, invocation),\n }\n }\n\n stream(options: GenerateOptions, context?: ModelInvocationContext): AsyncIterable<StreamChunk> {\n return this.retryStream(\n options,\n request => this.inner.stream(request, context),\n this.policyFor(options.provider),\n context,\n )\n }\n\n private policyFor(provider: string): ResolvedRetryPolicy {\n if (this.options.policy !== undefined) {\n return resolveRetryPolicy(this.options.policy, `withRetry(\"${provider}\").policy`)\n }\n return this.inner.providerRetryPolicy(provider)\n ?? resolveRetryPolicy(undefined, `withRetry(\"${provider}\").policy`)\n }\n\n private async * retryStream(\n options: GenerateOptions,\n dispatch: (request: GenerateOptions) => AsyncIterable<StreamChunk>,\n policy: ResolvedRetryPolicy,\n context?: ModelInvocationContext,\n ): AsyncGenerator<StreamChunk> {\n if (policy.mode === 'always' && options.signal === undefined) {\n yield {\n type: 'finish',\n reason: {\n kind: 'error',\n failure: {\n message: 'an always retry policy requires an AbortSignal or deadline',\n code: MODEL_ERROR_CODES.INVALID_REQUEST,\n },\n },\n }\n return\n }\n const random = this.options.random ?? Math.random\n let retries = 0\n\n while (true) {\n const attempt = yield* this.runAttempt(options, dispatch)\n if (attempt.kind === 'forward') {\n yield* attempt.chunks\n return\n }\n\n const failure = attempt.failure\n // An abort is the caller's decision, never a transient fault.\n if (options.signal?.aborted === true || failure.code === MODEL_ERROR_CODES.ABORTED) {\n yield { type: 'finish', reason: { kind: 'aborted', failure } }\n return\n }\n\n const eligible = policy.mode === 'always'\n || (policy.retryableCodes.includes(failure.code) && retries < policy.maxRetries)\n if (!eligible) {\n yield { type: 'finish', reason: { kind: 'error', failure } }\n return\n }\n\n const delayMs = delayFor(policy, failure, retries + 1, random)\n if (delayMs === 'give-up') {\n yield { type: 'finish', reason: { kind: 'error', failure } }\n return\n }\n\n retries += 1\n context?.recordProviderRetry?.({\n nextAttemptNumber: retries + 1,\n delayMs,\n failureCode: failure.code,\n })\n try {\n this.options.onRetry?.({\n provider: options.provider,\n attempt: retries,\n maxRetries: policy.mode === 'normal' ? policy.maxRetries : undefined,\n failure,\n delayMs,\n })\n } catch {\n // Metrics/logging observers do not own request availability.\n }\n if (!await cancellableDelay(delayMs, options.signal)) {\n yield {\n type: 'finish',\n reason: {\n kind: 'aborted',\n failure: {\n message: 'model call aborted while waiting to retry',\n code: MODEL_ERROR_CODES.ABORTED,\n },\n },\n }\n return\n }\n }\n }\n\n /**\n * Run one attempt, forwarding only provisional usage before committing content.\n *\n * Buffering is what makes retry safe: until the attempt either produces its\n * first non-progress chunk or fails, no content has been committed. Once that\n * chunk exists the attempt is no longer retryable, so it switches to\n * `forward` and streams the rest through untouched.\n */\n private async *runAttempt(\n options: GenerateOptions,\n dispatch: (request: GenerateOptions) => AsyncIterable<StreamChunk>,\n ): AsyncGenerator<StreamChunk,\n | { kind: 'forward'; chunks: AsyncIterable<StreamChunk> }\n | { kind: 'retryable'; failure: ModelFailure }\n > {\n let iterator: AsyncIterator<StreamChunk>\n try {\n iterator = dispatch(options)[Symbol.asyncIterator]()\n } catch (error: unknown) {\n return { kind: 'retryable', failure: normalizeModelFailure(error) }\n }\n\n let first: IteratorResult<StreamChunk>\n try {\n first = await iterator.next()\n // Provisional accounting is not response content: preserve pre-content\n // retries while allowing the caller to observe usage as it arrives.\n while (!first.done && first.value.type === 'usage-progress') {\n let resumed = false\n try {\n yield first.value\n resumed = true\n } finally {\n if (!resumed) await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n }\n first = await iterator.next()\n }\n } catch (error: unknown) {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: normalizeModelFailure(error) }\n }\n\n // A stream that ends with no chunks at all told us nothing; treat it as the\n // degenerate empty response rather than a silently successful turn.\n if (first.done === true) {\n return {\n kind: 'retryable',\n failure: {\n message: 'the adapter produced no chunks',\n code: MODEL_ERROR_CODES.UNKNOWN,\n },\n }\n }\n\n // An adapter behind the registry's funnel reports failure as a terminal\n // error finish rather than a throw. As the FIRST chunk, that is still a\n // clean nothing-emitted failure and remains retryable.\n const chunk = first.value\n if (chunk.type === 'finish' && chunk.reason.kind === 'error') {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: chunk.reason.failure }\n }\n\n return {\n kind: 'forward',\n chunks: resume(chunk, iterator, this.options.teardownTimeoutMs ?? 30_000),\n }\n }\n}\n\nfunction positiveFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${name} must be a positive finite number`)\n return value\n}\n\n/** Re-attach an already-read first chunk to the front of its iterator. */\nasync function* resume(\n first: StreamChunk,\n iterator: AsyncIterator<StreamChunk>,\n teardownTimeoutMs: number,\n): AsyncGenerator<StreamChunk> {\n let exhausted = false\n try {\n yield first\n while (true) {\n const next = await iterator.next()\n if (next.done === true) {\n exhausted = true\n return\n }\n yield next.value\n }\n } finally {\n if (!exhausted) await closeIterator(iterator, teardownTimeoutMs)\n }\n}\n\nasync function closeIterator(iterator: AsyncIterator<StreamChunk>, timeoutMs: number): Promise<void> {\n const closing = iterator.return?.()\n if (closing === undefined) return\n const settled = await waitForSettlement(\n Promise.resolve(closing),\n positiveFinite(timeoutMs, 'withRetry teardownTimeoutMs'),\n )\n if (!settled) {\n throw new ModelError(\n `retry attempt teardown exceeded ${timeoutMs}ms`,\n MODEL_ERROR_CODES.TEARDOWN_TIMEOUT,\n )\n }\n}\n\n/**\n * Wrap an adapter so eligible transient failures are retried with bounded\n * exponential backoff and jitter.\n *\n * Only failures that occur BEFORE the first chunk reaches the consumer are\n * retried; see the module note for why.\n * @param adapter - the adapter to wrap; its metadata methods are delegated unchanged.\n * @param options - policy, jitter source, and retry observer.\n * @returns a new adapter with retry behaviour; the original is unmodified.\n */\nexport function withRetry(adapter: ModelAdapter, options: WithRetryOptions = {}): ModelAdapter {\n return new RetryingAdapter(adapter, options)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"with-retry.js","names":[],"sources":["../../src/runtime/with-retry.ts"],"sourcesContent":["/**\n * Retry as an adapter DECORATOR.\n *\n * In deepseek-harness this was a plugin on the agent loop's failed-step hook,\n * which let it restart a whole step and recover its attempt count from a durable\n * session log. A standalone SDK has neither, so retry moves down to the adapter\n * and holds its attempt count in the call's own closure.\n *\n * That relocation brings one hard constraint, and it is the thing to understand\n * about this module: a retry may only happen before response content is yielded.\n * Provisional usage snapshots are the only exception. Once a text delta has reached the consumer, re-running the\n * request would replay those tokens and the consumer would render them twice.\n * So a failure that arrives mid-stream is forwarded, not retried Erecovering\n * from it requires re-running the whole turn, which only the caller can decide.\n *\n * @module ai-agent-sdk/core/runtime/with-retry\n */\n\nimport { ModelAdapter, type PreparedAdapterCall } from '../contract/adapter.ts'\nimport type { GenerateOptions } from '../contract/generate-options.ts'\nimport type { ModelInfo, ResolvedModelInfo } from '../contract/model-info.ts'\nimport {\n backoffDelayMs,\n resolveRetryPolicy,\n type ResolvedRetryPolicy,\n type RetryPolicyConfig,\n} from '../contract/retry-policy.ts'\nimport { normalizeModelFailure, type ModelFailure } from '../errors/failure.ts'\nimport { MODEL_ERROR_CODES, ModelError } from '../errors/model-error.ts'\nimport type { StreamChunk } from '../stream/chunk.ts'\nimport type { ModelInvocationContext } from '../observation/report.ts'\nimport { waitForSettlement } from '../async/settlement.ts'\n\n/** One retry that is about to be waited out. */\nexport interface RetryAttempt {\n /** The route whose call failed. */\n readonly provider: string\n /** 1-based retry number. */\n readonly attempt: number\n /** Retry ceiling, or `undefined` under an `always` policy. */\n readonly maxRetries: number | undefined\n /** The failure being recovered from. */\n readonly failure: ModelFailure\n /** How long the decorator will wait before re-dispatching. */\n readonly delayMs: number\n}\n\n/** Options for {@link withRetry}. */\nexport interface WithRetryOptions {\n /**\n * Policy to apply. Omission uses the wrapped adapter's own per-route policy,\n * falling back to the shared defaults.\n */\n policy?: RetryPolicyConfig\n /** Sample in `[0, 1)` for jitter; injectable so tests can be deterministic. */\n random?: () => number\n /** Observe each scheduled retry Ethe hook for logging and metrics. */\n onRetry?: (attempt: RetryAttempt) => void\n /** Maximum wait while closing an unsuccessful attempt. Defaults to 30s. */\n teardownTimeoutMs?: number\n /**\n * Keep an attempt retryable while it has only streamed reasoning.\n *\n * Reasoning models open a reasoning block before any answer, so by default\n * the retry window closes there and a provider failure while the model is\n * still thinking cannot be retried. With this on, reasoning chunks are held\n * back until the first answer or tool chunk (or the end), then released in\n * order; a failure before that discards them and retries cleanly, so the\n * consumer never sees a failed attempt's reasoning twice. The cost is that\n * reasoning is not shown live. `true` holds up to 4096 chunks; past the cap\n * the attempt is forwarded as usual and retry stops applying.\n */\n bufferReasoningPrefix?: boolean | { readonly maxChunks: number }\n}\n\n/** Resolve a delay that honours a provider-requested `retry-after` when sane. */\nfunction delayFor(\n policy: ResolvedRetryPolicy,\n failure: ModelFailure,\n attempt: number,\n random: () => number,\n): number | 'give-up' {\n const requested = failure.providerRetryAfterMs\n if (requested !== undefined && Number.isFinite(requested) && requested > 0) {\n if (requested <= policy.maxDelayMs) return requested\n // The provider asked for longer than this policy is willing to wait. Under a\n // bounded policy that is a refusal: sleeping less than asked would just earn\n // another rate-limit response. An `always` policy has nowhere to give up to,\n // so it falls back to local backoff and keeps trying.\n return policy.mode === 'always' ? backoffDelayMs(policy, attempt, random) : 'give-up'\n }\n return backoffDelayMs(policy, attempt, random)\n}\n\n/** Sleep, resolving early and reporting false if the signal aborts first. */\nfunction cancellableDelay(delayMs: number, signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted === true) return Promise.resolve(false)\n return new Promise((resolve) => {\n const onAbort = (): void => {\n clearTimeout(timer)\n resolve(false)\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve(true)\n }, delayMs)\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\nclass RetryingAdapter extends ModelAdapter {\n private readonly inner: ModelAdapter\n private readonly options: WithRetryOptions\n\n // Explicit fields rather than constructor parameter properties: Node's\n // strip-only TypeScript mode rejects those, and this package is meant to run\n // under `node file.ts` without a build step.\n constructor(inner: ModelAdapter, options: WithRetryOptions) {\n super()\n this.inner = inner\n this.options = options\n }\n\n override providerInfo(provider: string): ReturnType<ModelAdapter['providerInfo']> {\n return this.inner.providerInfo(provider)\n }\n\n override providerRetryPolicy(provider: string): ResolvedRetryPolicy | undefined {\n return this.inner.providerRetryPolicy(provider)\n }\n\n override listModels(provider: string): Promise<readonly ModelInfo[]> {\n return this.inner.listModels(provider)\n }\n\n override resolveModel(\n provider: string,\n model: string,\n signal?: AbortSignal,\n ): Promise<ResolvedModelInfo> {\n return this.inner.resolveModel(provider, model, signal)\n }\n\n override async prepareCall(\n provider: string,\n model: string,\n signal?: AbortSignal,\n context?: ModelInvocationContext,\n ): Promise<PreparedAdapterCall> {\n const prepared = await this.inner.prepareCall(provider, model, signal, context)\n const policy = this.policyFor(provider)\n return {\n model: prepared.model,\n // Retries reuse the SAME prepared generation. Re-preparing mid-retry could\n // pair a fresh endpoint with capabilities resolved against the old one,\n // which is exactly what the prepare/dispatch binding exists to prevent.\n stream: (options, invocation = context) => this.retryStream(options, request => prepared.stream(request, invocation), policy, invocation),\n }\n }\n\n stream(options: GenerateOptions, context?: ModelInvocationContext): AsyncIterable<StreamChunk> {\n return this.retryStream(\n options,\n request => this.inner.stream(request, context),\n this.policyFor(options.provider),\n context,\n )\n }\n\n private policyFor(provider: string): ResolvedRetryPolicy {\n if (this.options.policy !== undefined) {\n return resolveRetryPolicy(this.options.policy, `withRetry(\"${provider}\").policy`)\n }\n return this.inner.providerRetryPolicy(provider)\n ?? resolveRetryPolicy(undefined, `withRetry(\"${provider}\").policy`)\n }\n\n private async * retryStream(\n options: GenerateOptions,\n dispatch: (request: GenerateOptions) => AsyncIterable<StreamChunk>,\n policy: ResolvedRetryPolicy,\n context?: ModelInvocationContext,\n ): AsyncGenerator<StreamChunk> {\n if (policy.mode === 'always' && options.signal === undefined) {\n yield {\n type: 'finish',\n reason: {\n kind: 'error',\n failure: {\n message: 'an always retry policy requires an AbortSignal or deadline',\n code: MODEL_ERROR_CODES.INVALID_REQUEST,\n },\n },\n }\n return\n }\n const random = this.options.random ?? Math.random\n let retries = 0\n\n while (true) {\n const attempt = yield* this.runAttempt(options, dispatch)\n if (attempt.kind === 'forward') {\n yield* attempt.chunks\n return\n }\n\n const failure = attempt.failure\n // An abort is the caller's decision, never a transient fault.\n if (options.signal?.aborted === true || failure.code === MODEL_ERROR_CODES.ABORTED) {\n yield { type: 'finish', reason: { kind: 'aborted', failure } }\n return\n }\n\n const eligible = policy.mode === 'always'\n || (policy.retryableCodes.includes(failure.code) && retries < policy.maxRetries)\n if (!eligible) {\n yield { type: 'finish', reason: { kind: 'error', failure } }\n return\n }\n\n const delayMs = delayFor(policy, failure, retries + 1, random)\n if (delayMs === 'give-up') {\n yield { type: 'finish', reason: { kind: 'error', failure } }\n return\n }\n\n retries += 1\n context?.recordProviderRetry?.({\n nextAttemptNumber: retries + 1,\n delayMs,\n failureCode: failure.code,\n })\n try {\n this.options.onRetry?.({\n provider: options.provider,\n attempt: retries,\n maxRetries: policy.mode === 'normal' ? policy.maxRetries : undefined,\n failure,\n delayMs,\n })\n } catch {\n // Metrics/logging observers do not own request availability.\n }\n if (!await cancellableDelay(delayMs, options.signal)) {\n yield {\n type: 'finish',\n reason: {\n kind: 'aborted',\n failure: {\n message: 'model call aborted while waiting to retry',\n code: MODEL_ERROR_CODES.ABORTED,\n },\n },\n }\n return\n }\n }\n }\n\n /**\n * Run one attempt, forwarding only provisional usage before committing content.\n *\n * Buffering is what makes retry safe: until the attempt either produces its\n * first non-progress chunk or fails, no content has been committed. Once that\n * chunk exists the attempt is no longer retryable, so it switches to\n * `forward` and streams the rest through untouched.\n */\n private async *runAttempt(\n options: GenerateOptions,\n dispatch: (request: GenerateOptions) => AsyncIterable<StreamChunk>,\n ): AsyncGenerator<StreamChunk,\n | { kind: 'forward'; chunks: AsyncIterable<StreamChunk> }\n | { kind: 'retryable'; failure: ModelFailure }\n > {\n const cap = reasoningBufferCap(this.options.bufferReasoningPrefix)\n let iterator: AsyncIterator<StreamChunk>\n try {\n iterator = dispatch(options)[Symbol.asyncIterator]()\n } catch (error: unknown) {\n return { kind: 'retryable', failure: normalizeModelFailure(error) }\n }\n\n let first: IteratorResult<StreamChunk>\n try {\n first = await iterator.next()\n // Provisional accounting is not response content: preserve pre-content\n // retries while allowing the caller to observe usage as it arrives.\n while (!first.done && first.value.type === 'usage-progress') {\n let resumed = false\n try {\n yield first.value\n resumed = true\n } finally {\n if (!resumed) await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n }\n first = await iterator.next()\n }\n } catch (error: unknown) {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: normalizeModelFailure(error) }\n }\n\n // A stream that ends with no chunks at all told us nothing; treat it as the\n // degenerate empty response rather than a silently successful turn.\n if (first.done === true) {\n return {\n kind: 'retryable',\n failure: {\n message: 'the adapter produced no chunks',\n code: MODEL_ERROR_CODES.UNKNOWN,\n },\n }\n }\n\n // An adapter behind the registry's funnel reports failure as a terminal\n // error finish rather than a throw. As the FIRST chunk, that is still a\n // clean nothing-emitted failure and remains retryable.\n let chunk = first.value\n if (chunk.type === 'finish' && chunk.reason.kind === 'error') {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: chunk.reason.failure }\n }\n\n const held: StreamChunk[] = []\n if (cap > 0) {\n const reasoningBlocks = new Set<number>()\n let ended = false\n try {\n while (isReasoningChunk(chunk, reasoningBlocks) && held.length < cap) {\n held.push(chunk)\n let next = await iterator.next()\n while (!next.done && next.value.type === 'usage-progress') {\n let resumed = false\n try {\n yield next.value\n resumed = true\n } finally {\n if (!resumed) await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n }\n next = await iterator.next()\n }\n if (next.done === true) { ended = true; break }\n chunk = next.value\n // Still only thinking when it failed: nothing was shown, so retry.\n if (chunk.type === 'finish' && chunk.reason.kind === 'error') {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: chunk.reason.failure }\n }\n }\n } catch (error: unknown) {\n await closeIterator(iterator, this.options.teardownTimeoutMs ?? 30_000)\n return { kind: 'retryable', failure: normalizeModelFailure(error) }\n }\n // A stream that only reasoned and then ended releases what it held.\n if (ended) {\n return { kind: 'forward', chunks: resume(held, undefined, iterator, this.options.teardownTimeoutMs ?? 30_000) }\n }\n }\n\n return {\n kind: 'forward',\n chunks: resume(held, chunk, iterator, this.options.teardownTimeoutMs ?? 30_000),\n }\n }\n}\n\nfunction positiveFinite(value: number, name: string): number {\n if (!Number.isFinite(value) || value <= 0) throw new RangeError(`${name} must be a positive finite number`)\n return value\n}\n\nfunction reasoningBufferCap(option: WithRetryOptions['bufferReasoningPrefix']): number {\n if (option === undefined || option === false) return 0\n if (option === true) return 4096\n if (!Number.isSafeInteger(option.maxChunks) || option.maxChunks < 1) {\n throw new RangeError('bufferReasoningPrefix.maxChunks must be a positive safe integer')\n }\n return option.maxChunks\n}\n\n/** Whether a chunk only carries reasoning, tracking which block indexes are reasoning. */\nfunction isReasoningChunk(chunk: StreamChunk, reasoningBlocks: Set<number>): boolean {\n if (chunk.type === 'reasoning-delta') return true\n if (chunk.type === 'block-start' && chunk.blockType === 'reasoning') {\n reasoningBlocks.add(chunk.index)\n return true\n }\n return chunk.type === 'block-end' && (chunk.block.type === 'reasoning' || reasoningBlocks.has(chunk.index))\n}\n\n/** Re-attach already-read chunks to the front of their iterator. */\nasync function* resume(\n held: readonly StreamChunk[],\n first: StreamChunk | undefined,\n iterator: AsyncIterator<StreamChunk>,\n teardownTimeoutMs: number,\n): AsyncGenerator<StreamChunk> {\n let exhausted = false\n try {\n for (const chunk of held) yield chunk\n if (first !== undefined) yield first\n while (true) {\n const next = await iterator.next()\n if (next.done === true) {\n exhausted = true\n return\n }\n yield next.value\n }\n } finally {\n if (!exhausted) await closeIterator(iterator, teardownTimeoutMs)\n }\n}\n\nasync function closeIterator(iterator: AsyncIterator<StreamChunk>, timeoutMs: number): Promise<void> {\n const closing = iterator.return?.()\n if (closing === undefined) return\n const settled = await waitForSettlement(\n Promise.resolve(closing),\n positiveFinite(timeoutMs, 'withRetry teardownTimeoutMs'),\n )\n if (!settled) {\n throw new ModelError(\n `retry attempt teardown exceeded ${timeoutMs}ms`,\n MODEL_ERROR_CODES.TEARDOWN_TIMEOUT,\n )\n }\n}\n\n/**\n * Wrap an adapter so eligible transient failures are retried with bounded\n * exponential backoff and jitter.\n *\n * Only failures that occur BEFORE the first chunk reaches the consumer are\n * retried; see the module note for why.\n * @param adapter - the adapter to wrap; its metadata methods are delegated unchanged.\n * @param options - policy, jitter source, and retry observer.\n * @returns a new adapter with retry behaviour; the original is unmodified.\n */\nexport function withRetry(adapter: ModelAdapter, options: WithRetryOptions = {}): ModelAdapter {\n return new RetryingAdapter(adapter, options)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED