@qjp88995/provider-client 0.0.0-stage → 0.1.0

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 (122) hide show
  1. package/dist/center-fetch.d.ts +29 -0
  2. package/dist/center-fetch.d.ts.map +1 -0
  3. package/dist/center-fetch.js +45 -0
  4. package/dist/center-fetch.js.map +1 -0
  5. package/dist/direct-resolver.d.ts +29 -0
  6. package/dist/direct-resolver.d.ts.map +1 -0
  7. package/dist/direct-resolver.js +47 -0
  8. package/dist/direct-resolver.js.map +1 -0
  9. package/dist/errors.d.ts +38 -0
  10. package/dist/errors.d.ts.map +1 -0
  11. package/dist/errors.js +57 -0
  12. package/dist/errors.js.map +1 -0
  13. package/dist/index.d.ts +9 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +8 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/model-handle.d.ts +92 -0
  18. package/dist/model-handle.d.ts.map +1 -0
  19. package/dist/model-handle.js +72 -0
  20. package/dist/model-handle.js.map +1 -0
  21. package/dist/provider-client.d.ts +40 -0
  22. package/dist/provider-client.d.ts.map +1 -0
  23. package/dist/provider-client.js +96 -0
  24. package/dist/provider-client.js.map +1 -0
  25. package/dist/to-error.d.ts +12 -0
  26. package/dist/to-error.d.ts.map +1 -0
  27. package/dist/to-error.js +33 -0
  28. package/dist/to-error.js.map +1 -0
  29. package/dist/types.d.ts +78 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +75 -0
  32. package/dist/types.js.map +1 -0
  33. package/dist/vendors/alibaba.adapter.d.ts +47 -0
  34. package/dist/vendors/alibaba.adapter.d.ts.map +1 -0
  35. package/dist/vendors/alibaba.adapter.js +79 -0
  36. package/dist/vendors/alibaba.adapter.js.map +1 -0
  37. package/dist/vendors/ark-responses-shim.d.ts +25 -0
  38. package/dist/vendors/ark-responses-shim.d.ts.map +1 -0
  39. package/dist/vendors/ark-responses-shim.js +60 -0
  40. package/dist/vendors/ark-responses-shim.js.map +1 -0
  41. package/dist/vendors/deepseek.adapter.d.ts +50 -0
  42. package/dist/vendors/deepseek.adapter.d.ts.map +1 -0
  43. package/dist/vendors/deepseek.adapter.js +123 -0
  44. package/dist/vendors/deepseek.adapter.js.map +1 -0
  45. package/dist/vendors/dots.adapter.d.ts +32 -0
  46. package/dist/vendors/dots.adapter.d.ts.map +1 -0
  47. package/dist/vendors/dots.adapter.js +53 -0
  48. package/dist/vendors/dots.adapter.js.map +1 -0
  49. package/dist/vendors/generic.adapter.d.ts +33 -0
  50. package/dist/vendors/generic.adapter.d.ts.map +1 -0
  51. package/dist/vendors/generic.adapter.js +82 -0
  52. package/dist/vendors/generic.adapter.js.map +1 -0
  53. package/dist/vendors/google-signature.d.ts +17 -0
  54. package/dist/vendors/google-signature.d.ts.map +1 -0
  55. package/dist/vendors/google-signature.js +69 -0
  56. package/dist/vendors/google-signature.js.map +1 -0
  57. package/dist/vendors/google.adapter.d.ts +41 -0
  58. package/dist/vendors/google.adapter.d.ts.map +1 -0
  59. package/dist/vendors/google.adapter.js +164 -0
  60. package/dist/vendors/google.adapter.js.map +1 -0
  61. package/dist/vendors/index.d.ts +11 -0
  62. package/dist/vendors/index.d.ts.map +1 -0
  63. package/dist/vendors/index.js +39 -0
  64. package/dist/vendors/index.js.map +1 -0
  65. package/dist/vendors/minimax.adapter.d.ts +98 -0
  66. package/dist/vendors/minimax.adapter.d.ts.map +1 -0
  67. package/dist/vendors/minimax.adapter.js +163 -0
  68. package/dist/vendors/minimax.adapter.js.map +1 -0
  69. package/dist/vendors/moonshotai.adapter.d.ts +31 -0
  70. package/dist/vendors/moonshotai.adapter.d.ts.map +1 -0
  71. package/dist/vendors/moonshotai.adapter.js +57 -0
  72. package/dist/vendors/moonshotai.adapter.js.map +1 -0
  73. package/dist/vendors/openai-responses.d.ts +49 -0
  74. package/dist/vendors/openai-responses.d.ts.map +1 -0
  75. package/dist/vendors/openai-responses.js +64 -0
  76. package/dist/vendors/openai-responses.js.map +1 -0
  77. package/dist/vendors/openai.adapter.d.ts +27 -0
  78. package/dist/vendors/openai.adapter.d.ts.map +1 -0
  79. package/dist/vendors/openai.adapter.js +196 -0
  80. package/dist/vendors/openai.adapter.js.map +1 -0
  81. package/dist/vendors/responses-reasoning-text-shim.d.ts +50 -0
  82. package/dist/vendors/responses-reasoning-text-shim.d.ts.map +1 -0
  83. package/dist/vendors/responses-reasoning-text-shim.js +170 -0
  84. package/dist/vendors/responses-reasoning-text-shim.js.map +1 -0
  85. package/dist/vendors/vendor-adapter.d.ts +214 -0
  86. package/dist/vendors/vendor-adapter.d.ts.map +1 -0
  87. package/dist/vendors/vendor-adapter.js +150 -0
  88. package/dist/vendors/vendor-adapter.js.map +1 -0
  89. package/dist/vendors/volcengine.adapter.d.ts +74 -0
  90. package/dist/vendors/volcengine.adapter.d.ts.map +1 -0
  91. package/dist/vendors/volcengine.adapter.js +139 -0
  92. package/dist/vendors/volcengine.adapter.js.map +1 -0
  93. package/dist/vendors/zhipu.adapter.d.ts +81 -0
  94. package/dist/vendors/zhipu.adapter.d.ts.map +1 -0
  95. package/dist/vendors/zhipu.adapter.js +133 -0
  96. package/dist/vendors/zhipu.adapter.js.map +1 -0
  97. package/package.json +53 -3
  98. package/src/center-fetch.ts +69 -0
  99. package/src/direct-resolver.ts +90 -0
  100. package/src/errors.ts +88 -0
  101. package/src/index.ts +54 -0
  102. package/src/model-handle.ts +197 -0
  103. package/src/provider-client.ts +136 -0
  104. package/src/to-error.ts +39 -0
  105. package/src/types.ts +126 -0
  106. package/src/vendors/alibaba.adapter.ts +101 -0
  107. package/src/vendors/ark-responses-shim.ts +60 -0
  108. package/src/vendors/deepseek.adapter.ts +155 -0
  109. package/src/vendors/dots.adapter.ts +69 -0
  110. package/src/vendors/generic.adapter.ts +103 -0
  111. package/src/vendors/google-signature.ts +87 -0
  112. package/src/vendors/google.adapter.ts +197 -0
  113. package/src/vendors/index.ts +56 -0
  114. package/src/vendors/minimax.adapter.ts +193 -0
  115. package/src/vendors/moonshotai.adapter.ts +84 -0
  116. package/src/vendors/openai-responses.ts +82 -0
  117. package/src/vendors/openai.adapter.ts +235 -0
  118. package/src/vendors/responses-reasoning-text-shim.ts +174 -0
  119. package/src/vendors/vendor-adapter.ts +294 -0
  120. package/src/vendors/volcengine.adapter.ts +166 -0
  121. package/src/vendors/zhipu.adapter.ts +169 -0
  122. package/README.md +0 -3
