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

@opencode-ai/ai

Package Overview
Dependencies
Maintainers
2
Versions
1002
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-18314
to
0.0.0-beta-18371
+1
-0
dist/protocols/anthropic-messages.d.ts

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

}, {
providerMetadataKey: string;
tools: Partial<Record<number, ToolStream.PendingTool>>;

@@ -608,0 +609,0 @@ reasoningSignatures: {};

+36
-31

@@ -316,14 +316,14 @@ import { Buffer } from "node:buffer";

};
const anthropicMetadata = (metadata) => ({ anthropic: metadata });
const signatureFromMetadata = (metadata) => {
const anthropic = metadata?.anthropic;
if (!ProviderShared.isRecord(anthropic))
const providerMetadata = (key, metadata) => ({ [key]: metadata });
const signatureFromMetadata = (metadata, key) => {
const provider = metadata?.[key];
if (!ProviderShared.isRecord(provider))
return undefined;
return typeof anthropic.signature === "string" ? anthropic.signature : undefined;
return typeof provider.signature === "string" ? provider.signature : undefined;
};
const redactedDataFromMetadata = (metadata) => {
const anthropic = metadata?.anthropic;
if (!ProviderShared.isRecord(anthropic))
const redactedDataFromMetadata = (metadata, key) => {
const provider = metadata?.[key];
if (!ProviderShared.isRecord(provider))
return undefined;
return typeof anthropic.redactedData === "string" ? anthropic.redactedData : undefined;
return typeof provider.redactedData === "string" ? provider.redactedData : undefined;
};

@@ -383,3 +383,3 @@ const lowerTool = (breakpoints, tool, inputSchema) => ({

};
const lowerServerToolResult = Effect.fn("AnthropicMessages.lowerServerToolResult")(function* (part) {
const lowerServerToolResult = Effect.fn("AnthropicMessages.lowerServerToolResult")(function* (part, providerMetadataKey) {
const wireType = serverToolResultType(part.name);

@@ -390,3 +390,3 @@ if (!wireType)

// histories constructed directly from provider events.
const payload = part.providerMetadata?.anthropic?.["result"] ?? part.result.value;
const payload = part.providerMetadata?.[providerMetadataKey]?.["result"] ?? part.result.value;
return {

@@ -664,2 +664,3 @@ type: wireType,

const messages = [];
const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
for (const [index, message] of request.messages.entries()) {

@@ -708,4 +709,4 @@ if (message.role === "system") {

// redactedData round-trip as opaque redacted_thinking blocks.
const signature = part.encrypted ?? signatureFromMetadata(part.providerMetadata);
const redactedData = redactedDataFromMetadata(part.providerMetadata);
const signature = part.encrypted ?? signatureFromMetadata(part.providerMetadata, providerMetadataKey);
const redactedData = redactedDataFromMetadata(part.providerMetadata, providerMetadataKey);
if (signature === undefined && redactedData !== undefined) {

@@ -740,3 +741,3 @@ content.push({ type: "redacted_thinking", data: redactedData });

if (part.type === "tool-result" && part.providerExecuted) {
content.push(yield* lowerServerToolResult(part));
content.push(yield* lowerServerToolResult(part, providerMetadataKey));
continue;

@@ -906,3 +907,3 @@ }

// expose that subset through `output_tokens_details.thinking_tokens`.
const mapUsage = (usage) => {
const mapUsage = (usage, providerMetadataKey) => {
if (!usage)

@@ -922,3 +923,3 @@ return undefined;

totalTokens: ProviderShared.totalTokens(inputTokens, usage.output_tokens, undefined),
providerMetadata: { anthropic: usage },
providerMetadata: { [providerMetadataKey]: usage },
});

@@ -931,3 +932,3 @@ };

// consistent with `nonCached + cacheRead + cacheWrite`.
const mergeUsage = (left, right) => {
const mergeUsage = (left, right, providerMetadataKey) => {
if (!left)

@@ -952,3 +953,4 @@ return right;

providerMetadata: {
anthropic: mergeJsonRecords(left.providerMetadata?.["anthropic"], right.providerMetadata?.["anthropic"]) ?? {},
[providerMetadataKey]: mergeJsonRecords(left.providerMetadata?.[providerMetadataKey], right.providerMetadata?.[providerMetadataKey]) ??
{},
},

@@ -968,3 +970,3 @@ });

const isServerToolResultType = (type) => type in SERVER_TOOL_RESULT_NAMES;
const serverToolResultEvent = (block) => {
const serverToolResultEvent = (block, providerMetadataKey) => {
if (!block.type || !isServerToolResultType(block.type))

@@ -983,3 +985,3 @@ return undefined;

// stateless requests must round-trip the typed result block verbatim.
providerMetadata: anthropicMetadata({ blockType: block.type, result: block.content }),
providerMetadata: providerMetadata(providerMetadataKey, { blockType: block.type, result: block.content }),
});

@@ -989,4 +991,4 @@ };

const onMessageStart = (state, event) => {
const usage = mapUsage(event.message?.usage);
return [usage ? { ...state, usage: mergeUsage(state.usage, usage) } : state, NO_EVENTS];
const usage = mapUsage(event.message?.usage, state.providerMetadataKey);
return [usage ? { ...state, usage: mergeUsage(state.usage, usage, state.providerMetadataKey) } : state, NO_EVENTS];
};

@@ -1037,4 +1039,6 @@ const onContentBlockStart = (state, event) => {

const id = `reasoning-${event.index ?? 0}`;
const providerMetadata = block.signature === undefined ? undefined : anthropicMetadata({ signature: block.signature });
const lifecycle = Lifecycle.reasoningStart(state.lifecycle, events, id, providerMetadata);
const metadata = block.signature === undefined
? undefined
: providerMetadata(state.providerMetadataKey, { signature: block.signature });
const lifecycle = Lifecycle.reasoningStart(state.lifecycle, events, id, metadata);
return [

@@ -1044,3 +1048,3 @@ {

lifecycle: block.thinking
? Lifecycle.reasoningDelta(lifecycle, events, id, block.thinking, providerMetadata)
? Lifecycle.reasoningDelta(lifecycle, events, id, block.thinking, metadata)
: lifecycle,

@@ -1062,3 +1066,3 @@ reasoningSignatures: event.index === undefined || block.signature === undefined

...state,
lifecycle: Lifecycle.reasoningStart(state.lifecycle, events, `reasoning-${event.index ?? 0}`, anthropicMetadata({ redactedData: block.data })),
lifecycle: Lifecycle.reasoningStart(state.lifecycle, events, `reasoning-${event.index ?? 0}`, providerMetadata(state.providerMetadataKey, { redactedData: block.data })),
},

@@ -1068,3 +1072,3 @@ events,

}
const result = serverToolResultEvent(block);
const result = serverToolResultEvent(block, state.providerMetadataKey);
if (!result)

@@ -1134,3 +1138,3 @@ return [state, NO_EVENTS];

? Lifecycle.stepStart(state.lifecycle, events)
: Lifecycle.reasoningEnd(Lifecycle.textEnd(state.lifecycle, events, `text-${event.index}`), events, `reasoning-${event.index}`, signature === undefined ? undefined : anthropicMetadata({ signature }));
: Lifecycle.reasoningEnd(Lifecycle.textEnd(state.lifecycle, events, `text-${event.index}`), events, `reasoning-${event.index}`, signature === undefined ? undefined : providerMetadata(state.providerMetadataKey, { signature }));
events.push(...resultEvents);

@@ -1142,3 +1146,3 @@ const reasoningSignatures = { ...state.reasoningSignatures };

const onMessageDelta = (state, event) => {
const usage = mergeUsage(state.usage, mapUsage(event.usage));
const usage = mergeUsage(state.usage, mapUsage(event.usage, state.providerMetadataKey), state.providerMetadataKey);
return [

@@ -1155,3 +1159,3 @@ {

? undefined
: anthropicMetadata({ stopSequence: event.delta.stop_sequence }),
: providerMetadata(state.providerMetadataKey, { stopSequence: event.delta.stop_sequence }),
},

@@ -1269,3 +1273,4 @@ },

event: Protocol.jsonEvent(AnthropicEvent),
initial: () => ({
initial: (request) => ({
providerMetadataKey: request.model.route.providerMetadataKey ?? String(request.model.provider),
tools: ToolStream.empty(),

@@ -1272,0 +1277,0 @@ reasoningSignatures: {},

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

interface ParserState {
readonly providerMetadataKey: string;
readonly tools: ToolStream.State<number>;

@@ -132,0 +133,0 @@ readonly pendingFinish: {

@@ -184,11 +184,13 @@ import { Effect, Schema } from "effect";

});
const bedrockMetadata = (metadata) => ({ bedrock: metadata });
const reasoningSignature = (part) => {
const bedrock = part.providerMetadata?.bedrock;
const providerMetadata = (key, metadata) => ({ [key]: metadata });
const reasoningSignature = (part, providerMetadataKey) => {
const metadata = part.providerMetadata?.[providerMetadataKey];
return (part.encrypted ??
(ProviderShared.isRecord(bedrock) && typeof bedrock.signature === "string" ? bedrock.signature : undefined));
(ProviderShared.isRecord(metadata) && typeof metadata.signature === "string" ? metadata.signature : undefined));
};
const reasoningRedactedData = (part) => {
const bedrock = part.providerMetadata?.bedrock;
return ProviderShared.isRecord(bedrock) && typeof bedrock.redactedData === "string" ? bedrock.redactedData : undefined;
const reasoningRedactedData = (part, providerMetadataKey) => {
const metadata = part.providerMetadata?.[providerMetadataKey];
return ProviderShared.isRecord(metadata) && typeof metadata.redactedData === "string"
? metadata.redactedData
: undefined;
};

@@ -234,2 +236,3 @@ const lowerToolCall = (part) => ({

const messages = [];
const providerMetadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
for (const message of request.messages) {

@@ -281,4 +284,4 @@ if (message.role === "system") {

if (part.type === "reasoning") {
const signature = reasoningSignature(part);
const redactedData = reasoningRedactedData(part);
const signature = reasoningSignature(part, providerMetadataKey);
const redactedData = reasoningRedactedData(part, providerMetadataKey);
if (signature === undefined && redactedData !== undefined) {

@@ -377,3 +380,3 @@ content.push({ reasoningContent: { redactedContent: redactedData } });

// Bedrock does not break reasoning out of outputTokens for current models.
const mapUsage = (usage) => {
const mapUsage = (usage, providerMetadataKey) => {
if (!usage)

@@ -389,3 +392,3 @@ return undefined;

totalTokens: ProviderShared.totalTokens(inputTokens, usage.outputTokens, usage.totalTokens),
providerMetadata: { bedrock: usage },
providerMetadata: { [providerMetadataKey]: usage },
});

@@ -431,9 +434,9 @@ };

const redactedData = reasoning.redactedContent ?? reasoning.data;
const providerMetadata = reasoning.signature
? bedrockMetadata({ signature: reasoning.signature })
const metadata = reasoning.signature
? providerMetadata(state.providerMetadataKey, { signature: reasoning.signature })
: redactedData !== undefined
? bedrockMetadata({ redactedData })
? providerMetadata(state.providerMetadataKey, { redactedData })
: undefined;
const lifecycle = reasoning.text !== undefined || providerMetadata !== undefined
? Lifecycle.reasoningDelta(state.lifecycle, events, `reasoning-${index}`, reasoning.text ?? "", providerMetadata)
const lifecycle = reasoning.text !== undefined || metadata !== undefined
? Lifecycle.reasoningDelta(state.lifecycle, events, `reasoning-${index}`, reasoning.text ?? "", metadata)
: state.lifecycle;

@@ -469,3 +472,3 @@ return [

: Lifecycle.reasoningEnd(Lifecycle.textEnd(state.lifecycle, events, `text-${index}`), events, `reasoning-${index}`, state.reasoningSignatures[index]
? bedrockMetadata({ signature: state.reasoningSignatures[index] })
? providerMetadata(state.providerMetadataKey, { signature: state.reasoningSignatures[index] })
: undefined);

@@ -501,3 +504,3 @@ events.push(...resultEvents);

if (event.metadata) {
const usage = mapUsage(event.metadata.usage) ?? state.pendingFinish?.usage;
const usage = mapUsage(event.metadata.usage, state.providerMetadataKey) ?? state.pendingFinish?.usage;
return [

@@ -559,3 +562,4 @@ {

event: BedrockEvent,
initial: () => ({
initial: (request) => ({
providerMetadataKey: request.model.route.providerMetadataKey ?? String(request.model.provider),
tools: ToolStream.empty(),

@@ -562,0 +566,0 @@ pendingFinish: undefined,

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

route: string;
providerMetadataKey: string;
hasToolCalls: boolean;

@@ -202,0 +203,0 @@ lifecycle: Lifecycle.State;

@@ -200,15 +200,16 @@ import { Effect, Option, Schema } from "effect";

});
const googleMetadata = (metadata) => ({ google: metadata });
const thoughtSignature = (providerMetadata) => {
const google = providerMetadata?.google;
return ProviderShared.isRecord(google) && typeof google.thoughtSignature === "string"
? google.thoughtSignature
const providerMetadata = (key, metadata) => ({ [key]: metadata });
const thoughtSignature = (metadata, key) => {
const value = metadata?.[key];
return ProviderShared.isRecord(value) && typeof value.thoughtSignature === "string"
? value.thoughtSignature
: undefined;
};
const lowerToolCall = (part, omitIds) => ({
const lowerToolCall = (part, omitIds, metadataKey) => ({
functionCall: { ...(omitIds ? {} : { id: part.id }), name: part.name, args: part.input },
thoughtSignature: thoughtSignature(part.providerMetadata),
thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey),
});
const lowerMessages = Effect.fn("Gemini.lowerMessages")(function* (request) {
const contents = [];
const metadataKey = request.model.route.providerMetadataKey ?? String(request.model.provider);
const omitCallIds = omitsFunctionCallIds(request.model.id);

@@ -255,11 +256,15 @@ const legacyToolMedia = routesLegacyToolMedia(request.model.id);

if (part.type === "text") {
parts.push({ text: part.text, thoughtSignature: thoughtSignature(part.providerMetadata) });
parts.push({ text: part.text, thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey) });
continue;
}
if (part.type === "reasoning") {
parts.push({ text: part.text, thought: true, thoughtSignature: thoughtSignature(part.providerMetadata) });
parts.push({
text: part.text,
thought: true,
thoughtSignature: thoughtSignature(part.providerMetadata, metadataKey),
});
continue;
}
if (part.type === "tool-call") {
const lowered = lowerToolCall(part, omitCallIds);
const lowered = lowerToolCall(part, omitCallIds, metadataKey);
const signature = lowered.thoughtSignature;

@@ -401,3 +406,3 @@ parts.push({

// to produce the inclusive `outputTokens` the rest of the contract expects.
const mapUsage = (usage) => {
const mapUsage = (usage, metadataKey) => {
if (!usage)

@@ -424,3 +429,3 @@ return undefined;

totalTokens: ProviderShared.totalTokens(promptTokens, outputTokens, usage.totalTokenCount ?? undefined),
providerMetadata: { google: usage },
providerMetadata: providerMetadata(metadataKey, usage),
});

@@ -465,5 +470,5 @@ };

if (state.reasoningSignature !== undefined)
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", googleMetadata({ thoughtSignature: state.reasoningSignature }));
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", providerMetadata(state.providerMetadataKey, { thoughtSignature: state.reasoningSignature }));
if (state.textSignature !== undefined)
lifecycle = Lifecycle.textEnd(lifecycle, events, "text-0", googleMetadata({ thoughtSignature: state.textSignature }));
lifecycle = Lifecycle.textEnd(lifecycle, events, "text-0", providerMetadata(state.providerMetadataKey, { thoughtSignature: state.textSignature }));
Lifecycle.finish(lifecycle, events, {

@@ -475,3 +480,5 @@ reason: {

usage: state.usage,
providerMetadata: state.promptFeedback === undefined ? undefined : googleMetadata({ promptFeedback: state.promptFeedback }),
providerMetadata: state.promptFeedback === undefined
? undefined
: providerMetadata(state.providerMetadataKey, { promptFeedback: state.promptFeedback }),
});

@@ -484,3 +491,5 @@ return events;

promptFeedback: event.promptFeedback ?? state.promptFeedback,
usage: event.usageMetadata ? (mapUsage(event.usageMetadata) ?? state.usage) : state.usage,
usage: event.usageMetadata
? (mapUsage(event.usageMetadata, state.providerMetadataKey) ?? state.usage)
: state.usage,
};

@@ -520,7 +529,9 @@ const candidate = event.candidates?.[0];

if (part.thought) {
lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", part.text, signature ? googleMetadata({ thoughtSignature: signature }) : undefined);
lifecycle = Lifecycle.reasoningDelta(lifecycle, events, "reasoning-0", part.text, signature ? providerMetadata(state.providerMetadataKey, { thoughtSignature: signature }) : undefined);
continue;
}
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningSignature ? googleMetadata({ thoughtSignature: reasoningSignature }) : undefined);
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", part.text, textSignature ? googleMetadata({ thoughtSignature: textSignature }) : undefined);
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningSignature
? providerMetadata(state.providerMetadataKey, { thoughtSignature: reasoningSignature })
: undefined);
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", part.text, textSignature ? providerMetadata(state.providerMetadataKey, { thoughtSignature: textSignature }) : undefined);
textSignature = undefined;

@@ -540,3 +551,5 @@ continue;

const id = supplied !== undefined && !duplicate ? supplied : `tool_${crypto.randomUUID().replaceAll("-", "")}`;
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningSignature ? googleMetadata({ thoughtSignature: reasoningSignature }) : undefined);
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningSignature
? providerMetadata(state.providerMetadataKey, { thoughtSignature: reasoningSignature })
: undefined);
lifecycle = Lifecycle.stepStart(lifecycle, events);

@@ -548,3 +561,3 @@ events.push(LLMEvent.toolCall({

providerMetadata: part.thoughtSignature
? googleMetadata({ thoughtSignature: part.thoughtSignature })
? providerMetadata(state.providerMetadataKey, { thoughtSignature: part.thoughtSignature })
: undefined,

@@ -585,2 +598,3 @@ }));

route: `${request.model.provider}/${request.model.route.id}`,
providerMetadataKey: request.model.route.providerMetadataKey ?? String(request.model.provider),
hasToolCalls: false,

@@ -587,0 +601,0 @@ lifecycle: Lifecycle.initial(),

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

readonly summary_index: Schema.optional<Schema.Number>;
readonly item: Schema.optional<Schema.StructWithRest<Schema.Struct<{
readonly item: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
readonly type: Schema.String;

@@ -506,3 +506,3 @@ readonly id: Schema.optional<Schema.String>;

readonly encrypted_content: Schema.optional<Schema.NullOr<Schema.String>>;
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>;
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
readonly response: Schema.optional<Schema.StructWithRest<Schema.Struct<{

@@ -1170,3 +1170,3 @@ readonly id: Schema.optional<Schema.String>;

readonly call_id?: string | undefined;
} | undefined;
} | null | undefined;
readonly delta?: string | undefined;

@@ -1173,0 +1173,0 @@ readonly response?: {

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

summary_index: Schema.optional(Schema.Number),
item: Schema.optional(StreamItem),
// OutputItemAdded/Done permit a null item in the Open Responses OpenAPI schema.
item: optionalNull(StreamItem),
response: Schema.optional(Schema.StructWithRest(Schema.Struct({

@@ -602,3 +603,3 @@ id: Schema.optional(Schema.String),

});
const isReasoningItem = (item) => item.type === "reasoning" && typeof item.id === "string" && item.id.length > 0;
const isReasoningItem = (item) => item.type === "reasoning" && typeof item.id === "string";
const NO_EVENTS = [];

@@ -674,3 +675,3 @@ // `response.completed` / `response.incomplete` are clean finishes that emit a

const item = event.item;
if (item?.type === "message" && item.id) {
if (item?.type === "message" && item.id !== undefined) {
const phase = messagePhase(item.phase);

@@ -707,3 +708,3 @@ return [

const id = item.id ?? item.call_id;
const metadata = item.id ? providerMetadata(state, { itemId: item.id }) : undefined;
const metadata = item.id !== undefined ? providerMetadata(state, { itemId: item.id }) : undefined;
const events = [];

@@ -726,3 +727,3 @@ const lifecycle = Lifecycle.stepStart(state.lifecycle, events);

const onReasoningSummaryPartAdded = (state, event) => {
if (!event.item_id || event.summary_index === undefined)
if (event.item_id === undefined || event.summary_index === undefined)
return [state, NO_EVENTS];

@@ -757,3 +758,3 @@ const item = state.reasoningItems[event.item_id];

const onReasoningSummaryPartDone = (state, event) => {
if (!event.item_id || event.summary_index === undefined)
if (event.item_id === undefined || event.summary_index === undefined)
return [state, NO_EVENTS];

@@ -781,3 +782,3 @@ const item = state.reasoningItems[event.item_id];

const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgumentsDelta")(function* (state, event) {
if (!event.item_id)
if (event.item_id === undefined)
return [state, NO_EVENTS];

@@ -810,3 +811,3 @@ const tool = state.tools[event.item_id];

return [state, NO_EVENTS];
if (item.type === "message" && item.id) {
if (item.type === "message" && item.id !== undefined) {
const itemPhase = messagePhase(item.phase);

@@ -837,3 +838,3 @@ const phase = itemPhase === undefined ? state.messagePhases[item.id] : itemPhase;

name: item.name,
providerMetadata: item.id ? providerMetadata(state, { itemId: item.id }) : undefined,
providerMetadata: item.id !== undefined ? providerMetadata(state, { itemId: item.id }) : undefined,
});

@@ -886,3 +887,3 @@ const result = item.arguments === undefined

const id = item.id ?? (item.type === "function_call" ? item.call_id : undefined);
if (!id ||
if (id === undefined ||
((item.type !== "function_call" || !current.tools[id]) &&

@@ -958,7 +959,8 @@ (item.type !== "reasoning" || !current.reasoningItems[id])))

export const step = (state, input) => {
const event = input.item_id && outputItemID(state, input) !== input.item_id
// The OpenAPI requires string IDs but imposes no minLength; empty is not missing.
const event = input.item_id !== undefined && outputItemID(state, input) !== input.item_id
? { ...input, item_id: outputItemID(state, input) }
: input;
if (event.type === "response.output_text.delta" || event.type === "response.output_text.done") {
if (!event.item_id)
if (event.item_id === undefined)
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);

@@ -971,3 +973,3 @@ return Effect.succeed(event.type === "response.output_text.delta"

const value = event.type === "response.refusal.delta" ? event.delta : event.refusal;
if (!event.item_id || typeof value !== "string")
if (event.item_id === undefined || typeof value !== "string")
return ProviderShared.eventError(state.id, `${event.type} is malformed`);

@@ -979,3 +981,3 @@ return Effect.succeed(event.type === "response.refusal.delta"

if (event.type === "response.reasoning.delta" || event.type === "response.reasoning_summary_text.delta") {
if (!event.item_id)
if (event.item_id === undefined)
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);

@@ -987,3 +989,3 @@ return Effect.succeed(onReasoningDelta(state, event, event.item_id));

event.type === "response.reasoning_text.done") {
if (!event.item_id)
if (event.item_id === undefined)
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);

@@ -993,14 +995,14 @@ return Effect.succeed(onReasoningDone(state, event, event.item_id));

if (event.type === "response.reasoning_summary_part.added")
return event.item_id
return event.item_id !== undefined
? Effect.succeed(onReasoningSummaryPartAdded(state, event))
: ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
if (event.type === "response.reasoning_summary_part.done")
return event.item_id
return event.item_id !== undefined
? Effect.succeed(onReasoningSummaryPartDone(state, event))
: ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
if (event.type === "response.output_item.added") {
if (event.item?.type === "message" && !event.item.id)
if (event.item?.type === "message" && event.item.id === undefined)
return ProviderShared.eventError(state.id, `${event.type} message is missing id`);
const id = event.item?.id ?? (event.item?.type === "function_call" ? event.item.call_id : undefined);
return Effect.succeed(onOutputItemAdded(event.output_index !== undefined && id
return Effect.succeed(onOutputItemAdded(event.output_index !== undefined && id !== undefined
? { ...state, outputItems: { ...state.outputItems, [event.output_index]: id } }

@@ -1010,7 +1012,7 @@ : state, event));

if (event.type === "response.function_call_arguments.delta" || event.type === "response.function_call_arguments.done")
return event.item_id
return event.item_id !== undefined
? onFunctionCallArgumentsDelta(state, event)
: ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
if (event.type === "response.output_item.done") {
if (event.item?.type === "message" && !event.item.id)
if (event.item?.type === "message" && event.item.id === undefined)
return ProviderShared.eventError(state.id, `${event.type} message is missing id`);

@@ -1017,0 +1019,0 @@ return onOutputItemDone(state, event);

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

export interface ParserState {
readonly providerMetadataKey: string;
readonly tools: ToolStream.State<number>;

@@ -274,0 +275,0 @@ readonly pendingTools: Partial<Record<number, PendingToolDelta>>;

@@ -210,12 +210,12 @@ import { Effect, Schema } from "effect";

const openAICompatibleReasoningContent = (native) => isRecord(native) && typeof native.reasoning_content === "string" ? native.reasoning_content : undefined;
const reasoningField = (part) => {
const field = part.providerMetadata?.openai?.reasoningField;
const reasoningField = (part, providerMetadataKey) => {
const field = part.providerMetadata?.[providerMetadataKey]?.reasoningField;
return typeof field === "string" ? field : undefined;
};
const reasoningDetails = (parts, native) => {
const reasoningDetails = (parts, native, providerMetadataKey) => {
const observed = parts.flatMap((part) => {
const details = part.providerMetadata?.openai?.reasoningDetails;
const details = part.providerMetadata?.[providerMetadataKey]?.reasoningDetails;
return Array.isArray(details) ? details : [];
});
if (parts.some((part) => Array.isArray(part.providerMetadata?.openai?.reasoningDetails)))
if (parts.some((part) => Array.isArray(part.providerMetadata?.[providerMetadataKey]?.reasoningDetails)))
return observed;

@@ -266,6 +266,8 @@ if (isRecord(native) && Array.isArray(native.reasoning_details))

const text = reasoning.map((part) => part.text).join("");
const details = reasoningDetails(reasoning, message.native?.openaiCompatible);
const observedField = reasoning.map(reasoningField).find((value) => value !== undefined);
const details = reasoningDetails(reasoning, message.native?.openaiCompatible, options.providerMetadataKey);
const observedField = reasoning
.map((part) => reasoningField(part, options.providerMetadataKey))
.find((value) => value !== undefined);
const nativeReasoning = openAICompatibleReasoningContent(message.native?.openaiCompatible);
const fullyStructured = reasoning.every((part) => Array.isArray(part.providerMetadata?.openai?.reasoningDetails));
const fullyStructured = reasoning.every((part) => Array.isArray(part.providerMetadata?.[options.providerMetadataKey]?.reasoningDetails));
const field = (() => {

@@ -364,2 +366,3 @@ if (configuredField !== undefined && (requireReasoning || reasoning.length > 0 || nativeReasoning !== undefined))

...options,
providerMetadataKey: request.model.route.providerMetadataKey ?? String(request.model.provider),
toolCallID: (id) => {

@@ -650,3 +653,3 @@ if (mistral)

// `prompt_cache_hit_tokens`, and Zai uses top-level `cached_tokens`.
const mapUsage = (usage) => {
const mapUsage = (usage, providerMetadataKey) => {
if (!usage)

@@ -671,3 +674,3 @@ return undefined;

totalTokens: ProviderShared.totalTokens(input, output, usage.total_tokens ?? undefined),
providerMetadata: { openai: usage },
providerMetadata: { [providerMetadataKey]: usage },
});

@@ -733,4 +736,4 @@ };

const conflictingDetailValue = (previous, current) => previous !== undefined && previous !== null && current !== undefined && current !== null && previous !== current;
const reasoningMetadata = (field, details) => ({
openai: {
const reasoningMetadata = (providerMetadataKey, field, details) => ({
[providerMetadataKey]: {
...(field ? { reasoningField: field } : {}),

@@ -760,3 +763,5 @@ ...(details ? { reasoningDetails: details } : {}),

const choiceUsage = choice?.usage;
const usage = mapUsage(event.usage) ?? (choiceUsage ? mapUsage(choiceUsage) : undefined) ?? state.usage;
const usage = mapUsage(event.usage, state.providerMetadataKey) ??
(choiceUsage ? mapUsage(choiceUsage, state.providerMetadataKey) : undefined) ??
state.usage;
const rawFinishReason = choice?.finish_reason;

@@ -792,3 +797,3 @@ const finishReason = rawFinishReason

const reasoningDetailsObserved = state.reasoningDetailsObserved || detailDelta !== undefined;
const deltaMetadata = reasoningMetadata(reasoningField);
const deltaMetadata = reasoningMetadata(state.providerMetadataKey, reasoningField);
const text = detailDelta?.length ? (detailText(detailDelta) ?? reasoning?.text) : reasoning?.text;

@@ -803,7 +808,7 @@ if (text !== undefined)

if (delta?.content) {
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(state.providerMetadataKey, reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", delta.content);
}
if (delta?.refusal) {
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
lifecycle = Lifecycle.reasoningEnd(lifecycle, events, "reasoning-0", reasoningMetadata(state.providerMetadataKey, reasoningField, reasoningDetailsObserved ? state.reasoningDetails : undefined));
lifecycle = Lifecycle.textDelta(lifecycle, events, "text-0", delta.refusal);

@@ -853,2 +858,3 @@ }

{
providerMetadataKey: state.providerMetadataKey,
tools: finished?.tools ?? tools,

@@ -893,5 +899,5 @@ pendingTools,

: { normalized: hasToolCalls ? "tool-calls" : "stop" };
const metadata = reasoningMetadata(state.reasoningField, state.reasoningDetailsObserved ? state.reasoningDetails : undefined);
const metadata = reasoningMetadata(state.providerMetadataKey, state.reasoningField, state.reasoningDetailsObserved ? state.reasoningDetails : undefined);
const started = state.reasoningDetailsObserved && !state.reasoningEmitted
? Lifecycle.reasoningStart(state.lifecycle, events, "reasoning-0", reasoningMetadata(state.reasoningField))
? Lifecycle.reasoningStart(state.lifecycle, events, "reasoning-0", reasoningMetadata(state.providerMetadataKey, state.reasoningField))
: state.lifecycle;

@@ -922,2 +928,3 @@ const ended = Lifecycle.reasoningEnd(started, events, "reasoning-0", metadata);

initial: (request) => ({
providerMetadataKey: request.model.route.providerMetadataKey ?? String(request.model.provider),
tools: ToolStream.empty(),

@@ -924,0 +931,0 @@ pendingTools: {},

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

readonly call_id?: string | undefined;
} | undefined;
} | null | undefined;
readonly delta?: string | undefined;

@@ -392,0 +392,0 @@ readonly response?: {

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

if (event.type === "response.reasoning_text.delta")
return event.item_id
return event.item_id !== undefined
? Effect.succeed(OpenResponses.onReasoningDelta(state, event, OpenResponses.outputItemID(state, event) ?? event.item_id))

@@ -153,0 +153,0 @@ : ProviderShared.eventError(ADAPTER, `${event.type} is missing item_id`);

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

readonly call_id?: string | undefined;
} | undefined;
} | null | undefined;
readonly delta?: string | undefined;

@@ -193,0 +193,0 @@ readonly response?: {

@@ -20,2 +20,3 @@ import { Route, type RouteDefaultsInput } from "../route/client.js";

readonly region?: string;
readonly topP?: number;
readonly providerOptions?: OpenAIProviderOptionsInput;

@@ -22,0 +23,0 @@ }

@@ -12,3 +12,3 @@ import { Auth } from "../route/auth.js";

provider: id,
providerMetadataKey: OpenAIResponses.route.providerMetadataKey,
providerMetadataKey: "mantle",
protocol: OpenAIResponses.protocol,

@@ -23,2 +23,3 @@ endpoint: OpenAIResponses.route.endpoint,

provider: id,
providerMetadataKey: "mantle",
});

@@ -52,3 +53,3 @@ export const routes = [responsesRoute, chatRoute];

id,
model: chat,
model: responses,
chat,

@@ -69,2 +70,3 @@ responses,

credentials: settings.credentials,
generation: settings.topP === undefined ? undefined : { topP: settings.topP },
headers: settings.headers === undefined ? undefined : { ...settings.headers },

@@ -78,2 +80,2 @@ http: settings.body === undefined ? undefined : { body: { ...settings.body } },

export const responsesModel = (modelID, settings) => configure(config(settings)).responses(modelID);
export const model = chatModel;
export const model = responsesModel;

@@ -13,2 +13,3 @@ import { Auth } from "../route/auth.js";

provider: id,
providerMetadataKey: "bedrock",
endpoint: { baseURL: baseURL ?? bedrockBaseURL(resolvedRegion) },

@@ -15,0 +16,0 @@ auth: apiKey === undefined ? BedrockConverse.sigV4Auth(credentials) : Auth.bearer(apiKey),

@@ -1,2 +0,2 @@

export { chatModel as model } from "../amazon-bedrock-mantle.js";
export { responsesModel as model } from "../amazon-bedrock-mantle.js";
export type { Settings } from "../amazon-bedrock-mantle.js";

@@ -1,1 +0,1 @@

export { chatModel as model } from "../amazon-bedrock-mantle.js";
export { responsesModel as model } from "../amazon-bedrock-mantle.js";

@@ -8,2 +8,3 @@ import { OpenAICompatibleChat } from "../protocols/openai-compatible-chat.js";

provider: id,
providerMetadataKey: "vertex",
});

@@ -10,0 +11,0 @@ export const routes = [route];

@@ -8,2 +8,3 @@ import { OpenAICompatibleResponses } from "../protocols/openai-compatible-responses.js";

provider: id,
providerMetadataKey: "vertex",
providerOptions: { store: false },

@@ -10,0 +11,0 @@ });

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

provider: id,
providerMetadataKey: "google",
providerMetadataKey: "vertex",
protocol,

@@ -44,0 +44,0 @@ endpoint: Endpoint.path(({ request }) => {

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

provider: profile.provider,
providerMetadataKey: "openrouter",
protocol,

@@ -89,0 +90,0 @@ endpoint: Endpoint.path("/chat/completions", { baseURL: profile.baseURL }),

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

readonly provider?: string | ProviderID;
readonly providerMetadataKey?: string;
readonly auth?: Auth.Definition;

@@ -54,0 +55,0 @@ readonly transport?: Transport<Body, Prepared, unknown>;

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

with: (patch) => {
const { id, provider, auth, transport, endpoint, ...defaults } = patch;
const { id, provider, providerMetadataKey, auth, transport, endpoint, ...defaults } = patch;
return build({

@@ -107,2 +107,6 @@ ...routeInput,

provider: provider ?? routeInput.provider,
providerMetadataKey: providerMetadataKey ??
(provider !== undefined && String(provider) !== String(routeInput.provider)
? String(provider)
: routeInput.providerMetadataKey),
auth: auth ?? routeInput.auth,

@@ -109,0 +113,0 @@ endpoint: endpoint ? Endpoint.merge(routeInput.endpoint, endpoint) : routeInput.endpoint,

@@ -9,10 +9,2 @@ import { Cause, Context, Effect, Layer, Option, Schema, Stream } from "effect";

const normalizedHeaders = (headers) => Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]));
const requestId = (headers) => {
return (headers["x-request-id"] ??
headers["request-id"] ??
headers["x-amzn-requestid"] ??
headers["x-amz-request-id"] ??
headers["x-goog-request-id"] ??
headers["cf-ray"]);
};
const retryAfterMs = (headers) => {

@@ -99,3 +91,2 @@ const millis = Number(headers["retry-after-ms"]);

...input.body,
requestId: input.requestId,
rateLimit: input.rateLimit,

@@ -123,3 +114,2 @@ });

body: details,
requestId: requestId(headers),
rateLimit,

@@ -152,3 +142,2 @@ }),

...details,
requestId: requestId(headers),
rateLimit,

@@ -155,0 +144,0 @@ }),

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

readonly bodyTruncated: Schema.optional<Schema.Boolean>;
readonly requestId: Schema.optional<Schema.String>;
readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;

@@ -34,0 +33,0 @@ }>, {}>;

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

bodyTruncated: Schema.optional(Schema.Boolean),
requestId: Schema.optional(Schema.String),
rateLimit: Schema.optional(HttpRateLimitDetails),

@@ -32,0 +31,0 @@ }) {

{
"$schema": "https://json.schemastore.org/package.json",
"version": "0.0.0-beta-18314",
"version": "0.0.0-beta-18371",
"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-18314",
"@opencode-ai/http-recorder": "0.0.0-beta-18371",
"@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-18314",
"@opencode-ai/schema": "0.0.0-beta-18371",
"aws4fetch": "1.0.20",

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