New:Socket for Asana Is Now Available.Learn more
Get Started

@opencode-ai/ai

Package Overview
Dependencies
Maintainers
2
Versions
1005
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opencode-ai/ai - npm Package Compare versions

Comparing version
0.0.0-beta-17927
to
0.0.0-beta-17941
+12
dist/protocols/open-responses-continuation.d.ts
import type { WebSocketChannelDriver } from "../route/transport/index.js";
export interface DriverInput {
readonly id: string;
readonly name: string;
readonly request: Readonly<Record<string, unknown>>;
readonly message: string;
readonly base: WebSocketChannelDriver;
}
export declare const driver: (input: DriverInput) => WebSocketChannelDriver;
export declare const OpenResponsesContinuation: {
readonly driver: (input: DriverInput) => WebSocketChannelDriver;
};
import { AIError, TransportReason } from "../schema/index.js";
import { Effect, Option, Schema } from "effect";
import * as ProviderShared from "./shared.js";
import { OpenResponses } from "./open-responses.js";
const PROTOCOL = "open-responses.websocket.v1";
const VERSION = 1;
const decodeEvent = Schema.decodeUnknownEffect(OpenResponses.protocol.stream.event);
const checkpointValue = (checkpoint) => {
if (checkpoint?.protocol !== PROTOCOL || !ProviderShared.isRecord(checkpoint.value))
return undefined;
if (checkpoint.value.version !== VERSION)
return undefined;
if (typeof checkpoint.value.responseID !== "string" || checkpoint.value.responseID.trim().length === 0)
return undefined;
if (!ProviderShared.isRecord(checkpoint.value.request) || !Array.isArray(checkpoint.value.output))
return undefined;
return {
version: VERSION,
responseID: checkpoint.value.responseID,
request: checkpoint.value.request,
output: checkpoint.value.output,
};
};
const canonical = (value) => {
if (value === undefined)
return "undefined";
if (Array.isArray(value))
return `[${value.map(canonical).join(",")}]`;
if (!ProviderShared.isRecord(value))
return ProviderShared.encodeJson(value);
return `{${Object.keys(value)
.sort()
.map((key) => `${ProviderShared.encodeJson(key)}:${canonical(value[key])}`)
.join(",")}}`;
};
const json = (value) => {
if (typeof value !== "string")
return value;
return Option.getOrElse(Schema.decodeUnknownOption(ProviderShared.Json)(value), () => value);
};
const comparable = (value) => {
if (!ProviderShared.isRecord(value))
return value;
if (value.type === "message" && value.role === "assistant")
return {
role: "assistant",
content: value.content,
...(value.phase === undefined ? {} : { phase: value.phase }),
};
if (value.type === "function_call")
return {
type: value.type,
call_id: value.call_id,
name: value.name,
arguments: json(value.arguments),
};
if (value.type === "reasoning")
return {
type: value.type,
summary: value.summary,
encrypted_content: value.encrypted_content,
};
return value;
};
const invariant = (request) => {
const { type: _type, input: _input, previous_response_id: _previousResponseID, ...rest } = request;
return rest;
};
const incremental = (request, checkpoint) => {
const input = request.input;
const previousInput = checkpoint.request.input;
if (!Array.isArray(input) || !Array.isArray(previousInput))
return undefined;
if (canonical(invariant(request)) !== canonical(invariant(checkpoint.request)))
return undefined;
const baseline = [...previousInput, ...checkpoint.output];
if (input.length <= baseline.length)
return undefined;
if (!baseline.every((item, index) => canonical(comparable(item)) === canonical(comparable(input[index]))))
return undefined;
return input.slice(baseline.length);
};
const code = (event) => event.code || event.error?.code || event.response?.error?.code || undefined;
const rejected = (input, observation, recovery) => ({
type: "rejected",
recovery,
error: new AIError({
module: input.id,
method: "stream",
reason: new TransportReason({
message: observation.error.message,
transport: "websocket",
operation: "read",
phase: "receive",
delivery: "rejected",
recovery,
}),
}),
});
export const driver = (input) => {
const { previous_response_id: _previousResponseID, ...request } = input.request;
let output = [];
return {
create: (checkpoint) => Effect.sync(() => {
output = [];
const previous = checkpointValue(checkpoint);
const delta = previous ? incremental(request, previous) : undefined;
if (!previous || !delta)
return { message: ProviderShared.encodeJson(request), mode: "full" };
return {
message: ProviderShared.encodeJson({ ...request, input: delta, previous_response_id: previous.responseID }),
mode: "incremental",
};
}),
observe: (create, frame) => Effect.gen(function* () {
const event = yield* decodeEvent(frame).pipe(Effect.mapError(() => ProviderShared.eventError(input.id, `Invalid ${input.name} WebSocket event`, frame)));
const observation = yield* input.base.observe(create, frame);
if (event.type === "response.output_item.done" && event.item)
output.push(event.item);
if (observation.type === "provider-failure") {
const rejection = code(event);
if (rejection === "previous_response_not_found")
return rejected(input, observation, "retry-full");
if (rejection === "websocket_connection_limit_reached")
return rejected(input, observation, "rotate-and-retry-full");
}
if (observation.type !== "completed")
return observation;
const responseID = event.response?.id;
if (!responseID || responseID.trim().length === 0)
return observation;
return {
...observation,
checkpoint: {
protocol: PROTOCOL,
value: { version: VERSION, responseID, request, output: output.slice() },
},
};
}),
};
};
export const OpenResponsesContinuation = { driver };
import { Effect } from "effect";
import { type AIError, type ToolResultPart } from "../../schema/index.js";
import { OpenResponses } from "../open-responses.js";
export type Item = OpenResponses.StreamItem & {
readonly id: string;
readonly status?: string;
readonly action?: unknown;
readonly queries?: unknown;
readonly results?: unknown;
readonly code?: string;
readonly container_id?: string;
readonly outputs?: unknown;
readonly server_label?: string;
readonly output?: unknown;
readonly result?: string;
readonly output_format?: "png" | "jpeg" | "webp";
readonly error?: unknown;
};
export interface Definition {
readonly name: string;
readonly input: (item: Item) => unknown;
readonly result?: (item: Item) => Effect.Effect<ToolResultPart["result"], AIError>;
}
export type Definitions = Readonly<Record<string, Definition>>;
export declare const isItem: <Tools extends Definitions>(item: OpenResponses.StreamItem, tools: Tools) => item is Item;
export declare const onDone: (state: OpenResponses.ParserState, item: Item, tools: Definitions) => Effect.Effect<OpenResponses.StepResult, AIError>;
export * as ResponsesHostedTools from "./responses-hosted-tools.js";
import { Effect } from "effect";
import { LLMEvent } from "../../schema/index.js";
import { OpenResponses } from "../open-responses.js";
import { Lifecycle } from "./lifecycle.js";
export const isItem = (item, tools) => item.type in tools && typeof item.id === "string" && item.id.length > 0;
export const onDone = Effect.fn("ResponsesHostedTools.onDone")(function* (state, item, tools) {
const tool = tools[item.type];
if (!tool)
return [state, []];
const providerMetadata = OpenResponses.providerMetadata(state, { itemId: item.id });
const events = [];
const lifecycle = Lifecycle.stepStart(state.lifecycle, events);
events.push(LLMEvent.toolCall({
id: item.id,
name: tool.name,
input: tool.input(item),
providerExecuted: true,
providerMetadata,
}), LLMEvent.toolResult({
id: item.id,
name: tool.name,
result: tool.result
? yield* tool.result(item)
: item.error !== undefined && item.error !== null
? { type: "error", value: item.error }
: { type: "json", value: item },
providerExecuted: true,
providerMetadata,
}));
return [{ ...state, lifecycle }, events];
});
export * as ResponsesHostedTools from "./responses-hosted-tools.js";
import { Protocol } from "../route/protocol.js";
import { OpenResponses } from "./open-responses.js";
export declare const protocol: Protocol<{
readonly input: readonly ({
readonly type: "reasoning";
readonly summary: readonly {
readonly type: "summary_text";
readonly text: string;
}[];
readonly id?: string | undefined;
readonly encrypted_content?: string | null | undefined;
} | {
readonly type: "item_reference";
readonly id: string;
} | {
readonly role: "system";
readonly content: string;
} | {
readonly role: "developer";
readonly content: string;
} | {
readonly role: "user";
readonly content: readonly ({
readonly type: "input_image";
readonly image_url: string;
} | {
readonly type: "input_file";
readonly filename: string;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {
readonly type: "function_call";
readonly name: string;
readonly arguments: string;
readonly call_id: string;
readonly id?: string | undefined;
} | {
readonly type: "function_call_output";
readonly call_id: string;
readonly output: string | readonly ({
readonly type: "input_image";
readonly image_url: string;
} | {
readonly type: "input_file";
readonly filename: string;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
})[];
readonly model: string;
readonly stream: true;
readonly metadata?: {
readonly [x: string]: string;
} | undefined;
readonly instructions?: string | undefined;
readonly reasoning?: {
readonly summary?: "auto" | "concise" | "detailed" | undefined;
readonly effort?: import("./utils/open-responses-options.js").ReasoningEffort | undefined;
} | undefined;
readonly tools?: readonly {
readonly type: "function";
readonly description: string;
readonly name: string;
readonly parameters: {
readonly [x: string]: unknown;
};
readonly strict?: boolean | undefined;
}[] | undefined;
readonly text?: {
readonly verbosity?: import("./utils/open-responses-options.js").TextVerbosity | undefined;
} | undefined;
readonly temperature?: number | undefined;
readonly tool_choice?: "required" | "auto" | "none" | {
readonly type: "function";
readonly name: string;
} | {
readonly type: "allowed_tools";
readonly mode: "required" | "auto" | "none";
readonly tools: readonly {
readonly type: "function";
readonly name: string;
}[];
} | undefined;
readonly top_p?: number | undefined;
readonly store?: boolean | undefined;
readonly include?: readonly import("./utils/open-responses-options.js").ResponseIncludable[] | undefined;
readonly truncation?: "auto" | "disabled" | undefined;
readonly stream_options?: {
readonly include_obfuscation?: boolean | undefined;
} | undefined;
readonly prompt_cache_key?: string | undefined;
readonly frequency_penalty?: number | undefined;
readonly presence_penalty?: number | undefined;
readonly safety_identifier?: string | undefined;
readonly top_logprobs?: number | undefined;
readonly service_tier?: "default" | "auto" | "flex" | "priority" | undefined;
readonly max_output_tokens?: number | undefined;
readonly max_tool_calls?: number | undefined;
readonly parallel_tool_calls?: boolean | undefined;
}, string, {
readonly [x: string]: unknown;
readonly type: string;
readonly status?: unknown;
readonly code?: string | null | undefined;
readonly message?: string | undefined;
readonly headers?: unknown;
readonly text?: string | undefined;
readonly error?: {
readonly type?: string | null | undefined;
readonly code?: string | null | undefined;
readonly message?: string | null | undefined;
readonly param?: string | null | undefined;
} | null | undefined;
readonly item?: {
readonly [x: string]: unknown;
readonly type: string;
readonly id?: string | undefined;
readonly name?: string | undefined;
readonly arguments?: string | undefined;
readonly encrypted_content?: string | null | undefined;
readonly call_id?: string | undefined;
} | undefined;
readonly delta?: string | undefined;
readonly response?: {
readonly [x: string]: unknown;
readonly id?: string | undefined;
readonly error?: {
readonly type?: string | null | undefined;
readonly code?: string | null | undefined;
readonly message?: string | null | undefined;
readonly param?: string | null | undefined;
} | null | undefined;
readonly usage?: {
readonly input_tokens?: number | undefined;
readonly output_tokens?: number | undefined;
readonly output_tokens_details?: {
readonly reasoning_tokens?: number | undefined;
} | null | undefined;
readonly total_tokens?: number | undefined;
readonly input_tokens_details?: {
readonly cached_tokens?: number | undefined;
readonly cache_write_tokens?: number | undefined;
} | null | undefined;
} | null | undefined;
readonly service_tier?: string | null | undefined;
readonly incomplete_details?: {
readonly reason?: string | undefined;
} | null | undefined;
} | undefined;
readonly param?: string | null | undefined;
readonly status_code?: unknown;
readonly item_id?: string | undefined;
readonly summary_index?: number | undefined;
}, OpenResponses.ParserState>;
export * as XAIResponses from "./xai-responses.js";
import { Effect } from "effect";
import { Protocol } from "../route/protocol.js";
import { OpenResponses } from "./open-responses.js";
import { ProviderShared } from "./shared.js";
import { ResponsesHostedTools } from "./utils/responses-hosted-tools.js";
const ADAPTER = "xai-responses";
const NAME = "xAI Responses";
const extension = {
id: ADAPTER,
name: NAME,
};
const HOSTED_TOOLS = {
web_search_call: { name: "web_search", input: (item) => item.action ?? {} },
x_search_call: { name: "x_search", input: (item) => item.action ?? {} },
file_search_call: { name: "file_search", input: (item) => ({ queries: item.queries ?? [] }) },
code_interpreter_call: {
name: "code_interpreter",
input: (item) => ({ code: item.code, container_id: item.container_id }),
},
image_generation_call: { name: "image_generation", input: () => ({}) },
mcp_call: {
name: "mcp",
input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
},
};
const step = (state, event) => {
if (event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary.delta")
return event.item_id
? Effect.succeed(OpenResponses.onReasoningDelta(state, event, event.item_id))
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
if (event.type === "response.reasoning_text.done" || event.type === "response.reasoning_summary.done")
return event.item_id
? Effect.succeed(OpenResponses.onReasoningDone(state, event))
: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
return OpenResponses.step(state, event);
};
export const protocol = Protocol.make({
id: ADAPTER,
body: OpenResponses.protocol.body,
stream: {
event: OpenResponses.protocol.stream.event,
initial: (request) => OpenResponses.initial(request, extension),
step,
terminal: OpenResponses.terminal,
},
});
export * as XAIResponses from "./xai-responses.js";
+1
-0

@@ -11,1 +11,2 @@ export * as AnthropicMessages from "./anthropic-messages.js";

export * as OpenResponsesChannel from "./open-responses-channel.js";
export * as XAIResponses from "./xai-responses.js";

@@ -11,1 +11,2 @@ export * as AnthropicMessages from "./anthropic-messages.js";

export * as OpenResponsesChannel from "./open-responses-channel.js";
export * as XAIResponses from "./xai-responses.js";
+0
-5

@@ -10,7 +10,2 @@ import { Headers } from "effect/unstable/http";

readonly headers?: (headers: Headers.Headers) => Headers.Headers;
readonly driver?: (input: {
readonly request: Readonly<Record<string, unknown>>;
readonly message: string;
readonly base: WebSocketChannelDriver;
}) => WebSocketChannelDriver;
}

@@ -17,0 +12,0 @@ export interface Prepared {

@@ -7,2 +7,3 @@ import { Effect, Schema, Stream } from "effect";

import { OpenResponses } from "./open-responses.js";
import { OpenResponsesContinuation } from "./open-responses-continuation.js";
const WebSocketResponseCreate = Schema.StructWithRest(Schema.Struct({ type: Schema.tag("response.create") }), [

@@ -91,3 +92,9 @@ Schema.Record(Schema.String, Schema.Unknown),

rotateAfterMs: options.rotateAfterMs,
driver: options.driver?.({ request: create.request, message: create.message, base }) ?? base,
driver: OpenResponsesContinuation.driver({
id: options.id,
name: options.name,
request: create.request,
message: create.message,
base,
}),
};

@@ -94,0 +101,0 @@ })

@@ -16,7 +16,7 @@ import { Effect, Schema } from "effect";

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>]>;
export type MediaInput = Schema.Schema.Type<typeof MediaInput>;
export declare const MessagePhase: Schema.Literals<readonly ["commentary", "final_answer"]>;
export declare const MessagePhase: Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>;
type MessagePhase = Schema.Schema.Type<typeof MessagePhase>;

@@ -40,4 +40,4 @@ export declare const InputItem: Schema.Union<readonly [Schema.Struct<{

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>]>]>>;

@@ -52,3 +52,3 @@ }>, Schema.Struct<{

}>>;
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]>>;
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
}>, Schema.Struct<{

@@ -83,4 +83,7 @@ readonly type: Schema.tag<"reasoning">;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>, Schema.Struct<{
readonly type: Schema.tag<"input_video">;
readonly video_url: Schema.String;
}>]>>]>;

