@opencode/ai 0.0.0-dev-19364 → 0.0.0-dev-19366

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.
package/README.md CHANGED
@@ -29,6 +29,78 @@ await Effect.runPromise(program.pipe(Effect.provide(llmLayer)))
29
29
 
30
30
  Run `LLMClient.stream(request)` instead of `generate` when you want incremental `LLMEvent`s. The event stream is provider-neutral — same shape across OpenAI Chat, OpenAI Responses, Anthropic Messages, Gemini, Bedrock Converse, and any OpenAI-compatible deployment.
31
31
 
32
+ ## Alibaba Cloud Model Studio
33
+
34
+ `Alibaba` provides standard Model Studio inference. Configure a region explicitly, then select
35
+ Chat Completions (`.model` or `.chat`), Anthropic-compatible Messages (`.messages`), or OpenAI-compatible
36
+ Responses (`.responses`). These routes use HTTP/SSE.
37
+
38
+ ```ts
39
+ import { LLM } from "@opencode/ai"
40
+ import { Alibaba } from "@opencode/ai/providers"
41
+
42
+ const alibaba = Alibaba.configure({
43
+ region: "ap-southeast-1", // Singapore
44
+ apiKey: process.env.DASHSCOPE_API_KEY,
45
+ // workspaceID: "llm-your-workspace", // use a workspace-dedicated endpoint
46
+ })
47
+
48
+ const request = LLM.request({
49
+ model: alibaba.model("qwen3.8-max"),
50
+ prompt: "Explain this design.",
51
+ providerOptions: { reasoningEffort: "medium" },
52
+ })
53
+ ```
54
+
55
+ ### Regions and credentials
56
+
57
+ | Region | `region` | Shared host when `workspaceID` is omitted |
58
+ | ------------------- | ---------------- | ----------------------------------------- |
59
+ | Singapore | `ap-southeast-1` | `dashscope-intl.aliyuncs.com` |
60
+ | China (Beijing) | `cn-beijing` | `dashscope.aliyuncs.com` |
61
+ | China (Hong Kong) | `cn-hongkong` | `cn-hongkong.dashscope.aliyuncs.com` |
62
+ | US (Virginia) | `us-east-1` | `dashscope-us.aliyuncs.com` |
63
+ | Germany (Frankfurt) | `eu-central-1` | Supply `workspaceID` or `baseURL` |
64
+ | Japan (Tokyo) | `ap-northeast-1` | Supply `workspaceID` or `baseURL` |
65
+
66
+ With `workspaceID`, the host is `{workspaceID}.{region}.maas.aliyuncs.com`. A complete `baseURL`
67
+ overrides regional setup, including the API prefix: `/compatible-mode/v1` for Chat/Responses,
68
+ or `/apps/anthropic/v1` for Messages. The selector appends its operation path.
69
+
70
+ Keys and model availability are region-specific. Auth resolves from explicit `auth` or `apiKey`,
71
+ then `DASHSCOPE_API_KEY`, then `ALIBABA_API_KEY`.
72
+
73
+ The access region and inference scope differ: Virginia's `-us` model IDs request US-only inference;
74
+ some regions select scope through their workspace. Model IDs pass through unchanged.
75
+ Alibaba's [regional guide](https://www.alibabacloud.com/help/en/model-studio/regions) and
76
+ [base URL table](https://www.alibabacloud.com/help/en/model-studio/base-url) disagree about Virginia's
77
+ shared host; the entry above follows the base URL table. Dedicated hosts can be copied from the console.
78
+
79
+ ### Native options
80
+
81
+ - **Chat:** `reasoningEffort` → `reasoning_effort`, `enableThinking` → `enable_thinking`,
82
+ `thinkingBudget` → `thinking_budget`, and `preserveThinking` → `preserve_thinking`.
83
+ Replay complete `response.message` values to retain `reasoning_content` separately from answer text.
84
+ Qwen 3.8 defaults to preserving thinking; older models have different defaults.
85
+ Additional options include `toolStream`, `parallelToolCalls`, `repetitionPenalty`, `responseFormat`,
86
+ `enableSearch`, and native `searchOptions`. `generation.topK` lowers to `top_k`.
87
+ `clearThinking` is a hosted GLM control, and `thinking.type` is available for hosted MiniMax models.
88
+ - **Messages:** `effort` → `output_config.effort`. `thinking.type` accepts enabled/disabled with an
89
+ optional `budgetTokens` (or native `budget_tokens`). `outputConfig.format` accepts a JSON schema.
90
+ Model Studio's empty thinking signatures are accepted; supplied signatures are replayed unchanged.
91
+ - **Responses:** `reasoningEffort` → `reasoning.effort`, plus `enableThinking`, `store`,
92
+ `previousResponseId`, and `conversation`. Omitted `store` retains the API's default (`true`);
93
+ set it to `false` for client-managed history. `previousResponseId` requires a stored response.
94
+ Hosted tools are `Alibaba.webSearch()`, `Alibaba.webExtractor()`, and `Alibaba.codeInterpreter()`.
95
+ Web extraction is used together with web search. Hosted calls/results carry `providerExecuted: true`.
96
+
97
+ Omitted options preserve provider defaults. Effort values pass through unchanged and accept future
98
+ strings. Qwen 3.8 Chat rejects requests combining a thinking budget with effort.
99
+
100
+ Package entrypoints are `@opencode/ai/providers/alibaba`, `alibaba/chat`, `alibaba/messages`,
101
+ and `alibaba/responses`. Live recordings cover all three APIs in Singapore; regional URL construction
102
+ is unit-tested for all six regions.
103
+
32
104
  ## Z.AI
33
105
 
34
106
  `ZAI` uses the standard API. Chat Completions is the default language-model API;
@@ -0,0 +1,225 @@
1
+ import { Schema } from "effect";
2
+ import { Protocol } from "../route/protocol.js";
3
+ import { OpenAIChat } from "./openai-chat.js";
4
+ import { OpenResponsesOptions } from "./utils/open-responses-options.js";
5
+ export type ReasoningEffort = OpenResponsesOptions.ReasoningEffort;
6
+ declare const Options: Schema.Struct<{
7
+ readonly reasoningEffort: Schema.optional<Schema.declare<OpenResponsesOptions.ReasoningEffort, OpenResponsesOptions.ReasoningEffort>>;
8
+ readonly enableThinking: Schema.optional<Schema.Boolean>;
9
+ readonly thinkingBudget: Schema.optional<Schema.Int>;
10
+ readonly preserveThinking: Schema.optional<Schema.Boolean>;
11
+ readonly clearThinking: Schema.optional<Schema.Boolean>;
12
+ readonly thinking: Schema.optional<Schema.Struct<{
13
+ readonly type: Schema.declare<"disabled" | (string & {}) | "adaptive", "disabled" | (string & {}) | "adaptive">;
14
+ }>>;
15
+ readonly toolStream: Schema.optional<Schema.Boolean>;
16
+ readonly parallelToolCalls: Schema.optional<Schema.Boolean>;
17
+ readonly repetitionPenalty: Schema.optional<Schema.Number>;
18
+ readonly responseFormat: Schema.optional<Schema.Struct<{
19
+ readonly type: Schema.declare<(string & {}) | "text" | "json_schema" | "json_object", (string & {}) | "text" | "json_schema" | "json_object">;
20
+ readonly json_schema: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
21
+ }>>;
22
+ readonly enableSearch: Schema.optional<Schema.Boolean>;
23
+ readonly searchOptions: Schema.optional<Schema.Struct<{
24
+ readonly forced_search: Schema.optional<Schema.Boolean>;
25
+ readonly search_strategy: Schema.optional<Schema.declare<(string & {}) | "agent" | "max" | "turbo" | "agent_max", (string & {}) | "agent" | "max" | "turbo" | "agent_max">>;
26
+ readonly enable_search_extension: Schema.optional<Schema.Boolean>;
27
+ }>>;
28
+ }>;
29
+ export type OptionsInput = typeof Options.Type;
30
+ export declare const compatibility: {
31
+ maxTokensField: "max_completion_tokens";
32
+ supportsStore: false;
33
+ supportsStrictMode: false;
34
+ reasoningField: string;
35
+ zaiToolStream: false;
36
+ };
37
+ export declare const protocol: Protocol<{
38
+ readonly model: string;
39
+ readonly messages: readonly ({
40
+ readonly role: "system";
41
+ readonly content: string | readonly ({
42
+ readonly type: "text";
43
+ readonly text: string;
44
+ readonly cache_control?: {
45
+ readonly type: "ephemeral";
46
+ readonly ttl?: string | undefined;
47
+ } | undefined;
48
+ } | {
49
+ readonly type: "image_url";
50
+ readonly image_url: {
51
+ readonly url: string;
52
+ };
53
+ })[];
54
+ } | {
55
+ readonly role: "user";
56
+ readonly content: string | readonly ({
57
+ readonly type: "text";
58
+ readonly text: string;
59
+ readonly cache_control?: {
60
+ readonly type: "ephemeral";
61
+ readonly ttl?: string | undefined;
62
+ } | undefined;
63
+ } | {
64
+ readonly type: "image_url";
65
+ readonly image_url: {
66
+ readonly url: string;
67
+ };
68
+ })[];
69
+ } | {
70
+ readonly [x: string]: unknown;
71
+ readonly content: string | null;
72
+ readonly role: "assistant";
73
+ readonly reasoning?: string | undefined;
74
+ readonly reasoning_content?: string | undefined;
75
+ readonly reasoning_text?: string | undefined;
76
+ readonly cache_control?: {
77
+ readonly type: "ephemeral";
78
+ readonly ttl?: string | undefined;
79
+ } | undefined;
80
+ readonly tool_calls?: readonly {
81
+ readonly id: string;
82
+ readonly type: "function";
83
+ readonly function: {
84
+ readonly name: string;
85
+ readonly arguments: string;
86
+ };
87
+ }[] | undefined;
88
+ readonly reasoning_details?: unknown;
89
+ } | {
90
+ readonly content: string;
91
+ readonly role: "tool";
92
+ readonly tool_call_id: string;
93
+ readonly cache_control?: {
94
+ readonly type: "ephemeral";
95
+ readonly ttl?: string | undefined;
96
+ } | undefined;
97
+ })[];
98
+ readonly stream: true;
99
+ readonly max_completion_tokens?: number | undefined;
100
+ readonly max_tokens?: number | undefined;
101
+ readonly tools?: readonly {
102
+ readonly function: {
103
+ readonly description: string;
104
+ readonly name: string;
105
+ readonly parameters: {
106
+ readonly [x: string]: unknown;
107
+ };
108
+ readonly strict?: boolean | undefined;
109
+ };
110
+ readonly type: "function";
111
+ readonly cache_control?: {
112
+ readonly type: "ephemeral";
113
+ readonly ttl?: string | undefined;
114
+ } | undefined;
115
+ }[] | undefined;
116
+ readonly stop?: readonly string[] | undefined;
117
+ readonly temperature?: number | undefined;
118
+ readonly seed?: number | undefined;
119
+ readonly thinking?: {
120
+ readonly type: "disabled" | (string & {}) | "adaptive";
121
+ } | undefined;
122
+ readonly tool_choice?: "required" | "auto" | "none" | {
123
+ readonly type: "function";
124
+ readonly function: {
125
+ readonly name: string;
126
+ };
127
+ } | undefined;
128
+ readonly top_p?: number | undefined;
129
+ readonly top_k?: number | undefined;
130
+ readonly frequency_penalty?: number | undefined;
131
+ readonly presence_penalty?: number | undefined;
132
+ readonly prompt_cache_key?: string | undefined;
133
+ readonly parallel_tool_calls?: boolean | undefined;
134
+ readonly reasoning_effort?: OpenResponsesOptions.ReasoningEffort | undefined;
135
+ readonly store?: boolean | undefined;
136
+ readonly stream_options?: {
137
+ readonly include_usage: boolean;
138
+ } | undefined;
139
+ readonly tool_stream?: boolean | undefined;
140
+ readonly enable_thinking?: boolean | undefined;
141
+ readonly thinking_budget?: number | undefined;
142
+ readonly preserve_thinking?: boolean | undefined;
143
+ readonly clear_thinking?: boolean | undefined;
144
+ readonly repetition_penalty?: number | undefined;
145
+ readonly response_format?: {
146
+ readonly type: (string & {}) | "text" | "json_schema" | "json_object";
147
+ readonly json_schema?: {
148
+ readonly [x: string]: unknown;
149
+ } | undefined;
150
+ } | undefined;
151
+ readonly enable_search?: boolean | undefined;
152
+ readonly search_options?: {
153
+ readonly forced_search?: boolean | undefined;
154
+ readonly search_strategy?: (string & {}) | "agent" | "max" | "turbo" | "agent_max" | undefined;
155
+ readonly enable_search_extension?: boolean | undefined;
156
+ } | undefined;
157
+ }, string, "[DONE]" | {
158
+ readonly [x: string]: unknown;
159
+ readonly error?: {
160
+ readonly [x: string]: unknown;
161
+ readonly message: string;
162
+ readonly code?: string | number | null | undefined;
163
+ } | null | undefined;
164
+ readonly usage?: {
165
+ readonly [x: string]: unknown;
166
+ readonly cached_tokens?: number | null | undefined;
167
+ readonly prompt_tokens?: number | null | undefined;
168
+ readonly completion_tokens?: number | null | undefined;
169
+ readonly total_tokens?: number | null | undefined;
170
+ readonly prompt_tokens_details?: {
171
+ readonly [x: string]: unknown;
172
+ readonly cached_tokens?: number | null | undefined;
173
+ readonly cache_write_tokens?: number | null | undefined;
174
+ } | null | undefined;
175
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
176
+ readonly completion_tokens_details?: {
177
+ readonly [x: string]: unknown;
178
+ readonly reasoning_tokens?: number | null | undefined;
179
+ readonly accepted_prediction_tokens?: number | null | undefined;
180
+ readonly rejected_prediction_tokens?: number | null | undefined;
181
+ } | null | undefined;
182
+ } | null | undefined;
183
+ readonly choices?: readonly {
184
+ readonly [x: string]: unknown;
185
+ readonly delta?: {
186
+ readonly [x: string]: unknown;
187
+ readonly reasoning?: string | null | undefined;
188
+ readonly reasoning_content?: string | null | undefined;
189
+ readonly reasoning_text?: string | null | undefined;
190
+ readonly content?: string | null | undefined;
191
+ readonly refusal?: string | null | undefined;
192
+ readonly tool_calls?: readonly {
193
+ readonly function?: {
194
+ readonly name?: string | null | undefined;
195
+ readonly arguments?: string | null | undefined;
196
+ } | null | undefined;
197
+ readonly id?: string | null | undefined;
198
+ readonly index?: number | null | undefined;
199
+ }[] | null | undefined;
200
+ readonly reasoning_details?: unknown;
201
+ } | null | undefined;
202
+ readonly usage?: {
203
+ readonly [x: string]: unknown;
204
+ readonly cached_tokens?: number | null | undefined;
205
+ readonly prompt_tokens?: number | null | undefined;
206
+ readonly completion_tokens?: number | null | undefined;
207
+ readonly total_tokens?: number | null | undefined;
208
+ readonly prompt_tokens_details?: {
209
+ readonly [x: string]: unknown;
210
+ readonly cached_tokens?: number | null | undefined;
211
+ readonly cache_write_tokens?: number | null | undefined;
212
+ } | null | undefined;
213
+ readonly prompt_cache_hit_tokens?: number | null | undefined;
214
+ readonly completion_tokens_details?: {
215
+ readonly [x: string]: unknown;
216
+ readonly reasoning_tokens?: number | null | undefined;
217
+ readonly accepted_prediction_tokens?: number | null | undefined;
218
+ readonly rejected_prediction_tokens?: number | null | undefined;
219
+ } | null | undefined;
220
+ } | null | undefined;
221
+ readonly finish_reason?: string | null | undefined;
222
+ readonly native_finish_reason?: string | null | undefined;
223
+ }[] | null | undefined;
224
+ }, OpenAIChat.ParserState>;
225
+ export * as AlibabaChat from "./alibaba-chat.js";
@@ -0,0 +1,75 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { Protocol } from "../route/protocol.js";
3
+ import { OpenAIChat } from "./openai-chat.js";
4
+ import { JsonObject, ProviderShared } from "./shared.js";
5
+ import { OpenResponsesOptions } from "./utils/open-responses-options.js";
6
+ const Options = Schema.Struct({
7
+ reasoningEffort: OpenResponsesOptions.Options.fields.reasoningEffort,
8
+ enableThinking: Schema.optional(Schema.Boolean),
9
+ thinkingBudget: Schema.optional(Schema.Int),
10
+ preserveThinking: Schema.optional(Schema.Boolean),
11
+ clearThinking: Schema.optional(Schema.Boolean),
12
+ thinking: Schema.optional(Schema.Struct({
13
+ type: Schema.declare(Schema.is(Schema.String)),
14
+ })),
15
+ toolStream: Schema.optional(Schema.Boolean),
16
+ parallelToolCalls: OpenResponsesOptions.Options.fields.parallelToolCalls,
17
+ repetitionPenalty: Schema.optional(Schema.Number),
18
+ responseFormat: Schema.optional(Schema.Struct({
19
+ type: Schema.declare(Schema.is(Schema.String)),
20
+ json_schema: Schema.optional(JsonObject),
21
+ })),
22
+ enableSearch: Schema.optional(Schema.Boolean),
23
+ searchOptions: Schema.optional(Schema.Struct({
24
+ forced_search: Schema.optional(Schema.Boolean),
25
+ search_strategy: Schema.optional(Schema.declare(Schema.is(Schema.String))),
26
+ enable_search_extension: Schema.optional(Schema.Boolean),
27
+ })),
28
+ });
29
+ export const compatibility = {
30
+ maxTokensField: "max_completion_tokens",
31
+ supportsStore: false,
32
+ supportsStrictMode: false,
33
+ reasoningField: "reasoning_content",
34
+ zaiToolStream: false,
35
+ };
36
+ export const protocol = Protocol.make({
37
+ id: "alibaba-chat",
38
+ body: {
39
+ schema: Schema.Struct({
40
+ ...OpenAIChat.bodyFields,
41
+ enable_thinking: Options.fields.enableThinking,
42
+ thinking_budget: Options.fields.thinkingBudget,
43
+ preserve_thinking: Options.fields.preserveThinking,
44
+ clear_thinking: Options.fields.clearThinking,
45
+ thinking: Options.fields.thinking,
46
+ parallel_tool_calls: Options.fields.parallelToolCalls,
47
+ repetition_penalty: Options.fields.repetitionPenalty,
48
+ top_k: Schema.optional(Schema.Int),
49
+ response_format: Options.fields.responseFormat,
50
+ enable_search: Options.fields.enableSearch,
51
+ search_options: Options.fields.searchOptions,
52
+ }),
53
+ from: Effect.fn("AlibabaChat.fromRequest")(function* (req) {
54
+ const opts = yield* ProviderShared.validateWith(Schema.decodeUnknownEffect(Options))(req.providerOptions ?? {});
55
+ return {
56
+ ...(yield* OpenAIChat.protocol.body.from(req)),
57
+ enable_thinking: opts.enableThinking,
58
+ thinking_budget: opts.thinkingBudget,
59
+ preserve_thinking: opts.preserveThinking,
60
+ clear_thinking: opts.clearThinking,
61
+ thinking: opts.thinking,
62
+ tool_stream: opts.toolStream,
63
+ parallel_tool_calls: opts.parallelToolCalls ??
64
+ (req.toolChoice?.disableParallelToolUse === undefined ? undefined : !req.toolChoice.disableParallelToolUse),
65
+ repetition_penalty: opts.repetitionPenalty,
66
+ top_k: req.generation?.topK,
67
+ response_format: opts.responseFormat,
68
+ enable_search: opts.enableSearch,
69
+ search_options: opts.searchOptions,
70
+ };
71
+ }),
72
+ },
73
+ stream: OpenAIChat.protocol.stream,
74
+ });
75
+ export * as AlibabaChat from "./alibaba-chat.js";