






















@@ -141,6 +141,20 @@ function shouldRethrowAbort(err: unknown): boolean {
141141return isFallbackAbortError(err) && !isTimeoutError(err);
142142}
143143144+function isTerminalAbort(signal: AbortSignal | undefined): boolean {
145+if (!signal?.aborted) {
146+return false;
147+}
148+const reason = signal.reason;
149+if (!(reason instanceof Error)) {
150+return false;
151+}
152+if (reason.name === "TimeoutError") {
153+return true;
154+}
155+return reason.name === "ClientDisconnectError";
156+}
157+144158function createModelCandidateCollector(allowlist: Set<string> | null | undefined): {
145159candidates: ModelCandidate[];
146160addExplicitCandidate: (candidate: ModelCandidate) => void;
@@ -245,6 +259,7 @@ async function runFallbackCandidate<T>(params: {
245259model: string;
246260options?: ModelFallbackRunOptions;
247261attribution?: FailoverAttribution;
262+abortSignal?: AbortSignal;
248263}): Promise<{ ok: true; result: T } | { ok: false; error: unknown }> {
249264try {
250265const result = params.options
@@ -261,6 +276,9 @@ async function runFallbackCandidate<T>(params: {
261276if (isNonProviderRuntimeCoordinationError(err)) {
262277throw err;
263278}
279+if (isTerminalAbort(params.abortSignal)) {
280+throw err;
281+}
264282// Normalize abort-wrapped rate-limit errors (e.g. Google Vertex RESOURCE_EXHAUSTED)
265283// so they become FailoverErrors and continue the fallback loop instead of aborting.
266284const normalizedFailover = coerceToFailoverError(err, {
@@ -286,13 +304,15 @@ async function runFallbackAttempt<T>(params: {
286304attempt: number;
287305total: number;
288306attribution?: FailoverAttribution;
307+abortSignal?: AbortSignal;
289308}): Promise<{ success: ModelFallbackRunResult<T> } | { error: unknown }> {
290309const runResult = await runFallbackCandidate({
291310run: params.run,
292311provider: params.provider,
293312model: params.model,
294313options: params.options,
295314attribution: params.attribution,
315+abortSignal: params.abortSignal,
296316});
297317if (runResult.ok) {
298318const classification = await params.classifyResult?.({
@@ -308,6 +328,9 @@ async function runFallbackAttempt<T>(params: {
308328attribution: params.attribution,
309329});
310330if (classifiedError) {
331+if (isTerminalAbort(params.abortSignal)) {
332+throw classifiedError;
333+}
311334return { error: classifiedError };
312335}
313336return {
@@ -1059,6 +1082,7 @@ export async function runWithModelFallback<T>(
10591082onFallbackStep?: ModelFallbackStepHandler;
10601083classifyResult?: ModelFallbackResultClassifier<T>;
10611084skipAuthProfileRuntime?: boolean;
1085+abortSignal?: AbortSignal;
10621086} & ModelManifestNormalizationContext,
10631087): Promise<ModelFallbackRunResult<T>> {
10641088const candidates = resolveFallbackCandidates({
@@ -1301,6 +1325,7 @@ export async function runWithModelFallback<T>(
13011325attempt: i + 1,
13021326total: candidates.length,
13031327attribution: { sessionId: params.sessionId, lane: params.lane },
1328+abortSignal: params.abortSignal,
13041329});
13051330if ("success" in attemptRun) {
13061331if (i > 0 || attempts.length > 0 || attemptedDuringCooldown) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。