@opencode/ai 0.0.0-reserved → 2.0.0

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 (288) hide show
  1. package/README.md +879 -2
  2. package/dist/cache-policy.d.ts +2 -0
  3. package/dist/cache-policy.js +129 -0
  4. package/dist/image-client.d.ts +19 -0
  5. package/dist/image-client.js +28 -0
  6. package/dist/image.d.ts +110 -0
  7. package/dist/image.js +103 -0
  8. package/dist/index.d.ts +18 -0
  9. package/dist/index.js +12 -0
  10. package/dist/llm.d.ts +252 -0
  11. package/dist/llm.js +74 -0
  12. package/dist/protocols/alibaba-chat.d.ts +225 -0
  13. package/dist/protocols/alibaba-chat.js +75 -0
  14. package/dist/protocols/alibaba-messages.d.ts +350 -0
  15. package/dist/protocols/alibaba-messages.js +40 -0
  16. package/dist/protocols/alibaba-responses.d.ts +255 -0
  17. package/dist/protocols/alibaba-responses.js +80 -0
  18. package/dist/protocols/anthropic-messages.d.ts +980 -0
  19. package/dist/protocols/anthropic-messages.js +1460 -0
  20. package/dist/protocols/bedrock-converse.d.ts +499 -0
  21. package/dist/protocols/bedrock-converse.js +643 -0
  22. package/dist/protocols/bedrock-event-stream.d.ts +9 -0
  23. package/dist/protocols/bedrock-event-stream.js +97 -0
  24. package/dist/protocols/gemini.d.ts +285 -0
  25. package/dist/protocols/gemini.js +671 -0
  26. package/dist/protocols/google-images.d.ts +30 -0
  27. package/dist/protocols/google-images.js +181 -0
  28. package/dist/protocols/index.d.ts +12 -0
  29. package/dist/protocols/index.js +12 -0
  30. package/dist/protocols/meta-images.d.ts +26 -0
  31. package/dist/protocols/meta-images.js +89 -0
  32. package/dist/protocols/meta-messages.d.ts +356 -0
  33. package/dist/protocols/meta-messages.js +41 -0
  34. package/dist/protocols/meta-responses.d.ts +473 -0
  35. package/dist/protocols/meta-responses.js +173 -0
  36. package/dist/protocols/mistral-chat.d.ts +540 -0
  37. package/dist/protocols/mistral-chat.js +624 -0
  38. package/dist/protocols/open-responses-channel.d.ts +25 -0
  39. package/dist/protocols/open-responses-channel.js +141 -0
  40. package/dist/protocols/open-responses-continuation.d.ts +16 -0
  41. package/dist/protocols/open-responses-continuation.js +170 -0
  42. package/dist/protocols/open-responses.d.ts +1715 -0
  43. package/dist/protocols/open-responses.js +1228 -0
  44. package/dist/protocols/openai-chat.d.ts +860 -0
  45. package/dist/protocols/openai-chat.js +966 -0
  46. package/dist/protocols/openai-compatible-chat.d.ts +109 -0
  47. package/dist/protocols/openai-compatible-chat.js +19 -0
  48. package/dist/protocols/openai-compatible-responses.d.ts +172 -0
  49. package/dist/protocols/openai-compatible-responses.js +18 -0
  50. package/dist/protocols/openai-images.d.ts +32 -0
  51. package/dist/protocols/openai-images.js +183 -0
  52. package/dist/protocols/openai-responses.d.ts +1389 -0
  53. package/dist/protocols/openai-responses.js +260 -0
  54. package/dist/protocols/shared.d.ts +193 -0
  55. package/dist/protocols/shared.js +290 -0
  56. package/dist/protocols/utils/bedrock-auth.d.ts +60 -0
  57. package/dist/protocols/utils/bedrock-auth.js +85 -0
  58. package/dist/protocols/utils/bedrock-cache.d.ts +19 -0
  59. package/dist/protocols/utils/bedrock-cache.js +49 -0
  60. package/dist/protocols/utils/bedrock-media.d.ts +55 -0
  61. package/dist/protocols/utils/bedrock-media.js +73 -0
  62. package/dist/protocols/utils/cache.d.ts +6 -0
  63. package/dist/protocols/utils/cache.js +5 -0
  64. package/dist/protocols/utils/gemini-tool-schema.d.ts +2 -0
  65. package/dist/protocols/utils/gemini-tool-schema.js +103 -0
  66. package/dist/protocols/utils/image-input.d.ts +21 -0
  67. package/dist/protocols/utils/image-input.js +20 -0
  68. package/dist/protocols/utils/lifecycle.d.ts +24 -0
  69. package/dist/protocols/utils/lifecycle.js +72 -0
  70. package/dist/protocols/utils/meta-image.d.ts +2 -0
  71. package/dist/protocols/utils/meta-image.js +13 -0
  72. package/dist/protocols/utils/open-responses-options.d.ts +56 -0
  73. package/dist/protocols/utils/open-responses-options.js +61 -0
  74. package/dist/protocols/utils/openai-image.d.ts +5 -0
  75. package/dist/protocols/utils/openai-image.js +18 -0
  76. package/dist/protocols/utils/openai-options.d.ts +16 -0
  77. package/dist/protocols/utils/openai-options.js +14 -0
  78. package/dist/protocols/utils/partial-json-options.d.ts +62 -0
  79. package/dist/protocols/utils/partial-json-options.js +52 -0
  80. package/dist/protocols/utils/partial-json.d.ts +8 -0
  81. package/dist/protocols/utils/partial-json.js +279 -0
  82. package/dist/protocols/utils/responses-checkpoint.d.ts +4 -0
  83. package/dist/protocols/utils/responses-checkpoint.js +107 -0
  84. package/dist/protocols/utils/responses-compaction.d.ts +4 -0
  85. package/dist/protocols/utils/responses-compaction.js +129 -0
  86. package/dist/protocols/utils/responses-hosted-tools.d.ts +26 -0
  87. package/dist/protocols/utils/responses-hosted-tools.js +32 -0
  88. package/dist/protocols/utils/tool-schema.d.ts +8 -0
  89. package/dist/protocols/utils/tool-schema.js +54 -0
  90. package/dist/protocols/utils/tool-stream.d.ts +710 -0
  91. package/dist/protocols/utils/tool-stream.js +155 -0
  92. package/dist/protocols/xai-images.d.ts +26 -0
  93. package/dist/protocols/xai-images.js +106 -0
  94. package/dist/protocols/xai-responses.d.ts +250 -0
  95. package/dist/protocols/xai-responses.js +81 -0
  96. package/dist/protocols/zai-chat.d.ts +202 -0
  97. package/dist/protocols/zai-chat.js +49 -0
  98. package/dist/protocols/zai-images.d.ts +22 -0
  99. package/dist/protocols/zai-images.js +79 -0
  100. package/dist/protocols/zai-messages.d.ts +344 -0
  101. package/dist/protocols/zai-messages.js +27 -0
  102. package/dist/protocols.d.ts +1 -0
  103. package/dist/protocols.js +1 -0
  104. package/dist/provider-error.d.ts +15 -0
  105. package/dist/provider-error.js +125 -0
  106. package/dist/provider-package.d.ts +15 -0
  107. package/dist/provider-package.js +1 -0
  108. package/dist/provider.d.ts +23 -0
  109. package/dist/provider.js +2 -0
  110. package/dist/providers/alibaba/chat.d.ts +1 -0
  111. package/dist/providers/alibaba/chat.js +1 -0
  112. package/dist/providers/alibaba/messages.d.ts +3 -0
  113. package/dist/providers/alibaba/messages.js +1 -0
  114. package/dist/providers/alibaba/responses.d.ts +3 -0
  115. package/dist/providers/alibaba/responses.js +1 -0
  116. package/dist/providers/alibaba.d.ts +711 -0
  117. package/dist/providers/alibaba.js +94 -0
  118. package/dist/providers/amazon-bedrock/mantle/chat.d.ts +2 -0
  119. package/dist/providers/amazon-bedrock/mantle/chat.js +1 -0
  120. package/dist/providers/amazon-bedrock/mantle/responses.d.ts +2 -0
  121. package/dist/providers/amazon-bedrock/mantle/responses.js +1 -0
  122. package/dist/providers/amazon-bedrock/mantle.d.ts +2 -0
  123. package/dist/providers/amazon-bedrock/mantle.js +1 -0
  124. package/dist/providers/amazon-bedrock-mantle.d.ts +313 -0
  125. package/dist/providers/amazon-bedrock-mantle.js +79 -0
  126. package/dist/providers/amazon-bedrock.d.ts +173 -0
  127. package/dist/providers/amazon-bedrock.js +41 -0
  128. package/dist/providers/anthropic-compatible.d.ts +309 -0
  129. package/dist/providers/anthropic-compatible.js +50 -0
  130. package/dist/providers/anthropic.d.ts +307 -0
  131. package/dist/providers/anthropic.js +42 -0
  132. package/dist/providers/azure/chat.d.ts +2 -0
  133. package/dist/providers/azure/chat.js +1 -0
  134. package/dist/providers/azure/responses.d.ts +2 -0
  135. package/dist/providers/azure/responses.js +1 -0
  136. package/dist/providers/azure.d.ts +598 -0
  137. package/dist/providers/azure.js +115 -0
  138. package/dist/providers/baseten.d.ts +228 -0
  139. package/dist/providers/baseten.js +38 -0
  140. package/dist/providers/cerebras.d.ts +227 -0
  141. package/dist/providers/cerebras.js +40 -0
  142. package/dist/providers/cloudflare-ai-gateway.d.ts +237 -0
  143. package/dist/providers/cloudflare-ai-gateway.js +65 -0
  144. package/dist/providers/cloudflare-workers-ai.d.ts +231 -0
  145. package/dist/providers/cloudflare-workers-ai.js +51 -0
  146. package/dist/providers/deepinfra.d.ts +227 -0
  147. package/dist/providers/deepinfra.js +43 -0
  148. package/dist/providers/deepseek.d.ts +228 -0
  149. package/dist/providers/deepseek.js +41 -0
  150. package/dist/providers/fireworks.d.ts +228 -0
  151. package/dist/providers/fireworks.js +38 -0
  152. package/dist/providers/google-vertex/chat.d.ts +2 -0
  153. package/dist/providers/google-vertex/chat.js +1 -0
  154. package/dist/providers/google-vertex/gemini.d.ts +2 -0
  155. package/dist/providers/google-vertex/gemini.js +1 -0
  156. package/dist/providers/google-vertex/messages.d.ts +2 -0
  157. package/dist/providers/google-vertex/messages.js +1 -0
  158. package/dist/providers/google-vertex/responses.d.ts +2 -0
  159. package/dist/providers/google-vertex/responses.js +1 -0
  160. package/dist/providers/google-vertex-chat.d.ts +132 -0
  161. package/dist/providers/google-vertex-chat.js +55 -0
  162. package/dist/providers/google-vertex-messages.d.ts +306 -0
  163. package/dist/providers/google-vertex-messages.js +75 -0
  164. package/dist/providers/google-vertex-responses.d.ts +197 -0
  165. package/dist/providers/google-vertex-responses.js +56 -0
  166. package/dist/providers/google-vertex-shared.d.ts +22 -0
  167. package/dist/providers/google-vertex-shared.js +72 -0
  168. package/dist/providers/google-vertex.d.ts +119 -0
  169. package/dist/providers/google-vertex.js +98 -0
  170. package/dist/providers/google.d.ts +114 -0
  171. package/dist/providers/google.js +42 -0
  172. package/dist/providers/groq.d.ts +314 -0
  173. package/dist/providers/groq.js +81 -0
  174. package/dist/providers/index.d.ts +31 -0
  175. package/dist/providers/index.js +31 -0
  176. package/dist/providers/meta/chat.d.ts +2 -0
  177. package/dist/providers/meta/chat.js +1 -0
  178. package/dist/providers/meta/messages.d.ts +2 -0
  179. package/dist/providers/meta/messages.js +1 -0
  180. package/dist/providers/meta/responses.d.ts +2 -0
  181. package/dist/providers/meta/responses.js +1 -0
  182. package/dist/providers/meta.d.ts +636 -0
  183. package/dist/providers/meta.js +113 -0
  184. package/dist/providers/minimax/chat.d.ts +4 -0
  185. package/dist/providers/minimax/chat.js +8 -0
  186. package/dist/providers/minimax/messages.d.ts +1 -0
  187. package/dist/providers/minimax/messages.js +1 -0
  188. package/dist/providers/minimax/responses.d.ts +4 -0
  189. package/dist/providers/minimax/responses.js +8 -0
  190. package/dist/providers/minimax.d.ts +598 -0
  191. package/dist/providers/minimax.js +89 -0
  192. package/dist/providers/mistral.d.ts +207 -0
  193. package/dist/providers/mistral.js +28 -0
  194. package/dist/providers/moonshot/chat.d.ts +1 -0
  195. package/dist/providers/moonshot/chat.js +1 -0
  196. package/dist/providers/moonshot/messages.d.ts +4 -0
  197. package/dist/providers/moonshot/messages.js +8 -0
  198. package/dist/providers/moonshot/responses.d.ts +4 -0
  199. package/dist/providers/moonshot/responses.js +8 -0
  200. package/dist/providers/moonshot.d.ts +596 -0
  201. package/dist/providers/moonshot.js +90 -0
  202. package/dist/providers/open-responses-options.d.ts +6 -0
  203. package/dist/providers/open-responses-options.js +1 -0
  204. package/dist/providers/openai/chat.d.ts +2 -0
  205. package/dist/providers/openai/chat.js +1 -0
  206. package/dist/providers/openai/responses.d.ts +2 -0
  207. package/dist/providers/openai/responses.js +1 -0
  208. package/dist/providers/openai-compatible/responses.d.ts +1 -0
  209. package/dist/providers/openai-compatible/responses.js +1 -0
  210. package/dist/providers/openai-compatible-responses.d.ts +195 -0
  211. package/dist/providers/openai-compatible-responses.js +32 -0
  212. package/dist/providers/openai-compatible.d.ts +130 -0
  213. package/dist/providers/openai-compatible.js +33 -0
  214. package/dist/providers/openai-options.d.ts +26 -0
  215. package/dist/providers/openai-options.js +41 -0
  216. package/dist/providers/openai.d.ts +404 -0
  217. package/dist/providers/openai.js +82 -0
  218. package/dist/providers/openrouter.d.ts +563 -0
  219. package/dist/providers/openrouter.js +114 -0
  220. package/dist/providers/togetherai.d.ts +227 -0
  221. package/dist/providers/togetherai.js +40 -0
  222. package/dist/providers/xai.d.ts +163 -0
  223. package/dist/providers/xai.js +88 -0
  224. package/dist/providers/zai/chat.d.ts +1 -0
  225. package/dist/providers/zai/chat.js +1 -0
  226. package/dist/providers/zai-coding-plan/chat.d.ts +1 -0
  227. package/dist/providers/zai-coding-plan/chat.js +1 -0
  228. package/dist/providers/zai-coding-plan/messages.d.ts +4 -0
  229. package/dist/providers/zai-coding-plan/messages.js +8 -0
  230. package/dist/providers/zai-coding-plan/responses.d.ts +4 -0
  231. package/dist/providers/zai-coding-plan/responses.js +8 -0
  232. package/dist/providers/zai-coding-plan.d.ts +577 -0
  233. package/dist/providers/zai-coding-plan.js +63 -0
  234. package/dist/providers/zai.d.ts +149 -0
  235. package/dist/providers/zai.js +53 -0
  236. package/dist/providers.d.ts +1 -0
  237. package/dist/providers.js +1 -0
  238. package/dist/route/auth-options.d.ts +34 -0
  239. package/dist/route/auth-options.js +14 -0
  240. package/dist/route/auth.d.ts +51 -0
  241. package/dist/route/auth.js +87 -0
  242. package/dist/route/client.d.ts +430 -0
  243. package/dist/route/client.js +307 -0
  244. package/dist/route/endpoint.d.ts +28 -0
  245. package/dist/route/endpoint.js +21 -0
  246. package/dist/route/executor.d.ts +27 -0
  247. package/dist/route/executor.js +183 -0
  248. package/dist/route/framing.d.ts +29 -0
  249. package/dist/route/framing.js +14 -0
  250. package/dist/route/index.d.ts +16 -0
  251. package/dist/route/index.js +9 -0
  252. package/dist/route/protocol.d.ts +76 -0
  253. package/dist/route/protocol.js +16 -0
  254. package/dist/route/transport/http.d.ts +34 -0
  255. package/dist/route/transport/http.js +68 -0
  256. package/dist/route/transport/index.d.ts +41 -0
  257. package/dist/route/transport/index.js +4 -0
  258. package/dist/route/transport/websocket-channel.d.ts +57 -0
  259. package/dist/route/transport/websocket-channel.js +1 -0
  260. package/dist/route/transport/websocket.d.ts +56 -0
  261. package/dist/route/transport/websocket.js +370 -0
  262. package/dist/route.d.ts +1 -0
  263. package/dist/route.js +1 -0
  264. package/dist/schema/errors.d.ts +170 -0
  265. package/dist/schema/errors.js +131 -0
  266. package/dist/schema/events.d.ts +8123 -0
  267. package/dist/schema/events.js +550 -0
  268. package/dist/schema/ids.d.ts +17 -0
  269. package/dist/schema/ids.js +10 -0
  270. package/dist/schema/index.d.ts +5 -0
  271. package/dist/schema/index.js +5 -0
  272. package/dist/schema/messages.d.ts +646 -0
  273. package/dist/schema/messages.js +301 -0
  274. package/dist/schema/options.d.ts +159 -0
  275. package/dist/schema/options.js +189 -0
  276. package/dist/testing.d.ts +1693 -0
  277. package/dist/testing.js +129 -0
  278. package/dist/tool-history.d.ts +2 -0
  279. package/dist/tool-history.js +84 -0
  280. package/dist/tool-runtime.d.ts +15 -0
  281. package/dist/tool-runtime.js +62 -0
  282. package/dist/tool.d.ts +136 -0
  283. package/dist/tool.js +66 -0
  284. package/dist/utils/record.d.ts +2 -0
  285. package/dist/utils/record.js +2 -0
  286. package/dist/utils/sanitize.d.ts +1 -0
  287. package/dist/utils/sanitize.js +12 -0
  288. package/package.json +43 -10