@@ -136,4 +139,4 @@ }>]>;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>]>]>>;

@@ -148,3 +151,3 @@ }>, Schema.Struct<{

}>>;
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]>>;
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
}>, Schema.Struct<{

@@ -179,4 +182,7 @@ readonly type: Schema.tag<"reasoning">;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>, Schema.Struct<{
readonly type: Schema.tag<"input_video">;
readonly video_url: Schema.String;
}>]>>]>;

@@ -249,4 +255,4 @@ }>]>>;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>]>]>>;

@@ -261,3 +267,3 @@ }>, Schema.Struct<{

}>>;
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]>>;
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
}>, Schema.Struct<{

@@ -292,4 +298,7 @@ readonly type: Schema.tag<"reasoning">;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>, Schema.Struct<{
readonly type: Schema.tag<"input_video">;
readonly video_url: Schema.String;
}>]>>]>;

@@ -446,3 +455,2 @@ }>]>>;

}) => MediaInput | undefined;
readonly messagePhase?: (value: unknown) => MessagePhase | null | undefined;
}

@@ -561,4 +569,4 @@ export interface ParserState {

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -576,3 +584,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -593,7 +601,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -871,4 +882,4 @@ })[];

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -886,3 +897,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -903,7 +914,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -1042,4 +1056,4 @@ })[];

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -1057,3 +1071,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -1074,7 +1088,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -1081,0 +1098,0 @@ })[];

