@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,348 @@
1
+ import { Context, Effect, Layer, Schema, Stream } from "effect";
2
+ import { Auth } from "./auth.js";
3
+ import { Endpoint, type EndpointPatch } from "./endpoint.js";
4
+ import { RequestExecutor } from "./executor.js";
5
+ import { Framing } from "./framing.js";
6
+ import { HttpTransport } from "./transport/index.js";
7
+ import type { HttpMiddleware, Transport, TransportRuntime, WebSocketChannelExecutor } from "./transport/index.js";
8
+ import type { Protocol } from "./protocol.js";
9
+ import type { ProtocolID, ProviderOptions } from "../schema/index.js";
10
+ import { AIError, GenerationOptions, HttpOptions, LLMRequest, LLMResponse, LanguageModel, LanguageModelLimits, LLMEvent, ProviderID } from "../schema/index.js";
11
+ export interface RouteBody<Body> {
12
+ /** Schema for the validated provider-native body sent as the JSON request. */
13
+ readonly schema: Schema.Codec<Body, unknown>;
14
+ /** Build the provider-native body from a common `LLMRequest`. */
15
+ readonly from: (request: LLMRequest) => Effect.Effect<Body, AIError>;
16
+ }
17
+ export interface Route<Body, Prepared = unknown> {
18
+ readonly id: string;
19
+ readonly provider?: ProviderID;
20
+ /** ProviderMetadata namespace emitted and consumed by this route. */
21
+ readonly providerMetadataKey?: string;
22
+ readonly protocol: ProtocolID;
23
+ readonly endpoint: Endpoint.Definition<Body>;
24
+ readonly auth: Auth.Definition;
25
+ readonly transport: Transport<Body, Prepared, unknown>;
26
+ readonly defaults: RouteDefaults;
27
+ readonly body: RouteBody<Body>;
28
+ readonly with: (patch: RoutePatch<Body, Prepared>) => Route<Body, Prepared>;
29
+ readonly model: <Options extends ProviderOptions = ProviderOptions>(input: RouteMappedLanguageModelInput) => LanguageModel<Options>;
30
+ readonly prepareTransport: (body: Body, request: LLMRequest, options?: StreamOptions) => Effect.Effect<Prepared, AIError>;
31
+ readonly streamPrepared: (prepared: Prepared, request: LLMRequest, runtime: TransportRuntime, options?: StreamOptions) => Stream.Stream<LLMEvent, AIError>;
32
+ }
33
+ export type AnyRoute = Route<any, any>;
34
+ export type HttpOptionsInput = HttpOptions.Input;
35
+ export type RouteLanguageModelInput = Omit<LanguageModel.Input, "provider" | "route">;
36
+ export type RouteRoutedLanguageModelInput = Omit<LanguageModel.Input, "route">;
37
+ export interface RouteDefaults {
38
+ readonly headers?: Record<string, string>;
39
+ readonly limits?: LanguageModelLimits;
40
+ readonly generation?: GenerationOptions;
41
+ readonly providerOptions?: ProviderOptions;
42
+ readonly http?: HttpOptions;
43
+ }
44
+ export interface RouteDefaultsInput {
45
+ readonly headers?: Record<string, string>;
46
+ readonly limits?: LanguageModelLimits.Input;
47
+ readonly generation?: GenerationOptions.Input;
48
+ readonly providerOptions?: ProviderOptions;
49
+ readonly http?: HttpOptions.Input;
50
+ }
51
+ export interface RoutePatch<Body, Prepared> extends RouteDefaultsInput {
52
+ readonly id?: string;
53
+ readonly provider?: string | ProviderID;
54
+ readonly auth?: Auth.Definition;
55
+ readonly transport?: Transport<Body, Prepared, unknown>;
56
+ readonly endpoint?: EndpointPatch<Body>;
57
+ }
58
+ type RouteMappedLanguageModelInput = RouteLanguageModelInput | RouteRoutedLanguageModelInput;
59
+ export declare const generationOptions: (input: GenerationOptions.Input | undefined) => GenerationOptions | undefined;
60
+ export declare const httpOptions: (input: HttpOptionsInput | undefined) => HttpOptions | undefined;
61
+ export interface Interface {
62
+ readonly stream: StreamMethod;
63
+ readonly generate: GenerateMethod;
64
+ }
65
+ export interface StreamOptions {
66
+ readonly http?: HttpMiddleware;
67
+ readonly webSocket?: WebSocketChannelExecutor;
68
+ }
69
+ export interface StreamMethod {
70
+ (request: LLMRequest, options?: StreamOptions): Stream.Stream<LLMEvent, AIError>;
71
+ }
72
+ export interface GenerateMethod {
73
+ (request: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError>;
74
+ }
75
+ declare const Service_base: Context.ServiceClass<Service, "@opencode/LLMClient", Interface>;
76
+ export declare class Service extends Service_base {
77
+ }
78
+ export interface MakeInput<Body, Frame, Event, State> {
79
+ /** Route id used in diagnostics and prepared request metadata. */
80
+ readonly id: string;
81
+ /** Provider identity for route-owned model construction. */
82
+ readonly provider?: string | ProviderID;
83
+ /** ProviderMetadata namespace emitted and consumed by this route. */
84
+ readonly providerMetadataKey?: string;
85
+ /** Semantic API contract — owns body construction, body schema, and parsing. */
86
+ readonly protocol: Protocol<Body, Frame, Event, State>;
87
+ /** Where the request is sent. */
88
+ readonly endpoint: Endpoint.Definition<Body>;
89
+ /** Per-request transport auth. Provider facades override this via `route.with(...)`. */
90
+ readonly auth?: Auth.Definition;
91
+ /** Stream framing — bytes -> frames before `protocol.stream.event` decoding. */
92
+ readonly framing: Framing.Definition<Frame>;
93
+ /** Static / per-request headers added before `auth` runs. */
94
+ readonly headers?: (input: {
95
+ readonly request: LLMRequest;
96
+ }) => Record<string, string>;
97
+ /** Route/request defaults used when compiling requests for this route. */
98
+ readonly defaults?: RouteDefaultsInput;
99
+ }
100
+ export interface MakeTransportInput<Body, Prepared, Frame, Event, State> {
101
+ /** Route id used in diagnostics and prepared request metadata. */
102
+ readonly id: string;
103
+ /** Provider identity for route-owned model construction. */
104
+ readonly provider?: string | ProviderID;
105
+ /** ProviderMetadata namespace emitted and consumed by this route. */
106
+ readonly providerMetadataKey?: string;
107
+ /** Semantic API contract — owns body construction, body schema, and parsing. */
108
+ readonly protocol: Protocol<Body, Frame, Event, State>;
109
+ /** Where the request is sent. */
110
+ readonly endpoint: Endpoint.Definition<Body>;
111
+ /** Per-request transport auth. Provider facades override this via `route.with(...)`. */
112
+ readonly auth?: Auth.Definition;
113
+ /** Static / per-request headers added before `auth` runs. */
114
+ readonly headers?: (input: {
115
+ readonly request: LLMRequest;
116
+ }) => Record<string, string>;
117
+ /** Runnable transport route. */
118
+ readonly transport: Transport<Body, Prepared, Frame>;
119
+ /** Route/request defaults used when compiling requests for this route. */
120
+ readonly defaults?: RouteDefaultsInput;
121
+ }
122
+ export declare function make<Body, Prepared, Frame, Event, State>(input: MakeTransportInput<Body, Prepared, Frame, Event, State>): Route<Body, Prepared>;
123
+ /**
124
+ * Build a `Route` by composing the four orthogonal pieces of a deployment:
125
+ *
126
+ * - `Protocol` — what is the API I'm speaking?
127
+ * - `Endpoint` — where do I send the request?
128
+ * - `Auth` — how do I authenticate it?
129
+ * - `Framing` — how do I cut the response stream into protocol frames?
130
+ *
131
+ * Plus optional `headers` for cross-cutting deployment concerns (provider
132
+ * version pins, per-deployment quirks).
133
+ *
134
+ * This is the canonical route constructor. If a new route does not fit
135
+ * this four-axis model, add a purpose-built constructor rather than widening
136
+ * the public surface preemptively.
137
+ */
138
+ export declare function make<Body, Frame, Event, State>(input: MakeInput<Body, Frame, Event, State>): Route<Body, HttpTransport.HttpPrepared<Frame>>;
139
+ /** @internal Test-only projection of the execution compiler; not exported from package barrels. */
140
+ export declare const compileRequest: (request: LLMRequest) => Effect.Effect<{
141
+ id: string;
142
+ route: string;
143
+ protocol: string;
144
+ model: LanguageModel<{
145
+ readonly [x: string]: {
146
+ readonly [x: string]: unknown;
147
+ };
148
+ }>;
149
+ body: any;
150
+ metadata: {
151
+ transport: string;
152
+ };
153
+ }, AIError, never>;
154
+ export declare function stream(request: LLMRequest, options?: StreamOptions): Stream.Stream<LLMEvent, AIError, Service>;
155
+ export declare function generate(request: LLMRequest, options?: StreamOptions): Effect.Effect<LLMResponse, AIError, Service>;
156
+ export declare const streamRequest: (request: LLMRequest, options?: StreamOptions) => Stream.Stream<{
157
+ readonly type: "step-start";
158
+ readonly index: number;
159
+ } | {
160
+ readonly id: string;
161
+ readonly type: "text-start";
162
+ readonly providerMetadata?: {
163
+ readonly [x: string]: {
164
+ readonly [x: string]: unknown;
165
+ };
166
+ } | undefined;
167
+ } | {
168
+ readonly id: string;
169
+ readonly type: "text-delta";
170
+ readonly text: string;
171
+ readonly providerMetadata?: {
172
+ readonly [x: string]: {
173
+ readonly [x: string]: unknown;
174
+ };
175
+ } | undefined;
176
+ } | {
177
+ readonly id: string;
178
+ readonly type: "text-end";
179
+ readonly providerMetadata?: {
180
+ readonly [x: string]: {
181
+ readonly [x: string]: unknown;
182
+ };
183
+ } | undefined;
184
+ } | {
185
+ readonly id: string;
186
+ readonly type: "reasoning-start";
187
+ readonly providerMetadata?: {
188
+ readonly [x: string]: {
189
+ readonly [x: string]: unknown;
190
+ };
191
+ } | undefined;
192
+ } | {
193
+ readonly id: string;
194
+ readonly type: "reasoning-delta";
195
+ readonly text: string;
196
+ readonly providerMetadata?: {
197
+ readonly [x: string]: {
198
+ readonly [x: string]: unknown;
199
+ };
200
+ } | undefined;
201
+ } | {
202
+ readonly id: string;
203
+ readonly type: "reasoning-end";
204
+ readonly providerMetadata?: {
205
+ readonly [x: string]: {
206
+ readonly [x: string]: unknown;
207
+ };
208
+ } | undefined;
209
+ } | {
210
+ readonly id: string;
211
+ readonly type: "tool-input-start";
212
+ readonly name: string;
213
+ readonly providerMetadata?: {
214
+ readonly [x: string]: {
215
+ readonly [x: string]: unknown;
216
+ };
217
+ } | undefined;
218
+ readonly providerExecuted?: boolean | undefined;
219
+ } | {
220
+ readonly type: "tool-input-delta";
221
+ readonly id: string;
222
+ readonly name: string;
223
+ readonly text: string;
224
+ } | {
225
+ readonly id: string;
226
+ readonly type: "tool-input-end";
227
+ readonly name: string;
228
+ readonly providerMetadata?: {
229
+ readonly [x: string]: {
230
+ readonly [x: string]: unknown;
231
+ };
232
+ } | undefined;
233
+ } | {
234
+ readonly type: "tool-input-error";
235
+ readonly id: string;
236
+ readonly name: string;
237
+ readonly raw: string;
238
+ } | {
239
+ readonly id: string;
240
+ readonly type: "tool-call";
241
+ readonly name: string;
242
+ readonly input: unknown;
243
+ readonly providerMetadata?: {
244
+ readonly [x: string]: {
245
+ readonly [x: string]: unknown;
246
+ };
247
+ } | undefined;
248
+ readonly providerExecuted?: boolean | undefined;
249
+ } | {
250
+ readonly id: string;
251
+ readonly type: "tool-result";
252
+ readonly name: string;
253
+ readonly result: {
254
+ readonly type: "json";
255
+ readonly value: unknown;
256
+ } | {
257
+ readonly type: "text";
258
+ readonly value: unknown;
259
+ } | {
260
+ readonly type: "error";
261
+ readonly value: unknown;
262
+ } | {
263
+ readonly type: "content";
264
+ readonly value: readonly ({
265
+ readonly type: "text";
266
+ readonly text: string;
267
+ } | {
268
+ readonly type: "file";
269
+ readonly uri: string;
270
+ readonly mime: string;
271
+ readonly name?: string | undefined;
272
+ })[];
273
+ };
274
+ readonly output?: {
275
+ readonly structured: unknown;
276
+ readonly content: readonly ({
277
+ readonly type: "text";
278
+ readonly text: string;
279
+ } | {
280
+ readonly type: "file";
281
+ readonly uri: string;
282
+ readonly mime: string;
283
+ readonly name?: string | undefined;
284
+ })[];
285
+ } | undefined;
286
+ readonly providerMetadata?: {
287
+ readonly [x: string]: {
288
+ readonly [x: string]: unknown;
289
+ };
290
+ } | undefined;
291
+ readonly providerExecuted?: boolean | undefined;
292
+ } | {
293
+ readonly id: string;
294
+ readonly type: "tool-error";
295
+ readonly name: string;
296
+ readonly message: string;
297
+ readonly error?: unknown;
298
+ readonly providerMetadata?: {
299
+ readonly [x: string]: {
300
+ readonly [x: string]: unknown;
301
+ };
302
+ } | undefined;
303
+ } | {
304
+ readonly type: "step-finish";
305
+ readonly reason: {
306
+ readonly normalized: "length" | "stop" | "tool-calls" | "content-filter" | "error" | "unknown";
307
+ readonly raw?: string | undefined;
308
+ };
309
+ readonly index: number;
310
+ readonly providerMetadata?: {
311
+ readonly [x: string]: {
312
+ readonly [x: string]: unknown;
313
+ };
314
+ } | undefined;
315
+ readonly usage?: import("../schema/events.js").Usage | undefined;
316
+ } | {
317
+ readonly type: "finish";
318
+ readonly reason: {
319
+ readonly normalized: "length" | "stop" | "tool-calls" | "content-filter" | "error" | "unknown";
320
+ readonly raw?: string | undefined;
321
+ };
322
+ readonly providerMetadata?: {
323
+ readonly [x: string]: {
324
+ readonly [x: string]: unknown;
325
+ };
326
+ } | undefined;
327
+ readonly usage?: import("../schema/events.js").Usage | undefined;
328
+ } | {
329
+ readonly type: "provider-error";
330
+ readonly message: string;
331
+ readonly providerMetadata?: {
332
+ readonly [x: string]: {
333
+ readonly [x: string]: unknown;
334
+ };
335
+ } | undefined;
336
+ readonly classification?: "context-overflow" | "payload-too-large" | undefined;
337
+ }, AIError, Service>;
338
+ export declare const layer: Layer.Layer<Service, never, RequestExecutor.Service>;
339
+ export declare const Route: {
340
+ readonly make: typeof make;
341
+ };
342
+ export declare const LLMClient: {
343
+ readonly Service: typeof Service;
344
+ readonly layer: Layer.Layer<Service, never, RequestExecutor.Service>;
345
+ readonly stream: typeof stream;
346
+ readonly generate: typeof generate;
347
+ };
348
+ export {};
@@ -0,0 +1,214 @@
1
+ import { Cause, Context, Effect, Layer, Schema, Stream } from "effect";
2
+ import { Auth } from "./auth.js";
3
+ import { Endpoint } from "./endpoint.js";
4
+ import { RequestExecutor } from "./executor.js";
5
+ import { Framing } from "./framing.js";
6
+ import { HttpTransport } from "./transport/index.js";
7
+ import { applyCachePolicy } from "../cache-policy.js";
8
+ import * as ProviderShared from "../protocols/shared.js";
9
+ import { AIError, GenerationOptions, HttpOptions, LLMRequest, LLMResponse, LanguageModel, LanguageModelLimits, LLMEvent, InvalidProviderOutputReason, ProviderID, mergeGenerationOptions, mergeHttpOptions, mergeProviderOptions, } from "../schema/index.js";
10
+ const makeRouteLanguageModel = (route, mapped) => {
11
+ const provider = route.provider ?? ("provider" in mapped ? mapped.provider : undefined);
12
+ if (!provider)
13
+ throw new Error(`Route.model(${route.id}) requires a provider`);
14
+ if (!endpointBaseURL(route.endpoint))
15
+ throw new Error(`Route.model(${route.id}) requires an endpoint baseURL — configure it on the route first`);
16
+ return LanguageModel.make({
17
+ ...mapped,
18
+ provider,
19
+ route,
20
+ });
21
+ };
22
+ const mergeRouteDefaults = (base, patch) => {
23
+ const headers = mergeHeaders(base?.headers, patch.headers);
24
+ return {
25
+ ...base,
26
+ ...patch,
27
+ headers,
28
+ limits: patch.limits === undefined ? base?.limits : LanguageModelLimits.make(patch.limits),
29
+ generation: mergeGenerationOptions(generationOptions(base?.generation), generationOptions(patch.generation)),
30
+ providerOptions: mergeProviderOptions(base?.providerOptions, patch.providerOptions),
31
+ http: mergeHttpOptions(base?.http, httpOptions(patch.http), headers === undefined ? undefined : new HttpOptions({ headers })),
32
+ };
33
+ };
34
+ const endpointBaseURL = (endpoint) => typeof endpoint.baseURL === "string" ? endpoint.baseURL : undefined;
35
+ const mergeHeaders = (...items) => {
36
+ const entries = items.flatMap((item) => item === undefined ? [] : Object.entries(item).filter((entry) => entry[1] !== undefined));
37
+ if (entries.length === 0)
38
+ return undefined;
39
+ return Object.fromEntries(entries);
40
+ };
41
+ export const generationOptions = (input) => input === undefined ? undefined : GenerationOptions.make(input);
42
+ export const httpOptions = (input) => {
43
+ if (input === undefined)
44
+ return input;
45
+ return HttpOptions.make(input);
46
+ };
47
+ export class Service extends Context.Service()("@opencode/LLMClient") {
48
+ }
49
+ const resolveRequestOptions = (request) => {
50
+ const routeDefaults = request.model.route.defaults;
51
+ const modelDefaults = request.model.defaults;
52
+ const generation = mergeGenerationOptions(routeDefaults.generation, modelDefaults?.generation, request.generation);
53
+ return LLMRequest.update(request, {
54
+ generation: generation ?? new GenerationOptions({}),
55
+ providerOptions: mergeProviderOptions(routeDefaults.providerOptions, modelDefaults?.providerOptions, request.providerOptions),
56
+ http: mergeHttpOptions(routeDefaults.http, modelDefaults?.http, request.http),
57
+ });
58
+ };
59
+ const streamError = (route, message, cause) => {
60
+ const failed = cause.reasons.find(Cause.isFailReason)?.error;
61
+ if (failed instanceof AIError)
62
+ return failed;
63
+ return ProviderShared.eventError(route, message, Cause.pretty(cause));
64
+ };
65
+ const incompleteStreamError = (route) => new AIError({
66
+ module: "LLMClient",
67
+ method: "stream",
68
+ reason: new InvalidProviderOutputReason({
69
+ classification: "incomplete-stream",
70
+ message: "The provider response ended unexpectedly.",
71
+ route,
72
+ }),
73
+ });
74
+ const requireTerminalEvent = (route) => (events) => Stream.suspend(() => {
75
+ let terminal = false;
76
+ return events.pipe(Stream.mapEffect((event) => {
77
+ if (terminal)
78
+ return Effect.fail(ProviderShared.eventError(route, `Provider emitted ${event.type} after the terminal event`));
79
+ if (LLMEvent.is.finish(event) || LLMEvent.is.providerError(event))
80
+ terminal = true;
81
+ return Effect.succeed(event);
82
+ }), Stream.onEnd(Effect.suspend(() => (terminal ? Effect.void : Effect.fail(incompleteStreamError(route))))));
83
+ });
84
+ function makeFromTransport(input) {
85
+ const protocol = input.protocol;
86
+ const encodeBody = Schema.encodeSync(Schema.fromJsonString(protocol.body.schema));
87
+ const decodeEventEffect = Schema.decodeUnknownEffect(protocol.stream.event);
88
+ const decodeEvent = (route) => (frame) => decodeEventEffect(frame).pipe(Effect.mapError(() => ProviderShared.eventError(input.id, `Invalid ${route} stream event`, typeof frame === "string" ? frame : ProviderShared.encodeJson(frame))));
89
+ const build = (routeInput) => {
90
+ const route = {
91
+ id: routeInput.id,
92
+ provider: routeInput.provider === undefined ? undefined : ProviderID.make(routeInput.provider),
93
+ providerMetadataKey: routeInput.providerMetadataKey,
94
+ protocol: protocol.id,
95
+ endpoint: routeInput.endpoint,
96
+ auth: routeInput.auth ?? Auth.none,
97
+ transport: routeInput.transport,
98
+ defaults: routeInput.defaults ?? {},
99
+ body: protocol.body,
100
+ with: (patch) => {
101
+ const { id, provider, auth, transport, endpoint, ...defaults } = patch;
102
+ return build({
103
+ ...routeInput,
104
+ id: id ?? routeInput.id,
105
+ provider: provider ?? routeInput.provider,
106
+ auth: auth ?? routeInput.auth,
107
+ endpoint: endpoint ? Endpoint.merge(routeInput.endpoint, endpoint) : routeInput.endpoint,
108
+ transport: transport ?? routeInput.transport,
109
+ defaults: mergeRouteDefaults(route.defaults, defaults),
110
+ });
111
+ },
112
+ model: (input) => makeRouteLanguageModel(route, input),
113
+ prepareTransport: (body, request, options) => routeInput.transport.prepare({
114
+ body,
115
+ request,
116
+ endpoint: routeInput.endpoint,
117
+ auth: routeInput.auth ?? Auth.none,
118
+ encodeBody,
119
+ headers: routeInput.headers,
120
+ middleware: options?.http,
121
+ webSocket: options?.webSocket,
122
+ }),
123
+ streamPrepared: (prepared, request, runtime, options) => {
124
+ const route = `${request.model.provider}/${request.model.route.id}`;
125
+ return Stream.unwrap(routeInput.transport.execute(prepared, request, runtime, options).pipe(Effect.map((execution) => {
126
+ const events = execution.frames.pipe(Stream.mapEffect(decodeEvent(route)), protocol.stream.terminal ? Stream.takeUntil(protocol.stream.terminal) : (stream) => stream);
127
+ const stream = events.pipe(Stream.mapAccumEffect(() => protocol.stream.initial(request), protocol.stream.step, protocol.stream.onHalt ? { onHalt: protocol.stream.onHalt } : undefined), Stream.catchCause((cause) => Stream.fail(streamError(route, `Failed to read ${route} stream`, cause))), requireTerminalEvent(route));
128
+ return execution.complete ? stream.pipe(Stream.onEnd(execution.complete)) : stream;
129
+ })));
130
+ },
131
+ };
132
+ return route;
133
+ };
134
+ return build({ ...input, defaults: mergeRouteDefaults(undefined, input.defaults ?? {}) });
135
+ }
136
+ export function make(input) {
137
+ if ("transport" in input)
138
+ return makeFromTransport(input);
139
+ const protocol = input.protocol;
140
+ return makeFromTransport({
141
+ id: input.id,
142
+ provider: input.provider,
143
+ providerMetadataKey: input.providerMetadataKey,
144
+ protocol,
145
+ endpoint: input.endpoint,
146
+ auth: input.auth,
147
+ headers: input.headers,
148
+ transport: HttpTransport.httpJson({ framing: input.framing }),
149
+ defaults: input.defaults,
150
+ });
151
+ }
152
+ const compile = Effect.fn("LLM.compile")(function* (request, options) {
153
+ const resolved = applyCachePolicy(resolveRequestOptions(request));
154
+ const route = resolved.model.route;
155
+ const body = yield* route.body
156
+ .from(resolved)
157
+ .pipe(Effect.flatMap(ProviderShared.validateWith(Schema.decodeUnknownEffect(route.body.schema))));
158
+ const prepared = yield* route.prepareTransport(body, resolved, options);
159
+ return {
160
+ request: resolved,
161
+ route,
162
+ body,
163
+ prepared,
164
+ };
165
+ });
166
+ /** @internal Test-only projection of the execution compiler; not exported from package barrels. */
167
+ export const compileRequest = Effect.fn("LLM.compileRequest")(function* (request) {
168
+ const compiled = yield* compile(request);
169
+ return {
170
+ id: compiled.request.id ?? "request",
171
+ route: compiled.route.id,
172
+ protocol: compiled.route.protocol,
173
+ model: compiled.request.model,
174
+ body: compiled.body,
175
+ metadata: { transport: compiled.route.transport.id },
176
+ };
177
+ });
178
+ const streamRequestWith = (runtime) => (request, options) => Stream.unwrap(Effect.gen(function* () {
179
+ const compiled = yield* compile(request, options);
180
+ return compiled.route.streamPrepared(compiled.prepared, compiled.request, runtime, options);
181
+ }));
182
+ const generateWith = (stream) => Effect.fn("LLM.generate")(function* (request, options) {
183
+ const state = yield* stream(request, options).pipe(Stream.runFold(LLMResponse.empty, LLMResponse.reduce));
184
+ const response = LLMResponse.complete(state);
185
+ if (response)
186
+ return response;
187
+ return yield* incompleteStreamError(`${request.model.provider}/${request.model.route.id}`);
188
+ });
189
+ export function stream(request, options) {
190
+ return Stream.unwrap(Effect.gen(function* () {
191
+ return (yield* Service).stream(request, options);
192
+ }));
193
+ }
194
+ export function generate(request, options) {
195
+ return Effect.gen(function* () {
196
+ return yield* (yield* Service).generate(request, options);
197
+ });
198
+ }
199
+ export const streamRequest = (request, options) => Stream.unwrap(Effect.gen(function* () {
200
+ return (yield* Service).stream(request, options);
201
+ }));
202
+ export const layer = Layer.effect(Service, Effect.gen(function* () {
203
+ const stream = streamRequestWith({
204
+ http: yield* RequestExecutor.Service,
205
+ });
206
+ return Service.of({ stream, generate: generateWith(stream) });
207
+ }));
208
+ export const Route = { make };
209
+ export const LLMClient = {
210
+ Service,
211
+ layer,
212
+ stream,
213
+ generate,
214
+ };
@@ -0,0 +1,28 @@
1
+ import type { LLMRequest } from "../schema/index.js";
2
+ export interface EndpointInput<Body> {
3
+ readonly request: LLMRequest;
4
+ readonly body: Body;
5
+ }
6
+ export type EndpointPart<Body> = string | ((input: EndpointInput<Body>) => string);
7
+ /**
8
+ * Declarative URL construction for one route.
9
+ *
10
+ * `Endpoint` carries URL construction for one route. Routes with a canonical
11
+ * host put `baseURL` here; provider helpers can override it by configuring the
12
+ * route before selecting a model.
13
+ *
14
+ * `path` may be a string or a function of `EndpointInput`, for routes whose
15
+ * URL embeds the model id, region, or another body field (e.g. Bedrock,
16
+ * Gemini).
17
+ */
18
+ export interface Definition<Body> {
19
+ readonly baseURL?: string;
20
+ readonly path: EndpointPart<Body>;
21
+ readonly query?: Record<string, string>;
22
+ }
23
+ export type EndpointPatch<Body> = Partial<Definition<Body>>;
24
+ /** Construct an `Endpoint` from a path string or path function. */
25
+ export declare const path: <Body>(value: EndpointPart<Body>, options?: Omit<Definition<Body>, "path">) => Definition<Body>;
26
+ export declare const merge: <Body>(base: Definition<Body>, patch: EndpointPatch<Body>) => Definition<Body>;
27
+ export declare const render: <Body>(endpoint: Definition<Body>, input: EndpointInput<Body>) => URL;
28
+ export * as Endpoint from "./endpoint.js";
@@ -0,0 +1,21 @@
1
+ import * as ProviderShared from "../protocols/shared.js";
2
+ /** Construct an `Endpoint` from a path string or path function. */
3
+ export const path = (value, options = {}) => ({
4
+ ...options,
5
+ path: value,
6
+ });
7
+ export const merge = (base, patch) => ({
8
+ ...base,
9
+ ...patch,
10
+ baseURL: patch.baseURL ?? base.baseURL,
11
+ path: patch.path ?? base.path,
12
+ query: patch.query === undefined ? base.query : { ...base.query, ...patch.query },
13
+ });
14
+ const renderPart = (part, input) => typeof part === "function" ? part(input) : part;
15
+ export const render = (endpoint, input) => {
16
+ const url = new URL(`${ProviderShared.trimBaseUrl(endpoint.baseURL ?? "")}${renderPart(endpoint.path, input)}`);
17
+ for (const [key, value] of Object.entries(endpoint.query ?? {}))
18
+ url.searchParams.set(key, value);
19
+ return url;
20
+ };
21
+ export * as Endpoint from "./endpoint.js";
@@ -0,0 +1,23 @@
1
+ import { Context, Effect, Layer, Stream } from "effect";
2
+ import { HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
3
+ import { AIError, TransportReason } from "../schema/index.js";
4
+ export interface Interface {
5
+ readonly execute: (request: HttpClientRequest.HttpClientRequest, middleware?: HttpMiddleware) => Effect.Effect<HttpClientResponse.HttpClientResponse, AIError>;
6
+ }
7
+ export type HttpHandler = (request: HttpClientRequest.HttpClientRequest) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error>;
8
+ export type HttpMiddleware = (request: HttpClientRequest.HttpClientRequest, handler: HttpHandler) => Effect.Effect<HttpClientResponse.HttpClientResponse, Error>;
9
+ declare const Service_base: Context.ServiceClass<Service, "@opencode/AI/RequestExecutor", Interface>;
10
+ export declare class Service extends Service_base {
11
+ }
12
+ export declare const classifyHttpFailure: (input: {
13
+ readonly message: string;
14
+ readonly url: string;
15
+ readonly status?: number | undefined;
16
+ readonly code?: string | undefined;
17
+ readonly responseHeaders?: Record<string, string> | undefined;
18
+ readonly responseBody?: string | undefined;
19
+ }) => import("../schema/errors.js").InvalidRequestReason | import("../schema/errors.js").NoRouteReason | import("../schema/errors.js").AuthenticationReason | import("../schema/errors.js").RateLimitReason | import("../schema/errors.js").QuotaExceededReason | import("../schema/errors.js").ContentPolicyReason | import("../schema/errors.js").ProviderInternalReason | TransportReason | import("../schema/errors.js").InvalidProviderOutputReason | import("../schema/errors.js").UnknownProviderReason;
20
+ export declare const stream: (executor: Interface, request: HttpClientRequest.HttpClientRequest, middleware?: HttpMiddleware) => Stream.Stream<Uint8Array, AIError>;
21
+ export declare const layer: Layer.Layer<Service, never, HttpClient.HttpClient>;
22
+ export declare const fetchLayer: Layer.Layer<Service, never, never>;
23
+ export * as RequestExecutor from "./executor.js";