@opencode-ai/ai 0.0.0-beta-17492

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.
Files changed (194) hide show
  1. package/README.md +392 -0
  2. package/dist/cache-policy.d.ts +2 -0
  3. package/dist/cache-policy.js +121 -0
  4. package/dist/image-client.d.ts +19 -0
  5. package/dist/image-client.js +19 -0
  6. package/dist/image.d.ts +110 -0
  7. package/dist/image.js +102 -0
  8. package/dist/index.d.ts +18 -0
  9. package/dist/index.js +12 -0
  10. package/dist/llm.d.ts +230 -0
  11. package/dist/llm.js +77 -0
  12. package/dist/protocols/anthropic-messages.d.ts +633 -0
  13. package/dist/protocols/anthropic-messages.js +860 -0
  14. package/dist/protocols/bedrock-converse.d.ts +533 -0
  15. package/dist/protocols/bedrock-converse.js +584 -0
  16. package/dist/protocols/bedrock-event-stream.d.ts +9 -0
  17. package/dist/protocols/bedrock-event-stream.js +73 -0
  18. package/dist/protocols/gemini.d.ts +300 -0
  19. package/dist/protocols/gemini.js +512 -0
  20. package/dist/protocols/google-images.d.ts +30 -0
  21. package/dist/protocols/google-images.js +191 -0
  22. package/dist/protocols/index.d.ts +10 -0
  23. package/dist/protocols/index.js +10 -0
  24. package/dist/protocols/open-responses-channel.d.ts +26 -0
  25. package/dist/protocols/open-responses-channel.js +120 -0
  26. package/dist/protocols/open-responses.d.ts +951 -0
  27. package/dist/protocols/open-responses.js +873 -0
  28. package/dist/protocols/openai-chat.d.ts +795 -0
  29. package/dist/protocols/openai-chat.js +718 -0
  30. package/dist/protocols/openai-compatible-chat.d.ts +107 -0
  31. package/dist/protocols/openai-compatible-chat.js +20 -0
  32. package/dist/protocols/openai-compatible-responses.d.ts +96 -0
  33. package/dist/protocols/openai-compatible-responses.js +17 -0
  34. package/dist/protocols/openai-images.d.ts +32 -0
  35. package/dist/protocols/openai-images.js +188 -0
  36. package/dist/protocols/openai-responses-channel.d.ts +12 -0
  37. package/dist/protocols/openai-responses-channel.js +142 -0
  38. package/dist/protocols/openai-responses.d.ts +596 -0
  39. package/dist/protocols/openai-responses.js +208 -0
  40. package/dist/protocols/shared.d.ts +194 -0
  41. package/dist/protocols/shared.js +238 -0
  42. package/dist/protocols/utils/bedrock-auth.d.ts +21 -0
  43. package/dist/protocols/utils/bedrock-auth.js +43 -0
  44. package/dist/protocols/utils/bedrock-cache.d.ts +15 -0
  45. package/dist/protocols/utils/bedrock-cache.js +29 -0
  46. package/dist/protocols/utils/bedrock-media.d.ts +49 -0
  47. package/dist/protocols/utils/bedrock-media.js +70 -0
  48. package/dist/protocols/utils/cache.d.ts +6 -0
  49. package/dist/protocols/utils/cache.js +8 -0
  50. package/dist/protocols/utils/gemini-tool-schema.d.ts +2 -0
  51. package/dist/protocols/utils/gemini-tool-schema.js +103 -0
  52. package/dist/protocols/utils/image-input.d.ts +21 -0
  53. package/dist/protocols/utils/image-input.js +22 -0
  54. package/dist/protocols/utils/lifecycle.d.ts +20 -0
  55. package/dist/protocols/utils/lifecycle.js +68 -0
  56. package/dist/protocols/utils/open-responses-options.d.ts +21 -0
  57. package/dist/protocols/utils/open-responses-options.js +41 -0
  58. package/dist/protocols/utils/openai-image.d.ts +5 -0
  59. package/dist/protocols/utils/openai-image.js +18 -0
  60. package/dist/protocols/utils/openai-options.d.ts +14 -0
  61. package/dist/protocols/utils/openai-options.js +14 -0
  62. package/dist/protocols/utils/tool-schema.d.ts +8 -0
  63. package/dist/protocols/utils/tool-schema.js +81 -0
  64. package/dist/protocols/utils/tool-stream.d.ts +639 -0
  65. package/dist/protocols/utils/tool-stream.js +141 -0
  66. package/dist/protocols/xai-images.d.ts +26 -0
  67. package/dist/protocols/xai-images.js +111 -0
  68. package/dist/protocols/zai-images.d.ts +22 -0
  69. package/dist/protocols/zai-images.js +84 -0
  70. package/dist/protocols.d.ts +1 -0
  71. package/dist/protocols.js +1 -0
  72. package/dist/provider-error.d.ts +14 -0
  73. package/dist/provider-error.js +130 -0
  74. package/dist/provider-package.d.ts +15 -0
  75. package/dist/provider-package.js +1 -0
  76. package/dist/provider.d.ts +23 -0
  77. package/dist/provider.js +2 -0
  78. package/dist/providers/amazon-bedrock/mantle/chat.d.ts +2 -0
  79. package/dist/providers/amazon-bedrock/mantle/chat.js +1 -0
  80. package/dist/providers/amazon-bedrock/mantle/responses.d.ts +2 -0
  81. package/dist/providers/amazon-bedrock/mantle/responses.js +1 -0
  82. package/dist/providers/amazon-bedrock/mantle.d.ts +2 -0
  83. package/dist/providers/amazon-bedrock/mantle.js +1 -0
  84. package/dist/providers/amazon-bedrock-mantle.d.ts +247 -0
  85. package/dist/providers/amazon-bedrock-mantle.js +68 -0
  86. package/dist/providers/amazon-bedrock.d.ts +172 -0
  87. package/dist/providers/amazon-bedrock.js +41 -0
  88. package/dist/providers/anthropic-compatible.d.ts +218 -0
  89. package/dist/providers/anthropic-compatible.js +45 -0
  90. package/dist/providers/anthropic.d.ts +216 -0
  91. package/dist/providers/anthropic.js +40 -0
  92. package/dist/providers/azure/chat.d.ts +2 -0
  93. package/dist/providers/azure/chat.js +1 -0
  94. package/dist/providers/azure/responses.d.ts +2 -0
  95. package/dist/providers/azure/responses.js +1 -0
  96. package/dist/providers/azure.d.ts +248 -0
  97. package/dist/providers/azure.js +90 -0
  98. package/dist/providers/cloudflare.d.ts +338 -0
  99. package/dist/providers/cloudflare.js +87 -0
  100. package/dist/providers/google-vertex/chat.d.ts +2 -0
  101. package/dist/providers/google-vertex/chat.js +1 -0
  102. package/dist/providers/google-vertex/gemini.d.ts +2 -0
  103. package/dist/providers/google-vertex/gemini.js +1 -0
  104. package/dist/providers/google-vertex/messages.d.ts +2 -0
  105. package/dist/providers/google-vertex/messages.js +1 -0
  106. package/dist/providers/google-vertex/responses.d.ts +2 -0
  107. package/dist/providers/google-vertex/responses.js +1 -0
  108. package/dist/providers/google-vertex-chat.d.ts +131 -0
  109. package/dist/providers/google-vertex-chat.js +50 -0
  110. package/dist/providers/google-vertex-messages.d.ts +215 -0
  111. package/dist/providers/google-vertex-messages.js +75 -0
  112. package/dist/providers/google-vertex-responses.d.ts +122 -0
  113. package/dist/providers/google-vertex-responses.js +51 -0
  114. package/dist/providers/google-vertex-shared.d.ts +22 -0
  115. package/dist/providers/google-vertex-shared.js +61 -0
  116. package/dist/providers/google-vertex.d.ts +115 -0
  117. package/dist/providers/google-vertex.js +64 -0
  118. package/dist/providers/google.d.ts +112 -0
  119. package/dist/providers/google.js +43 -0
  120. package/dist/providers/index.d.ts +18 -0
  121. package/dist/providers/index.js +18 -0
  122. package/dist/providers/open-responses-options.d.ts +16 -0
  123. package/dist/providers/open-responses-options.js +1 -0
  124. package/dist/providers/openai/chat.d.ts +2 -0
  125. package/dist/providers/openai/chat.js +1 -0
  126. package/dist/providers/openai/responses.d.ts +2 -0
  127. package/dist/providers/openai/responses.js +1 -0
  128. package/dist/providers/openai-compatible/responses.d.ts +1 -0
  129. package/dist/providers/openai-compatible/responses.js +1 -0
  130. package/dist/providers/openai-compatible-profile.d.ts +43 -0
  131. package/dist/providers/openai-compatible-profile.js +12 -0
  132. package/dist/providers/openai-compatible-responses.d.ts +120 -0
  133. package/dist/providers/openai-compatible-responses.js +33 -0
  134. package/dist/providers/openai-compatible.d.ts +167 -0
  135. package/dist/providers/openai-compatible.js +55 -0
  136. package/dist/providers/openai-options.d.ts +21 -0
  137. package/dist/providers/openai-options.js +41 -0
  138. package/dist/providers/openai.d.ts +264 -0
  139. package/dist/providers/openai.js +83 -0
  140. package/dist/providers/openrouter.d.ts +537 -0
  141. package/dist/providers/openrouter.js +117 -0
  142. package/dist/providers/xai.d.ts +249 -0
  143. package/dist/providers/xai.js +79 -0
  144. package/dist/providers/zai.d.ts +24 -0
  145. package/dist/providers/zai.js +21 -0
  146. package/dist/providers.d.ts +1 -0
  147. package/dist/providers.js +1 -0
  148. package/dist/route/auth-options.d.ts +34 -0
  149. package/dist/route/auth-options.js +14 -0
  150. package/dist/route/auth.d.ts +51 -0
  151. package/dist/route/auth.js +89 -0
  152. package/dist/route/client.d.ts +348 -0
  153. package/dist/route/client.js +214 -0
  154. package/dist/route/endpoint.d.ts +28 -0
  155. package/dist/route/endpoint.js +21 -0
  156. package/dist/route/executor.d.ts +23 -0
  157. package/dist/route/executor.js +227 -0
  158. package/dist/route/framing.d.ts +23 -0
  159. package/dist/route/framing.js +4 -0
  160. package/dist/route/index.d.ts +16 -0
  161. package/dist/route/index.js +9 -0
  162. package/dist/route/protocol.d.ts +77 -0
  163. package/dist/route/protocol.js +17 -0
  164. package/dist/route/transport/http.d.ts +34 -0
  165. package/dist/route/transport/http.js +63 -0
  166. package/dist/route/transport/index.d.ts +39 -0
  167. package/dist/route/transport/index.js +4 -0
  168. package/dist/route/transport/websocket-channel.d.ts +56 -0
  169. package/dist/route/transport/websocket-channel.js +1 -0
  170. package/dist/route/transport/websocket.d.ts +55 -0
  171. package/dist/route/transport/websocket.js +326 -0
  172. package/dist/route.d.ts +1 -0
  173. package/dist/route.js +1 -0
  174. package/dist/schema/errors.d.ts +159 -0
  175. package/dist/schema/errors.js +155 -0
  176. package/dist/schema/events.d.ts +4587 -0
  177. package/dist/schema/events.js +492 -0
  178. package/dist/schema/ids.d.ts +30 -0
  179. package/dist/schema/ids.js +19 -0
  180. package/dist/schema/index.d.ts +5 -0
  181. package/dist/schema/index.js +5 -0
  182. package/dist/schema/messages.d.ts +402 -0
  183. package/dist/schema/messages.js +244 -0
  184. package/dist/schema/options.d.ts +159 -0
  185. package/dist/schema/options.js +202 -0
  186. package/dist/testing.d.ts +1493 -0
  187. package/dist/testing.js +88 -0
  188. package/dist/tool-runtime.d.ts +15 -0
  189. package/dist/tool-runtime.js +54 -0
  190. package/dist/tool.d.ts +135 -0
  191. package/dist/tool.js +66 -0
  192. package/dist/utils/record.d.ts +2 -0
  193. package/dist/utils/record.js +2 -0
  194. package/package.json +47 -0