@@ -28,5 +28,9 @@ import { Effect, Schema } from "effect";

filename: Schema.String,
file_data: Schema.String,
mime_type: Schema.optional(Schema.String),
file_data: Schema.optional(Schema.String),
file_url: Schema.optional(Schema.String),
});
const OpenResponsesInputVideo = Schema.Struct({
type: Schema.tag("input_video"),
video_url: Schema.String,
});
const MediaInput = Schema.Union([OpenResponsesInputImage, OpenResponsesInputFile]);

@@ -38,3 +42,3 @@ const OpenResponsesInputContent = Schema.Union([OpenResponsesInputText, MediaInput]);

});
export const MessagePhase = Schema.Literals(["commentary", "final_answer"]);
export const MessagePhase = Schema.NullOr(Schema.Literals(["commentary", "final_answer"]));
const OpenResponsesReasoningSummaryText = Schema.Struct({

@@ -61,2 +65,3 @@ type: Schema.tag("summary_text"),

OpenResponsesInputFile,
OpenResponsesInputVideo,
]);

@@ -288,3 +293,3 @@ const OpenResponsesFunctionCallOutput = Schema.Union([

};
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension) {
const lowerMedia = Effect.fn("OpenResponses.lowerMedia")(function* (part, request, extension, target) {
const media = ProviderShared.normalizeMedia(part);

@@ -294,10 +299,15 @@ const extended = extension.lowerMedia?.({ part, media, request });

return extended;
const url = typeof part.data === "string" && (part.data.startsWith("https://") || part.data.startsWith("http://"))
? part.data
: undefined;
if (!media.mime.startsWith("image/")) {
if (target === "tool-result" && media.mime.startsWith("video/"))
return { type: "input_video", video_url: url ?? media.dataUrl };
return {
type: "input_file",
filename: part.filename ?? (media.mime === "application/pdf" ? "document.pdf" : "file"),
file_data: media.dataUrl,
...(url ? { file_url: url } : { file_data: media.base64 }),
};
}
return { type: "input_image", image_url: media.dataUrl };
return { type: "input_image", image_url: url ?? media.dataUrl };
});

@@ -308,5 +318,11 @@ const lowerUserContent = Effect.fnUntraced(function* (part, request, extension) {

if (part.type === "media")
return yield* lowerMedia(part, request, extension);
return yield* lowerMessageMedia(part, request, extension);
return yield* ProviderShared.unsupportedContent(extension.name, "user", ["text", "media"]);
});
const lowerMessageMedia = Effect.fnUntraced(function* (part, request, extension) {
const lowered = yield* lowerMedia(part, request, extension, "message");
if (lowered.type === "input_video")
return yield* ProviderShared.invalidRequest(`${extension.name} user messages do not support input_video`);
return lowered;
});
// Tool results may carry structured text, images, and files. Keep media as provider-native

@@ -317,4 +333,9 @@ // content instead of JSON-stringifying base64 into a prompt string.

return { type: "input_text", text: item.text };
return yield* lowerMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension);
return yield* lowerMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension, "tool-result");
});
const lowerHostedToolResultContentItem = Effect.fnUntraced(function* (item, request, extension) {
if (item.type === "text")
return { type: "input_text", text: item.text };
return yield* lowerMessageMedia({ type: "media", mediaType: item.mime, data: item.uri, filename: item.name }, request, extension);
});
const lowerToolResultOutput = Effect.fnUntraced(function* (part, request, extension) {

@@ -360,3 +381,3 @@ // Text/json/error results are encoded as a plain string for backward

const id = itemID(part.providerMetadata, providerMetadataKey);
const phase = ProviderShared.isRecord(metadata) ? messagePhase(metadata.phase, extension) : undefined;
const phase = ProviderShared.isRecord(metadata) ? messagePhase(metadata.phase) : undefined;
const group = groups.at(-1);

@@ -421,3 +442,3 @@ if (group && group.id === id && group.phase === phase)

role: "user",
content: yield* Effect.forEach(content, (item) => lowerToolResultContentItem(item, request, extension)),
content: yield* Effect.forEach(content, (item) => lowerHostedToolResultContentItem(item, request, extension)),
});

