@oh-my-pi/pi-ai 18.2.6 → 18.2.7
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/CHANGELOG.md +13 -1
- package/THIRD-PARTY-NOTICES.txt +0 -37
- package/dist/types/auth-retry.d.ts +2 -0
- package/dist/types/auth-storage.d.ts +2 -2
- package/dist/types/error/classes.d.ts +4 -1
- package/dist/types/error/flags.d.ts +12 -4
- package/dist/types/index.d.ts +14 -12
- package/dist/types/judgment/types.d.ts +5 -2
- package/dist/types/judgment/typesafe.d.ts +16 -22
- package/dist/types/providers/anthropic-compaction.d.ts +10 -0
- package/dist/types/providers/anthropic-identity.d.ts +18 -0
- package/dist/types/providers/anthropic-state.d.ts +13 -0
- package/dist/types/providers/anthropic.d.ts +6 -59
- package/dist/types/providers/gitlab-duo.d.ts +0 -1
- package/dist/types/providers/kimi.d.ts +1 -5
- package/dist/types/providers/openai-codex-attestation.d.ts +6 -0
- package/dist/types/providers/openai-codex-compaction.d.ts +6 -0
- package/dist/types/providers/openai-codex-responses.d.ts +3 -27
- package/dist/types/providers/openai-codex-transport.d.ts +7 -0
- package/dist/types/providers/openai-shared.d.ts +0 -9
- package/dist/types/providers/register-builtins.d.ts +20 -22
- package/dist/types/providers/synthetic.d.ts +1 -5
- package/package.json +6 -6
- package/src/auth-retry.ts +3 -0
- package/src/auth-storage.ts +28 -22
- package/src/error/auth-classify.ts +10 -2
- package/src/error/classes.ts +23 -3
- package/src/error/flags.ts +51 -16
- package/src/index.ts +15 -12
- package/src/judgment/types.ts +6 -3
- package/src/judgment/typesafe.ts +53 -48
- package/src/provider-session-state.ts +1 -1
- package/src/providers/anthropic-compaction.ts +54 -0
- package/src/providers/anthropic-identity.ts +136 -0
- package/src/providers/anthropic-state.ts +55 -0
- package/src/providers/anthropic.ts +39 -296
- package/src/providers/bedrock-mantle.ts +1 -1
- package/src/providers/gitlab-duo.ts +0 -4
- package/src/providers/kimi.ts +1 -8
- package/src/providers/openai-codex-attestation.ts +19 -0
- package/src/providers/openai-codex-compaction.ts +18 -0
- package/src/providers/openai-codex-responses.ts +9 -68
- package/src/providers/openai-codex-transport.ts +18 -0
- package/src/providers/openai-shared.ts +1 -10
- package/src/providers/register-builtins.ts +113 -320
- package/src/providers/synthetic.ts +1 -8
- package/src/registry/cloudflare-ai-gateway.ts +1 -1
- package/src/stream.ts +7 -15
- package/src/utils/anthropic-auth.ts +3 -6
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Each provider module is loaded only when its stream function is first called.
|
|
5
|
-
* This avoids eagerly importing heavy SDK dependencies (e.g., openai) at
|
|
6
|
-
* startup. The loaded module promise is cached so subsequent calls
|
|
7
|
-
* reuse the same import.
|
|
8
|
-
*
|
|
9
|
-
* NOTE: stream.ts currently imports providers directly, so this file is not yet
|
|
10
|
-
* wired into the main streaming path. It provides the infrastructure for lazy
|
|
11
|
-
* loading that can be integrated when stream.ts is refactored.
|
|
2
|
+
* Built-in provider stream dispatch with shared error, cancellation, and timeout handling.
|
|
12
3
|
*/
|
|
13
4
|
|
|
14
5
|
import type { CompatOf } from "@oh-my-pi/pi-catalog/types";
|
|
15
6
|
import * as AIError from "../error";
|
|
16
|
-
import type {
|
|
17
|
-
Api,
|
|
18
|
-
AssistantMessage,
|
|
19
|
-
AssistantMessageEvent,
|
|
20
|
-
AssistantMessageEventStream,
|
|
21
|
-
Context,
|
|
22
|
-
Model,
|
|
23
|
-
OptionsForApi,
|
|
24
|
-
} from "../types";
|
|
7
|
+
import type { Api, AssistantMessage, AssistantMessageEvent, Context, Model, OptionsForApi } from "../types";
|
|
25
8
|
import { type AbortSourceTracker, createAbortSourceTracker } from "../utils/abort";
|
|
26
9
|
import { AssistantMessageEventStream as EventStreamImpl } from "../utils/event-stream";
|
|
27
10
|
import {
|
|
@@ -31,156 +14,44 @@ import {
|
|
|
31
14
|
getStreamIdleTimeoutMs,
|
|
32
15
|
iterateWithIdleTimeout,
|
|
33
16
|
} from "../utils/idle-iterator";
|
|
34
|
-
import
|
|
35
|
-
import
|
|
36
|
-
import
|
|
37
|
-
import
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
import
|
|
41
|
-
import
|
|
42
|
-
import
|
|
43
|
-
import
|
|
44
|
-
import
|
|
45
|
-
import
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
stream: (model: Model<TApi>, context: Context, options: OptionsForApi<TApi>) => AsyncIterable<AssistantMessageEvent>;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
interface AnthropicProviderModule {
|
|
56
|
-
streamAnthropic: (
|
|
57
|
-
model: Model<"anthropic-messages">,
|
|
58
|
-
context: Context,
|
|
59
|
-
options: AnthropicOptions,
|
|
60
|
-
) => AssistantMessageEventStream;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
interface AzureOpenAIResponsesProviderModule {
|
|
64
|
-
streamAzureOpenAIResponses: (
|
|
65
|
-
model: Model<"azure-openai-responses">,
|
|
66
|
-
context: Context,
|
|
67
|
-
options: AzureOpenAIResponsesOptions,
|
|
68
|
-
) => AssistantMessageEventStream;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface GoogleProviderModule {
|
|
72
|
-
streamGoogle: (
|
|
73
|
-
model: Model<"google-generative-ai">,
|
|
74
|
-
context: Context,
|
|
75
|
-
options: GoogleOptions,
|
|
76
|
-
) => AssistantMessageEventStream;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
interface GoogleGeminiCliProviderModule {
|
|
80
|
-
streamGoogleGeminiCli: (
|
|
81
|
-
model: Model<"google-gemini-cli">,
|
|
82
|
-
context: Context,
|
|
83
|
-
options: GoogleGeminiCliOptions,
|
|
84
|
-
) => AssistantMessageEventStream;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
interface GoogleVertexProviderModule {
|
|
88
|
-
streamGoogleVertex: (
|
|
89
|
-
model: Model<"google-vertex">,
|
|
90
|
-
context: Context,
|
|
91
|
-
options: GoogleVertexOptions,
|
|
92
|
-
) => AssistantMessageEventStream;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
interface OpenAICodexResponsesProviderModule {
|
|
96
|
-
streamOpenAICodexResponses: (
|
|
97
|
-
model: Model<"openai-codex-responses">,
|
|
98
|
-
context: Context,
|
|
99
|
-
options: OpenAICodexResponsesOptions,
|
|
100
|
-
) => AssistantMessageEventStream;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
interface OpenAICompletionsProviderModule {
|
|
104
|
-
streamOpenAICompletions: (
|
|
105
|
-
model: Model<"openai-completions">,
|
|
106
|
-
context: Context,
|
|
107
|
-
options: OpenAICompletionsOptions,
|
|
108
|
-
) => AssistantMessageEventStream;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
interface OpenAIResponsesProviderModule {
|
|
112
|
-
streamOpenAIResponses: (
|
|
113
|
-
model: Model<"openai-responses">,
|
|
114
|
-
context: Context,
|
|
115
|
-
options: OpenAIResponsesOptions,
|
|
116
|
-
) => AssistantMessageEventStream;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
interface OllamaProviderModule {
|
|
120
|
-
streamOllama: (
|
|
121
|
-
model: Model<"ollama-chat">,
|
|
122
|
-
context: Context,
|
|
123
|
-
options: OllamaChatOptions,
|
|
124
|
-
) => AssistantMessageEventStream;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
interface CursorProviderModule {
|
|
128
|
-
streamCursor: (
|
|
129
|
-
model: Model<"cursor-agent">,
|
|
130
|
-
context: Context,
|
|
131
|
-
options: CursorOptions,
|
|
132
|
-
) => AssistantMessageEventStream;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
interface DevinProviderModule {
|
|
136
|
-
streamDevin: (model: Model<"devin-agent">, context: Context, options: DevinOptions) => AssistantMessageEventStream;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
interface BedrockProviderModule {
|
|
140
|
-
streamBedrock: (
|
|
141
|
-
model: Model<"bedrock-converse-stream">,
|
|
142
|
-
context: Context,
|
|
143
|
-
options: BedrockOptions,
|
|
144
|
-
) => AssistantMessageEventStream;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
// Module-level lazy promise caches
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
17
|
+
import * as AnthropicProvider from "./anthropic";
|
|
18
|
+
import * as AzureOpenAIResponsesProvider from "./azure-openai-responses";
|
|
19
|
+
import * as BedrockProvider from "./amazon-bedrock";
|
|
20
|
+
import * as CursorProvider from "./cursor";
|
|
21
|
+
import * as DevinProvider from "./devin";
|
|
22
|
+
import * as GoogleProvider from "./google";
|
|
23
|
+
import * as GoogleGeminiCliProvider from "./google-gemini-cli";
|
|
24
|
+
import * as GoogleVertexProvider from "./google-vertex";
|
|
25
|
+
import * as OllamaProvider from "./ollama";
|
|
26
|
+
import * as OpenAICodexResponsesProvider from "./openai-codex-responses";
|
|
27
|
+
import * as OpenAICompletionsProvider from "./openai-completions";
|
|
28
|
+
import * as OpenAIResponsesProvider from "./openai-responses";
|
|
29
|
+
|
|
30
|
+
type ProviderStream<TApi extends Api> = (
|
|
31
|
+
model: Model<TApi>,
|
|
32
|
+
context: Context,
|
|
33
|
+
options: OptionsForApi<TApi>,
|
|
34
|
+
) => AsyncIterable<AssistantMessageEvent>;
|
|
150
35
|
|
|
151
|
-
let
|
|
152
|
-
let
|
|
153
|
-
let googleProviderModulePromise: Promise<LazyProviderModule<"google-generative-ai">> | undefined;
|
|
154
|
-
let googleGeminiCliProviderModulePromise: Promise<LazyProviderModule<"google-gemini-cli">> | undefined;
|
|
155
|
-
let googleVertexProviderModulePromise: Promise<LazyProviderModule<"google-vertex">> | undefined;
|
|
156
|
-
let openAICodexResponsesProviderModulePromise: Promise<LazyProviderModule<"openai-codex-responses">> | undefined;
|
|
157
|
-
let openAICompletionsProviderModulePromise: Promise<LazyProviderModule<"openai-completions">> | undefined;
|
|
158
|
-
let openAIResponsesProviderModulePromise: Promise<LazyProviderModule<"openai-responses">> | undefined;
|
|
159
|
-
let ollamaProviderModulePromise: Promise<LazyProviderModule<"ollama-chat">> | undefined;
|
|
160
|
-
let cursorProviderModulePromise: Promise<LazyProviderModule<"cursor-agent">> | undefined;
|
|
161
|
-
let cursorProviderModuleOverride: LazyProviderModule<"cursor-agent"> | undefined;
|
|
162
|
-
let devinProviderModulePromise: Promise<LazyProviderModule<"devin-agent">> | undefined;
|
|
163
|
-
let bedrockProviderModuleOverride: LazyProviderModule<"bedrock-converse-stream"> | undefined;
|
|
164
|
-
let bedrockProviderModulePromise: Promise<LazyProviderModule<"bedrock-converse-stream">> | undefined;
|
|
36
|
+
let cursorStreamOverride: typeof CursorProvider.streamCursor | undefined;
|
|
37
|
+
let bedrockStreamOverride: typeof BedrockProvider.streamBedrock | undefined;
|
|
165
38
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
};
|
|
39
|
+
/** Install a host-supplied Bedrock transport in place of the built-in provider. */
|
|
40
|
+
export function setBedrockProviderModule(module: Pick<typeof BedrockProvider, "streamBedrock">): void {
|
|
41
|
+
bedrockStreamOverride = module.streamBedrock;
|
|
170
42
|
}
|
|
171
43
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
};
|
|
44
|
+
/** Install a host-supplied Cursor transport in place of the built-in provider. */
|
|
45
|
+
export function setCursorProviderModule(module: Pick<typeof CursorProvider, "streamCursor">): void {
|
|
46
|
+
cursorStreamOverride = module.streamCursor;
|
|
176
47
|
}
|
|
177
48
|
|
|
178
49
|
// ---------------------------------------------------------------------------
|
|
179
50
|
// Stream forwarding / error helpers
|
|
180
51
|
// ---------------------------------------------------------------------------
|
|
181
52
|
|
|
182
|
-
const
|
|
183
|
-
const
|
|
53
|
+
const STREAM_IDLE_TIMEOUT_ERROR = "Provider stream stalled while waiting for the next event";
|
|
54
|
+
const STREAM_FIRST_EVENT_TIMEOUT_ERROR = "Provider stream timed out while waiting for the first event";
|
|
184
55
|
|
|
185
56
|
function hasFinalResult(
|
|
186
57
|
source: AsyncIterable<AssistantMessageEvent>,
|
|
@@ -194,21 +65,21 @@ function hasFinalResult(
|
|
|
194
65
|
* take precedence unless a provider opts into OpenAI-family idle flooring for
|
|
195
66
|
* local backends that users historically tuned with `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS`.
|
|
196
67
|
*/
|
|
197
|
-
interface
|
|
68
|
+
interface StreamLimits {
|
|
198
69
|
defaultFirstEventTimeoutMs?: number;
|
|
199
70
|
defaultIdleTimeoutMs?: number;
|
|
200
71
|
/**
|
|
201
72
|
* The provider implementation already wraps its upstream transport with
|
|
202
|
-
* stream timeouts. Keep the
|
|
73
|
+
* stream timeouts. Keep the shared watchdog from racing it with generic errors.
|
|
203
74
|
*/
|
|
204
75
|
providerHandlesStreamTimeouts?: boolean;
|
|
205
76
|
/**
|
|
206
77
|
* The provider retries or fails over when no first event arrives, while the
|
|
207
|
-
*
|
|
78
|
+
* shared wrapper continues to own steady-state idle detection.
|
|
208
79
|
*/
|
|
209
80
|
providerHandlesFirstEventTimeouts?: boolean;
|
|
210
81
|
/**
|
|
211
|
-
* Apply OpenAI-family idle timeout precedence in the
|
|
82
|
+
* Apply OpenAI-family idle timeout precedence in the shared wrapper. Used by
|
|
212
83
|
* local backends whose users historically tune slow prompt-processing gaps
|
|
213
84
|
* with `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS`.
|
|
214
85
|
*/
|
|
@@ -217,18 +88,18 @@ interface LazyStreamLimits {
|
|
|
217
88
|
/**
|
|
218
89
|
* Cloud Code Assist owns first-event detection because Antigravity can return
|
|
219
90
|
* successful headers and then never emit an SSE event. Keeping the watchdog in
|
|
220
|
-
* the provider lets it fail over before surfacing an error; the
|
|
91
|
+
* the provider lets it fail over before surfacing an error; the shared wrapper
|
|
221
92
|
* still catches post-first-event stalls.
|
|
222
93
|
*/
|
|
223
|
-
const
|
|
94
|
+
const GOOGLE_GEMINI_CLI_STREAM_LIMITS: StreamLimits = {
|
|
224
95
|
providerHandlesFirstEventTimeouts: true,
|
|
225
96
|
};
|
|
226
97
|
|
|
227
|
-
const PROVIDER_HANDLED_STREAM_TIMEOUTS:
|
|
98
|
+
const PROVIDER_HANDLED_STREAM_TIMEOUTS: StreamLimits = {
|
|
228
99
|
providerHandlesStreamTimeouts: true,
|
|
229
100
|
};
|
|
230
101
|
|
|
231
|
-
const
|
|
102
|
+
const OPENAI_IDLE_FLOORED_STREAM_LIMITS: StreamLimits = {
|
|
232
103
|
openAIIdleEnvFloorsFirstEvent: true,
|
|
233
104
|
};
|
|
234
105
|
|
|
@@ -238,7 +109,7 @@ function forwardStream<TApi extends Api>(
|
|
|
238
109
|
model: Model<TApi>,
|
|
239
110
|
options: OptionsForApi<TApi>,
|
|
240
111
|
abortTracker: AbortSourceTracker,
|
|
241
|
-
limits?:
|
|
112
|
+
limits?: StreamLimits,
|
|
242
113
|
): void {
|
|
243
114
|
(async () => {
|
|
244
115
|
try {
|
|
@@ -275,11 +146,11 @@ function forwardStream<TApi extends Api>(
|
|
|
275
146
|
const watchedSource = iterateWithIdleTimeout(source, {
|
|
276
147
|
idleTimeoutMs,
|
|
277
148
|
firstItemTimeoutMs,
|
|
278
|
-
errorMessage:
|
|
279
|
-
firstItemErrorMessage:
|
|
280
|
-
onIdle: () => abortTracker.abortLocally(new AIError.StreamTimeoutError(
|
|
149
|
+
errorMessage: STREAM_IDLE_TIMEOUT_ERROR,
|
|
150
|
+
firstItemErrorMessage: STREAM_FIRST_EVENT_TIMEOUT_ERROR,
|
|
151
|
+
onIdle: () => abortTracker.abortLocally(new AIError.StreamTimeoutError(STREAM_IDLE_TIMEOUT_ERROR)),
|
|
281
152
|
onFirstItemTimeout: () =>
|
|
282
|
-
abortTracker.abortLocally(new AIError.StreamTimeoutError(
|
|
153
|
+
abortTracker.abortLocally(new AIError.StreamTimeoutError(STREAM_FIRST_EVENT_TIMEOUT_ERROR)),
|
|
283
154
|
abortSignal: options.signal,
|
|
284
155
|
// The synthetic `start` event is yielded immediately by every provider before
|
|
285
156
|
// the upstream model has emitted any tokens. Treating it as the first "real"
|
|
@@ -300,14 +171,14 @@ function forwardStream<TApi extends Api>(
|
|
|
300
171
|
}
|
|
301
172
|
} catch (error) {
|
|
302
173
|
const stopReason = abortTracker.wasCallerAbort() ? "aborted" : "error";
|
|
303
|
-
const message =
|
|
174
|
+
const message = createProviderStreamError(model, error, stopReason);
|
|
304
175
|
target.push({ type: "error", reason: stopReason, error: message });
|
|
305
176
|
target.end(message);
|
|
306
177
|
}
|
|
307
178
|
})();
|
|
308
179
|
}
|
|
309
180
|
|
|
310
|
-
function
|
|
181
|
+
function createProviderStreamError<TApi extends Api>(
|
|
311
182
|
model: Model<TApi>,
|
|
312
183
|
error: unknown,
|
|
313
184
|
stopReason: Extract<AssistantMessage["stopReason"], "aborted" | "error"> = "error",
|
|
@@ -335,173 +206,95 @@ function createLazyLoadErrorMessage<TApi extends Api>(
|
|
|
335
206
|
}
|
|
336
207
|
|
|
337
208
|
// ---------------------------------------------------------------------------
|
|
338
|
-
//
|
|
209
|
+
// Provider stream wrapper
|
|
339
210
|
// ---------------------------------------------------------------------------
|
|
340
211
|
|
|
341
|
-
function
|
|
342
|
-
|
|
343
|
-
limits?:
|
|
212
|
+
function createProviderStream<TApi extends Api>(
|
|
213
|
+
stream: ProviderStream<TApi>,
|
|
214
|
+
limits?: StreamLimits,
|
|
344
215
|
): (model: Model<TApi>, context: Context, options: OptionsForApi<TApi>) => EventStreamImpl {
|
|
345
216
|
return (model, context, options) => {
|
|
346
217
|
const outer = new EventStreamImpl();
|
|
347
|
-
const streamOptions =
|
|
218
|
+
const streamOptions: OptionsForApi<TApi> = options ?? {};
|
|
348
219
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
outer.end(message);
|
|
360
|
-
});
|
|
220
|
+
try {
|
|
221
|
+
const abortTracker = createAbortSourceTracker(streamOptions.signal);
|
|
222
|
+
const providerOptions: OptionsForApi<TApi> = { ...streamOptions, signal: abortTracker.requestSignal };
|
|
223
|
+
const inner = stream(model, context, providerOptions);
|
|
224
|
+
forwardStream(outer, inner, model, streamOptions, abortTracker, limits);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
const message = createProviderStreamError(model, error);
|
|
227
|
+
outer.push({ type: "error", reason: "error", error: message });
|
|
228
|
+
outer.end(message);
|
|
229
|
+
}
|
|
361
230
|
|
|
362
231
|
return outer;
|
|
363
232
|
};
|
|
364
233
|
}
|
|
365
234
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
anthropicProviderModulePromise ||= import("./anthropic").then(module => {
|
|
372
|
-
const provider = module as AnthropicProviderModule;
|
|
373
|
-
return { stream: provider.streamAnthropic };
|
|
374
|
-
});
|
|
375
|
-
return anthropicProviderModulePromise;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function loadAzureOpenAIResponsesProviderModule(): Promise<LazyProviderModule<"azure-openai-responses">> {
|
|
379
|
-
azureOpenAIResponsesProviderModulePromise ||= import("./azure-openai-responses").then(module => {
|
|
380
|
-
const provider = module as AzureOpenAIResponsesProviderModule;
|
|
381
|
-
return { stream: provider.streamAzureOpenAIResponses };
|
|
382
|
-
});
|
|
383
|
-
return azureOpenAIResponsesProviderModulePromise;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
function loadGoogleProviderModule(): Promise<LazyProviderModule<"google-generative-ai">> {
|
|
387
|
-
googleProviderModulePromise ||= import("./google").then(module => {
|
|
388
|
-
const provider = module as GoogleProviderModule;
|
|
389
|
-
return { stream: provider.streamGoogle };
|
|
390
|
-
});
|
|
391
|
-
return googleProviderModulePromise;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
function loadGoogleGeminiCliProviderModule(): Promise<LazyProviderModule<"google-gemini-cli">> {
|
|
395
|
-
googleGeminiCliProviderModulePromise ||= import("./google-gemini-cli").then(module => {
|
|
396
|
-
const provider = module as GoogleGeminiCliProviderModule;
|
|
397
|
-
return { stream: provider.streamGoogleGeminiCli };
|
|
398
|
-
});
|
|
399
|
-
return googleGeminiCliProviderModulePromise;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function loadGoogleVertexProviderModule(): Promise<LazyProviderModule<"google-vertex">> {
|
|
403
|
-
googleVertexProviderModulePromise ||= import("./google-vertex").then(module => {
|
|
404
|
-
const provider = module as GoogleVertexProviderModule;
|
|
405
|
-
return { stream: provider.streamGoogleVertex };
|
|
406
|
-
});
|
|
407
|
-
return googleVertexProviderModulePromise;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
function loadOpenAICodexResponsesProviderModule(): Promise<LazyProviderModule<"openai-codex-responses">> {
|
|
411
|
-
openAICodexResponsesProviderModulePromise ||= import("./openai-codex-responses").then(module => {
|
|
412
|
-
const provider = module as OpenAICodexResponsesProviderModule;
|
|
413
|
-
return { stream: provider.streamOpenAICodexResponses };
|
|
414
|
-
});
|
|
415
|
-
return openAICodexResponsesProviderModulePromise;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
function loadOpenAICompletionsProviderModule(): Promise<LazyProviderModule<"openai-completions">> {
|
|
419
|
-
openAICompletionsProviderModulePromise ||= import("./openai-completions").then(module => {
|
|
420
|
-
const provider = module as OpenAICompletionsProviderModule;
|
|
421
|
-
return { stream: provider.streamOpenAICompletions };
|
|
422
|
-
});
|
|
423
|
-
return openAICompletionsProviderModulePromise;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
function loadOpenAIResponsesProviderModule(): Promise<LazyProviderModule<"openai-responses">> {
|
|
427
|
-
openAIResponsesProviderModulePromise ||= import("./openai-responses").then(module => {
|
|
428
|
-
const provider = module as OpenAIResponsesProviderModule;
|
|
429
|
-
return { stream: provider.streamOpenAIResponses };
|
|
430
|
-
});
|
|
431
|
-
return openAIResponsesProviderModulePromise;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
function loadOllamaProviderModule(): Promise<LazyProviderModule<"ollama-chat">> {
|
|
435
|
-
ollamaProviderModulePromise ||= import("./ollama").then(module => {
|
|
436
|
-
const provider = module as OllamaProviderModule;
|
|
437
|
-
return { stream: provider.streamOllama };
|
|
438
|
-
});
|
|
439
|
-
return ollamaProviderModulePromise;
|
|
440
|
-
}
|
|
235
|
+
/** Stream Anthropic responses with provider-owned timeout handling. */
|
|
236
|
+
export const streamAnthropic = createProviderStream<"anthropic-messages">(
|
|
237
|
+
(model, context, options) => AnthropicProvider.streamAnthropic(model, context, options),
|
|
238
|
+
PROVIDER_HANDLED_STREAM_TIMEOUTS,
|
|
239
|
+
);
|
|
441
240
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
const provider = module as CursorProviderModule;
|
|
448
|
-
return { stream: provider.streamCursor };
|
|
449
|
-
});
|
|
450
|
-
return cursorProviderModulePromise;
|
|
451
|
-
}
|
|
241
|
+
/** Stream Azure Responses with provider-owned timeout handling. */
|
|
242
|
+
export const streamAzureOpenAIResponses = createProviderStream<"azure-openai-responses">(
|
|
243
|
+
(model, context, options) => AzureOpenAIResponsesProvider.streamAzureOpenAIResponses(model, context, options),
|
|
244
|
+
PROVIDER_HANDLED_STREAM_TIMEOUTS,
|
|
245
|
+
);
|
|
452
246
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
});
|
|
458
|
-
return devinProviderModulePromise;
|
|
459
|
-
}
|
|
247
|
+
/** Stream Google's direct API through the shared watchdog. */
|
|
248
|
+
export const streamGoogle = createProviderStream<"google-generative-ai">((model, context, options) =>
|
|
249
|
+
GoogleProvider.streamGoogle(model, context, options),
|
|
250
|
+
);
|
|
460
251
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const provider = module as BedrockProviderModule;
|
|
467
|
-
return { stream: provider.streamBedrock };
|
|
468
|
-
});
|
|
469
|
-
return bedrockProviderModulePromise;
|
|
470
|
-
}
|
|
252
|
+
/** Stream Cloud Code Assist while retaining its first-event watchdog. */
|
|
253
|
+
export const streamGoogleGeminiCli = createProviderStream<"google-gemini-cli">(
|
|
254
|
+
(model, context, options) => GoogleGeminiCliProvider.streamGoogleGeminiCli(model, context, options),
|
|
255
|
+
GOOGLE_GEMINI_CLI_STREAM_LIMITS,
|
|
256
|
+
);
|
|
471
257
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
// stream.ts is updated to import from this module instead of individual
|
|
477
|
-
// providers, the lazy loading will take effect on the main code path.
|
|
478
|
-
// ---------------------------------------------------------------------------
|
|
258
|
+
/** Stream the Vertex API through the shared watchdog. */
|
|
259
|
+
export const streamGoogleVertex = createProviderStream<"google-vertex">((model, context, options) =>
|
|
260
|
+
GoogleVertexProvider.streamGoogleVertex(model, context, options),
|
|
261
|
+
);
|
|
479
262
|
|
|
480
|
-
|
|
481
|
-
export const
|
|
482
|
-
|
|
263
|
+
/** Stream Codex with provider-owned timeout handling. */
|
|
264
|
+
export const streamOpenAICodexResponses = createProviderStream<"openai-codex-responses">(
|
|
265
|
+
(model, context, options) => OpenAICodexResponsesProvider.streamOpenAICodexResponses(model, context, options),
|
|
483
266
|
PROVIDER_HANDLED_STREAM_TIMEOUTS,
|
|
484
267
|
);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
);
|
|
490
|
-
export const streamGoogleVertex = createLazyStream(loadGoogleVertexProviderModule);
|
|
491
|
-
export const streamOpenAICodexResponses = createLazyStream(
|
|
492
|
-
loadOpenAICodexResponsesProviderModule,
|
|
268
|
+
|
|
269
|
+
/** Stream Chat Completions with provider-owned timeout handling. */
|
|
270
|
+
export const streamOpenAICompletions = createProviderStream<"openai-completions">(
|
|
271
|
+
(model, context, options) => OpenAICompletionsProvider.streamOpenAICompletions(model, context, options),
|
|
493
272
|
PROVIDER_HANDLED_STREAM_TIMEOUTS,
|
|
494
273
|
);
|
|
495
|
-
|
|
496
|
-
|
|
274
|
+
|
|
275
|
+
/** Stream Responses with provider-owned timeout handling. */
|
|
276
|
+
export const streamOpenAIResponses = createProviderStream<"openai-responses">(
|
|
277
|
+
(model, context, options) => OpenAIResponsesProvider.streamOpenAIResponses(model, context, options),
|
|
497
278
|
PROVIDER_HANDLED_STREAM_TIMEOUTS,
|
|
498
279
|
);
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
280
|
+
|
|
281
|
+
/** Stream through the host Cursor transport when installed, otherwise the built-in transport. */
|
|
282
|
+
export const streamCursor = createProviderStream<"cursor-agent">((model, context, options) =>
|
|
283
|
+
(cursorStreamOverride ?? CursorProvider.streamCursor)(model, context, options),
|
|
502
284
|
);
|
|
503
|
-
export const streamCursor = createLazyStream(loadCursorProviderModule);
|
|
504
|
-
export const streamDevin = createLazyStream(loadDevinProviderModule);
|
|
505
|
-
export const streamOllama = createLazyStream(loadOllamaProviderModule, OPENAI_IDLE_FLOORED_LAZY_STREAM_LIMITS);
|
|
506
285
|
|
|
507
|
-
|
|
286
|
+
/** Stream Devin through the shared watchdog. */
|
|
287
|
+
export const streamDevin = createProviderStream<"devin-agent">((model, context, options) =>
|
|
288
|
+
DevinProvider.streamDevin(model, context, options),
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
/** Stream Ollama with OpenAI-compatible idle timeout precedence. */
|
|
292
|
+
export const streamOllama = createProviderStream<"ollama-chat">(
|
|
293
|
+
(model, context, options) => OllamaProvider.streamOllama(model, context, options),
|
|
294
|
+
OPENAI_IDLE_FLOORED_STREAM_LIMITS,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
/** Stream through the host Bedrock transport when installed, otherwise the built-in transport. */
|
|
298
|
+
export const streamBedrock = createProviderStream<"bedrock-converse-stream">((model, context, options) =>
|
|
299
|
+
(bedrockStreamOverride ?? BedrockProvider.streamBedrock)(model, context, options),
|
|
300
|
+
);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @see https://dev.synthetic.new/docs/api/overview
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { Context, Model } from "../types";
|
|
12
12
|
import type { AssistantMessageEventStream } from "../utils/event-stream";
|
|
13
13
|
import {
|
|
14
14
|
type OpenAIAnthropicApiFormat,
|
|
@@ -41,10 +41,3 @@ export function streamSynthetic(
|
|
|
41
41
|
defaultFormat: "openai",
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Check if a model is a Synthetic model.
|
|
47
|
-
*/
|
|
48
|
-
export function isSyntheticModel(model: Model<Api>): boolean {
|
|
49
|
-
return model.provider === "synthetic";
|
|
50
|
-
}
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
parseCloudflareAiGatewayCredential,
|
|
9
9
|
} from "@oh-my-pi/pi-catalog/wire/cloudflare-ai-gateway";
|
|
10
10
|
import { $env } from "@oh-my-pi/pi-utils";
|
|
11
|
+
import { NO_AUTH_SENTINEL } from "../auth-retry";
|
|
11
12
|
import * as AIError from "../error";
|
|
12
|
-
import { NO_AUTH_SENTINEL } from "../providers/openai-shared";
|
|
13
13
|
import type { ProviderTransport } from "./build";
|
|
14
14
|
|
|
15
15
|
/** Cloudflare AI Gateway model/request shaping; login lives in `oauth/cloudflare-ai-gateway.ts` + its auth rule. */
|
package/src/stream.ts
CHANGED
|
@@ -26,24 +26,17 @@ import type { AnthropicOptions } from "./providers/anthropic";
|
|
|
26
26
|
import type { MessageCreateParamsStreaming } from "./providers/anthropic-wire";
|
|
27
27
|
import type { CursorOptions } from "./providers/cursor";
|
|
28
28
|
import type { DevinOptions } from "./providers/devin";
|
|
29
|
-
import {
|
|
29
|
+
import { streamGitLabDuo } from "./providers/gitlab-duo";
|
|
30
30
|
import { type GitLabDuoWorkflowOptions, streamGitLabDuoWorkflow } from "./providers/gitlab-duo-workflow";
|
|
31
31
|
import type { GoogleOptions } from "./providers/google";
|
|
32
32
|
import { getVertexAccessToken } from "./providers/google-auth";
|
|
33
33
|
import type { GoogleGeminiCliOptions } from "./providers/google-gemini-cli";
|
|
34
34
|
import type { GoogleVertexOptions } from "./providers/google-vertex";
|
|
35
|
-
import {
|
|
35
|
+
import { streamKimi } from "./providers/kimi";
|
|
36
36
|
import type { OllamaChatOptions } from "./providers/ollama";
|
|
37
37
|
import type { OpenAICompletionsOptions } from "./providers/openai-completions";
|
|
38
38
|
import { streamPiNative } from "./providers/pi-native-client";
|
|
39
|
-
|
|
40
|
-
// which wraps each provider module in a dynamic import. This keeps the
|
|
41
|
-
// AWS SDK, google-auth-library, @google/genai, and
|
|
42
|
-
// other provider SDKs out of the CLI startup parse graph. The
|
|
43
|
-
// gitlab-duo / kimi / synthetic providers stay eager because their modules
|
|
44
|
-
// export routing predicates (isGitLabDuoModel, isKimiModel, isSyntheticModel)
|
|
45
|
-
// that must be callable synchronously before streaming begins, and their
|
|
46
|
-
// modules are thin wrappers with no heavy SDK dependencies.
|
|
39
|
+
import { streamSynthetic } from "./providers/synthetic";
|
|
47
40
|
import {
|
|
48
41
|
streamAnthropic,
|
|
49
42
|
streamAzureOpenAIResponses,
|
|
@@ -58,7 +51,6 @@ import {
|
|
|
58
51
|
streamOpenAICompletions,
|
|
59
52
|
streamOpenAIResponses,
|
|
60
53
|
} from "./providers/register-builtins";
|
|
61
|
-
import { isSyntheticModel, streamSynthetic } from "./providers/synthetic";
|
|
62
54
|
import { getProviderDefinition, PROVIDER_REGISTRY } from "./registry";
|
|
63
55
|
import type {
|
|
64
56
|
Api,
|
|
@@ -953,7 +945,7 @@ function streamDispatch<TApi extends Api>(
|
|
|
953
945
|
return customApiProvider.stream(model, context, requestOptions as StreamOptions);
|
|
954
946
|
}
|
|
955
947
|
|
|
956
|
-
if (
|
|
948
|
+
if (model.provider === "gitlab-duo") {
|
|
957
949
|
const apiKey = requestOptions.apiKey || getEnvApiKey(model.provider);
|
|
958
950
|
if (!apiKey) {
|
|
959
951
|
throw new AIError.MissingApiKeyError(model.provider);
|
|
@@ -1725,7 +1717,7 @@ function streamSimpleRequest<TApi extends Api>(
|
|
|
1725
1717
|
}
|
|
1726
1718
|
|
|
1727
1719
|
// GitLab Duo - wraps Anthropic/OpenAI behind GitLab AI Gateway direct access tokens
|
|
1728
|
-
if (
|
|
1720
|
+
if (model.provider === "gitlab-duo") {
|
|
1729
1721
|
return withThinkingLoopGuard(model, requestOptions, opts =>
|
|
1730
1722
|
withProviderInFlightLimit(model, opts, () =>
|
|
1731
1723
|
streamGitLabDuo(model, context, {
|
|
@@ -1751,7 +1743,7 @@ function streamSimpleRequest<TApi extends Api>(
|
|
|
1751
1743
|
}
|
|
1752
1744
|
|
|
1753
1745
|
// Kimi Code - route to dedicated handler that wraps OpenAI or Anthropic API
|
|
1754
|
-
if (
|
|
1746
|
+
if (model.provider === "kimi-code") {
|
|
1755
1747
|
// streamKimi handles openai/anthropic format mapping internally, but the
|
|
1756
1748
|
// mandatory-reasoning clamp is a request-shaping concern owned here: K3's
|
|
1757
1749
|
// `supports_thinking_type: "only"` endpoint rejects disabled/omitted
|
|
@@ -1770,7 +1762,7 @@ function streamSimpleRequest<TApi extends Api>(
|
|
|
1770
1762
|
}
|
|
1771
1763
|
|
|
1772
1764
|
// Synthetic - route to dedicated handler that wraps OpenAI or Anthropic API
|
|
1773
|
-
if (
|
|
1765
|
+
if (model.provider === "synthetic") {
|
|
1774
1766
|
// Pass raw SimpleStreamOptions - streamSynthetic handles mapping internally.
|
|
1775
1767
|
return withThinkingLoopGuard(model, requestOptions, opts =>
|
|
1776
1768
|
withProviderInFlightLimit(model, opts, () =>
|