@opencode/ai 2.0.20 → 2.0.22

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 (59) hide show
  1. package/dist/cache-policy.js +22 -3
  2. package/dist/llm.d.ts +4 -0
  3. package/dist/promise.d.ts +8 -0
  4. package/dist/protocols/alibaba-chat.d.ts +20 -10
  5. package/dist/protocols/alibaba-chat.js +2 -1
  6. package/dist/protocols/anthropic-messages.js +14 -12
  7. package/dist/protocols/bedrock-converse.js +30 -1
  8. package/dist/protocols/open-responses.d.ts +4 -0
  9. package/dist/protocols/openai-chat.d.ts +122 -71
  10. package/dist/protocols/openai-chat.js +40 -37
  11. package/dist/protocols/openai-compatible-chat.d.ts +16 -10
  12. package/dist/protocols/openai-responses.js +4 -3
  13. package/dist/protocols/utils/cache.d.ts +5 -0
  14. package/dist/protocols/utils/cache.js +9 -1
  15. package/dist/protocols/utils/tool-stream.d.ts +12 -0
  16. package/dist/protocols/zai-chat.d.ts +20 -10
  17. package/dist/protocols/zai-chat.js +6 -3
  18. package/dist/provider-error.js +24 -6
  19. package/dist/providers/alibaba.d.ts +16 -10
  20. package/dist/providers/amazon-bedrock-mantle.d.ts +16 -10
  21. package/dist/providers/azure.d.ts +16 -10
  22. package/dist/providers/baseten.d.ts +32 -20
  23. package/dist/providers/cerebras.d.ts +32 -20
  24. package/dist/providers/cloudflare-ai-gateway.d.ts +32 -20
  25. package/dist/providers/cloudflare-ai-gateway.js +43 -35
  26. package/dist/providers/cloudflare-workers-ai.d.ts +32 -20
  27. package/dist/providers/deepinfra.d.ts +32 -20
  28. package/dist/providers/deepseek.d.ts +32 -20
  29. package/dist/providers/digitalocean.d.ts +469 -0
  30. package/dist/providers/digitalocean.js +53 -0
  31. package/dist/providers/fireworks.d.ts +32 -20
  32. package/dist/providers/google-vertex-chat.d.ts +16 -10
  33. package/dist/providers/google-vertex-messages.js +1 -1
  34. package/dist/providers/groq.d.ts +36 -20
  35. package/dist/providers/groq.js +1 -1
  36. package/dist/providers/index.d.ts +1 -0
  37. package/dist/providers/index.js +1 -0
  38. package/dist/providers/meta.d.ts +16 -10
  39. package/dist/providers/minimax.d.ts +16 -10
  40. package/dist/providers/moonshot.d.ts +16 -10
  41. package/dist/providers/openai-compatible.d.ts +16 -10
  42. package/dist/providers/openai.d.ts +16 -10
  43. package/dist/providers/openrouter.d.ts +68 -40
  44. package/dist/providers/openrouter.js +1 -13
  45. package/dist/providers/togetherai.d.ts +32 -20
  46. package/dist/providers/xai.d.ts +16 -10
  47. package/dist/providers/zai-coding-plan.d.ts +16 -10
  48. package/dist/providers/zai.d.ts +16 -10
  49. package/dist/route/client.d.ts +4 -0
  50. package/dist/route/executor.js +13 -6
  51. package/dist/route/transport/http.d.ts +2 -1
  52. package/dist/route/transport/http.js +28 -6
  53. package/dist/schema/events.d.ts +176 -0
  54. package/dist/schema/events.js +4 -0
  55. package/dist/schema/options.d.ts +11 -0
  56. package/dist/schema/options.js +15 -2
  57. package/dist/testing.d.ts +32 -0
  58. package/dist/tool-history.js +17 -3
  59. package/package.json +3 -3
