Sign In

@opencode-ai/ai

Package Overview
Dependencies
Maintainers
2
Versions
848
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-18148
to
0.0.0-beta-18155
+1
-1
dist/protocols/bedrock-converse.js

@@ -568,3 +568,3 @@ import { Effect, Schema } from "effect";

step,
onHalt,
onHalt: (state) => Effect.succeed(onHalt(state)),
},

@@ -571,0 +571,0 @@ });

@@ -577,3 +577,3 @@ import { Effect, Option, Schema } from "effect";

step,
onHalt: finish,
onHalt: (state) => Effect.succeed(finish(state)),
},

@@ -580,0 +580,0 @@ });

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

readonly delta: Schema.optional<Schema.String>;
readonly arguments: Schema.optional<Schema.String>;
readonly text: Schema.optional<Schema.String>;

@@ -1013,2 +1014,3 @@ readonly item_id: Schema.optional<Schema.String>;

} | undefined;
readonly arguments?: string | undefined;
readonly param?: string | null | undefined;

@@ -1015,0 +1017,0 @@ readonly status_code?: unknown;

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

delta: Schema.optional(Schema.String),
arguments: Schema.optional(Schema.String),
text: Schema.optional(Schema.String),

@@ -760,5 +761,19 @@ item_id: Schema.optional(Schema.String),

const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgumentsDelta")(function* (state, event) {
if (!event.item_id || !event.delta || !state.tools[event.item_id])
if (!event.item_id)
return [state, NO_EVENTS];
const result = ToolStream.appendExisting(state.id, state.tools, event.item_id, event.delta, `${state.name} tool argument delta is missing its tool call`);
const tool = state.tools[event.item_id];
if (!tool)
return [state, NO_EVENTS];
const final = event.type === "response.function_call_arguments.done" ? event.arguments : undefined;
if (event.type === "response.function_call_arguments.done" && final === undefined)
return [state, NO_EVENTS];
if (final !== undefined && !final.startsWith(tool.input))
return [
{ ...state, tools: ToolStream.start(state.tools, event.item_id, { ...tool, input: final }) },
NO_EVENTS,
];
const delta = final === undefined ? event.delta : final.slice(tool.input.length);
if (!delta)
return [state, NO_EVENTS];
const result = ToolStream.appendExisting(state.id, state.tools, event.item_id, delta, `${state.name} tool argument delta is missing its tool call`);
if (ToolStream.isError(result))

@@ -948,3 +963,3 @@ return yield* result;

}
if (event.type === "response.function_call_arguments.delta")
if (event.type === "response.function_call_arguments.delta" || event.type === "response.function_call_arguments.done")
return event.item_id

@@ -951,0 +966,0 @@ ? onFunctionCallArgumentsDelta(state, event)

@@ -207,3 +207,3 @@ import { Effect, Schema } from "effect";

export type OpenAIChatBody = Schema.Schema.Type<typeof OpenAIChatBody>;
export declare const OpenAIChatEvent: Schema.Struct<{
export declare const OpenAIChatEvent: Schema.StructWithRest<Schema.Struct<{
readonly choices: Schema.optional<Schema.NullOr<Schema.$Array<Schema.StructWithRest<Schema.Struct<{

@@ -261,7 +261,7 @@ readonly delta: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{

}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
readonly error: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
readonly code: Schema.optional<Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.Number]>>>;
readonly message: Schema.String;
}>>>;
}>;
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>;
export type OpenAIChatEvent = Schema.Schema.Type<typeof OpenAIChatEvent>;

@@ -286,2 +286,3 @@ interface PendingToolDelta {

readonly nextToolIndex: number;
readonly requireFinishReason: boolean;
}