@@ -930,3 +951,3 @@ }

messageItems: new Set(),
messagePhase: (value) => messagePhase(value, extension),
messagePhase,
messagePhases: {},

@@ -936,6 +957,6 @@ reasoningItems: {},

});
const messagePhase = (value, extension) => {
if (value === "commentary" || value === "final_answer")
const messagePhase = (value) => {
if (value === null || value === "commentary" || value === "final_answer")
return value;
return extension.messagePhase?.(value);
return undefined;
};

@@ -942,0 +963,0 @@ export const protocol = Protocol.make({

@@ -34,4 +34,4 @@ import { Route, type RouteRoutedLanguageModelInput } from "../route/client.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -49,3 +49,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -66,7 +66,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -73,0 +76,0 @@ })[];

@@ -6,3 +6,2 @@ import { Schema } from "effect";

import { OpenResponses } from "./open-responses.js";
import { type Options } from "./open-responses-channel.js";
export declare const DEFAULT_BASE_URL = "https://api.openai.com/v1";

@@ -12,12 +11,34 @@ export declare const PATH = "/responses";

readonly stream: Schema.Literal<true>;
readonly tools: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
readonly description: Schema.String;
readonly parameters: Schema.$Record<Schema.String, Schema.Unknown>;
readonly strict: Schema.optional<Schema.Boolean>;
}>, Schema.Struct<{
readonly type: Schema.tag<"image_generation">;
readonly action: Schema.optional<Schema.Literals<readonly ["auto", "generate", "edit"]>>;
readonly background: Schema.optional<Schema.Literals<readonly ["auto", "opaque", "transparent"]>>;
readonly input_fidelity: Schema.optional<Schema.Literals<readonly ["low", "high"]>>;
readonly output_compression: Schema.optional<Schema.Int>;
readonly output_format: Schema.optional<Schema.Literals<readonly ["png", "jpeg", "webp"]>>;
readonly partial_images: Schema.optional<Schema.Int>;
readonly quality: Schema.optional<Schema.Literals<readonly ["auto", "low", "medium", "high"]>>;
readonly size: Schema.optional<Schema.String>;
}>]>>>;
readonly tool_choice: Schema.optional<Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["auto", "none", "required"]>, Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
}>, Schema.Struct<{
readonly type: Schema.tag<"allowed_tools">;
readonly mode: Schema.Literals<readonly ["auto", "none", "required"]>;
readonly tools: Schema.$Array<Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
}>>;
}>]>, Schema.Struct<{
readonly type: Schema.tag<"image_generation">;
}>]>>;
readonly model: Schema.String;
readonly input: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
readonly type: Schema.tag<"message">;
readonly id: Schema.optionalKey<Schema.String>;
readonly role: Schema.tag<"assistant">;
readonly content: Schema.$Array<Schema.Struct<{
readonly type: Schema.tag<"output_text">;
readonly text: Schema.String;
}>>;
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
}>, Schema.Union<readonly [Schema.Struct<{
readonly role: Schema.tag<"system">;

@@ -39,4 +60,4 @@ readonly content: Schema.String;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>]>]>>;