@@ -7,13 +7,20 @@ export const authEnvVars = ["CLOUDFLARE_API_TOKEN", "CF_AIG_TOKEN"];
7
7
  export const baseURL = (input) => {
8
8
  if (input.baseURL)
9
9
  return input.baseURL;
10
- if (!input.accountId)
11
- throw new ProviderConfigurationError({
12
- provider: id,
13
- message: "CloudflareAIGateway.configure requires accountId unless baseURL is supplied",
14
- });
15
- return `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(input.accountId)}/ai/v1`;
10
+ return `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(requireAccountId(input))}/ai/v1`;
16
11
  };
12
+ // Cloudflare's REST API rejects parts of the Anthropic Messages and OpenAI Responses request shapes, such as
13
+ // system prompt blocks and `minimal` reasoning effort, so these models use the provider-native gateway endpoints.
14
+ const passthroughURL = (input, provider) => `https://gateway.ai.cloudflare.com/v1/${encodeURIComponent(requireAccountId(input))}/${encodeURIComponent(gatewayId(input))}/${provider}`;
15
+ const requireAccountId = (input) => {
16
+ if (input.accountId)
17
+ return input.accountId;
18
+ throw new ProviderConfigurationError({
19
+ provider: id,
20
+ message: "CloudflareAIGateway.configure requires accountId unless baseURL is supplied",
21
+ });
22
+ };
23
+ const gatewayId = (input) => input.gatewayId?.trim() || "default";
17
24
  export const responsesRoute = OpenAIResponses.route.with({
18
25
  id: "cloudflare-ai-gateway-responses",
19
26
  provider: id,
@@ -30,16 +37,10 @@ export const route = OpenAIChat.route.with({
30
37
  endpoint: { baseURL: undefined },
31
38
  });
32
39
  export const routes = [responsesRoute, messagesRoute, route];
33
- const auth = (input) => {
34
- if ("auth" in input && input.auth)
35
- return input.auth;
36
- return Auth.optional(input.gatewayApiKey ?? ("apiKey" in input ? input.apiKey : undefined), "apiKey")
37
- .orElse(Auth.config(authEnvVars[0]))
38
- .orElse(Auth.config(authEnvVars[1]))
39
- .bearer();
40
- };
40
+ const credential = (input) => Auth.optional(input.gatewayApiKey ?? ("apiKey" in input ? input.apiKey : undefined), "apiKey")
41
+ .orElse(Auth.config(authEnvVars[0]))
42
+ .orElse(Auth.config(authEnvVars[1]));
41
43
  const headers = (input) => ({
42
- ...(input.gatewayId === undefined ? {} : { "cf-aig-gateway-id": input.gatewayId.trim() || "default" }),
43
44
  ...(input.metadata === undefined
44
45
  ? {}
45
46
  : { "cf-aig-metadata": Schema.encodeSync(Schema.fromJsonString(Schema.Unknown))(input.metadata) }),
@@ -49,34 +50,41 @@ const headers = (input) => ({
49
50
  ...(input.collectLog === undefined ? {} : { "cf-aig-collect-log": String(input.collectLog) }),
50
51
  ...input.headers,
51
52
  });
52
- const modelID = (input) => {
53
- const value = String(input);
54
- if (value.startsWith("workers-ai/"))
55
- return value.slice("workers-ai/".length);
56
- if (value.startsWith("anthropic/"))
57
- return `anthropic/${value.slice("anthropic/".length).replaceAll(".", "-")}`;
58
- return value;
59
- };
60
53
  export const configure = (input) => {
61
- const defaults = {
54
+ const custom = "auth" in input && input.auth ? input.auth : undefined;
55
+ const rest = {
62
56
  endpoint: { baseURL: baseURL(input) },
63
- auth: auth(input),
64
- headers: headers(input),
57
+ auth: custom ?? credential(input).bearer(),
58
+ headers: { "cf-aig-gateway-id": gatewayId(input), ...headers(input) },
65
59
  http: input.http,
66
60
  providerOptions: input.providerOptions,
67
61
  };
68
- const responses = responsesRoute.with(defaults);
69
- const messages = messagesRoute.with(defaults);
70
- const chat = route.with(defaults);
62
+ // A custom baseURL stands in for the REST API, so every model keeps using it with gateway model IDs.
63
+ const native = input.baseURL === undefined;
64
+ const passthrough = (provider) => native
65
+ ? {
66
+ ...rest,
67
+ endpoint: { baseURL: passthroughURL(input, provider) },
68
+ auth: custom ?? Auth.bearerHeader("cf-aig-authorization", credential(input)),
69
+ headers: headers(input),
70
+ }
71
+ : rest;
72
+ const responses = responsesRoute.with(passthrough("openai"));
73
+ const messages = messagesRoute.with(passthrough("anthropic/v1"));
74
+ const chat = route.with(rest);
71
75
  return {
72
76
  id,
73
77
  model: (input) => {
74
- const wire = modelID(input);
75
- if (String(input).startsWith("openai/"))
76
- return responses.model({ id: wire });
77
- if (String(input).startsWith("anthropic/"))
78
- return messages.model({ id: wire });
79
- return chat.model({ id: wire });
78
+ const value = String(input);
79
+ if (value.startsWith("openai/"))
80
+ return responses.model({ id: native ? value.slice("openai/".length) : value });
81
+ if (value.startsWith("anthropic/"))
82
+ return messages.model({
83
+ id: native ? value.slice("anthropic/".length).replaceAll(".", "-") : value,
84
+ });
85
+ if (value.startsWith("workers-ai/"))
86
+ return chat.model({ id: value.slice("workers-ai/".length) });
87
+ return chat.model({ id: value });
80
88
  },
81
89
  configure,
82
90
  };
@@ -62,15 +62,18 @@ export declare const route: Route<{
62
62
  })[];
63
63
  } | {
64
64
  readonly [x: string]: unknown;
65
- readonly content: string | null;
65
+ readonly content: string | readonly {
66
+ readonly type: "text";
67
+ readonly text: string;
68
+ readonly cache_control?: {
69
+ readonly type: "ephemeral";
70
+ readonly ttl?: string | undefined;
71
+ } | undefined;
72
+ }[] | null;
66
73
  readonly role: "assistant";
67
74
  readonly reasoning?: string | undefined;
68
75
  readonly reasoning_content?: string | undefined;
69
76
  readonly reasoning_text?: string | undefined;
70
- readonly cache_control?: {
71
- readonly type: "ephemeral";
72
- readonly ttl?: string | undefined;
73
- } | undefined;
74
77
  readonly tool_calls?: readonly {
75
78
  readonly function: {
76
79
  readonly name: string;
@@ -86,13 +89,16 @@ export declare const route: Route<{
86
89
  }[] | undefined;
87
90
  readonly reasoning_details?: unknown;
88
91
  } | {
89
- readonly content: string;
90
92
  readonly role: "tool";
91
93
  readonly tool_call_id: string;
92
- readonly cache_control?: {
93
- readonly type: "ephemeral";
94
- readonly ttl?: string | undefined;
95
- } | undefined;
94
+ readonly content: string | readonly {
95
+ readonly type: "text";
96
+ readonly text: string;
97
+ readonly cache_control?: {
98
+ readonly type: "ephemeral";
99
+ readonly ttl?: string | undefined;
100
+ } | undefined;
101
+ }[];
96
102
  })[];
97
103
  readonly stream: true;
98
104
  readonly max_completion_tokens?: number | undefined;
@@ -178,15 +184,18 @@ export declare const routes: Route<{
178
184
  })[];
179
185
  } | {
180
186
  readonly [x: string]: unknown;
181
- readonly content: string | null;
187
+ readonly content: string | readonly {
188
+ readonly type: "text";
189
+ readonly text: string;
190
+ readonly cache_control?: {
191
+ readonly type: "ephemeral";
192
+ readonly ttl?: string | undefined;
193
+ } | undefined;
194
+ }[] | null;
182
195
  readonly role: "assistant";
183
196
  readonly reasoning?: string | undefined;
184
197
  readonly reasoning_content?: string | undefined;
185
198
  readonly reasoning_text?: string | undefined;
186
- readonly cache_control?: {
187
- readonly type: "ephemeral";
188
- readonly ttl?: string | undefined;
189
- } | undefined;
190
199
  readonly tool_calls?: readonly {
191
200
  readonly function: {
192
201
  readonly name: string;
@@ -202,13 +211,16 @@ export declare const routes: Route<{
202
211
  }[] | undefined;
203
212
  readonly reasoning_details?: unknown;
204
213
  } | {
205
- readonly content: string;
206
214
  readonly role: "tool";
207
215
  readonly tool_call_id: string;
208
- readonly cache_control?: {
209
- readonly type: "ephemeral";
210
- readonly ttl?: string | undefined;
211
- } | undefined;
216
+ readonly content: string | readonly {
217
+ readonly type: "text";
218
+ readonly text: string;
219
+ readonly cache_control?: {
220
+ readonly type: "ephemeral";
221
+ readonly ttl?: string | undefined;
222
+ } | undefined;
223
+ }[];
212
224
  })[];
213
225
  readonly stream: true;
214
226
  readonly max_completion_tokens?: number | undefined;
@@ -58,15 +58,18 @@ export declare const route: Route<{
58
58
  })[];
59
59
  } | {
60
60
  readonly [x: string]: unknown;
61
- readonly content: string | null;
61
+ readonly content: string | readonly {
62
+ readonly type: "text";
63
+ readonly text: string;
64
+ readonly cache_control?: {
65
+ readonly type: "ephemeral";
66
+ readonly ttl?: string | undefined;
67
+ } | undefined;
68
+ }[] | null;
62
69
  readonly role: "assistant";
63
70
  readonly reasoning?: string | undefined;
64
71
  readonly reasoning_content?: string | undefined;
65
72
  readonly reasoning_text?: string | undefined;
66
- readonly cache_control?: {
67
- readonly type: "ephemeral";
68
- readonly ttl?: string | undefined;
69
- } | undefined;
70
73
  readonly tool_calls?: readonly {
71
74
  readonly function: {
72
75
  readonly name: string;
@@ -82,13 +85,16 @@ export declare const route: Route<{
82
85
  }[] | undefined;
83
86
  readonly reasoning_details?: unknown;
84
87
  } | {
85
- readonly content: string;
86
88
  readonly role: "tool";
87
89
  readonly tool_call_id: string;
88
- readonly cache_control?: {
89
- readonly type: "ephemeral";
90
- readonly ttl?: string | undefined;
91
- } | undefined;
90
+ readonly content: string | readonly {
91
+ readonly type: "text";
92
+ readonly text: string;
93
+ readonly cache_control?: {
94
+ readonly type: "ephemeral";
95
+ readonly ttl?: string | undefined;
96
+ } | undefined;
97
+ }[];
92
98
  })[];
93
99
  readonly stream: true;
94
100
  readonly max_completion_tokens?: number | undefined;
@@ -174,15 +180,18 @@ export declare const routes: Route<{
174
180
  })[];
175
181
  } | {
176
182
  readonly [x: string]: unknown;
177
- readonly content: string | null;
183
+ readonly content: string | readonly {
184
+ readonly type: "text";
185
+ readonly text: string;
186
+ readonly cache_control?: {
187
+ readonly type: "ephemeral";
188
+ readonly ttl?: string | undefined;
189
+ } | undefined;
190
+ }[] | null;
178
191
  readonly role: "assistant";
179
192
  readonly reasoning?: string | undefined;
180
193
  readonly reasoning_content?: string | undefined;
181
194
  readonly reasoning_text?: string | undefined;
182
- readonly cache_control?: {
183
- readonly type: "ephemeral";
184
- readonly ttl?: string | undefined;
185
- } | undefined;
186
195
  readonly tool_calls?: readonly {
187
196
  readonly function: {
188
197
  readonly name: string;
@@ -198,13 +207,16 @@ export declare const routes: Route<{
198
207
  }[] | undefined;
199
208
  readonly reasoning_details?: unknown;
200
209
  } | {
201
- readonly content: string;
202
210
  readonly role: "tool";
203
211
  readonly tool_call_id: string;
204
- readonly cache_control?: {
205
- readonly type: "ephemeral";
206
- readonly ttl?: string | undefined;
207
- } | undefined;
212
+ readonly content: string | readonly {
213
+ readonly type: "text";
214
+ readonly text: string;
215
+ readonly cache_control?: {
216
+ readonly type: "ephemeral";
217
+ readonly ttl?: string | undefined;
218
+ } | undefined;
219
+ }[];
208
220
  })[];
209
221
  readonly stream: true;
210
222
  readonly max_completion_tokens?: number | undefined;
@@ -58,15 +58,18 @@ export declare const route: Route<{
58
58
  })[];
59
59
  } | {
60
60
  readonly [x: string]: unknown;
61
- readonly content: string | null;
61
+ readonly content: string | readonly {
62
+ readonly type: "text";
63
+ readonly text: string;
64
+ readonly cache_control?: {
65
+ readonly type: "ephemeral";
66
+ readonly ttl?: string | undefined;
67
+ } | undefined;
68
+ }[] | null;
62
69
  readonly role: "assistant";
63
70
  readonly reasoning?: string | undefined;
64
71
  readonly reasoning_content?: string | undefined;
65
72
  readonly reasoning_text?: string | undefined;
66
- readonly cache_control?: {
67
- readonly type: "ephemeral";
68
- readonly ttl?: string | undefined;
69
- } | undefined;
70
73
  readonly tool_calls?: readonly {
71
74
  readonly function: {
72
75
  readonly name: string;
@@ -82,13 +85,16 @@ export declare const route: Route<{
82
85
  }[] | undefined;
83
86
  readonly reasoning_details?: unknown;
84
87
  } | {
85
- readonly content: string;
86
88
  readonly role: "tool";
87
89
  readonly tool_call_id: string;
88
- readonly cache_control?: {
89
- readonly type: "ephemeral";
90
- readonly ttl?: string | undefined;
91
- } | undefined;
90
+ readonly content: string | readonly {
91
+ readonly type: "text";
92
+ readonly text: string;
93
+ readonly cache_control?: {
94
+ readonly type: "ephemeral";
95
+ readonly ttl?: string | undefined;
96
+ } | undefined;
97
+ }[];
92
98
  })[];
93
99
  readonly stream: true;
94
100
  readonly max_completion_tokens?: number | undefined;
@@ -174,15 +180,18 @@ export declare const routes: Route<{
174
180
  })[];
