@opencode-ai/ai 0.0.0-beta-17793 → 0.0.0-beta-17887
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/protocols/gemini.js +35 -9
- package/dist/protocols/open-responses-channel.d.ts +2 -0
- package/dist/protocols/open-responses-channel.js +2 -2
- package/dist/protocols/openai-images.js +1 -1
- package/dist/protocols/openai-responses.d.ts +136 -0
- package/dist/protocols/openai-responses.js +5 -2
- package/dist/protocols/utils/image-input.js +1 -1
- package/dist/protocols/utils/lifecycle.d.ts +1 -1
- package/dist/protocols/utils/lifecycle.js +2 -2
- package/dist/providers/azure.js +25 -0
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +6 -1
- package/package.json +3 -3
package/dist/protocols/gemini.js
CHANGED
|
@@ -26,6 +26,9 @@ const requiresThoughtSignatureFallback = (modelID) => {
|
|
|
26
26
|
return false;
|
|
27
27
|
return !/(^|\/)gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelID);
|
|
28
28
|
};
|
|
29
|
+
// Gemini 3 accepts media nested inside function responses; matched Gemini 2.5 variants reject it,
|
|
30
|
+
// so their tool-result attachments lower as a separate user turn instead.
|
|
31
|
+
const routesLegacyToolMedia = (modelID) => /gemini-2[.-]5(?:[.-]|$)/i.test(modelID);
|
|
29
32
|
// =============================================================================
|
|
30
33
|
// Request Body Schema
|
|
31
34
|
// =============================================================================
|
|
@@ -197,7 +200,17 @@ const lowerToolCall = (part) => ({
|
|
|
197
200
|
});
|
|
198
201
|
const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
199
202
|
const contents = [];
|
|
203
|
+
const legacyToolMedia = routesLegacyToolMedia(request.model.id);
|
|
204
|
+
let pendingMedia;
|
|
205
|
+
const flushMedia = () => {
|
|
206
|
+
if (!pendingMedia)
|
|
207
|
+
return;
|
|
208
|
+
contents.push({ role: "user", parts: [{ text: "Attached media from tool result:" }, ...pendingMedia] });
|
|
209
|
+
pendingMedia = undefined;
|
|
210
|
+
};
|
|
200
211
|
for (const message of request.messages) {
|
|
212
|
+
if (message.role !== "tool")
|
|
213
|
+
flushMedia();
|
|
201
214
|
if (message.role === "system") {
|
|
202
215
|
const part = yield* ProviderShared.wrappedSystemUpdate("Gemini", message);
|
|
203
216
|
const previous = contents.at(-1);
|
|
@@ -227,7 +240,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
227
240
|
if (!ProviderShared.supportsContent(part, ["text", "reasoning", "tool-call"]))
|
|
228
241
|
return yield* ProviderShared.unsupportedContent("Gemini", "assistant", ["text", "reasoning", "tool-call"]);
|
|
229
242
|
if (part.type === "text") {
|
|
230
|
-
parts.push({ text: part.text });
|
|
243
|
+
parts.push({ text: part.text, thoughtSignature: thoughtSignature(part.providerMetadata) });
|
|
231
244
|
continue;
|
|
232
245
|
}
|
|
233
246
|
if (part.type === "reasoning") {
|
|
@@ -278,6 +291,8 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
278
291
|
const value = ProviderShared.normalizeToolFile(item);
|
|
279
292
|
media.push({ inlineData: { mimeType: value.mime, data: value.base64 } });
|
|
280
293
|
}
|
|
294
|
+
if (legacyToolMedia && media.length > 0)
|
|
295
|
+
(pendingMedia ??= []).push(...media);
|
|
281
296
|
parts.push({
|
|
282
297
|
functionResponse: {
|
|
283
298
|
id: functionCallId(part.providerMetadata),
|
|
@@ -286,7 +301,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
286
301
|
name: part.name,
|
|
287
302
|
content: text.join("\n"),
|
|
288
303
|
},
|
|
289
|
-
parts: media.length
|
|
304
|
+
parts: legacyToolMedia || media.length === 0 ? undefined : media,
|
|
290
305
|
},
|
|
291
306
|
});
|
|
292
307
|
}
|
|
@@ -298,6 +313,7 @@ const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
|
|
|
298
313
|
else
|
|
299
314
|
contents.push({ role: "user", parts });
|
|
300
315
|
}
|
|
316
|
+
flushMedia();
|
|
301
317
|
return contents;
|
|
302
318
|
});
|
|
303
319
|
const resolveOptions = (request) => {
|
|
@@ -422,9 +438,11 @@ const finish = (state) => {
|
|
|
422
438
|
if (finishReason === undefined && state.usage === undefined)
|
|
423
439
|
return [];
|
|
424
440
|
const events = [];
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
: state.
|
|
441
|
+
let lifecycle = state.lifecycle;
|
|
442
|
+
if (state.reasoningSignature !== undefined)
|
|
443
|
+
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", googleMetadata({ thoughtSignature: state.reasoningSignature }));
|
|
444
|
+
if (state.textSignature !== undefined)
|
|
445
|
+
lifecycle = Lifecycle.textEnd(lifecycle, events, "text-0", googleMetadata({ thoughtSignature: state.textSignature }));
|
|
428
446
|
Lifecycle.finish(lifecycle, events, {
|
|
429
447
|
reason: {
|
|
430
448
|
normalized: promptBlockReason === undefined ? mapFinishReason(finishReason, state.hasToolCalls) : "content-filter",
|
|
@@ -452,16 +470,23 @@ const step = (state, event) => {
|
|
|
452
470
|
let lifecycle = nextState.lifecycle;
|
|
453
471
|
let nextToolCallId = nextState.nextToolCallId;
|
|
454
472
|
let reasoningSignature = nextState.reasoningSignature;
|
|
473
|
+
let textSignature = nextState.textSignature;
|
|
455
474
|
for (const part of candidate.content.parts) {
|
|
456
|
-
|
|
457
|
-
|
|
475
|
+
const signature = "thoughtSignature" in part && part.thoughtSignature ? part.thoughtSignature : undefined;
|
|
476
|
+
// Gemini attaches replay signatures to thought parts, visible text, or function calls;
|
|
477
|
+
// each block kind must retain the signature attached to its own parts.
|
|
478
|
+
if (signature !== undefined && "thought" in part && part.thought)
|
|
479
|
+
reasoningSignature = signature;
|
|
480
|
+
else if (signature !== undefined && "text" in part)
|
|
481
|
+
textSignature = signature;
|
|
458
482
|
if ("text" in part && part.text.length > 0) {
|
|
459
483
|
if (part.thought) {
|
|
460
|
-
lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", part.text,
|
|
484
|
+
lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", part.text, signature ? googleMetadata({ thoughtSignature: signature }) : undefined);
|
|
461
485
|
continue;
|
|
462
486
|
}
|
|
463
487
|
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningSignature ? googleMetadata({ thoughtSignature: reasoningSignature }) : undefined);
|
|
464
|
-
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", part.text);
|
|
488
|
+
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", part.text, textSignature ? googleMetadata({ thoughtSignature: textSignature }) : undefined);
|
|
489
|
+
textSignature = undefined;
|
|
465
490
|
continue;
|
|
466
491
|
}
|
|
467
492
|
if ("functionCall" in part) {
|
|
@@ -489,6 +514,7 @@ const step = (state, event) => {
|
|
|
489
514
|
lifecycle,
|
|
490
515
|
nextToolCallId,
|
|
491
516
|
reasoningSignature,
|
|
517
|
+
textSignature,
|
|
492
518
|
finishReason: candidate.finishReason ?? nextState.finishReason,
|
|
493
519
|
},
|
|
494
520
|
events,
|
|
@@ -4,6 +4,8 @@ export interface Options {
|
|
|
4
4
|
readonly id: string;
|
|
5
5
|
readonly name: string;
|
|
6
6
|
readonly rotateAfterMs?: number;
|
|
7
|
+
readonly enabled?: (url: string) => boolean;
|
|
8
|
+
readonly url?: (url: string) => string;
|
|
7
9
|
readonly headers?: (headers: Headers.Headers) => Headers.Headers;
|
|
8
10
|
readonly driver?: (input: {
|
|
9
11
|
readonly request: Readonly<Record<string, unknown>>;
|
|
@@ -79,12 +79,12 @@ export const transport = (options) => {
|
|
|
79
79
|
prepare: (input) => Effect.gen(function* () {
|
|
80
80
|
const parts = yield* HttpTransport.jsonRequestParts(input);
|
|
81
81
|
const headers = Headers.remove(options.headers?.(parts.headers) ?? parts.headers, "content-length");
|
|
82
|
-
const channel = input.webSocket
|
|
82
|
+
const channel = input.webSocket && (options.enabled?.(parts.url) ?? true)
|
|
83
83
|
? yield* Effect.gen(function* () {
|
|
84
84
|
const create = yield* message(parts.jsonBody);
|
|
85
85
|
const base = driver(options, create.message);
|
|
86
86
|
return {
|
|
87
|
-
url: yield* WebSocketTransport.toWebSocketUrl(parts.url),
|
|
87
|
+
url: yield* WebSocketTransport.toWebSocketUrl(options.url?.(parts.url) ?? parts.url),
|
|
88
88
|
headers,
|
|
89
89
|
rotateAfterMs: options.rotateAfterMs,
|
|
90
90
|
driver: options.driver?.({ request: create.request, message: create.message, base }) ?? base,
|
|
@@ -61,7 +61,7 @@ export const model = (input) => {
|
|
|
61
61
|
return Effect.succeed({ data: image.data, mediaType: image.mediaType });
|
|
62
62
|
if (image.type === "url")
|
|
63
63
|
return ImageInputs.decodeDataUrl(image.url, ADAPTER);
|
|
64
|
-
return Effect.
|
|
64
|
+
return Effect.undefined;
|
|
65
65
|
});
|
|
66
66
|
const multipartMask = mask === undefined
|
|
67
67
|
? undefined
|
|
@@ -3,6 +3,7 @@ import { Route } from "../route/client.js";
|
|
|
3
3
|
import { Protocol } from "../route/protocol.js";
|
|
4
4
|
import { HttpTransport } from "../route/transport/index.js";
|
|
5
5
|
import { OpenResponses } from "./open-responses.js";
|
|
6
|
+
import { type Options } from "./open-responses-channel.js";
|
|
6
7
|
export declare const DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
7
8
|
export declare const PATH = "/responses";
|
|
8
9
|
declare const OpenAIResponsesBody: Schema.Struct<{
|
|
@@ -461,6 +462,141 @@ export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
|
461
462
|
readonly max_tool_calls?: number | undefined;
|
|
462
463
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
463
464
|
}, string>;
|
|
465
|
+
export declare const channelTransport: (options: Omit<Options, "driver">) => import("../route/transport/index.js").Transport<{
|
|
466
|
+
readonly input: readonly ({
|
|
467
|
+
readonly type: "reasoning";
|
|
468
|
+
readonly summary: readonly {
|
|
469
|
+
readonly type: "summary_text";
|
|
470
|
+
readonly text: string;
|
|
471
|
+
}[];
|
|
472
|
+
readonly id?: string | undefined;
|
|
473
|
+
readonly encrypted_content?: string | null | undefined;
|
|
474
|
+
} | {
|
|
475
|
+
readonly type: "item_reference";
|
|
476
|
+
readonly id: string;
|
|
477
|
+
} | {
|
|
478
|
+
readonly role: "system";
|
|
479
|
+
readonly content: string;
|
|
480
|
+
} | {
|
|
481
|
+
readonly role: "developer";
|
|
482
|
+
readonly content: string;
|
|
483
|
+
} | {
|
|
484
|
+
readonly role: "user";
|
|
485
|
+
readonly content: readonly ({
|
|
486
|
+
readonly type: "input_image";
|
|
487
|
+
readonly image_url: string;
|
|
488
|
+
} | {
|
|
489
|
+
readonly type: "input_file";
|
|
490
|
+
readonly filename: string;
|
|
491
|
+
readonly file_data: string;
|
|
492
|
+
readonly mime_type?: string | undefined;
|
|
493
|
+
} | {
|
|
494
|
+
readonly type: "input_text";
|
|
495
|
+
readonly text: string;
|
|
496
|
+
})[];
|
|
497
|
+
} | {
|
|
498
|
+
readonly type: "message";
|
|
499
|
+
readonly content: readonly {
|
|
500
|
+
readonly type: "output_text";
|
|
501
|
+
readonly text: string;
|
|
502
|
+
}[];
|
|
503
|
+
readonly role: "assistant";
|
|
504
|
+
readonly id?: string | undefined;
|
|
505
|
+
readonly phase?: "commentary" | "final_answer" | undefined;
|
|
506
|
+
} | {
|
|
507
|
+
readonly type: "function_call";
|
|
508
|
+
readonly name: string;
|
|
509
|
+
readonly arguments: string;
|
|
510
|
+
readonly call_id: string;
|
|
511
|
+
readonly id?: string | undefined;
|
|
512
|
+
} | {
|
|
513
|
+
readonly type: "function_call_output";
|
|
514
|
+
readonly call_id: string;
|
|
515
|
+
readonly output: string | readonly ({
|
|
516
|
+
readonly type: "input_image";
|
|
517
|
+
readonly image_url: string;
|
|
518
|
+
} | {
|
|
519
|
+
readonly type: "input_file";
|
|
520
|
+
readonly filename: string;
|
|
521
|
+
readonly file_data: string;
|
|
522
|
+
readonly mime_type?: string | undefined;
|
|
523
|
+
} | {
|
|
524
|
+
readonly type: "input_text";
|
|
525
|
+
readonly text: string;
|
|
526
|
+
})[];
|
|
527
|
+
} | {
|
|
528
|
+
readonly type: "message";
|
|
529
|
+
readonly content: readonly {
|
|
530
|
+
readonly type: "output_text";
|
|
531
|
+
readonly text: string;
|
|
532
|
+
}[];
|
|
533
|
+
readonly role: "assistant";
|
|
534
|
+
readonly id?: string | undefined;
|
|
535
|
+
readonly phase?: "commentary" | "final_answer" | null | undefined;
|
|
536
|
+
})[];
|
|
537
|
+
readonly model: string;
|
|
538
|
+
readonly stream: true;
|
|
539
|
+
readonly metadata?: {
|
|
540
|
+
readonly [x: string]: string;
|
|
541
|
+
} | undefined;
|
|
542
|
+
readonly instructions?: string | undefined;
|
|
543
|
+
readonly reasoning?: {
|
|
544
|
+
readonly summary?: "auto" | "concise" | "detailed" | undefined;
|
|
545
|
+
readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
|
|
546
|
+
} | undefined;
|
|
547
|
+
readonly tools?: readonly ({
|
|
548
|
+
readonly type: "function";
|
|
549
|
+
readonly description: string;
|
|
550
|
+
readonly name: string;
|
|
551
|
+
readonly parameters: {
|
|
552
|
+
readonly [x: string]: unknown;
|
|
553
|
+
};
|
|
554
|
+
readonly strict?: boolean | undefined;
|
|
555
|
+
} | {
|
|
556
|
+
readonly type: "image_generation";
|
|
557
|
+
readonly size?: string | undefined;
|
|
558
|
+
readonly action?: "generate" | "auto" | "edit" | undefined;
|
|
559
|
+
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
|
|
560
|
+
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
|
|
561
|
+
readonly background?: "auto" | "opaque" | "transparent" | undefined;
|
|
562
|
+
readonly output_compression?: number | undefined;
|
|
563
|
+
readonly input_fidelity?: "low" | "high" | undefined;
|
|
564
|
+
readonly partial_images?: number | undefined;
|
|
565
|
+
})[] | undefined;
|
|
566
|
+
readonly text?: {
|
|
567
|
+
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
|
|
568
|
+
} | undefined;
|
|
569
|
+
readonly temperature?: number | undefined;
|
|
570
|
+
readonly tool_choice?: "required" | "auto" | "none" | {
|
|
571
|
+
readonly type: "function";
|
|
572
|
+
readonly name: string;
|
|
573
|
+
} | {
|
|
574
|
+
readonly type: "allowed_tools";
|
|
575
|
+
readonly mode: "required" | "auto" | "none";
|
|
576
|
+
readonly tools: readonly {
|
|
577
|
+
readonly type: "function";
|
|
578
|
+
readonly name: string;
|
|
579
|
+
}[];
|
|
580
|
+
} | {
|
|
581
|
+
readonly type: "image_generation";
|
|
582
|
+
} | undefined;
|
|
583
|
+
readonly top_p?: number | undefined;
|
|
584
|
+
readonly store?: boolean | undefined;
|
|
585
|
+
readonly include?: readonly import("./utils/open-responses-options.js").ResponseIncludable[] | undefined;
|
|
586
|
+
readonly truncation?: "auto" | "disabled" | undefined;
|
|
587
|
+
readonly stream_options?: {
|
|
588
|
+
readonly include_obfuscation?: boolean | undefined;
|
|
589
|
+
} | undefined;
|
|
590
|
+
readonly prompt_cache_key?: string | undefined;
|
|
591
|
+
readonly frequency_penalty?: number | undefined;
|
|
592
|
+
readonly presence_penalty?: number | undefined;
|
|
593
|
+
readonly safety_identifier?: string | undefined;
|
|
594
|
+
readonly top_logprobs?: number | undefined;
|
|
595
|
+
readonly service_tier?: "default" | "auto" | "flex" | "priority" | undefined;
|
|
596
|
+
readonly max_output_tokens?: number | undefined;
|
|
597
|
+
readonly max_tool_calls?: number | undefined;
|
|
598
|
+
readonly parallel_tool_calls?: boolean | undefined;
|
|
599
|
+
}, import("./open-responses-channel.js").Prepared, string>;
|
|
464
600
|
export declare const transport: import("../route/transport/index.js").Transport<{
|
|
465
601
|
readonly input: readonly ({
|
|
466
602
|
readonly type: "reasoning";
|
|
@@ -190,12 +190,15 @@ export const protocol = Protocol.make({
|
|
|
190
190
|
const endpoint = Endpoint.path(PATH, { baseURL: DEFAULT_BASE_URL });
|
|
191
191
|
const auth = Auth.none;
|
|
192
192
|
export const httpTransport = HttpTransport.sseJson.with();
|
|
193
|
-
export const
|
|
193
|
+
export const channelTransport = (options) => OpenResponsesChannel.transport({
|
|
194
|
+
...options,
|
|
195
|
+
driver: (input) => OpenAIResponsesChannel.driver({ id: options.id, name: options.name, ...input }),
|
|
196
|
+
});
|
|
197
|
+
export const transport = channelTransport({
|
|
194
198
|
id: ADAPTER,
|
|
195
199
|
name: NAME,
|
|
196
200
|
rotateAfterMs: WEBSOCKET_ROTATE_AFTER_MS,
|
|
197
201
|
headers: (headers) => Headers.set(headers, "openai-beta", headers["openai-beta"] ?? WEBSOCKET_PROTOCOL_HEADER),
|
|
198
|
-
driver: (input) => OpenAIResponsesChannel.driver({ id: ADAPTER, name: NAME, ...input }),
|
|
199
202
|
});
|
|
200
203
|
export const route = Route.make({
|
|
201
204
|
id: ADAPTER,
|
|
@@ -8,7 +8,7 @@ const invalid = (module, message) => new AIError({
|
|
|
8
8
|
export const dataUrl = (input) => `data:${input.mediaType};base64,${Encoding.encodeBase64(input.data)}`;
|
|
9
9
|
export const decodeDataUrl = (url, module) => {
|
|
10
10
|
if (!url.startsWith("data:"))
|
|
11
|
-
return Effect.
|
|
11
|
+
return Effect.undefined;
|
|
12
12
|
const match = /^data:([^;,]+);base64,(.*)$/s.exec(url);
|
|
13
13
|
if (!match)
|
|
14
14
|
return Effect.fail(invalid(module, "Image data URLs must contain a MIME type and base64 data"));
|
|
@@ -7,7 +7,7 @@ export interface State {
|
|
|
7
7
|
export declare const initial: () => State;
|
|
8
8
|
export declare const stepStart: (state: State, events: LLMEvent[]) => State;
|
|
9
9
|
export declare const textStart: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata) => State;
|
|
10
|
-
export declare const textDelta: (state: State, events: LLMEvent[], id: string, text: string) => State;
|
|
10
|
+
export declare const textDelta: (state: State, events: LLMEvent[], id: string, text: string, providerMetadata?: ProviderMetadata) => State;
|
|
11
11
|
export declare const reasoningStart: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata) => State;
|
|
12
12
|
export declare const reasoningDelta: (state: State, events: LLMEvent[], id: string, text: string, providerMetadata?: ProviderMetadata) => State;
|
|
13
13
|
export declare const reasoningEnd: (state: State, events: LLMEvent[], id: string, providerMetadata?: ProviderMetadata) => State;
|
|
@@ -13,9 +13,9 @@ export const textStart = (state, events, id, providerMetadata) => {
|
|
|
13
13
|
events.push(LLMEvent.textStart({ id, providerMetadata }));
|
|
14
14
|
return { ...stepped, text: new Set([...stepped.text, id]) };
|
|
15
15
|
};
|
|
16
|
-
export const textDelta = (state, events, id, text) => {
|
|
16
|
+
export const textDelta = (state, events, id, text, providerMetadata) => {
|
|
17
17
|
const started = textStart(state, events, id);
|
|
18
|
-
events.push(LLMEvent.textDelta({ id, text }));
|
|
18
|
+
events.push(LLMEvent.textDelta({ id, text, providerMetadata }));
|
|
19
19
|
return started;
|
|
20
20
|
};
|
|
21
21
|
export const reasoningStart = (state, events, id, providerMetadata) => {
|
package/dist/providers/azure.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Headers } from "effect/unstable/http";
|
|
1
2
|
import { Auth } from "../route/auth.js";
|
|
2
3
|
import {} from "../route/auth-options.js";
|
|
3
4
|
import { ProviderID } from "../schema/index.js";
|
|
@@ -7,11 +8,35 @@ import { ProviderShared } from "../protocols/shared.js";
|
|
|
7
8
|
import { withOpenAIOptions } from "./openai-options.js";
|
|
8
9
|
export const id = ProviderID.make("azure");
|
|
9
10
|
const routeAuth = Auth.remove("authorization");
|
|
11
|
+
const RESPONSES_WEBSOCKET_ROTATE_AFTER_MS = 55 * 60 * 1000;
|
|
10
12
|
const resourceBaseURL = (resourceName) => `https://${resourceName.trim()}.openai.azure.com/openai`;
|
|
11
13
|
const responsesRoute = OpenAIResponses.route.with({
|
|
12
14
|
id: "azure-openai-responses",
|
|
13
15
|
provider: id,
|
|
14
16
|
auth: routeAuth,
|
|
17
|
+
transport: OpenAIResponses.channelTransport({
|
|
18
|
+
id: "azure-openai-responses",
|
|
19
|
+
name: "Azure OpenAI Responses",
|
|
20
|
+
rotateAfterMs: RESPONSES_WEBSOCKET_ROTATE_AFTER_MS,
|
|
21
|
+
enabled: (value) => {
|
|
22
|
+
const url = new URL(value);
|
|
23
|
+
return (url.protocol === "https:" &&
|
|
24
|
+
url.hostname.endsWith(".openai.azure.com") &&
|
|
25
|
+
url.pathname.endsWith("/openai/v1/responses") &&
|
|
26
|
+
url.searchParams.get("api-version") === "v1");
|
|
27
|
+
},
|
|
28
|
+
url: (value) => {
|
|
29
|
+
const url = new URL(value);
|
|
30
|
+
url.searchParams.delete("api-version");
|
|
31
|
+
return url.toString();
|
|
32
|
+
},
|
|
33
|
+
headers: (headers) => {
|
|
34
|
+
const apiKey = headers["api-key"];
|
|
35
|
+
if (!apiKey)
|
|
36
|
+
return headers;
|
|
37
|
+
return Headers.remove(Headers.set(headers, "authorization", `Bearer ${apiKey}`), "api-key");
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
15
40
|
});
|
|
16
41
|
const chatRoute = OpenAIChat.route.with({
|
|
17
42
|
id: "azure-openai-chat",
|
package/dist/providers/xai.d.ts
CHANGED
|
@@ -245,7 +245,7 @@ export declare const routes: (Route<{
|
|
|
245
245
|
readonly max_output_tokens?: number | undefined;
|
|
246
246
|
readonly max_tool_calls?: number | undefined;
|
|
247
247
|
readonly parallel_tool_calls?: boolean | undefined;
|
|
248
|
-
}, import("../
|
|
248
|
+
}, import("../protocols/open-responses-channel.js").Prepared>)[];
|
|
249
249
|
export declare const configure: (input?: LanguageModelOptions) => {
|
|
250
250
|
id: string & import("effect/Brand").Brand<"AI.ProviderID">;
|
|
251
251
|
model: (modelID: string | ModelID) => import("../schema/options.js").LanguageModel<import("./open-responses-options.js").OpenResponsesOptionsInput>;
|
package/dist/providers/xai.js
CHANGED
|
@@ -8,13 +8,18 @@ import * as OpenAIChat from "../protocols/openai-chat.js";
|
|
|
8
8
|
import * as OpenAIResponses from "../protocols/openai-responses.js";
|
|
9
9
|
import { XAIImages } from "../protocols/xai-images.js";
|
|
10
10
|
export const id = ProviderID.make("xai");
|
|
11
|
+
const RESPONSES_WEBSOCKET_ROTATE_AFTER_MS = 24 * 60 * 1000;
|
|
11
12
|
const responsesRoute = Route.make({
|
|
12
13
|
id: "openai-responses",
|
|
13
14
|
provider: id,
|
|
14
15
|
providerMetadataKey: "xai",
|
|
15
16
|
protocol: OpenAIResponses.protocol,
|
|
16
17
|
endpoint: Endpoint.path("/responses", { baseURL: OpenAICompatibleProfiles.profiles.xai.baseURL }),
|
|
17
|
-
transport: OpenAIResponses.
|
|
18
|
+
transport: OpenAIResponses.channelTransport({
|
|
19
|
+
id: "openai-responses",
|
|
20
|
+
name: "xAI Responses",
|
|
21
|
+
rotateAfterMs: RESPONSES_WEBSOCKET_ROTATE_AFTER_MS,
|
|
22
|
+
}),
|
|
18
23
|
defaults: { providerOptions: { store: false } },
|
|
19
24
|
});
|
|
20
25
|
const chatRoute = Route.make({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
-
"version": "0.0.0-beta-
|
|
3
|
+
"version": "0.0.0-beta-17887",
|
|
4
4
|
"name": "@opencode-ai/ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@clack/prompts": "1.0.0-alpha.1",
|
|
32
32
|
"@effect/platform-node": "4.0.0-rc.110",
|
|
33
|
-
"@opencode-ai/http-recorder": "0.0.0-beta-
|
|
33
|
+
"@opencode-ai/http-recorder": "0.0.0-beta-17887",
|
|
34
34
|
"@tsconfig/bun": "1.0.9",
|
|
35
35
|
"@types/bun": "1.3.13",
|
|
36
36
|
"@typescript/native-preview": "7.0.0-dev.20251207.1",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@smithy/eventstream-codec": "4.2.14",
|
|
41
41
|
"@smithy/util-utf8": "4.2.2",
|
|
42
|
-
"@opencode-ai/schema": "0.0.0-beta-
|
|
42
|
+
"@opencode-ai/schema": "0.0.0-beta-17887",
|
|
43
43
|
"aws4fetch": "1.0.20",
|
|
44
44
|
"effect": "4.0.0-rc.110",
|
|
45
45
|
"google-auth-library": "10.5.0"
|