@opencode-ai/ai 0.0.0-beta-18387 → 0.0.0-beta-18593
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/README.md +29 -11
- package/dist/image.js +5 -4
- package/dist/llm.d.ts +2 -0
- package/dist/llm.js +4 -7
- package/dist/protocols/anthropic-messages.js +7 -5
- package/dist/protocols/bedrock-converse.d.ts +1 -0
- package/dist/protocols/bedrock-converse.js +17 -7
- package/dist/protocols/bedrock-event-stream.js +16 -6
- package/dist/protocols/gemini.d.ts +1 -0
- package/dist/protocols/gemini.js +13 -1
- package/dist/protocols/google-images.js +8 -18
- package/dist/protocols/open-responses-channel.js +20 -9
- package/dist/protocols/open-responses-continuation.js +9 -8
- package/dist/protocols/open-responses.d.ts +9 -3
- package/dist/protocols/open-responses.js +139 -78
- package/dist/protocols/openai-chat.d.ts +3 -1
- package/dist/protocols/openai-chat.js +39 -28
- package/dist/protocols/openai-compatible-chat.js +1 -2
- package/dist/protocols/openai-images.js +11 -16
- package/dist/protocols/openai-responses.js +1 -1
- package/dist/protocols/shared.d.ts +11 -7
- package/dist/protocols/shared.js +31 -18
- package/dist/protocols/utils/image-input.d.ts +4 -4
- package/dist/protocols/utils/image-input.js +6 -8
- package/dist/protocols/utils/lifecycle.d.ts +6 -2
- package/dist/protocols/utils/lifecycle.js +11 -7
- package/dist/protocols/utils/tool-stream.d.ts +6 -0
- package/dist/protocols/xai-images.js +7 -12
- package/dist/protocols/zai-images.js +5 -10
- package/dist/provider-error.d.ts +4 -4
- package/dist/provider-error.js +39 -55
- package/dist/providers/groq.d.ts +1 -1
- package/dist/providers/groq.js +1 -2
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +1 -2
- package/dist/route/auth.js +3 -5
- package/dist/route/client.d.ts +2 -0
- package/dist/route/client.js +29 -11
- package/dist/route/executor.d.ts +9 -5
- package/dist/route/executor.js +33 -66
- package/dist/route/framing.d.ts +6 -2
- package/dist/route/framing.js +5 -0
- package/dist/route/transport/http.js +7 -2
- package/dist/route/transport/index.d.ts +3 -1
- package/dist/route/transport/websocket-channel.d.ts +2 -1
- package/dist/route/transport/websocket.d.ts +2 -1
- package/dist/route/transport/websocket.js +70 -30
- package/dist/schema/errors.d.ts +71 -89
- package/dist/schema/errors.js +35 -87
- package/dist/schema/events.d.ts +2835 -351
- package/dist/schema/events.js +32 -14
- package/dist/testing.d.ts +41 -2
- package/dist/testing.js +39 -18
- package/package.json +5 -5
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Cause, Effect, Queue, Stream } from "effect";
|
|
2
2
|
import { Headers } from "effect/unstable/http";
|
|
3
3
|
import { Socket } from "effect/unstable/socket";
|
|
4
|
-
import { AIError,
|
|
4
|
+
import { AIError, AIErrorReason, TransportError, } from "../../schema/index.js";
|
|
5
5
|
import * as HttpTransport from "./http.js";
|
|
6
6
|
const MAX_FRAME_BYTES = 16 * 1024 * 1024;
|
|
7
|
-
const transportError = (
|
|
8
|
-
|
|
9
|
-
method,
|
|
10
|
-
reason: new TransportReason({
|
|
7
|
+
const transportError = (message, input) => new AIError({
|
|
8
|
+
reason: new TransportError({
|
|
11
9
|
message,
|
|
10
|
+
body: input.body,
|
|
11
|
+
cause: input.cause,
|
|
12
12
|
transport: "websocket",
|
|
13
13
|
operation: input.operation,
|
|
14
14
|
url: input.url,
|
|
@@ -19,18 +19,12 @@ const transportError = (method, message, input) => new AIError({
|
|
|
19
19
|
});
|
|
20
20
|
const annotateTransportError = (error, input) => error.reason._tag === "Transport"
|
|
21
21
|
? new AIError({
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
reason: new TransportReason({
|
|
22
|
+
reason: new TransportError({
|
|
23
|
+
...error.reason,
|
|
25
24
|
message: error.reason.message,
|
|
26
|
-
|
|
27
|
-
operation: error.reason.operation,
|
|
28
|
-
code: error.reason.code,
|
|
29
|
-
url: error.reason.url,
|
|
30
|
-
http: error.reason.http,
|
|
25
|
+
cause: error.reason.cause,
|
|
31
26
|
phase: input.phase,
|
|
32
27
|
delivery: input.delivery,
|
|
33
|
-
recovery: error.reason.recovery,
|
|
34
28
|
}),
|
|
35
29
|
})
|
|
36
30
|
: error;
|
|
@@ -52,7 +46,7 @@ const waitOpen = (ws, input) => {
|
|
|
52
46
|
if (ws.readyState === globalThis.WebSocket.OPEN)
|
|
53
47
|
return Effect.void;
|
|
54
48
|
if (ws.readyState === globalThis.WebSocket.CLOSING || ws.readyState === globalThis.WebSocket.CLOSED) {
|
|
55
|
-
return Effect.fail(transportError(
|
|
49
|
+
return Effect.fail(transportError(`WebSocket closed before opening (state ${ws.readyState})`, {
|
|
56
50
|
url: input.url,
|
|
57
51
|
operation: "request",
|
|
58
52
|
code: "closed",
|
|
@@ -78,7 +72,8 @@ const waitOpen = (ws, input) => {
|
|
|
78
72
|
};
|
|
79
73
|
const onError = (event) => {
|
|
80
74
|
cleanup();
|
|
81
|
-
resume(Effect.fail(transportError(
|
|
75
|
+
resume(Effect.fail(transportError(`Failed to open WebSocket: ${eventMessage(event)}`, {
|
|
76
|
+
cause: "error" in event ? (event.error ?? event) : event,
|
|
82
77
|
url: input.url,
|
|
83
78
|
operation: "request",
|
|
84
79
|
phase: "connect",
|
|
@@ -87,7 +82,9 @@ const waitOpen = (ws, input) => {
|
|
|
87
82
|
};
|
|
88
83
|
const onClose = (event) => {
|
|
89
84
|
cleanup();
|
|
90
|
-
resume(Effect.fail(transportError(
|
|
85
|
+
resume(Effect.fail(transportError(`WebSocket closed before opening with code ${event.code}`, {
|
|
86
|
+
body: event.reason,
|
|
87
|
+
cause: event,
|
|
91
88
|
url: input.url,
|
|
92
89
|
operation: "request",
|
|
93
90
|
code: String(event.code),
|
|
@@ -114,7 +111,8 @@ export const toWebSocketUrl = (value) => Effect.try({
|
|
|
114
111
|
}
|
|
115
112
|
throw new Error(`Unsupported WebSocket URL protocol ${url.protocol}`);
|
|
116
113
|
},
|
|
117
|
-
catch: (error) => transportError(
|
|
114
|
+
catch: (error) => transportError(error instanceof Error ? error.message : "Invalid WebSocket URL", {
|
|
115
|
+
cause: error,
|
|
118
116
|
url: value,
|
|
119
117
|
operation: "request",
|
|
120
118
|
code: "invalid-url",
|
|
@@ -131,7 +129,8 @@ export const open = (input) => Effect.gen(function* () {
|
|
|
131
129
|
constructor(input.url, {
|
|
132
130
|
headers: input.headers,
|
|
133
131
|
}),
|
|
134
|
-
catch: (error) => transportError(
|
|
132
|
+
catch: (error) => transportError(error instanceof Error ? error.message : "Failed to construct WebSocket", {
|
|
133
|
+
cause: error,
|
|
135
134
|
url: input.url,
|
|
136
135
|
operation: "request",
|
|
137
136
|
phase: "connect",
|
|
@@ -147,7 +146,8 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
147
146
|
const rejectOversized = (message) => {
|
|
148
147
|
if (!oversized(message))
|
|
149
148
|
return false;
|
|
150
|
-
Queue.failCauseUnsafe(messages, Cause.fail(transportError("
|
|
149
|
+
Queue.failCauseUnsafe(messages, Cause.fail(transportError("WebSocket message exceeds the 16 MiB limit", {
|
|
150
|
+
body: typeof message === "string" ? message : new TextDecoder().decode(message),
|
|
151
151
|
url: input.url,
|
|
152
152
|
operation: "read",
|
|
153
153
|
code: "message-too-large",
|
|
@@ -162,7 +162,8 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
162
162
|
return;
|
|
163
163
|
if (Queue.offerUnsafe(messages, message))
|
|
164
164
|
return;
|
|
165
|
-
Queue.failCauseUnsafe(messages, Cause.fail(transportError("
|
|
165
|
+
Queue.failCauseUnsafe(messages, Cause.fail(transportError("WebSocket inbound queue overflow", {
|
|
166
|
+
body: typeof message === "string" ? message : new TextDecoder().decode(message),
|
|
166
167
|
url: input.url,
|
|
167
168
|
operation: "read",
|
|
168
169
|
code: "queue-overflow",
|
|
@@ -175,7 +176,8 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
175
176
|
const binary = binaryMessage(event.data);
|
|
176
177
|
if (binary)
|
|
177
178
|
return offer(binary);
|
|
178
|
-
Queue.failCauseUnsafe(messages, Cause.fail(transportError("
|
|
179
|
+
Queue.failCauseUnsafe(messages, Cause.fail(transportError("Unsupported WebSocket message payload", {
|
|
180
|
+
cause: event,
|
|
179
181
|
url: input.url,
|
|
180
182
|
operation: "read",
|
|
181
183
|
code: "message",
|
|
@@ -183,7 +185,8 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
183
185
|
})));
|
|
184
186
|
};
|
|
185
187
|
const onError = (event) => {
|
|
186
|
-
Queue.failCauseUnsafe(messages, Cause.fail(transportError(
|
|
188
|
+
Queue.failCauseUnsafe(messages, Cause.fail(transportError(`WebSocket error: ${eventMessage(event)}`, {
|
|
189
|
+
cause: "error" in event ? (event.error ?? event) : event,
|
|
187
190
|
url: input.url,
|
|
188
191
|
operation: "read",
|
|
189
192
|
code: "message",
|
|
@@ -191,7 +194,9 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
191
194
|
})));
|
|
192
195
|
};
|
|
193
196
|
const onClose = (event) => {
|
|
194
|
-
Queue.failCauseUnsafe(messages, Cause.fail(transportError(
|
|
197
|
+
Queue.failCauseUnsafe(messages, Cause.fail(transportError(`WebSocket closed with code ${event.code}`, {
|
|
198
|
+
body: event.reason,
|
|
199
|
+
cause: event,
|
|
195
200
|
url: input.url,
|
|
196
201
|
operation: "read",
|
|
197
202
|
code: String(event.code),
|
|
@@ -209,7 +214,7 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
209
214
|
return {
|
|
210
215
|
sendText: (message) => Effect.suspend(() => {
|
|
211
216
|
if (ws.readyState !== globalThis.WebSocket.OPEN)
|
|
212
|
-
return Effect.fail(transportError(
|
|
217
|
+
return Effect.fail(transportError(`WebSocket is not open (state ${ws.readyState})`, {
|
|
213
218
|
url: input.url,
|
|
214
219
|
operation: "write",
|
|
215
220
|
phase: "send",
|
|
@@ -217,7 +222,8 @@ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
|
|
|
217
222
|
}));
|
|
218
223
|
return Effect.try({
|
|
219
224
|
try: () => ws.send(message),
|
|
220
|
-
catch: (error) => transportError(
|
|
225
|
+
catch: (error) => transportError(error instanceof Error ? error.message : "Failed to send WebSocket message", {
|
|
226
|
+
cause: error,
|
|
221
227
|
url: input.url,
|
|
222
228
|
operation: "write",
|
|
223
229
|
phase: "send",
|
|
@@ -246,17 +252,51 @@ export const makeDirect = (connector) => ({
|
|
|
246
252
|
.open(exchange.connect)
|
|
247
253
|
.pipe(Effect.mapError((error) => annotateTransportError(error, { phase: "connect", delivery: "not-sent" }))), (connection) => connection.close);
|
|
248
254
|
const create = yield* exchange.driver.create(undefined);
|
|
249
|
-
yield* connection.sendText(create.message)
|
|
255
|
+
yield* connection.sendText(create.message).pipe(Effect.mapError((error) => new AIError({
|
|
256
|
+
reason: AIErrorReason.make({
|
|
257
|
+
...error.reason,
|
|
258
|
+
message: error.reason.message,
|
|
259
|
+
cause: error.reason.cause,
|
|
260
|
+
http: error.reason.http ?? connection.http,
|
|
261
|
+
}),
|
|
262
|
+
})));
|
|
250
263
|
const decoder = new TextDecoder();
|
|
251
264
|
let observed = false;
|
|
252
265
|
return {
|
|
266
|
+
http: connection.http,
|
|
253
267
|
frames: connection.messages.pipe(Stream.map((message) => {
|
|
254
268
|
observed = true;
|
|
255
269
|
return messageText(message, decoder);
|
|
256
270
|
}), Stream.mapError((error) => annotateTransportError(error, {
|
|
257
271
|
phase: error.reason._tag === "Transport" && error.reason.phase === "close" ? "close" : "receive",
|
|
258
272
|
delivery: observed ? "accepted" : "ambiguous",
|
|
259
|
-
})), Stream.mapEffect((frame) => exchange.driver.observe(create, frame)
|
|
273
|
+
})), Stream.mapEffect((frame) => exchange.driver.observe(create, frame).pipe(Effect.mapError((error) => new AIError({
|
|
274
|
+
reason: AIErrorReason.make({
|
|
275
|
+
...error.reason,
|
|
276
|
+
message: error.reason.message,
|
|
277
|
+
cause: error.reason.cause,
|
|
278
|
+
body: frame,
|
|
279
|
+
}),
|
|
280
|
+
})), Effect.map((observation) => "error" in observation
|
|
281
|
+
? {
|
|
282
|
+
...observation,
|
|
283
|
+
error: new AIError({
|
|
284
|
+
reason: AIErrorReason.make({
|
|
285
|
+
...observation.error.reason,
|
|
286
|
+
message: observation.error.reason.message,
|
|
287
|
+
cause: observation.error.reason.cause,
|
|
288
|
+
body: frame,
|
|
289
|
+
}),
|
|
290
|
+
}),
|
|
291
|
+
}
|
|
292
|
+
: observation))), Stream.takeUntil(observationTerminal), Stream.mapEffect(observationFrame), Stream.mapError((error) => new AIError({
|
|
293
|
+
reason: AIErrorReason.make({
|
|
294
|
+
...error.reason,
|
|
295
|
+
message: error.reason.message,
|
|
296
|
+
cause: error.reason.cause,
|
|
297
|
+
http: error.reason.http ?? connection.http,
|
|
298
|
+
}),
|
|
299
|
+
}))),
|
|
260
300
|
complete: Effect.void,
|
|
261
301
|
};
|
|
262
302
|
}),
|
|
@@ -283,7 +323,7 @@ export const json = (input) => ({
|
|
|
283
323
|
execute: (prepared, request, _runtime, options) => {
|
|
284
324
|
const webSocket = options?.webSocket;
|
|
285
325
|
if (!webSocket) {
|
|
286
|
-
return Effect.fail(transportError("
|
|
326
|
+
return Effect.fail(transportError("WebSocket JSON transport requires StreamOptions.webSocket", {
|
|
287
327
|
url: prepared.url,
|
|
288
328
|
operation: "request",
|
|
289
329
|
code: "unavailable",
|
|
@@ -298,7 +338,7 @@ export const json = (input) => ({
|
|
|
298
338
|
const exchange = {
|
|
299
339
|
id: request.id ?? "request",
|
|
300
340
|
connect: { url: prepared.url, headers: prepared.headers },
|
|
301
|
-
fallback: () => Stream.fail(transportError("
|
|
341
|
+
fallback: () => Stream.fail(transportError("WebSocket JSON transport does not provide HTTP fallback", {
|
|
302
342
|
url: prepared.url,
|
|
303
343
|
operation: "request",
|
|
304
344
|
code: "websocket",
|
package/dist/schema/errors.d.ts
CHANGED
|
@@ -2,18 +2,12 @@ import { Schema } from "effect";
|
|
|
2
2
|
import { Tool } from "@opencode-ai/schema/tool";
|
|
3
3
|
export declare const ProviderFailureClassification: Schema.Literals<readonly ["context-overflow", "payload-too-large"]>;
|
|
4
4
|
export type ProviderFailureClassification = typeof ProviderFailureClassification.Type;
|
|
5
|
-
declare const
|
|
6
|
-
readonly method: Schema.String;
|
|
5
|
+
declare const HttpContext_base: Schema.Class<HttpContext, Schema.Struct<{
|
|
7
6
|
readonly url: Schema.String;
|
|
7
|
+
readonly status: Schema.Int;
|
|
8
8
|
readonly headers: Schema.$Record<Schema.String, Schema.String>;
|
|
9
9
|
}>, {}>;
|
|
10
|
-
export declare class
|
|
11
|
-
}
|
|
12
|
-
declare const HttpResponseDetails_base: Schema.Class<HttpResponseDetails, Schema.Struct<{
|
|
13
|
-
readonly status: Schema.Number;
|
|
14
|
-
readonly headers: Schema.$Record<Schema.String, Schema.String>;
|
|
15
|
-
}>, {}>;
|
|
16
|
-
export declare class HttpResponseDetails extends HttpResponseDetails_base {
|
|
10
|
+
export declare class HttpContext extends HttpContext_base {
|
|
17
11
|
}
|
|
18
12
|
declare const HttpRateLimitDetails_base: Schema.Class<HttpRateLimitDetails, Schema.Struct<{
|
|
19
13
|
readonly retryAfterMs: Schema.optional<Schema.Number>;
|
|
@@ -23,126 +17,114 @@ declare const HttpRateLimitDetails_base: Schema.Class<HttpRateLimitDetails, Sche
|
|
|
23
17
|
}>, {}>;
|
|
24
18
|
export declare class HttpRateLimitDetails extends HttpRateLimitDetails_base {
|
|
25
19
|
}
|
|
26
|
-
declare const
|
|
27
|
-
readonly request: typeof HttpRequestDetails;
|
|
28
|
-
readonly response: Schema.optional<typeof HttpResponseDetails>;
|
|
29
|
-
readonly body: Schema.optional<Schema.String>;
|
|
30
|
-
readonly bodyTruncated: Schema.optional<Schema.Boolean>;
|
|
31
|
-
readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
|
|
32
|
-
}>, {}>;
|
|
33
|
-
export declare class HttpContext extends HttpContext_base {
|
|
34
|
-
}
|
|
35
|
-
declare const InvalidRequestReason_base: Schema.Class<InvalidRequestReason, Schema.Struct<{
|
|
36
|
-
readonly _tag: Schema.tag<"InvalidRequest">;
|
|
37
|
-
readonly message: Schema.String;
|
|
20
|
+
declare const InvalidRequestError_base: Schema.Class<InvalidRequestError, Schema.TaggedStruct<"InvalidRequest", {
|
|
38
21
|
readonly parameter: Schema.optional<Schema.String>;
|
|
39
22
|
readonly classification: Schema.optional<Schema.Literals<readonly ["context-overflow", "payload-too-large"]>>;
|
|
40
|
-
readonly
|
|
23
|
+
readonly message: Schema.String;
|
|
24
|
+
readonly body: Schema.optional<Schema.String>;
|
|
41
25
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
42
|
-
|
|
43
|
-
|
|
26
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
27
|
+
}>, import("effect/Cause").YieldableError>;
|
|
28
|
+
export declare class InvalidRequestError extends InvalidRequestError_base {
|
|
44
29
|
}
|
|
45
|
-
declare const
|
|
46
|
-
readonly _tag: Schema.tag<"NoRoute">;
|
|
30
|
+
declare const NoRouteError_base: Schema.Class<NoRouteError, Schema.TaggedStruct<"NoRoute", {
|
|
47
31
|
readonly route: Schema.String;
|
|
48
32
|
readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
|
|
49
33
|
readonly model: Schema.brand<Schema.String, "AI.ModelID">;
|
|
50
|
-
}>, {}>;
|
|
51
|
-
export declare class NoRouteReason extends NoRouteReason_base {
|
|
52
|
-
get message(): string;
|
|
53
|
-
}
|
|
54
|
-
declare const AuthenticationReason_base: Schema.Class<AuthenticationReason, Schema.Struct<{
|
|
55
|
-
readonly _tag: Schema.tag<"Authentication">;
|
|
56
34
|
readonly message: Schema.String;
|
|
57
|
-
readonly
|
|
58
|
-
readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
|
|
35
|
+
readonly body: Schema.optional<Schema.String>;
|
|
59
36
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
38
|
+
}>, import("effect/Cause").YieldableError>;
|
|
39
|
+
export declare class NoRouteError extends NoRouteError_base {
|
|
62
40
|
}
|
|
63
|
-
declare const
|
|
64
|
-
|
|
65
|
-
|
|
41
|
+
declare const AuthenticationError_base: Schema.Class<AuthenticationError, Schema.TaggedStruct<"Authentication", {
|
|
42
|
+
message: Schema.String;
|
|
43
|
+
body: Schema.optional<Schema.String>;
|
|
44
|
+
http: Schema.optional<typeof HttpContext>;
|
|
45
|
+
cause: Schema.optional<Schema.Defect>;
|
|
46
|
+
}>, import("effect/Cause").YieldableError>;
|
|
47
|
+
export declare class AuthenticationError extends AuthenticationError_base {
|
|
48
|
+
}
|
|
49
|
+
declare const RateLimitError_base: Schema.Class<RateLimitError, Schema.TaggedStruct<"RateLimit", {
|
|
66
50
|
readonly retryAfterMs: Schema.optional<Schema.Number>;
|
|
67
51
|
readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
|
|
68
|
-
readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
|
|
69
|
-
readonly http: Schema.optional<typeof HttpContext>;
|
|
70
|
-
}>, {}>;
|
|
71
|
-
export declare class RateLimitReason extends RateLimitReason_base {
|
|
72
|
-
}
|
|
73
|
-
declare const QuotaExceededReason_base: Schema.Class<QuotaExceededReason, Schema.Struct<{
|
|
74
|
-
readonly _tag: Schema.tag<"QuotaExceeded">;
|
|
75
52
|
readonly message: Schema.String;
|
|
76
|
-
readonly
|
|
53
|
+
readonly body: Schema.optional<Schema.String>;
|
|
77
54
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
78
|
-
|
|
79
|
-
|
|
55
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
56
|
+
}>, import("effect/Cause").YieldableError>;
|
|
57
|
+
export declare class RateLimitError extends RateLimitError_base {
|
|
80
58
|
}
|
|
81
|
-
declare const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}>,
|
|
87
|
-
export declare class
|
|
59
|
+
declare const QuotaExceededError_base: Schema.Class<QuotaExceededError, Schema.TaggedStruct<"QuotaExceeded", {
|
|
60
|
+
message: Schema.String;
|
|
61
|
+
body: Schema.optional<Schema.String>;
|
|
62
|
+
http: Schema.optional<typeof HttpContext>;
|
|
63
|
+
cause: Schema.optional<Schema.Defect>;
|
|
64
|
+
}>, import("effect/Cause").YieldableError>;
|
|
65
|
+
export declare class QuotaExceededError extends QuotaExceededError_base {
|
|
88
66
|
}
|
|
89
|
-
declare const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
67
|
+
declare const ContentPolicyError_base: Schema.Class<ContentPolicyError, Schema.TaggedStruct<"ContentPolicy", {
|
|
68
|
+
message: Schema.String;
|
|
69
|
+
body: Schema.optional<Schema.String>;
|
|
70
|
+
http: Schema.optional<typeof HttpContext>;
|
|
71
|
+
cause: Schema.optional<Schema.Defect>;
|
|
72
|
+
}>, import("effect/Cause").YieldableError>;
|
|
73
|
+
export declare class ContentPolicyError extends ContentPolicyError_base {
|
|
74
|
+
}
|
|
75
|
+
declare const ProviderInternalError_base: Schema.Class<ProviderInternalError, Schema.TaggedStruct<"ProviderInternal", {
|
|
93
76
|
readonly retryAfterMs: Schema.optional<Schema.Number>;
|
|
94
|
-
readonly
|
|
77
|
+
readonly message: Schema.String;
|
|
78
|
+
readonly body: Schema.optional<Schema.String>;
|
|
95
79
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
96
|
-
|
|
97
|
-
|
|
80
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
81
|
+
}>, import("effect/Cause").YieldableError>;
|
|
82
|
+
export declare class ProviderInternalError extends ProviderInternalError_base {
|
|
98
83
|
}
|
|
99
84
|
export declare const TransportType: Schema.Literals<readonly ["http", "websocket"]>;
|
|
100
85
|
export type TransportType = typeof TransportType.Type;
|
|
101
86
|
export declare const TransportOperation: Schema.Literals<readonly ["request", "read", "write"]>;
|
|
102
87
|
export type TransportOperation = typeof TransportOperation.Type;
|
|
103
|
-
declare const
|
|
104
|
-
readonly _tag: Schema.tag<"Transport">;
|
|
105
|
-
readonly message: Schema.String;
|
|
88
|
+
declare const TransportError_base: Schema.Class<TransportError, Schema.TaggedStruct<"Transport", {
|
|
106
89
|
readonly transport: Schema.Literals<readonly ["http", "websocket"]>;
|
|
107
90
|
readonly operation: Schema.Literals<readonly ["request", "read", "write"]>;
|
|
108
91
|
readonly code: Schema.optional<Schema.String>;
|
|
109
92
|
readonly url: Schema.optional<Schema.String>;
|
|
110
|
-
readonly http: Schema.optional<typeof HttpContext>;
|
|
111
93
|
readonly phase: Schema.optional<Schema.Literals<readonly ["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"]>>;
|
|
112
94
|
readonly delivery: Schema.optional<Schema.Literals<readonly ["not-sent", "rejected", "ambiguous", "accepted"]>>;
|
|
113
95
|
readonly recovery: Schema.optional<Schema.Literals<readonly ["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"]>>;
|
|
114
|
-
}>, {}>;
|
|
115
|
-
export declare class TransportReason extends TransportReason_base {
|
|
116
|
-
}
|
|
117
|
-
declare const InvalidProviderOutputReason_base: Schema.Class<InvalidProviderOutputReason, Schema.Struct<{
|
|
118
|
-
readonly _tag: Schema.tag<"InvalidProviderOutput">;
|
|
119
96
|
readonly message: Schema.String;
|
|
97
|
+
readonly body: Schema.optional<Schema.String>;
|
|
98
|
+
readonly http: Schema.optional<typeof HttpContext>;
|
|
99
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
100
|
+
}>, import("effect/Cause").YieldableError>;
|
|
101
|
+
export declare class TransportError extends TransportError_base {
|
|
102
|
+
}
|
|
103
|
+
declare const InvalidProviderOutputError_base: Schema.Class<InvalidProviderOutputError, Schema.TaggedStruct<"InvalidProviderOutput", {
|
|
120
104
|
readonly classification: Schema.optional<Schema.Literals<readonly ["incomplete-stream"]>>;
|
|
121
105
|
readonly route: Schema.optional<Schema.String>;
|
|
122
|
-
readonly raw: Schema.optional<Schema.String>;
|
|
123
|
-
readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
|
|
124
|
-
}>, {}>;
|
|
125
|
-
export declare class InvalidProviderOutputReason extends InvalidProviderOutputReason_base {
|
|
126
|
-
}
|
|
127
|
-
declare const UnknownProviderReason_base: Schema.Class<UnknownProviderReason, Schema.Struct<{
|
|
128
|
-
readonly _tag: Schema.tag<"UnknownProvider">;
|
|
129
106
|
readonly message: Schema.String;
|
|
130
|
-
readonly
|
|
131
|
-
readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
|
|
107
|
+
readonly body: Schema.optional<Schema.String>;
|
|
132
108
|
readonly http: Schema.optional<typeof HttpContext>;
|
|
133
|
-
|
|
134
|
-
|
|
109
|
+
readonly cause: Schema.optional<Schema.Defect>;
|
|
110
|
+
}>, import("effect/Cause").YieldableError>;
|
|
111
|
+
export declare class InvalidProviderOutputError extends InvalidProviderOutputError_base {
|
|
135
112
|
}
|
|
136
|
-
|
|
113
|
+
declare const UnknownProviderError_base: Schema.Class<UnknownProviderError, Schema.TaggedStruct<"UnknownProvider", {
|
|
114
|
+
message: Schema.String;
|
|
115
|
+
body: Schema.optional<Schema.String>;
|
|
116
|
+
http: Schema.optional<typeof HttpContext>;
|
|
117
|
+
cause: Schema.optional<Schema.Defect>;
|
|
118
|
+
}>, import("effect/Cause").YieldableError>;
|
|
119
|
+
export declare class UnknownProviderError extends UnknownProviderError_base {
|
|
120
|
+
}
|
|
121
|
+
export declare const AIErrorReason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestError, typeof NoRouteError, typeof AuthenticationError, typeof RateLimitError, typeof QuotaExceededError, typeof ContentPolicyError, typeof ProviderInternalError, typeof TransportError, typeof InvalidProviderOutputError, typeof UnknownProviderError]>;
|
|
137
122
|
export type AIErrorReason = Schema.Schema.Type<typeof AIErrorReason>;
|
|
138
123
|
declare const AIError_base: Schema.Class<AIError, Schema.TaggedStruct<"AI.Error", {
|
|
139
|
-
readonly
|
|
140
|
-
readonly method: Schema.String;
|
|
141
|
-
readonly reason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestReason, typeof NoRouteReason, typeof AuthenticationReason, typeof RateLimitReason, typeof QuotaExceededReason, typeof ContentPolicyReason, typeof ProviderInternalReason, typeof TransportReason, typeof InvalidProviderOutputReason, typeof UnknownProviderReason]>;
|
|
142
|
-
readonly body: Schema.optional<Schema.String>;
|
|
124
|
+
readonly reason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestError, typeof NoRouteError, typeof AuthenticationError, typeof RateLimitError, typeof QuotaExceededError, typeof ContentPolicyError, typeof ProviderInternalError, typeof TransportError, typeof InvalidProviderOutputError, typeof UnknownProviderError]>;
|
|
143
125
|
}>, import("effect/Cause").YieldableError>;
|
|
144
126
|
export declare class AIError extends AIError_base {
|
|
145
|
-
readonly cause:
|
|
127
|
+
readonly cause: InvalidRequestError | NoRouteError | AuthenticationError | RateLimitError | QuotaExceededError | ContentPolicyError | ProviderInternalError | TransportError | InvalidProviderOutputError | UnknownProviderError;
|
|
146
128
|
get message(): string;
|
|
147
129
|
}
|
|
148
130
|
/**
|
package/dist/schema/errors.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
import { Tool } from "@opencode-ai/schema/tool";
|
|
3
3
|
import { ModelID, ProviderID, RouteID } from "./ids.js";
|
|
4
|
-
import { ProviderMetadata } from "./messages.js";
|
|
5
4
|
export const ProviderFailureClassification = Schema.Literals(["context-overflow", "payload-too-large"]);
|
|
6
|
-
export class
|
|
7
|
-
method: Schema.String,
|
|
5
|
+
export class HttpContext extends Schema.Class("AI.HttpContext")({
|
|
8
6
|
url: Schema.String,
|
|
9
|
-
|
|
10
|
-
}) {
|
|
11
|
-
}
|
|
12
|
-
export class HttpResponseDetails extends Schema.Class("AI.HttpResponseDetails")({
|
|
13
|
-
status: Schema.Number,
|
|
7
|
+
status: Schema.Int.check(Schema.isBetween({ minimum: 100, maximum: 599 })),
|
|
14
8
|
headers: Schema.Record(Schema.String, Schema.String),
|
|
15
9
|
}) {
|
|
16
10
|
}
|
|
@@ -21,128 +15,82 @@ export class HttpRateLimitDetails extends Schema.Class("AI.HttpRateLimitDetails"
|
|
|
21
15
|
reset: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
|
22
16
|
}) {
|
|
23
17
|
}
|
|
24
|
-
|
|
25
|
-
request: HttpRequestDetails,
|
|
26
|
-
response: Schema.optional(HttpResponseDetails),
|
|
27
|
-
body: Schema.optional(Schema.String),
|
|
28
|
-
bodyTruncated: Schema.optional(Schema.Boolean),
|
|
29
|
-
rateLimit: Schema.optional(HttpRateLimitDetails),
|
|
30
|
-
}) {
|
|
31
|
-
}
|
|
32
|
-
export class InvalidRequestReason extends Schema.Class("AI.Error.InvalidRequest")({
|
|
33
|
-
_tag: Schema.tag("InvalidRequest"),
|
|
18
|
+
const ReasonFields = {
|
|
34
19
|
message: Schema.String,
|
|
20
|
+
// Preserve the complete original response or triggering event before decoding narrows it.
|
|
21
|
+
body: Schema.optional(Schema.String),
|
|
22
|
+
http: Schema.optional(HttpContext),
|
|
23
|
+
cause: Schema.optional(Schema.Defect({ includeStack: true })),
|
|
24
|
+
};
|
|
25
|
+
export class InvalidRequestError extends Schema.TaggedError("AI.Error.InvalidRequest")("InvalidRequest", {
|
|
26
|
+
...ReasonFields,
|
|
35
27
|
parameter: Schema.optional(Schema.String),
|
|
36
28
|
classification: Schema.optional(ProviderFailureClassification),
|
|
37
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
38
|
-
http: Schema.optional(HttpContext),
|
|
39
29
|
}) {
|
|
40
30
|
}
|
|
41
|
-
export class
|
|
42
|
-
|
|
31
|
+
export class NoRouteError extends Schema.TaggedError("AI.Error.NoRoute")("NoRoute", {
|
|
32
|
+
...ReasonFields,
|
|
43
33
|
route: RouteID,
|
|
44
34
|
provider: ProviderID,
|
|
45
35
|
model: ModelID,
|
|
46
36
|
}) {
|
|
47
|
-
get message() {
|
|
48
|
-
return `No AI route for ${this.provider}/${this.model} using ${this.route}`;
|
|
49
|
-
}
|
|
50
37
|
}
|
|
51
|
-
export class
|
|
52
|
-
_tag: Schema.tag("Authentication"),
|
|
53
|
-
message: Schema.String,
|
|
54
|
-
kind: Schema.Literals(["missing", "invalid", "expired", "insufficient-permissions", "unknown"]),
|
|
55
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
56
|
-
http: Schema.optional(HttpContext),
|
|
57
|
-
}) {
|
|
38
|
+
export class AuthenticationError extends Schema.TaggedError("AI.Error.Authentication")("Authentication", ReasonFields) {
|
|
58
39
|
}
|
|
59
|
-
export class
|
|
60
|
-
|
|
61
|
-
message: Schema.String,
|
|
40
|
+
export class RateLimitError extends Schema.TaggedError("AI.Error.RateLimit")("RateLimit", {
|
|
41
|
+
...ReasonFields,
|
|
62
42
|
retryAfterMs: Schema.optional(Schema.Number),
|
|
63
43
|
rateLimit: Schema.optional(HttpRateLimitDetails),
|
|
64
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
65
|
-
http: Schema.optional(HttpContext),
|
|
66
44
|
}) {
|
|
67
45
|
}
|
|
68
|
-
export class
|
|
69
|
-
_tag: Schema.tag("QuotaExceeded"),
|
|
70
|
-
message: Schema.String,
|
|
71
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
72
|
-
http: Schema.optional(HttpContext),
|
|
73
|
-
}) {
|
|
46
|
+
export class QuotaExceededError extends Schema.TaggedError("AI.Error.QuotaExceeded")("QuotaExceeded", ReasonFields) {
|
|
74
47
|
}
|
|
75
|
-
export class
|
|
76
|
-
_tag: Schema.tag("ContentPolicy"),
|
|
77
|
-
message: Schema.String,
|
|
78
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
79
|
-
http: Schema.optional(HttpContext),
|
|
80
|
-
}) {
|
|
48
|
+
export class ContentPolicyError extends Schema.TaggedError("AI.Error.ContentPolicy")("ContentPolicy", ReasonFields) {
|
|
81
49
|
}
|
|
82
|
-
export class
|
|
83
|
-
|
|
84
|
-
message: Schema.String,
|
|
85
|
-
status: Schema.optional(Schema.Number),
|
|
50
|
+
export class ProviderInternalError extends Schema.TaggedError("AI.Error.ProviderInternal")("ProviderInternal", {
|
|
51
|
+
...ReasonFields,
|
|
86
52
|
retryAfterMs: Schema.optional(Schema.Number),
|
|
87
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
88
|
-
http: Schema.optional(HttpContext),
|
|
89
53
|
}) {
|
|
90
54
|
}
|
|
91
55
|
export const TransportType = Schema.Literals(["http", "websocket"]);
|
|
92
56
|
export const TransportOperation = Schema.Literals(["request", "read", "write"]);
|
|
93
|
-
export class
|
|
94
|
-
|
|
95
|
-
message: Schema.String,
|
|
57
|
+
export class TransportError extends Schema.TaggedError("AI.Error.Transport")("Transport", {
|
|
58
|
+
...ReasonFields,
|
|
96
59
|
transport: TransportType,
|
|
97
60
|
operation: TransportOperation,
|
|
98
61
|
code: Schema.optional(Schema.String),
|
|
99
62
|
url: Schema.optional(Schema.String),
|
|
100
|
-
http: Schema.optional(HttpContext),
|
|
101
63
|
phase: Schema.optional(Schema.Literals(["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"])),
|
|
102
64
|
delivery: Schema.optional(Schema.Literals(["not-sent", "rejected", "ambiguous", "accepted"])),
|
|
103
65
|
recovery: Schema.optional(Schema.Literals(["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"])),
|
|
104
66
|
}) {
|
|
105
67
|
}
|
|
106
|
-
export class
|
|
107
|
-
|
|
108
|
-
message: Schema.String,
|
|
68
|
+
export class InvalidProviderOutputError extends Schema.TaggedError("AI.Error.InvalidProviderOutput")("InvalidProviderOutput", {
|
|
69
|
+
...ReasonFields,
|
|
109
70
|
classification: Schema.optional(Schema.Literals(["incomplete-stream"])),
|
|
110
71
|
route: Schema.optional(Schema.String),
|
|
111
|
-
raw: Schema.optional(Schema.String),
|
|
112
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
113
72
|
}) {
|
|
114
73
|
}
|
|
115
|
-
export class
|
|
116
|
-
_tag: Schema.tag("UnknownProvider"),
|
|
117
|
-
message: Schema.String,
|
|
118
|
-
status: Schema.optional(Schema.Number),
|
|
119
|
-
providerMetadata: Schema.optional(ProviderMetadata),
|
|
120
|
-
http: Schema.optional(HttpContext),
|
|
121
|
-
}) {
|
|
74
|
+
export class UnknownProviderError extends Schema.TaggedError("AI.Error.UnknownProvider")("UnknownProvider", ReasonFields) {
|
|
122
75
|
}
|
|
123
76
|
export const AIErrorReason = Schema.Union([
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
77
|
+
InvalidRequestError,
|
|
78
|
+
NoRouteError,
|
|
79
|
+
AuthenticationError,
|
|
80
|
+
RateLimitError,
|
|
81
|
+
QuotaExceededError,
|
|
82
|
+
ContentPolicyError,
|
|
83
|
+
ProviderInternalError,
|
|
84
|
+
TransportError,
|
|
85
|
+
InvalidProviderOutputError,
|
|
86
|
+
UnknownProviderError,
|
|
134
87
|
]).pipe(Schema.toTaggedUnion("_tag"));
|
|
135
88
|
export class AIError extends Schema.TaggedError()("AI.Error", {
|
|
136
|
-
module: Schema.String,
|
|
137
|
-
method: Schema.String,
|
|
138
89
|
reason: AIErrorReason,
|
|
139
|
-
// Raw provider payload as a string, so classified failures never lose the
|
|
140
|
-
// original error detail even when the pretty message is a summary.
|
|
141
|
-
body: Schema.optional(Schema.String),
|
|
142
90
|
}) {
|
|
143
91
|
cause = this.reason;
|
|
144
92
|
get message() {
|
|
145
|
-
return
|
|
93
|
+
return this.reason.message;
|
|
146
94
|
}
|
|
147
95
|
}
|
|
148
96
|
/**
|