@agnt-sdk/studio 0.0.34 → 0.0.36
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/BaseExecutor.d.ts +4 -1
- package/dist/BaseExecutor.d.ts.map +1 -1
- package/dist/BaseExecutor.js +18 -1
- package/dist/BaseExecutor.js.map +1 -1
- package/dist/__tests__/_streamMocks.d.ts +35 -0
- package/dist/__tests__/_streamMocks.d.ts.map +1 -0
- package/dist/__tests__/_streamMocks.js +102 -0
- package/dist/__tests__/_streamMocks.js.map +1 -0
- package/dist/executorFactory.d.ts +9 -1
- package/dist/executorFactory.d.ts.map +1 -1
- package/dist/executorFactory.js +28 -8
- package/dist/executorFactory.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +25 -7
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/deepseek.d.ts +7 -18
- package/dist/providers/deepseek.d.ts.map +1 -1
- package/dist/providers/deepseek.js +7 -197
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +33 -6
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +29 -8
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openaiCompatible.d.ts +47 -0
- package/dist/providers/openaiCompatible.d.ts.map +1 -0
- package/dist/providers/openaiCompatible.js +241 -0
- package/dist/providers/openaiCompatible.js.map +1 -0
- package/dist/providers/streaming.d.ts +109 -0
- package/dist/providers/streaming.d.ts.map +1 -0
- package/dist/providers/streaming.js +226 -0
- package/dist/providers/streaming.js.map +1 -0
- package/dist/types.d.ts +15 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAICompatibleExecutor — shared adapter for OpenAI-compatible providers
|
|
3
|
+
*
|
|
4
|
+
* One adapter for every provider that speaks the OpenAI Chat Completions wire
|
|
5
|
+
* format: Together AI (Kimi / Qwen), Fireworks, DeepInfra, DeepSeek, and any
|
|
6
|
+
* future open-model host. Per-provider differences — base URL, credentials,
|
|
7
|
+
* model IDs, pricing, cache behavior — live in CONFIG, never in code:
|
|
8
|
+
*
|
|
9
|
+
* - baseURL: resolved from OPENAI_COMPATIBLE_BASE_URLS[provider], overridable
|
|
10
|
+
* by credentials[provider].baseURL or model metadata.baseURL.
|
|
11
|
+
* - apiKey: credentials[provider].apiKey (via the existing secret manager;
|
|
12
|
+
* never stored in manifest/config rows).
|
|
13
|
+
* - model: manifest.spec.models[].model.
|
|
14
|
+
* - params: manifest.spec.models[].metadata (temperature, top_p, …).
|
|
15
|
+
*
|
|
16
|
+
* Adding a new OpenAI-compatible provider is therefore a config + credentials
|
|
17
|
+
* change (new AiModel row + creds entry), with no new adapter code required —
|
|
18
|
+
* unless it needs a base URL we don't know, which is a one-line registry entry.
|
|
19
|
+
*
|
|
20
|
+
* CACHING: these providers do AUTOMATIC (best-effort) prefix caching — the
|
|
21
|
+
* provider caches transparently, there is no billed cache write, and cached
|
|
22
|
+
* reads are reported back in usage.prompt_tokens_details.cached_tokens. We map
|
|
23
|
+
* that to cache_read_input_tokens and leave cache_creation_input_tokens at 0
|
|
24
|
+
* (there is no write concept here; the backend renders it as "—" / null based
|
|
25
|
+
* on the model's cacheMode). We never send Anthropic-style cache_control blocks
|
|
26
|
+
* — they are not part of the OpenAI wire format and must not leak through.
|
|
27
|
+
*/
|
|
28
|
+
import OpenAI from 'openai';
|
|
29
|
+
import BaseExecutor from '../BaseExecutor.js';
|
|
30
|
+
import { streamWithRetry, consumeOpenAIStream, STREAM_ABSOLUTE_BACKSTOP_MS } from './streaming.js';
|
|
31
|
+
/** Known OpenAI-compatible provider base URLs. A provider not listed here is
|
|
32
|
+
* still usable by supplying baseURL via credentials or model metadata. */
|
|
33
|
+
export const OPENAI_COMPATIBLE_BASE_URLS = {
|
|
34
|
+
together: 'https://api.together.ai/v1',
|
|
35
|
+
fireworks: 'https://api.fireworks.ai/inference/v1',
|
|
36
|
+
deepinfra: 'https://api.deepinfra.com/v1/openai',
|
|
37
|
+
deepseek: 'https://api.deepseek.com/v1',
|
|
38
|
+
};
|
|
39
|
+
/** Providers routed through this adapter. Keep in sync with executorFactory. */
|
|
40
|
+
export const OPENAI_COMPATIBLE_PROVIDERS = new Set(Object.keys(OPENAI_COMPATIBLE_BASE_URLS));
|
|
41
|
+
export default class OpenAICompatibleExecutor extends BaseExecutor {
|
|
42
|
+
client;
|
|
43
|
+
providerName;
|
|
44
|
+
constructor(config) {
|
|
45
|
+
super(config);
|
|
46
|
+
// this.provider is set by BaseExecutor from the selected model config.
|
|
47
|
+
this.providerName = (this.provider || '').toLowerCase();
|
|
48
|
+
// Credentials are keyed by provider name. Real provider strings are
|
|
49
|
+
// lowercase ('together', 'deepseek'), but tolerate the original casing too.
|
|
50
|
+
const credMap = this.credentials;
|
|
51
|
+
const creds = credMap[this.provider] ?? credMap[this.providerName];
|
|
52
|
+
if (!creds) {
|
|
53
|
+
throw new Error(`[OpenAICompatibleExecutor] credentials.${this.providerName} is required`);
|
|
54
|
+
}
|
|
55
|
+
if (!creds.apiKey) {
|
|
56
|
+
throw new Error(`[OpenAICompatibleExecutor] credentials.${this.providerName}.apiKey is required`);
|
|
57
|
+
}
|
|
58
|
+
// baseURL resolution order: creds override → model metadata → registry.
|
|
59
|
+
const metadata = (this.primaryModelConfig.metadata || {});
|
|
60
|
+
const baseURL = creds.baseURL ||
|
|
61
|
+
metadata.baseURL ||
|
|
62
|
+
OPENAI_COMPATIBLE_BASE_URLS[this.providerName];
|
|
63
|
+
if (!baseURL) {
|
|
64
|
+
throw new Error(`[OpenAICompatibleExecutor] no baseURL for provider "${this.providerName}" — ` +
|
|
65
|
+
`add one to OPENAI_COMPATIBLE_BASE_URLS, credentials.${this.providerName}.baseURL, or model metadata.baseURL`);
|
|
66
|
+
}
|
|
67
|
+
// Initialize OpenAI-compatible client. invoke() STREAMS and bounds the
|
|
68
|
+
// response with an inter-chunk IDLE timeout (see streaming.ts), so a
|
|
69
|
+
// long-but-progressing turn — exactly Kimi doing multi-tool agentic work —
|
|
70
|
+
// never races a total-completion timeout. The client `timeout` here is only
|
|
71
|
+
// the SDK's own absolute request cap; set it to the streaming backstop and
|
|
72
|
+
// let the idle timeout be the operative ceiling. maxRetries matches the
|
|
73
|
+
// other streamed adapters.
|
|
74
|
+
this.client = new OpenAI({
|
|
75
|
+
apiKey: creds.apiKey,
|
|
76
|
+
baseURL,
|
|
77
|
+
maxRetries: 3,
|
|
78
|
+
timeout: STREAM_ABSOLUTE_BACKSTOP_MS,
|
|
79
|
+
dangerouslyAllowBrowser: creds.dangerouslyAllowBrowser,
|
|
80
|
+
});
|
|
81
|
+
this.log(`[OpenAICompatibleExecutor] Initialized ${this.providerName} @ ${baseURL} with model: ${this.model}`);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Invoke the OpenAI-compatible API.
|
|
85
|
+
* Returns: { message: { role, content, tool_calls }, usage: {...disjoint buckets} }
|
|
86
|
+
*/
|
|
87
|
+
async invoke(messages, options = {}) {
|
|
88
|
+
const params = {
|
|
89
|
+
model: this.model,
|
|
90
|
+
messages: this.#formatMessages(messages),
|
|
91
|
+
};
|
|
92
|
+
// Pass through provider-specific params from model config (temperature, top_p, …).
|
|
93
|
+
Object.assign(params, this.#extractProviderParams());
|
|
94
|
+
if (options.tools && options.tools.length > 0) {
|
|
95
|
+
params.tools = options.tools.map(t => this.#formatTool(t));
|
|
96
|
+
// Explicit parallel tool calls — OpenAI-compatible default; set so it
|
|
97
|
+
// can't silently regress and matches parallel behavior across providers.
|
|
98
|
+
params.parallel_tool_calls = true;
|
|
99
|
+
}
|
|
100
|
+
if (options.tool_choice && options.tool_choice !== 'auto') {
|
|
101
|
+
params.tool_choice = this.#formatToolChoice(options.tool_choice);
|
|
102
|
+
}
|
|
103
|
+
this.log(`[OpenAICompatibleExecutor:${this.providerName}] Invoking:`, {
|
|
104
|
+
model: params.model,
|
|
105
|
+
temperature: params.temperature,
|
|
106
|
+
top_p: params.top_p,
|
|
107
|
+
tools: params.tools?.length || 0,
|
|
108
|
+
});
|
|
109
|
+
// STREAMED: consumeOpenAIStream reassembles content + tool_call arg deltas
|
|
110
|
+
// back into the exact non-streamed completion shape, so the extraction below
|
|
111
|
+
// is unchanged. Each chunk bumps the idle timer; a transient failure retries
|
|
112
|
+
// the whole prompt. stream_options.include_usage rides usage on the final
|
|
113
|
+
// chunk (guarded below — not all OpenAI-compatible hosts honor it).
|
|
114
|
+
const response = await streamWithRetry(async (guard) => {
|
|
115
|
+
const stream = await this.client.chat.completions.create({ ...params, stream: true, stream_options: { include_usage: true } }, { signal: guard.signal });
|
|
116
|
+
return await consumeOpenAIStream(stream, () => guard.bump());
|
|
117
|
+
}, {
|
|
118
|
+
externalSignal: options.signal,
|
|
119
|
+
isRetryable: (err) => this.isRetryableError(err),
|
|
120
|
+
log: (m) => this.log(m),
|
|
121
|
+
});
|
|
122
|
+
const choice = response.choices[0];
|
|
123
|
+
const message = choice.message;
|
|
124
|
+
// Automatic-cache providers report cached prefix tokens as a SUBSET of
|
|
125
|
+
// prompt_tokens (same convention as OpenAI direct). We subtract them out so
|
|
126
|
+
// input_tokens is the UNCACHED count and the four usage buckets stay
|
|
127
|
+
// disjoint across providers — otherwise cached reads get billed twice (once
|
|
128
|
+
// as input, once as read). cache_creation is 0: these providers have no
|
|
129
|
+
// billed write concept.
|
|
130
|
+
//
|
|
131
|
+
// Field location is NOT consistent across OpenAI-compatible hosts. Read all
|
|
132
|
+
// known spellings so a cache hit is never silently missed (a missed field
|
|
133
|
+
// reads as 0% hit rate → ~5x cost on our cache-heavy workload, and fails
|
|
134
|
+
// silently — the spec's highest-risk case):
|
|
135
|
+
// - OpenAI direct / Together dedicated-inference: nested
|
|
136
|
+
// prompt_tokens_details.cached_tokens
|
|
137
|
+
// - Together OpenAI-compat surface: top-level cached_tokens
|
|
138
|
+
// - DeepSeek: prompt_cache_hit_tokens (with prompt_cache_miss_tokens)
|
|
139
|
+
// All three are a SUBSET of prompt_tokens, so subtracting keeps input
|
|
140
|
+
// uncached. NOTE: prompt_tokens-is-cache-inclusive must be confirmed with a
|
|
141
|
+
// live Together call; if a host reports cached ADDITIVELY, this subtraction
|
|
142
|
+
// under-counts input and needs a per-host flag.
|
|
143
|
+
const usageTyped = response.usage;
|
|
144
|
+
const cachedTokens = usageTyped?.prompt_tokens_details?.cached_tokens ??
|
|
145
|
+
usageTyped?.cached_tokens ??
|
|
146
|
+
usageTyped?.prompt_cache_hit_tokens ??
|
|
147
|
+
0;
|
|
148
|
+
// Streamed usage rides the final include_usage chunk. Real OpenAI/Together
|
|
149
|
+
// send it, but guard so a host that omits it yields 0s instead of a crash
|
|
150
|
+
// on response.usage!. If a host silently drops usage, cost → 0 and the
|
|
151
|
+
// credit engine under-bills — LIVE-VERIFY Together honors include_usage.
|
|
152
|
+
const promptTokens = response.usage?.prompt_tokens ?? 0;
|
|
153
|
+
const completionTokens = response.usage?.completion_tokens ?? 0;
|
|
154
|
+
return {
|
|
155
|
+
message: {
|
|
156
|
+
role: message.role,
|
|
157
|
+
content: message.content || '',
|
|
158
|
+
tool_calls: this.#extractToolCalls(message.tool_calls),
|
|
159
|
+
},
|
|
160
|
+
usage: {
|
|
161
|
+
input_tokens: Math.max(0, promptTokens - cachedTokens),
|
|
162
|
+
output_tokens: completionTokens,
|
|
163
|
+
cache_read_input_tokens: cachedTokens,
|
|
164
|
+
cache_creation_input_tokens: 0,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
hasToolCalls(message) {
|
|
169
|
+
return Boolean(message?.tool_calls && message.tool_calls.length > 0);
|
|
170
|
+
}
|
|
171
|
+
/** Format messages for the OpenAI wire format. */
|
|
172
|
+
#formatMessages(messages) {
|
|
173
|
+
return messages.map(msg => {
|
|
174
|
+
if (msg.role === 'tool') {
|
|
175
|
+
return { role: 'tool', tool_call_id: msg.tool_call_id, content: msg.content };
|
|
176
|
+
}
|
|
177
|
+
return { role: msg.role, content: msg.content };
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/** Format a tool definition to OpenAI format from any of our known shapes. */
|
|
181
|
+
#formatTool(tool) {
|
|
182
|
+
if (tool.type === 'function' && tool.function)
|
|
183
|
+
return tool;
|
|
184
|
+
if (tool.function)
|
|
185
|
+
return { type: 'function', function: tool.function };
|
|
186
|
+
if (tool.input_schema) {
|
|
187
|
+
return {
|
|
188
|
+
type: 'function',
|
|
189
|
+
function: { name: tool.name, description: tool.description || '', parameters: tool.input_schema },
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (tool.parameters) {
|
|
193
|
+
return {
|
|
194
|
+
type: 'function',
|
|
195
|
+
function: { name: tool.name, description: tool.description || '', parameters: tool.parameters },
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
this.log(`[OpenAICompatibleExecutor:${this.providerName}] Warning: Unrecognized tool format:`, JSON.stringify(tool));
|
|
199
|
+
return {
|
|
200
|
+
type: 'function',
|
|
201
|
+
function: {
|
|
202
|
+
name: tool.name || 'unknown',
|
|
203
|
+
description: tool.description || '',
|
|
204
|
+
parameters: tool.parameters || tool.input_schema || { type: 'object', properties: {} },
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/** Format tool_choice to OpenAI format. */
|
|
209
|
+
#formatToolChoice(toolChoice) {
|
|
210
|
+
if (typeof toolChoice === 'string') {
|
|
211
|
+
if (toolChoice === 'required' || toolChoice === 'any')
|
|
212
|
+
return 'required';
|
|
213
|
+
return 'auto';
|
|
214
|
+
}
|
|
215
|
+
if (toolChoice.type === 'function' || toolChoice.function?.name)
|
|
216
|
+
return toolChoice;
|
|
217
|
+
// Anthropic format: { type: "tool", name: "..." }
|
|
218
|
+
if (toolChoice.type === 'tool' && toolChoice.name) {
|
|
219
|
+
return { type: 'function', function: { name: toolChoice.name } };
|
|
220
|
+
}
|
|
221
|
+
return 'auto';
|
|
222
|
+
}
|
|
223
|
+
/** Extract tool calls from an OpenAI-compatible response. */
|
|
224
|
+
#extractToolCalls(toolCalls) {
|
|
225
|
+
if (!toolCalls || toolCalls.length === 0)
|
|
226
|
+
return [];
|
|
227
|
+
return toolCalls.map(tc => ({
|
|
228
|
+
id: tc.id,
|
|
229
|
+
name: tc.function.name,
|
|
230
|
+
args: JSON.parse(tc.function.arguments),
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
/** Provider-specific params from model config metadata (excludes non-API keys). */
|
|
234
|
+
#extractProviderParams() {
|
|
235
|
+
const metadata = this.primaryModelConfig.metadata || {};
|
|
236
|
+
// Strip keys that are adapter config, not model-call params.
|
|
237
|
+
const { displayName, baseURL, cacheMode, quantization, ...providerParams } = metadata;
|
|
238
|
+
return providerParams;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=openaiCompatible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openaiCompatible.js","sourceRoot":"","sources":["../../src/providers/openaiCompatible.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* streaming.ts — shared streaming orchestration for the provider adapters.
|
|
3
|
+
*
|
|
4
|
+
* WHY: model responses used to be awaited as a single non-streamed completion,
|
|
5
|
+
* so the SDK's per-attempt `timeout` measured *total* time-to-complete. A
|
|
6
|
+
* legitimately long-but-progressing response (a full slide deck, a long report)
|
|
7
|
+
* could exceed that ceiling, get retried — re-sending the whole prompt and
|
|
8
|
+
* re-billing each attempt — and eventually fail as "Request timed out".
|
|
9
|
+
*
|
|
10
|
+
* Streaming removes the ceiling: we consume the provider's token stream and
|
|
11
|
+
* reset an INTER-CHUNK IDLE timer on every event. A response that keeps making
|
|
12
|
+
* progress never times out no matter how long it runs; only a genuinely STALLED
|
|
13
|
+
* stream (no token for `idleTimeoutMs`) is aborted and retried. A generous
|
|
14
|
+
* ABSOLUTE BACKSTOP guards the pathological "one token every 59 s forever" case.
|
|
15
|
+
*
|
|
16
|
+
* This module owns the timeout/abort/retry *orchestration* (provider-agnostic).
|
|
17
|
+
* Each provider adapter owns its SDK-specific stream consumption and assembles
|
|
18
|
+
* the SAME final response object its non-streamed path produced — so the
|
|
19
|
+
* executor's consumption (and token accounting) is byte-for-byte unchanged.
|
|
20
|
+
*/
|
|
21
|
+
/** No token for this long → the stream is stalled; abort + retry the attempt. */
|
|
22
|
+
export declare const STREAM_IDLE_TIMEOUT_MS: number;
|
|
23
|
+
/** Absolute per-attempt ceiling. Only the pathological dribble case reaches it;
|
|
24
|
+
* a steadily-streaming multi-minute response never does. It is TERMINAL (not
|
|
25
|
+
* retried) so a misbehaving stream can't be retried 3× and blow the worker's
|
|
26
|
+
* 14-min checkpoint. Comfortably above any legitimate single-turn duration. */
|
|
27
|
+
export declare const STREAM_ABSOLUTE_BACKSTOP_MS: number;
|
|
28
|
+
/** Whole-attempt retries on a transient mid-stream failure (idle stall, network
|
|
29
|
+
* drop, 5xx after the stream opened). Matches the pre-existing retry budget. */
|
|
30
|
+
export declare const STREAM_MAX_RETRIES: number;
|
|
31
|
+
export type StreamAbortReason = 'idle' | 'backstop' | 'external';
|
|
32
|
+
/** Raised when the guard aborts a stream. `reason` decides retry policy:
|
|
33
|
+
* `idle` is transient (retry); `backstop` and `external` are terminal. */
|
|
34
|
+
export declare class StreamAbortError extends Error {
|
|
35
|
+
reason: StreamAbortReason;
|
|
36
|
+
constructor(reason: StreamAbortReason, message: string);
|
|
37
|
+
}
|
|
38
|
+
export interface StreamGuard {
|
|
39
|
+
/** Pass to the provider SDK's stream call; aborts on idle/backstop/external. */
|
|
40
|
+
readonly signal: AbortSignal;
|
|
41
|
+
/** Call on every stream event/chunk to reset the idle timer. */
|
|
42
|
+
bump(): void;
|
|
43
|
+
/** Why the guard aborted, or null if it hasn't. */
|
|
44
|
+
reason(): StreamAbortReason | null;
|
|
45
|
+
/** Clear all timers + listeners. Idempotent; always call in a finally. */
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
export interface StreamGuardOptions {
|
|
49
|
+
idleTimeoutMs?: number;
|
|
50
|
+
backstopMs?: number;
|
|
51
|
+
/** The caller's AbortSignal (backend stop/timeout). Aborts the stream with
|
|
52
|
+
* reason `external` — terminal, never retried. */
|
|
53
|
+
externalSignal?: AbortSignal;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build an abort guard around a single stream attempt: an idle timer reset by
|
|
57
|
+
* `bump()`, an absolute backstop, and linkage to an optional external signal.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createStreamGuard(opts?: StreamGuardOptions): StreamGuard;
|
|
60
|
+
/** True for the abort error a provider SDK throws when we call `controller.abort()`. */
|
|
61
|
+
export declare function isAbortError(err: any): boolean;
|
|
62
|
+
export interface StreamRetryOptions {
|
|
63
|
+
maxRetries?: number;
|
|
64
|
+
idleTimeoutMs?: number;
|
|
65
|
+
backstopMs?: number;
|
|
66
|
+
externalSignal?: AbortSignal;
|
|
67
|
+
/** Classify a NON-abort mid-stream error as transient (retry) vs fatal. */
|
|
68
|
+
isRetryable?: (err: any) => boolean;
|
|
69
|
+
log?: (message: string) => void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Run one stream `attempt` with a fresh guard, retrying the WHOLE prompt on a
|
|
73
|
+
* transient failure (idle stall or a caller-classified retryable error). The
|
|
74
|
+
* partial output is discarded on failure. Backstop and external aborts are
|
|
75
|
+
* terminal. Bounded by `maxRetries`.
|
|
76
|
+
*/
|
|
77
|
+
export declare function streamWithRetry<T>(attempt: (guard: StreamGuard) => Promise<T>, opts?: StreamRetryOptions): Promise<T>;
|
|
78
|
+
/** The subset of an OpenAI chat completion the executor consumes. Assembling
|
|
79
|
+
* the stream back into this shape lets the non-streamed extraction run
|
|
80
|
+
* unchanged. */
|
|
81
|
+
export interface OpenAICompletionLike {
|
|
82
|
+
choices: Array<{
|
|
83
|
+
message: {
|
|
84
|
+
role: string;
|
|
85
|
+
content: string | null;
|
|
86
|
+
tool_calls?: Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
type: 'function';
|
|
89
|
+
function: {
|
|
90
|
+
name: string;
|
|
91
|
+
arguments: string;
|
|
92
|
+
};
|
|
93
|
+
}>;
|
|
94
|
+
};
|
|
95
|
+
}>;
|
|
96
|
+
usage?: any;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Fold an OpenAI (or OpenAI-compatible) chat completion STREAM back into the
|
|
100
|
+
* non-streamed completion shape.
|
|
101
|
+
*
|
|
102
|
+
* Deltas arrive fragmented: `content` in pieces, and each tool call as an
|
|
103
|
+
* index-keyed run of deltas — the id + function.name usually in the first, the
|
|
104
|
+
* JSON `arguments` string across many. We reassemble per index and join in
|
|
105
|
+
* index order. Usage arrives on the final chunk (requires
|
|
106
|
+
* `stream_options.include_usage: true`).
|
|
107
|
+
*/
|
|
108
|
+
export declare function consumeOpenAIStream(stream: AsyncIterable<any>, bump: () => void): Promise<OpenAICompletionLike>;
|
|
109
|
+
//# sourceMappingURL=streaming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../../src/providers/streaming.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,QACwB,CAAC;AAE5D;;;gFAGgF;AAChF,eAAO,MAAM,2BAA2B,QACgB,CAAC;AAEzD;iFACiF;AACjF,eAAO,MAAM,kBAAkB,QAAmD,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;AAEjE;2EAC2E;AAC3E,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,MAAM,EAAE,iBAAiB,CAAC;gBACd,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM;CAKvD;AAED,MAAM,WAAW,WAAW;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,gEAAgE;IAChE,IAAI,IAAI,IAAI,CAAC;IACb,mDAAmD;IACnD,MAAM,IAAI,iBAAiB,GAAG,IAAI,CAAC;IACnC,0EAA0E;IAC1E,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;uDACmD;IACnD,cAAc,CAAC,EAAE,WAAW,CAAC;CAC9B;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,kBAAuB,GAAG,WAAW,CAqD5E;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAI9C;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,2EAA2E;IAC3E,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;IACpC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,OAAO,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3C,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,CAAC,CAAC,CAyCZ;AAMD;;iBAEiB;AACjB,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;QACb,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;YACvB,UAAU,CAAC,EAAE,KAAK,CAAC;gBAAE,EAAE,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,UAAU,CAAC;gBAAC,QAAQ,EAAE;oBAAE,IAAI,EAAE,MAAM,CAAC;oBAAC,SAAS,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,CAAC,CAAC;SACrG,CAAC;KACH,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,GAAG,CAAC;CACb;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,EAC1B,IAAI,EAAE,MAAM,IAAI,GACf,OAAO,CAAC,oBAAoB,CAAC,CAgD/B"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* streaming.ts — shared streaming orchestration for the provider adapters.
|
|
3
|
+
*
|
|
4
|
+
* WHY: model responses used to be awaited as a single non-streamed completion,
|
|
5
|
+
* so the SDK's per-attempt `timeout` measured *total* time-to-complete. A
|
|
6
|
+
* legitimately long-but-progressing response (a full slide deck, a long report)
|
|
7
|
+
* could exceed that ceiling, get retried — re-sending the whole prompt and
|
|
8
|
+
* re-billing each attempt — and eventually fail as "Request timed out".
|
|
9
|
+
*
|
|
10
|
+
* Streaming removes the ceiling: we consume the provider's token stream and
|
|
11
|
+
* reset an INTER-CHUNK IDLE timer on every event. A response that keeps making
|
|
12
|
+
* progress never times out no matter how long it runs; only a genuinely STALLED
|
|
13
|
+
* stream (no token for `idleTimeoutMs`) is aborted and retried. A generous
|
|
14
|
+
* ABSOLUTE BACKSTOP guards the pathological "one token every 59 s forever" case.
|
|
15
|
+
*
|
|
16
|
+
* This module owns the timeout/abort/retry *orchestration* (provider-agnostic).
|
|
17
|
+
* Each provider adapter owns its SDK-specific stream consumption and assembles
|
|
18
|
+
* the SAME final response object its non-streamed path produced — so the
|
|
19
|
+
* executor's consumption (and token accounting) is byte-for-byte unchanged.
|
|
20
|
+
*/
|
|
21
|
+
/** No token for this long → the stream is stalled; abort + retry the attempt. */
|
|
22
|
+
export const STREAM_IDLE_TIMEOUT_MS = Number(process.env.AGNT_STREAM_IDLE_TIMEOUT_MS) || 60_000;
|
|
23
|
+
/** Absolute per-attempt ceiling. Only the pathological dribble case reaches it;
|
|
24
|
+
* a steadily-streaming multi-minute response never does. It is TERMINAL (not
|
|
25
|
+
* retried) so a misbehaving stream can't be retried 3× and blow the worker's
|
|
26
|
+
* 14-min checkpoint. Comfortably above any legitimate single-turn duration. */
|
|
27
|
+
export const STREAM_ABSOLUTE_BACKSTOP_MS = Number(process.env.AGNT_STREAM_BACKSTOP_MS) || 600_000;
|
|
28
|
+
/** Whole-attempt retries on a transient mid-stream failure (idle stall, network
|
|
29
|
+
* drop, 5xx after the stream opened). Matches the pre-existing retry budget. */
|
|
30
|
+
export const STREAM_MAX_RETRIES = Number(process.env.AGNT_STREAM_MAX_RETRIES) || 3;
|
|
31
|
+
/** Raised when the guard aborts a stream. `reason` decides retry policy:
|
|
32
|
+
* `idle` is transient (retry); `backstop` and `external` are terminal. */
|
|
33
|
+
export class StreamAbortError extends Error {
|
|
34
|
+
reason;
|
|
35
|
+
constructor(reason, message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = 'StreamAbortError';
|
|
38
|
+
this.reason = reason;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function unref(t) {
|
|
42
|
+
// Don't let the idle/backstop timer keep the event loop (or a Lambda) alive.
|
|
43
|
+
if (t && typeof t.unref === 'function')
|
|
44
|
+
t.unref();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build an abort guard around a single stream attempt: an idle timer reset by
|
|
48
|
+
* `bump()`, an absolute backstop, and linkage to an optional external signal.
|
|
49
|
+
*/
|
|
50
|
+
export function createStreamGuard(opts = {}) {
|
|
51
|
+
const idleMs = opts.idleTimeoutMs ?? STREAM_IDLE_TIMEOUT_MS;
|
|
52
|
+
const backstopMs = opts.backstopMs ?? STREAM_ABSOLUTE_BACKSTOP_MS;
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
let abortedReason = null;
|
|
55
|
+
let idleTimer = null;
|
|
56
|
+
let backstopTimer = null;
|
|
57
|
+
let externalCleanup = null;
|
|
58
|
+
const abort = (reason) => {
|
|
59
|
+
if (abortedReason)
|
|
60
|
+
return; // first reason wins
|
|
61
|
+
abortedReason = reason;
|
|
62
|
+
clearTimers();
|
|
63
|
+
controller.abort();
|
|
64
|
+
};
|
|
65
|
+
const clearTimers = () => {
|
|
66
|
+
if (idleTimer) {
|
|
67
|
+
clearTimeout(idleTimer);
|
|
68
|
+
idleTimer = null;
|
|
69
|
+
}
|
|
70
|
+
if (backstopTimer) {
|
|
71
|
+
clearTimeout(backstopTimer);
|
|
72
|
+
backstopTimer = null;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const bump = () => {
|
|
76
|
+
if (abortedReason)
|
|
77
|
+
return;
|
|
78
|
+
if (idleTimer)
|
|
79
|
+
clearTimeout(idleTimer);
|
|
80
|
+
idleTimer = setTimeout(() => abort('idle'), idleMs);
|
|
81
|
+
unref(idleTimer);
|
|
82
|
+
};
|
|
83
|
+
backstopTimer = setTimeout(() => abort('backstop'), backstopMs);
|
|
84
|
+
unref(backstopTimer);
|
|
85
|
+
if (opts.externalSignal) {
|
|
86
|
+
const ext = opts.externalSignal;
|
|
87
|
+
if (ext.aborted) {
|
|
88
|
+
abort('external');
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const onAbort = () => abort('external');
|
|
92
|
+
ext.addEventListener('abort', onAbort, { once: true });
|
|
93
|
+
externalCleanup = () => ext.removeEventListener('abort', onAbort);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
bump(); // arm the idle timer for the connection-open window
|
|
97
|
+
return {
|
|
98
|
+
signal: controller.signal,
|
|
99
|
+
bump,
|
|
100
|
+
reason: () => abortedReason,
|
|
101
|
+
dispose: () => {
|
|
102
|
+
clearTimers();
|
|
103
|
+
if (externalCleanup) {
|
|
104
|
+
externalCleanup();
|
|
105
|
+
externalCleanup = null;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/** True for the abort error a provider SDK throws when we call `controller.abort()`. */
|
|
111
|
+
export function isAbortError(err) {
|
|
112
|
+
const name = err?.name ?? err?.constructor?.name;
|
|
113
|
+
if (name === 'AbortError' || name === 'APIUserAbortError')
|
|
114
|
+
return true;
|
|
115
|
+
return typeof err?.message === 'string' && /\baborted\b/i.test(err.message);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Run one stream `attempt` with a fresh guard, retrying the WHOLE prompt on a
|
|
119
|
+
* transient failure (idle stall or a caller-classified retryable error). The
|
|
120
|
+
* partial output is discarded on failure. Backstop and external aborts are
|
|
121
|
+
* terminal. Bounded by `maxRetries`.
|
|
122
|
+
*/
|
|
123
|
+
export async function streamWithRetry(attempt, opts = {}) {
|
|
124
|
+
const maxRetries = opts.maxRetries ?? STREAM_MAX_RETRIES;
|
|
125
|
+
const isRetryable = opts.isRetryable ?? (() => true);
|
|
126
|
+
let lastError;
|
|
127
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
128
|
+
if (opts.externalSignal?.aborted) {
|
|
129
|
+
throw new StreamAbortError('external', '[streaming] aborted before attempt');
|
|
130
|
+
}
|
|
131
|
+
const guard = createStreamGuard({
|
|
132
|
+
idleTimeoutMs: opts.idleTimeoutMs,
|
|
133
|
+
backstopMs: opts.backstopMs,
|
|
134
|
+
externalSignal: opts.externalSignal,
|
|
135
|
+
});
|
|
136
|
+
try {
|
|
137
|
+
return await attempt(guard);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
// Map a guard-triggered abort to a typed error carrying its reason.
|
|
141
|
+
const reason = guard.reason();
|
|
142
|
+
const mapped = reason && isAbortError(err)
|
|
143
|
+
? new StreamAbortError(reason, `[streaming] stream aborted: ${reason}`)
|
|
144
|
+
: err;
|
|
145
|
+
lastError = mapped;
|
|
146
|
+
// Terminal: the caller asked to stop, or the stream dribbled to the
|
|
147
|
+
// backstop — retrying either would be wrong/wasteful.
|
|
148
|
+
if (mapped instanceof StreamAbortError && mapped.reason !== 'idle') {
|
|
149
|
+
throw mapped;
|
|
150
|
+
}
|
|
151
|
+
const retryable = mapped instanceof StreamAbortError ? mapped.reason === 'idle' : isRetryable(mapped);
|
|
152
|
+
if (!retryable || i === maxRetries - 1)
|
|
153
|
+
throw mapped;
|
|
154
|
+
opts.log?.(`[streaming] attempt ${i + 1}/${maxRetries} failed (${mapped?.message ?? mapped}) — discarding partial, retrying`);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
guard.dispose();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
throw lastError;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Fold an OpenAI (or OpenAI-compatible) chat completion STREAM back into the
|
|
164
|
+
* non-streamed completion shape.
|
|
165
|
+
*
|
|
166
|
+
* Deltas arrive fragmented: `content` in pieces, and each tool call as an
|
|
167
|
+
* index-keyed run of deltas — the id + function.name usually in the first, the
|
|
168
|
+
* JSON `arguments` string across many. We reassemble per index and join in
|
|
169
|
+
* index order. Usage arrives on the final chunk (requires
|
|
170
|
+
* `stream_options.include_usage: true`).
|
|
171
|
+
*/
|
|
172
|
+
export async function consumeOpenAIStream(stream, bump) {
|
|
173
|
+
let role = 'assistant';
|
|
174
|
+
let content = '';
|
|
175
|
+
let sawContent = false;
|
|
176
|
+
let usage = undefined;
|
|
177
|
+
const byIndex = new Map();
|
|
178
|
+
for await (const chunk of stream) {
|
|
179
|
+
bump();
|
|
180
|
+
const choice = chunk?.choices?.[0];
|
|
181
|
+
if (choice) {
|
|
182
|
+
const delta = choice.delta || {};
|
|
183
|
+
if (delta.role)
|
|
184
|
+
role = delta.role;
|
|
185
|
+
if (typeof delta.content === 'string') {
|
|
186
|
+
content += delta.content;
|
|
187
|
+
sawContent = true;
|
|
188
|
+
}
|
|
189
|
+
if (Array.isArray(delta.tool_calls)) {
|
|
190
|
+
for (const tc of delta.tool_calls) {
|
|
191
|
+
const idx = typeof tc.index === 'number' ? tc.index : 0;
|
|
192
|
+
let acc = byIndex.get(idx);
|
|
193
|
+
if (!acc) {
|
|
194
|
+
acc = { id: '', name: '', args: '' };
|
|
195
|
+
byIndex.set(idx, acc);
|
|
196
|
+
}
|
|
197
|
+
if (tc.id)
|
|
198
|
+
acc.id = tc.id;
|
|
199
|
+
if (tc.function?.name)
|
|
200
|
+
acc.name += tc.function.name;
|
|
201
|
+
if (typeof tc.function?.arguments === 'string')
|
|
202
|
+
acc.args += tc.function.arguments;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// Usage rides its own final chunk (choices may be empty there).
|
|
207
|
+
if (chunk?.usage)
|
|
208
|
+
usage = chunk.usage;
|
|
209
|
+
}
|
|
210
|
+
const tool_calls = byIndex.size
|
|
211
|
+
? [...byIndex.entries()]
|
|
212
|
+
.sort((a, b) => a[0] - b[0])
|
|
213
|
+
// Default empty args to "{}" — a zero-arg tool call may stream an id+name
|
|
214
|
+
// with no `arguments` fragment (real OpenAI always sends "{}", but
|
|
215
|
+
// DeepSeek / OpenAI-compatible endpoints may not). The downstream
|
|
216
|
+
// extractor does JSON.parse(arguments), which throws on "". Mirror the
|
|
217
|
+
// non-streamed shape so a no-arg tool call parses to {} instead of crashing.
|
|
218
|
+
.map(([, v]) => ({ id: v.id, type: 'function', function: { name: v.name, arguments: v.args || '{}' } }))
|
|
219
|
+
: undefined;
|
|
220
|
+
return {
|
|
221
|
+
// Mirror the non-streamed shape: content is null when the turn is tool-only.
|
|
222
|
+
choices: [{ message: { role, content: sawContent ? content : (tool_calls ? null : ''), tool_calls } }],
|
|
223
|
+
usage,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=streaming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming.js","sourceRoot":"","sources":["../../src/providers/streaming.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -48,14 +48,21 @@ export interface ProviderCredentials {
|
|
|
48
48
|
accessKeyId?: string;
|
|
49
49
|
secretAccessKey?: string;
|
|
50
50
|
};
|
|
51
|
-
deepseek?:
|
|
52
|
-
apiKey: string;
|
|
53
|
-
dangerouslyAllowBrowser?: boolean;
|
|
54
|
-
};
|
|
51
|
+
deepseek?: OpenAICompatibleCredentials;
|
|
55
52
|
google?: {
|
|
56
53
|
apiKey: string;
|
|
57
54
|
dangerouslyAllowBrowser?: boolean;
|
|
58
55
|
};
|
|
56
|
+
together?: OpenAICompatibleCredentials;
|
|
57
|
+
fireworks?: OpenAICompatibleCredentials;
|
|
58
|
+
deepinfra?: OpenAICompatibleCredentials;
|
|
59
|
+
[provider: string]: any;
|
|
60
|
+
}
|
|
61
|
+
export interface OpenAICompatibleCredentials {
|
|
62
|
+
apiKey: string;
|
|
63
|
+
/** Override the provider registry / model-metadata base URL. */
|
|
64
|
+
baseURL?: string;
|
|
65
|
+
dangerouslyAllowBrowser?: boolean;
|
|
59
66
|
}
|
|
60
67
|
export interface ToolHandler {
|
|
61
68
|
execute: (args: any) => Promise<any>;
|
|
@@ -159,6 +166,10 @@ export interface InvokeOptions {
|
|
|
159
166
|
* no follow-up turn to hit the cache — avoids paying the 25% write surcharge
|
|
160
167
|
* with zero benefit. Agent/Prime multi-turn runs should NOT set this. */
|
|
161
168
|
disableCache?: boolean;
|
|
169
|
+
/** Caller's abort signal (backend stop/timeout). Threaded to the provider's
|
|
170
|
+
* streaming call so an in-flight token stream stops cleanly. Set by
|
|
171
|
+
* BaseExecutor from its per-run AbortController (see cancel()). */
|
|
172
|
+
signal?: AbortSignal;
|
|
162
173
|
}
|
|
163
174
|
/** Leaf condition: variable op value */
|
|
164
175
|
export interface LeafCondition {
|