@yourgpt/llm-sdk 2.6.0-beta.0 → 2.6.0-beta.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/README.md +189 -0
- package/dist/adapters/index.d.mts +11 -13
- package/dist/adapters/index.d.ts +11 -13
- package/dist/adapters/index.js +610 -186
- package/dist/adapters/index.mjs +610 -186
- package/dist/audio-BBSwnjo8.d.mts +92 -0
- package/dist/audio-BBSwnjo8.d.ts +92 -0
- package/dist/{base-tNgbBaSo.d.mts → base-BICaQaRS.d.mts} +8 -3
- package/dist/{base-C58Dsr9p.d.ts → base-CpRPB8u8.d.ts} +8 -3
- package/dist/fallback/index.d.mts +4 -4
- package/dist/fallback/index.d.ts +4 -4
- package/dist/fallback/index.js +75 -39
- package/dist/fallback/index.mjs +75 -39
- package/dist/index.d.mts +18 -35
- package/dist/index.d.ts +18 -35
- package/dist/index.js +304 -88
- package/dist/index.mjs +302 -89
- package/dist/providers/anthropic/index.d.mts +3 -3
- package/dist/providers/anthropic/index.d.ts +3 -3
- package/dist/providers/anthropic/index.js +123 -7
- package/dist/providers/anthropic/index.mjs +123 -7
- package/dist/providers/azure/index.d.mts +3 -3
- package/dist/providers/azure/index.d.ts +3 -3
- package/dist/providers/azure/index.js +101 -4
- package/dist/providers/azure/index.mjs +101 -4
- package/dist/providers/fireworks/index.d.mts +3 -3
- package/dist/providers/fireworks/index.d.ts +3 -3
- package/dist/providers/fireworks/index.js +559 -178
- package/dist/providers/fireworks/index.mjs +559 -178
- package/dist/providers/google/index.d.mts +3 -3
- package/dist/providers/google/index.d.ts +3 -3
- package/dist/providers/google/index.js +559 -178
- package/dist/providers/google/index.mjs +559 -178
- package/dist/providers/ollama/index.d.mts +4 -4
- package/dist/providers/ollama/index.d.ts +4 -4
- package/dist/providers/ollama/index.js +87 -2
- package/dist/providers/ollama/index.mjs +87 -2
- package/dist/providers/openai/index.d.mts +25 -23
- package/dist/providers/openai/index.d.ts +25 -23
- package/dist/providers/openai/index.js +1397 -481
- package/dist/providers/openai/index.mjs +1396 -482
- package/dist/providers/openrouter/index.d.mts +3 -3
- package/dist/providers/openrouter/index.d.ts +3 -3
- package/dist/providers/openrouter/index.js +559 -178
- package/dist/providers/openrouter/index.mjs +559 -178
- package/dist/providers/togetherai/index.d.mts +3 -3
- package/dist/providers/togetherai/index.d.ts +3 -3
- package/dist/providers/togetherai/index.js +559 -178
- package/dist/providers/togetherai/index.mjs +559 -178
- package/dist/providers/xai/index.d.mts +3 -3
- package/dist/providers/xai/index.d.ts +3 -3
- package/dist/providers/xai/index.js +559 -178
- package/dist/providers/xai/index.mjs +559 -178
- package/dist/{types-B6dhnguR.d.mts → types-C3RgRbEC.d.mts} +11 -4
- package/dist/{types-CCxPmkmK.d.ts → types-DCFqkJAy.d.ts} +11 -4
- package/dist/{types-BQ31QIsA.d.ts → types-DHQEMFHA.d.mts} +3 -11
- package/dist/{types-BkQCSiIt.d.mts → types-Dg1Bcg1k.d.mts} +127 -3
- package/dist/{types-BkQCSiIt.d.ts → types-Dg1Bcg1k.d.ts} +127 -3
- package/dist/{types-BSSiJW2o.d.mts → types-Dikj3En4.d.ts} +3 -11
- package/dist/yourgpt/index.d.mts +1 -1
- package/dist/yourgpt/index.d.ts +1 -1
- package/docs/multimodal-and-audio.md +170 -0
- package/package.json +117 -49
- package/LICENSE +0 -21
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** Audio models are independent of chat models and chat streaming events. */
|
|
2
|
+
type SpeechFormat = "mp3" | "opus" | "aac" | "flac" | "wav" | "pcm";
|
|
3
|
+
interface AudioResponseMetadata {
|
|
4
|
+
provider: string;
|
|
5
|
+
modelId: string;
|
|
6
|
+
requestId?: string;
|
|
7
|
+
status?: number;
|
|
8
|
+
}
|
|
9
|
+
interface AudioWarning {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
interface SpeechOptions {
|
|
14
|
+
text: string;
|
|
15
|
+
voice?: string;
|
|
16
|
+
outputFormat?: SpeechFormat;
|
|
17
|
+
speed?: number;
|
|
18
|
+
instructions?: string;
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
21
|
+
}
|
|
22
|
+
interface GeneratedSpeech {
|
|
23
|
+
audio: {
|
|
24
|
+
uint8Array: Uint8Array;
|
|
25
|
+
readonly base64: string;
|
|
26
|
+
mediaType: string;
|
|
27
|
+
format: SpeechFormat;
|
|
28
|
+
};
|
|
29
|
+
response: AudioResponseMetadata;
|
|
30
|
+
warnings: AudioWarning[];
|
|
31
|
+
usage?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
interface SpeechModel {
|
|
34
|
+
readonly provider: string;
|
|
35
|
+
readonly modelId: string;
|
|
36
|
+
doGenerate(options: SpeechOptions): Promise<GeneratedSpeech>;
|
|
37
|
+
}
|
|
38
|
+
interface TranscriptionOptions {
|
|
39
|
+
/** Recorded file bytes, base64, or a Blob. URLs and raw PCM are not fetched/decoded. */
|
|
40
|
+
audio: Uint8Array | ArrayBuffer | Blob | string;
|
|
41
|
+
mediaType?: string;
|
|
42
|
+
filename?: string;
|
|
43
|
+
language?: string;
|
|
44
|
+
prompt?: string;
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
47
|
+
}
|
|
48
|
+
interface TranscriptSegment {
|
|
49
|
+
text: string;
|
|
50
|
+
start: number;
|
|
51
|
+
end: number;
|
|
52
|
+
speaker?: string;
|
|
53
|
+
}
|
|
54
|
+
interface TranscriptionResult {
|
|
55
|
+
text: string;
|
|
56
|
+
language?: string;
|
|
57
|
+
durationSeconds?: number;
|
|
58
|
+
segments?: TranscriptSegment[];
|
|
59
|
+
words?: Array<{
|
|
60
|
+
word: string;
|
|
61
|
+
start: number;
|
|
62
|
+
end: number;
|
|
63
|
+
}>;
|
|
64
|
+
response: AudioResponseMetadata;
|
|
65
|
+
warnings: AudioWarning[];
|
|
66
|
+
usage?: Record<string, unknown>;
|
|
67
|
+
/** Provider-supplied extras, including log probabilities when requested. */
|
|
68
|
+
providerMetadata?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
interface TranscriptionModel {
|
|
71
|
+
readonly provider: string;
|
|
72
|
+
readonly modelId: string;
|
|
73
|
+
doTranscribe(options: TranscriptionOptions): Promise<TranscriptionResult>;
|
|
74
|
+
}
|
|
75
|
+
declare const audioErrorMarker: unique symbol;
|
|
76
|
+
declare class AudioAPIError extends Error {
|
|
77
|
+
readonly code: "invalid_input" | "unsupported_option" | "provider_error" | "invalid_response" | "network_error";
|
|
78
|
+
readonly status?: number | undefined;
|
|
79
|
+
readonly requestId?: string | undefined;
|
|
80
|
+
readonly [audioErrorMarker] = true;
|
|
81
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
82
|
+
readonly name = "AudioAPIError";
|
|
83
|
+
constructor(message: string, code: "invalid_input" | "unsupported_option" | "provider_error" | "invalid_response" | "network_error", status?: number | undefined, requestId?: string | undefined);
|
|
84
|
+
}
|
|
85
|
+
declare function generateSpeech({ model, ...options }: SpeechOptions & {
|
|
86
|
+
model: SpeechModel;
|
|
87
|
+
}): Promise<GeneratedSpeech>;
|
|
88
|
+
declare function transcribe({ model, ...options }: TranscriptionOptions & {
|
|
89
|
+
model: TranscriptionModel;
|
|
90
|
+
}): Promise<TranscriptionResult>;
|
|
91
|
+
|
|
92
|
+
export { AudioAPIError as A, type GeneratedSpeech as G, type SpeechModel as S, type TranscriptionModel as T, type SpeechOptions as a, type TranscriptionOptions as b, type TranscriptionResult as c, type SpeechFormat as d, type TranscriptSegment as e, type AudioResponseMetadata as f, generateSpeech as g, type AudioWarning as h, transcribe as t };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** Audio models are independent of chat models and chat streaming events. */
|
|
2
|
+
type SpeechFormat = "mp3" | "opus" | "aac" | "flac" | "wav" | "pcm";
|
|
3
|
+
interface AudioResponseMetadata {
|
|
4
|
+
provider: string;
|
|
5
|
+
modelId: string;
|
|
6
|
+
requestId?: string;
|
|
7
|
+
status?: number;
|
|
8
|
+
}
|
|
9
|
+
interface AudioWarning {
|
|
10
|
+
code: string;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
interface SpeechOptions {
|
|
14
|
+
text: string;
|
|
15
|
+
voice?: string;
|
|
16
|
+
outputFormat?: SpeechFormat;
|
|
17
|
+
speed?: number;
|
|
18
|
+
instructions?: string;
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
21
|
+
}
|
|
22
|
+
interface GeneratedSpeech {
|
|
23
|
+
audio: {
|
|
24
|
+
uint8Array: Uint8Array;
|
|
25
|
+
readonly base64: string;
|
|
26
|
+
mediaType: string;
|
|
27
|
+
format: SpeechFormat;
|
|
28
|
+
};
|
|
29
|
+
response: AudioResponseMetadata;
|
|
30
|
+
warnings: AudioWarning[];
|
|
31
|
+
usage?: Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
interface SpeechModel {
|
|
34
|
+
readonly provider: string;
|
|
35
|
+
readonly modelId: string;
|
|
36
|
+
doGenerate(options: SpeechOptions): Promise<GeneratedSpeech>;
|
|
37
|
+
}
|
|
38
|
+
interface TranscriptionOptions {
|
|
39
|
+
/** Recorded file bytes, base64, or a Blob. URLs and raw PCM are not fetched/decoded. */
|
|
40
|
+
audio: Uint8Array | ArrayBuffer | Blob | string;
|
|
41
|
+
mediaType?: string;
|
|
42
|
+
filename?: string;
|
|
43
|
+
language?: string;
|
|
44
|
+
prompt?: string;
|
|
45
|
+
signal?: AbortSignal;
|
|
46
|
+
providerOptions?: Record<string, Record<string, unknown>>;
|
|
47
|
+
}
|
|
48
|
+
interface TranscriptSegment {
|
|
49
|
+
text: string;
|
|
50
|
+
start: number;
|
|
51
|
+
end: number;
|
|
52
|
+
speaker?: string;
|
|
53
|
+
}
|
|
54
|
+
interface TranscriptionResult {
|
|
55
|
+
text: string;
|
|
56
|
+
language?: string;
|
|
57
|
+
durationSeconds?: number;
|
|
58
|
+
segments?: TranscriptSegment[];
|
|
59
|
+
words?: Array<{
|
|
60
|
+
word: string;
|
|
61
|
+
start: number;
|
|
62
|
+
end: number;
|
|
63
|
+
}>;
|
|
64
|
+
response: AudioResponseMetadata;
|
|
65
|
+
warnings: AudioWarning[];
|
|
66
|
+
usage?: Record<string, unknown>;
|
|
67
|
+
/** Provider-supplied extras, including log probabilities when requested. */
|
|
68
|
+
providerMetadata?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
interface TranscriptionModel {
|
|
71
|
+
readonly provider: string;
|
|
72
|
+
readonly modelId: string;
|
|
73
|
+
doTranscribe(options: TranscriptionOptions): Promise<TranscriptionResult>;
|
|
74
|
+
}
|
|
75
|
+
declare const audioErrorMarker: unique symbol;
|
|
76
|
+
declare class AudioAPIError extends Error {
|
|
77
|
+
readonly code: "invalid_input" | "unsupported_option" | "provider_error" | "invalid_response" | "network_error";
|
|
78
|
+
readonly status?: number | undefined;
|
|
79
|
+
readonly requestId?: string | undefined;
|
|
80
|
+
readonly [audioErrorMarker] = true;
|
|
81
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
82
|
+
readonly name = "AudioAPIError";
|
|
83
|
+
constructor(message: string, code: "invalid_input" | "unsupported_option" | "provider_error" | "invalid_response" | "network_error", status?: number | undefined, requestId?: string | undefined);
|
|
84
|
+
}
|
|
85
|
+
declare function generateSpeech({ model, ...options }: SpeechOptions & {
|
|
86
|
+
model: SpeechModel;
|
|
87
|
+
}): Promise<GeneratedSpeech>;
|
|
88
|
+
declare function transcribe({ model, ...options }: TranscriptionOptions & {
|
|
89
|
+
model: TranscriptionModel;
|
|
90
|
+
}): Promise<TranscriptionResult>;
|
|
91
|
+
|
|
92
|
+
export { AudioAPIError as A, type GeneratedSpeech as G, type SpeechModel as S, type TranscriptionModel as T, type SpeechOptions as a, type TranscriptionOptions as b, type TranscriptionResult as c, type SpeechFormat as d, type TranscriptSegment as e, type AudioResponseMetadata as f, generateSpeech as g, type AudioWarning as h, transcribe as t };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { M as Message, A as ActionDefinition,
|
|
1
|
+
import { M as Message, A as ActionDefinition, e as ToolDefinition, O as OpenAITransportOptions, h as OpenAIReasoningEffort, R as ResponseFormat, W as WebSearchConfig, l as ProviderToolRuntimeOptions, i as StreamEvent, P as ProviderMetadata, V as TokenUsage, $ as LLMConfig, c as ToolModelOutput, af as MessageAttachment } from './types-Dg1Bcg1k.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Request-level LLM configuration overrides
|
|
5
5
|
*/
|
|
6
6
|
interface RequestLLMConfig {
|
|
7
|
+
openai?: OpenAITransportOptions;
|
|
7
8
|
model?: string;
|
|
9
|
+
reasoningEffort?: OpenAIReasoningEffort;
|
|
8
10
|
temperature?: number;
|
|
9
11
|
maxTokens?: number;
|
|
10
12
|
responseFormat?: ResponseFormat;
|
|
@@ -45,6 +47,7 @@ interface ChatCompletionRequest {
|
|
|
45
47
|
* Non-streaming completion result
|
|
46
48
|
*/
|
|
47
49
|
interface CompletionResult {
|
|
50
|
+
providerMetadata?: ProviderMetadata;
|
|
48
51
|
/** Text content */
|
|
49
52
|
content: string;
|
|
50
53
|
/** Tool calls */
|
|
@@ -207,7 +210,7 @@ type AnthropicToolUseBlock = {
|
|
|
207
210
|
type AnthropicToolResultBlock = {
|
|
208
211
|
type: "tool_result";
|
|
209
212
|
tool_use_id: string;
|
|
210
|
-
content: string
|
|
213
|
+
content: string | Array<Record<string, unknown>>;
|
|
211
214
|
};
|
|
212
215
|
type AnthropicMessageContent = string | Array<AnthropicContentBlock | AnthropicToolUseBlock | AnthropicToolResultBlock>;
|
|
213
216
|
/**
|
|
@@ -236,6 +239,7 @@ type OpenAIMessage = {
|
|
|
236
239
|
content: string | OpenAIContentBlock[];
|
|
237
240
|
} | {
|
|
238
241
|
role: "assistant";
|
|
242
|
+
providerMetadata?: ProviderMetadata;
|
|
239
243
|
content: string | null;
|
|
240
244
|
tool_calls?: Array<{
|
|
241
245
|
id: string;
|
|
@@ -249,11 +253,12 @@ type OpenAIMessage = {
|
|
|
249
253
|
role: "tool";
|
|
250
254
|
content: string;
|
|
251
255
|
tool_call_id: string;
|
|
256
|
+
modelOutput?: ToolModelOutput;
|
|
252
257
|
};
|
|
253
258
|
/**
|
|
254
259
|
* Format messages for OpenAI with full tool support
|
|
255
260
|
* Handles: text, images, tool_calls, and tool results
|
|
256
261
|
*/
|
|
257
|
-
declare function formatMessagesForOpenAI(messages: Message[], systemPrompt?: string): OpenAIMessage[];
|
|
262
|
+
declare function formatMessagesForOpenAI(messages: Message[], systemPrompt?: string, preserveProviderMetadata?: boolean): OpenAIMessage[];
|
|
258
263
|
|
|
259
264
|
export { type AdapterFactory as A, type ChatCompletionRequest as C, type LLMAdapter as L, type OpenAIContentBlock as O, type CompletionResult as a, formatTools as b, formatMessagesForAnthropic as c, formatMessagesForOpenAI as d, messageToOpenAIContent as e, formatMessages as f, hasMediaAttachments as g, hasImageAttachments as h, attachmentToAnthropicImage as i, attachmentToAnthropicDocument as j, attachmentToOpenAIImage as k, type AnthropicContentBlock as l, messageToAnthropicContent as m };
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { M as Message, A as ActionDefinition,
|
|
1
|
+
import { M as Message, A as ActionDefinition, e as ToolDefinition, O as OpenAITransportOptions, h as OpenAIReasoningEffort, R as ResponseFormat, W as WebSearchConfig, l as ProviderToolRuntimeOptions, i as StreamEvent, P as ProviderMetadata, V as TokenUsage, $ as LLMConfig, c as ToolModelOutput, af as MessageAttachment } from './types-Dg1Bcg1k.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Request-level LLM configuration overrides
|
|
5
5
|
*/
|
|
6
6
|
interface RequestLLMConfig {
|
|
7
|
+
openai?: OpenAITransportOptions;
|
|
7
8
|
model?: string;
|
|
9
|
+
reasoningEffort?: OpenAIReasoningEffort;
|
|
8
10
|
temperature?: number;
|
|
9
11
|
maxTokens?: number;
|
|
10
12
|
responseFormat?: ResponseFormat;
|
|
@@ -45,6 +47,7 @@ interface ChatCompletionRequest {
|
|
|
45
47
|
* Non-streaming completion result
|
|
46
48
|
*/
|
|
47
49
|
interface CompletionResult {
|
|
50
|
+
providerMetadata?: ProviderMetadata;
|
|
48
51
|
/** Text content */
|
|
49
52
|
content: string;
|
|
50
53
|
/** Tool calls */
|
|
@@ -207,7 +210,7 @@ type AnthropicToolUseBlock = {
|
|
|
207
210
|
type AnthropicToolResultBlock = {
|
|
208
211
|
type: "tool_result";
|
|
209
212
|
tool_use_id: string;
|
|
210
|
-
content: string
|
|
213
|
+
content: string | Array<Record<string, unknown>>;
|
|
211
214
|
};
|
|
212
215
|
type AnthropicMessageContent = string | Array<AnthropicContentBlock | AnthropicToolUseBlock | AnthropicToolResultBlock>;
|
|
213
216
|
/**
|
|
@@ -236,6 +239,7 @@ type OpenAIMessage = {
|
|
|
236
239
|
content: string | OpenAIContentBlock[];
|
|
237
240
|
} | {
|
|
238
241
|
role: "assistant";
|
|
242
|
+
providerMetadata?: ProviderMetadata;
|
|
239
243
|
content: string | null;
|
|
240
244
|
tool_calls?: Array<{
|
|
241
245
|
id: string;
|
|
@@ -249,11 +253,12 @@ type OpenAIMessage = {
|
|
|
249
253
|
role: "tool";
|
|
250
254
|
content: string;
|
|
251
255
|
tool_call_id: string;
|
|
256
|
+
modelOutput?: ToolModelOutput;
|
|
252
257
|
};
|
|
253
258
|
/**
|
|
254
259
|
* Format messages for OpenAI with full tool support
|
|
255
260
|
* Handles: text, images, tool_calls, and tool results
|
|
256
261
|
*/
|
|
257
|
-
declare function formatMessagesForOpenAI(messages: Message[], systemPrompt?: string): OpenAIMessage[];
|
|
262
|
+
declare function formatMessagesForOpenAI(messages: Message[], systemPrompt?: string, preserveProviderMetadata?: boolean): OpenAIMessage[];
|
|
258
263
|
|
|
259
264
|
export { type AdapterFactory as A, type ChatCompletionRequest as C, type LLMAdapter as L, type OpenAIContentBlock as O, type CompletionResult as a, formatTools as b, formatMessagesForAnthropic as c, formatMessagesForOpenAI as d, messageToOpenAIContent as e, formatMessages as f, hasMediaAttachments as g, hasImageAttachments as h, attachmentToAnthropicImage as i, attachmentToAnthropicDocument as j, attachmentToOpenAIImage as k, type AnthropicContentBlock as l, messageToAnthropicContent as m };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LLMAdapter } from '../base-
|
|
2
|
-
import { F as FallbackChainConfig, c as FallbackFailure, R as RoutingStore } from '../types-
|
|
3
|
-
export { d as FallbackInfo, b as RetryBackoff, e as RetryInfo, a as RoutingStrategy } from '../types-
|
|
4
|
-
import '../types-
|
|
1
|
+
import { L as LLMAdapter } from '../base-BICaQaRS.mjs';
|
|
2
|
+
import { F as FallbackChainConfig, c as FallbackFailure, R as RoutingStore } from '../types-C3RgRbEC.mjs';
|
|
3
|
+
export { d as FallbackInfo, b as RetryBackoff, e as RetryInfo, a as RoutingStrategy } from '../types-C3RgRbEC.mjs';
|
|
4
|
+
import '../types-Dg1Bcg1k.mjs';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/fallback/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { L as LLMAdapter } from '../base-
|
|
2
|
-
import { F as FallbackChainConfig, c as FallbackFailure, R as RoutingStore } from '../types-
|
|
3
|
-
export { d as FallbackInfo, b as RetryBackoff, e as RetryInfo, a as RoutingStrategy } from '../types-
|
|
4
|
-
import '../types-
|
|
1
|
+
import { L as LLMAdapter } from '../base-CpRPB8u8.js';
|
|
2
|
+
import { F as FallbackChainConfig, c as FallbackFailure, R as RoutingStore } from '../types-DCFqkJAy.js';
|
|
3
|
+
export { d as FallbackInfo, b as RetryBackoff, e as RetryInfo, a as RoutingStrategy } from '../types-DCFqkJAy.js';
|
|
4
|
+
import '../types-Dg1Bcg1k.js';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
|
7
7
|
/**
|
package/dist/fallback/index.js
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/core/provider-error.ts
|
|
4
|
+
function errorFromEvent(event) {
|
|
5
|
+
if (event.cause instanceof Error) return event.cause;
|
|
6
|
+
return Object.assign(new Error(event.message), {
|
|
7
|
+
status: event.status,
|
|
8
|
+
code: event.providerCode ?? event.code,
|
|
9
|
+
param: event.param,
|
|
10
|
+
request_id: event.requestId
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function throwIfAborted(signal) {
|
|
14
|
+
if (!signal?.aborted) return;
|
|
15
|
+
const error = new Error("The operation was aborted");
|
|
16
|
+
error.name = "AbortError";
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
function isAbortError(error) {
|
|
20
|
+
if (!(error instanceof Error)) return false;
|
|
21
|
+
return error.name === "AbortError" || error.constructor.name === "APIUserAbortError" || /^(aborted|the operation was aborted|the user aborted a request)/i.test(
|
|
22
|
+
error.message
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
3
26
|
// src/fallback/errors.ts
|
|
4
27
|
var FallbackExhaustedError = class extends Error {
|
|
5
28
|
constructor(failures) {
|
|
@@ -74,8 +97,24 @@ function calcDelay(base, attempt, backoff) {
|
|
|
74
97
|
if (backoff === "fixed") return base;
|
|
75
98
|
return base * Math.pow(2, attempt - 1);
|
|
76
99
|
}
|
|
77
|
-
function sleep(ms) {
|
|
78
|
-
|
|
100
|
+
function sleep(ms, signal) {
|
|
101
|
+
throwIfAborted(signal);
|
|
102
|
+
return new Promise((resolve, reject) => {
|
|
103
|
+
const onAbort = () => {
|
|
104
|
+
clearTimeout(timer);
|
|
105
|
+
signal?.removeEventListener("abort", onAbort);
|
|
106
|
+
try {
|
|
107
|
+
throwIfAborted(signal);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
reject(error);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const timer = setTimeout(() => {
|
|
113
|
+
signal?.removeEventListener("abort", onAbort);
|
|
114
|
+
resolve();
|
|
115
|
+
}, ms);
|
|
116
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
117
|
+
});
|
|
79
118
|
}
|
|
80
119
|
var FallbackChain = class {
|
|
81
120
|
constructor(config) {
|
|
@@ -91,7 +130,8 @@ var FallbackChain = class {
|
|
|
91
130
|
retryBackoff: config.retryBackoff ?? "exponential",
|
|
92
131
|
onFallback: config.onFallback,
|
|
93
132
|
onRetry: config.onRetry,
|
|
94
|
-
retryableErrors: config.retryableErrors
|
|
133
|
+
retryableErrors: config.retryableErrors,
|
|
134
|
+
fallbackErrors: config.fallbackErrors
|
|
95
135
|
};
|
|
96
136
|
}
|
|
97
137
|
get provider() {
|
|
@@ -111,8 +151,12 @@ var FallbackChain = class {
|
|
|
111
151
|
await this._config.store.set(ROUND_ROBIN_KEY, next);
|
|
112
152
|
}
|
|
113
153
|
_isRetryable(error) {
|
|
154
|
+
if (isAbortError(error)) return false;
|
|
114
155
|
return this._config.retryableErrors ? this._config.retryableErrors(error) : defaultIsRetryable(error);
|
|
115
156
|
}
|
|
157
|
+
_canFallback(error) {
|
|
158
|
+
return !isAbortError(error) && (this._isRetryable(error) || this._config.fallbackErrors?.(error) === true);
|
|
159
|
+
}
|
|
116
160
|
/**
|
|
117
161
|
* Try streaming from a single adapter, with per-model retries.
|
|
118
162
|
*
|
|
@@ -125,65 +169,52 @@ var FallbackChain = class {
|
|
|
125
169
|
*/
|
|
126
170
|
async *_streamWithRetries(adapter, request, out) {
|
|
127
171
|
const { retries, retryDelay, retryBackoff, onRetry } = this._config;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
let failureError = null;
|
|
172
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
173
|
+
throwIfAborted(request.signal);
|
|
174
|
+
out.retriesAttempted = attempt;
|
|
132
175
|
try {
|
|
133
176
|
for await (const chunk of adapter.stream(request)) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const msg = chunk.message ?? "Unknown error";
|
|
137
|
-
failureError = new Error(msg);
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
yield chunk;
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
177
|
+
throwIfAborted(request.signal);
|
|
178
|
+
if (chunk.type === "error") throw errorFromEvent(chunk);
|
|
143
179
|
if (chunk.type === "message:start") continue;
|
|
144
|
-
contentStarted = true;
|
|
180
|
+
out.contentStarted = true;
|
|
145
181
|
yield chunk;
|
|
146
182
|
}
|
|
183
|
+
throwIfAborted(request.signal);
|
|
184
|
+
return;
|
|
147
185
|
} catch (error) {
|
|
148
|
-
|
|
149
|
-
if (!this._isRetryable(error)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (!this._isRetryable(failureError)) throw failureError;
|
|
154
|
-
out.retriesAttempted = attempt - 1;
|
|
155
|
-
if (attempt < maxAttempts) {
|
|
156
|
-
const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
|
|
157
|
-
const retryInfo = {
|
|
186
|
+
throwIfAborted(request.signal);
|
|
187
|
+
if (out.contentStarted || !this._isRetryable(error) || attempt === retries)
|
|
188
|
+
throw error;
|
|
189
|
+
const delayMs = calcDelay(retryDelay, attempt + 1, retryBackoff);
|
|
190
|
+
onRetry?.({
|
|
158
191
|
model: adapter.model,
|
|
159
192
|
provider: adapter.provider,
|
|
160
|
-
error:
|
|
161
|
-
retryAttempt: attempt,
|
|
193
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
194
|
+
retryAttempt: attempt + 1,
|
|
162
195
|
maxRetries: retries,
|
|
163
196
|
delayMs
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
await sleep(delayMs);
|
|
167
|
-
continue;
|
|
197
|
+
});
|
|
198
|
+
await sleep(delayMs, request.signal);
|
|
168
199
|
}
|
|
169
|
-
out.retriesAttempted = retries;
|
|
170
|
-
throw failureError;
|
|
171
200
|
}
|
|
172
201
|
}
|
|
173
202
|
async *stream(request) {
|
|
174
203
|
const { models, onFallback } = this._config;
|
|
204
|
+
throwIfAborted(request.signal);
|
|
175
205
|
const startIndex = await this._startIndex();
|
|
176
206
|
const failures = [];
|
|
177
207
|
for (let i = 0; i < models.length; i++) {
|
|
178
208
|
const index = (startIndex + i) % models.length;
|
|
179
209
|
const adapter = models[index];
|
|
180
|
-
const out = { retriesAttempted: 0 };
|
|
210
|
+
const out = { retriesAttempted: 0, contentStarted: false };
|
|
181
211
|
try {
|
|
182
212
|
yield* this._streamWithRetries(adapter, request, out);
|
|
183
213
|
await this._advanceIndex(index);
|
|
184
214
|
return;
|
|
185
215
|
} catch (error) {
|
|
186
|
-
|
|
216
|
+
throwIfAborted(request.signal);
|
|
217
|
+
if (out.contentStarted || !this._canFallback(error)) throw error;
|
|
187
218
|
const failure = {
|
|
188
219
|
model: adapter.model,
|
|
189
220
|
provider: adapter.provider,
|
|
@@ -208,6 +239,7 @@ var FallbackChain = class {
|
|
|
208
239
|
}
|
|
209
240
|
async complete(request) {
|
|
210
241
|
const { models, onFallback, retries, retryDelay, retryBackoff, onRetry } = this._config;
|
|
242
|
+
throwIfAborted(request.signal);
|
|
211
243
|
const startIndex = await this._startIndex();
|
|
212
244
|
const failures = [];
|
|
213
245
|
for (let i = 0; i < models.length; i++) {
|
|
@@ -229,14 +261,18 @@ var FallbackChain = class {
|
|
|
229
261
|
let lastError = null;
|
|
230
262
|
let retriesAttempted = 0;
|
|
231
263
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
264
|
+
throwIfAborted(request.signal);
|
|
232
265
|
try {
|
|
233
266
|
const result = await adapter.complete(request);
|
|
267
|
+
throwIfAborted(request.signal);
|
|
234
268
|
await this._advanceIndex(index);
|
|
235
269
|
return result;
|
|
236
270
|
} catch (error) {
|
|
237
|
-
|
|
271
|
+
throwIfAborted(request.signal);
|
|
272
|
+
if (!this._canFallback(error)) throw error;
|
|
238
273
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
239
274
|
retriesAttempted = attempt - 1;
|
|
275
|
+
if (!this._isRetryable(error)) break;
|
|
240
276
|
if (attempt < maxAttempts) {
|
|
241
277
|
const delayMs = calcDelay(retryDelay, attempt, retryBackoff);
|
|
242
278
|
onRetry?.({
|
|
@@ -247,7 +283,7 @@ var FallbackChain = class {
|
|
|
247
283
|
maxRetries: retries,
|
|
248
284
|
delayMs
|
|
249
285
|
});
|
|
250
|
-
await sleep(delayMs);
|
|
286
|
+
await sleep(delayMs, request.signal);
|
|
251
287
|
}
|
|
252
288
|
}
|
|
253
289
|
}
|