175
181
  } | {
176
182
  readonly [x: string]: unknown;
177
- readonly content: string | null;
183
+ readonly content: string | readonly {
184
+ readonly type: "text";
185
+ readonly text: string;
186
+ readonly cache_control?: {
187
+ readonly type: "ephemeral";
188
+ readonly ttl?: string | undefined;
189
+ } | undefined;
190
+ }[] | null;
178
191
  readonly role: "assistant";
179
192
  readonly reasoning?: string | undefined;
180
193
  readonly reasoning_content?: string | undefined;
181
194
  readonly reasoning_text?: string | undefined;
182
- readonly cache_control?: {
183
- readonly type: "ephemeral";
184
- readonly ttl?: string | undefined;
185
- } | undefined;
186
195
  readonly tool_calls?: readonly {
187
196
  readonly function: {
188
197
  readonly name: string;
@@ -198,13 +207,16 @@ export declare const routes: Route<{
198
207
  }[] | undefined;
199
208
  readonly reasoning_details?: unknown;
200
209
  } | {
201
- readonly content: string;
202
210
  readonly role: "tool";
203
211
  readonly tool_call_id: string;
204
- readonly cache_control?: {
205
- readonly type: "ephemeral";
206
- readonly ttl?: string | undefined;
207
- } | undefined;
212
+ readonly content: string | readonly {
213
+ readonly type: "text";
214
+ readonly text: string;
215
+ readonly cache_control?: {
216
+ readonly type: "ephemeral";
217
+ readonly ttl?: string | undefined;
218
+ } | undefined;
219
+ }[];
208
220
  })[];
209
221
  readonly stream: true;
210
222
  readonly max_completion_tokens?: number | undefined;