@opencode/ai 0.0.0-beta-19275

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 (252) hide show
  1. package/README.md +682 -0
  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/anthropic-messages.d.ts +957 -0
  13. package/dist/protocols/anthropic-messages.js +1414 -0
  14. package/dist/protocols/bedrock-converse.d.ts +499 -0
  15. package/dist/protocols/bedrock-converse.js +643 -0
  16. package/dist/protocols/bedrock-event-stream.d.ts +9 -0
  17. package/dist/protocols/bedrock-event-stream.js +97 -0
  18. package/dist/protocols/gemini.d.ts +285 -0
  19. package/dist/protocols/gemini.js +671 -0
  20. package/dist/protocols/google-images.d.ts +30 -0
  21. package/dist/protocols/google-images.js +181 -0
  22. package/dist/protocols/index.d.ts +12 -0
  23. package/dist/protocols/index.js +12 -0
  24. package/dist/protocols/meta-images.d.ts +26 -0
  25. package/dist/protocols/meta-images.js +89 -0
  26. package/dist/protocols/meta-messages.d.ts +350 -0
  27. package/dist/protocols/meta-messages.js +41 -0
  28. package/dist/protocols/meta-responses.d.ts +473 -0
  29. package/dist/protocols/meta-responses.js +173 -0
  30. package/dist/protocols/mistral-chat.d.ts +540 -0
  31. package/dist/protocols/mistral-chat.js +624 -0
  32. package/dist/protocols/open-responses-channel.d.ts +23 -0
  33. package/dist/protocols/open-responses-channel.js +141 -0
  34. package/dist/protocols/open-responses-continuation.d.ts +12 -0
  35. package/dist/protocols/open-responses-continuation.js +161 -0
  36. package/dist/protocols/open-responses.d.ts +1583 -0
  37. package/dist/protocols/open-responses.js +1206 -0
  38. package/dist/protocols/openai-chat.d.ts +860 -0
  39. package/dist/protocols/openai-chat.js +966 -0
  40. package/dist/protocols/openai-compatible-chat.d.ts +109 -0
  41. package/dist/protocols/openai-compatible-chat.js +19 -0
  42. package/dist/protocols/openai-compatible-responses.d.ts +172 -0
  43. package/dist/protocols/openai-compatible-responses.js +18 -0
  44. package/dist/protocols/openai-images.d.ts +32 -0
  45. package/dist/protocols/openai-images.js +183 -0
  46. package/dist/protocols/openai-responses.d.ts +1389 -0
  47. package/dist/protocols/openai-responses.js +260 -0
  48. package/dist/protocols/shared.d.ts +193 -0
  49. package/dist/protocols/shared.js +290 -0
  50. package/dist/protocols/utils/bedrock-auth.d.ts +60 -0
  51. package/dist/protocols/utils/bedrock-auth.js +85 -0
  52. package/dist/protocols/utils/bedrock-cache.d.ts +19 -0
  53. package/dist/protocols/utils/bedrock-cache.js +49 -0
  54. package/dist/protocols/utils/bedrock-media.d.ts +55 -0
  55. package/dist/protocols/utils/bedrock-media.js +73 -0
  56. package/dist/protocols/utils/cache.d.ts +6 -0
  57. package/dist/protocols/utils/cache.js +5 -0
  58. package/dist/protocols/utils/gemini-tool-schema.d.ts +2 -0
  59. package/dist/protocols/utils/gemini-tool-schema.js +103 -0
  60. package/dist/protocols/utils/image-input.d.ts +21 -0
  61. package/dist/protocols/utils/image-input.js +20 -0
  62. package/dist/protocols/utils/lifecycle.d.ts +24 -0
  63. package/dist/protocols/utils/lifecycle.js +72 -0
  64. package/dist/protocols/utils/meta-image.d.ts +2 -0
  65. package/dist/protocols/utils/meta-image.js +13 -0
  66. package/dist/protocols/utils/open-responses-options.d.ts +56 -0
  67. package/dist/protocols/utils/open-responses-options.js +61 -0
  68. package/dist/protocols/utils/openai-image.d.ts +5 -0
  69. package/dist/protocols/utils/openai-image.js +18 -0
  70. package/dist/protocols/utils/openai-options.d.ts +16 -0
  71. package/dist/protocols/utils/openai-options.js +14 -0
  72. package/dist/protocols/utils/partial-json-options.d.ts +62 -0
  73. package/dist/protocols/utils/partial-json-options.js +52 -0
  74. package/dist/protocols/utils/partial-json.d.ts +8 -0
  75. package/dist/protocols/utils/partial-json.js +279 -0
  76. package/dist/protocols/utils/responses-checkpoint.d.ts +4 -0
  77. package/dist/protocols/utils/responses-checkpoint.js +107 -0
  78. package/dist/protocols/utils/responses-compaction.d.ts +4 -0
  79. package/dist/protocols/utils/responses-compaction.js +129 -0
  80. package/dist/protocols/utils/responses-hosted-tools.d.ts +26 -0
  81. package/dist/protocols/utils/responses-hosted-tools.js +32 -0
  82. package/dist/protocols/utils/tool-schema.d.ts +8 -0
  83. package/dist/protocols/utils/tool-schema.js +54 -0
  84. package/dist/protocols/utils/tool-stream.d.ts +710 -0
  85. package/dist/protocols/utils/tool-stream.js +155 -0
  86. package/dist/protocols/xai-images.d.ts +26 -0
  87. package/dist/protocols/xai-images.js +106 -0
  88. package/dist/protocols/xai-responses.d.ts +250 -0
  89. package/dist/protocols/xai-responses.js +81 -0
  90. package/dist/protocols/zai-images.d.ts +22 -0
  91. package/dist/protocols/zai-images.js +79 -0
  92. package/dist/protocols.d.ts +1 -0
  93. package/dist/protocols.js +1 -0
  94. package/dist/provider-error.d.ts +15 -0
  95. package/dist/provider-error.js +125 -0
  96. package/dist/provider-package.d.ts +11 -0
  97. package/dist/provider-package.js +1 -0
  98. package/dist/provider.d.ts +23 -0
  99. package/dist/provider.js +2 -0
  100. package/dist/providers/amazon-bedrock/mantle/chat.d.ts +2 -0
  101. package/dist/providers/amazon-bedrock/mantle/chat.js +1 -0
  102. package/dist/providers/amazon-bedrock/mantle/responses.d.ts +2 -0
  103. package/dist/providers/amazon-bedrock/mantle/responses.js +1 -0
  104. package/dist/providers/amazon-bedrock/mantle.d.ts +2 -0
  105. package/dist/providers/amazon-bedrock/mantle.js +1 -0
  106. package/dist/providers/amazon-bedrock-mantle.d.ts +371 -0
  107. package/dist/providers/amazon-bedrock-mantle.js +76 -0
  108. package/dist/providers/amazon-bedrock.d.ts +173 -0
  109. package/dist/providers/amazon-bedrock.js +41 -0
  110. package/dist/providers/anthropic-compatible.d.ts +304 -0
  111. package/dist/providers/anthropic-compatible.js +44 -0
  112. package/dist/providers/anthropic.d.ts +302 -0
  113. package/dist/providers/anthropic.js +39 -0
  114. package/dist/providers/azure/chat.d.ts +2 -0
  115. package/dist/providers/azure/chat.js +1 -0
  116. package/dist/providers/azure/responses.d.ts +2 -0
  117. package/dist/providers/azure/responses.js +1 -0
  118. package/dist/providers/azure.d.ts +599 -0
  119. package/dist/providers/azure.js +115 -0
  120. package/dist/providers/baseten.d.ts +229 -0
  121. package/dist/providers/baseten.js +38 -0
  122. package/dist/providers/cerebras.d.ts +228 -0
  123. package/dist/providers/cerebras.js +40 -0
  124. package/dist/providers/cloudflare-ai-gateway.d.ts +238 -0
  125. package/dist/providers/cloudflare-ai-gateway.js +59 -0
  126. package/dist/providers/cloudflare-workers-ai.d.ts +232 -0
  127. package/dist/providers/cloudflare-workers-ai.js +45 -0
  128. package/dist/providers/deepinfra.d.ts +228 -0
  129. package/dist/providers/deepinfra.js +43 -0
  130. package/dist/providers/deepseek.d.ts +229 -0
  131. package/dist/providers/deepseek.js +41 -0
  132. package/dist/providers/fireworks.d.ts +229 -0
  133. package/dist/providers/fireworks.js +38 -0
  134. package/dist/providers/google-vertex/chat.d.ts +2 -0
  135. package/dist/providers/google-vertex/chat.js +1 -0
  136. package/dist/providers/google-vertex/gemini.d.ts +2 -0
  137. package/dist/providers/google-vertex/gemini.js +1 -0
  138. package/dist/providers/google-vertex/messages.d.ts +2 -0
  139. package/dist/providers/google-vertex/messages.js +1 -0
  140. package/dist/providers/google-vertex/responses.d.ts +2 -0
  141. package/dist/providers/google-vertex/responses.js +1 -0
  142. package/dist/providers/google-vertex-chat.d.ts +133 -0
  143. package/dist/providers/google-vertex-chat.js +55 -0
  144. package/dist/providers/google-vertex-messages.d.ts +301 -0
  145. package/dist/providers/google-vertex-messages.js +75 -0
  146. package/dist/providers/google-vertex-responses.d.ts +198 -0
  147. package/dist/providers/google-vertex-responses.js +56 -0
  148. package/dist/providers/google-vertex-shared.d.ts +22 -0
  149. package/dist/providers/google-vertex-shared.js +61 -0
  150. package/dist/providers/google-vertex.d.ts +120 -0
  151. package/dist/providers/google-vertex.js +92 -0
  152. package/dist/providers/google.d.ts +115 -0
  153. package/dist/providers/google.js +42 -0
  154. package/dist/providers/groq.d.ts +315 -0
  155. package/dist/providers/groq.js +81 -0
  156. package/dist/providers/index.d.ts +28 -0
  157. package/dist/providers/index.js +28 -0
  158. package/dist/providers/meta/chat.d.ts +2 -0
  159. package/dist/providers/meta/chat.js +1 -0
  160. package/dist/providers/meta/messages.d.ts +2 -0
  161. package/dist/providers/meta/messages.js +1 -0
  162. package/dist/providers/meta/responses.d.ts +2 -0
  163. package/dist/providers/meta/responses.js +1 -0
  164. package/dist/providers/meta.d.ts +631 -0
  165. package/dist/providers/meta.js +113 -0
  166. package/dist/providers/minimax/chat.d.ts +4 -0
  167. package/dist/providers/minimax/chat.js +8 -0
  168. package/dist/providers/minimax/messages.d.ts +1 -0
  169. package/dist/providers/minimax/messages.js +1 -0
  170. package/dist/providers/minimax/responses.d.ts +4 -0
  171. package/dist/providers/minimax/responses.js +8 -0
  172. package/dist/providers/minimax.d.ts +593 -0
  173. package/dist/providers/minimax.js +89 -0
  174. package/dist/providers/mistral.d.ts +208 -0
  175. package/dist/providers/mistral.js +28 -0
  176. package/dist/providers/open-responses-options.d.ts +6 -0
  177. package/dist/providers/open-responses-options.js +1 -0
  178. package/dist/providers/openai/chat.d.ts +2 -0
  179. package/dist/providers/openai/chat.js +1 -0
  180. package/dist/providers/openai/responses.d.ts +2 -0
  181. package/dist/providers/openai/responses.js +1 -0
  182. package/dist/providers/openai-compatible/responses.d.ts +1 -0
  183. package/dist/providers/openai-compatible/responses.js +1 -0
  184. package/dist/providers/openai-compatible-responses.d.ts +196 -0
  185. package/dist/providers/openai-compatible-responses.js +32 -0
  186. package/dist/providers/openai-compatible.d.ts +131 -0
  187. package/dist/providers/openai-compatible.js +33 -0
  188. package/dist/providers/openai-options.d.ts +26 -0
  189. package/dist/providers/openai-options.js +41 -0
  190. package/dist/providers/openai.d.ts +405 -0
  191. package/dist/providers/openai.js +82 -0
  192. package/dist/providers/openrouter.d.ts +564 -0
  193. package/dist/providers/openrouter.js +114 -0
  194. package/dist/providers/togetherai.d.ts +228 -0
  195. package/dist/providers/togetherai.js +40 -0
  196. package/dist/providers/xai.d.ts +164 -0
  197. package/dist/providers/xai.js +84 -0
  198. package/dist/providers/zai.d.ts +24 -0
  199. package/dist/providers/zai.js +21 -0
  200. package/dist/providers.d.ts +1 -0
  201. package/dist/providers.js +1 -0
  202. package/dist/route/auth-options.d.ts +34 -0
  203. package/dist/route/auth-options.js +14 -0
  204. package/dist/route/auth.d.ts +51 -0
  205. package/dist/route/auth.js +87 -0
  206. package/dist/route/client.d.ts +430 -0
  207. package/dist/route/client.js +304 -0
  208. package/dist/route/endpoint.d.ts +28 -0
  209. package/dist/route/endpoint.js +21 -0
  210. package/dist/route/executor.d.ts +27 -0
  211. package/dist/route/executor.js +183 -0
  212. package/dist/route/framing.d.ts +29 -0
  213. package/dist/route/framing.js +14 -0
  214. package/dist/route/index.d.ts +16 -0
  215. package/dist/route/index.js +9 -0
  216. package/dist/route/protocol.d.ts +76 -0
  217. package/dist/route/protocol.js +16 -0
  218. package/dist/route/transport/http.d.ts +34 -0
  219. package/dist/route/transport/http.js +68 -0
  220. package/dist/route/transport/index.d.ts +41 -0
  221. package/dist/route/transport/index.js +4 -0
  222. package/dist/route/transport/websocket-channel.d.ts +57 -0
  223. package/dist/route/transport/websocket-channel.js +1 -0
  224. package/dist/route/transport/websocket.d.ts +56 -0
  225. package/dist/route/transport/websocket.js +366 -0
  226. package/dist/route.d.ts +1 -0
  227. package/dist/route.js +1 -0
  228. package/dist/schema/errors.d.ts +158 -0
  229. package/dist/schema/errors.js +120 -0
  230. package/dist/schema/events.d.ts +8123 -0
  231. package/dist/schema/events.js +550 -0
  232. package/dist/schema/ids.d.ts +17 -0
  233. package/dist/schema/ids.js +10 -0
  234. package/dist/schema/index.d.ts +5 -0
  235. package/dist/schema/index.js +5 -0
  236. package/dist/schema/messages.d.ts +646 -0
  237. package/dist/schema/messages.js +301 -0
  238. package/dist/schema/options.d.ts +157 -0
  239. package/dist/schema/options.js +187 -0
  240. package/dist/testing.d.ts +1693 -0
  241. package/dist/testing.js +129 -0
  242. package/dist/tool-history.d.ts +2 -0
  243. package/dist/tool-history.js +84 -0
  244. package/dist/tool-runtime.d.ts +15 -0
  245. package/dist/tool-runtime.js +62 -0
  246. package/dist/tool.d.ts +136 -0
  247. package/dist/tool.js +66 -0
  248. package/dist/utils/record.d.ts +2 -0
  249. package/dist/utils/record.js +2 -0
  250. package/dist/utils/sanitize.d.ts +1 -0
  251. package/dist/utils/sanitize.js +12 -0
  252. package/package.json +48 -0