@@ -591,3 +592,5 @@ interface LoweringOptions {

}, string, {
readonly [x: string]: unknown;
readonly error?: {
readonly [x: string]: unknown;
readonly message: string;

@@ -594,0 +597,0 @@ readonly code?: string | number | null | undefined;

@@ -8,3 +8,3 @@ import { Effect, Schema } from "effect";

import { Protocol } from "../route/protocol.js";
import { AIError, LLMEvent, Usage, } from "../schema/index.js";
import { AIError, InvalidProviderOutputReason, LLMEvent, ProviderInternalReason, UnknownProviderReason, Usage, } from "../schema/index.js";
import { classifyProviderFailure } from "../provider-error.js";

@@ -171,11 +171,11 @@ import { isRecord, JsonObject, optionalArray, optionalNull, ProviderShared } from "./shared.js";

}), [Schema.Record(Schema.String, Schema.Unknown)]);
const OpenAIChatError = Schema.Struct({
const OpenAIChatError = Schema.StructWithRest(Schema.Struct({
code: optionalNull(Schema.Union([Schema.String, Schema.Number])),
message: Schema.String,
});
export const OpenAIChatEvent = Schema.Struct({
}), [Schema.Record(Schema.String, Schema.Unknown)]);
export const OpenAIChatEvent = Schema.StructWithRest(Schema.Struct({
choices: optionalNull(Schema.Array(OpenAIChatChoice)),
usage: optionalNull(OpenAIChatUsage),
error: optionalNull(OpenAIChatError),
});
}), [Schema.Record(Schema.String, Schema.Unknown)]);
const lowerTool = (tool, inputSchema, options, supportsStrictMode) => ({

@@ -582,15 +582,28 @@ type: "function",

// because OpenAI streams JSON arguments across multiple deltas.
const mapFinishReason = (reason) => {
if (reason === "stop")
return "stop";
if (reason === "length")
return "length";
if (reason === "content_filter")
return "content-filter";
if (reason === "function_call" || reason === "tool_calls")
return "tool-calls";
if (reason === "error")
return "error";
return "unknown";
};
const finishReasonError = (event, reason) => new AIError({
module: ADAPTER,
method: "stream",
body: ProviderShared.encodeJson(event),
reason,
});
const mapFinishReason = Effect.fn("OpenAIChat.mapFinishReason")(function* (event, reason) {
switch (reason) {
case "error":
return yield* finishReasonError(event, new UnknownProviderReason({ message: "Provider reported an error (finish_reason: error)" }));
case "network_error":
return yield* finishReasonError(event, new ProviderInternalReason({ message: "Provider reported a network error (finish_reason: network_error)" }));
case "stop":
case "end":
return "stop";
case "length":
return "length";
case "content_filter":
return "content-filter";
case "function_call":
case "tool_calls":
return "tool-calls";
default:
return "unknown";
}
});
// OpenAI Chat reports `prompt_tokens` (inclusive total) with a

@@ -692,6 +705,8 @@ // cached-read and cache-write subsets, and `completion_tokens` (inclusive

const step = (state, event) => Effect.gen(function* () {
if (event.error)
if (event.error) {
const body = ProviderShared.encodeJson(event);
return yield* new AIError({
module: ADAPTER,
method: "stream",
body,
reason: classifyProviderFailure({

@@ -701,4 +716,6 @@ message: event.error.message,

status: typeof event.error.code === "number" ? event.error.code : undefined,
rawBody: body,
}),
});
}
const events = [];

@@ -711,4 +728,7 @@ const choice = event.choices?.[0];

const rawFinishReason = choice?.finish_reason;
const finishReason = rawFinishReason !== undefined && rawFinishReason !== null
? { normalized: mapFinishReason(rawFinishReason), raw: choice?.native_finish_reason ?? rawFinishReason }
const finishReason = rawFinishReason
? {
normalized: yield* mapFinishReason(event, rawFinishReason),
raw: choice?.native_finish_reason ?? rawFinishReason,
}
: state.finishReason;

@@ -730,3 +750,3 @@ const delta = choice?.delta;

if (hasLateContent)
return yield* ProviderShared.eventError(ADAPTER, "OpenAI Chat received content after the finish reason");
return yield* ProviderShared.eventError(ADAPTER, "OpenAI Chat received content after the finish reason", ProviderShared.encodeJson(event));
return [{ ...state, usage }, events];

@@ -783,3 +803,3 @@ }

if (ToolStream.isError(result))
return yield* result;
return yield* ProviderShared.eventError(ADAPTER, result.reason.message, ProviderShared.encodeJson(event));
tools = result.tools;

@@ -791,3 +811,3 @@ if (result.events.length)

if (finishReason !== undefined && state.finishReason === undefined && Object.keys(pendingTools).length > 0)
return yield* ProviderShared.eventError(ADAPTER, "OpenAI Chat tool call delta is missing id or name");
return yield* ProviderShared.eventError(ADAPTER, "OpenAI Chat tool call delta is missing id or name", ProviderShared.encodeJson(event));
// Finalize accumulated tool inputs eagerly when finish_reason arrives so

@@ -812,2 +832,3 @@ // valid calls and malformed local calls settle independently.

nextToolIndex,
requireFinishReason: state.requireFinishReason,
},

@@ -817,6 +838,16 @@ events,

});
const finishEvents = (state) => {
const finishEvents = Effect.fn("OpenAIChat.finishEvents")(function* (state) {
if (state.finishReason === undefined && state.requireFinishReason)
return yield* new AIError({
module: ADAPTER,
method: "stream",
reason: new InvalidProviderOutputReason({
classification: "incomplete-stream",
message: "OpenAI Chat stream ended without finish_reason",
route: ADAPTER,
}),
});
const events = [];
const toolCallEvents = state.finishReason === undefined && Object.keys(state.tools).length > 0
? Effect.runSync(ToolStream.finishAll(ADAPTER, state.tools)).events
? (yield* ToolStream.finishAll(ADAPTER, state.tools)).events
: state.toolCallEvents;

@@ -829,3 +860,3 @@ const hasToolCalls = toolCallEvents.length > 0;

}
: { normalized: hasToolCalls ? "tool-calls" : "unknown" };
: { normalized: hasToolCalls ? "tool-calls" : "stop" };
const metadata = reasoningMetadata(state.reasoningField, state.reasoningDetailsObserved ? state.reasoningDetails : undefined);

@@ -840,3 +871,3 @@ const started = state.reasoningDetailsObserved && !state.reasoningEmitted

return events;
};
});
// =============================================================================