@@ -0,0 +1,49 @@
1
+ import { createOpenAI } from '@ai-sdk/openai';
2
+ import type { JSONValue, LanguageModel, LanguageModelMiddleware } from 'ai';
3
+ import type { CreateModelInput } from './vendor-adapter.js';
4
+ /**
5
+ * `createOpenAI` 接受的自定义 fetch。类型从工厂签名上取,不为此多引一个
6
+ * `@ai-sdk/provider-utils` 依赖——它是 `@ai-sdk/openai` 的内部依赖,版本跟着走。
7
+ */
8
+ export type ResponsesFetch = NonNullable<Parameters<typeof createOpenAI>[0]>['fetch'];
9
+ /**
10
+ * `openai-responses` 协议的句柄,三家(openai / generic / deepseek)共用:
11
+ * 线格式由 OpenAI 定义,别家只是「兼容」,所以承载它的包也只有 `@ai-sdk/openai`
12
+ * 这一个——`@ai-sdk/deepseek` 3.0.x 只有 chat-completions(已核 dist:路径里只有
13
+ * `/chat/completions`,`DeepSeekProvider` 也只暴露 `chat()`),别去那里找开关。
14
+ *
15
+ * 兼容厂商的差异用 `fetch` 垫片在 HTTP 层抹平(见 `responses-reasoning-text-shim.ts`),
16
+ * SDK 一行不动。
17
+ */
18
+ export declare function createResponsesModel(input: CreateModelInput, fetch?: ResponsesFetch): LanguageModel;
19
+ /**
20
+ * 兼容厂商走 responses 协议时 `providerOptions.openai` 里必带的两项。
21
+ *
22
+ * - **`forceReasoning: true`**:`@ai-sdk/openai` 的 responses 模型按**模型名**
23
+ * 判断「是不是推理模型」(`o` 系 / `gpt-5+`),不是就**整个不发 `reasoning`
24
+ * 参数**——`deepseek-v4-flash` 这种名字下档位与关闭指令会静默丢光,而
25
+ * DeepSeek 默认开着推理,「不发 ≠ 关闭」在这里再次成立。已核 4.0.46 dist
26
+ * (`isReasoningModel = forceReasoning ?? modelCapabilities.isReasoningModel`)。
27
+ * 代价:SDK 在推理模型上会剥掉 `temperature`/`top_p` 并打 warning——DeepSeek
28
+ * 文档本就声明思考模式下二者无效,可接受;`off` 时也会被剥,记为已知限制。
29
+ * - **`systemMessageMode: 'system'`**:推理模型默认把 system 消息发成
30
+ * `developer` 角色,那是 OpenAI 自家的规矩,兼容厂商只保证认 `system`。
31
+ *
32
+ * OpenAI 官方**不**用这组:它的模型名 SDK 认得,强制反而会给 `gpt-4.1` 这类
33
+ * 非推理模型发 `reasoning` 参数而 400。
34
+ */
35
+ export declare const COMPATIBLE_RESPONSES_OPTIONS: {
36
+ readonly forceReasoning: true;
37
+ readonly systemMessageMode: "system";
38
+ };
39
+ /**
40
+ * 给 responses 句柄挂一层「每次调用必带的 `providerOptions.openai` 默认值」。
41
+ *
42
+ * 用它而不是把默认值放进 `reasoning()`:那条只对标了 `reasoning` 能力的模型行
43
+ * 才会被问,而这些默认值**与有没有推理无关**(方舟不带 `store:false` 多步工具
44
+ * 回环第二步就 400,MiniMax 的 InputItem 根本没有 `item_reference` 这一型)。
45
+ * 调用方显式给的同名选项优先(spread 在后)。首个使用者是方舟
46
+ * (`ARK_RESPONSES_DEFAULTS`),MiniMax 用同一组值。
47
+ */
48
+ export declare function responsesDefaultsMiddleware(defaults: Readonly<Record<string, JSONValue>>): LanguageModelMiddleware;
49
+ //# sourceMappingURL=openai-responses.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/vendors/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,IAAI,CAAC;AAE5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,CACtC,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CACnC,CAAC,OAAO,CAAC,CAAC;AAEX;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,gBAAgB,EACvB,KAAK,CAAC,EAAE,cAAc,GACrB,aAAa,CAQf;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B;;;CAG/B,CAAC;AAEX;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,GAC5C,uBAAuB,CAczB"}
@@ -0,0 +1,64 @@
1
+ import { createOpenAI } from '@ai-sdk/openai';
2
+ /**
3
+ * `openai-responses` 协议的句柄,三家(openai / generic / deepseek)共用:
4
+ * 线格式由 OpenAI 定义,别家只是「兼容」,所以承载它的包也只有 `@ai-sdk/openai`
5
+ * 这一个——`@ai-sdk/deepseek` 3.0.x 只有 chat-completions(已核 dist:路径里只有
6
+ * `/chat/completions`,`DeepSeekProvider` 也只暴露 `chat()`),别去那里找开关。
7
+ *
8
+ * 兼容厂商的差异用 `fetch` 垫片在 HTTP 层抹平(见 `responses-reasoning-text-shim.ts`),
9
+ * SDK 一行不动。
10
+ */
11
+ export function createResponsesModel(input, fetch) {
12
+ const { baseUrl, apiKey, modelId } = input;
13
+ // 垫片自己以 `input.fetch` 为 base(见各家 createModel),没有垫片时直接用它。
14
+ return createOpenAI({
15
+ baseURL: baseUrl,
16
+ apiKey,
17
+ fetch: fetch ?? input.fetch,
18
+ }).responses(modelId);
19
+ }
20
+ /**
21
+ * 兼容厂商走 responses 协议时 `providerOptions.openai` 里必带的两项。
22
+ *
23
+ * - **`forceReasoning: true`**:`@ai-sdk/openai` 的 responses 模型按**模型名**
24
+ * 判断「是不是推理模型」(`o` 系 / `gpt-5+`),不是就**整个不发 `reasoning`
25
+ * 参数**——`deepseek-v4-flash` 这种名字下档位与关闭指令会静默丢光,而
26
+ * DeepSeek 默认开着推理,「不发 ≠ 关闭」在这里再次成立。已核 4.0.46 dist
27
+ * (`isReasoningModel = forceReasoning ?? modelCapabilities.isReasoningModel`)。
28
+ * 代价:SDK 在推理模型上会剥掉 `temperature`/`top_p` 并打 warning——DeepSeek
29
+ * 文档本就声明思考模式下二者无效,可接受;`off` 时也会被剥,记为已知限制。
30
+ * - **`systemMessageMode: 'system'`**:推理模型默认把 system 消息发成
31
+ * `developer` 角色,那是 OpenAI 自家的规矩,兼容厂商只保证认 `system`。
32
+ *
33
+ * OpenAI 官方**不**用这组:它的模型名 SDK 认得,强制反而会给 `gpt-4.1` 这类
34
+ * 非推理模型发 `reasoning` 参数而 400。
35
+ */
36
+ export const COMPATIBLE_RESPONSES_OPTIONS = {
37
+ forceReasoning: true,
38
+ systemMessageMode: 'system',
39
+ };
40
+ /**
41
+ * 给 responses 句柄挂一层「每次调用必带的 `providerOptions.openai` 默认值」。
42
+ *
43
+ * 用它而不是把默认值放进 `reasoning()`:那条只对标了 `reasoning` 能力的模型行
44
+ * 才会被问,而这些默认值**与有没有推理无关**(方舟不带 `store:false` 多步工具
45
+ * 回环第二步就 400,MiniMax 的 InputItem 根本没有 `item_reference` 这一型)。
46
+ * 调用方显式给的同名选项优先(spread 在后)。首个使用者是方舟
47
+ * (`ARK_RESPONSES_DEFAULTS`),MiniMax 用同一组值。
48
+ */
49
+ export function responsesDefaultsMiddleware(defaults) {
50
+ return {
51
+ specificationVersion: 'v4',
52
+ transformParams: ({ params }) => {
53
+ const openai = params.providerOptions?.openai ?? {};
54
+ return Promise.resolve({
55
+ ...params,
56
+ providerOptions: {
57
+ ...params.providerOptions,
58
+ openai: { ...defaults, ...openai },
59
+ },
60
+ });
61
+ },
62
+ };
63
+ }
64
+ //# sourceMappingURL=openai-responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/vendors/openai-responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAa9C;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAuB,EACvB,KAAsB;IAEtB,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC3C,yDAAyD;IACzD,OAAO,YAAY,CAAC;QAClB,OAAO,EAAE,OAAO;QAChB,MAAM;QACN,KAAK,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK;KAC5B,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,cAAc,EAAE,IAAI;IACpB,iBAAiB,EAAE,QAAQ;CACnB,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAA6C;IAE7C,OAAO;QACL,oBAAoB,EAAE,IAAI;QAC1B,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;YAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,EAAE,MAAM,IAAI,EAAE,CAAC;YACpD,OAAO,OAAO,CAAC,OAAO,CAAC;gBACrB,GAAG,MAAM;gBACT,eAAe,EAAE;oBACf,GAAG,MAAM,CAAC,eAAe;oBACzB,MAAM,EAAE,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE;iBACnC;aACF,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
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
+ export declare class OpenAiAdapter extends LlmVendorAdapter {
5
+ readonly kind: "openai";
6
+ readonly supportedProtocols: readonly LlmProtocol[];
7
+ createModel(input: CreateModelInput): LanguageModel;
8
+ /**
9
+ * 判据与 `reasoning()` 同源(`parseGpt` / `serverEfforts` / `chatToolsNeedNone`):
10
+ * 实际走 chat 而型号在 chat 下带不了工具(报错原文让改用 Responses)、非推理模型
11
+ * 标了推理(档位不会下发)、推理模型没标推理(档位不会下发,按默认档跑)。
12
+ */
13
+ adviseModel(model: AdviceModelView): ModelAdvice[];
14
+ /**
15
+ * **档位是模型级的**(判据见 `serverEfforts`):同一个「关闭」,gpt-5.5 发
16
+ * `none`、gpt-5 只能发 `minimal`、gpt-6-astra 只能发 `low`;同一个「最高」,
17
+ * gpt-5.2 发 `xhigh`、gpt-6 走 responses 发 `max`。发了模型不认的档位,
18
+ * 服务端 400;gpt-6 系还有一层 SDK 自己的校验,不认的档位**静默丢掉**只打
19
+ * warning,模型按默认档跑——两种都不报到我们这边来,所以在这里按模型算好。
20
+ *
21
+ * 不是推理模型(`gpt-4.1`)时什么都不发:后台把它误标成 reasoning 也不该 400。
22
+ * 两种协议的 key 都是 `openai`;**不**带 `forceReasoning`:SDK 认得自家模型名,
23
+ * 强制会给非推理模型发 `reasoning` 而 400。
24
+ */
25
+ reasoning(modelId: string, effort: ReasoningEffort, protocol: LlmProtocol): ProviderOptions | undefined;
26
+ }
27
+ //# sourceMappingURL=openai.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.adapter.d.ts","sourceRoot":"","sources":["../../src/vendors/openai.adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAqB,MAAM,IAAI,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,eAAe,EAErB,MAAM,qBAAqB,CAAC;AA8H7B,qBAAa,aAAc,SAAQ,gBAAgB;IACjD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,SAAkB,kBAAkB,EAAE,SAAS,WAAW,EAAE,CAG1D;IAEF,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa;IAqBnD;;;;OAIG;IACM,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,WAAW,EAAE;IAgC3D;;;;;;;;;;OAUG;IACM,SAAS,CAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACvB,QAAQ,EAAE,WAAW,GACpB,eAAe,GAAG,SAAS;CAY/B"}
@@ -0,0 +1,196 @@
1
+ import { createOpenAI } from '@ai-sdk/openai';
2
+ import { wrapLanguageModel } from 'ai';
3
+ import { createResponsesModel, responsesDefaultsMiddleware, } from './openai-responses.js';
4
+ import { LlmVendorAdapter, unsupportedProtocol, } from './vendor-adapter.js';
5
+ /** 所有推理模型都认的三档;认不出的模型只发这几个。 */
6
+ const COMMON = ['low', 'medium', 'high'];
7
+ function parseGpt(modelId) {
8
+ const m = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/.exec(modelId);
9
+ if (!m)
10
+ return null;
11
+ const major = Number(m[1]);
12
+ const variant = m[3] ?? '';
13
+ const chatAlias = major === 5 && m[2] === undefined && variant.startsWith('chat');
14
+ return {
15
+ major,
16
+ minor: m[2] === undefined ? 0 : Number(m[2]),
17
+ variant,
18
+ reasoning: major >= 5 && !chatAlias,
19
+ };
20
+ }
21
+ /**
22
+ * Chat Completions 带工具时只认 `none` 的家族:gpt-5.4 起(含 gpt-6 系)。探针:
23
+ * gpt-5.4 / 5.4-mini / 5.5 开任何推理档都 400「Function tools with reasoning_effort
24
+ * are not supported … use /v1/responses or set reasoning_effort to 'none'」,
25
+ * gpt-5.6 与 gpt-6-sol 连不发都 400(默认 medium),gpt-5.2 及更早、o 系不受限。
26
+ */
27
+ function chatToolsNeedNone(modelId) {
28
+ const gpt = parseGpt(modelId);
29
+ if (!gpt?.reasoning)
30
+ return false;
31
+ return gpt.major >= 6 || gpt.minor >= 4;
32
+ }
33
+ /**
34
+ * 这个模型在**服务端**认哪些档位(不含 `max` 的协议差异,见 `effortsFor`)。
35
+ * `null` = 不是推理模型(`gpt-4.1` 这类收到任何推理参数都 400)。
36
+ *
37
+ * 全部来自 2026-10-23 真 key 探针(16 个文本模型 × 7 档 × 两种协议 + nano /
38
+ * codex / pro 变体,两种协议的结论一致):
39
+ *
40
+ * - o 系(o3 / o4-mini):只有 low / medium / high。
41
+ * - gpt-5 / -mini / -nano:`minimal` 有、`none` 没有、`xhigh` 没有。
42
+ * - gpt-5.1:`none` 有、`minimal` 没了、`xhigh` 还没有。
43
+ * - gpt-5.2 ~ 5.5(含 -mini / -nano / 5.3-codex):none + 三档 + xhigh。
44
+ * - gpt-5.6-* 与 gpt-6-sol / gpt-6-luna:再加 `max`。
45
+ * - 其余 gpt-6+(gpt-6-astra、gpt-6.1-sol):没有 `none`(官方文档也这么写)。
46
+ * - pro:gpt-5-pro 只认 high;更新的 pro(5.5-pro 探过)认 medium / high / xhigh。
47
+ *
48
+ * 名字按 SDK 同一条正则拆(`gpt-<major>[.<minor>][-<variant>]`,带日期后缀的
49
+ * 快照也落在同一档);拆不出的 gpt 名字与未来的家族按 `COMMON` 走——猜成
50
+ * 「认」是 400,猜成「不认」只是退到相邻一档。
51
+ */
52
+ function serverEfforts(modelId) {
53
+ if (/^o\d+(?:-|$)/.test(modelId))
54
+ return COMMON;
55
+ const gpt = parseGpt(modelId);
56
+ if (!gpt)
57
+ return COMMON;
58
+ const { major, minor, variant } = gpt;
59
+ if (!gpt.reasoning)
60
+ return null;
61
+ if (variant.startsWith('pro')) {
62
+ return major === 5 && minor === 0 ? ['high'] : ['medium', 'high', 'xhigh'];
63
+ }
64
+ if (major >= 6) {
65
+ const withNone = modelId === 'gpt-6-sol' || modelId === 'gpt-6-luna';
66
+ return [
67
+ ...(withNone ? ['none'] : []),
68
+ ...COMMON,
69
+ 'xhigh',
70
+ 'max',
71
+ ];
72
+ }
73
+ if (minor === 0)
74
+ return ['minimal', ...COMMON];
75
+ if (minor === 1)
76
+ return ['none', ...COMMON];
77
+ if (minor <= 5)
78
+ return ['none', ...COMMON, 'xhigh'];
79
+ return ['none', ...COMMON, 'xhigh', 'max'];
80
+ }
81
+ /**
82
+ * 某协议下实际能发的档位:**Chat Completions 在任何模型上都不认 `max`**(连
83
+ * gpt-6 系也 400,Responses 才收)。SDK 4.0.101 对 gpt-6 系把 `max` 列为支持,
84
+ * 走 chat 时会原样发出去,所以这里先剔掉。
85
+ */
86
+ function effortsFor(modelId, protocol) {
87
+ const efforts = serverEfforts(modelId);
88
+ if (!efforts || protocol === 'openai-responses')
89
+ return efforts;
90
+ return efforts.filter(e => e !== 'max');
91
+ }
92
+ /**
93
+ * 我们的档位 → 按偏好依次尝试的 OpenAI 档位,取第一个这个模型认的。`off` 先找
94
+ * 真关闭(`none`),没有就退到最少的那档——没有关闭开关的模型(gpt-5、gpt-6-astra、
95
+ * o 系)只能做到这一步;`max` 先找原生 `max`,再退 `xhigh` / `high`。
96
+ */
97
+ const PREFERENCE = {
98
+ off: ['none', 'minimal', 'low', 'medium', 'high'],
99
+ minimal: ['minimal', 'low', 'medium', 'high'],
100
+ low: ['low', 'medium', 'high'],
101
+ medium: ['medium', 'high', 'low'],
102
+ high: ['high', 'xhigh', 'medium'],
103
+ max: ['max', 'xhigh', 'high', 'medium'],
104
+ };
105
+ /**
106
+ * Responses 每次调用必带 `store: false`。不发时服务端按默认把请求与响应存 30 天,
107
+ * 而我们每轮发全量历史、从不引用存档(`previous_response_id` / `item_reference`)
108
+ * ——存了只是让对话内容平白留在 OpenAI 那边。探针:功能不变,提示词缓存照样
109
+ * 命中(缓存与 `store` 无关)。放中间件而不是 `reasoning()`:与推理无关,没标
110
+ * `reasoning` 能力的模型行也要带。
111
+ */
112
+ const OPENAI_RESPONSES_DEFAULTS = { store: false };
113
+ export class OpenAiAdapter extends LlmVendorAdapter {
114
+ kind = 'openai';
115
+ supportedProtocols = [
116
+ 'openai-chat-completions',
117
+ 'openai-responses',
118
+ ];
119
+ createModel(input) {
120
+ switch (input.protocol) {
121
+ case 'openai-chat-completions': {
122
+ const { baseUrl, apiKey, modelId, fetch } = input;
123
+ // **必须 `.chat()`**:`@ai-sdk/openai` 4.x 里直接调用工厂造的是
124
+ // Responses 模型——这一行曾写成 `createOpenAI(...)(modelId)`,后台选了
125
+ // Chat Completions 的模型实际一直在打 `/responses`(2026-10-23 契约
126
+ // 测试回放 chat 抓包时 SDK 报「Received a Chat Completions stream while
127
+ // using the OpenAI Responses API」才发现)。
128
+ return createOpenAI({ baseURL: baseUrl, apiKey, fetch }).chat(modelId);
129
+ }
130
+ case 'openai-responses':
131
+ return wrapLanguageModel({
132
+ model: createResponsesModel(input),
133
+ middleware: responsesDefaultsMiddleware(OPENAI_RESPONSES_DEFAULTS),
134
+ });
135
+ default:
136
+ throw unsupportedProtocol(this, input.protocol);
137
+ }
138
+ }
139
+ /**
140
+ * 判据与 `reasoning()` 同源(`parseGpt` / `serverEfforts` / `chatToolsNeedNone`):
141
+ * 实际走 chat 而型号在 chat 下带不了工具(报错原文让改用 Responses)、非推理模型
142
+ * 标了推理(档位不会下发)、推理模型没标推理(档位不会下发,按默认档跑)。
143
+ */
144
+ adviseModel(model) {
145
+ const out = [];
146
+ const id = model.modelId;
147
+ if (model.effectiveProtocol === 'openai-chat-completions' &&
148
+ chatToolsNeedNone(id)) {
149
+ out.push({
150
+ severity: 'warn',
151
+ message: serverEfforts(id)?.includes('none')
152
+ ? `「${id}」在 Chat Completions 下带工具时只能关闭推理(none),而 Agent 每轮都带工具,请改用 Responses。`
153
+ : `「${id}」在 Chat Completions 下不支持工具(需 none 档,而它没有),请改用 Responses。`,
154
+ });
155
+ }
156
+ const known = /^o\d+(?:-|$)/.test(id) || parseGpt(id) !== null;
157
+ const reasoningModel = serverEfforts(id) !== null;
158
+ const marked = model.capabilities.includes('reasoning');
159
+ if (known && !reasoningModel && marked) {
160
+ out.push({
161
+ severity: 'info',
162
+ message: `「${id}」不是推理模型,标记「推理」也不会下发推理档位。`,
163
+ });
164
+ }
165
+ if (known && reasoningModel && !marked) {
166
+ out.push({
167
+ severity: 'info',
168
+ message: `「${id}」是推理模型,未标记「推理」时推理档位不会下发,按模型默认档。`,
169
+ });
170
+ }
171
+ return out;
172
+ }
173
+ /**
174
+ * **档位是模型级的**(判据见 `serverEfforts`):同一个「关闭」,gpt-5.5 发
175
+ * `none`、gpt-5 只能发 `minimal`、gpt-6-astra 只能发 `low`;同一个「最高」,
176
+ * gpt-5.2 发 `xhigh`、gpt-6 走 responses 发 `max`。发了模型不认的档位,
177
+ * 服务端 400;gpt-6 系还有一层 SDK 自己的校验,不认的档位**静默丢掉**只打
178
+ * warning,模型按默认档跑——两种都不报到我们这边来,所以在这里按模型算好。
179
+ *
180
+ * 不是推理模型(`gpt-4.1`)时什么都不发:后台把它误标成 reasoning 也不该 400。
181
+ * 两种协议的 key 都是 `openai`;**不**带 `forceReasoning`:SDK 认得自家模型名,
182
+ * 强制会给非推理模型发 `reasoning` 而 400。
183
+ */
184
+ reasoning(modelId, effort, protocol) {
185
+ if (protocol !== 'openai-chat-completions' &&
186
+ protocol !== 'openai-responses') {
187
+ throw unsupportedProtocol(this, protocol);
188
+ }
189
+ const supported = effortsFor(modelId, protocol);
190
+ if (!supported)
191
+ return undefined;
192
+ const sent = PREFERENCE[effort].find(e => supported.includes(e));
193
+ return sent ? { openai: { reasoningEffort: sent } } : undefined;
194
+ }
195
+ }
196
+ //# sourceMappingURL=openai.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.adapter.js","sourceRoot":"","sources":["../../src/vendors/openai.adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { ResponsesFetch } from './openai-responses.js';
2
+ /**
3
+ * 「推理正文走 `reasoning_text`」这一类 Responses 兼容端点的 HTTP 层垫片——把它们
4
+ * 与 OpenAI 线格式的**三处差异**在响应侧抹平,让 `@ai-sdk/openai` 的 responses
5
+ * 模型原样可用。首个使用者是 DeepSeek(本文件前身叫 `deepseek-responses-fetch.ts`),
6
+ * 2026-08-27 智谱探针抓到的事件序列与它**逐字段一致**,于是升成协议级共享件:
7
+ * 这不是 DeepSeek 的私有怪癖,而是「非 OpenAI 厂商实现 Responses」的通行做法——
8
+ * 它们回的是推理**正文**而 OpenAI 只回摘要,字段名自然不同。
9
+ *
10
+ * 差异(2026-08-27 对 `deepseek-v4-flash` / `glm-5.2` 真机探针,见 providers.md):
11
+ *
12
+ * 1. 推理**正文**以 reasoning item 的 `content: [{type:'reasoning_text'}]` 返回,
13
+ * `summary` 恒空——OpenAI 官方只回 `summary`(摘要),SDK 的 item schema
14
+ * 也只读 `summary`/`encrypted_content`(4.0.46 dist:3603、6790)。
15
+ * 2. 流式事件是 `response.reasoning_text.delta / .done`;SDK 的 chunk union 里
16
+ * **没有**这两个名字(0 命中,GitHub main 亦然),未知事件按 loose schema
17
+ * 静默丢弃——推理过程在对话页整段消失。
18
+ * 3. `encrypted_content` 是 `<response_id>-<n>` 形状的不透明串,文档说不支持、
19
+ * 实际会返回;对我们无害(SDK 原样塞进 providerMetadata)。
20
+ *
21
+ * **请求侧刻意不改写**。探针把六种回传形状(原样 item / 只带 encrypted_content /
22
+ * 假 encrypted_content / 假 id / 无 id / `item_reference`)全部打过一遍:全部
23
+ * 200,且 `input_tokens` 分毫不差(多轮 29、工具回环 387)——DeepSeek 根本不消费
24
+ * 发回去的 reasoning,SDK 默认(`store` 未设=true)发出的 `item_reference`
25
+ * 它也照收。没有可走私的东西,也就没有请求侧。
26
+ *
27
+ * 映射:`reasoning_text.delta` → `reasoning_summary_text.delta`(`summary_index`
28
+ * 恒 0——SDK 在 `output_item.added` 时已把第 0 段标成 active,多段 `content_index`
29
+ * 合并进它就够了,另开段要先发 `summary_part.added`,徒增状态机);
30
+ * `reasoning_text.done` → `reasoning_summary_part.done`;`output_item.added/done`、
31
+ * `response.completed/incomplete/failed` 与非流式响应体里的 reasoning item 一律
32
+ * `content` → `summary`。`content` 保留不删,SDK schema 会剥。
33
+ *
34
+ * 只认 OpenAI 公开的线格式,不碰 SDK 内部结构——SDK 升级不影响它。契约由
35
+ * `deepseek-responses.sdk-contract.spec.ts` 与 `zhipu.sdk-contract.spec.ts` 用真实
36
+ * SDK 钉住(后者回放的是带 `event:` 行的原始 SSE——智谱多发这一行,SDK 不看)。
37
+ */
38
+ export declare function withReasoningTextResponsesShim(base?: ResponsesFetch): NonNullable<ResponsesFetch>;
39
+ /** 改写过的 body 长度变了,且已解压;带着原头会让下游按错的长度截断。 */
40
+ export declare function withoutLength(headers: Headers): Headers;
41
+ /**
42
+ * reasoning item:`content[].reasoning_text` → `summary[].summary_text`。
43
+ * 已有非空 `summary` 就不动(那是真 OpenAI 形状,别覆盖)。
44
+ */
45
+ export declare function rewriteReasoningItem(item: unknown): void;
46
+ /** 完整的 response 对象(非流式 body,或 `response.completed` 事件里的那份)。 */
47
+ export declare function rewriteResponseObject(body: unknown): void;
48
+ /** 一条 SSE 事件对象。返回改写后的对象(可能是同一引用)。 */
49
+ export declare function rewriteEvent(event: unknown): unknown;
50
+ //# sourceMappingURL=responses-reasoning-text-shim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses-reasoning-text-shim.d.ts","sourceRoot":"","sources":["../../src/vendors/responses-reasoning-text-shim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,CAAC,EAAE,cAAc,GACpB,WAAW,CAAC,cAAc,CAAC,CAwB7B;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAKvD;AAQD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAWxD;AAED,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGzD;AAED,qCAAqC;AACrC,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAgCpD"}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * 「推理正文走 `reasoning_text`」这一类 Responses 兼容端点的 HTTP 层垫片——把它们
3
+ * 与 OpenAI 线格式的**三处差异**在响应侧抹平,让 `@ai-sdk/openai` 的 responses
4
+ * 模型原样可用。首个使用者是 DeepSeek(本文件前身叫 `deepseek-responses-fetch.ts`),
5
+ * 2026-08-27 智谱探针抓到的事件序列与它**逐字段一致**,于是升成协议级共享件:
6
+ * 这不是 DeepSeek 的私有怪癖,而是「非 OpenAI 厂商实现 Responses」的通行做法——
7
+ * 它们回的是推理**正文**而 OpenAI 只回摘要,字段名自然不同。
8
+ *
9
+ * 差异(2026-08-27 对 `deepseek-v4-flash` / `glm-5.2` 真机探针,见 providers.md):
10
+ *
11
+ * 1. 推理**正文**以 reasoning item 的 `content: [{type:'reasoning_text'}]` 返回,
12
+ * `summary` 恒空——OpenAI 官方只回 `summary`(摘要),SDK 的 item schema
13
+ * 也只读 `summary`/`encrypted_content`(4.0.46 dist:3603、6790)。
14
+ * 2. 流式事件是 `response.reasoning_text.delta / .done`;SDK 的 chunk union 里
15
+ * **没有**这两个名字(0 命中,GitHub main 亦然),未知事件按 loose schema
16
+ * 静默丢弃——推理过程在对话页整段消失。
17
+ * 3. `encrypted_content` 是 `<response_id>-<n>` 形状的不透明串,文档说不支持、
18
+ * 实际会返回;对我们无害(SDK 原样塞进 providerMetadata)。
19
+ *
20
+ * **请求侧刻意不改写**。探针把六种回传形状(原样 item / 只带 encrypted_content /
21
+ * 假 encrypted_content / 假 id / 无 id / `item_reference`)全部打过一遍:全部
22
+ * 200,且 `input_tokens` 分毫不差(多轮 29、工具回环 387)——DeepSeek 根本不消费
23
+ * 发回去的 reasoning,SDK 默认(`store` 未设=true)发出的 `item_reference`
24
+ * 它也照收。没有可走私的东西,也就没有请求侧。
25
+ *
26
+ * 映射:`reasoning_text.delta` → `reasoning_summary_text.delta`(`summary_index`
27
+ * 恒 0——SDK 在 `output_item.added` 时已把第 0 段标成 active,多段 `content_index`
28
+ * 合并进它就够了,另开段要先发 `summary_part.added`,徒增状态机);
29
+ * `reasoning_text.done` → `reasoning_summary_part.done`;`output_item.added/done`、
30
+ * `response.completed/incomplete/failed` 与非流式响应体里的 reasoning item 一律
31
+ * `content` → `summary`。`content` 保留不删,SDK schema 会剥。
32
+ *
33
+ * 只认 OpenAI 公开的线格式,不碰 SDK 内部结构——SDK 升级不影响它。契约由
34
+ * `deepseek-responses.sdk-contract.spec.ts` 与 `zhipu.sdk-contract.spec.ts` 用真实
35
+ * SDK 钉住(后者回放的是带 `event:` 行的原始 SSE——智谱多发这一行,SDK 不看)。
36
+ */
37
+ export function withReasoningTextResponsesShim(base) {
38
+ return async (url, init) => {
39
+ // 延迟到调用时再取全局 fetch:测试用 vi.stubGlobal 换掉的才是这一个。
40
+ const res = await (base ?? globalThis.fetch)(url, init);
41
+ if (!res.ok || !res.body)
42
+ return res;
43
+ const contentType = res.headers.get('content-type') ?? '';
44
+ if (contentType.includes('text/event-stream')) {
45
+ return new Response(res.body.pipeThrough(sseRewriter()), {
46
+ status: res.status,
47
+ statusText: res.statusText,
48
+ headers: withoutLength(res.headers),
49
+ });
50
+ }
51
+ if (contentType.includes('application/json')) {
52
+ const body = (await res.json());
53
+ rewriteResponseObject(body);
54
+ return new Response(JSON.stringify(body), {
55
+ status: res.status,
56
+ statusText: res.statusText,
57
+ headers: withoutLength(res.headers),
58
+ });
59
+ }
60
+ return res;
61
+ };
62
+ }
63
+ /** 改写过的 body 长度变了,且已解压;带着原头会让下游按错的长度截断。 */
64
+ export function withoutLength(headers) {
65
+ const out = new Headers(headers);
66
+ out.delete('content-length');
67
+ out.delete('content-encoding');
68
+ return out;
69
+ }
70
+ function isObject(v) {
71
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
72
+ }
73
+ /**
74
+ * reasoning item:`content[].reasoning_text` → `summary[].summary_text`。
75
+ * 已有非空 `summary` 就不动(那是真 OpenAI 形状,别覆盖)。
76
+ */
77
+ export function rewriteReasoningItem(item) {
78
+ if (!isObject(item) || item.type !== 'reasoning')
79
+ return;
80
+ if (Array.isArray(item.summary) && item.summary.length > 0)
81
+ return;
82
+ const content = Array.isArray(item.content) ? item.content : [];
83
+ item.summary = content.flatMap(part => isObject(part) &&
84
+ part.type === 'reasoning_text' &&
85
+ typeof part.text === 'string'
86
+ ? [{ type: 'summary_text', text: part.text }]
87
+ : []);
88
+ }
89
+ /** 完整的 response 对象(非流式 body,或 `response.completed` 事件里的那份)。 */
90
+ export function rewriteResponseObject(body) {
91
+ if (!isObject(body) || !Array.isArray(body.output))
92
+ return;
93
+ for (const item of body.output)
94
+ rewriteReasoningItem(item);
95
+ }
96
+ /** 一条 SSE 事件对象。返回改写后的对象(可能是同一引用)。 */
97
+ export function rewriteEvent(event) {
98
+ if (!isObject(event) || typeof event.type !== 'string')
99
+ return event;
100
+ switch (event.type) {
101
+ case 'response.reasoning_text.delta':
102
+ return {
103
+ type: 'response.reasoning_summary_text.delta',
104
+ item_id: event.item_id,
105
+ output_index: event.output_index,
106
+ summary_index: 0,
107
+ delta: event.delta,
108
+ sequence_number: event.sequence_number,
109
+ };
110
+ case 'response.reasoning_text.done':
111
+ return {
112
+ type: 'response.reasoning_summary_part.done',
113
+ item_id: event.item_id,
114
+ output_index: event.output_index,
115
+ summary_index: 0,
116
+ sequence_number: event.sequence_number,
117
+ };
118
+ case 'response.output_item.added':
119
+ case 'response.output_item.done':
120
+ rewriteReasoningItem(event.item);
121
+ return event;
122
+ case 'response.completed':
123
+ case 'response.incomplete':
124
+ case 'response.failed':
125
+ rewriteResponseObject(event.response);
126
+ return event;
127
+ default:
128
+ return event;
129
+ }
130
+ }
131
+ /**
132
+ * 按行处理 SSE:只动 `data:` 行且只在它是合法 JSON 时改写,其余字节原样透传。
133
+ * 半行留在缓冲里等下一块,flush 时把尾巴吐掉。
134
+ */
135
+ function sseRewriter() {
136
+ const decoder = new TextDecoder();
137
+ const encoder = new TextEncoder();
138
+ let buffer = '';
139
+ const rewriteLine = (line) => {
140
+ if (!line.startsWith('data:'))
141
+ return line;
142
+ const payload = line.slice(5).trim();
143
+ if (!payload || payload === '[DONE]')
144
+ return line;
145
+ let parsed;
146
+ try {
147
+ parsed = JSON.parse(payload);
148
+ }
149
+ catch {
150
+ return line;
151
+ }
152
+ return `data: ${JSON.stringify(rewriteEvent(parsed))}`;
153
+ };
154
+ return new TransformStream({
155
+ transform(chunk, controller) {
156
+ buffer += decoder.decode(chunk, { stream: true });
157
+ const lines = buffer.split('\n');
158
+ buffer = lines.pop() ?? '';
159
+ if (lines.length === 0)
160
+ return;
161
+ controller.enqueue(encoder.encode(lines.map(rewriteLine).join('\n') + '\n'));
162
+ },
163
+ flush(controller) {
164
+ buffer += decoder.decode();
165
+ if (buffer)
166
+ controller.enqueue(encoder.encode(rewriteLine(buffer)));
167
+ },
168
+ });
169
+ }
170
+ //# sourceMappingURL=responses-reasoning-text-shim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses-reasoning-text-shim.js","sourceRoot":"","sources":["../../src/vendors/responses-reasoning-text-shim.ts"],"names":[],"mappings":"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"}