@@ -0,0 +1,370 @@
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, AIErrorReason, TransportError, } from "../../schema/index.js";
5
+ import * as HttpTransport from "./http.js";
6
+ const MAX_FRAME_BYTES = 16 * 1024 * 1024;
7
+ const transportError = (message, input) => new AIError({
8
+ reason: new TransportError({
9
+ message,
10
+ body: input.body,
11
+ cause: input.cause,
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
+ reason: new TransportError({
23
+ ...error.reason,
24
+ message: error.reason.message,
25
+ cause: error.reason.cause,
26
+ phase: input.phase,
27
+ delivery: input.delivery,
28
+ }),
29
+ })
30
+ : error;
31
+ const eventMessage = (event) => {
32
+ if ("message" in event && typeof event.message === "string")
33
+ return event.message;
34
+ return event.type;
35
+ };
36
+ const binaryMessage = (data) => {
37
+ if (data instanceof Uint8Array)
38
+ return data;
39
+ if (data instanceof ArrayBuffer)
40
+ return new Uint8Array(data);
41
+ if (ArrayBuffer.isView(data))
42
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
43
+ return undefined;
44
+ };
45
+ const waitOpen = (ws, input) => {
46
+ if (ws.readyState === globalThis.WebSocket.OPEN)
47
+ return Effect.void;
48
+ if (ws.readyState === globalThis.WebSocket.CLOSING || ws.readyState === globalThis.WebSocket.CLOSED) {
49
+ return Effect.fail(transportError(`WebSocket closed before opening (state ${ws.readyState})`, {
50
+ url: input.url,
51
+ operation: "request",
52
+ code: "closed",
53
+ phase: "connect",
54
+ delivery: "not-sent",
55
+ }));
56
+ }
57
+ return Effect.callback((resume, signal) => {
58
+ const cleanup = () => {
59
+ ws.removeEventListener("open", onOpen);
60
+ ws.removeEventListener("error", onError);
61
+ ws.removeEventListener("close", onClose);
62
+ signal.removeEventListener("abort", onAbort);
63
+ };
64
+ const onAbort = () => {
65
+ cleanup();
66
+ if (ws.readyState === globalThis.WebSocket.CLOSED || ws.readyState === globalThis.WebSocket.CLOSING)
67
+ return;
68
+ // Node's ws reports an aborted handshake as an error event on the next tick; with no listener left
69
+ // after cleanup, EventEmitter would throw it as an uncaught exception.
70
+ ws.addEventListener("error", () => { }, { once: true });
71
+ ws.close(1000);
72
+ };
73
+ const onOpen = () => {
74
+ cleanup();
75
+ resume(Effect.void);
76
+ };
77
+ const onError = (event) => {
78
+ cleanup();
79
+ resume(Effect.fail(transportError(`Failed to open WebSocket: ${eventMessage(event)}`, {
80
+ cause: "error" in event ? (event.error ?? event) : event,
81
+ url: input.url,
82
+ operation: "request",
83
+ phase: "connect",
84
+ delivery: "not-sent",
85
+ })));
86
+ };
87
+ const onClose = (event) => {
88
+ cleanup();
89
+ resume(Effect.fail(transportError(`WebSocket closed before opening with code ${event.code}`, {
90
+ body: event.reason,
91
+ cause: event,
92
+ url: input.url,
93
+ operation: "request",
94
+ code: String(event.code),
95
+ phase: "connect",
96
+ delivery: "not-sent",
97
+ })));
98
+ };
99
+ ws.addEventListener("open", onOpen, { once: true });
100
+ ws.addEventListener("error", onError, { once: true });
101
+ ws.addEventListener("close", onClose, { once: true });
102
+ signal.addEventListener("abort", onAbort, { once: true });
103
+ });
104
+ };
105
+ export const toWebSocketUrl = (value) => Effect.try({
106
+ try: () => {
107
+ const url = new URL(value);
108
+ if (url.protocol === "https:") {
109
+ url.protocol = "wss:";
110
+ return url.toString();
111
+ }
112
+ if (url.protocol === "http:") {
113
+ url.protocol = "ws:";
114
+ return url.toString();
115
+ }
116
+ throw new Error(`Unsupported WebSocket URL protocol ${url.protocol}`);
117
+ },
118
+ catch: (error) => transportError(error instanceof Error ? error.message : "Invalid WebSocket URL", {
119
+ cause: error,
120
+ url: value,
121
+ operation: "request",
122
+ code: "invalid-url",
123
+ phase: "prepare",
124
+ delivery: "not-sent",
125
+ }),
126
+ });
127
+ export const open = (input) => Effect.gen(function* () {
128
+ const constructor = yield* Socket.WebSocketConstructor;
129
+ const ws = yield* Effect.try({
130
+ try: () =>
131
+ // Platform implementations may extend Effect's browser-compatible constructor with handshake options.
132
+ // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion
133
+ constructor(input.url, {
134
+ headers: input.headers,
135
+ }),
136
+ catch: (error) => transportError(error instanceof Error ? error.message : "Failed to construct WebSocket", {
137
+ cause: error,
138
+ url: input.url,
139
+ operation: "request",
140
+ phase: "connect",
141
+ delivery: "not-sent",
142
+ }),
143
+ });
144
+ return yield* fromWebSocket(ws, input);
145
+ });
146
+ export const fromWebSocket = (ws, input) => Effect.gen(function* () {
147
+ yield* waitOpen(ws, input);
148
+ const messages = yield* Queue.bounded(128);
149
+ const oversized = (message) => typeof message === "string" ? new Blob([message]).size > MAX_FRAME_BYTES : message.byteLength > MAX_FRAME_BYTES;
150
+ const rejectOversized = (message) => {
151
+ if (!oversized(message))
152
+ return false;
153
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("WebSocket message exceeds the 16 MiB limit", {
154
+ body: typeof message === "string" ? message : new TextDecoder().decode(message),
155
+ url: input.url,
156
+ operation: "read",
157
+ code: "message-too-large",
158
+ phase: "receive",
159
+ })));
160
+ if (ws.readyState === globalThis.WebSocket.OPEN)
161
+ ws.close(1009, "Message too large");
162
+ return true;
163
+ };
164
+ const offer = (message) => {
165
+ if (rejectOversized(message))
166
+ return;
167
+ if (Queue.offerUnsafe(messages, message))
168
+ return;
169
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("WebSocket inbound queue overflow", {
170
+ body: typeof message === "string" ? message : new TextDecoder().decode(message),
171
+ url: input.url,
172
+ operation: "read",
173
+ code: "queue-overflow",
174
+ phase: "receive",
175
+ })));
176
+ };
177
+ const onMessage = (event) => {
178
+ if (typeof event.data === "string")
179
+ return offer(event.data);
180
+ const binary = binaryMessage(event.data);
181
+ if (binary)
182
+ return offer(binary);
183
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError("Unsupported WebSocket message payload", {
184
+ cause: event,
185
+ url: input.url,
186
+ operation: "read",
187
+ code: "message",
188
+ phase: "receive",
189
+ })));
190
+ };
191
+ const onError = (event) => {
192
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError(`WebSocket error: ${eventMessage(event)}`, {
193
+ cause: "error" in event ? (event.error ?? event) : event,
194
+ url: input.url,
195
+ operation: "read",
196
+ code: "message",
197
+ phase: "receive",
198
+ })));
199
+ };
200
+ const onClose = (event) => {
201
+ Queue.failCauseUnsafe(messages, Cause.fail(transportError(`WebSocket closed with code ${event.code}`, {
202
+ body: event.reason,
203
+ cause: event,
204
+ url: input.url,
205
+ operation: "read",
206
+ code: String(event.code),
207
+ phase: "close",
208
+ })));
209
+ };
210
+ const cleanup = Effect.sync(() => {
211
+ ws.removeEventListener("message", onMessage);
212
+ ws.removeEventListener("error", onError);
213
+ ws.removeEventListener("close", onClose);
214
+ }).pipe(Effect.andThen(Queue.shutdown(messages)));
215
+ ws.addEventListener("message", onMessage);
216
+ ws.addEventListener("error", onError);
217
+ ws.addEventListener("close", onClose);
218
+ return {
219
+ sendText: (message) => Effect.suspend(() => {
220
+ if (ws.readyState !== globalThis.WebSocket.OPEN)
221
+ return Effect.fail(transportError(`WebSocket is not open (state ${ws.readyState})`, {
222
+ url: input.url,
223
+ operation: "write",
224
+ phase: "send",
225
+ delivery: "not-sent",
226
+ }));
227
+ return Effect.try({
228
+ try: () => ws.send(message),
229
+ catch: (error) => transportError(error instanceof Error ? error.message : "Failed to send WebSocket message", {
230
+ cause: error,
231
+ url: input.url,
232
+ operation: "write",
233
+ phase: "send",
234
+ delivery: "not-sent",
235
+ }),
236
+ });
237
+ }),
238
+ messages: Stream.fromQueue(messages),
239
+ close: cleanup.pipe(Effect.andThen(Effect.sync(() => {
240
+ if (ws.readyState === globalThis.WebSocket.CLOSED || ws.readyState === globalThis.WebSocket.CLOSING)
241
+ return;
242
+ ws.close(1000);
243
+ }))),
244
+ };
245
+ });
246
+ export const messageText = (message, decoder) => typeof message === "string" ? message : decoder.decode(message);
247
+ const observationFrame = (observation) => {
248
+ if (observation.type === "frame" || observation.type === "completed" || observation.type === "incomplete")
249
+ return Effect.succeed(observation.frame);
250
+ return Effect.fail(observation.error);
251
+ };
252
+ const observationTerminal = (observation) => observation.type !== "frame";
253
+ export const makeDirect = (connector) => ({
254
+ execute: (exchange) => Effect.gen(function* () {
255
+ const connection = yield* Effect.acquireRelease(connector
256
+ .open(exchange.connect)
257
+ .pipe(Effect.mapError((error) => annotateTransportError(error, { phase: "connect", delivery: "not-sent" }))), (connection) => connection.close);
258
+ const create = yield* exchange.driver.create(undefined);
259
+ yield* connection.sendText(create.message).pipe(Effect.mapError((error) => new AIError({
260
+ reason: AIErrorReason.make({
261
+ ...error.reason,
262
+ message: error.reason.message,
263
+ cause: error.reason.cause,
264
+ http: error.reason.http ?? connection.http,
265
+ }),
266
+ })));
267
+ const decoder = new TextDecoder();
268
+ let observed = false;
269
+ return {
270
+ http: connection.http,
271
+ frames: connection.messages.pipe(Stream.map((message) => {
272
+ observed = true;
273
+ return messageText(message, decoder);
274
+ }), Stream.mapError((error) => annotateTransportError(error, {
275
+ phase: error.reason._tag === "Transport" && error.reason.phase === "close" ? "close" : "receive",
276
+ delivery: observed ? "accepted" : "ambiguous",
277
+ })), Stream.mapEffect((frame) => exchange.driver.observe(create, frame).pipe(Effect.mapError((error) => new AIError({
278
+ reason: AIErrorReason.make({
279
+ ...error.reason,
280
+ message: error.reason.message,
281
+ cause: error.reason.cause,
282
+ body: frame,
283
+ }),
284
+ })), Effect.map((observation) => "error" in observation
285
+ ? {
286
+ ...observation,
287
+ error: new AIError({
288
+ reason: AIErrorReason.make({
289
+ ...observation.error.reason,
290
+ message: observation.error.reason.message,
291
+ cause: observation.error.reason.cause,
292
+ body: frame,
293
+ }),
294
+ }),
295
+ }
296
+ : observation))), Stream.takeUntil(observationTerminal), Stream.mapEffect(observationFrame), Stream.mapError((error) => new AIError({
297
+ reason: AIErrorReason.make({
298
+ ...error.reason,
299
+ message: error.reason.message,
300
+ cause: error.reason.cause,
301
+ http: error.reason.http ?? connection.http,
302
+ }),
303
+ }))),
304
+ complete: Effect.void,
305
+ };
306
+ }),
307
+ });
308
+ export const direct = Effect.gen(function* () {
309
+ const constructor = yield* Socket.WebSocketConstructor;
310
+ return makeDirect({
311
+ open: (input) => open(input).pipe(Effect.provideService(Socket.WebSocketConstructor, constructor)),
312
+ });
313
+ });
314
+ export const json = (input) => ({
315
+ id: "websocket-json",
316
+ with: (patch) => json({ ...input, ...patch }),
317
+ prepare: (prepareInput) => Effect.gen(function* () {
318
+ const parts = yield* HttpTransport.jsonRequestParts({
319
+ ...prepareInput,
320
+ });
321
+ return {
322
+ url: yield* toWebSocketUrl(parts.url),
323
+ headers: parts.headers,
324
+ message: input.encodeMessage(yield* input.toMessage(parts.jsonBody)),
325
+ };
326
+ }),
327
+ execute: (prepared, request, _runtime, options) => {
328
+ const webSocket = options?.webSocket;
329
+ if (!webSocket) {
330
+ return Effect.fail(transportError("WebSocket JSON transport requires StreamOptions.webSocket", {
331
+ url: prepared.url,
332
+ operation: "request",
333
+ code: "unavailable",
334
+ phase: "prepare",
335
+ delivery: "not-sent",
336
+ }));
337
+ }
338
+ const driver = {
339
+ create: () => Effect.succeed({ message: prepared.message, mode: "full" }),
340
+ observe: (_create, frame) => Effect.succeed({ type: "frame", frame }),
341
+ };
342
+ const exchange = {
343
+ id: request.id ?? "request",
344
+ connect: { url: prepared.url, headers: prepared.headers },
345
+ fallback: () => Stream.fail(transportError("WebSocket JSON transport does not provide HTTP fallback", {
346
+ url: prepared.url,
347
+ operation: "request",
348
+ code: "websocket",
349
+ phase: "fallback",
350
+ delivery: "not-sent",
351
+ })),
352
+ driver,
353
+ };
354
+ return webSocket.execute(exchange);
355
+ },
356
+ });
357
+ export const jsonTransport = {
358
+ id: "websocket-json",
359
+ with: json,
360
+ };
361
+ export const WebSocketTransport = {
362
+ json,
363
+ jsonTransport,
364
+ direct,
365
+ makeDirect,
366
+ open,
367
+ fromWebSocket,
368
+ messageText,
369
+ toWebSocketUrl,
370
+ };
@@ -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,170 @@
1
+ import { Schema } from "effect";
2
+ import { Tool } from "@opencode/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 HttpContext_base: Schema.Class<HttpContext, Schema.Struct<{
6
+ readonly url: Schema.String;
7
+ readonly status: Schema.Int;
8
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
9
+ }>, {}>;
10
+ export declare class HttpContext extends HttpContext_base {
11
+ }
12
+ declare const HttpRateLimitDetails_base: Schema.Class<HttpRateLimitDetails, Schema.Struct<{
13
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
14
+ readonly limit: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
15
+ readonly remaining: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
16
+ readonly reset: Schema.optional<Schema.$Record<Schema.String, Schema.String>>;
17
+ }>, {}>;
18
+ export declare class HttpRateLimitDetails extends HttpRateLimitDetails_base {
19
+ }
20
+ declare const InvalidRequestError_base: Schema.Class<InvalidRequestError, Schema.TaggedStruct<"InvalidRequest", {
21
+ readonly parameter: Schema.optional<Schema.String>;
22
+ readonly classification: Schema.optional<Schema.Literals<readonly ["context-overflow", "payload-too-large"]>>;
23
+ readonly message: Schema.String;
24
+ readonly body: Schema.optional<Schema.String>;
25
+ readonly http: Schema.optional<typeof HttpContext>;
26
+ readonly cause: Schema.optional<Schema.Defect>;
27
+ }>, import("effect/Cause").YieldableError>;
28
+ export declare class InvalidRequestError extends InvalidRequestError_base {
29
+ }
30
+ declare const UnsupportedOperationError_base: Schema.Class<UnsupportedOperationError, Schema.TaggedStruct<"UnsupportedOperation", {
31
+ readonly operation: Schema.String;
32
+ readonly provider: Schema.optional<Schema.brand<Schema.String, "AI.ProviderID">>;
33
+ readonly route: Schema.optional<Schema.String>;
34
+ readonly message: Schema.String;
35
+ readonly body: Schema.optional<Schema.String>;
36
+ readonly http: Schema.optional<typeof HttpContext>;
37
+ readonly cause: Schema.optional<Schema.Defect>;
38
+ }>, import("effect/Cause").YieldableError>;
39
+ /**
40
+ * A caller-requested operation the selected route does not implement, such as
41
+ * explicit compaction on a route without a compact endpoint. Detected locally
42
+ * before any network I/O, so unlike transport or provider-output failures it
43
+ * never carries HTTP context from a provider round-trip.
44
+ */
45
+ export declare class UnsupportedOperationError extends UnsupportedOperationError_base {
46
+ }
47
+ declare const ProviderConfigurationError_base: Schema.Class<ProviderConfigurationError, Schema.TaggedStruct<"ProviderConfiguration", {
48
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
49
+ readonly message: Schema.String;
50
+ }>, import("effect/Cause").YieldableError>;
51
+ /**
52
+ * Provider settings that are missing, conflicting, or unsupported, such as
53
+ * Azure without `resourceName` or `baseURL`. Thrown synchronously while a
54
+ * provider facade or package entrypoint configures a model, before any
55
+ * request exists, so it is not an `AIError` reason.
56
+ */
57
+ export declare class ProviderConfigurationError extends ProviderConfigurationError_base {
58
+ }
59
+ declare const NoRouteError_base: Schema.Class<NoRouteError, Schema.TaggedStruct<"NoRoute", {
60
+ readonly route: Schema.String;
61
+ readonly provider: Schema.brand<Schema.String, "AI.ProviderID">;
62
+ readonly model: Schema.brand<Schema.String, "AI.ModelID">;
63
+ readonly message: Schema.String;
64
+ readonly body: Schema.optional<Schema.String>;
65
+ readonly http: Schema.optional<typeof HttpContext>;
66
+ readonly cause: Schema.optional<Schema.Defect>;
67
+ }>, import("effect/Cause").YieldableError>;
68
+ export declare class NoRouteError extends NoRouteError_base {
69
+ }
70
+ declare const AuthenticationError_base: Schema.Class<AuthenticationError, Schema.TaggedStruct<"Authentication", {
71
+ message: Schema.String;
72
+ body: Schema.optional<Schema.String>;
73
+ http: Schema.optional<typeof HttpContext>;
74
+ cause: Schema.optional<Schema.Defect>;
75
+ }>, import("effect/Cause").YieldableError>;
76
+ export declare class AuthenticationError extends AuthenticationError_base {
77
+ }
78
+ declare const RateLimitError_base: Schema.Class<RateLimitError, Schema.TaggedStruct<"RateLimit", {
79
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
80
+ readonly rateLimit: Schema.optional<typeof HttpRateLimitDetails>;
81
+ readonly message: Schema.String;
82
+ readonly body: Schema.optional<Schema.String>;
83
+ readonly http: Schema.optional<typeof HttpContext>;
84
+ readonly cause: Schema.optional<Schema.Defect>;
85
+ }>, import("effect/Cause").YieldableError>;
86
+ export declare class RateLimitError extends RateLimitError_base {
87
+ }
88
+ declare const QuotaExceededError_base: Schema.Class<QuotaExceededError, Schema.TaggedStruct<"QuotaExceeded", {
89
+ message: Schema.String;
90
+ body: Schema.optional<Schema.String>;
91
+ http: Schema.optional<typeof HttpContext>;
92
+ cause: Schema.optional<Schema.Defect>;
93
+ }>, import("effect/Cause").YieldableError>;
94
+ export declare class QuotaExceededError extends QuotaExceededError_base {
95
+ }
96
+ declare const ContentPolicyError_base: Schema.Class<ContentPolicyError, Schema.TaggedStruct<"ContentPolicy", {
97
+ message: Schema.String;
98
+ body: Schema.optional<Schema.String>;
99
+ http: Schema.optional<typeof HttpContext>;
100
+ cause: Schema.optional<Schema.Defect>;
101
+ }>, import("effect/Cause").YieldableError>;
102
+ export declare class ContentPolicyError extends ContentPolicyError_base {
103
+ }
104
+ declare const ProviderInternalError_base: Schema.Class<ProviderInternalError, Schema.TaggedStruct<"ProviderInternal", {
105
+ readonly retryAfterMs: Schema.optional<Schema.Number>;
106
+ readonly message: Schema.String;
107
+ readonly body: Schema.optional<Schema.String>;
108
+ readonly http: Schema.optional<typeof HttpContext>;
109
+ readonly cause: Schema.optional<Schema.Defect>;
110
+ }>, import("effect/Cause").YieldableError>;
111
+ export declare class ProviderInternalError extends ProviderInternalError_base {
112
+ }
113
+ export declare const TransportType: Schema.Literals<readonly ["http", "websocket"]>;
114
+ export type TransportType = typeof TransportType.Type;
115
+ export declare const TransportOperation: Schema.Literals<readonly ["request", "read", "write"]>;
116
+ export type TransportOperation = typeof TransportOperation.Type;
117
+ declare const TransportError_base: Schema.Class<TransportError, Schema.TaggedStruct<"Transport", {
118
+ readonly transport: Schema.Literals<readonly ["http", "websocket"]>;
119
+ readonly operation: Schema.Literals<readonly ["request", "read", "write"]>;
120
+ readonly code: Schema.optional<Schema.String>;
121
+ readonly url: Schema.optional<Schema.String>;
122
+ readonly phase: Schema.optional<Schema.Literals<readonly ["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"]>>;
123
+ readonly delivery: Schema.optional<Schema.Literals<readonly ["not-sent", "rejected", "ambiguous", "accepted"]>>;
124
+ readonly recovery: Schema.optional<Schema.Literals<readonly ["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"]>>;
125
+ readonly message: Schema.String;
126
+ readonly body: Schema.optional<Schema.String>;
127
+ readonly http: Schema.optional<typeof HttpContext>;
128
+ readonly cause: Schema.optional<Schema.Defect>;
129
+ }>, import("effect/Cause").YieldableError>;
130
+ export declare class TransportError extends TransportError_base {
131
+ }
132
+ declare const InvalidProviderOutputError_base: Schema.Class<InvalidProviderOutputError, Schema.TaggedStruct<"InvalidProviderOutput", {
133
+ readonly classification: Schema.optional<Schema.Literals<readonly ["incomplete-stream"]>>;
134
+ readonly route: Schema.optional<Schema.String>;
135
+ readonly message: Schema.String;
136
+ readonly body: Schema.optional<Schema.String>;
137
+ readonly http: Schema.optional<typeof HttpContext>;
138
+ readonly cause: Schema.optional<Schema.Defect>;
139
+ }>, import("effect/Cause").YieldableError>;
140
+ export declare class InvalidProviderOutputError extends InvalidProviderOutputError_base {
141
+ }
142
+ declare const UnknownProviderError_base: Schema.Class<UnknownProviderError, Schema.TaggedStruct<"UnknownProvider", {
143
+ message: Schema.String;
144
+ body: Schema.optional<Schema.String>;
145
+ http: Schema.optional<typeof HttpContext>;
146
+ cause: Schema.optional<Schema.Defect>;
147
+ }>, import("effect/Cause").YieldableError>;
148
+ export declare class UnknownProviderError extends UnknownProviderError_base {
149
+ }
150
+ export declare const AIErrorReason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestError, typeof UnsupportedOperationError, typeof NoRouteError, typeof AuthenticationError, typeof RateLimitError, typeof QuotaExceededError, typeof ContentPolicyError, typeof ProviderInternalError, typeof TransportError, typeof InvalidProviderOutputError, typeof UnknownProviderError]>;
151
+ export type AIErrorReason = Schema.Schema.Type<typeof AIErrorReason>;
152
+ declare const AIError_base: Schema.Class<AIError, Schema.TaggedStruct<"AI.Error", {
153
+ readonly reason: Schema.toTaggedUnion<"_tag", readonly [typeof InvalidRequestError, typeof UnsupportedOperationError, typeof NoRouteError, typeof AuthenticationError, typeof RateLimitError, typeof QuotaExceededError, typeof ContentPolicyError, typeof ProviderInternalError, typeof TransportError, typeof InvalidProviderOutputError, typeof UnknownProviderError]>;
154
+ }>, import("effect/Cause").YieldableError>;
155
+ export declare class AIError extends AIError_base {
156
+ readonly cause: InvalidRequestError | UnsupportedOperationError | NoRouteError | AuthenticationError | RateLimitError | QuotaExceededError | ContentPolicyError | ProviderInternalError | TransportError | InvalidProviderOutputError | UnknownProviderError;
157
+ get message(): string;
158
+ }
159
+ /**
160
+ * Failure type for tool execute handlers. Handlers must map their internal
161
+ * errors to this shape; the runtime catches `ToolFailure`s and surfaces them
162
+ * as `tool-error` events plus a `tool-result` of `type: "error"` so the model
163
+ * can self-correct.
164
+ *
165
+ * Anything thrown or yielded by a handler that is not a `ToolFailure` is
166
+ * treated as a defect and fails the stream.
167
+ */
168
+ export declare class ToolFailure extends Tool.Error {
169
+ }
170
+ export {};
@@ -0,0 +1,131 @@
1
+ import { Schema } from "effect";
2
+ import { Tool } from "@opencode/schema/tool";
3
+ import { ModelID, ProviderID, RouteID } from "./ids.js";
4
+ export const ProviderFailureClassification = Schema.Literals(["context-overflow", "payload-too-large"]);
5
+ export class HttpContext extends Schema.Class("AI.HttpContext")({
6
+ url: Schema.String,
7
+ status: Schema.Int.check(Schema.isBetween({ minimum: 100, maximum: 599 })),
8
+ headers: Schema.Record(Schema.String, Schema.String),
9
+ }) {
10
+ }
11
+ export class HttpRateLimitDetails extends Schema.Class("AI.HttpRateLimitDetails")({
12
+ retryAfterMs: Schema.optional(Schema.Number),
13
+ limit: Schema.optional(Schema.Record(Schema.String, Schema.String)),
14
+ remaining: Schema.optional(Schema.Record(Schema.String, Schema.String)),
15
+ reset: Schema.optional(Schema.Record(Schema.String, Schema.String)),
16
+ }) {
17
+ }
18
+ const ReasonFields = {
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,
27
+ parameter: Schema.optional(Schema.String),
28
+ classification: Schema.optional(ProviderFailureClassification),
29
+ }) {
30
+ }
31
+ /**
32
+ * A caller-requested operation the selected route does not implement, such as
33
+ * explicit compaction on a route without a compact endpoint. Detected locally
34
+ * before any network I/O, so unlike transport or provider-output failures it
35
+ * never carries HTTP context from a provider round-trip.
36
+ */
37
+ export class UnsupportedOperationError extends Schema.TaggedError("AI.Error.UnsupportedOperation")("UnsupportedOperation", {
38
+ ...ReasonFields,
39
+ operation: Schema.String,
40
+ provider: Schema.optional(ProviderID),
41
+ route: Schema.optional(RouteID),
42
+ }) {
43
+ }
44
+ /**
45
+ * Provider settings that are missing, conflicting, or unsupported, such as
46
+ * Azure without `resourceName` or `baseURL`. Thrown synchronously while a
47
+ * provider facade or package entrypoint configures a model, before any
48
+ * request exists, so it is not an `AIError` reason.
49
+ */
50
+ export class ProviderConfigurationError extends Schema.TaggedError("AI.Error.ProviderConfiguration")("ProviderConfiguration", {
51
+ provider: ProviderID,
52
+ message: Schema.String,
53
+ }) {
54
+ }
55
+ export class NoRouteError extends Schema.TaggedError("AI.Error.NoRoute")("NoRoute", {
56
+ ...ReasonFields,
57
+ route: RouteID,
58
+ provider: ProviderID,
59
+ model: ModelID,
60
+ }) {
61
+ }
62
+ export class AuthenticationError extends Schema.TaggedError("AI.Error.Authentication")("Authentication", ReasonFields) {
63
+ }
64
+ export class RateLimitError extends Schema.TaggedError("AI.Error.RateLimit")("RateLimit", {
65
+ ...ReasonFields,
66
+ retryAfterMs: Schema.optional(Schema.Number),
67
+ rateLimit: Schema.optional(HttpRateLimitDetails),
68
+ }) {
69
+ }
70
+ export class QuotaExceededError extends Schema.TaggedError("AI.Error.QuotaExceeded")("QuotaExceeded", ReasonFields) {
71
+ }
72
+ export class ContentPolicyError extends Schema.TaggedError("AI.Error.ContentPolicy")("ContentPolicy", ReasonFields) {
73
+ }
74
+ export class ProviderInternalError extends Schema.TaggedError("AI.Error.ProviderInternal")("ProviderInternal", {
75
+ ...ReasonFields,
76
+ retryAfterMs: Schema.optional(Schema.Number),
77
+ }) {
78
+ }
79
+ export const TransportType = Schema.Literals(["http", "websocket"]);
80
+ export const TransportOperation = Schema.Literals(["request", "read", "write"]);
81
+ export class TransportError extends Schema.TaggedError("AI.Error.Transport")("Transport", {
82
+ ...ReasonFields,
83
+ transport: TransportType,
84
+ operation: TransportOperation,
85
+ code: Schema.optional(Schema.String),
86
+ url: Schema.optional(Schema.String),
87
+ phase: Schema.optional(Schema.Literals(["prepare", "queue", "connect", "send", "receive", "decode", "complete", "fallback", "close"])),
88
+ delivery: Schema.optional(Schema.Literals(["not-sent", "rejected", "ambiguous", "accepted"])),
89
+ recovery: Schema.optional(Schema.Literals(["retry-connect", "retry-full", "rotate-and-retry-full", "fallback-http", "fail"])),
90
+ }) {
91
+ }
92
+ export class InvalidProviderOutputError extends Schema.TaggedError("AI.Error.InvalidProviderOutput")("InvalidProviderOutput", {
93
+ ...ReasonFields,
94
+ classification: Schema.optional(Schema.Literals(["incomplete-stream"])),
95
+ route: Schema.optional(Schema.String),
96
+ }) {
97
+ }
98
+ export class UnknownProviderError extends Schema.TaggedError("AI.Error.UnknownProvider")("UnknownProvider", ReasonFields) {
99
+ }
100
+ export const AIErrorReason = Schema.Union([
101
+ InvalidRequestError,
102
+ UnsupportedOperationError,
103
+ NoRouteError,
104
+ AuthenticationError,
105
+ RateLimitError,
106
+ QuotaExceededError,
107
+ ContentPolicyError,
108
+ ProviderInternalError,
109
+ TransportError,
110
+ InvalidProviderOutputError,
111
+ UnknownProviderError,
112
+ ]).pipe(Schema.toTaggedUnion("_tag"));
113
+ export class AIError extends Schema.TaggedError()("AI.Error", {
114
+ reason: AIErrorReason,
115
+ }) {
116
+ cause = this.reason;
117
+ get message() {
118
+ return this.reason.message;
119
+ }
120
+ }
121
+ /**
122
+ * Failure type for tool execute handlers. Handlers must map their internal
123
+ * errors to this shape; the runtime catches `ToolFailure`s and surfaces them
124
+ * as `tool-error` events plus a `tool-result` of `type: "error"` so the model
125
+ * can self-correct.
126
+ *
127
+ * Anything thrown or yielded by a handler that is not a `ToolFailure` is
128
+ * treated as a defect and fails the stream.
129
+ */
130
+ export class ToolFailure extends Tool.Error {
131
+ }