@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 @@
|
|
|
1
|
+
{"version":3,"file":"provider-client.js","sourceRoot":"","sources":["../src/provider-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ProviderClientError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* 把一次 AI SDK 调用的错误里**中心自己报的**那部分认出来(`no_credential`、`vendor_not_allowed`、
|
|
4
|
+
* `pinned_credential_unavailable`、`upstream_error` ……),变成 `ProviderClientError`;别的错误(厂商原样回的
|
|
5
|
+
* 4xx / 5xx、网络、取消)给 null,调用方照旧处理。
|
|
6
|
+
*
|
|
7
|
+
* 判据:响应体是中心的 `{ code, message }`,**且没有 `x-pc-credential` 响应头**——中心只在把厂商的响应
|
|
8
|
+
* 原样回传时才带这个头,厂商自己的错误体碰巧长得像也不会被误认。AI SDK 重试耗尽时包在 `RetryError` 里,
|
|
9
|
+
* 看它的最后一次。
|
|
10
|
+
*/
|
|
11
|
+
export declare function toProviderClientError(error: unknown): ProviderClientError | null;
|
|
12
|
+
//# sourceMappingURL=to-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-error.d.ts","sourceRoot":"","sources":["../src/to-error.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGpE;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GACb,mBAAmB,GAAG,IAAI,CAsB5B"}
|
package/dist/to-error.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { APICallError, RetryError } from 'ai';
|
|
2
|
+
import { parseCenterError, ProviderClientError } from './errors.js';
|
|
3
|
+
import { PC_HEADERS } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* 把一次 AI SDK 调用的错误里**中心自己报的**那部分认出来(`no_credential`、`vendor_not_allowed`、
|
|
6
|
+
* `pinned_credential_unavailable`、`upstream_error` ……),变成 `ProviderClientError`;别的错误(厂商原样回的
|
|
7
|
+
* 4xx / 5xx、网络、取消)给 null,调用方照旧处理。
|
|
8
|
+
*
|
|
9
|
+
* 判据:响应体是中心的 `{ code, message }`,**且没有 `x-pc-credential` 响应头**——中心只在把厂商的响应
|
|
10
|
+
* 原样回传时才带这个头,厂商自己的错误体碰巧长得像也不会被误认。AI SDK 重试耗尽时包在 `RetryError` 里,
|
|
11
|
+
* 看它的最后一次。
|
|
12
|
+
*/
|
|
13
|
+
export function toProviderClientError(error) {
|
|
14
|
+
const last = RetryError.isInstance(error) ? error.lastError : error;
|
|
15
|
+
if (!APICallError.isInstance(last))
|
|
16
|
+
return null;
|
|
17
|
+
const headers = last.responseHeaders ?? {};
|
|
18
|
+
const fromVendor = Object.keys(headers).some(k => k.toLowerCase() === PC_HEADERS.credential);
|
|
19
|
+
if (fromVendor || !last.responseBody)
|
|
20
|
+
return null;
|
|
21
|
+
let body;
|
|
22
|
+
try {
|
|
23
|
+
body = JSON.parse(last.responseBody);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const known = parseCenterError(body);
|
|
29
|
+
if (!known)
|
|
30
|
+
return null;
|
|
31
|
+
return new ProviderClientError(known.code, known.message, last.statusCode ?? null, { cause: error });
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=to-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"to-error.js","sourceRoot":"","sources":["../src/to-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAc;IAEd,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,IAAI,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAC1C,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,UAAU,CAC/C,CAAC;IACF,IAAI,UAAU,IAAI,CAAC,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,IAAI,mBAAmB,CAC5B,KAAK,CAAC,IAAI,EACV,KAAK,CAAC,OAAO,EACb,IAAI,CAAC,UAAU,IAAI,IAAI,EACvB,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 与中心的契约。`@pc/shared` 是私有包发不出去,这里是它的手抄本——`contract.spec.ts` 逐项对照两边,
|
|
3
|
+
* 服务端改了契约这里当场红。
|
|
4
|
+
*/
|
|
5
|
+
/** 线协议(wire 上的请求 / 响应格式)。 */
|
|
6
|
+
export declare const LLM_PROTOCOLS: readonly ["openai-chat-completions", "openai-responses", "anthropic-messages", "google-generate-content", "google-interactions"];
|
|
7
|
+
export type LlmProtocol = (typeof LLM_PROTOCOLS)[number];
|
|
8
|
+
/** 模型能力(目录元数据:发不发图片 / 开不开推理由调用方据此决定)。 */
|
|
9
|
+
export declare const LLM_CAPABILITIES: readonly ["vision", "video", "reasoning"];
|
|
10
|
+
export type LlmCapability = (typeof LLM_CAPABILITIES)[number];
|
|
11
|
+
/** 厂商类型。一种类型对应一个适配器(`VENDOR_ADAPTERS`)。 */
|
|
12
|
+
export declare const VENDOR_KINDS: readonly ["openai", "generic", "deepseek", "moonshotai", "alibaba", "zhipu", "volcengine", "minimax", "dots", "google"];
|
|
13
|
+
export type VendorKind = (typeof VENDOR_KINDS)[number];
|
|
14
|
+
/**
|
|
15
|
+
* 推理档位——**我们自己的抽象**,不是任何一家的原生枚举,各家适配器的 `reasoning()` 把它翻译成自己的形状:
|
|
16
|
+
*
|
|
17
|
+
* - `off` 发**真正的关闭指令**(deepseek 默认开着推理,「不发」≠ 关闭);只有厂商根本没有关闭开关时
|
|
18
|
+
* (如 kimi-k3)才不发。
|
|
19
|
+
* - `minimal` 只有 openai 有,其余家降档 `low`。
|
|
20
|
+
* - `max` 是 deepseek 与 kimi-k3 的原生最高档,openai 映射到 `xhigh`。
|
|
21
|
+
* - 只有开关没有档位的家(alibaba、kimi-k2.x),非 `off` 一律塌缩成「开」。
|
|
22
|
+
*/
|
|
23
|
+
export declare const REASONING_EFFORTS: readonly ["off", "minimal", "low", "medium", "high", "max"];
|
|
24
|
+
export type ReasoningEffort = (typeof REASONING_EFFORTS)[number];
|
|
25
|
+
/** 每百万 token 的单价,十进制字符串(这是钱,别过 `Number`)。给接入方自己算用量用。 */
|
|
26
|
+
export interface ModelPricing {
|
|
27
|
+
currency: string;
|
|
28
|
+
input: string;
|
|
29
|
+
output: string;
|
|
30
|
+
cacheRead?: string | null;
|
|
31
|
+
cacheWrite?: string | null;
|
|
32
|
+
}
|
|
33
|
+
/** `GET /v1/catalog`:这个接入方能用的厂商、端点、模型。不含任何凭证信息。 */
|
|
34
|
+
export interface CatalogResponse {
|
|
35
|
+
vendors: CatalogVendor[];
|
|
36
|
+
}
|
|
37
|
+
export interface CatalogVendor {
|
|
38
|
+
/** 透传路由段,也是 `ModelRef.vendor`。 */
|
|
39
|
+
slug: string;
|
|
40
|
+
name: string;
|
|
41
|
+
kind: VendorKind;
|
|
42
|
+
endpoints: CatalogEndpoint[];
|
|
43
|
+
models: CatalogModel[];
|
|
44
|
+
}
|
|
45
|
+
export interface CatalogEndpoint {
|
|
46
|
+
protocol: LlmProtocol;
|
|
47
|
+
baseUrl: string;
|
|
48
|
+
}
|
|
49
|
+
export interface CatalogModel {
|
|
50
|
+
/** 厂商侧的模型名(请求体里的 `model`)。 */
|
|
51
|
+
modelId: string;
|
|
52
|
+
displayName: string;
|
|
53
|
+
capabilities: LlmCapability[];
|
|
54
|
+
/** 有序:解析时按这个顺序取第一个「有端点且适配器已实现」的协议。 */
|
|
55
|
+
protocols: LlmProtocol[];
|
|
56
|
+
maxContextTokens: number | null;
|
|
57
|
+
maxOutputTokens: number | null;
|
|
58
|
+
pricing: ModelPricing | null;
|
|
59
|
+
}
|
|
60
|
+
/** 中心的错误码(响应体 `{ code, message }`)。 */
|
|
61
|
+
export declare const CENTER_ERROR_CODES: readonly ["unauthorized", "forbidden", "tenant_disabled", "not_found", "invalid_request", "conflict", "unprocessable", "upstream_error", "admin_unavailable", "vendor_not_allowed", "no_credential", "pinned_credential_unavailable"];
|
|
62
|
+
export type CenterErrorCode = (typeof CENTER_ERROR_CODES)[number];
|
|
63
|
+
/** 中心的请求头 / 响应头。 */
|
|
64
|
+
export declare const PC_HEADERS: {
|
|
65
|
+
/** 接入方 API key(`pc_…`)。 */
|
|
66
|
+
readonly key: "x-pc-key";
|
|
67
|
+
/** 会话粘性键:同一个键在健康的 key 里固定落到同一把。 */
|
|
68
|
+
readonly affinity: "x-pc-affinity";
|
|
69
|
+
/** 钉住某把 key(值是 `credential` 响应头给过的 ref),不可用时报错不切换。 */
|
|
70
|
+
readonly pin: "x-pc-pin";
|
|
71
|
+
/** 响应头:这次实际用的 key(不透明 ref)。 */
|
|
72
|
+
readonly credential: "x-pc-credential";
|
|
73
|
+
/** 响应头:这次换过几次 key。 */
|
|
74
|
+
readonly switches: "x-pc-switches";
|
|
75
|
+
};
|
|
76
|
+
/** 透传路由前缀:`<中心>/v1/proxy/<厂商 slug>/<厂商 URL 的完整 pathname>`。 */
|
|
77
|
+
export declare const PROXY_ROUTE_PREFIX = "/v1/proxy";
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6BAA6B;AAC7B,eAAO,MAAM,aAAa,kIAMhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,yCAAyC;AACzC,eAAO,MAAM,gBAAgB,2CAA4C,CAAC;AAC1E,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D,2CAA2C;AAC3C,eAAO,MAAM,YAAY,yHAWf,CAAC;AACX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,6DAOpB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjE,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,sCAAsC;IACtC,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CAC9B;AAED,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,uOAarB,CAAC;AACX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAElE,oBAAoB;AACpB,eAAO,MAAM,UAAU;IACrB,2BAA2B;;IAE3B,mCAAmC;;IAEnC,sDAAsD;;IAEtD,+BAA+B;;IAE/B,sBAAsB;;CAEd,CAAC;AAEX,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,cAAc,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 与中心的契约。`@pc/shared` 是私有包发不出去,这里是它的手抄本——`contract.spec.ts` 逐项对照两边,
|
|
3
|
+
* 服务端改了契约这里当场红。
|
|
4
|
+
*/
|
|
5
|
+
/** 线协议(wire 上的请求 / 响应格式)。 */
|
|
6
|
+
export const LLM_PROTOCOLS = [
|
|
7
|
+
'openai-chat-completions',
|
|
8
|
+
'openai-responses',
|
|
9
|
+
'anthropic-messages',
|
|
10
|
+
'google-generate-content',
|
|
11
|
+
'google-interactions',
|
|
12
|
+
];
|
|
13
|
+
/** 模型能力(目录元数据:发不发图片 / 开不开推理由调用方据此决定)。 */
|
|
14
|
+
export const LLM_CAPABILITIES = ['vision', 'video', 'reasoning'];
|
|
15
|
+
/** 厂商类型。一种类型对应一个适配器(`VENDOR_ADAPTERS`)。 */
|
|
16
|
+
export const VENDOR_KINDS = [
|
|
17
|
+
'openai',
|
|
18
|
+
'generic',
|
|
19
|
+
'deepseek',
|
|
20
|
+
'moonshotai',
|
|
21
|
+
'alibaba',
|
|
22
|
+
'zhipu',
|
|
23
|
+
'volcengine',
|
|
24
|
+
'minimax',
|
|
25
|
+
'dots',
|
|
26
|
+
'google',
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* 推理档位——**我们自己的抽象**,不是任何一家的原生枚举,各家适配器的 `reasoning()` 把它翻译成自己的形状:
|
|
30
|
+
*
|
|
31
|
+
* - `off` 发**真正的关闭指令**(deepseek 默认开着推理,「不发」≠ 关闭);只有厂商根本没有关闭开关时
|
|
32
|
+
* (如 kimi-k3)才不发。
|
|
33
|
+
* - `minimal` 只有 openai 有,其余家降档 `low`。
|
|
34
|
+
* - `max` 是 deepseek 与 kimi-k3 的原生最高档,openai 映射到 `xhigh`。
|
|
35
|
+
* - 只有开关没有档位的家(alibaba、kimi-k2.x),非 `off` 一律塌缩成「开」。
|
|
36
|
+
*/
|
|
37
|
+
export const REASONING_EFFORTS = [
|
|
38
|
+
'off',
|
|
39
|
+
'minimal',
|
|
40
|
+
'low',
|
|
41
|
+
'medium',
|
|
42
|
+
'high',
|
|
43
|
+
'max',
|
|
44
|
+
];
|
|
45
|
+
/** 中心的错误码(响应体 `{ code, message }`)。 */
|
|
46
|
+
export const CENTER_ERROR_CODES = [
|
|
47
|
+
'unauthorized',
|
|
48
|
+
'forbidden',
|
|
49
|
+
'tenant_disabled',
|
|
50
|
+
'not_found',
|
|
51
|
+
'invalid_request',
|
|
52
|
+
'conflict',
|
|
53
|
+
'unprocessable',
|
|
54
|
+
'upstream_error',
|
|
55
|
+
'admin_unavailable',
|
|
56
|
+
'vendor_not_allowed',
|
|
57
|
+
'no_credential',
|
|
58
|
+
'pinned_credential_unavailable',
|
|
59
|
+
];
|
|
60
|
+
/** 中心的请求头 / 响应头。 */
|
|
61
|
+
export const PC_HEADERS = {
|
|
62
|
+
/** 接入方 API key(`pc_…`)。 */
|
|
63
|
+
key: 'x-pc-key',
|
|
64
|
+
/** 会话粘性键:同一个键在健康的 key 里固定落到同一把。 */
|
|
65
|
+
affinity: 'x-pc-affinity',
|
|
66
|
+
/** 钉住某把 key(值是 `credential` 响应头给过的 ref),不可用时报错不切换。 */
|
|
67
|
+
pin: 'x-pc-pin',
|
|
68
|
+
/** 响应头:这次实际用的 key(不透明 ref)。 */
|
|
69
|
+
credential: 'x-pc-credential',
|
|
70
|
+
/** 响应头:这次换过几次 key。 */
|
|
71
|
+
switches: 'x-pc-switches',
|
|
72
|
+
};
|
|
73
|
+
/** 透传路由前缀:`<中心>/v1/proxy/<厂商 slug>/<厂商 URL 的完整 pathname>`。 */
|
|
74
|
+
export const PROXY_ROUTE_PREFIX = '/v1/proxy';
|
|
75
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6BAA6B;AAC7B,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,yBAAyB;IACzB,kBAAkB;IAClB,oBAAoB;IACpB,yBAAyB;IACzB,qBAAqB;CACb,CAAC;AAGX,yCAAyC;AACzC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAU,CAAC;AAG1E,2CAA2C;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,SAAS;IACT,UAAU;IACV,YAAY;IACZ,SAAS;IACT,OAAO;IACP,YAAY;IACZ,SAAS;IACT,MAAM;IACN,QAAQ;CACA,CAAC;AAGX;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,KAAK;IACL,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;IACN,KAAK;CACG,CAAC;AA2CX,uCAAuC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,eAAe;IACf,gBAAgB;IAChB,mBAAmB;IACnB,oBAAoB;IACpB,eAAe;IACf,+BAA+B;CACvB,CAAC;AAGX,oBAAoB;AACpB,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,2BAA2B;IAC3B,GAAG,EAAE,UAAU;IACf,mCAAmC;IACnC,QAAQ,EAAE,eAAe;IACzB,sDAAsD;IACtD,GAAG,EAAE,UAAU;IACf,+BAA+B;IAC/B,UAAU,EAAE,iBAAiB;IAC7B,sBAAsB;IACtB,QAAQ,EAAE,eAAe;CACjB,CAAC;AAEX,8DAA8D;AAC9D,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
* 阿里云百炼(DashScope)。两条协议**同一个根** `/compatible-mode/v1`,SDK 各自拼
|
|
6
|
+
* `/chat/completions` 与 `/responses`(文档 `referenes/alibaba-model.md`;百炼另有
|
|
7
|
+
* 业务空间专属域名 `https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com`,公共域名
|
|
8
|
+
* 「现有域名仍可正常使用」,预填公共域名——专属域名要填业务空间 ID,运营自己换)。
|
|
9
|
+
*
|
|
10
|
+
* **responses 面的判据来自 2026-08-27 对 `qwen3.8-flash` 的探针**,文档与实况有一处
|
|
11
|
+
* 出入必须以实况为准:文档示例里流式推理事件写的是 OpenAI 原生的
|
|
12
|
+
* `response.reasoning_summary_text.delta`,**真机回的是 `response.reasoning_text.delta`
|
|
13
|
+
* / `.done`(带 `content_index`)**——与 DeepSeek、智谱同一形状,所以同样挂
|
|
14
|
+
* `withReasoningTextResponsesShim`;而 `output_item.added/done`、`response.completed`
|
|
15
|
+
* 与非流式响应体里的 reasoning item 用的**是**原生 `summary[{summary_text}]`,垫片
|
|
16
|
+
* 对已有非空 `summary` 的 item 不动,两种形状在同一条流里各自落到位。SSE 还多发
|
|
17
|
+
* `id:` 与 `:HTTP_STATUS/200` 两行,SDK 的解析器按规范忽略。
|
|
18
|
+
*/
|
|
19
|
+
export declare class AlibabaAdapter extends LlmVendorAdapter {
|
|
20
|
+
readonly kind: "alibaba";
|
|
21
|
+
readonly supportedProtocols: readonly LlmProtocol[];
|
|
22
|
+
createModel(input: CreateModelInput): LanguageModel;
|
|
23
|
+
/**
|
|
24
|
+
* **chat-completions** 只有开关,没有档位:`alibabaLanguageModelChatOptions` 就
|
|
25
|
+
* `enableThinking`(布尔)+ `thinkingBudget`(token 数),没有 `reasoningEffort`。
|
|
26
|
+
* 非 off 的四个档位一律塌缩成"开"——**如实映射,不发明厂商没有的粒度**
|
|
27
|
+
* (thinking budget 是 token 数,不是档位,替用户拍一个数没有依据)。
|
|
28
|
+
*
|
|
29
|
+
* **responses** 只有 `reasoning.effort` 一个开关,厂商原生七档
|
|
30
|
+
* `none/minimal/low/medium/high/xhigh/max`(默认 `xhigh`;文档:`xhigh`/`max`
|
|
31
|
+
* 仅北京、新加坡地域)。我们的六档**逐个都有同名原生档**,一律直通、不映射:
|
|
32
|
+
* `off`→`none` 是真正的关闭指令(探针 `reasoning_tokens: 0`、不出 reasoning
|
|
33
|
+
* item),`minimal` 与 `max` 各自 200。文档还说 `enable_thinking` 将废弃、
|
|
34
|
+
* `reasoning.effort` 优先级更高,所以这个面上只发 effort。key 随承载包换成
|
|
35
|
+
* `openai`,并带 `COMPATIBLE_RESPONSES_OPTIONS`(不带则 SDK 按模型名判成非推理
|
|
36
|
+
* 模型、`reasoning` 整个不发——它默认 `xhigh`,「不发 ≠ 关闭」在这家也成立;
|
|
37
|
+
* `developer` 角色实测也收,但只保证 `system`)。代价同 DeepSeek:SDK 在
|
|
38
|
+
* `forceReasoning` 下剥掉 `temperature`/`top_p`(厂商本身收),记为已知限制。
|
|
39
|
+
*
|
|
40
|
+
* 请求侧回传:四种形状(原样 output / 只回 function_call / `item_reference` /
|
|
41
|
+
* `previous_response_id`)与 `store:false` 全部 200;它**会消费**回传的 reasoning
|
|
42
|
+
* item(带着回传比不带多出恰好上一轮 reasoning_tokens 的 input_tokens),SDK 默认
|
|
43
|
+
* 发什么就发什么。
|
|
44
|
+
*/
|
|
45
|
+
reasoning(_modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=alibaba.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alibaba.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/alibaba.adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,OAAO,EACL,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IAEnC,SAAkB,kBAAkB,EAAE,SAAS,WAAW,EAAE,CAG1D;IAEF,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAmBnD;;;;;;;;;;;;;;;;;;;;;OAqBG;IACM,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe;CAenB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { createAlibaba } from '@ai-sdk/alibaba';
|
|
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
|
+
* 阿里云百炼(DashScope)。两条协议**同一个根** `/compatible-mode/v1`,SDK 各自拼
|
|
7
|
+
* `/chat/completions` 与 `/responses`(文档 `referenes/alibaba-model.md`;百炼另有
|
|
8
|
+
* 业务空间专属域名 `https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com`,公共域名
|
|
9
|
+
* 「现有域名仍可正常使用」,预填公共域名——专属域名要填业务空间 ID,运营自己换)。
|
|
10
|
+
*
|
|
11
|
+
* **responses 面的判据来自 2026-08-27 对 `qwen3.8-flash` 的探针**,文档与实况有一处
|
|
12
|
+
* 出入必须以实况为准:文档示例里流式推理事件写的是 OpenAI 原生的
|
|
13
|
+
* `response.reasoning_summary_text.delta`,**真机回的是 `response.reasoning_text.delta`
|
|
14
|
+
* / `.done`(带 `content_index`)**——与 DeepSeek、智谱同一形状,所以同样挂
|
|
15
|
+
* `withReasoningTextResponsesShim`;而 `output_item.added/done`、`response.completed`
|
|
16
|
+
* 与非流式响应体里的 reasoning item 用的**是**原生 `summary[{summary_text}]`,垫片
|
|
17
|
+
* 对已有非空 `summary` 的 item 不动,两种形状在同一条流里各自落到位。SSE 还多发
|
|
18
|
+
* `id:` 与 `:HTTP_STATUS/200` 两行,SDK 的解析器按规范忽略。
|
|
19
|
+
*/
|
|
20
|
+
export class AlibabaAdapter extends LlmVendorAdapter {
|
|
21
|
+
kind = 'alibaba';
|
|
22
|
+
supportedProtocols = [
|
|
23
|
+
'openai-chat-completions',
|
|
24
|
+
'openai-responses',
|
|
25
|
+
];
|
|
26
|
+
createModel(input) {
|
|
27
|
+
switch (input.protocol) {
|
|
28
|
+
case 'openai-chat-completions': {
|
|
29
|
+
const { baseUrl, apiKey, modelId, fetch } = input;
|
|
30
|
+
// baseUrl 指 OpenAI 兼容端点(`/compatible-mode/v1`)。该包另有
|
|
31
|
+
// embedding/video 两条走 DashScope 原生端点的支线(`embeddingBaseURL`/
|
|
32
|
+
// `videoBaseURL`),本仓只用 languageModel,不配。
|
|
33
|
+
return createAlibaba({ baseURL: baseUrl, apiKey, fetch })(modelId);
|
|
34
|
+
}
|
|
35
|
+
case 'openai-responses':
|
|
36
|
+
return createResponsesModel(input, withReasoningTextResponsesShim(input.fetch));
|
|
37
|
+
default:
|
|
38
|
+
throw unsupportedProtocol(this, input.protocol);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* **chat-completions** 只有开关,没有档位:`alibabaLanguageModelChatOptions` 就
|
|
43
|
+
* `enableThinking`(布尔)+ `thinkingBudget`(token 数),没有 `reasoningEffort`。
|
|
44
|
+
* 非 off 的四个档位一律塌缩成"开"——**如实映射,不发明厂商没有的粒度**
|
|
45
|
+
* (thinking budget 是 token 数,不是档位,替用户拍一个数没有依据)。
|
|
46
|
+
*
|
|
47
|
+
* **responses** 只有 `reasoning.effort` 一个开关,厂商原生七档
|
|
48
|
+
* `none/minimal/low/medium/high/xhigh/max`(默认 `xhigh`;文档:`xhigh`/`max`
|
|
49
|
+
* 仅北京、新加坡地域)。我们的六档**逐个都有同名原生档**,一律直通、不映射:
|
|
50
|
+
* `off`→`none` 是真正的关闭指令(探针 `reasoning_tokens: 0`、不出 reasoning
|
|
51
|
+
* item),`minimal` 与 `max` 各自 200。文档还说 `enable_thinking` 将废弃、
|
|
52
|
+
* `reasoning.effort` 优先级更高,所以这个面上只发 effort。key 随承载包换成
|
|
53
|
+
* `openai`,并带 `COMPATIBLE_RESPONSES_OPTIONS`(不带则 SDK 按模型名判成非推理
|
|
54
|
+
* 模型、`reasoning` 整个不发——它默认 `xhigh`,「不发 ≠ 关闭」在这家也成立;
|
|
55
|
+
* `developer` 角色实测也收,但只保证 `system`)。代价同 DeepSeek:SDK 在
|
|
56
|
+
* `forceReasoning` 下剥掉 `temperature`/`top_p`(厂商本身收),记为已知限制。
|
|
57
|
+
*
|
|
58
|
+
* 请求侧回传:四种形状(原样 output / 只回 function_call / `item_reference` /
|
|
59
|
+
* `previous_response_id`)与 `store:false` 全部 200;它**会消费**回传的 reasoning
|
|
60
|
+
* item(带着回传比不带多出恰好上一轮 reasoning_tokens 的 input_tokens),SDK 默认
|
|
61
|
+
* 发什么就发什么。
|
|
62
|
+
*/
|
|
63
|
+
reasoning(_modelId, effort, protocol) {
|
|
64
|
+
switch (protocol) {
|
|
65
|
+
case 'openai-chat-completions':
|
|
66
|
+
return { alibaba: { enableThinking: effort !== 'off' } };
|
|
67
|
+
case 'openai-responses':
|
|
68
|
+
return {
|
|
69
|
+
openai: {
|
|
70
|
+
reasoningEffort: effort === 'off' ? 'none' : effort,
|
|
71
|
+
...COMPATIBLE_RESPONSES_OPTIONS,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
default:
|
|
75
|
+
throw unsupportedProtocol(this, protocol);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=alibaba.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alibaba.adapter.js","sourceRoot":"","sources":["../../src/vendors/alibaba.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AACpF,OAAO,EAEL,gBAAgB,EAGhB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACzC,IAAI,GAAG,SAAkB,CAAC;IAEjB,kBAAkB,GAA2B;QAC7D,yBAAyB;QACzB,kBAAkB;KACnB,CAAC;IAEF,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,oDAAoD;gBACpD,4DAA4D;gBAC5D,yCAAyC;gBACzC,OAAO,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;YACrE,CAAC;YACD,KAAK,kBAAkB;gBACrB,OAAO,oBAAoB,CACzB,KAAK,EACL,8BAA8B,CAAC,KAAK,CAAC,KAAK,CAAC,CAC5C,CAAC;YACJ;gBACE,MAAM,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACM,SAAS,CAChB,QAAgB,EAChB,MAAuB,EACvB,QAAqB;QAErB,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,yBAAyB;gBAC5B,OAAO,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,KAAK,KAAK,EAAE,EAAE,CAAC;YAC3D,KAAK,kBAAkB;gBACrB,OAAO;oBACL,MAAM,EAAE;wBACN,eAAe,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;wBACnD,GAAG,4BAA4B;qBAChC;iBACF,CAAC;YACJ;gBACE,MAAM,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ResponsesFetch } from './openai-responses.js';
|
|
2
|
+
/**
|
|
3
|
+
* 火山方舟(Ark)Responses 端点的 HTTP 层垫片——**只改响应、只改非流式**。
|
|
4
|
+
*
|
|
5
|
+
* 方舟的 Responses 面在推理形状上是 OpenAI 原生的(reasoning item 用
|
|
6
|
+
* `summary[{summary_text}]`、流式事件是 `response.reasoning_summary_text.delta`,
|
|
7
|
+
* 2026-09-07 对 `doubao-seed-2-1-pro` / `2-0-lite` 的探针逐字段核对过),所以
|
|
8
|
+
* **不**用 `withReasoningTextResponsesShim`。它与 OpenAI 唯一会让 SDK 炸的差异是:
|
|
9
|
+
* 非流式响应体里 `output_text` 内容块**没有 `annotations` 字段**,而
|
|
10
|
+
* `@ai-sdk/openai` 4.0.46 的非流式 zod schema 把它写成必填数组(dist:4107),
|
|
11
|
+
* 于是 `generateText` / `generateObject` 一律 `Invalid JSON response`——请求明明
|
|
12
|
+
* 200、钱也扣了,SDK 却报错。流式路径不受影响:SSE 事件的 schema 里这个字段是
|
|
13
|
+
* 可选的(真实 SDK 回放过,见 `volcengine.sdk-contract.spec.ts`),所以流式原样透传。
|
|
14
|
+
*
|
|
15
|
+
* 请求侧的两处差异(拒收 `reasoning.summary`、拒收 `item_reference`)不在这里
|
|
16
|
+
* 改:它们由 SDK 的 providerOptions 就能关掉(`reasoningSummary: null` /
|
|
17
|
+
* `store: false`),改请求体去猜 SDK 内部结构没有必要——见 `volcengine.adapter.ts`。
|
|
18
|
+
*/
|
|
19
|
+
export declare function withArkResponsesShim(base?: ResponsesFetch): NonNullable<ResponsesFetch>;
|
|
20
|
+
/**
|
|
21
|
+
* 给 response 对象里每个 `message.content[].output_text` 补上缺失的
|
|
22
|
+
* `annotations: []`。已有的不动;别的类型的 item / part 不碰。
|
|
23
|
+
*/
|
|
24
|
+
export declare function fillOutputTextAnnotations(body: unknown): void;
|
|
25
|
+
//# sourceMappingURL=ark-responses-shim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ark-responses-shim.d.ts","sourceRoot":"","sources":["../../src/vendors/ark-responses-shim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,CAAC,EAAE,cAAc,GACpB,WAAW,CAAC,cAAc,CAAC,CAe7B;AAQD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAU7D"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { withoutLength } from './responses-reasoning-text-shim.js';
|
|
2
|
+
/**
|
|
3
|
+
* 火山方舟(Ark)Responses 端点的 HTTP 层垫片——**只改响应、只改非流式**。
|
|
4
|
+
*
|
|
5
|
+
* 方舟的 Responses 面在推理形状上是 OpenAI 原生的(reasoning item 用
|
|
6
|
+
* `summary[{summary_text}]`、流式事件是 `response.reasoning_summary_text.delta`,
|
|
7
|
+
* 2026-09-07 对 `doubao-seed-2-1-pro` / `2-0-lite` 的探针逐字段核对过),所以
|
|
8
|
+
* **不**用 `withReasoningTextResponsesShim`。它与 OpenAI 唯一会让 SDK 炸的差异是:
|
|
9
|
+
* 非流式响应体里 `output_text` 内容块**没有 `annotations` 字段**,而
|
|
10
|
+
* `@ai-sdk/openai` 4.0.46 的非流式 zod schema 把它写成必填数组(dist:4107),
|
|
11
|
+
* 于是 `generateText` / `generateObject` 一律 `Invalid JSON response`——请求明明
|
|
12
|
+
* 200、钱也扣了,SDK 却报错。流式路径不受影响:SSE 事件的 schema 里这个字段是
|
|
13
|
+
* 可选的(真实 SDK 回放过,见 `volcengine.sdk-contract.spec.ts`),所以流式原样透传。
|
|
14
|
+
*
|
|
15
|
+
* 请求侧的两处差异(拒收 `reasoning.summary`、拒收 `item_reference`)不在这里
|
|
16
|
+
* 改:它们由 SDK 的 providerOptions 就能关掉(`reasoningSummary: null` /
|
|
17
|
+
* `store: false`),改请求体去猜 SDK 内部结构没有必要——见 `volcengine.adapter.ts`。
|
|
18
|
+
*/
|
|
19
|
+
export function withArkResponsesShim(base) {
|
|
20
|
+
return async (url, init) => {
|
|
21
|
+
// 延迟到调用时再取全局 fetch:测试用 vi.stubGlobal 换掉的才是这一个。
|
|
22
|
+
const res = await (base ?? globalThis.fetch)(url, init);
|
|
23
|
+
if (!res.ok || !res.body)
|
|
24
|
+
return res;
|
|
25
|
+
const contentType = res.headers.get('content-type') ?? '';
|
|
26
|
+
if (!contentType.includes('application/json'))
|
|
27
|
+
return res;
|
|
28
|
+
const body = await res.json();
|
|
29
|
+
fillOutputTextAnnotations(body);
|
|
30
|
+
return new Response(JSON.stringify(body), {
|
|
31
|
+
status: res.status,
|
|
32
|
+
statusText: res.statusText,
|
|
33
|
+
headers: withoutLength(res.headers),
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function isObject(v) {
|
|
38
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 给 response 对象里每个 `message.content[].output_text` 补上缺失的
|
|
42
|
+
* `annotations: []`。已有的不动;别的类型的 item / part 不碰。
|
|
43
|
+
*/
|
|
44
|
+
export function fillOutputTextAnnotations(body) {
|
|
45
|
+
if (!isObject(body) || !Array.isArray(body.output))
|
|
46
|
+
return;
|
|
47
|
+
for (const item of body.output) {
|
|
48
|
+
if (!isObject(item) || item.type !== 'message')
|
|
49
|
+
continue;
|
|
50
|
+
if (!Array.isArray(item.content))
|
|
51
|
+
continue;
|
|
52
|
+
for (const part of item.content) {
|
|
53
|
+
if (!isObject(part) || part.type !== 'output_text')
|
|
54
|
+
continue;
|
|
55
|
+
if (part.annotations == null)
|
|
56
|
+
part.annotations = [];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=ark-responses-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ark-responses-shim.js","sourceRoot":"","sources":["../../src/vendors/ark-responses-shim.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AAEnE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAqB;IAErB,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,+CAA+C;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;YAAE,OAAO,GAAG,CAAC;QACrC,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAAE,OAAO,GAAG,CAAC;QAC1D,MAAM,IAAI,GAAY,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACvC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE;YACxC,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;SACpC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAID,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAa;IACrD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO;IAC3D,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACzD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,SAAS;QAC3C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa;gBAAE,SAAS;YAC7D,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI;gBAAE,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { LanguageModel } from 'ai';
|
|
2
|
+
import type { LlmProtocol } from '../types.js';
|
|
3
|
+
import { type CreateModelInput, LlmVendorAdapter, type ProviderOptions, type ReasoningEffort, type VendorFileStore } from './vendor-adapter.js';
|
|
4
|
+
export declare class DeepSeekAdapter extends LlmVendorAdapter {
|
|
5
|
+
readonly kind: "deepseek";
|
|
6
|
+
readonly supportedProtocols: readonly LlmProtocol[];
|
|
7
|
+
/**
|
|
8
|
+
* responses 走 `@ai-sdk/openai` + HTTP 垫片,**不是** `@ai-sdk/deepseek`——那个包
|
|
9
|
+
* 只有 chat-completions;垫片的由来见 `responses-reasoning-text-shim.ts` 头注释。
|
|
10
|
+
*/
|
|
11
|
+
createModel(input: CreateModelInput): LanguageModel;
|
|
12
|
+
/**
|
|
13
|
+
* Files API(<https://api-docs.deepseek.com/guides/files_api>):`POST /files`
|
|
14
|
+
* 挂在与 chat 同一个根上,`purpose` 固定 `user_data`,`expires_after` 1h–30d
|
|
15
|
+
* 或省略=永久;只收 JPEG/PNG/GIF/WebP、单文件 64 MiB。承载用 `@ai-sdk/deepseek`
|
|
16
|
+
* 的 `files().uploadFile()`(两种协议都用它上传——它只是个 multipart POST,与
|
|
17
|
+
* 线协议无关),而**引用 key 跟协议走**:chat 的 user 消息由 `@ai-sdk/deepseek`
|
|
18
|
+
* 翻成 `{type:'file', file_id}`,responses 由 `@ai-sdk/openai` 翻成
|
|
19
|
+
* `{type:'input_image', file_id}`,两家读的命名空间不同。
|
|
20
|
+
*
|
|
21
|
+
* baseUrl 尾部的 `/v1` 要剥掉:Files API 文档给的根是
|
|
22
|
+
* `https://api.deepseek.com`,运营两种写法都可能填。
|
|
23
|
+
*/
|
|
24
|
+
createFileStore(input: CreateModelInput): VendorFileStore;
|
|
25
|
+
/**
|
|
26
|
+
* chat-completions 有两个开关,形状不同(`referenes/deepseek-request.md` §2):
|
|
27
|
+
*
|
|
28
|
+
* - 关闭走 `thinking:{type:'disabled'}`(默认是 `enabled`,**不发 ≠ 关闭**,
|
|
29
|
+
* 已用真实 API 实测)。
|
|
30
|
+
* - 档位走**顶层** `reasoning_effort`。别试图发嵌套的
|
|
31
|
+
* `thinking:{type,reasoningEffort}`——实测 SDK 会把嵌套里的 effort 整个吞掉,
|
|
32
|
+
* 只发出 `{"thinking":{"type":"enabled"}}`,档位静默丢失。
|
|
33
|
+
*
|
|
34
|
+
* 档位只发它的原生三档 `low/high/max`:`minimal` 降 `low`(openai 独有档位),
|
|
35
|
+
* `medium` 升 `high`(vendor 侧本来也这么映射)。**别改回原样发 `medium`**——
|
|
36
|
+
* `@ai-sdk/deepseek` 3.0.32 起会在客户端替你映射成 `high`,但每次调用附带一条
|
|
37
|
+
* `compatibility` 警告刷进日志(`deepseek-chat.sdk-contract.spec.ts` 钉住)。
|
|
38
|
+
* v4-pro 的 `low` 仍由 vendor 侧自动映射 `high`。
|
|
39
|
+
*
|
|
40
|
+
* 推理开着时 SDK 还会带警告剥掉 `temperature`/`top_p`(厂商文档:思考模式下
|
|
41
|
+
* 二者无效)。服务端行为不变,故不在 `sampling` 上跟着声明。
|
|
42
|
+
*
|
|
43
|
+
* responses 只有一个开关 `reasoning.effort`,且 **`none` 就是关闭**
|
|
44
|
+
* (探针:`reasoning_tokens: 0`、不出 reasoning item),`max` 原样收;key 随
|
|
45
|
+
* 承载包换成 `openai`,并带 `COMPATIBLE_RESPONSES_OPTIONS`(不带则 SDK 按模型名
|
|
46
|
+
* 判成非推理模型、`reasoning` 整个不发——又是一次「不发 ≠ 关闭」)。
|
|
47
|
+
*/
|
|
48
|
+
reasoning(_modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=deepseek.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/deepseek.adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAExC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,OAAO,EACL,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AAK7B,qBAAa,eAAgB,SAAQ,gBAAgB;IACnD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IAEpC,SAAkB,kBAAkB,EAAE,SAAS,WAAW,EAAE,CAG1D;IAEF;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAgBnD;;;;;;;;;;;OAWG;IACM,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,eAAe;IA6ClE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACM,SAAS,CAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe;CAqBnB"}
|