@@ -0,0 +1,326 @@
1
+ import { Cause, Effect, Queue, Stream } from "effect";
2
+ import { Headers } from "effect/unstable/http";
3
+ import { Socket } from "effect/unstable/socket";
4
+ import { AIError, TransportReason } from "../../schema/index.js";
5
+ import * as HttpTransport from "./http.js";
6
+ const MAX_FRAME_BYTES = 16 * 1024 * 1024;
7
+ const transportError = (method, message, input) => new AIError({
8
+ module: "WebSocketConnector",
9
+ method,
10
+ reason: new TransportReason({
11
+ message,
12
+ transport: "websocket",
13
+ operation: input.operation,
14
+ url: input.url,
15
+ code: input.code,
16
+ phase: input.phase,
17
+ delivery: input.delivery,
18
+ }),
19
+ });
20
+ const annotateTransportError = (error, input) => error.reason._tag === "Transport"
21
+ ? new AIError({
22
+ module: error.module,
23
+ method: error.method,
24
+ reason: new TransportReason({
25
+ message: error.reason.message,
26
+ transport: error.reason.transport,
27
+ operation: error.reason.operation,
28
+ code: error.reason.code,
29
+ url: error.reason.url,
30
+ http: error.reason.http,
31
+ phase: input.phase,
32
+ delivery: input.delivery,
33
+ recovery: error.reason.recovery,
34
+ }),
35
+ })
36
+ : error;
37
+ const eventMessage = (event) => {
38
+ if ("message" in event && typeof event.message === "string")
39
+ return event.message;
40
+ return event.type;
41
+ };
42
+ const binaryMessage = (data) => {
43
+ if (data instanceof Uint8Array)
44
+ return data;
45
+ if (data instanceof ArrayBuffer)
46
+ return new Uint8Array(data);
47
+ if (ArrayBuffer.isView(data))
48
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
49
+ return undefined;
50
+ };
51
+ const waitOpen = (ws, input) => {
52
+ if (ws.readyState === globalThis.WebSocket.OPEN)
53
+ return Effect.void;
54
+ if (ws.readyState === globalThis.WebSocket.CLOSING || ws.readyState === globalThis.WebSocket.CLOSED) {
55
+ return Effect.fail(transportError("open", `WebSocket closed before opening (state ${ws.readyState})`, {
56
+ url: input.url,
57
+ operation: "request",
58
+ code: "closed",
59
+ phase: "connect",
60
+ delivery: "not-sent",
61
+ }));
62
+ }
63
+ return Effect.callback((resume, signal) => {
64
+ const cleanup = () => {
65
+ ws.removeEventListener("open", onOpen);
66
+ ws.removeEventListener("error", onError);
67
+ ws.removeEventListener("close", onClose);
68
+ signal.removeEventListener("abort", onAbort);
69
+ };
70
+ const onAbort = () => {
71
+ cleanup();
72
+ if (ws.readyState !== globalThis.WebSocket.CLOSED && ws.readyState !== globalThis.WebSocket.CLOSING)
73
+ ws.close(1000);
74
+ };
75
+ const onOpen = () => {
76
+ cleanup();
77
+ resume(Effect.void);
78
+ };
79
+ const onError = (event) => {
80
+ cleanup();
81
+ resume(Effect.fail(transportError("open", `Failed to open WebSocket: ${eventMessage(event)}`, {
82
+ url: input.url,
83
+ operation: "request",
84
+ phase: "connect",
85
+ delivery: "not-sent",
86
+ })));
87
+ };
88
+ const onClose = (event) => {
89
+ cleanup();
90
+ resume(Effect.fail(transportError("open", `WebSocket closed before opening with code ${event.code}`, {
91
+ url: input.url,
92
+ operation: "request",
93
+ code: String(event.code),
94
+ phase: "connect",
95
+ delivery: "not-sent",
96
+ })));
97
+ };
98
+ ws.addEventListener("open", onOpen, { once: true });
99
+ ws.addEventListener("error", onError, { once: true });
100
+ ws.addEventListener("close", onClose, { once: true });
101
+ signal.addEventListener("abort", onAbort, { once: true });
102
+ });
103
+ };
104
+ export const toWebSocketUrl = (value) => Effect.try({
105
+ try: () => {
106
+ const url = new URL(value);
107
+ if (url.protocol === "https:") {
108
+ url.protocol = "wss:";
109
+ return url.toString();
110
+ }
111
+ if (url.protocol === "http:") {
112
+ url.protocol = "ws:";
113
+ return url.toString();
114
+ }
115
+ throw new Error(`Unsupported WebSocket URL protocol ${url.protocol}`);
116
+ },
117
+ catch: (error) => transportError("prepare", error instanceof Error ? error.message : "Invalid WebSocket URL", {
118
+ url: value,
119
+ operation: "request",
120
+ code: "invalid-url",
121
+ phase: "prepare",
122
+ delivery: "not-sent",
123
+ }),
124
+ });
125
+ export const open = (input) => Effect.gen(function* () {
126
+ const constructor = yield* Socket.WebSocketConstructor;
127
+ const ws = yield* Effect.try({
128
+ try: () =>
129
+ // Platform implementations may extend Effect's browser-compatible constructor with handshake options.
130
+ // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
131
+ constructor(input.url, {
132
+ headers: input.headers,
133
+ }),
134
+ catch: (error) => transportError("open", error instanceof Error ? error.message : "Failed to construct WebSocket", {
135
+ url: input.url,
136
+ operation: "request",
137
+ phase: "connect",
138
+ delivery: "not-sent",
139
+ }),
140
+ });
141
+ return yield* fromWebSocket(ws, input);
142
+ });
143
+ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
144
+ yield* waitOpen(ws, input);
145
+ const messages = yield* Queue.bounded(128);
146
+ const oversized = (message) => typeof message === "string" ? new Blob([message]).size > MAX_FRAME_BYTES : message.byteLength > MAX_FRAME_BYTES;
147
+ const rejectOversized = (message) => {
148
+ if (!oversized(message))
149
+ return false;
150
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("message", "WebSocket message exceeds the 16 MiB limit", {
151
+ url: input.url,
152
+ operation: "read",
153
+ code: "message-too-large",
154
+ phase: "receive",
155
+ })));
156
+ if (ws.readyState === globalThis.WebSocket.OPEN)
157
+ ws.close(1009, "Message too large");
158
+ return true;
159
+ };
160
+ const offer = (message) => {
161
+ if (rejectOversized(message))
162
+ return;
163
+ if (Queue.offerUnsafe(messages, message))
164
+ return;
165
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("message", "WebSocket inbound queue overflow", {
166
+ url: input.url,
167
+ operation: "read",
168
+ code: "queue-overflow",
169
+ phase: "receive",
170
+ })));
171
+ };
172
+ const onMessage = (event) => {
173
+ if (typeof event.data === "string")
174
+ return offer(event.data);
175
+ const binary = binaryMessage(event.data);
176
+ if (binary)
177
+ return offer(binary);
178
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("message", "Unsupported WebSocket message payload", {
179
+ url: input.url,
180
+ operation: "read",
181
+ code: "message",
182
+ phase: "receive",
183
+ })));
184
+ };
185
+ const onError = (event) => {
186
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("message", `WebSocket error: ${eventMessage(event)}`, {
187
+ url: input.url,
188
+ operation: "read",
189
+ code: "message",
190
+ phase: "receive",
191
+ })));
192
+ };
193
+ const onClose = (event) => {
194
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("message", `WebSocket closed with code ${event.code}`, {
195
+ url: input.url,
196
+ operation: "read",
197
+ code: String(event.code),
198
+ phase: "close",
199
+ })));
200
+ };
201
+ const cleanup = Effect.sync(() => {
202
+ ws.removeEventListener("message", onMessage);
203
+ ws.removeEventListener("error", onError);
204
+ ws.removeEventListener("close", onClose);
205
+ }).pipe(Effect.andThen(Queue.shutdown(messages)));
206
+ ws.addEventListener("message", onMessage);
207
+ ws.addEventListener("error", onError);
208
+ ws.addEventListener("close", onClose);
209
+ return {
210
+ sendText: (message) => Effect.suspend(() => {
211
+ if (ws.readyState !== globalThis.WebSocket.OPEN)
212
+ return Effect.fail(transportError("sendText", `WebSocket is not open (state ${ws.readyState})`, {
213
+ url: input.url,
214
+ operation: "write",
215
+ phase: "send",
216
+ delivery: "not-sent",
217
+ }));
218
+ return Effect.try({
219
+ try: () => ws.send(message),
220
+ catch: (error) => transportError("sendText", error instanceof Error ? error.message : "Failed to send WebSocket message", {
221
+ url: input.url,
222
+ operation: "write",
223
+ phase: "send",
224
+ delivery: "not-sent",
225
+ }),
226
+ });
227
+ }),
228
+ messages: Stream.fromQueue(messages),
229
+ close: cleanup.pipe(Effect.andThen(Effect.sync(() => {
230
+ if (ws.readyState === globalThis.WebSocket.CLOSED || ws.readyState === globalThis.WebSocket.CLOSING)
231
+ return;
232
+ ws.close(1000);
233
+ }))),
234
+ };
235
+ });
236
+ export const messageText = (message, decoder) => typeof message === "string" ? message : decoder.decode(message);
237
+ const observationFrame = (observation) => {
238
+ if (observation.type === "frame" || observation.type === "completed" || observation.type === "incomplete")
239
+ return Effect.succeed(observation.frame);
240
+ return Effect.fail(observation.error);
241
+ };
242
+ const observationTerminal = (observation) => observation.type !== "frame";
243
+ export const makeDirect = (connector) => ({
244
+ execute: (exchange) => Effect.gen(function* () {
245
+ const connection = yield* Effect.acquireRelease(connector
246
+ .open(exchange.connect)
247
+ .pipe(Effect.mapError((error) => annotateTransportError(error, { phase: "connect", delivery: "not-sent" }))), (connection) => connection.close);
248
+ const create = yield* exchange.driver.create(undefined);
249
+ yield* connection.sendText(create.message);
250
+ const decoder = new TextDecoder();
251
+ let observed = false;
252
+ return {
253
+ frames: connection.messages.pipe(Stream.map((message) => {
254
+ observed = true;
255
+ return messageText(message, decoder);
256
+ }), Stream.mapError((error) => annotateTransportError(error, {
257
+ phase: error.reason._tag === "Transport" && error.reason.phase === "close" ? "close" : "receive",
258
+ delivery: observed ? "accepted" : "ambiguous",
259
+ })), Stream.mapEffect((frame) => exchange.driver.observe(create, frame)), Stream.takeUntil(observationTerminal), Stream.mapEffect(observationFrame)),
260
+ complete: Effect.void,
261
+ };
262
+ }),
263
+ });
264
+ export const direct = Effect.gen(function* () {
265
+ const constructor = yield* Socket.WebSocketConstructor;
266
+ return makeDirect({
267
+ open: (input) => open(input).pipe(Effect.provideService(Socket.WebSocketConstructor, constructor)),
268
+ });
269
+ });
270
+ export const json = (input) => ({
271
+ id: "websocket-json",
272
+ with: (patch) => json({ ...input, ...patch }),
273
+ prepare: (prepareInput) => Effect.gen(function* () {
274
+ const parts = yield* HttpTransport.jsonRequestParts({
275
+ ...prepareInput,
276
+ });
277
+ return {
278
+ url: yield* toWebSocketUrl(parts.url),
279
+ headers: parts.headers,
280
+ message: input.encodeMessage(yield* input.toMessage(parts.jsonBody)),
281
+ };
282
+ }),
283
+ execute: (prepared, request, _runtime, options) => {
284
+ const webSocket = options?.webSocket;
285
+ if (!webSocket) {
286
+ return Effect.fail(transportError("json", "WebSocket JSON transport requires StreamOptions.webSocket", {
287
+ url: prepared.url,
288
+ operation: "request",
289
+ code: "unavailable",
290
+ phase: "prepare",
291
+ delivery: "not-sent",
292
+ }));
293
+ }
294
+ const driver = {
295
+ create: () => Effect.succeed({ message: prepared.message, mode: "full" }),
296
+ observe: (_create, frame) => Effect.succeed({ type: "frame", frame }),
297
+ };
298
+ const exchange = {
299
+ id: request.id ?? "request",
300
+ connect: { url: prepared.url, headers: prepared.headers },
301
+ fallback: () => Stream.fail(transportError("fallback", "WebSocket JSON transport does not provide HTTP fallback", {
302
+ url: prepared.url,
303
+ operation: "request",
304
+ code: "websocket",
305
+ phase: "fallback",
306
+ delivery: "not-sent",
307
+ })),
308
+ driver,
309
+ };
310
+ return webSocket.execute(exchange);
311
+ },
312
+ });
313
+ export const jsonTransport = {
314
+ id: "websocket-json",
315
+ with: json,
316
+ };
317
+ export const WebSocketTransport = {
318
+ json,
319
+ jsonTransport,
320
+ direct,
321
+ makeDirect,
322
+ open,
323
+ fromWebSocket,
324
+ messageText,
325
+ toWebSocketUrl,
326
+ };
@@ -0,0 +1 @@
1
+ export * from "./route/index.js";
package/dist/route.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./route/index.js";
@@ -0,0 +1,159 @@
1
+ import { Schema } from "effect";
2
+ import { Tool } from "@opencode-ai/schema/tool";
3
+ export declare const ProviderFailureClassification: Schema.Literals<readonly ["context-overflow", "payload-too-large"]>;
4
+ export type ProviderFailureClassification = typeof ProviderFailureClassification.Type;
5
+ declare const HttpRequestDetails_base: Schema.Class<HttpRequestDetails, Schema.Struct<{
6
+ readonly method: Schema.String;
7
+ readonly url: Schema.String;
8
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
9
+ }>, {}>;
10
+ export declare class HttpRequestDetails extends HttpRequestDetails_base {
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 {
17
+ }
18
+ declare const HttpRateLimitDetails_base: Schema.Class<HttpRateLimitDetails, Schema.Struct<{
19
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
20
+ readonly limit: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
21
+ readonly remaining: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
22
+ readonly reset: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
23
+ }>, {}>;
24
+ export declare class HttpRateLimitDetails extends HttpRateLimitDetails_base {
25
+ }
26
+ declare const HttpContext_base: Schema.Class<HttpContext, Schema.Struct<{
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 requestId: Schema.optional<Schema.String>;
32
+ readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
33
+ }>, {}>;
34
+ export declare class HttpContext extends HttpContext_base {
35
+ }
36
+ declare const InvalidRequestReason_base: Schema.Class<InvalidRequestReason, Schema.Struct<{
37
+ readonly _tag: Schema.tag<"InvalidRequest">;
38
+ readonly message: Schema.String;
39
+ readonly parameter: Schema.optional<Schema.String>;
40
+ readonly classification: Schema.optional<Schema.Literals<readonly ["context-overflow", "payload-too-large"]>>;
41
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
42
+ readonly http: Schema.optional<typeof HttpContext>;
43
+ }>, {}>;
44
+ export declare class InvalidRequestReason extends InvalidRequestReason_base {
45
+ }
46
+ declare const NoRouteReason_base: Schema.Class<NoRouteReason, Schema.Struct<{
47
+ readonly _tag: Schema.tag<"NoRoute">;
48
+ readonly route: Schema.String;
49
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
50
+ readonly model: Schema.brand<Schema.String, "AI.ModelID">;
51
+ }>, {}>;
52
+ export declare class NoRouteReason extends NoRouteReason_base {
53
+ get message(): string;
54
+ }
55
+ declare const AuthenticationReason_base: Schema.Class<AuthenticationReason, Schema.Struct<{
56
+ readonly _tag: Schema.tag<"Authentication">;
57
+ readonly message: Schema.String;
58
+ readonly kind: Schema.Literals<readonly ["missing", "invalid", "expired", "insufficient-permissions", "unknown"]>;
59
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
60
+ readonly http: Schema.optional<typeof HttpContext>;
61
+ }>, {}>;
62
+ export declare class AuthenticationReason extends AuthenticationReason_base {
63
+ }
64
+ declare const RateLimitReason_base: Schema.Class<RateLimitReason, Schema.Struct<{
65
+ readonly _tag: Schema.tag<"RateLimit">;
66
+ readonly message: Schema.String;
67
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
68
+ readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
69
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
70
+ readonly http: Schema.optional<typeof HttpContext>;
71
+ }>, {}>;
72
+ export declare class RateLimitReason extends RateLimitReason_base {
73
+ }
74
+ declare const QuotaExceededReason_base: Schema.Class<QuotaExceededReason, Schema.Struct<{
75
+ readonly _tag: Schema.tag<"QuotaExceeded">;
76
+ readonly message: Schema.String;
77
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
78
+ readonly http: Schema.optional<typeof HttpContext>;
79
+ }>, {}>;
80
+ export declare class QuotaExceededReason extends QuotaExceededReason_base {
81
+ }
82
+ declare const ContentPolicyReason_base: Schema.Class<ContentPolicyReason, Schema.Struct<{
83
+ readonly _tag: Schema.tag<"ContentPolicy">;
84
+ readonly message: Schema.String;
85
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
86
+ readonly http: Schema.optional<typeof HttpContext>;
87
+ }>, {}>;
88
+ export declare class ContentPolicyReason extends ContentPolicyReason_base {
89
+ }
90
+ declare const ProviderInternalReason_base: Schema.Class<ProviderInternalReason, Schema.Struct<{
91
+ readonly _tag: Schema.tag<"ProviderInternal">;
92
+ readonly message: Schema.String;
93
+ readonly status: Schema.optional<Schema.Number>;
94
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
95
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
96
+ readonly http: Schema.optional<typeof HttpContext>;
97
+ }>, {}>;
98
+ export declare class ProviderInternalReason extends ProviderInternalReason_base {
99
+ }
100
+ export declare const TransportType: Schema.Literals<readonly ["http", "websocket"]>;
101
+ export type TransportType = typeof TransportType.Type;
102
+ export declare const TransportOperation: Schema.Literals<readonly ["request", "read", "write"]>;
103
+ export type TransportOperation = typeof TransportOperation.Type;
104
+ declare const TransportReason_base: Schema.Class<TransportReason, Schema.Struct<{
105
+ readonly _tag: Schema.tag<"Transport">;
106
+ readonly message: Schema.String;
107
+ readonly transport: Schema.Literals<readonly ["http", "websocket"]>;
108
+ readonly operation: Schema.Literals<readonly ["request", "read", "write"]>;
109
+ readonly code: Schema.optional<Schema.String>;
110
+ readonly url: Schema.optional<Schema.String>;
111
+ readonly http: Schema.optional<typeof HttpContext>;
112
+ readonly phase: Schema.optional<Schema.Literals<readonly ["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"]>>;
113
+ readonly delivery: Schema.optional<Schema.Literals<readonly ["not-sent", "rejected", "ambiguous", "accepted"]>>;
114
+ readonly recovery: Schema.optional<Schema.Literals<readonly ["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"]>>;
115
+ }>, {}>;
116
+ export declare class TransportReason extends TransportReason_base {
117
+ }
118
+ declare const InvalidProviderOutputReason_base: Schema.Class<InvalidProviderOutputReason, Schema.Struct<{
119
+ readonly _tag: Schema.tag<"InvalidProviderOutput">;
120
+ readonly message: Schema.String;
121
+ readonly classification: Schema.optional<Schema.Literals<readonly ["incomplete-stream"]>>;
122
+ readonly route: Schema.optional<Schema.String>;
123
+ readonly raw: Schema.optional<Schema.String>;
124
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
125
+ }>, {}>;
126
+ export declare class InvalidProviderOutputReason extends InvalidProviderOutputReason_base {
127
+ }
128
+ declare const UnknownProviderReason_base: Schema.Class<UnknownProviderReason, Schema.Struct<{
129
+ readonly _tag: Schema.tag<"UnknownProvider">;
130
+ readonly message: Schema.String;
131
+ readonly status: Schema.optional<Schema.Number>;
132
+ readonly providerMetadata: Schema.optional<Schema.$Record<Schema.String, Schema.$Record<Schema.String, Schema.Unknown>>>;
133
+ readonly http: Schema.optional<typeof HttpContext>;
134
+ }>, {}>;
135
+ export declare class UnknownProviderReason extends UnknownProviderReason_base {
136
+ }
137
+ export declare const AIErrorReason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestReason, typeof NoRouteReason, typeof AuthenticationReason, typeof RateLimitReason, typeof QuotaExceededReason, typeof ContentPolicyReason, typeof ProviderInternalReason, typeof TransportReason, typeof InvalidProviderOutputReason, typeof UnknownProviderReason]>;
138
+ export type AIErrorReason = Schema.Schema.Type<typeof AIErrorReason>;
139
+ declare const AIError_base: Schema.Class<AIError, Schema.TaggedStruct<"AI.Error", {
140
+ readonly module: Schema.String;
141
+ readonly method: Schema.String;
142
+ 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]>;
143
+ }>, import("effect/Cause").YieldableError>;
144
+ export declare class AIError extends AIError_base {
145
+ readonly cause: InvalidRequestReason | NoRouteReason | AuthenticationReason | RateLimitReason | QuotaExceededReason | ContentPolicyReason | ProviderInternalReason | TransportReason | InvalidProviderOutputReason | UnknownProviderReason;
146
+ get message(): string;
147
+ }
148
+ /**
149
+ * Failure type for tool execute handlers. Handlers must map their internal
150
+ * errors to this shape; the runtime catches `ToolFailure`s and surfaces them
151
+ * as `tool-error` events plus a `tool-result` of `type: "error"` so the model
152
+ * can self-correct.
153
+ *
154
+ * Anything thrown or yielded by a handler that is not a `ToolFailure` is
155
+ * treated as a defect and fails the stream.
156
+ */
157
+ export declare class ToolFailure extends Tool.Error {
158
+ }
159
+ export {};
@@ -0,0 +1,155 @@
1
+ import { Schema } from "effect";
2
+ import { Tool } from "@opencode-ai/schema/tool";
3
+ import { ModelID, ProviderID, ProviderMetadata, RouteID } from "./ids.js";
4
+ export const ProviderFailureClassification = Schema.Literals(["context-overflow", "payload-too-large"]);
5
+ export class HttpRequestDetails extends Schema.Class("AI.HttpRequestDetails")({
6
+ method: Schema.String,
7
+ url: Schema.String,
8
+ headers: Schema.Record(Schema.String, Schema.String),
9
+ }) {
10
+ }
11
+ export class HttpResponseDetails extends Schema.Class("AI.HttpResponseDetails")({
12
+ status: Schema.Number,
13
+ headers: Schema.Record(Schema.String, Schema.String),
14
+ }) {
15
+ }
16
+ export class HttpRateLimitDetails extends Schema.Class("AI.HttpRateLimitDetails")({
17
+ retryAfterMs: Schema.optional(Schema.Number),
18
+ limit: Schema.optional(Schema.Record(Schema.String, Schema.String)),
19
+ remaining: Schema.optional(Schema.Record(Schema.String, Schema.String)),
20
+ reset: Schema.optional(Schema.Record(Schema.String, Schema.String)),
21
+ }) {
22
+ }
23
+ export class HttpContext extends Schema.Class("AI.HttpContext")({
24
+ request: HttpRequestDetails,
25
+ response: Schema.optional(HttpResponseDetails),
26
+ body: Schema.optional(Schema.String),
27
+ bodyTruncated: Schema.optional(Schema.Boolean),
28
+ requestId: Schema.optional(Schema.String),
29
+ rateLimit: Schema.optional(HttpRateLimitDetails),
30
+ }) {
31
+ }
32
+ export class InvalidRequestReason extends Schema.Class("AI.Error.InvalidRequest")({
33
+ _tag: Schema.tag("InvalidRequest"),
34
+ message: Schema.String,
35
+ parameter: Schema.optional(Schema.String),
36
+ classification: Schema.optional(ProviderFailureClassification),
37
+ providerMetadata: Schema.optional(ProviderMetadata),
38
+ http: Schema.optional(HttpContext),
39
+ }) {
40
+ }
41
+ export class NoRouteReason extends Schema.Class("AI.Error.NoRoute")({
42
+ _tag: Schema.tag("NoRoute"),
43
+ route: RouteID,
44
+ provider: ProviderID,
45
+ model: ModelID,
46
+ }) {
47
+ get message() {
48
+ return `No AI route for ${this.provider}/${this.model} using ${this.route}`;
49
+ }
50
+ }
51
+ export class AuthenticationReason extends Schema.Class("AI.Error.Authentication")({
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
+ }) {
58
+ }
59
+ export class RateLimitReason extends Schema.Class("AI.Error.RateLimit")({
60
+ _tag: Schema.tag("RateLimit"),
61
+ message: Schema.String,
62
+ retryAfterMs: Schema.optional(Schema.Number),
63
+ rateLimit: Schema.optional(HttpRateLimitDetails),
64
+ providerMetadata: Schema.optional(ProviderMetadata),
65
+ http: Schema.optional(HttpContext),
66
+ }) {
67
+ }
68
+ export class QuotaExceededReason extends Schema.Class("AI.Error.QuotaExceeded")({
69
+ _tag: Schema.tag("QuotaExceeded"),
70
+ message: Schema.String,
71
+ providerMetadata: Schema.optional(ProviderMetadata),
72
+ http: Schema.optional(HttpContext),
73
+ }) {
74
+ }
75
+ export class ContentPolicyReason extends Schema.Class("AI.Error.ContentPolicy")({
76
+ _tag: Schema.tag("ContentPolicy"),
77
+ message: Schema.String,
78
+ providerMetadata: Schema.optional(ProviderMetadata),
79
+ http: Schema.optional(HttpContext),
80
+ }) {
81
+ }
82
+ export class ProviderInternalReason extends Schema.Class("AI.Error.ProviderInternal")({
83
+ _tag: Schema.tag("ProviderInternal"),
84
+ message: Schema.String,
85
+ status: Schema.optional(Schema.Number),
86
+ retryAfterMs: Schema.optional(Schema.Number),
87
+ providerMetadata: Schema.optional(ProviderMetadata),
88
+ http: Schema.optional(HttpContext),
89
+ }) {
90
+ }
91
+ export const TransportType = Schema.Literals(["http", "websocket"]);
92
+ export const TransportOperation = Schema.Literals(["request", "read", "write"]);
93
+ export class TransportReason extends Schema.Class("AI.Error.Transport")({
94
+ _tag: Schema.tag("Transport"),
95
+ message: Schema.String,
96
+ transport: TransportType,
97
+ operation: TransportOperation,
98
+ code: Schema.optional(Schema.String),
99
+ url: Schema.optional(Schema.String),
100
+ http: Schema.optional(HttpContext),
101
+ phase: Schema.optional(Schema.Literals(["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"])),
102
+ delivery: Schema.optional(Schema.Literals(["not-sent", "rejected", "ambiguous", "accepted"])),
103
+ recovery: Schema.optional(Schema.Literals(["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"])),
104
+ }) {
105
+ }
106
+ export class InvalidProviderOutputReason extends Schema.Class("AI.Error.InvalidProviderOutput")({
107
+ _tag: Schema.tag("InvalidProviderOutput"),
108
+ message: Schema.String,
109
+ classification: Schema.optional(Schema.Literals(["incomplete-stream"])),
110
+ route: Schema.optional(Schema.String),
111
+ raw: Schema.optional(Schema.String),
112
+ providerMetadata: Schema.optional(ProviderMetadata),
113
+ }) {
114
+ }
115
+ export class UnknownProviderReason extends Schema.Class("AI.Error.UnknownProvider")({
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
+ }) {
122
+ }
123
+ export const AIErrorReason = Schema.Union([
124
+ InvalidRequestReason,
125
+ NoRouteReason,
126
+ AuthenticationReason,
127
+ RateLimitReason,
128
+ QuotaExceededReason,
129
+ ContentPolicyReason,
130
+ ProviderInternalReason,
131
+ TransportReason,
132
+ InvalidProviderOutputReason,
133
+ UnknownProviderReason,
134
+ ]).pipe(Schema.toTaggedUnion("_tag"));
135
+ export class AIError extends Schema.TaggedErrorClass()("AI.Error", {
136
+ module: Schema.String,
137
+ method: Schema.String,
138
+ reason: AIErrorReason,
139
+ }) {
140
+ cause = this.reason;
141
+ get message() {
142
+ return `${this.module}.${this.method}: ${this.reason.message}`;
143
+ }
144
+ }
145
+ /**
146
+ * Failure type for tool execute handlers. Handlers must map their internal
147
+ * errors to this shape; the runtime catches `ToolFailure`s and surfaces them
148
+ * as `tool-error` events plus a `tool-result` of `type: "error"` so the model
149
+ * can self-correct.
150
+ *
151
+ * Anything thrown or yielded by a handler that is not a `ToolFailure` is
152
+ * treated as a defect and fails the stream.
153
+ */
154
+ export class ToolFailure extends Tool.Error {
155
+ }