@@ -51,3 +72,3 @@ }>, Schema.Struct<{

}>>;
readonly phase: Schema.optionalKey<Schema.Literals<readonly ["commentary", "final_answer"]>>;
readonly phase: Schema.optionalKey<Schema.NullOr<Schema.Literals<readonly ["commentary", "final_answer"]>>>;
}>, Schema.Struct<{

@@ -82,37 +103,9 @@ readonly type: Schema.tag<"reasoning">;

readonly filename: Schema.String;
readonly file_data: Schema.String;
readonly mime_type: Schema.optional<Schema.String>;
readonly file_data: Schema.optional<Schema.String>;
readonly file_url: Schema.optional<Schema.String>;
}>, Schema.Struct<{
readonly type: Schema.tag<"input_video">;
readonly video_url: Schema.String;
}>]>>]>;
}>]>]>>;
readonly tools: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
readonly description: Schema.String;
readonly parameters: Schema.$Record<Schema.String, Schema.Unknown>;
readonly strict: Schema.optional<Schema.Boolean>;
}>, Schema.Struct<{
readonly type: Schema.tag<"image_generation">;
readonly action: Schema.optional<Schema.Literals<readonly ["auto", "generate", "edit"]>>;
readonly background: Schema.optional<Schema.Literals<readonly ["auto", "opaque", "transparent"]>>;
readonly input_fidelity: Schema.optional<Schema.Literals<readonly ["low", "high"]>>;
readonly output_compression: Schema.optional<Schema.Int>;
readonly output_format: Schema.optional<Schema.Literals<readonly ["png", "jpeg", "webp"]>>;
readonly partial_images: Schema.optional<Schema.Int>;
readonly quality: Schema.optional<Schema.Literals<readonly ["auto", "low", "medium", "high"]>>;
readonly size: Schema.optional<Schema.String>;
}>]>>>;
readonly tool_choice: Schema.optional<Schema.Union<readonly [Schema.Union<readonly [Schema.Literals<readonly ["auto", "none", "required"]>, Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
}>, Schema.Struct<{
readonly type: Schema.tag<"allowed_tools">;
readonly mode: Schema.Literals<readonly ["auto", "none", "required"]>;
readonly tools: Schema.$Array<Schema.Struct<{
readonly type: Schema.tag<"function">;
readonly name: Schema.String;
}>>;
}>]>, Schema.Struct<{
readonly type: Schema.tag<"image_generation">;
}>]>>;
readonly model: Schema.String;
readonly instructions: Schema.optional<Schema.String>;

