@qjp88995/provider-client 0.0.0-stage → 0.1.1
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/dist/center-fetch.d.ts +29 -0
- package/dist/center-fetch.d.ts.map +1 -0
- package/dist/center-fetch.js +45 -0
- package/dist/center-fetch.js.map +1 -0
- package/dist/direct-resolver.d.ts +29 -0
- package/dist/direct-resolver.d.ts.map +1 -0
- package/dist/direct-resolver.js +47 -0
- package/dist/direct-resolver.js.map +1 -0
- package/dist/errors.d.ts +38 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +57 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/model-handle.d.ts +92 -0
- package/dist/model-handle.d.ts.map +1 -0
- package/dist/model-handle.js +72 -0
- package/dist/model-handle.js.map +1 -0
- package/dist/provider-client.d.ts +40 -0
- package/dist/provider-client.d.ts.map +1 -0
- package/dist/provider-client.js +96 -0
- package/dist/provider-client.js.map +1 -0
- package/dist/to-error.d.ts +12 -0
- package/dist/to-error.d.ts.map +1 -0
- package/dist/to-error.js +33 -0
- package/dist/to-error.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +75 -0
- package/dist/types.js.map +1 -0
- package/dist/vendors/alibaba.adapter.d.ts +47 -0
- package/dist/vendors/alibaba.adapter.d.ts.map +1 -0
- package/dist/vendors/alibaba.adapter.js +79 -0
- package/dist/vendors/alibaba.adapter.js.map +1 -0
- package/dist/vendors/ark-responses-shim.d.ts +25 -0
- package/dist/vendors/ark-responses-shim.d.ts.map +1 -0
- package/dist/vendors/ark-responses-shim.js +60 -0
- package/dist/vendors/ark-responses-shim.js.map +1 -0
- package/dist/vendors/deepseek.adapter.d.ts +50 -0
- package/dist/vendors/deepseek.adapter.d.ts.map +1 -0
- package/dist/vendors/deepseek.adapter.js +123 -0
- package/dist/vendors/deepseek.adapter.js.map +1 -0
- package/dist/vendors/dots.adapter.d.ts +32 -0
- package/dist/vendors/dots.adapter.d.ts.map +1 -0
- package/dist/vendors/dots.adapter.js +53 -0
- package/dist/vendors/dots.adapter.js.map +1 -0
- package/dist/vendors/generic.adapter.d.ts +33 -0
- package/dist/vendors/generic.adapter.d.ts.map +1 -0
- package/dist/vendors/generic.adapter.js +82 -0
- package/dist/vendors/generic.adapter.js.map +1 -0
- package/dist/vendors/google-signature.d.ts +17 -0
- package/dist/vendors/google-signature.d.ts.map +1 -0
- package/dist/vendors/google-signature.js +69 -0
- package/dist/vendors/google-signature.js.map +1 -0
- package/dist/vendors/google.adapter.d.ts +41 -0
- package/dist/vendors/google.adapter.d.ts.map +1 -0
- package/dist/vendors/google.adapter.js +164 -0
- package/dist/vendors/google.adapter.js.map +1 -0
- package/dist/vendors/index.d.ts +11 -0
- package/dist/vendors/index.d.ts.map +1 -0
- package/dist/vendors/index.js +39 -0
- package/dist/vendors/index.js.map +1 -0
- package/dist/vendors/minimax.adapter.d.ts +98 -0
- package/dist/vendors/minimax.adapter.d.ts.map +1 -0
- package/dist/vendors/minimax.adapter.js +163 -0
- package/dist/vendors/minimax.adapter.js.map +1 -0
- package/dist/vendors/moonshotai.adapter.d.ts +31 -0
- package/dist/vendors/moonshotai.adapter.d.ts.map +1 -0
- package/dist/vendors/moonshotai.adapter.js +57 -0
- package/dist/vendors/moonshotai.adapter.js.map +1 -0
- package/dist/vendors/openai-responses.d.ts +49 -0
- package/dist/vendors/openai-responses.d.ts.map +1 -0
- package/dist/vendors/openai-responses.js +64 -0
- package/dist/vendors/openai-responses.js.map +1 -0
- package/dist/vendors/openai.adapter.d.ts +27 -0
- package/dist/vendors/openai.adapter.d.ts.map +1 -0
- package/dist/vendors/openai.adapter.js +196 -0
- package/dist/vendors/openai.adapter.js.map +1 -0
- package/dist/vendors/responses-reasoning-text-shim.d.ts +50 -0
- package/dist/vendors/responses-reasoning-text-shim.d.ts.map +1 -0
- package/dist/vendors/responses-reasoning-text-shim.js +170 -0
- package/dist/vendors/responses-reasoning-text-shim.js.map +1 -0
- package/dist/vendors/vendor-adapter.d.ts +214 -0
- package/dist/vendors/vendor-adapter.d.ts.map +1 -0
- package/dist/vendors/vendor-adapter.js +150 -0
- package/dist/vendors/vendor-adapter.js.map +1 -0
- package/dist/vendors/volcengine.adapter.d.ts +74 -0
- package/dist/vendors/volcengine.adapter.d.ts.map +1 -0
- package/dist/vendors/volcengine.adapter.js +139 -0
- package/dist/vendors/volcengine.adapter.js.map +1 -0
- package/dist/vendors/zhipu.adapter.d.ts +81 -0
- package/dist/vendors/zhipu.adapter.d.ts.map +1 -0
- package/dist/vendors/zhipu.adapter.js +133 -0
- package/dist/vendors/zhipu.adapter.js.map +1 -0
- package/package.json +53 -3
- package/src/center-fetch.ts +69 -0
- package/src/direct-resolver.ts +90 -0
- package/src/errors.ts +88 -0
- package/src/index.ts +54 -0
- package/src/model-handle.ts +197 -0
- package/src/provider-client.ts +136 -0
- package/src/to-error.ts +39 -0
- package/src/types.ts +126 -0
- package/src/vendors/alibaba.adapter.ts +101 -0
- package/src/vendors/ark-responses-shim.ts +60 -0
- package/src/vendors/deepseek.adapter.ts +155 -0
- package/src/vendors/dots.adapter.ts +69 -0
- package/src/vendors/generic.adapter.ts +103 -0
- package/src/vendors/google-signature.ts +87 -0
- package/src/vendors/google.adapter.ts +197 -0
- package/src/vendors/index.ts +56 -0
- package/src/vendors/minimax.adapter.ts +193 -0
- package/src/vendors/moonshotai.adapter.ts +84 -0
- package/src/vendors/openai-responses.ts +82 -0
- package/src/vendors/openai.adapter.ts +235 -0
- package/src/vendors/responses-reasoning-text-shim.ts +174 -0
- package/src/vendors/vendor-adapter.ts +294 -0
- package/src/vendors/volcengine.adapter.ts +166 -0
- package/src/vendors/zhipu.adapter.ts +169 -0
- package/README.md +0 -3
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
2
|
+
import { COMPATIBLE_RESPONSES_OPTIONS, createResponsesModel, } from './openai-responses.js';
|
|
3
|
+
import { withReasoningTextResponsesShim } from './responses-reasoning-text-shim.js';
|
|
4
|
+
import { LlmVendorAdapter, unsupportedProtocol, } from './vendor-adapter.js';
|
|
5
|
+
/** 删除厂商文件的超时。 */
|
|
6
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
7
|
+
export class DeepSeekAdapter extends LlmVendorAdapter {
|
|
8
|
+
kind = 'deepseek';
|
|
9
|
+
supportedProtocols = [
|
|
10
|
+
'openai-chat-completions',
|
|
11
|
+
'openai-responses',
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* responses 走 `@ai-sdk/openai` + HTTP 垫片,**不是** `@ai-sdk/deepseek`——那个包
|
|
15
|
+
* 只有 chat-completions;垫片的由来见 `responses-reasoning-text-shim.ts` 头注释。
|
|
16
|
+
*/
|
|
17
|
+
createModel(input) {
|
|
18
|
+
switch (input.protocol) {
|
|
19
|
+
case 'openai-chat-completions': {
|
|
20
|
+
const { baseUrl, apiKey, modelId, fetch } = input;
|
|
21
|
+
return createDeepSeek({ baseURL: baseUrl, apiKey, fetch })(modelId);
|
|
22
|
+
}
|
|
23
|
+
case 'openai-responses':
|
|
24
|
+
return createResponsesModel(input, withReasoningTextResponsesShim(input.fetch));
|
|
25
|
+
default:
|
|
26
|
+
throw unsupportedProtocol(this, input.protocol);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Files API(<https://api-docs.deepseek.com/guides/files_api>):`POST /files`
|
|
31
|
+
* 挂在与 chat 同一个根上,`purpose` 固定 `user_data`,`expires_after` 1h–30d
|
|
32
|
+
* 或省略=永久;只收 JPEG/PNG/GIF/WebP、单文件 64 MiB。承载用 `@ai-sdk/deepseek`
|
|
33
|
+
* 的 `files().uploadFile()`(两种协议都用它上传——它只是个 multipart POST,与
|
|
34
|
+
* 线协议无关),而**引用 key 跟协议走**:chat 的 user 消息由 `@ai-sdk/deepseek`
|
|
35
|
+
* 翻成 `{type:'file', file_id}`,responses 由 `@ai-sdk/openai` 翻成
|
|
36
|
+
* `{type:'input_image', file_id}`,两家读的命名空间不同。
|
|
37
|
+
*
|
|
38
|
+
* baseUrl 尾部的 `/v1` 要剥掉:Files API 文档给的根是
|
|
39
|
+
* `https://api.deepseek.com`,运营两种写法都可能填。
|
|
40
|
+
*/
|
|
41
|
+
createFileStore(input) {
|
|
42
|
+
const root = input.baseUrl.replace(/\/+$/, '').replace(/\/v1$/, '');
|
|
43
|
+
const referenceKey = input.protocol === 'openai-responses' ? 'openai' : 'deepseek';
|
|
44
|
+
const send = input.fetch ?? globalThis.fetch;
|
|
45
|
+
const files = createDeepSeek({
|
|
46
|
+
baseURL: root,
|
|
47
|
+
apiKey: input.apiKey,
|
|
48
|
+
fetch: input.fetch,
|
|
49
|
+
}).files();
|
|
50
|
+
return {
|
|
51
|
+
referenceKey,
|
|
52
|
+
async upload({ data, mediaType, filename, ttlSeconds }) {
|
|
53
|
+
const r = await files.uploadFile({
|
|
54
|
+
data: { type: 'data', data },
|
|
55
|
+
mediaType,
|
|
56
|
+
...(filename !== undefined ? { filename } : {}),
|
|
57
|
+
...(ttlSeconds !== undefined
|
|
58
|
+
? { providerOptions: { deepseek: { expiresAfter: ttlSeconds } } }
|
|
59
|
+
: {}),
|
|
60
|
+
});
|
|
61
|
+
const meta = r.providerMetadata?.deepseek;
|
|
62
|
+
const expiresAt = typeof meta?.expiresAt === 'number'
|
|
63
|
+
? new Date(meta.expiresAt * 1000)
|
|
64
|
+
: null;
|
|
65
|
+
return { fileId: r.providerReference.deepseek, expiresAt };
|
|
66
|
+
},
|
|
67
|
+
async delete(fileId) {
|
|
68
|
+
const res = await send(`${root}/files/${encodeURIComponent(fileId)}`, {
|
|
69
|
+
method: 'DELETE',
|
|
70
|
+
headers: { Authorization: `Bearer ${input.apiKey}` },
|
|
71
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
72
|
+
});
|
|
73
|
+
// 404 = 厂商那边已经没了(到期自动清),目的达成。
|
|
74
|
+
if (!res.ok && res.status !== 404) {
|
|
75
|
+
throw new Error(`DeepSeek file delete failed: ${res.status} ${res.statusText ?? ''}`.trim());
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* chat-completions 有两个开关,形状不同(`referenes/deepseek-request.md` §2):
|
|
82
|
+
*
|
|
83
|
+
* - 关闭走 `thinking:{type:'disabled'}`(默认是 `enabled`,**不发 ≠ 关闭**,
|
|
84
|
+
* 已用真实 API 实测)。
|
|
85
|
+
* - 档位走**顶层** `reasoning_effort`。别试图发嵌套的
|
|
86
|
+
* `thinking:{type,reasoningEffort}`——实测 SDK 会把嵌套里的 effort 整个吞掉,
|
|
87
|
+
* 只发出 `{"thinking":{"type":"enabled"}}`,档位静默丢失。
|
|
88
|
+
*
|
|
89
|
+
* 档位只发它的原生三档 `low/high/max`:`minimal` 降 `low`(openai 独有档位),
|
|
90
|
+
* `medium` 升 `high`(vendor 侧本来也这么映射)。**别改回原样发 `medium`**——
|
|
91
|
+
* `@ai-sdk/deepseek` 3.0.32 起会在客户端替你映射成 `high`,但每次调用附带一条
|
|
92
|
+
* `compatibility` 警告刷进日志(`deepseek-chat.sdk-contract.spec.ts` 钉住)。
|
|
93
|
+
* v4-pro 的 `low` 仍由 vendor 侧自动映射 `high`。
|
|
94
|
+
*
|
|
95
|
+
* 推理开着时 SDK 还会带警告剥掉 `temperature`/`top_p`(厂商文档:思考模式下
|
|
96
|
+
* 二者无效)。服务端行为不变,故不在 `sampling` 上跟着声明。
|
|
97
|
+
*
|
|
98
|
+
* responses 只有一个开关 `reasoning.effort`,且 **`none` 就是关闭**
|
|
99
|
+
* (探针:`reasoning_tokens: 0`、不出 reasoning item),`max` 原样收;key 随
|
|
100
|
+
* 承载包换成 `openai`,并带 `COMPATIBLE_RESPONSES_OPTIONS`(不带则 SDK 按模型名
|
|
101
|
+
* 判成非推理模型、`reasoning` 整个不发——又是一次「不发 ≠ 关闭」)。
|
|
102
|
+
*/
|
|
103
|
+
reasoning(_modelId, effort, protocol) {
|
|
104
|
+
switch (protocol) {
|
|
105
|
+
case 'openai-chat-completions': {
|
|
106
|
+
if (effort === 'off') {
|
|
107
|
+
return { deepseek: { thinking: { type: 'disabled' } } };
|
|
108
|
+
}
|
|
109
|
+
const sent = effort === 'minimal' ? 'low' : effort === 'medium' ? 'high' : effort;
|
|
110
|
+
return { deepseek: { reasoningEffort: sent } };
|
|
111
|
+
}
|
|
112
|
+
case 'openai-responses': {
|
|
113
|
+
const sent = effort === 'off' ? 'none' : effort === 'minimal' ? 'low' : effort;
|
|
114
|
+
return {
|
|
115
|
+
openai: { reasoningEffort: sent, ...COMPATIBLE_RESPONSES_OPTIONS },
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
default:
|
|
119
|
+
throw unsupportedProtocol(this, protocol);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=deepseek.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.adapter.js","sourceRoot":"","sources":["../../src/vendors/deepseek.adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { LanguageModel } from 'ai';
|
|
2
|
+
import type { LlmProtocol } from '../types.js';
|
|
3
|
+
import { type CreateModelInput, LlmVendorAdapter, type ProviderOptions, type ReasoningEffort } from './vendor-adapter.js';
|
|
4
|
+
/**
|
|
5
|
+
* 小红书 Dots(dots3-note-prev)。
|
|
6
|
+
*
|
|
7
|
+
* 全部判据来自 2026-10-21 真 key 探针(文档只写了 Anthropic Messages 一面):
|
|
8
|
+
*
|
|
9
|
+
* - **只接 chat-completions**。`/v1/messages`(Anthropic)也通,但本仓没有
|
|
10
|
+
* `anthropic-messages` 分支;`/v1/responses` 路由在(文档的 Codex 指南还配了
|
|
11
|
+
* `wire_api = "responses"`),可四种请求体(字符串 input / 显式 message item /
|
|
12
|
+
* `instructions` / 带 `reasoning`)一律 400 `provider.client_bad_request`,
|
|
13
|
+
* 拿不到一次 200 就不写那个分支。
|
|
14
|
+
* - **推理默认开着**(省略 `reasoning_effort` 照样回 `reasoning_content`,「不发 ≠
|
|
15
|
+
* 关闭」);`reasoning_effort` 收 `none/minimal/low/medium/high/xhigh/max`,
|
|
16
|
+
* `none` 是真关闭(无 `reasoning_content`)、未知值 400。私有的
|
|
17
|
+
* `thinking:{type:'disabled'}` 在这一面**被接受但无效**,别改成发它。
|
|
18
|
+
* - 思考走 `message.reasoning_content` / `delta.reasoning_content`,SDK 原生读;
|
|
19
|
+
* 历史里 assistant 带回 `reasoning_content` 它也收。
|
|
20
|
+
* - 工具调用、`image_url`(公网 URL)、`temperature`/`top_p` 都正常;鉴权
|
|
21
|
+
* `Authorization: Bearer`;`GET /v1/models` 是标准形状。没找到余额接口。
|
|
22
|
+
*/
|
|
23
|
+
export declare class DotsAdapter extends LlmVendorAdapter {
|
|
24
|
+
readonly kind: "dots";
|
|
25
|
+
createModel(input: CreateModelInput): LanguageModel;
|
|
26
|
+
/**
|
|
27
|
+
* `off` → `none`(显式关闭);其余五档它原生都认,直通——`minimal` 也是它
|
|
28
|
+
* 枚举里的值,不像别家要降档。
|
|
29
|
+
*/
|
|
30
|
+
reasoning(_modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=dots.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dots.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/dots.adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAEL,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAS7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,WAAY,SAAQ,gBAAgB;IAC/C,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAEhC,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAWnD;;;OAGG;IACM,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe;CAQnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
2
|
+
import { assertChatCompletions, LlmVendorAdapter, } from './vendor-adapter.js';
|
|
3
|
+
/**
|
|
4
|
+
* 工厂 `name`。决定 provider id(`dots.chat`)与 providerOptions 的命名空间 key
|
|
5
|
+
* (单词无连字符,`name` 与 `toCamelCase(name)` 相同),恰好等于 `kind`,基类
|
|
6
|
+
* 默认的 `optionsKey` 直接可用。
|
|
7
|
+
*/
|
|
8
|
+
const FACTORY_NAME = 'dots';
|
|
9
|
+
/**
|
|
10
|
+
* 小红书 Dots(dots3-note-prev)。
|
|
11
|
+
*
|
|
12
|
+
* 全部判据来自 2026-10-21 真 key 探针(文档只写了 Anthropic Messages 一面):
|
|
13
|
+
*
|
|
14
|
+
* - **只接 chat-completions**。`/v1/messages`(Anthropic)也通,但本仓没有
|
|
15
|
+
* `anthropic-messages` 分支;`/v1/responses` 路由在(文档的 Codex 指南还配了
|
|
16
|
+
* `wire_api = "responses"`),可四种请求体(字符串 input / 显式 message item /
|
|
17
|
+
* `instructions` / 带 `reasoning`)一律 400 `provider.client_bad_request`,
|
|
18
|
+
* 拿不到一次 200 就不写那个分支。
|
|
19
|
+
* - **推理默认开着**(省略 `reasoning_effort` 照样回 `reasoning_content`,「不发 ≠
|
|
20
|
+
* 关闭」);`reasoning_effort` 收 `none/minimal/low/medium/high/xhigh/max`,
|
|
21
|
+
* `none` 是真关闭(无 `reasoning_content`)、未知值 400。私有的
|
|
22
|
+
* `thinking:{type:'disabled'}` 在这一面**被接受但无效**,别改成发它。
|
|
23
|
+
* - 思考走 `message.reasoning_content` / `delta.reasoning_content`,SDK 原生读;
|
|
24
|
+
* 历史里 assistant 带回 `reasoning_content` 它也收。
|
|
25
|
+
* - 工具调用、`image_url`(公网 URL)、`temperature`/`top_p` 都正常;鉴权
|
|
26
|
+
* `Authorization: Bearer`;`GET /v1/models` 是标准形状。没找到余额接口。
|
|
27
|
+
*/
|
|
28
|
+
export class DotsAdapter extends LlmVendorAdapter {
|
|
29
|
+
kind = 'dots';
|
|
30
|
+
createModel(input) {
|
|
31
|
+
assertChatCompletions(this, input.protocol);
|
|
32
|
+
const { baseUrl, apiKey, modelId, fetch } = input;
|
|
33
|
+
return createOpenAICompatible({
|
|
34
|
+
name: FACTORY_NAME,
|
|
35
|
+
baseURL: baseUrl,
|
|
36
|
+
apiKey,
|
|
37
|
+
fetch,
|
|
38
|
+
})(modelId);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* `off` → `none`(显式关闭);其余五档它原生都认,直通——`minimal` 也是它
|
|
42
|
+
* 枚举里的值,不像别家要降档。
|
|
43
|
+
*/
|
|
44
|
+
reasoning(_modelId, effort, protocol) {
|
|
45
|
+
assertChatCompletions(this, protocol);
|
|
46
|
+
return {
|
|
47
|
+
[this.optionsKey]: {
|
|
48
|
+
reasoningEffort: effort === 'off' ? 'none' : effort,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=dots.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dots.adapter.js","sourceRoot":"","sources":["../../src/vendors/dots.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAInE,OAAO,EACL,qBAAqB,EAErB,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B;;;;GAIG;AACH,MAAM,YAAY,GAAG,MAAM,CAAC;AAE5B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,WAAY,SAAQ,gBAAgB;IACtC,IAAI,GAAG,MAAe,CAAC;IAEhC,WAAW,CAAC,KAAuB;QACjC,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QAClD,OAAO,sBAAsB,CAAC;YAC5B,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,OAAO;YAChB,MAAM;YACN,KAAK;SACN,CAAC,CAAC,OAAO,CAAC,CAAC;IACd,CAAC;IAED;;;OAGG;IACM,SAAS,CAChB,QAAgB,EAChB,MAAuB,EACvB,QAAqB;QAErB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO;YACL,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;gBACjB,eAAe,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;aACpD;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { LanguageModel } from 'ai';
|
|
2
|
+
import type { LlmProtocol } from '../types.js';
|
|
3
|
+
import { type CreateModelInput, LlmVendorAdapter, type ProviderOptions, type ReasoningEffort } from './vendor-adapter.js';
|
|
4
|
+
/**
|
|
5
|
+
* 「我们没有专门适配的厂商」。它天然是按协议接入的:就在这里按 `input.protocol`
|
|
6
|
+
* 选包(chat-completions → `@ai-sdk/openai-compatible`;responses →
|
|
7
|
+
* `createOpenAI({baseURL}).responses()`;将来 anthropic → `createAnthropic({baseURL})`),
|
|
8
|
+
* 不必拆成 generic-openai / generic-anthropic。
|
|
9
|
+
* 历史上 kind 叫 `openai-compatible`——那是把协议层的形容词放在厂商列上,已改名。
|
|
10
|
+
*
|
|
11
|
+
* responses 分支**不带** DeepSeek 那种垫片:这个桶后面是任意后端,谁家的线格式
|
|
12
|
+
* 偏差都不该在这里猜;偏差稳定到值得适配的家应该有自己的 kind。
|
|
13
|
+
*/
|
|
14
|
+
export declare class GenericAdapter extends LlmVendorAdapter {
|
|
15
|
+
readonly kind: "generic";
|
|
16
|
+
readonly supportedProtocols: readonly LlmProtocol[];
|
|
17
|
+
protected get optionsKey(): string;
|
|
18
|
+
createModel(input: CreateModelInput): LanguageModel;
|
|
19
|
+
/**
|
|
20
|
+
* 这个桶后面站着的是**任意**一家 OpenAI 兼容后端,`reasoningEffort` 在
|
|
21
|
+
* `@ai-sdk/openai-compatible` 里是裸 `z.ZodString`,各后端实现不一。
|
|
22
|
+
*
|
|
23
|
+
* - `off` 不发任何东西:没有统一的关闭语义,别在这里发明一个约定值
|
|
24
|
+
* (这是有意的现状而非遗漏)。
|
|
25
|
+
* - `minimal` 降档 `low`:那是 openai 独有的官方档位,原样发有 400 风险。
|
|
26
|
+
*
|
|
27
|
+
* responses 协议下承载包换成 `@ai-sdk/openai`,key 随之变成 `openai`,并要带
|
|
28
|
+
* `COMPATIBLE_RESPONSES_OPTIONS`(否则 SDK 按模型名判成非推理模型、整个不发)。
|
|
29
|
+
* `off` 仍不发——没有统一的关闭语义,责任在协议不在包。
|
|
30
|
+
*/
|
|
31
|
+
reasoning(_modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions | undefined;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=generic.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/generic.adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,OAAO,EACL,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAkB7B;;;;;;;;;GASG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IAEnC,SAAkB,kBAAkB,EAAE,SAAS,WAAW,EAAE,CAG1D;IAEF,cAAuB,UAAU,IAAI,MAAM,CAE1C;IAED,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAkBnD;;;;;;;;;;;OAWG;IACM,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe,GAAG,SAAS;CAc/B"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
2
|
+
import { COMPATIBLE_RESPONSES_OPTIONS, createResponsesModel, } from './openai-responses.js';
|
|
3
|
+
import { LlmVendorAdapter, unsupportedProtocol, } from './vendor-adapter.js';
|
|
4
|
+
/** 工厂的 `name`;它决定 provider id(`openai-compatible.chat`),**不再**是 options key。 */
|
|
5
|
+
const FACTORY_NAME = 'openai-compatible';
|
|
6
|
+
/**
|
|
7
|
+
* providerOptions 的命名空间 key。
|
|
8
|
+
*
|
|
9
|
+
* `@ai-sdk/openai-compatible` 3.x 起把这个 key **固定成驼峰**:模型层按
|
|
10
|
+
* `openaiCompatible`(以及 `toCamelCase(工厂 name)`)解析选项,凡是用带连字符的
|
|
11
|
+
* 原名下发的都会打一条 `DeprecationWarning: providerOptions key
|
|
12
|
+
* 'openai-compatible'. Use 'openaiCompatible' instead.`——每次调用一条,刷满日志。
|
|
13
|
+
*
|
|
14
|
+
* 所以这里**不能**再跟 `FACTORY_NAME` 走。两者恰好互为驼峰/连字符形式是巧合,
|
|
15
|
+
* 不是契约:真要改工厂 name,得同步改这里(SDK 认 `toCamelCase(name)`)。
|
|
16
|
+
*/
|
|
17
|
+
const OPTIONS_KEY = 'openaiCompatible';
|
|
18
|
+
/**
|
|
19
|
+
* 「我们没有专门适配的厂商」。它天然是按协议接入的:就在这里按 `input.protocol`
|
|
20
|
+
* 选包(chat-completions → `@ai-sdk/openai-compatible`;responses →
|
|
21
|
+
* `createOpenAI({baseURL}).responses()`;将来 anthropic → `createAnthropic({baseURL})`),
|
|
22
|
+
* 不必拆成 generic-openai / generic-anthropic。
|
|
23
|
+
* 历史上 kind 叫 `openai-compatible`——那是把协议层的形容词放在厂商列上,已改名。
|
|
24
|
+
*
|
|
25
|
+
* responses 分支**不带** DeepSeek 那种垫片:这个桶后面是任意后端,谁家的线格式
|
|
26
|
+
* 偏差都不该在这里猜;偏差稳定到值得适配的家应该有自己的 kind。
|
|
27
|
+
*/
|
|
28
|
+
export class GenericAdapter extends LlmVendorAdapter {
|
|
29
|
+
kind = 'generic';
|
|
30
|
+
supportedProtocols = [
|
|
31
|
+
'openai-chat-completions',
|
|
32
|
+
'openai-responses',
|
|
33
|
+
];
|
|
34
|
+
get optionsKey() {
|
|
35
|
+
return OPTIONS_KEY;
|
|
36
|
+
}
|
|
37
|
+
createModel(input) {
|
|
38
|
+
switch (input.protocol) {
|
|
39
|
+
case 'openai-chat-completions': {
|
|
40
|
+
const { baseUrl, apiKey, modelId, fetch } = input;
|
|
41
|
+
return createOpenAICompatible({
|
|
42
|
+
name: FACTORY_NAME,
|
|
43
|
+
baseURL: baseUrl,
|
|
44
|
+
apiKey,
|
|
45
|
+
fetch,
|
|
46
|
+
})(modelId);
|
|
47
|
+
}
|
|
48
|
+
case 'openai-responses':
|
|
49
|
+
return createResponsesModel(input);
|
|
50
|
+
default:
|
|
51
|
+
throw unsupportedProtocol(this, input.protocol);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 这个桶后面站着的是**任意**一家 OpenAI 兼容后端,`reasoningEffort` 在
|
|
56
|
+
* `@ai-sdk/openai-compatible` 里是裸 `z.ZodString`,各后端实现不一。
|
|
57
|
+
*
|
|
58
|
+
* - `off` 不发任何东西:没有统一的关闭语义,别在这里发明一个约定值
|
|
59
|
+
* (这是有意的现状而非遗漏)。
|
|
60
|
+
* - `minimal` 降档 `low`:那是 openai 独有的官方档位,原样发有 400 风险。
|
|
61
|
+
*
|
|
62
|
+
* responses 协议下承载包换成 `@ai-sdk/openai`,key 随之变成 `openai`,并要带
|
|
63
|
+
* `COMPATIBLE_RESPONSES_OPTIONS`(否则 SDK 按模型名判成非推理模型、整个不发)。
|
|
64
|
+
* `off` 仍不发——没有统一的关闭语义,责任在协议不在包。
|
|
65
|
+
*/
|
|
66
|
+
reasoning(_modelId, effort, protocol) {
|
|
67
|
+
if (effort === 'off')
|
|
68
|
+
return undefined;
|
|
69
|
+
const sent = effort === 'minimal' ? 'low' : effort;
|
|
70
|
+
switch (protocol) {
|
|
71
|
+
case 'openai-chat-completions':
|
|
72
|
+
return { [this.optionsKey]: { reasoningEffort: sent } };
|
|
73
|
+
case 'openai-responses':
|
|
74
|
+
return {
|
|
75
|
+
openai: { reasoningEffort: sent, ...COMPATIBLE_RESPONSES_OPTIONS },
|
|
76
|
+
};
|
|
77
|
+
default:
|
|
78
|
+
throw unsupportedProtocol(this, protocol);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=generic.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generic.adapter.js","sourceRoot":"","sources":["../../src/vendors/generic.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAInE,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,gBAAgB,EAGhB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,gFAAgF;AAChF,MAAM,YAAY,GAAG,mBAAmB,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAEvC;;;;;;;;;GASG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACzC,IAAI,GAAG,SAAkB,CAAC;IAEjB,kBAAkB,GAA2B;QAC7D,yBAAyB;QACzB,kBAAkB;KACnB,CAAC;IAEF,IAAuB,UAAU;QAC/B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,WAAW,CAAC,KAAuB;QACjC,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC;YACvB,KAAK,yBAAyB,CAAC,CAAC,CAAC;gBAC/B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;gBAClD,OAAO,sBAAsB,CAAC;oBAC5B,IAAI,EAAE,YAAY;oBAClB,OAAO,EAAE,OAAO;oBAChB,MAAM;oBACN,KAAK;iBACN,CAAC,CAAC,OAAO,CAAC,CAAC;YACd,CAAC;YACD,KAAK,kBAAkB;gBACrB,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACrC;gBACE,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACM,SAAS,CAChB,QAAgB,EAChB,MAAuB,EACvB,QAAqB;QAErB,IAAI,MAAM,KAAK,KAAK;YAAE,OAAO,SAAS,CAAC;QACvC,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACnD,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,yBAAyB;gBAC5B,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;YAC1D,KAAK,kBAAkB;gBACrB,OAAO;oBACL,MAAM,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,4BAA4B,EAAE;iBACnE,CAAC;YACJ;gBACE,MAAM,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LanguageModelMiddleware } from 'ai';
|
|
2
|
+
/**
|
|
3
|
+
* Interactions 句柄的思考签名规范化:**让签名总是落在 tool-call 上**。
|
|
4
|
+
*
|
|
5
|
+
* 为什么要它:内核只把 tool-call 上的 metadata 落库回放(reasoning 照全仓默认
|
|
6
|
+
* 丢弃),而 Interactions 的签名按协议属于 thought 步骤——2026-10-23 抓包:流式
|
|
7
|
+
* 时签名只在 `thought` 的 `thought_signature` delta 里(SDK 挂到 `reasoning-end`
|
|
8
|
+
* 上),`function_call` 有时带自己的签名、有时不带;想得很少时 thought 连摘要
|
|
9
|
+
* 都没有,账本里压根不会出现那条 reasoning part。当前这一轮的函数调用没有签名
|
|
10
|
+
* 就 400,所以把 thought 的签名补到紧随其后的第一个无签名 tool-call 上——SDK 的
|
|
11
|
+
* 非流式路径本来就是这个形状,回放探针也证实服务端认(折叠后 200、不带 400)。
|
|
12
|
+
*
|
|
13
|
+
* 顺带剔掉 tool-call 上的 `interactionId`:每轮都 `store: false` 发全量历史,
|
|
14
|
+
* 这个 id 引用不到任何东西,落进库只是噪音。
|
|
15
|
+
*/
|
|
16
|
+
export declare const interactionsSignatureMiddleware: LanguageModelMiddleware;
|
|
17
|
+
//# sourceMappingURL=google-signature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-signature.d.ts","sourceRoot":"","sources":["../../src/vendors/google-signature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAmDlD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,+BAA+B,EAAE,uBAqB7C,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Interactions 的签名在 `providerMetadata.google.signature`。 */
|
|
2
|
+
function signatureOf(metadata) {
|
|
3
|
+
const signature = metadata?.google?.signature;
|
|
4
|
+
return typeof signature === 'string' && signature.length > 0
|
|
5
|
+
? signature
|
|
6
|
+
: null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* 给一次调用产出的 part 序列做签名规范化:tool-call 的 `google` metadata 收窄成
|
|
10
|
+
* 只剩 `signature`,没有自己的签名时补上**前面最近一个还没被用掉的** thought
|
|
11
|
+
* 签名。对别的 part 原样放行。
|
|
12
|
+
*/
|
|
13
|
+
function signatureNormalizer() {
|
|
14
|
+
let pending = null;
|
|
15
|
+
return (part) => {
|
|
16
|
+
if (part.type === 'reasoning' || part.type === 'reasoning-end') {
|
|
17
|
+
pending = signatureOf(part.providerMetadata) ?? pending;
|
|
18
|
+
return part;
|
|
19
|
+
}
|
|
20
|
+
if (part.type !== 'tool-call')
|
|
21
|
+
return part;
|
|
22
|
+
const signature = signatureOf(part.providerMetadata) ?? pending;
|
|
23
|
+
pending = null;
|
|
24
|
+
const { google: _google, ...others } = part.providerMetadata ?? {};
|
|
25
|
+
const providerMetadata = {
|
|
26
|
+
...others,
|
|
27
|
+
...(signature && { google: { signature } }),
|
|
28
|
+
};
|
|
29
|
+
return {
|
|
30
|
+
...part,
|
|
31
|
+
providerMetadata: Object.keys(providerMetadata).length > 0 ? providerMetadata : undefined,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Interactions 句柄的思考签名规范化:**让签名总是落在 tool-call 上**。
|
|
37
|
+
*
|
|
38
|
+
* 为什么要它:内核只把 tool-call 上的 metadata 落库回放(reasoning 照全仓默认
|
|
39
|
+
* 丢弃),而 Interactions 的签名按协议属于 thought 步骤——2026-10-23 抓包:流式
|
|
40
|
+
* 时签名只在 `thought` 的 `thought_signature` delta 里(SDK 挂到 `reasoning-end`
|
|
41
|
+
* 上),`function_call` 有时带自己的签名、有时不带;想得很少时 thought 连摘要
|
|
42
|
+
* 都没有,账本里压根不会出现那条 reasoning part。当前这一轮的函数调用没有签名
|
|
43
|
+
* 就 400,所以把 thought 的签名补到紧随其后的第一个无签名 tool-call 上——SDK 的
|
|
44
|
+
* 非流式路径本来就是这个形状,回放探针也证实服务端认(折叠后 200、不带 400)。
|
|
45
|
+
*
|
|
46
|
+
* 顺带剔掉 tool-call 上的 `interactionId`:每轮都 `store: false` 发全量历史,
|
|
47
|
+
* 这个 id 引用不到任何东西,落进库只是噪音。
|
|
48
|
+
*/
|
|
49
|
+
export const interactionsSignatureMiddleware = {
|
|
50
|
+
specificationVersion: 'v4',
|
|
51
|
+
wrapStream: async ({ doStream }) => {
|
|
52
|
+
const { stream, ...rest } = await doStream();
|
|
53
|
+
const normalize = signatureNormalizer();
|
|
54
|
+
return {
|
|
55
|
+
...rest,
|
|
56
|
+
stream: stream.pipeThrough(new TransformStream({
|
|
57
|
+
transform(part, controller) {
|
|
58
|
+
controller.enqueue(normalize(part));
|
|
59
|
+
},
|
|
60
|
+
})),
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
wrapGenerate: async ({ doGenerate }) => {
|
|
64
|
+
const result = await doGenerate();
|
|
65
|
+
const normalize = signatureNormalizer();
|
|
66
|
+
return { ...result, content: result.content.map(normalize) };
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=google-signature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-signature.js","sourceRoot":"","sources":["../../src/vendors/google-signature.ts"],"names":[],"mappings":"AAeA,6DAA6D;AAC7D,SAAS,WAAW,CAAC,QAAsC;IACzD,MAAM,SAAS,GAAG,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC;IAC9C,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAC1D,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED;;;;GAIG;AACH,SAAS,mBAAmB;IAC1B,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,OAAO,CAAqC,IAAO,EAAK,EAAE;QACxD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,IAAI,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;YAC/D,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,OAAO,CAAC;YACxD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC3C,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,OAAO,CAAC;QAChE,OAAO,GAAG,IAAI,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC;QACnE,MAAM,gBAAgB,GAAqB;YACzC,GAAG,MAAM;YACT,GAAG,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC;SAC5C,CAAC;QACF,OAAO;YACL,GAAG,IAAI;YACP,gBAAgB,EACd,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS;SAC1E,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAA4B;IACtE,oBAAoB,EAAE,IAAI;IAC1B,UAAU,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACjC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;QACxC,OAAO;YACL,GAAG,IAAI;YACP,MAAM,EAAE,MAAM,CAAC,WAAW,CACxB,IAAI,eAAe,CAAyB;gBAC1C,SAAS,CAAC,IAAI,EAAE,UAAU;oBACxB,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtC,CAAC;aACF,CAAC,CACH;SACF,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;QACxC,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;IAC/D,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type LanguageModel } from 'ai';
|
|
2
|
+
import type { LlmProtocol } from '../types.js';
|
|
3
|
+
import { type AdviceModelView, type CreateModelInput, LlmVendorAdapter, type ModelAdvice, type ProviderOptions, type ReasoningEffort } from './vendor-adapter.js';
|
|
4
|
+
/**
|
|
5
|
+
* Google(Gemini API)。承载包 `@ai-sdk/google`:`chat()` 走 `:generateContent`,
|
|
6
|
+
* `interactions()` 走 `/interactions`。全部判据来自 2026-10-23 真 key 探针:
|
|
7
|
+
*
|
|
8
|
+
* - **思考签名必须原样带回**。两种协议都把签名挂在一步里**第一个函数调用**上
|
|
9
|
+
* (SDK 放进 tool-call 的 `providerMetadata.google`,generateContent 叫
|
|
10
|
+
* `thoughtSignature`、Interactions 叫 `signature`),下一步不带回去:
|
|
11
|
+
* generateContent 400「Function call is missing a thought_signature」——SDK
|
|
12
|
+
* 4.0.104 会在缺签名时自己塞官方哑签名 `skip_thought_signature_validator`
|
|
13
|
+
* 兜住并打 warning,Google 说那样会降质;Interactions 没有这层兜底,直接
|
|
14
|
+
* 400。故 `replayedMetadataKeys = ['google']`,签名随 tool-call part 落库、
|
|
15
|
+
* 重放时原样发回。Interactions 的签名按协议属于 thought 步骤,流式时常常
|
|
16
|
+
* 只挂在那上面,由 `interactionsSignatureMiddleware` 补到 tool-call 上。**只看当前这一轮**:更早轮次里没有签名的调用(会话中途
|
|
17
|
+
* 从别家切过来)两种协议都放行。
|
|
18
|
+
* - **思考块不必回传**:只回带签名的函数调用,两种协议都 200(generateContent
|
|
19
|
+
* 官方允许;Interactions 文档写「必须原样回传 thought 块」但服务端不强制)。
|
|
20
|
+
* 所以 reasoning part 照全仓默认丢弃,不为这家开例外。
|
|
21
|
+
* - 推理档位见 `thinkingLevelOf`;思考摘要要显式要(generateContent
|
|
22
|
+
* `includeThoughts`、Interactions `thinkingSummaries: 'auto'`),否则对话页
|
|
23
|
+
* 没有思考过程可显示。
|
|
24
|
+
* - `gemini-2.5-*` 已不对新用户开放(404「no longer available to new users」)。
|
|
25
|
+
* - 目录 `GET {base}/models` 用 `x-goog-api-key`、回 `models[]`(`name` 带
|
|
26
|
+
* `models/` 前缀),不是 OpenAI 形状,故覆盖 `fetchCatalog`。
|
|
27
|
+
* - 国内直连不通,部署在国内要给这家选网络代理。
|
|
28
|
+
*/
|
|
29
|
+
export declare class GoogleAdapter extends LlmVendorAdapter {
|
|
30
|
+
readonly kind: "google";
|
|
31
|
+
readonly supportedProtocols: readonly LlmProtocol[];
|
|
32
|
+
readonly replayedMetadataKeys: string[];
|
|
33
|
+
/**
|
|
34
|
+
* 2.5 系对新用户 404(探针原话「no longer available to new users」);3 系起总在
|
|
35
|
+
* 思考,不标「推理」就拿不到思考摘要、档位也不下发。
|
|
36
|
+
*/
|
|
37
|
+
adviseModel(model: AdviceModelView): ModelAdvice[];
|
|
38
|
+
createModel(input: CreateModelInput): LanguageModel;
|
|
39
|
+
reasoning(modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=google.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/google.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,IAAI,CAAC;AAEZ,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AA2E7B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,aAAc,SAAQ,gBAAgB;IACjD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,WAAW,EAAE,CAGjD;IACF,SAAkB,oBAAoB,WAAiB;IAEvD;;;OAGG;IACM,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,EAAE;IAuB3D,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAuB1C,SAAS,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe;CAiBnB"}
|