@@ -0,0 +1,141 @@
1
+ import { Effect, Schema, Stream } from "effect";
2
+ import { Headers } from "effect/unstable/http";
3
+ import { Framing } from "../route/framing.js";
4
+ import { HttpTransport, WebSocketTransport, } from "../route/transport/index.js";
5
+ import * as ProviderShared from "./shared.js";
6
+ import { OpenResponses } from "./open-responses.js";
7
+ import { OpenResponsesContinuation } from "./open-responses-continuation.js";
8
+ const WebSocketResponseCreate = Schema.StructWithRest(Schema.Struct({ type: Schema.tag("response.create") }), [
9
+ Schema.Record(Schema.String, Schema.Unknown),
10
+ ]);
11
+ const decodeMessage = ProviderShared.validateWith(Schema.decodeUnknownEffect(WebSocketResponseCreate));
12
+ const encodeMessage = Schema.encodeSync(Schema.fromJsonString(WebSocketResponseCreate));
13
+ const decodeEvent = Schema.decodeUnknownEffect(OpenResponses.protocol.stream.event);
14
+ const message = (body) => Effect.gen(function* () {
15
+ if (!ProviderShared.isRecord(body))
16
+ return yield* ProviderShared.invalidRequest("Open Responses WebSocket body must be a JSON object");
17
+ const { stream: _stream, stream_options: _streamOptions, background: _background, ...request } = body;
18
+ const decoded = yield* decodeMessage({ ...request, type: "response.create" });
19
+ return { request: decoded, message: encodeMessage(decoded) };
20
+ });
21
+ const driver = (options, body) => {
22
+ let responseID;
23
+ let terminal = false;
24
+ return {
25
+ create: () => Effect.sync(() => {
26
+ responseID = undefined;
27
+ terminal = false;
28
+ return { message: body, mode: "full" };
29
+ }),
30
+ observe: (_create, frame) => Effect.gen(function* () {
31
+ const event = yield* decodeEvent(frame).pipe(Effect.mapError((cause) => ProviderShared.eventError(options.id, `Invalid ${options.name} WebSocket event`, frame, cause)));
32
+ if (terminal)
33
+ return yield* ProviderShared.eventError(options.id, `${options.name} emitted ${event.type} after a terminal event`, frame);
34
+ if (event.type === "error") {
35
+ terminal = true;
36
+ yield* OpenResponses.decodeKnownErrorEvent(event).pipe(Effect.mapError((cause) => ProviderShared.eventError(options.id, `${options.name} returned a malformed error event`, frame, cause)));
37
+ return {
38
+ type: "provider-failure",
39
+ error: OpenResponses.providerFailure(event, `${options.name} stream error`, frame),
40
+ };
41
+ }
42
+ if (event.type === "response.failed") {
43
+ terminal = true;
44
+ if (responseID && event.response?.id && event.response.id !== responseID)
45
+ return yield* ProviderShared.eventError(options.id, `${options.name} response ID changed during execution`, frame);
46
+ return {
47
+ type: "provider-failure",
48
+ error: OpenResponses.providerFailure(event, `${options.name} response failed`, frame),
49
+ };
50
+ }
51
+ if (event.type === "response.created") {
52
+ const created = event.response?.id;
53
+ if (responseID)
54
+ return yield* ProviderShared.eventError(options.id, `${options.name} emitted duplicate response.created`, frame);
55
+ if (!created)
56
+ return yield* ProviderShared.eventError(options.id, `${options.name} response.created is missing response.id`, frame);
57
+ responseID = created;
58
+ return { type: "frame", frame };
59
+ }
60
+ // Keepalives and provider notifications carry no response state and may precede response.created.
61
+ if (!event.type.startsWith("response."))
62
+ return { type: "frame", frame };
63
+ if (!responseID)
64
+ return yield* ProviderShared.eventError(options.id, `${options.name} emitted ${event.type} before response.created`, frame);
65
+ if (event.response?.id && event.response.id !== responseID)
66
+ return yield* ProviderShared.eventError(options.id, `${options.name} response ID changed during execution`, frame);
67
+ if (event.type === "response.completed") {
68
+ terminal = true;
69
+ return { type: "completed", frame };
70
+ }
71
+ if (event.type === "response.incomplete") {
72
+ terminal = true;
73
+ return { type: "incomplete", frame };
74
+ }
75
+ return { type: "frame", frame };
76
+ }),
77
+ };
78
+ };
79
+ export const transport = (options) => {
80
+ const http = HttpTransport.sseJson.with();
81
+ return {
82
+ id: http.id,
83
+ prepare: (input) => Effect.gen(function* () {
84
+ const parts = yield* HttpTransport.jsonRequestParts(input);
85
+ const headers = Headers.remove(options.headers?.(parts.headers) ?? parts.headers, "content-length");
86
+ const channel = input.webSocket && (options.enabled?.(parts.url) ?? true)
87
+ ? yield* Effect.gen(function* () {
88
+ const create = yield* message(parts.jsonBody);
89
+ const base = driver(options, create.message);
90
+ return {
91
+ url: yield* WebSocketTransport.toWebSocketUrl(options.url?.(parts.url) ?? parts.url),
92
+ headers,
93
+ rotateAfterMs: options.rotateAfterMs,
94
+ driver: OpenResponsesContinuation.driver({
95
+ id: options.id,
96
+ name: options.name,
97
+ request: create.request,
98
+ message: create.message,
99
+ base,
100
+ }),
101
+ };
102
+ })
103
+ : undefined;
104
+ return {
105
+ http: {
106
+ request: ProviderShared.jsonPost({ url: parts.url, body: parts.bodyText, headers: parts.headers }),
107
+ framing: Framing.sse,
108
+ middleware: input.middleware,
109
+ },
110
+ channel,
111
+ };
112
+ }),
113
+ execute: (prepared, request, runtime, executeOptions) => Effect.gen(function* () {
114
+ if (!executeOptions?.webSocket || !prepared.channel)
115
+ return yield* http.execute(prepared.http, request, runtime);
116
+ let fallbackHttp;
117
+ const exchange = {
118
+ id: request.id ?? "request",
119
+ connect: {
120
+ url: prepared.channel.url,
121
+ headers: prepared.channel.headers,
122
+ rotateAfterMs: prepared.channel.rotateAfterMs,
123
+ },
124
+ fallback: () => Stream.unwrap(http.execute(prepared.http, request, runtime).pipe(Effect.map((execution) => {
125
+ fallbackHttp = execution.http;
126
+ return execution.frames;
127
+ }))),
128
+ driver: prepared.channel.driver,
129
+ };
130
+ const execution = yield* executeOptions.webSocket.execute(exchange);
131
+ return {
132
+ frames: execution.frames,
133
+ complete: execution.complete,
134
+ get http() {
135
+ return fallbackHttp ?? execution.http;
136
+ },
137
+ };
138
+ }),
139
+ };
140
+ };
141
+ export const OpenResponsesChannel = { transport };
@@ -0,0 +1,12 @@
1
+ import type { WebSocketChannelDriver } from "../route/transport/index.js";
2
+ export interface DriverInput {
3
+ readonly id: string;
4
+ readonly name: string;
5
+ readonly request: Readonly<Record<string, unknown>>;
6
+ readonly message: string;
7
+ readonly base: WebSocketChannelDriver;
8
+ }
9
+ export declare const driver: (input: DriverInput) => WebSocketChannelDriver;
10
+ export declare const OpenResponsesContinuation: {
11
+ readonly driver: (input: DriverInput) => WebSocketChannelDriver;
12
+ };
@@ -0,0 +1,161 @@
1
+ import { AIError, TransportError } from "../schema/index.js";
2
+ import { Effect, Option, Schema } from "effect";
3
+ import * as ProviderShared from "./shared.js";
4
+ import { OpenResponses } from "./open-responses.js";
5
+ const PROTOCOL = "open-responses.websocket.v1";
6
+ const VERSION = 1;
7
+ const decodeEvent = Schema.decodeUnknownEffect(OpenResponses.protocol.stream.event);
8
+ const checkpointValue = (checkpoint) => {
9
+ if (checkpoint?.protocol !== PROTOCOL || !ProviderShared.isRecord(checkpoint.value))
10
+ return undefined;
11
+ if (checkpoint.value.version !== VERSION)
12
+ return undefined;
13
+ if (typeof checkpoint.value.responseID !== "string" || checkpoint.value.responseID.trim().length === 0)
14
+ return undefined;
15
+ if (!ProviderShared.isRecord(checkpoint.value.request) || !Array.isArray(checkpoint.value.output))
16
+ return undefined;
17
+ return {
18
+ version: VERSION,
19
+ responseID: checkpoint.value.responseID,
20
+ request: checkpoint.value.request,
21
+ output: checkpoint.value.output,
22
+ };
23
+ };
24
+ const canonical = (value) => {
25
+ if (value === undefined)
26
+ return "undefined";
27
+ if (Array.isArray(value))
28
+ return `[${value.map(canonical).join(",")}]`;
29
+ if (!ProviderShared.isRecord(value))
30
+ return ProviderShared.encodeJson(value);
31
+ return `{${Object.keys(value)
32
+ .filter((key) => value[key] !== undefined)
33
+ .sort()
34
+ .map((key) => `${ProviderShared.encodeJson(key)}:${canonical(value[key])}`)
35
+ .join(",")}}`;
36
+ };
37
+ const json = (value) => {
38
+ if (typeof value !== "string")
39
+ return value;
40
+ return Option.getOrElse(Schema.decodeUnknownOption(ProviderShared.Json)(value), () => value);
41
+ };
42
+ const comparable = (value) => {
43
+ if (!ProviderShared.isRecord(value))
44
+ return value;
45
+ if (value.type === "message" && value.role === "assistant")
46
+ return {
47
+ role: "assistant",
48
+ // Annotations and logprobs describe the response, not the text replayed in model input.
49
+ content: Array.isArray(value.content)
50
+ ? value.content.map((part) => ProviderShared.isRecord(part) && part.type === "output_text" ? { type: part.type, text: part.text } : part)
51
+ : value.content,
52
+ ...(value.phase === undefined ? {} : { phase: value.phase }),
53
+ };
54
+ if (value.type === "function_call")
55
+ return {
56
+ type: value.type,
57
+ call_id: value.call_id,
58
+ name: value.name,
59
+ arguments: json(value.arguments),
60
+ };
61
+ if (value.type === "reasoning")
62
+ return {
63
+ type: value.type,
64
+ summary: value.summary,
65
+ encrypted_content: value.encrypted_content,
66
+ };
67
+ return value;
68
+ };
69
+ const invariant = (request) => {
70
+ const { type: _type, input: _input, previous_response_id: _previousResponseID, ...rest } = request;
71
+ return rest;
72
+ };
73
+ const incremental = (request, checkpoint) => {
74
+ const input = request.input;
75
+ const previousInput = checkpoint.request.input;
76
+ if (!Array.isArray(input) || !Array.isArray(previousInput))
77
+ return undefined;
78
+ if (canonical(invariant(request)) !== canonical(invariant(checkpoint.request)))
79
+ return undefined;
80
+ const baseline = [...previousInput, ...checkpoint.output];
81
+ if (input.length <= baseline.length)
82
+ return undefined;
83
+ if (!baseline.every((item, index) => canonical(comparable(item)) === canonical(comparable(input[index]))))
84
+ return undefined;
85
+ return input.slice(baseline.length);
86
+ };
87
+ const code = (event) => event.code || event.error?.code || event.response?.error?.code || undefined;
88
+ const rejected = (observation, recovery) => ({
89
+ type: "rejected",
90
+ recovery,
91
+ error: new AIError({
92
+ reason: new TransportError({
93
+ message: observation.error.message,
94
+ body: observation.error.reason.body,
95
+ http: observation.error.reason.http,
96
+ cause: observation.error.reason.cause,
97
+ transport: "websocket",
98
+ operation: "read",
99
+ phase: "receive",
100
+ delivery: "rejected",
101
+ recovery,
102
+ }),
103
+ }),
104
+ });
105
+ export const driver = (input) => {
106
+ const { previous_response_id: _previousResponseID, ...request } = input.request;
107
+ let output = [];
108
+ return {
109
+ create: (checkpoint) => Effect.sync(() => {
110
+ output = [];
111
+ const previous = checkpointValue(checkpoint);
112
+ const delta = previous ? incremental(request, previous) : undefined;
113
+ if (!previous || !delta)
114
+ return { message: ProviderShared.encodeJson(request), mode: "full" };
115
+ return {
116
+ message: ProviderShared.encodeJson({ ...request, input: delta, previous_response_id: previous.responseID }),
117
+ mode: "incremental",
118
+ };
119
+ }),
120
+ observe: (create, frame) => Effect.gen(function* () {
121
+ const event = yield* decodeEvent(frame).pipe(Effect.mapError((cause) => ProviderShared.eventError(input.id, `Invalid ${input.name} WebSocket event`, frame, cause)));
122
+ const observation = yield* input.base.observe(create, frame);
123
+ if (event.type === "response.output_item.done" && event.item)
124
+ output.push(event.item);
125
+ if (observation.type === "provider-failure") {
126
+ const rejection = code(event);
127
+ if (rejection === "previous_response_not_found")
128
+ return rejected(observation, "retry-full");
129
+ if (rejection === "websocket_connection_limit_reached")
130
+ return rejected(observation, "rotate-and-retry-full");
131
+ }
132
+ if (observation.type !== "completed")
133
+ return observation;
134
+ // A trigger installs a different context window. Clear the append baseline, retaining the socket.
135
+ if (Array.isArray(request.input) &&
136
+ request.input.some((item) => ProviderShared.isRecord(item) && item.type === "compaction_trigger"))
137
+ return observation;
138
+ const responseID = event.response?.id;
139
+ if (!responseID || responseID.trim().length === 0)
140
+ return observation;
141
+ return {
142
+ ...observation,
143
+ checkpoint: {
144
+ protocol: PROTOCOL,
145
+ value: {
146
+ version: VERSION,
147
+ responseID,
148
+ request,
149
+ // Completion can re-encrypt reasoning. Callers replay the item already emitted by output_item.done.
150
+ output: event.response?.output
151
+ ? event.response.output.map((item) => item.type === "reasoning" && item.id !== undefined
152
+ ? (output.find((done) => done.type === item.type && done.id === item.id) ?? item)
153
+ : item)
154
+ : output.slice(),
155
+ },
156
+ },
157
+ };
158
+ }),
159
+ };
160
+ };
161
+ export const OpenResponsesContinuation = { driver };