@@ -172,4 +165,4 @@ readonly store: Schema.optional<Schema.Boolean>;

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -187,3 +180,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -204,17 +197,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -364,4 +351,4 @@ readonly model: string;

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -379,3 +366,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -396,17 +383,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -476,3 +457,3 @@ readonly model: string;

}, string>;
export declare const channelTransport: (options: Omit<Options, "driver">) => import("../route/transport/index.js").Transport<{
export declare const channelTransport: (options: import("./open-responses-channel.js").Options) => import("../route/transport/index.js").Transport<{
readonly input: readonly ({

@@ -503,4 +484,4 @@ readonly type: "reasoning";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -518,3 +499,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -535,17 +516,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -641,4 +616,4 @@ readonly model: string;

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -656,3 +631,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -673,17 +648,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -779,4 +748,4 @@ readonly model: string;

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -794,3 +763,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -811,17 +780,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -828,0 +791,0 @@ readonly model: string;

@@ -8,10 +8,9 @@ import { Effect, Encoding, Schema } from "effect";

import { HttpTransport } from "../route/transport/index.js";
import { LLMEvent, LLMRequest } from "../schema/index.js";
import { LLMRequest } from "../schema/index.js";
import { OpenResponses } from "./open-responses.js";
import { optionalArray, ProviderShared } from "./shared.js";
import { Lifecycle } from "./utils/lifecycle.js";
import { OpenAIImage } from "./utils/openai-image.js";
import { ResponsesHostedTools } from "./utils/responses-hosted-tools.js";
import { ToolSchemaProjection } from "./utils/tool-schema.js";
import { OpenResponsesChannel } from "./open-responses-channel.js";
import { OpenAIResponsesChannel } from "./openai-responses-channel.js";
const ADAPTER = "openai-responses";

@@ -39,15 +38,4 @@ const NAME = "OpenAI Responses";

]);
const OpenAIResponsesInputItem = Schema.Union([
Schema.Struct({
type: Schema.tag("message"),
id: Schema.optionalKey(Schema.String),
role: Schema.tag("assistant"),
content: Schema.Array(Schema.Struct({ type: Schema.tag("output_text"), text: Schema.String })),
phase: Schema.optionalKey(Schema.NullOr(OpenResponses.MessagePhase)),
}),
OpenResponses.InputItem,
]);
const OpenAIResponsesCoreFields = {
...OpenResponses.coreFields,
input: Schema.Array(OpenAIResponsesInputItem),
tools: optionalArray(OpenAIResponsesTools),

@@ -63,13 +51,2 @@ tool_choice: Schema.optional(OpenAIResponsesToolChoice),

name: NAME,
messagePhase: (value) => (value === null ? null : undefined),
lowerMedia: ({ part, media, request }) => {
if (request.model.provider !== "xai" || media.mime !== "application/pdf")
return undefined;
return {
type: "input_file",
filename: part.filename ?? "document.pdf",
file_data: media.base64,
mime_type: media.mime,
};
},
};

@@ -112,19 +89,2 @@ const nativeImageToolInput = (tool) => {

});
const HOSTED_TOOLS = {
web_search_call: { name: "web_search", input: (item) => item.action ?? {} },
web_search_preview_call: { name: "web_search_preview", input: (item) => item.action ?? {} },
file_search_call: { name: "file_search", input: (item) => ({ queries: item.queries ?? [] }) },
code_interpreter_call: {
name: "code_interpreter",
input: (item) => ({ code: item.code, container_id: item.container_id }),
},
computer_use_call: { name: "computer_use", input: (item) => item.action ?? {} },
image_generation_call: { name: "image_generation", input: () => ({}) },
mcp_call: {
name: "mcp",
input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
},
local_shell_call: { name: "local_shell", input: (item) => item.action ?? {} },
};
const isHostedToolItem = (item) => item.type in HOSTED_TOOLS && typeof item.id === "string" && item.id.length > 0;
const hostedToolResult = Effect.fn("OpenAIResponses.hostedToolResult")(function* (item) {

@@ -148,22 +108,18 @@ const isError = item.error !== undefined && item.error !== null;

});
const onHostedToolDone = Effect.fn("OpenAIResponses.onHostedToolDone")(function* (state, item) {
const tool = HOSTED_TOOLS[item.type];
const providerMetadata = OpenResponses.providerMetadata(state, { itemId: item.id });
const events = [];
const lifecycle = Lifecycle.stepStart(state.lifecycle, events);
events.push(LLMEvent.toolCall({
id: item.id,
name: tool.name,
input: tool.input(item),
providerExecuted: true,
providerMetadata,
}), LLMEvent.toolResult({
id: item.id,
name: tool.name,
result: yield* hostedToolResult(item),
providerExecuted: true,
providerMetadata,
}));
return [{ ...state, lifecycle }, events];
});
const HOSTED_TOOLS = {
web_search_call: { name: "web_search", input: (item) => item.action ?? {} },
web_search_preview_call: { name: "web_search_preview", input: (item) => item.action ?? {} },
file_search_call: { name: "file_search", input: (item) => ({ queries: item.queries ?? [] }) },
code_interpreter_call: {
name: "code_interpreter",
input: (item) => ({ code: item.code, container_id: item.container_id }),
},
computer_use_call: { name: "computer_use", input: (item) => item.action ?? {} },
image_generation_call: { name: "image_generation", input: () => ({}), result: hostedToolResult },
mcp_call: {
name: "mcp",
input: (item) => ({ server_label: item.server_label, name: item.name, arguments: item.arguments }),
},
local_shell_call: { name: "local_shell", input: (item) => item.action ?? {} },
};
const step = (state, event) => {

@@ -178,4 +134,4 @@ if (event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary.delta")

: ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);
if (event.type === "response.output_item.done" && event.item && isHostedToolItem(event.item))
return onHostedToolDone(state, event.item);
if (event.type === "response.output_item.done" && event.item && ResponsesHostedTools.isItem(event.item, HOSTED_TOOLS))
return ResponsesHostedTools.onDone(state, event.item, HOSTED_TOOLS);
return OpenResponses.step(state, event);

@@ -199,6 +155,3 @@ };

export const httpTransport = HttpTransport.sseJson.with();
export const channelTransport = (options) => OpenResponsesChannel.transport({
...options,
driver: (input) => OpenAIResponsesChannel.driver({ id: options.id, name: options.name, ...input }),
});
export const channelTransport = (OpenResponsesChannel.transport);
export const transport = channelTransport({

@@ -205,0 +158,0 @@ id: ADAPTER,

@@ -144,4 +144,4 @@ import type { Route as RouteDef, RouteDefaultsInput } from "../route/client.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -159,3 +159,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -176,17 +176,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -193,0 +187,0 @@ readonly model: string;

@@ -147,4 +147,4 @@ import { type AtLeastOne, type ProviderAuthOption } from "../route/auth-options.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -162,3 +162,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -179,17 +179,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -196,0 +190,0 @@ readonly model: string;

@@ -47,4 +47,4 @@ import type { ProviderPackage } from "../provider-package.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -62,3 +62,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -79,7 +79,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -86,0 +89,0 @@ })[];

@@ -45,4 +45,4 @@ import type { ProviderPackage } from "../provider-package.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -60,3 +60,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -77,7 +77,10 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];

@@ -84,0 +87,0 @@ })[];

@@ -132,4 +132,4 @@ import { type ProviderAuthOption } from "../route/auth-options.js";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {

@@ -147,3 +147,3 @@ readonly type: "input_text";

readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
} | {

@@ -164,17 +164,11 @@ readonly type: "function_call";

readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
readonly file_data?: string | undefined;
readonly file_url?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
} | {
readonly type: "input_video";
readonly video_url: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];

@@ -181,0 +175,0 @@ readonly model: string;

@@ -114,137 +114,3 @@ import { type ProviderAuthOption } from "../route/auth-options.js";

readonly presence_penalty?: number | undefined;
}, import("../route/transport/http.js").HttpPrepared<string>> | Route<{
readonly input: readonly ({
readonly type: "reasoning";
readonly summary: readonly {
readonly type: "summary_text";
readonly text: string;
}[];
readonly id?: string | undefined;
readonly encrypted_content?: string | null | undefined;
} | {
readonly type: "item_reference";
readonly id: string;
} | {
readonly role: "system";
readonly content: string;
} | {
readonly role: "developer";
readonly content: string;
} | {
readonly role: "user";
readonly content: readonly ({
readonly type: "input_image";
readonly image_url: string;
} | {
readonly type: "input_file";
readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | undefined;
} | {
readonly type: "function_call";
readonly name: string;
readonly arguments: string;
readonly call_id: string;
readonly id?: string | undefined;
} | {
readonly type: "function_call_output";
readonly call_id: string;
readonly output: string | readonly ({
readonly type: "input_image";
readonly image_url: string;
} | {
readonly type: "input_file";
readonly filename: string;
readonly file_data: string;
readonly mime_type?: string | undefined;
} | {
readonly type: "input_text";
readonly text: string;
})[];
} | {
readonly type: "message";
readonly content: readonly {
readonly type: "output_text";
readonly text: string;
}[];
readonly role: "assistant";
readonly id?: string | undefined;
readonly phase?: "commentary" | "final_answer" | null | undefined;
})[];
readonly model: string;
readonly stream: true;
readonly metadata?: {
readonly [x: string]: string;
} | undefined;
readonly instructions?: string | undefined;
readonly reasoning?: {
readonly summary?: "auto" | "concise" | "detailed" | undefined;
readonly effort?: import("../protocols/utils/open-responses-options.js").ReasoningEffort | undefined;
} | undefined;
readonly tools?: readonly ({
readonly type: "function";
readonly description: string;
readonly name: string;
readonly parameters: {
readonly [x: string]: unknown;
};
readonly strict?: boolean | undefined;
} | {
readonly type: "image_generation";
readonly size?: string | undefined;
readonly action?: "generate" | "auto" | "edit" | undefined;
readonly output_format?: "png" | "jpeg" | "webp" | undefined;
readonly quality?: "auto" | "low" | "medium" | "high" | undefined;
readonly background?: "auto" | "opaque" | "transparent" | undefined;
readonly output_compression?: number | undefined;
readonly input_fidelity?: "low" | "high" | undefined;
readonly partial_images?: number | undefined;
})[] | undefined;
readonly text?: {
readonly verbosity?: import("../protocols/utils/open-responses-options.js").TextVerbosity | undefined;
} | undefined;
readonly temperature?: number | undefined;
readonly tool_choice?: "required" | "auto" | "none" | {
readonly type: "function";
readonly name: string;
} | {
readonly type: "allowed_tools";
readonly mode: "required" | "auto" | "none";
readonly tools: readonly {
readonly type: "function";
readonly name: string;
}[];
} | {
readonly type: "image_generation";
} | undefined;
readonly top_p?: number | undefined;
readonly store?: boolean | undefined;
readonly include?: readonly import("../protocols/utils/open-responses-options.js").ResponseIncludable[] | undefined;
readonly truncation?: "auto" | "disabled" | undefined;
readonly stream_options?: {
readonly include_obfuscation?: boolean | undefined;
} | undefined;
readonly prompt_cache_key?: string | undefined;
readonly frequency_penalty?: number | undefined;
readonly presence_penalty?: number | undefined;
readonly safety_identifier?: string | undefined;
readonly top_logprobs?: number | undefined;
readonly service_tier?: "default" | "auto" | "flex" | "priority" | undefined;
readonly max_output_tokens?: number | undefined;
readonly max_tool_calls?: number | undefined;
readonly parallel_tool_calls?: boolean | undefined;
}, import("../protocols/open-responses-channel.js").Prepared>)[];
}, import("../route/transport/http.js").HttpPrepared<string>> | Route<unknown, import("../protocols/open-responses-channel.js").Prepared>)[];
export declare const configure: (input?: LanguageModelOptions) => {

@@ -251,0 +117,0 @@ id: string & import("effect/Brand").Brand<"AI.ProviderID">;

@@ -8,3 +8,4 @@ import { AuthOptions } from "../route/auth-options.js";

import * as OpenAIChat from "../protocols/openai-chat.js";
import * as OpenAIResponses from "../protocols/openai-responses.js";
import { OpenResponsesChannel } from "../protocols/open-responses-channel.js";
import { XAIResponses } from "../protocols/xai-responses.js";
import { XAIImages } from "../protocols/xai-images.js";

@@ -17,5 +18,5 @@ export const id = ProviderID.make("xai");

providerMetadataKey: "xai",
protocol: OpenAIResponses.protocol,
protocol: XAIResponses.protocol,
endpoint: Endpoint.path("/responses", { baseURL: OpenAICompatibleProfiles.profiles.xai.baseURL }),
transport: OpenAIResponses.channelTransport({
transport: OpenResponsesChannel.transport({
id: "openai-responses",

@@ -22,0 +23,0 @@ name: "xAI Responses",

{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.0.0-beta-17927",
"version": "0.0.0-beta-17941",
"name": "@opencode-ai/ai",

@@ -33,3 +33,3 @@ "type": "module",

"@effect/platform-node": "4.0.0-rc.110",
"@opencode-ai/http-recorder": "0.0.0-beta-17927",
"@opencode-ai/http-recorder": "0.0.0-beta-17941",
"@tsconfig/bun": "1.0.9",

@@ -43,3 +43,3 @@ "@types/bun": "1.3.13",

"@smithy/util-utf8": "4.2.2",
"@opencode-ai/schema": "0.0.0-beta-17927",
"@opencode-ai/schema": "0.0.0-beta-17941",
"aws4fetch": "1.0.20",

@@ -46,0 +46,0 @@ "effect": "4.0.0-rc.110",

import type { WebSocketChannelDriver } from "../route/transport/index.js";
export interface DriverInput {
readonly id: string;
readonly name: string;
readonly request: Readonly<Record<string, unknown>>;
readonly message: string;
readonly base: WebSocketChannelDriver;
}
export declare const driver: (input: DriverInput) => WebSocketChannelDriver;
export declare const OpenAIResponsesChannel: {
readonly driver: (input: DriverInput) => WebSocketChannelDriver;
};
import { AIError, TransportReason } from "../schema/index.js";
import { Effect, Option, Schema } from "effect";
import * as ProviderShared from "./shared.js";
import { OpenResponses } from "./open-responses.js";
const PROTOCOL = "openai-responses.websocket.v1";
const VERSION = 1;
const decodeEvent = Schema.decodeUnknownEffect(OpenResponses.protocol.stream.event);
const checkpointValue = (checkpoint) => {
if (checkpoint?.protocol !== PROTOCOL || !ProviderShared.isRecord(checkpoint.value))
return undefined;
if (checkpoint.value.version !== VERSION)
return undefined;
if (typeof checkpoint.value.responseID !== "string" || checkpoint.value.responseID.trim().length === 0)
return undefined;
if (!ProviderShared.isRecord(checkpoint.value.request) || !Array.isArray(checkpoint.value.output))
return undefined;
return {
version: VERSION,
responseID: checkpoint.value.responseID,
request: checkpoint.value.request,
output: checkpoint.value.output,
};
};
const canonical = (value) => {
if (value === undefined)
return "undefined";
if (Array.isArray(value))
return `[${value.map(canonical).join(",")}]`;
if (!ProviderShared.isRecord(value))
return ProviderShared.encodeJson(value);
return `{${Object.keys(value)
.sort()
.map((key) => `${ProviderShared.encodeJson(key)}:${canonical(value[key])}`)
.join(",")}}`;
};
const json = (value) => {
if (typeof value !== "string")
return value;
return Option.getOrElse(Schema.decodeUnknownOption(ProviderShared.Json)(value), () => value);
};
const comparable = (value) => {
if (!ProviderShared.isRecord(value))
return value;
if (value.type === "message" && value.role === "assistant")
return {
role: "assistant",
content: value.content,
...(value.phase === undefined ? {} : { phase: value.phase }),
};
if (value.type === "function_call")
return {
type: value.type,
call_id: value.call_id,
name: value.name,
arguments: json(value.arguments),
};
if (value.type === "reasoning")
return {
type: value.type,
summary: value.summary,
encrypted_content: value.encrypted_content,
};
return value;
};
const invariant = (request) => {
const { type: _type, input: _input, previous_response_id: _previousResponseID, ...rest } = request;
return rest;
};
const incremental = (request, checkpoint) => {
const input = request.input;
const previousInput = checkpoint.request.input;
if (!Array.isArray(input) || !Array.isArray(previousInput))
return undefined;
if (canonical(invariant(request)) !== canonical(invariant(checkpoint.request)))
return undefined;
const baseline = [...previousInput, ...checkpoint.output];
if (input.length <= baseline.length)
return undefined;
if (!baseline.every((item, index) => canonical(comparable(item)) === canonical(comparable(input[index]))))
return undefined;
return input.slice(baseline.length);
};
const code = (event) => event.code || event.error?.code || event.response?.error?.code || undefined;
const rejected = (input, observation, recovery) => ({
type: "rejected",
recovery,
error: new AIError({
module: input.id,
method: "stream",
reason: new TransportReason({
message: observation.error.message,
transport: "websocket",
operation: "read",
phase: "receive",
delivery: "rejected",
recovery,
}),
}),
});
export const driver = (input) => {
const { previous_response_id: _previousResponseID, ...request } = input.request;
let output = [];
return {
create: (checkpoint) => Effect.sync(() => {
output = [];
const previous = checkpointValue(checkpoint);
const delta = previous ? incremental(request, previous) : undefined;
if (!previous || !delta)
return { message: ProviderShared.encodeJson(request), mode: "full" };
return {
message: ProviderShared.encodeJson({ ...request, input: delta, previous_response_id: previous.responseID }),
mode: "incremental",
};
}),
observe: (create, frame) => Effect.gen(function* () {
const event = yield* decodeEvent(frame).pipe(Effect.mapError(() => ProviderShared.eventError(input.id, `Invalid ${input.name} WebSocket event`, frame)));
const observation = yield* input.base.observe(create, frame);
if (event.type === "response.output_item.done" && event.item)
output.push(event.item);
if (observation.type === "provider-failure") {
const rejection = code(event);
if (rejection === "previous_response_not_found")
return rejected(input, observation, "retry-full");
if (rejection === "websocket_connection_limit_reached")
return rejected(input, observation, "rotate-and-retry-full");
}
if (observation.type !== "completed")
return observation;
const responseID = event.response?.id;
if (!responseID || responseID.trim().length === 0)
return observation;
return {
...observation,
checkpoint: {
protocol: PROTOCOL,
value: { version: VERSION, responseID, request, output: output.slice() },
},
};
}),
};
};
export const OpenAIResponsesChannel = { driver };