@@ -869,2 +900,3 @@ // Protocol And OpenAI Route

nextToolIndex: 0,
requireFinishReason: request.model.compatibility?.requireFinishReason ?? true,
}),

@@ -871,0 +903,0 @@ step,

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

} | undefined;
readonly arguments?: string | undefined;
readonly param?: string | null | undefined;

@@ -314,0 +315,0 @@ readonly status_code?: unknown;

@@ -169,2 +169,3 @@ import { Protocol } from "../route/protocol.js";

} | undefined;
readonly arguments?: string | undefined;
readonly param?: string | null | undefined;

@@ -171,0 +172,0 @@ readonly status_code?: unknown;

@@ -286,3 +286,5 @@ import { Schema } from "effect";

}, string, {
readonly [x: string]: unknown;
readonly error?: {
readonly [x: string]: unknown;
readonly message: string;

@@ -289,0 +291,0 @@ readonly code?: string | number | null | undefined;

@@ -126,3 +126,13 @@ import { Cause, Context, Effect, Layer, Schema, Stream } from "effect";

const events = execution.frames.pipe(Stream.mapEffect(decodeEvent(route)), protocol.stream.terminal ? Stream.takeUntil(protocol.stream.terminal) : (stream) => stream);
const stream = events.pipe(Stream.mapAccumEffect(() => protocol.stream.initial(request), protocol.stream.step, protocol.stream.onHalt ? { onHalt: protocol.stream.onHalt } : undefined), Stream.catchCause((cause) => Stream.fail(streamError(route, `Failed to read ${route} stream`, cause))), requireTerminalEvent(route));
const stream = Stream.suspend(() => {
let state = protocol.stream.initial(request);
const parsed = events.pipe(Stream.mapEffect((event) => protocol.stream.step(state, event).pipe(Effect.map(([next, output]) => {
state = next;
return output;
}))), Stream.flatMap(Stream.fromIterable));
const onHalt = protocol.stream.onHalt;
return onHalt
? parsed.pipe(Stream.concat(Stream.suspend(() => Stream.unwrap(onHalt(state).pipe(Effect.map(Stream.fromIterable))))))
: parsed;
}).pipe(Stream.catchCause((cause) => Stream.fail(streamError(route, `Failed to read ${route} stream`, cause))), requireTerminalEvent(route));
return execution.complete ? stream.pipe(Stream.onEnd(execution.complete)) : stream;

@@ -129,0 +139,0 @@ })));

@@ -59,4 +59,4 @@ import { Schema, type Effect } from "effect";

readonly terminal?: (event: Event) => boolean;
/** Optional flush emitted when the framed stream ends. */
readonly onHalt?: (state: State) => ReadonlyArray<LLMEvent>;
/** Optional effectful flush emitted when the framed stream ends. */
readonly onHalt?: (state: State) => Effect.Effect<ReadonlyArray<LLMEvent>, AIError>;
}

@@ -63,0 +63,0 @@ /**

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

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

"@effect/platform-node": "4.0.0-rc.111",
"@opencode-ai/http-recorder": "0.0.0-beta-18148",
"@opencode-ai/http-recorder": "0.0.0-beta-18155",
"@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-18148",
"@opencode-ai/schema": "0.0.0-beta-18155",
"aws4fetch": "1.0.20",

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