@caupulican/pi-ai 0.96.0 → 0.96.2
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/models.generated.d.ts +5210 -3786
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +1927 -689
- package/dist/models.generated.js.map +1 -1
- package/dist/providers/provider-runtime.d.ts +1 -1
- package/dist/providers/provider-runtime.d.ts.map +1 -1
- package/dist/providers/provider-runtime.js +3 -1
- package/dist/providers/provider-runtime.js.map +1 -1
- package/dist/utils/provider-retry.d.ts +11 -1
- package/dist/utils/provider-retry.d.ts.map +1 -1
- package/dist/utils/provider-retry.js +128 -27
- package/dist/utils/provider-retry.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clampThinkingLevel } from "../model-capabilities.ts";
|
|
2
2
|
import type { Api, AssistantMessage, CacheRetention, ImagesOptions, Model, ProviderResponse, SimpleStreamOptions, StreamOptions, TextContent, ThinkingContent } from "../types.ts";
|
|
3
3
|
import type { AssistantMessageEventStream } from "../utils/event-stream.ts";
|
|
4
|
-
import type
|
|
4
|
+
import { type ProviderRetryOptions } from "../utils/provider-retry.ts";
|
|
5
5
|
type ProviderRequestOptions = Pick<StreamOptions | ImagesOptions, "signal" | "timeoutMs">;
|
|
6
6
|
type ProviderRetrySource = Pick<StreamOptions | ImagesOptions, "signal" | "maxRetries" | "maxRetryDelayMs">;
|
|
7
7
|
type AssistantMessageOverrides = Partial<Pick<AssistantMessage, "stopReason" | "errorMessage">>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-runtime.d.ts","sourceRoot":"","sources":["../../src/providers/provider-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,KAAK,EACL,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,eAAe,EACf,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"provider-runtime.d.ts","sourceRoot":"","sources":["../../src/providers/provider-runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { clampThinkingLevel } from "../model-capabilities.js";
|
|
2
2
|
import { createEmptyUsage } from "../usage.js";
|
|
3
3
|
import { headersToRecord } from "../utils/headers.js";
|
|
4
|
+
import { appendProviderRetryDirective } from "../utils/provider-retry.js";
|
|
4
5
|
import { buildBaseOptions } from "./simple-options.js";
|
|
5
6
|
const committedSuccessfulParses = new WeakSet();
|
|
6
7
|
function isSuccessfulStopReason(stopReason) {
|
|
@@ -91,7 +92,8 @@ export function terminateAssistantStreamWithError(stream, output, signal, error,
|
|
|
91
92
|
return;
|
|
92
93
|
}
|
|
93
94
|
output.stopReason = signal?.aborted ? "aborted" : "error";
|
|
94
|
-
|
|
95
|
+
const formattedError = options.formatError(error);
|
|
96
|
+
output.errorMessage = signal?.aborted ? formattedError : appendProviderRetryDirective(formattedError, error);
|
|
95
97
|
stream.push({ type: "error", reason: output.stopReason, error: output });
|
|
96
98
|
stream.end();
|
|
97
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-runtime.js","sourceRoot":"","sources":["../../src/providers/provider-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAa9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAOvD,MAAM,yBAAyB,GAAG,IAAI,OAAO,EAAoB,CAAC;AAElE,SAAS,sBAAsB,CAAC,UAA0C;IACzE,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,OAAO,CAAC;AAC3D,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,8BAA8B,CAAC,MAAwB;IACtE,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,UAAU,CAAC;QAAE,OAAO;IACvD,yBAAyB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,sBAAsB,CACrC,KAAkB,EAClB,SAAS,GAA8B,EAAE;IAEzC,OAAO;QACN,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,EAAE;QACX,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,KAAK,EAAE,gBAAgB,EAAE;QACzB,UAAU,EAAE,MAAM;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,GAAG,SAAS;KACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,KAAkB,EAClB,OAAwC;IAKxC,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAC/B,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3E,OAAO;QACN,IAAI,EAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;QAC9C,gBAAgB,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,cAA+B;IACpE,IAAI,cAAc;QAAE,OAAO,cAAc,CAAC;IAC1C,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IAC/F,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,OAAiB,EACjB,KAAa,EACb,IAA8F;IAE9F,MAAM,WAAW,GAAG,MAAM,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjD,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,WAAwB,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC5C,OAA2C,EAC3C,gBAAyB;IAEzB,MAAM,OAAO,GAAG,OAAO,EAAE,SAAS,IAAI,gBAAgB,CAAC;IACvD,OAAO;QACN,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,UAAU,EAAE,CAAC;KACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,0BAA0B,CACzC,OAAwC,EACxC,iBAA0B;IAE1B,OAAO;QACN,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,iBAAiB;QACpD,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,MAAM,EAAE,OAAO,EAAE,MAAM;KACvB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CACjD,MAAmC,EACnC,MAAwB,EACxB,QAA8C,EAC9C,KAAa,EACb,UAAgF;IAEhF,MAAM,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACnG,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CACtC,MAAmC,EACnC,MAAwB,EACxB,OAAqB;IAErB,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1E,MAAM,CAAC,GAAG,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iCAAiC,CAChD,MAAmC,EACnC,MAAwB,EACxB,MAA+B,EAC/B,KAAc,EACd,OAGC;IAED,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,YAAY,GAAG,KAAuE,CAAC;YAC7F,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,aAAa;gBAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;QACvE,CAAC;IACF,CAAC;IACD,IAAI,yBAAyB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,sBAAsB,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QACxF,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACxC,OAAO;IACR,CAAC;IACD,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1D,MAAM,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACzE,MAAM,CAAC,GAAG,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,MAAmC,EACnC,MAAwB,EACxB,KAAuD,EACvD,YAAoB;IAEpB,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACtF,OAAO;IACR,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,yBAAyB,CACxC,KAA2C,EAC3C,KAA4F;IAE5F,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACxC,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import { clampThinkingLevel } from \"../model-capabilities.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tImagesOptions,\n\tModel,\n\tProviderResponse,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n} from \"../types.ts\";\nimport { createEmptyUsage } from \"../usage.ts\";\nimport type { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport type { ProviderRetryOptions } from \"../utils/provider-retry.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\ntype ProviderRequestOptions = Pick<StreamOptions | ImagesOptions, \"signal\" | \"timeoutMs\">;\ntype ProviderRetrySource = Pick<StreamOptions | ImagesOptions, \"signal\" | \"maxRetries\" | \"maxRetryDelayMs\">;\ntype AssistantMessageOverrides = Partial<Pick<AssistantMessage, \"stopReason\" | \"errorMessage\">>;\ntype StreamingScratchField = \"index\" | \"partialArgs\" | \"partialArgsComplete\" | \"partialJson\" | \"streamIndex\";\n\nconst committedSuccessfulParses = new WeakSet<AssistantMessage>();\n\nfunction isSuccessfulStopReason(stopReason: AssistantMessage[\"stopReason\"]): boolean {\n\treturn stopReason !== \"aborted\" && stopReason !== \"error\";\n}\n\n/** Mark a fully parsed assistant message so a later iterator abort cannot rewrite it. */\nexport function commitSuccessfulAssistantParse(output: AssistantMessage): void {\n\tif (!isSuccessfulStopReason(output.stopReason)) return;\n\tcommittedSuccessfulParses.add(output);\n}\n\nexport function createAssistantMessage<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toverrides: AssistantMessageOverrides = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t\t...overrides,\n\t};\n}\n\nexport function buildClampedSimpleOptions<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toptions: SimpleStreamOptions | undefined,\n): {\n\tbase: StreamOptions;\n\tclampedReasoning: ReturnType<typeof clampThinkingLevel> | undefined;\n} {\n\tconst apiKey = options?.apiKey;\n\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\treturn {\n\t\tbase: buildBaseOptions(model, options, apiKey),\n\t\tclampedReasoning: options.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined,\n\t};\n}\n\nexport function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {\n\tif (cacheRetention) return cacheRetention;\n\tif (typeof process !== \"undefined\" && process.env.PI_CACHE_RETENTION === \"long\") return \"long\";\n\treturn \"short\";\n}\n\nexport async function applyProviderPayloadHook<TPayload, TModel>(\n\tpayload: TPayload,\n\tmodel: TModel,\n\thook?: (payload: unknown, model: TModel) => unknown | undefined | Promise<unknown | undefined>,\n): Promise<TPayload> {\n\tconst replacement = await hook?.(payload, model);\n\treturn replacement === undefined ? payload : (replacement as TPayload);\n}\n\nexport function createRetryFreeRequestOptions(\n\toptions: ProviderRequestOptions | undefined,\n\tdefaultTimeoutMs?: number,\n): { signal?: AbortSignal; timeout?: number; maxRetries: 0 } {\n\tconst timeout = options?.timeoutMs ?? defaultTimeoutMs;\n\treturn {\n\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\tmaxRetries: 0,\n\t};\n}\n\nexport function createProviderRetryOptions(\n\toptions: ProviderRetrySource | undefined,\n\tdefaultMaxRetries?: number,\n): ProviderRetryOptions {\n\treturn {\n\t\tmaxRetries: options?.maxRetries ?? defaultMaxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tsignal: options?.signal,\n\t};\n}\n\nexport async function beginAssistantResponseStream<TModel>(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tresponse: { status: number; headers: Headers },\n\tmodel: TModel,\n\tonResponse?: (response: ProviderResponse, model: TModel) => void | Promise<void>,\n): Promise<void> {\n\tawait onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\tstream.push({ type: \"start\", partial: output });\n}\n\n/**\n * Push the successful terminal event for a fully parsed assistant message.\n *\n * A late abort on `signal` must not discard that message: mid-stream abort is\n * the transport's job and is already converted by {@link terminateAssistantStreamWithError}.\n * Checking the signal here is a TOCTOU that drops completed-only / fast responses.\n */\nexport function completeAssistantStream(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\t_signal?: AbortSignal,\n): void {\n\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\tthrow new Error(\"An unknown error occurred\");\n\t}\n\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\tstream.end();\n}\n\nexport function terminateAssistantStreamWithError(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tsignal: AbortSignal | undefined,\n\terror: unknown,\n\toptions: {\n\t\tformatError: (error: unknown) => string;\n\t\tscratchFields?: readonly StreamingScratchField[];\n\t},\n): void {\n\tif (options.scratchFields) {\n\t\tfor (const block of output.content) {\n\t\t\tconst scratchBlock = block as typeof block & Partial<Record<StreamingScratchField, unknown>>;\n\t\t\tfor (const field of options.scratchFields) delete scratchBlock[field];\n\t\t}\n\t}\n\tif (committedSuccessfulParses.has(output) && isSuccessfulStopReason(output.stopReason)) {\n\t\tcompleteAssistantStream(stream, output);\n\t\treturn;\n\t}\n\toutput.stopReason = signal?.aborted ? \"aborted\" : \"error\";\n\toutput.errorMessage = options.formatError(error);\n\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\tstream.end();\n}\n\nexport function finishTextOrThinkingBlock(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tblock: TextContent | ThinkingContent | null | undefined,\n\tcontentIndex: number,\n): void {\n\tif (!block) return;\n\tif (block.type === \"text\") {\n\t\tstream.push({ type: \"text_end\", contentIndex, content: block.text, partial: output });\n\t\treturn;\n\t}\n\tstream.push({ type: \"thinking_end\", contentIndex, content: block.thinking, partial: output });\n}\n\nexport function mapStandardThinkingEffort(\n\tmodel: Pick<Model<Api>, \"thinkingLevelMap\">,\n\tlevel: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\" | \"ultra\" | undefined,\n): string {\n\tconst mapped = level ? model.thinkingLevelMap?.[level] : undefined;\n\tif (typeof mapped === \"string\") return mapped;\n\tif (level === \"minimal\" || level === \"low\") return \"low\";\n\tif (level === \"medium\") return \"medium\";\n\treturn \"high\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-runtime.js","sourceRoot":"","sources":["../../src/providers/provider-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { clampThinkingLevel } from \"../model-capabilities.ts\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tCacheRetention,\n\tImagesOptions,\n\tModel,\n\tProviderResponse,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n} from \"../types.ts\";\nimport { createEmptyUsage } from \"../usage.ts\";\nimport type { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord } from \"../utils/headers.ts\";\nimport { appendProviderRetryDirective, type ProviderRetryOptions } from \"../utils/provider-retry.ts\";\nimport { buildBaseOptions } from \"./simple-options.ts\";\n\ntype ProviderRequestOptions = Pick<StreamOptions | ImagesOptions, \"signal\" | \"timeoutMs\">;\ntype ProviderRetrySource = Pick<StreamOptions | ImagesOptions, \"signal\" | \"maxRetries\" | \"maxRetryDelayMs\">;\ntype AssistantMessageOverrides = Partial<Pick<AssistantMessage, \"stopReason\" | \"errorMessage\">>;\ntype StreamingScratchField = \"index\" | \"partialArgs\" | \"partialArgsComplete\" | \"partialJson\" | \"streamIndex\";\n\nconst committedSuccessfulParses = new WeakSet<AssistantMessage>();\n\nfunction isSuccessfulStopReason(stopReason: AssistantMessage[\"stopReason\"]): boolean {\n\treturn stopReason !== \"aborted\" && stopReason !== \"error\";\n}\n\n/** Mark a fully parsed assistant message so a later iterator abort cannot rewrite it. */\nexport function commitSuccessfulAssistantParse(output: AssistantMessage): void {\n\tif (!isSuccessfulStopReason(output.stopReason)) return;\n\tcommittedSuccessfulParses.add(output);\n}\n\nexport function createAssistantMessage<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toverrides: AssistantMessageOverrides = {},\n): AssistantMessage {\n\treturn {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"stop\",\n\t\ttimestamp: Date.now(),\n\t\t...overrides,\n\t};\n}\n\nexport function buildClampedSimpleOptions<TApi extends Api>(\n\tmodel: Model<TApi>,\n\toptions: SimpleStreamOptions | undefined,\n): {\n\tbase: StreamOptions;\n\tclampedReasoning: ReturnType<typeof clampThinkingLevel> | undefined;\n} {\n\tconst apiKey = options?.apiKey;\n\tif (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);\n\treturn {\n\t\tbase: buildBaseOptions(model, options, apiKey),\n\t\tclampedReasoning: options.reasoning ? clampThinkingLevel(model, options.reasoning) : undefined,\n\t};\n}\n\nexport function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention {\n\tif (cacheRetention) return cacheRetention;\n\tif (typeof process !== \"undefined\" && process.env.PI_CACHE_RETENTION === \"long\") return \"long\";\n\treturn \"short\";\n}\n\nexport async function applyProviderPayloadHook<TPayload, TModel>(\n\tpayload: TPayload,\n\tmodel: TModel,\n\thook?: (payload: unknown, model: TModel) => unknown | undefined | Promise<unknown | undefined>,\n): Promise<TPayload> {\n\tconst replacement = await hook?.(payload, model);\n\treturn replacement === undefined ? payload : (replacement as TPayload);\n}\n\nexport function createRetryFreeRequestOptions(\n\toptions: ProviderRequestOptions | undefined,\n\tdefaultTimeoutMs?: number,\n): { signal?: AbortSignal; timeout?: number; maxRetries: 0 } {\n\tconst timeout = options?.timeoutMs ?? defaultTimeoutMs;\n\treturn {\n\t\t...(options?.signal ? { signal: options.signal } : {}),\n\t\t...(timeout !== undefined ? { timeout } : {}),\n\t\tmaxRetries: 0,\n\t};\n}\n\nexport function createProviderRetryOptions(\n\toptions: ProviderRetrySource | undefined,\n\tdefaultMaxRetries?: number,\n): ProviderRetryOptions {\n\treturn {\n\t\tmaxRetries: options?.maxRetries ?? defaultMaxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tsignal: options?.signal,\n\t};\n}\n\nexport async function beginAssistantResponseStream<TModel>(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tresponse: { status: number; headers: Headers },\n\tmodel: TModel,\n\tonResponse?: (response: ProviderResponse, model: TModel) => void | Promise<void>,\n): Promise<void> {\n\tawait onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\tstream.push({ type: \"start\", partial: output });\n}\n\n/**\n * Push the successful terminal event for a fully parsed assistant message.\n *\n * A late abort on `signal` must not discard that message: mid-stream abort is\n * the transport's job and is already converted by {@link terminateAssistantStreamWithError}.\n * Checking the signal here is a TOCTOU that drops completed-only / fast responses.\n */\nexport function completeAssistantStream(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\t_signal?: AbortSignal,\n): void {\n\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\tthrow new Error(\"An unknown error occurred\");\n\t}\n\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\tstream.end();\n}\n\nexport function terminateAssistantStreamWithError(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tsignal: AbortSignal | undefined,\n\terror: unknown,\n\toptions: {\n\t\tformatError: (error: unknown) => string;\n\t\tscratchFields?: readonly StreamingScratchField[];\n\t},\n): void {\n\tif (options.scratchFields) {\n\t\tfor (const block of output.content) {\n\t\t\tconst scratchBlock = block as typeof block & Partial<Record<StreamingScratchField, unknown>>;\n\t\t\tfor (const field of options.scratchFields) delete scratchBlock[field];\n\t\t}\n\t}\n\tif (committedSuccessfulParses.has(output) && isSuccessfulStopReason(output.stopReason)) {\n\t\tcompleteAssistantStream(stream, output);\n\t\treturn;\n\t}\n\toutput.stopReason = signal?.aborted ? \"aborted\" : \"error\";\n\tconst formattedError = options.formatError(error);\n\toutput.errorMessage = signal?.aborted ? formattedError : appendProviderRetryDirective(formattedError, error);\n\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\tstream.end();\n}\n\nexport function finishTextOrThinkingBlock(\n\tstream: AssistantMessageEventStream,\n\toutput: AssistantMessage,\n\tblock: TextContent | ThinkingContent | null | undefined,\n\tcontentIndex: number,\n): void {\n\tif (!block) return;\n\tif (block.type === \"text\") {\n\t\tstream.push({ type: \"text_end\", contentIndex, content: block.text, partial: output });\n\t\treturn;\n\t}\n\tstream.push({ type: \"thinking_end\", contentIndex, content: block.thinking, partial: output });\n}\n\nexport function mapStandardThinkingEffort(\n\tmodel: Pick<Model<Api>, \"thinkingLevelMap\">,\n\tlevel: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\" | \"ultra\" | undefined,\n): string {\n\tconst mapped = level ? model.thinkingLevelMap?.[level] : undefined;\n\tif (typeof mapped === \"string\") return mapped;\n\tif (level === \"minimal\" || level === \"low\") return \"low\";\n\tif (level === \"medium\") return \"medium\";\n\treturn \"high\";\n}\n"]}
|
|
@@ -3,9 +3,19 @@ export interface ProviderRetryOptions {
|
|
|
3
3
|
maxRetryDelayMs?: number;
|
|
4
4
|
signal?: AbortSignal;
|
|
5
5
|
}
|
|
6
|
+
export interface ProviderRetryDirective {
|
|
7
|
+
/** Explicit provider override from headers or structured availability metadata. */
|
|
8
|
+
shouldRetry?: boolean;
|
|
9
|
+
/** Minimum provider-requested delay before another request. */
|
|
10
|
+
retryAfterMs?: number;
|
|
11
|
+
}
|
|
12
|
+
/** Extract redacted semantic retry guidance without retaining raw provider headers. */
|
|
13
|
+
export declare function getProviderRetryDirective(error: unknown): ProviderRetryDirective | undefined;
|
|
14
|
+
/** Preserve retry guidance through string-only error/session boundaries. */
|
|
15
|
+
export declare function appendProviderRetryDirective(message: string, error: unknown): string;
|
|
6
16
|
/**
|
|
7
17
|
* Reproduce the retry behavior used by the OpenAI and Anthropic SDKs with an abortable backoff.
|
|
8
|
-
* Call the SDK with `maxRetries: 0`; this helper is the sole retry owner.
|
|
18
|
+
* Call the SDK with `maxRetries: 0`; this helper is the sole provider-request retry owner.
|
|
9
19
|
*/
|
|
10
20
|
export declare function retryProviderRequest<T>(request: () => Promise<T>, options?: ProviderRetryOptions): Promise<T>;
|
|
11
21
|
//# sourceMappingURL=provider-retry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-retry.d.ts","sourceRoot":"","sources":["../../src/utils/provider-retry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"provider-retry.d.ts","sourceRoot":"","sources":["../../src/utils/provider-retry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACtC,mFAAmF;IACnF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAyFD,uFAAuF;AACvF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,GAAG,SAAS,CAa5F;AAOD,4EAA4E;AAC5E,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAYpF;AAoCD;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC3C,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,OAAO,GAAE,oBAAyB,GAChC,OAAO,CAAC,CAAC,CAAC,CAuBZ"}
|
|
@@ -1,49 +1,144 @@
|
|
|
1
1
|
import { abortableSleep, createAbortError } from "./abort-signals.js";
|
|
2
2
|
const DEFAULT_MAX_RETRY_DELAY_MS = 60_000;
|
|
3
|
+
const providerRetryDirectiveOverrides = new WeakMap();
|
|
4
|
+
function isProviderHeaders(value) {
|
|
5
|
+
return value === undefined || (typeof value === "object" && value !== null);
|
|
6
|
+
}
|
|
7
|
+
function getProviderHeader(headers, name) {
|
|
8
|
+
if (!headers)
|
|
9
|
+
return undefined;
|
|
10
|
+
if ("get" in headers && typeof headers.get === "function") {
|
|
11
|
+
const value = headers.get(name);
|
|
12
|
+
return value === null ? undefined : value;
|
|
13
|
+
}
|
|
14
|
+
const entry = Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1];
|
|
15
|
+
return Array.isArray(entry) ? entry.join(", ") : entry;
|
|
16
|
+
}
|
|
3
17
|
function isProviderError(error) {
|
|
4
18
|
if (!(error instanceof Error) || !("status" in error) || !("headers" in error))
|
|
5
19
|
return false;
|
|
6
|
-
return (
|
|
7
|
-
(error.headers === undefined || error.headers instanceof Headers));
|
|
20
|
+
return (error.status === undefined || typeof error.status === "number") && isProviderHeaders(error.headers);
|
|
8
21
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (shouldRetry === "true")
|
|
22
|
+
function getExplicitShouldRetry(headers) {
|
|
23
|
+
const value = getProviderHeader(headers, "x-should-retry")?.trim().toLowerCase();
|
|
24
|
+
if (value === "true")
|
|
13
25
|
return true;
|
|
14
|
-
if (
|
|
26
|
+
if (value === "false")
|
|
27
|
+
return false;
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
function asRecord(value) {
|
|
31
|
+
return typeof value === "object" && value !== null ? value : undefined;
|
|
32
|
+
}
|
|
33
|
+
function getStructuredAvailability(error) {
|
|
34
|
+
const body = asRecord(error.error);
|
|
35
|
+
if (!body)
|
|
36
|
+
return undefined;
|
|
37
|
+
const direct = asRecord(body.availability);
|
|
38
|
+
if (direct)
|
|
39
|
+
return direct;
|
|
40
|
+
return asRecord(asRecord(body.error)?.availability);
|
|
41
|
+
}
|
|
42
|
+
function getStructuredShouldRetry(error) {
|
|
43
|
+
const retryable = getStructuredAvailability(error)?.retryable;
|
|
44
|
+
return typeof retryable === "boolean" ? retryable : undefined;
|
|
45
|
+
}
|
|
46
|
+
function getStructuredRetryDelayMs(error) {
|
|
47
|
+
const seconds = getStructuredAvailability(error)?.retry_after;
|
|
48
|
+
return typeof seconds === "number" && Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : undefined;
|
|
49
|
+
}
|
|
50
|
+
function getHeaderRetryDelayMs(error, nowMs = Date.now()) {
|
|
51
|
+
const retryAfterMs = getProviderHeader(error.headers, "retry-after-ms");
|
|
52
|
+
if (retryAfterMs !== null && retryAfterMs !== undefined) {
|
|
53
|
+
const value = Number.parseFloat(retryAfterMs);
|
|
54
|
+
if (Number.isFinite(value))
|
|
55
|
+
return Math.max(0, value);
|
|
56
|
+
}
|
|
57
|
+
const retryAfter = getProviderHeader(error.headers, "retry-after");
|
|
58
|
+
if (retryAfter !== null && retryAfter !== undefined) {
|
|
59
|
+
const seconds = Number.parseFloat(retryAfter);
|
|
60
|
+
const delayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - nowMs : seconds * 1000;
|
|
61
|
+
if (Number.isFinite(delayMs))
|
|
62
|
+
return Math.max(0, delayMs);
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
function getServerRetryDelayMs(error) {
|
|
67
|
+
const delays = [getHeaderRetryDelayMs(error), getStructuredRetryDelayMs(error)].filter((delay) => delay !== undefined);
|
|
68
|
+
return delays.length > 0 ? Math.max(...delays) : undefined;
|
|
69
|
+
}
|
|
70
|
+
function combineShouldRetry(...values) {
|
|
71
|
+
if (values.includes(false))
|
|
15
72
|
return false;
|
|
73
|
+
return values.includes(true) ? true : undefined;
|
|
74
|
+
}
|
|
75
|
+
/** Extract redacted semantic retry guidance without retaining raw provider headers. */
|
|
76
|
+
export function getProviderRetryDirective(error) {
|
|
77
|
+
if (!(error instanceof Error))
|
|
78
|
+
return undefined;
|
|
79
|
+
const override = providerRetryDirectiveOverrides.get(error);
|
|
80
|
+
if (override)
|
|
81
|
+
return override;
|
|
82
|
+
if (!isProviderError(error))
|
|
83
|
+
return undefined;
|
|
84
|
+
const shouldRetry = combineShouldRetry(getExplicitShouldRetry(error.headers), getStructuredShouldRetry(error));
|
|
85
|
+
const retryAfterMs = getServerRetryDelayMs(error);
|
|
86
|
+
if (shouldRetry === undefined && retryAfterMs === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
return {
|
|
89
|
+
...(shouldRetry !== undefined ? { shouldRetry } : {}),
|
|
90
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function formatRetrySeconds(delayMs) {
|
|
94
|
+
const seconds = delayMs / 1000;
|
|
95
|
+
return Number.isInteger(seconds) ? String(seconds) : String(Number(seconds.toFixed(3)));
|
|
96
|
+
}
|
|
97
|
+
/** Preserve retry guidance through string-only error/session boundaries. */
|
|
98
|
+
export function appendProviderRetryDirective(message, error) {
|
|
99
|
+
const directive = getProviderRetryDirective(error);
|
|
100
|
+
let suffix;
|
|
101
|
+
if (directive?.shouldRetry === false) {
|
|
102
|
+
suffix = "Provider retry directive: do not retry.";
|
|
103
|
+
}
|
|
104
|
+
else if (directive?.retryAfterMs !== undefined) {
|
|
105
|
+
suffix = `Provider retry directive: retry after ${formatRetrySeconds(directive.retryAfterMs)}s.`;
|
|
106
|
+
}
|
|
107
|
+
else if (directive?.shouldRetry === true) {
|
|
108
|
+
suffix = "Provider retry directive: retry.";
|
|
109
|
+
}
|
|
110
|
+
if (!suffix || message.includes(suffix))
|
|
111
|
+
return message;
|
|
112
|
+
return message.length > 0 ? `${message}\n${suffix}` : suffix;
|
|
113
|
+
}
|
|
114
|
+
/** Mirrors the pinned OpenAI and Anthropic SDK retry policy. */
|
|
115
|
+
function isRetryableProviderError(error) {
|
|
116
|
+
const shouldRetry = combineShouldRetry(getExplicitShouldRetry(error.headers), getStructuredShouldRetry(error));
|
|
117
|
+
if (shouldRetry !== undefined)
|
|
118
|
+
return shouldRetry;
|
|
16
119
|
if (error.status === undefined)
|
|
17
120
|
return true;
|
|
18
121
|
return error.status === 408 || error.status === 409 || error.status === 429 || error.status >= 500;
|
|
19
122
|
}
|
|
20
|
-
function
|
|
123
|
+
function createRetryDelayExceededError(error, delayMs, maxDelayMs) {
|
|
124
|
+
const boundedError = new Error(`Server requested ${formatRetrySeconds(delayMs)}s retry delay (max: ${formatRetrySeconds(maxDelayMs)}s). ${error.message}`, { cause: error });
|
|
125
|
+
providerRetryDirectiveOverrides.set(boundedError, { shouldRetry: false, retryAfterMs: delayMs });
|
|
126
|
+
return boundedError;
|
|
127
|
+
}
|
|
128
|
+
function validateServerRetryDelayMs(delayMs, maxRetryDelayMs, error) {
|
|
21
129
|
const maxDelayMs = maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
22
130
|
if (maxDelayMs > 0 && delayMs > maxDelayMs) {
|
|
23
|
-
throw
|
|
131
|
+
throw createRetryDelayExceededError(error, delayMs, maxDelayMs);
|
|
24
132
|
}
|
|
25
|
-
return
|
|
133
|
+
return delayMs;
|
|
26
134
|
}
|
|
27
|
-
function
|
|
28
|
-
const retryAfterMs = error.headers?.get("retry-after-ms");
|
|
29
|
-
if (retryAfterMs) {
|
|
30
|
-
const value = Number.parseFloat(retryAfterMs);
|
|
31
|
-
if (!Number.isNaN(value))
|
|
32
|
-
return validateServerRetryDelayMs(value, maxRetryDelayMs, error.message);
|
|
33
|
-
}
|
|
34
|
-
const retryAfter = error.headers?.get("retry-after");
|
|
35
|
-
if (retryAfter) {
|
|
36
|
-
const seconds = Number.parseFloat(retryAfter);
|
|
37
|
-
const delayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1000;
|
|
38
|
-
if (Number.isFinite(delayMs))
|
|
39
|
-
return validateServerRetryDelayMs(delayMs, maxRetryDelayMs, error.message);
|
|
40
|
-
}
|
|
135
|
+
function getFallbackRetryDelayMs(retryIndex) {
|
|
41
136
|
const exponentialDelay = Math.min(0.5 * 2 ** retryIndex, 8) * 1000;
|
|
42
137
|
return exponentialDelay * (1 - Math.random() * 0.25);
|
|
43
138
|
}
|
|
44
139
|
/**
|
|
45
140
|
* Reproduce the retry behavior used by the OpenAI and Anthropic SDKs with an abortable backoff.
|
|
46
|
-
* Call the SDK with `maxRetries: 0`; this helper is the sole retry owner.
|
|
141
|
+
* Call the SDK with `maxRetries: 0`; this helper is the sole provider-request retry owner.
|
|
47
142
|
*/
|
|
48
143
|
export async function retryProviderRequest(request, options = {}) {
|
|
49
144
|
const maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 0));
|
|
@@ -55,11 +150,17 @@ export async function retryProviderRequest(request, options = {}) {
|
|
|
55
150
|
catch (error) {
|
|
56
151
|
if (options.signal?.aborted)
|
|
57
152
|
throw createAbortError();
|
|
58
|
-
if (
|
|
153
|
+
if (!isProviderError(error) || !isRetryableProviderError(error))
|
|
154
|
+
throw error;
|
|
155
|
+
const serverDelayMs = getServerRetryDelayMs(error);
|
|
156
|
+
const boundedServerDelayMs = serverDelayMs === undefined
|
|
157
|
+
? undefined
|
|
158
|
+
: validateServerRetryDelayMs(serverDelayMs, options.maxRetryDelayMs, error);
|
|
159
|
+
if (retriesRemaining <= 0)
|
|
59
160
|
throw error;
|
|
60
161
|
const retryIndex = maxRetries - retriesRemaining;
|
|
61
162
|
retriesRemaining--;
|
|
62
|
-
await abortableSleep(
|
|
163
|
+
await abortableSleep(boundedServerDelayMs ?? getFallbackRetryDelayMs(retryIndex), options.signal);
|
|
63
164
|
}
|
|
64
165
|
}
|
|
65
166
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-retry.js","sourceRoot":"","sources":["../../src/utils/provider-retry.ts"],"names":[],"mappings":"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","sourcesContent":["import { abortableSleep, createAbortError } from \"./abort-signals.ts\";\n\nconst DEFAULT_MAX_RETRY_DELAY_MS = 60_000;\n\nexport interface ProviderRetryOptions {\n\tmaxRetries?: number;\n\tmaxRetryDelayMs?: number;\n\tsignal?: AbortSignal;\n}\n\ninterface ProviderError extends Error {\n\tstatus: number | undefined;\n\theaders: Headers | undefined;\n}\n\nfunction isProviderError(error: unknown): error is ProviderError {\n\tif (!(error instanceof Error) || !(\"status\" in error) || !(\"headers\" in error)) return false;\n\treturn (\n\t\t(error.status === undefined || typeof error.status === \"number\") &&\n\t\t(error.headers === undefined || error.headers instanceof Headers)\n\t);\n}\n\n/** Mirrors the pinned OpenAI and Anthropic SDK retry policy. */\nfunction isRetryableProviderError(error: ProviderError): boolean {\n\tconst shouldRetry = error.headers?.get(\"x-should-retry\");\n\tif (shouldRetry === \"true\") return true;\n\tif (shouldRetry === \"false\") return false;\n\tif (error.status === undefined) return true;\n\treturn error.status === 408 || error.status === 409 || error.status === 429 || error.status >= 500;\n}\n\nfunction validateServerRetryDelayMs(delayMs: number, maxRetryDelayMs: number | undefined, message: string): number {\n\tconst maxDelayMs = maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;\n\tif (maxDelayMs > 0 && delayMs > maxDelayMs) {\n\t\tthrow new Error(\n\t\t\t`Server requested ${Math.ceil(delayMs / 1000)}s retry delay (max: ${Math.ceil(maxDelayMs / 1000)}s). ${message}`,\n\t\t);\n\t}\n\treturn Math.max(0, delayMs);\n}\n\nfunction getRetryDelayMs(error: ProviderError, retryIndex: number, maxRetryDelayMs: number | undefined): number {\n\tconst retryAfterMs = error.headers?.get(\"retry-after-ms\");\n\tif (retryAfterMs) {\n\t\tconst value = Number.parseFloat(retryAfterMs);\n\t\tif (!Number.isNaN(value)) return validateServerRetryDelayMs(value, maxRetryDelayMs, error.message);\n\t}\n\n\tconst retryAfter = error.headers?.get(\"retry-after\");\n\tif (retryAfter) {\n\t\tconst seconds = Number.parseFloat(retryAfter);\n\t\tconst delayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1000;\n\t\tif (Number.isFinite(delayMs)) return validateServerRetryDelayMs(delayMs, maxRetryDelayMs, error.message);\n\t}\n\n\tconst exponentialDelay = Math.min(0.5 * 2 ** retryIndex, 8) * 1000;\n\treturn exponentialDelay * (1 - Math.random() * 0.25);\n}\n\n/**\n * Reproduce the retry behavior used by the OpenAI and Anthropic SDKs with an abortable backoff.\n * Call the SDK with `maxRetries: 0`; this helper is the sole retry owner.\n */\nexport async function retryProviderRequest<T>(\n\trequest: () => Promise<T>,\n\toptions: ProviderRetryOptions = {},\n): Promise<T> {\n\tconst maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 0));\n\tlet retriesRemaining = maxRetries;\n\n\tfor (;;) {\n\t\ttry {\n\t\t\treturn await request();\n\t\t} catch (error) {\n\t\t\tif (options.signal?.aborted) throw createAbortError();\n\t\t\tif (retriesRemaining <= 0 || !isProviderError(error) || !isRetryableProviderError(error)) throw error;\n\n\t\t\tconst retryIndex = maxRetries - retriesRemaining;\n\t\t\tretriesRemaining--;\n\t\t\tawait abortableSleep(getRetryDelayMs(error, retryIndex, options.maxRetryDelayMs), options.signal);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-retry.js","sourceRoot":"","sources":["../../src/utils/provider-retry.ts"],"names":[],"mappings":"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","sourcesContent":["import { abortableSleep, createAbortError } from \"./abort-signals.ts\";\n\nconst DEFAULT_MAX_RETRY_DELAY_MS = 60_000;\n\nexport interface ProviderRetryOptions {\n\tmaxRetries?: number;\n\tmaxRetryDelayMs?: number;\n\tsignal?: AbortSignal;\n}\n\nexport interface ProviderRetryDirective {\n\t/** Explicit provider override from headers or structured availability metadata. */\n\tshouldRetry?: boolean;\n\t/** Minimum provider-requested delay before another request. */\n\tretryAfterMs?: number;\n}\n\ntype ProviderHeaders = Headers | Record<string, string | string[] | undefined>;\n\ninterface ProviderError extends Error {\n\tstatus: number | undefined;\n\theaders: ProviderHeaders | undefined;\n\t/** Structured provider body retained by SDK errors, when available. */\n\terror?: unknown;\n}\n\nconst providerRetryDirectiveOverrides = new WeakMap<Error, ProviderRetryDirective>();\n\nfunction isProviderHeaders(value: unknown): value is ProviderHeaders | undefined {\n\treturn value === undefined || (typeof value === \"object\" && value !== null);\n}\n\nfunction getProviderHeader(headers: ProviderHeaders | undefined, name: string): string | undefined {\n\tif (!headers) return undefined;\n\tif (\"get\" in headers && typeof headers.get === \"function\") {\n\t\tconst value = headers.get(name);\n\t\treturn value === null ? undefined : value;\n\t}\n\tconst entry = Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase())?.[1];\n\treturn Array.isArray(entry) ? entry.join(\", \") : entry;\n}\n\nfunction isProviderError(error: unknown): error is ProviderError {\n\tif (!(error instanceof Error) || !(\"status\" in error) || !(\"headers\" in error)) return false;\n\treturn (error.status === undefined || typeof error.status === \"number\") && isProviderHeaders(error.headers);\n}\n\nfunction getExplicitShouldRetry(headers: ProviderHeaders | undefined): boolean | undefined {\n\tconst value = getProviderHeader(headers, \"x-should-retry\")?.trim().toLowerCase();\n\tif (value === \"true\") return true;\n\tif (value === \"false\") return false;\n\treturn undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction getStructuredAvailability(error: ProviderError): Record<string, unknown> | undefined {\n\tconst body = asRecord(error.error);\n\tif (!body) return undefined;\n\tconst direct = asRecord(body.availability);\n\tif (direct) return direct;\n\treturn asRecord(asRecord(body.error)?.availability);\n}\n\nfunction getStructuredShouldRetry(error: ProviderError): boolean | undefined {\n\tconst retryable = getStructuredAvailability(error)?.retryable;\n\treturn typeof retryable === \"boolean\" ? retryable : undefined;\n}\n\nfunction getStructuredRetryDelayMs(error: ProviderError): number | undefined {\n\tconst seconds = getStructuredAvailability(error)?.retry_after;\n\treturn typeof seconds === \"number\" && Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : undefined;\n}\n\nfunction getHeaderRetryDelayMs(error: ProviderError, nowMs = Date.now()): number | undefined {\n\tconst retryAfterMs = getProviderHeader(error.headers, \"retry-after-ms\");\n\tif (retryAfterMs !== null && retryAfterMs !== undefined) {\n\t\tconst value = Number.parseFloat(retryAfterMs);\n\t\tif (Number.isFinite(value)) return Math.max(0, value);\n\t}\n\n\tconst retryAfter = getProviderHeader(error.headers, \"retry-after\");\n\tif (retryAfter !== null && retryAfter !== undefined) {\n\t\tconst seconds = Number.parseFloat(retryAfter);\n\t\tconst delayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - nowMs : seconds * 1000;\n\t\tif (Number.isFinite(delayMs)) return Math.max(0, delayMs);\n\t}\n\treturn undefined;\n}\n\nfunction getServerRetryDelayMs(error: ProviderError): number | undefined {\n\tconst delays = [getHeaderRetryDelayMs(error), getStructuredRetryDelayMs(error)].filter(\n\t\t(delay): delay is number => delay !== undefined,\n\t);\n\treturn delays.length > 0 ? Math.max(...delays) : undefined;\n}\n\nfunction combineShouldRetry(...values: Array<boolean | undefined>): boolean | undefined {\n\tif (values.includes(false)) return false;\n\treturn values.includes(true) ? true : undefined;\n}\n\n/** Extract redacted semantic retry guidance without retaining raw provider headers. */\nexport function getProviderRetryDirective(error: unknown): ProviderRetryDirective | undefined {\n\tif (!(error instanceof Error)) return undefined;\n\tconst override = providerRetryDirectiveOverrides.get(error);\n\tif (override) return override;\n\tif (!isProviderError(error)) return undefined;\n\n\tconst shouldRetry = combineShouldRetry(getExplicitShouldRetry(error.headers), getStructuredShouldRetry(error));\n\tconst retryAfterMs = getServerRetryDelayMs(error);\n\tif (shouldRetry === undefined && retryAfterMs === undefined) return undefined;\n\treturn {\n\t\t...(shouldRetry !== undefined ? { shouldRetry } : {}),\n\t\t...(retryAfterMs !== undefined ? { retryAfterMs } : {}),\n\t};\n}\n\nfunction formatRetrySeconds(delayMs: number): string {\n\tconst seconds = delayMs / 1000;\n\treturn Number.isInteger(seconds) ? String(seconds) : String(Number(seconds.toFixed(3)));\n}\n\n/** Preserve retry guidance through string-only error/session boundaries. */\nexport function appendProviderRetryDirective(message: string, error: unknown): string {\n\tconst directive = getProviderRetryDirective(error);\n\tlet suffix: string | undefined;\n\tif (directive?.shouldRetry === false) {\n\t\tsuffix = \"Provider retry directive: do not retry.\";\n\t} else if (directive?.retryAfterMs !== undefined) {\n\t\tsuffix = `Provider retry directive: retry after ${formatRetrySeconds(directive.retryAfterMs)}s.`;\n\t} else if (directive?.shouldRetry === true) {\n\t\tsuffix = \"Provider retry directive: retry.\";\n\t}\n\tif (!suffix || message.includes(suffix)) return message;\n\treturn message.length > 0 ? `${message}\\n${suffix}` : suffix;\n}\n\n/** Mirrors the pinned OpenAI and Anthropic SDK retry policy. */\nfunction isRetryableProviderError(error: ProviderError): boolean {\n\tconst shouldRetry = combineShouldRetry(getExplicitShouldRetry(error.headers), getStructuredShouldRetry(error));\n\tif (shouldRetry !== undefined) return shouldRetry;\n\tif (error.status === undefined) return true;\n\treturn error.status === 408 || error.status === 409 || error.status === 429 || error.status >= 500;\n}\n\nfunction createRetryDelayExceededError(error: ProviderError, delayMs: number, maxDelayMs: number): Error {\n\tconst boundedError = new Error(\n\t\t`Server requested ${formatRetrySeconds(delayMs)}s retry delay (max: ${formatRetrySeconds(maxDelayMs)}s). ${error.message}`,\n\t\t{ cause: error },\n\t);\n\tproviderRetryDirectiveOverrides.set(boundedError, { shouldRetry: false, retryAfterMs: delayMs });\n\treturn boundedError;\n}\n\nfunction validateServerRetryDelayMs(\n\tdelayMs: number,\n\tmaxRetryDelayMs: number | undefined,\n\terror: ProviderError,\n): number {\n\tconst maxDelayMs = maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;\n\tif (maxDelayMs > 0 && delayMs > maxDelayMs) {\n\t\tthrow createRetryDelayExceededError(error, delayMs, maxDelayMs);\n\t}\n\treturn delayMs;\n}\n\nfunction getFallbackRetryDelayMs(retryIndex: number): number {\n\tconst exponentialDelay = Math.min(0.5 * 2 ** retryIndex, 8) * 1000;\n\treturn exponentialDelay * (1 - Math.random() * 0.25);\n}\n\n/**\n * Reproduce the retry behavior used by the OpenAI and Anthropic SDKs with an abortable backoff.\n * Call the SDK with `maxRetries: 0`; this helper is the sole provider-request retry owner.\n */\nexport async function retryProviderRequest<T>(\n\trequest: () => Promise<T>,\n\toptions: ProviderRetryOptions = {},\n): Promise<T> {\n\tconst maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 0));\n\tlet retriesRemaining = maxRetries;\n\n\tfor (;;) {\n\t\ttry {\n\t\t\treturn await request();\n\t\t} catch (error) {\n\t\t\tif (options.signal?.aborted) throw createAbortError();\n\t\t\tif (!isProviderError(error) || !isRetryableProviderError(error)) throw error;\n\n\t\t\tconst serverDelayMs = getServerRetryDelayMs(error);\n\t\t\tconst boundedServerDelayMs =\n\t\t\t\tserverDelayMs === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: validateServerRetryDelayMs(serverDelayMs, options.maxRetryDelayMs, error);\n\t\t\tif (retriesRemaining <= 0) throw error;\n\n\t\t\tconst retryIndex = maxRetries - retriesRemaining;\n\t\t\tretriesRemaining--;\n\t\t\tawait abortableSleep(boundedServerDelayMs ?? getFallbackRetryDelayMs(retryIndex), options.signal);\n\t\t}\n\t}\n}\n"]}
|