@opencode-ai/ai 0.0.0-beta-18148 → 0.0.0-beta-18219
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/image-client.d.ts +1 -1
- package/dist/image-client.js +10 -1
- package/dist/protocols/anthropic-messages.d.ts +2 -21
- package/dist/protocols/anthropic-messages.js +55 -10
- package/dist/protocols/bedrock-converse.d.ts +16 -50
- package/dist/protocols/bedrock-converse.js +5 -16
- package/dist/protocols/bedrock-event-stream.js +1 -1
- package/dist/protocols/gemini.js +1 -1
- package/dist/protocols/open-responses-continuation.js +6 -1
- package/dist/protocols/open-responses.d.ts +25 -2
- package/dist/protocols/open-responses.js +49 -20
- package/dist/protocols/openai-chat.d.ts +7 -4
- package/dist/protocols/openai-chat.js +72 -29
- package/dist/protocols/openai-compatible-responses.js +1 -0
- package/dist/protocols/openai-responses.d.ts +11 -0
- package/dist/protocols/openai-responses.js +2 -2
- package/dist/protocols/shared.d.ts +1 -1
- package/dist/protocols/shared.js +4 -4
- package/dist/protocols/utils/partial-json.js +57 -2
- package/dist/protocols/utils/tool-stream.d.ts +1 -1
- package/dist/protocols/utils/tool-stream.js +15 -21
- package/dist/protocols/xai-responses.d.ts +11 -0
- package/dist/providers/openrouter.d.ts +2 -0
- package/dist/providers/openrouter.js +1 -3
- package/dist/providers/xai.js +1 -1
- package/dist/route/client.js +14 -2
- package/dist/route/protocol.d.ts +2 -2
- package/dist/schema/options.d.ts +1 -0
- package/dist/schema/options.js +1 -0
- package/dist/utils/sanitize.d.ts +1 -0
- package/dist/utils/sanitize.js +12 -0
- package/package.json +3 -3
package/dist/image-client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
2
|
import { RequestExecutor } from "./route/executor.js";
|
|
3
|
+
import { type AIError } from "./schema/index.js";
|
|
3
4
|
import type { ImageOptions, ImageRequestFor, ImageResponse } from "./image.js";
|
|
4
|
-
import type { AIError } from "./schema/index.js";
|
|
5
5
|
export type Execute = RequestExecutor.Interface["execute"];
|
|
6
6
|
export interface Interface {
|
|
7
7
|
readonly generate: <Options extends ImageOptions>(request: ImageRequestFor<Options>) => Effect.Effect<ImageResponse, AIError>;
|
package/dist/image-client.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from "effect";
|
|
2
2
|
import { RequestExecutor } from "./route/executor.js";
|
|
3
|
+
import { mergeHttpOptions } from "./schema/index.js";
|
|
4
|
+
import { sanitizeSurrogates } from "./utils/sanitize.js";
|
|
3
5
|
export class Service extends Context.Service()("@opencode/ImageClient") {
|
|
4
6
|
}
|
|
5
7
|
export const generate = (request) => Effect.gen(function* () {
|
|
@@ -9,7 +11,14 @@ export const generate = (request) => Effect.gen(function* () {
|
|
|
9
11
|
export const layer = Layer.effect(Service, Effect.gen(function* () {
|
|
10
12
|
const executor = yield* RequestExecutor.Service;
|
|
11
13
|
return Service.of({
|
|
12
|
-
generate: (request) => request.model.route.generate(
|
|
14
|
+
generate: (request) => request.model.route.generate({
|
|
15
|
+
...sanitizeSurrogates({
|
|
16
|
+
...request,
|
|
17
|
+
model: undefined,
|
|
18
|
+
http: mergeHttpOptions(request.model.http, request.http),
|
|
19
|
+
}),
|
|
20
|
+
model: request.model,
|
|
21
|
+
}, executor.execute),
|
|
13
22
|
});
|
|
14
23
|
}));
|
|
15
24
|
export const ImageClient = {
|
|
@@ -584,15 +584,7 @@ export declare const protocol: Protocol<{
|
|
|
584
584
|
readonly type?: string | undefined;
|
|
585
585
|
readonly message?: string | undefined;
|
|
586
586
|
} | undefined;
|
|
587
|
-
readonly delta?:
|
|
588
|
-
readonly type?: string | undefined;
|
|
589
|
-
readonly text?: string | undefined;
|
|
590
|
-
readonly thinking?: string | undefined;
|
|
591
|
-
readonly signature?: string | undefined;
|
|
592
|
-
readonly partial_json?: string | undefined;
|
|
593
|
-
readonly stop_reason?: string | null | undefined;
|
|
594
|
-
readonly stop_sequence?: string | null | undefined;
|
|
595
|
-
} | undefined;
|
|
587
|
+
readonly delta?: unknown;
|
|
596
588
|
readonly index?: number | undefined;
|
|
597
589
|
readonly usage?: {
|
|
598
590
|
readonly [x: string]: unknown;
|
|
@@ -609,18 +601,7 @@ export declare const protocol: Protocol<{
|
|
|
609
601
|
readonly thinking_tokens?: number | undefined;
|
|
610
602
|
} | null | undefined;
|
|
611
603
|
} | undefined;
|
|
612
|
-
readonly content_block?:
|
|
613
|
-
readonly type: string;
|
|
614
|
-
readonly id?: string | undefined;
|
|
615
|
-
readonly data?: string | undefined;
|
|
616
|
-
readonly name?: string | undefined;
|
|
617
|
-
readonly input?: unknown;
|
|
618
|
-
readonly text?: string | undefined;
|
|
619
|
-
readonly content?: unknown;
|
|
620
|
-
readonly thinking?: string | undefined;
|
|
621
|
-
readonly signature?: string | undefined;
|
|
622
|
-
readonly tool_use_id?: string | undefined;
|
|
623
|
-
} | undefined;
|
|
604
|
+
readonly content_block?: unknown;
|
|
624
605
|
}, {
|
|
625
606
|
tools: Partial<Record<number, ToolStream.PendingTool>>;
|
|
626
607
|
reasoningSignatures: {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
|
-
import { Effect, Schema } from "effect";
|
|
2
|
+
import { Effect, Option, Schema } from "effect";
|
|
3
3
|
import { Tool } from "@opencode-ai/schema/tool";
|
|
4
4
|
import { Route } from "../route/client.js";
|
|
5
5
|
import { Auth } from "../route/auth.js";
|
|
@@ -264,6 +264,7 @@ const AnthropicStreamBlock = Schema.Struct({
|
|
|
264
264
|
tool_use_id: Schema.optional(Schema.String),
|
|
265
265
|
content: Schema.optional(Schema.Unknown),
|
|
266
266
|
});
|
|
267
|
+
const decodeAnthropicStreamBlock = Schema.decodeUnknownOption(AnthropicStreamBlock);
|
|
267
268
|
const AnthropicStreamDelta = Schema.Struct({
|
|
268
269
|
type: Schema.optional(Schema.String),
|
|
269
270
|
text: Schema.optional(Schema.String),
|
|
@@ -273,12 +274,13 @@ const AnthropicStreamDelta = Schema.Struct({
|
|
|
273
274
|
stop_reason: optionalNull(Schema.String),
|
|
274
275
|
stop_sequence: optionalNull(Schema.String),
|
|
275
276
|
});
|
|
277
|
+
const decodeAnthropicStreamDelta = Schema.decodeUnknownOption(AnthropicStreamDelta);
|
|
276
278
|
const AnthropicEvent = Schema.Struct({
|
|
277
279
|
type: Schema.String,
|
|
278
280
|
index: Schema.optional(Schema.Number),
|
|
279
281
|
message: Schema.optional(Schema.Struct({ usage: Schema.optional(AnthropicUsage) })),
|
|
280
|
-
content_block: Schema.optional(
|
|
281
|
-
delta: Schema.optional(
|
|
282
|
+
content_block: Schema.optional(Schema.Unknown),
|
|
283
|
+
delta: Schema.optional(Schema.Unknown),
|
|
282
284
|
usage: Schema.optional(AnthropicUsage),
|
|
283
285
|
// `type` and `message` are both required per Anthropic's spec, but
|
|
284
286
|
// OpenAI-compatible proxies and gateway translations occasionally drop one
|
|
@@ -1044,6 +1046,8 @@ const onContentBlockStart = (state, event) => {
|
|
|
1044
1046
|
const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(function* (state, event) {
|
|
1045
1047
|
const delta = event.delta;
|
|
1046
1048
|
if (delta?.type === "text_delta" && delta.text) {
|
|
1049
|
+
if (!state.lifecycle.text.has(`text-${event.index ?? 0}`))
|
|
1050
|
+
return [state, NO_EVENTS];
|
|
1047
1051
|
const events = [];
|
|
1048
1052
|
return [
|
|
1049
1053
|
{ ...state, lifecycle: Lifecycle.textDelta(state.lifecycle, events, `text-${event.index ?? 0}`, delta.text) },
|
|
@@ -1051,6 +1055,8 @@ const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(f
|
|
|
1051
1055
|
];
|
|
1052
1056
|
}
|
|
1053
1057
|
if (delta?.type === "thinking_delta" && delta.thinking) {
|
|
1058
|
+
if (!state.lifecycle.reasoning.has(`reasoning-${event.index ?? 0}`))
|
|
1059
|
+
return [state, NO_EVENTS];
|
|
1054
1060
|
const events = [];
|
|
1055
1061
|
return [
|
|
1056
1062
|
{
|
|
@@ -1062,6 +1068,8 @@ const onContentBlockDelta = Effect.fn("AnthropicMessages.onContentBlockDelta")(f
|
|
|
1062
1068
|
}
|
|
1063
1069
|
if (delta?.type === "signature_delta" && delta.signature) {
|
|
1064
1070
|
const index = event.index ?? 0;
|
|
1071
|
+
if (!state.lifecycle.reasoning.has(`reasoning-${index}`))
|
|
1072
|
+
return [state, NO_EVENTS];
|
|
1065
1073
|
return [
|
|
1066
1074
|
{
|
|
1067
1075
|
...state,
|
|
@@ -1148,25 +1156,62 @@ const onError = (event) => Effect.fail(new AIError({
|
|
|
1148
1156
|
method: "stream",
|
|
1149
1157
|
reason: classifyProviderFailure({ message: providerErrorMessage(event), code: event.error?.type }),
|
|
1150
1158
|
}));
|
|
1159
|
+
const isKnownStreamBlockType = (type) => type === "text" ||
|
|
1160
|
+
type === "thinking" ||
|
|
1161
|
+
type === "redacted_thinking" ||
|
|
1162
|
+
type === "tool_use" ||
|
|
1163
|
+
type === "server_tool_use" ||
|
|
1164
|
+
isServerToolResultType(type);
|
|
1165
|
+
const isKnownStreamDeltaType = (type) => type === "text_delta" || type === "thinking_delta" || type === "signature_delta" || type === "input_json_delta";
|
|
1166
|
+
const invalidStreamEvent = (event) => Effect.fail(ProviderShared.eventError(ADAPTER, "Invalid anthropic/anthropic-messages stream event", ProviderShared.encodeJson(event)));
|
|
1151
1167
|
const step = (state, event) => {
|
|
1168
|
+
if (!SSE_EVENTS.has(event.type))
|
|
1169
|
+
return Effect.succeed([state, NO_EVENTS]);
|
|
1170
|
+
if (event.type !== "content_block_start" &&
|
|
1171
|
+
event.content_block !== undefined &&
|
|
1172
|
+
Option.isNone(decodeAnthropicStreamBlock(event.content_block)))
|
|
1173
|
+
return invalidStreamEvent(event);
|
|
1174
|
+
if (event.type !== "content_block_delta" &&
|
|
1175
|
+
event.delta !== undefined &&
|
|
1176
|
+
Option.isNone(decodeAnthropicStreamDelta(event.delta)))
|
|
1177
|
+
return invalidStreamEvent(event);
|
|
1152
1178
|
if (event.type === "message_start")
|
|
1153
1179
|
return Effect.succeed(onMessageStart(state, event));
|
|
1154
1180
|
if (event.type === "content_block_start") {
|
|
1155
|
-
|
|
1156
|
-
|
|
1181
|
+
if (!ProviderShared.isRecord(event.content_block) || typeof event.content_block.type !== "string")
|
|
1182
|
+
return invalidStreamEvent(event);
|
|
1183
|
+
if (!isKnownStreamBlockType(event.content_block.type))
|
|
1184
|
+
return Effect.succeed([state, NO_EVENTS]);
|
|
1185
|
+
const decoded = decodeAnthropicStreamBlock(event.content_block);
|
|
1186
|
+
if (Option.isNone(decoded))
|
|
1187
|
+
return invalidStreamEvent(event);
|
|
1188
|
+
const block = decoded.value;
|
|
1189
|
+
if (block.type === "tool_use" || block.type === "server_tool_use") {
|
|
1157
1190
|
if (event.index === undefined)
|
|
1158
1191
|
return Effect.fail(ProviderShared.eventError(ADAPTER, `Anthropic ${block.type} missing index`));
|
|
1159
1192
|
if (!block.id)
|
|
1160
1193
|
return Effect.fail(ProviderShared.eventError(ADAPTER, `Anthropic tool_use missing id at index ${event.index}`));
|
|
1161
1194
|
}
|
|
1162
|
-
return Effect.succeed(onContentBlockStart(state, event));
|
|
1195
|
+
return Effect.succeed(onContentBlockStart(state, { ...event, content_block: block }));
|
|
1196
|
+
}
|
|
1197
|
+
if (event.type === "content_block_delta") {
|
|
1198
|
+
if (!ProviderShared.isRecord(event.delta))
|
|
1199
|
+
return invalidStreamEvent(event);
|
|
1200
|
+
if (typeof event.delta.type === "string" && !isKnownStreamDeltaType(event.delta.type))
|
|
1201
|
+
return Effect.succeed([state, NO_EVENTS]);
|
|
1202
|
+
const decoded = decodeAnthropicStreamDelta(event.delta);
|
|
1203
|
+
if (Option.isNone(decoded))
|
|
1204
|
+
return invalidStreamEvent(event);
|
|
1205
|
+
return onContentBlockDelta(state, { ...event, delta: decoded.value });
|
|
1163
1206
|
}
|
|
1164
|
-
if (event.type === "content_block_delta")
|
|
1165
|
-
return onContentBlockDelta(state, event);
|
|
1166
1207
|
if (event.type === "content_block_stop")
|
|
1167
1208
|
return onContentBlockStop(state, event);
|
|
1168
|
-
if (event.type === "message_delta")
|
|
1169
|
-
|
|
1209
|
+
if (event.type === "message_delta") {
|
|
1210
|
+
const decoded = decodeAnthropicStreamDelta(event.delta);
|
|
1211
|
+
if (Option.isNone(decoded))
|
|
1212
|
+
return invalidStreamEvent(event);
|
|
1213
|
+
return Effect.succeed(onMessageDelta(state, { ...event, delta: decoded.value }));
|
|
1214
|
+
}
|
|
1170
1215
|
if (event.type === "message_stop")
|
|
1171
1216
|
return onMessageStop(state);
|
|
1172
1217
|
if (event.type === "error")
|
|
@@ -273,6 +273,14 @@ export declare const protocol: Protocol<{
|
|
|
273
273
|
} | undefined;
|
|
274
274
|
readonly metrics?: unknown;
|
|
275
275
|
} | undefined;
|
|
276
|
+
readonly exception?: {
|
|
277
|
+
readonly type: string;
|
|
278
|
+
readonly details: {
|
|
279
|
+
readonly message?: string | undefined;
|
|
280
|
+
readonly originalMessage?: string | undefined;
|
|
281
|
+
readonly originalStatusCode?: number | undefined;
|
|
282
|
+
};
|
|
283
|
+
} | undefined;
|
|
276
284
|
readonly messageStart?: {
|
|
277
285
|
readonly role: string;
|
|
278
286
|
} | undefined;
|
|
@@ -307,31 +315,6 @@ export declare const protocol: Protocol<{
|
|
|
307
315
|
readonly stopReason: string;
|
|
308
316
|
readonly additionalModelResponseFields?: unknown;
|
|
309
317
|
} | undefined;
|
|
310
|
-
readonly internalServerException?: {
|
|
311
|
-
readonly message?: string | undefined;
|
|
312
|
-
readonly originalMessage?: string | undefined;
|
|
313
|
-
readonly originalStatusCode?: number | undefined;
|
|
314
|
-
} | undefined;
|
|
315
|
-
readonly modelStreamErrorException?: {
|
|
316
|
-
readonly message?: string | undefined;
|
|
317
|
-
readonly originalMessage?: string | undefined;
|
|
318
|
-
readonly originalStatusCode?: number | undefined;
|
|
319
|
-
} | undefined;
|
|
320
|
-
readonly validationException?: {
|
|
321
|
-
readonly message?: string | undefined;
|
|
322
|
-
readonly originalMessage?: string | undefined;
|
|
323
|
-
readonly originalStatusCode?: number | undefined;
|
|
324
|
-
} | undefined;
|
|
325
|
-
readonly throttlingException?: {
|
|
326
|
-
readonly message?: string | undefined;
|
|
327
|
-
readonly originalMessage?: string | undefined;
|
|
328
|
-
readonly originalStatusCode?: number | undefined;
|
|
329
|
-
} | undefined;
|
|
330
|
-
readonly serviceUnavailableException?: {
|
|
331
|
-
readonly message?: string | undefined;
|
|
332
|
-
readonly originalMessage?: string | undefined;
|
|
333
|
-
readonly originalStatusCode?: number | undefined;
|
|
334
|
-
} | undefined;
|
|
335
318
|
}, {
|
|
336
319
|
readonly metadata?: {
|
|
337
320
|
readonly usage?: {
|
|
@@ -343,6 +326,14 @@ export declare const protocol: Protocol<{
|
|
|
343
326
|
} | undefined;
|
|
344
327
|
readonly metrics?: unknown;
|
|
345
328
|
} | undefined;
|
|
329
|
+
readonly exception?: {
|
|
330
|
+
readonly type: string;
|
|
331
|
+
readonly details: {
|
|
332
|
+
readonly message?: string | undefined;
|
|
333
|
+
readonly originalMessage?: string | undefined;
|
|
334
|
+
readonly originalStatusCode?: number | undefined;
|
|
335
|
+
};
|
|
336
|
+
} | undefined;
|
|
346
337
|
readonly messageStart?: {
|
|
347
338
|
readonly role: string;
|
|
348
339
|
} | undefined;
|
|
@@ -377,31 +368,6 @@ export declare const protocol: Protocol<{
|
|
|
377
368
|
readonly stopReason: string;
|
|
378
369
|
readonly additionalModelResponseFields?: unknown;
|
|
379
370
|
} | undefined;
|
|
380
|
-
readonly internalServerException?: {
|
|
381
|
-
readonly message?: string | undefined;
|
|
382
|
-
readonly originalMessage?: string | undefined;
|
|
383
|
-
readonly originalStatusCode?: number | undefined;
|
|
384
|
-
} | undefined;
|
|
385
|
-
readonly modelStreamErrorException?: {
|
|
386
|
-
readonly message?: string | undefined;
|
|
387
|
-
readonly originalMessage?: string | undefined;
|
|
388
|
-
readonly originalStatusCode?: number | undefined;
|
|
389
|
-
} | undefined;
|
|
390
|
-
readonly validationException?: {
|
|
391
|
-
readonly message?: string | undefined;
|
|
392
|
-
readonly originalMessage?: string | undefined;
|
|
393
|
-
readonly originalStatusCode?: number | undefined;
|
|
394
|
-
} | undefined;
|
|
395
|
-
readonly throttlingException?: {
|
|
396
|
-
readonly message?: string | undefined;
|
|
397
|
-
readonly originalMessage?: string | undefined;
|
|
398
|
-
readonly originalStatusCode?: number | undefined;
|
|
399
|
-
} | undefined;
|
|
400
|
-
readonly serviceUnavailableException?: {
|
|
401
|
-
readonly message?: string | undefined;
|
|
402
|
-
readonly originalMessage?: string | undefined;
|
|
403
|
-
readonly originalStatusCode?: number | undefined;
|
|
404
|
-
} | undefined;
|
|
405
371
|
}, ParserState>;
|
|
406
372
|
export declare const route: Route<{
|
|
407
373
|
readonly messages: readonly ({
|
|
@@ -149,11 +149,7 @@ const BedrockEvent = Schema.Struct({
|
|
|
149
149
|
usage: Schema.optional(BedrockUsageSchema),
|
|
150
150
|
metrics: Schema.optional(Schema.Unknown),
|
|
151
151
|
})),
|
|
152
|
-
|
|
153
|
-
modelStreamErrorException: Schema.optional(BedrockStreamException),
|
|
154
|
-
validationException: Schema.optional(BedrockStreamException),
|
|
155
|
-
throttlingException: Schema.optional(BedrockStreamException),
|
|
156
|
-
serviceUnavailableException: Schema.optional(BedrockStreamException),
|
|
152
|
+
exception: Schema.optional(Schema.Struct({ type: Schema.String, details: BedrockStreamException })),
|
|
157
153
|
});
|
|
158
154
|
// =============================================================================
|
|
159
155
|
// Request Lowering
|
|
@@ -507,20 +503,13 @@ const step = (state, event) => Effect.gen(function* () {
|
|
|
507
503
|
[],
|
|
508
504
|
];
|
|
509
505
|
}
|
|
510
|
-
|
|
511
|
-
["internalServerException", event.internalServerException],
|
|
512
|
-
["modelStreamErrorException", event.modelStreamErrorException],
|
|
513
|
-
["serviceUnavailableException", event.serviceUnavailableException],
|
|
514
|
-
["throttlingException", event.throttlingException],
|
|
515
|
-
["validationException", event.validationException],
|
|
516
|
-
].find((entry) => entry[1] !== undefined);
|
|
517
|
-
if (exception) {
|
|
506
|
+
if (event.exception) {
|
|
518
507
|
return yield* new AIError({
|
|
519
508
|
module: ADAPTER,
|
|
520
509
|
method: "stream",
|
|
521
510
|
reason: classifyProviderFailure({
|
|
522
|
-
message: exception
|
|
523
|
-
code: exception
|
|
511
|
+
message: event.exception.details.message ?? event.exception.details.originalMessage ?? "Bedrock Converse stream error",
|
|
512
|
+
code: event.exception.type,
|
|
524
513
|
}),
|
|
525
514
|
});
|
|
526
515
|
}
|
|
@@ -565,7 +554,7 @@ export const protocol = Protocol.make({
|
|
|
565
554
|
reasoningSignatures: {},
|
|
566
555
|
}),
|
|
567
556
|
step,
|
|
568
|
-
onHalt,
|
|
557
|
+
onHalt: (state) => Effect.succeed(onHalt(state)),
|
|
569
558
|
},
|
|
570
559
|
});
|
|
571
560
|
export const route = Route.make({
|
|
@@ -56,7 +56,7 @@ const consumeFrames = (route) => (state, chunk) => Effect.gen(function* () {
|
|
|
56
56
|
// against ad-hoc `JSON.parse` calls.
|
|
57
57
|
const parsed = (yield* ProviderShared.parseJson(route, payload, "Failed to parse Bedrock Converse event-stream payload"));
|
|
58
58
|
delete parsed.p;
|
|
59
|
-
out.push({ [eventType]: parsed });
|
|
59
|
+
out.push(messageType === "exception" ? { exception: { type: eventType, details: parsed } } : { [eventType]: parsed });
|
|
60
60
|
}
|
|
61
61
|
return [cursor, out];
|
|
62
62
|
});
|
package/dist/protocols/gemini.js
CHANGED
|
@@ -133,7 +133,12 @@ export const driver = (input) => {
|
|
|
133
133
|
...observation,
|
|
134
134
|
checkpoint: {
|
|
135
135
|
protocol: PROTOCOL,
|
|
136
|
-
value: {
|
|
136
|
+
value: {
|
|
137
|
+
version: VERSION,
|
|
138
|
+
responseID,
|
|
139
|
+
request,
|
|
140
|
+
output: event.response?.output ? [...event.response.output] : output.slice(),
|
|
141
|
+
},
|
|
137
142
|
},
|
|
138
143
|
};
|
|
139
144
|
}),
|
|
@@ -384,8 +384,10 @@ export declare const decodeKnownErrorEvent: (event: Event) => Effect.Effect<{
|
|
|
384
384
|
export declare const Event: Schema.StructWithRest<Schema.Struct<{
|
|
385
385
|
readonly type: Schema.String;
|
|
386
386
|
readonly delta: Schema.optional<Schema.String>;
|
|
387
|
+
readonly arguments: Schema.optional<Schema.String>;
|
|
387
388
|
readonly text: Schema.optional<Schema.String>;
|
|
388
389
|
readonly item_id: Schema.optional<Schema.String>;
|
|
390
|
+
readonly output_index: Schema.optional<Schema.Number>;
|
|
389
391
|
readonly summary_index: Schema.optional<Schema.Number>;
|
|
390
392
|
readonly item: Schema.optional<Schema.StructWithRest<Schema.Struct<{
|
|
391
393
|
readonly type: Schema.String;
|
|
@@ -401,6 +403,14 @@ export declare const Event: Schema.StructWithRest<Schema.Struct<{
|
|
|
401
403
|
readonly incomplete_details: Schema.optional<Schema.NullOr<Schema.Struct<{
|
|
402
404
|
readonly reason: Schema.optional<Schema.String>;
|
|
403
405
|
}>>>;
|
|
406
|
+
readonly output: Schema.optional<Schema.$Array<Schema.StructWithRest<Schema.Struct<{
|
|
407
|
+
readonly type: Schema.String;
|
|
408
|
+
readonly id: Schema.optional<Schema.String>;
|
|
409
|
+
readonly call_id: Schema.optional<Schema.String>;
|
|
410
|
+
readonly name: Schema.optional<Schema.String>;
|
|
411
|
+
readonly arguments: Schema.optional<Schema.String>;
|
|
412
|
+
readonly encrypted_content: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
413
|
+
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
|
|
404
414
|
readonly usage: Schema.optional<Schema.NullOr<Schema.Struct<{
|
|
405
415
|
readonly input_tokens: Schema.optional<Schema.Number>;
|
|
406
416
|
readonly input_tokens_details: Schema.optional<Schema.NullOr<Schema.Struct<{
|
|
@@ -452,6 +462,7 @@ export interface ParserState {
|
|
|
452
462
|
readonly tools: ToolStream.State<string>;
|
|
453
463
|
readonly hasFunctionCall: boolean;
|
|
454
464
|
readonly lifecycle: Lifecycle.State;
|
|
465
|
+
readonly outputItems: Readonly<Record<number, string>>;
|
|
455
466
|
readonly messageItems: ReadonlySet<string>;
|
|
456
467
|
readonly messagePhases: Readonly<Record<string, MessagePhase | null>>;
|
|
457
468
|
readonly reasoningItems: Readonly<Record<string, ReasoningStreamItem>>;
|
|
@@ -652,10 +663,11 @@ export declare const fromRequest: (request: LLMRequest) => Effect.Effect<{
|
|
|
652
663
|
export declare const providerMetadata: (state: ParserState, metadata: Record<string, unknown>) => ProviderMetadata;
|
|
653
664
|
export type StepResult = readonly [ParserState, ReadonlyArray<LLMEvent>];
|
|
654
665
|
export declare const terminal: (event: Event) => boolean;
|
|
666
|
+
export declare const outputItemID: (state: ParserState, event: Event) => string | undefined;
|
|
655
667
|
export declare const onReasoningDelta: (state: ParserState, event: Event, itemID: string) => StepResult;
|
|
656
668
|
export declare const onReasoningDone: (state: ParserState, event: Event, itemID: string) => StepResult;
|
|
657
669
|
export declare const providerFailure: (id: string, event: Event, fallback: string) => AIError;
|
|
658
|
-
export declare const step: (state: ParserState,
|
|
670
|
+
export declare const step: (state: ParserState, input: Event) => AIError | Effect.Effect<[ParserState, readonly ({
|
|
659
671
|
readonly type: "step-start";
|
|
660
672
|
readonly index: number;
|
|
661
673
|
} | {
|
|
@@ -837,7 +849,7 @@ export declare const step: (state: ParserState, event: Event) => AIError | Effec
|
|
|
837
849
|
};
|
|
838
850
|
} | undefined;
|
|
839
851
|
readonly classification?: "context-overflow" | "payload-too-large" | undefined;
|
|
840
|
-
})[]], AIError, never>;
|
|
852
|
+
})[]], AIError, never> | Effect.Effect<StepResult, never, never>;
|
|
841
853
|
/**
|
|
842
854
|
* The provider-neutral Open Responses protocol. Provider-specific Responses
|
|
843
855
|
* implementations compose this baseline with their own tools and event variants.
|
|
@@ -986,6 +998,15 @@ export declare const protocol: Protocol<{
|
|
|
986
998
|
readonly response?: {
|
|
987
999
|
readonly [x: string]: unknown;
|
|
988
1000
|
readonly id?: string | undefined;
|
|
1001
|
+
readonly output?: readonly {
|
|
1002
|
+
readonly [x: string]: unknown;
|
|
1003
|
+
readonly type: string;
|
|
1004
|
+
readonly id?: string | undefined;
|
|
1005
|
+
readonly name?: string | undefined;
|
|
1006
|
+
readonly arguments?: string | undefined;
|
|
1007
|
+
readonly encrypted_content?: string | null | undefined;
|
|
1008
|
+
readonly call_id?: string | undefined;
|
|
1009
|
+
}[] | undefined;
|
|
989
1010
|
readonly error?: {
|
|
990
1011
|
readonly type?: string | null | undefined;
|
|
991
1012
|
readonly code?: string | null | undefined;
|
|
@@ -1009,9 +1030,11 @@ export declare const protocol: Protocol<{
|
|
|
1009
1030
|
readonly reason?: string | undefined;
|
|
1010
1031
|
} | null | undefined;
|
|
1011
1032
|
} | undefined;
|
|
1033
|
+
readonly arguments?: string | undefined;
|
|
1012
1034
|
readonly param?: string | null | undefined;
|
|
1013
1035
|
readonly status_code?: unknown;
|
|
1014
1036
|
readonly item_id?: string | undefined;
|
|
1037
|
+
readonly output_index?: number | undefined;
|
|
1015
1038
|
readonly summary_index?: number | undefined;
|
|
1016
1039
|
}, ParserState>;
|
|
1017
1040
|
export declare const httpTransport: HttpTransport.HttpJsonTransport<{
|
|
@@ -204,14 +204,17 @@ export const decodeKnownErrorEvent = (event) => decodeWebSocketErrorEvent({
|
|
|
204
204
|
export const Event = Schema.StructWithRest(Schema.Struct({
|
|
205
205
|
type: Schema.String,
|
|
206
206
|
delta: Schema.optional(Schema.String),
|
|
207
|
+
arguments: Schema.optional(Schema.String),
|
|
207
208
|
text: Schema.optional(Schema.String),
|
|
208
209
|
item_id: Schema.optional(Schema.String),
|
|
210
|
+
output_index: Schema.optional(Schema.Number),
|
|
209
211
|
summary_index: Schema.optional(Schema.Number),
|
|
210
212
|
item: Schema.optional(StreamItem),
|
|
211
213
|
response: Schema.optional(Schema.StructWithRest(Schema.Struct({
|
|
212
214
|
id: Schema.optional(Schema.String),
|
|
213
215
|
service_tier: optionalNull(Schema.String),
|
|
214
216
|
incomplete_details: optionalNull(Schema.Struct({ reason: Schema.optional(Schema.String) })),
|
|
217
|
+
output: Schema.optional(Schema.Array(StreamItem)),
|
|
215
218
|
usage: optionalNull(OpenResponsesUsage),
|
|
216
219
|
error: optionalNull(OpenResponsesErrorPayload),
|
|
217
220
|
}), [Schema.Record(Schema.String, Schema.Unknown)])),
|
|
@@ -461,16 +464,11 @@ const lowerMessages = Effect.fn("OpenResponses.lowerMessages")(function* (reques
|
|
|
461
464
|
});
|
|
462
465
|
}
|
|
463
466
|
}
|
|
464
|
-
|
|
465
|
-
// complete item has encrypted state. Summary blocks for one item may carry
|
|
466
|
-
// that state only on the last block, so filter after they have been joined.
|
|
467
|
-
return store === false
|
|
468
|
-
? input.filter((item) => !("type" in item) || item.type !== "reasoning" || typeof item.encrypted_content === "string")
|
|
469
|
-
: input;
|
|
467
|
+
return input;
|
|
470
468
|
});
|
|
471
469
|
const lowerOptions = (request) => {
|
|
472
470
|
const options = OpenResponsesOptions.resolve(request);
|
|
473
|
-
const cacheKey = ProviderShared.
|
|
471
|
+
const cacheKey = ProviderShared.promptCacheKey(request);
|
|
474
472
|
const parallelToolCalls = resolveParallelToolCalls(request);
|
|
475
473
|
return {
|
|
476
474
|
...(options.instructions ? { instructions: options.instructions } : {}),
|
|
@@ -602,6 +600,7 @@ const onOutputTextDone = (state, event, id) => {
|
|
|
602
600
|
const events = [];
|
|
603
601
|
return [{ ...state, lifecycle: Lifecycle.textEnd(state.lifecycle, events, id) }, events];
|
|
604
602
|
};
|
|
603
|
+
export const outputItemID = (state, event) => event.output_index === undefined ? event.item_id : (state.outputItems[event.output_index] ?? event.item_id);
|
|
605
604
|
export const onReasoningDelta = (state, event, itemID) => {
|
|
606
605
|
const item = state.reasoningItems[itemID];
|
|
607
606
|
if (!event.delta || !item)
|
|
@@ -756,9 +755,23 @@ const onReasoningSummaryPartDone = (state, event) => {
|
|
|
756
755
|
];
|
|
757
756
|
};
|
|
758
757
|
const onFunctionCallArgumentsDelta = Effect.fn("OpenResponses.onFunctionCallArgumentsDelta")(function* (state, event) {
|
|
759
|
-
if (!event.item_id
|
|
758
|
+
if (!event.item_id)
|
|
759
|
+
return [state, NO_EVENTS];
|
|
760
|
+
const tool = state.tools[event.item_id];
|
|
761
|
+
if (!tool)
|
|
760
762
|
return [state, NO_EVENTS];
|
|
761
|
-
const
|
|
763
|
+
const final = event.type === "response.function_call_arguments.done" ? event.arguments : undefined;
|
|
764
|
+
if (event.type === "response.function_call_arguments.done" && final === undefined)
|
|
765
|
+
return [state, NO_EVENTS];
|
|
766
|
+
if (final !== undefined && !final.startsWith(tool.input))
|
|
767
|
+
return [
|
|
768
|
+
{ ...state, tools: ToolStream.start(state.tools, event.item_id, { ...tool, input: final }) },
|
|
769
|
+
NO_EVENTS,
|
|
770
|
+
];
|
|
771
|
+
const delta = final === undefined ? event.delta : final.slice(tool.input.length);
|
|
772
|
+
if (!delta)
|
|
773
|
+
return [state, NO_EVENTS];
|
|
774
|
+
const result = ToolStream.appendExisting(state.id, state.tools, event.item_id, delta, `${state.name} tool argument delta is missing its tool call`);
|
|
762
775
|
if (ToolStream.isError(result))
|
|
763
776
|
return yield* result;
|
|
764
777
|
const events = [];
|
|
@@ -840,27 +853,37 @@ const onOutputItemDone = Effect.fn("OpenResponses.onOutputItemDone")(function* (
|
|
|
840
853
|
return [state, NO_EVENTS];
|
|
841
854
|
});
|
|
842
855
|
const onResponseFinish = Effect.fn("OpenResponses.onResponseFinish")(function* (state, event) {
|
|
856
|
+
const reconciled = event.type === "response.completed"
|
|
857
|
+
? yield* Effect.reduce(event.response?.output ?? [], () => [state, NO_EVENTS], ([current, events], item) => {
|
|
858
|
+
if (!item.id ||
|
|
859
|
+
((item.type !== "function_call" || !current.tools[item.id]) &&
|
|
860
|
+
(item.type !== "reasoning" || !current.reasoningItems[item.id])))
|
|
861
|
+
return Effect.succeed([current, events]);
|
|
862
|
+
return onOutputItemDone(current, { type: "response.output_item.done", item }).pipe(Effect.map(([next, emitted]) => [next, [...events, ...emitted]]));
|
|
863
|
+
})
|
|
864
|
+
: [state, NO_EVENTS];
|
|
865
|
+
const current = reconciled[0];
|
|
843
866
|
// Some compatible providers omit output_item.done even after completing the response.
|
|
844
867
|
const pending = event.type === "response.completed"
|
|
845
|
-
? yield* ToolStream.finishAll(
|
|
846
|
-
: { tools:
|
|
847
|
-
const events = [...pending.events];
|
|
868
|
+
? yield* ToolStream.finishAll(current.id, current.tools)
|
|
869
|
+
: { tools: current.tools, events: NO_EVENTS };
|
|
870
|
+
const events = [...reconciled[1], ...pending.events];
|
|
848
871
|
const hasFunctionCall = pending.events.some((event) => LLMEvent.is.toolCall(event) || LLMEvent.is.toolInputError(event)) ||
|
|
849
|
-
|
|
850
|
-
const lifecycle = Lifecycle.finish(
|
|
872
|
+
current.hasFunctionCall;
|
|
873
|
+
const lifecycle = Lifecycle.finish(current.lifecycle, events, {
|
|
851
874
|
reason: {
|
|
852
875
|
normalized: mapFinishReason(event, hasFunctionCall),
|
|
853
876
|
raw: event.response?.incomplete_details?.reason,
|
|
854
877
|
},
|
|
855
|
-
usage: mapUsage(event.response?.usage,
|
|
878
|
+
usage: mapUsage(event.response?.usage, current.providerMetadataKey),
|
|
856
879
|
providerMetadata: event.response?.id || event.response?.service_tier
|
|
857
|
-
? providerMetadata(
|
|
880
|
+
? providerMetadata(current, {
|
|
858
881
|
responseId: event.response.id,
|
|
859
882
|
serviceTier: event.response.service_tier,
|
|
860
883
|
})
|
|
861
884
|
: undefined,
|
|
862
885
|
});
|
|
863
|
-
return [{ ...
|
|
886
|
+
return [{ ...current, lifecycle, hasFunctionCall, tools: pending.tools }, events];
|
|
864
887
|
});
|
|
865
888
|
// Build the prettiest summary available from whatever the provider supplied.
|
|
866
889
|
// When both code and message are present, prefix the code so consumers see
|
|
@@ -902,7 +925,10 @@ export const providerFailure = (id, event, fallback) => {
|
|
|
902
925
|
});
|
|
903
926
|
};
|
|
904
927
|
const providerError = (state, event, fallback) => providerFailure(state.id, event, fallback);
|
|
905
|
-
export const step = (state,
|
|
928
|
+
export const step = (state, input) => {
|
|
929
|
+
const event = input.item_id && outputItemID(state, input) !== input.item_id
|
|
930
|
+
? { ...input, item_id: outputItemID(state, input) }
|
|
931
|
+
: input;
|
|
906
932
|
if (event.type === "response.output_text.delta" || event.type === "response.output_text.done") {
|
|
907
933
|
if (!event.item_id)
|
|
908
934
|
return ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
@@ -941,9 +967,11 @@ export const step = (state, event) => {
|
|
|
941
967
|
if (event.type === "response.output_item.added") {
|
|
942
968
|
if (event.item?.type === "message" && !event.item.id)
|
|
943
969
|
return ProviderShared.eventError(state.id, `${event.type} message is missing id`);
|
|
944
|
-
return Effect.succeed(onOutputItemAdded(
|
|
970
|
+
return Effect.succeed(onOutputItemAdded(event.output_index !== undefined && event.item?.id
|
|
971
|
+
? { ...state, outputItems: { ...state.outputItems, [event.output_index]: event.item.id } }
|
|
972
|
+
: state, event));
|
|
945
973
|
}
|
|
946
|
-
if (event.type === "response.function_call_arguments.delta")
|
|
974
|
+
if (event.type === "response.function_call_arguments.delta" || event.type === "response.function_call_arguments.done")
|
|
947
975
|
return event.item_id
|
|
948
976
|
? onFunctionCallArgumentsDelta(state, event)
|
|
949
977
|
: ProviderShared.eventError(state.id, `${event.type} is missing item_id`);
|
|
@@ -974,6 +1002,7 @@ export const initial = (request, extension = BASE) => ({
|
|
|
974
1002
|
hasFunctionCall: false,
|
|
975
1003
|
tools: ToolStream.empty(),
|
|
976
1004
|
lifecycle: Lifecycle.initial(),
|
|
1005
|
+
outputItems: {},
|
|
977
1006
|
messageItems: new Set(),
|
|
978
1007
|
messagePhases: {},
|
|
979
1008
|
reasoningItems: {},
|
|
@@ -204,7 +204,7 @@ declare const OpenAIChatBody: Schema.Struct<{
|
|
|
204
204
|
stop: Schema.optional<Schema.$Array<Schema.String>>;
|
|
205
205
|
}>;
|
|
206
206
|
export type OpenAIChatBody = Schema.Schema.Type<typeof OpenAIChatBody>;
|
|
207
|
-
export declare const OpenAIChatEvent: Schema.Struct<{
|
|
207
|
+
export declare const OpenAIChatEvent: Schema.StructWithRest<Schema.Struct<{
|
|
208
208
|
readonly choices: Schema.optional<Schema.NullOr<Schema.$Array<Schema.StructWithRest<Schema.Struct<{
|
|
209
209
|
readonly delta: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
|
|
210
210
|
readonly content: Schema.optional<Schema.NullOr<Schema.String>>;
|
|
@@ -257,11 +257,11 @@ export declare const OpenAIChatEvent: Schema.Struct<{
|
|
|
257
257
|
readonly rejected_prediction_tokens: Schema.optional<Schema.NullOr<Schema.Number>>;
|
|
258
258
|
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
|
|
259
259
|
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
|
|
260
|
-
readonly error: Schema.optional<Schema.NullOr<Schema.Struct<{
|
|
260
|
+
readonly error: Schema.optional<Schema.NullOr<Schema.StructWithRest<Schema.Struct<{
|
|
261
261
|
readonly code: Schema.optional<Schema.NullOr<Schema.Union<readonly [Schema.String, Schema.Number]>>>;
|
|
262
262
|
readonly message: Schema.String;
|
|
263
|
-
}>>>;
|
|
264
|
-
}>;
|
|
263
|
+
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>>>;
|
|
264
|
+
}>, readonly [Schema.$Record<Schema.String, Schema.Unknown>]>;
|
|
265
265
|
export type OpenAIChatEvent = Schema.Schema.Type<typeof OpenAIChatEvent>;
|
|
266
266
|
interface PendingToolDelta {
|
|
267
267
|
readonly id?: string;
|
|
@@ -281,6 +281,7 @@ export interface ParserState {
|
|
|
281
281
|
readonly reasoningEmitted: boolean;
|
|
282
282
|
readonly latestToolIndex?: number;
|
|
283
283
|
readonly nextToolIndex: number;
|
|
284
|
+
readonly requireFinishReason: boolean;
|
|
284
285
|
}
|
|
285
286
|
interface LoweringOptions {
|
|
286
287
|
readonly cacheControl?: (cache: CacheHint | undefined) => Schema.Schema.Type<typeof OpenAIChatCacheControl> | undefined;
|
|
@@ -585,7 +586,9 @@ export declare const protocol: Protocol<{
|
|
|
585
586
|
readonly frequency_penalty?: number | undefined;
|
|
586
587
|
readonly presence_penalty?: number | undefined;
|
|
587
588
|
}, string, {
|
|
589
|
+
readonly [x: string]: unknown;
|
|
588
590
|
readonly error?: {
|
|
591
|
+
readonly [x: string]: unknown;
|
|
589
592
|
readonly message: string;
|
|
590
593
|
readonly code?: string | number | null | undefined;
|
|
591
594
|
} | null | undefined;
|