@sortedyuan/maybecode 0.3.2 → 0.5.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 (295) hide show
  1. package/README.md +166 -55
  2. package/README.zh-CN.md +267 -0
  3. package/dist/application.d.ts +40 -34
  4. package/dist/application.d.ts.map +1 -1
  5. package/dist/application.js +290 -170
  6. package/dist/application.js.map +1 -1
  7. package/dist/args.d.ts +2 -2
  8. package/dist/args.d.ts.map +1 -1
  9. package/dist/args.js +50 -27
  10. package/dist/args.js.map +1 -1
  11. package/dist/bin.js +82 -71
  12. package/dist/bin.js.map +4 -4
  13. package/dist/cli/chunk-3IORPKBL.js +3572 -0
  14. package/dist/cli/chunk-3IORPKBL.js.map +7 -0
  15. package/dist/cli/{chunk-LVTRXPDS.js → chunk-4B2Z6KW7.js} +1547 -1536
  16. package/dist/cli/chunk-4B2Z6KW7.js.map +7 -0
  17. package/dist/cli/{chunk-JT6VBKOM.js → chunk-4WG6JIJJ.js} +127 -33
  18. package/dist/cli/{chunk-JT6VBKOM.js.map → chunk-4WG6JIJJ.js.map} +3 -3
  19. package/dist/cli/{chunk-K5JWPNSY.js → chunk-5SLWALZK.js} +3521 -16164
  20. package/dist/cli/chunk-5SLWALZK.js.map +7 -0
  21. package/dist/cli/chunk-MNBYXL5Y.js +132 -0
  22. package/dist/cli/chunk-MNBYXL5Y.js.map +7 -0
  23. package/dist/cli/{chunk-F4XRPLUM.js → chunk-SLWLUEHQ.js} +226 -86
  24. package/dist/cli/chunk-SLWLUEHQ.js.map +7 -0
  25. package/dist/cli/chunk-UQDZ55LQ.js +199 -0
  26. package/dist/cli/chunk-UQDZ55LQ.js.map +7 -0
  27. package/dist/cli/{chunk-7ISOHFS7.js → chunk-WMSG5ZTR.js} +717 -388
  28. package/dist/cli/chunk-WMSG5ZTR.js.map +7 -0
  29. package/dist/cli/chunk-WVIRS76R.js +4057 -0
  30. package/dist/cli/chunk-WVIRS76R.js.map +7 -0
  31. package/dist/cli/{chunk-HOU5ITUK.js → chunk-XTEMRAQW.js} +1 -1
  32. package/dist/cli/chunk-XTEMRAQW.js.map +7 -0
  33. package/dist/cli/chunk-Z3BOPBVU.js +91 -0
  34. package/dist/cli/chunk-Z3BOPBVU.js.map +7 -0
  35. package/dist/cli/{configured-WHY3GGAJ.js → configured-ACNM6TRQ.js} +10 -9
  36. package/dist/cli/{file-type-R2T7TBHI.js → file-type-HLHPV7WC.js} +817 -13
  37. package/dist/cli/file-type-HLHPV7WC.js.map +7 -0
  38. package/dist/cli/mcp-auth-XD5U7WCV.js +74 -0
  39. package/dist/cli/mcp-auth-XD5U7WCV.js.map +7 -0
  40. package/dist/cli/onboarding-WQWCPYEO.js +530 -0
  41. package/dist/cli/onboarding-WQWCPYEO.js.map +7 -0
  42. package/dist/cli/onboarding-check-HRRI5OJ7.js +32 -0
  43. package/dist/cli/onboarding-check-HRRI5OJ7.js.map +7 -0
  44. package/dist/cli/{retained-tui-VJ3VX4R3.js → retained-tui-QF5VMYLC.js} +788 -332
  45. package/dist/cli/retained-tui-QF5VMYLC.js.map +7 -0
  46. package/dist/cli/{sixel-LWTCM76G.js → sixel-ISZ4FZ3U.js} +37 -37
  47. package/dist/cli/{sixel-LWTCM76G.js.map → sixel-ISZ4FZ3U.js.map} +1 -1
  48. package/dist/cli/{team-T7G7PPNN.js → team-O2I5BXHM.js} +7 -6
  49. package/dist/cli/{team-v2-JGBBQ7FR.js → team-v2-YYO2G7DJ.js} +816 -390
  50. package/dist/cli/team-v2-YYO2G7DJ.js.map +7 -0
  51. package/dist/cli/{web-server-FOMNPY7Q.js → web-server-SXMH6FGA.js} +55 -19
  52. package/dist/cli/web-server-SXMH6FGA.js.map +7 -0
  53. package/dist/cli/{web-ui-COB6PKC5.js → web-ui-UWQUFE4W.js} +7 -6
  54. package/dist/config-schema.json +337 -0
  55. package/dist/configured.d.ts +18 -11
  56. package/dist/configured.d.ts.map +1 -1
  57. package/dist/configured.js +213 -390
  58. package/dist/configured.js.map +1 -1
  59. package/dist/controller.d.ts +19 -18
  60. package/dist/controller.d.ts.map +1 -1
  61. package/dist/delegation-commands.d.ts +1 -1
  62. package/dist/delegation-commands.d.ts.map +1 -1
  63. package/dist/delegation-commands.js +8 -8
  64. package/dist/delegation-commands.js.map +1 -1
  65. package/dist/errors.d.ts +2 -1
  66. package/dist/errors.d.ts.map +1 -1
  67. package/dist/errors.js +2 -1
  68. package/dist/errors.js.map +1 -1
  69. package/dist/events.d.ts +8 -6
  70. package/dist/events.d.ts.map +1 -1
  71. package/dist/fork-picker.d.ts.map +1 -1
  72. package/dist/fork-picker.js +19 -5
  73. package/dist/fork-picker.js.map +1 -1
  74. package/dist/git-request.d.ts +6 -6
  75. package/dist/git-request.d.ts.map +1 -1
  76. package/dist/git-request.js +28 -15
  77. package/dist/git-request.js.map +1 -1
  78. package/dist/goal-commands.d.ts +1 -1
  79. package/dist/goal-commands.d.ts.map +1 -1
  80. package/dist/goal-commands.js +12 -5
  81. package/dist/goal-commands.js.map +1 -1
  82. package/dist/index.d.ts +5 -37
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +3 -36
  85. package/dist/index.js.map +1 -1
  86. package/dist/instructions.d.ts +2 -7
  87. package/dist/instructions.d.ts.map +1 -1
  88. package/dist/instructions.js +7 -15
  89. package/dist/instructions.js.map +1 -1
  90. package/dist/keymap.d.ts +2 -2
  91. package/dist/keymap.d.ts.map +1 -1
  92. package/dist/keymap.js +2 -2
  93. package/dist/keymap.js.map +1 -1
  94. package/dist/maybecode-config.schema.json +1765 -0
  95. package/dist/mcp-auth.d.ts +1 -1
  96. package/dist/mcp-auth.d.ts.map +1 -1
  97. package/dist/mcp-auth.js +11 -8
  98. package/dist/mcp-auth.js.map +1 -1
  99. package/dist/mcp-commands.d.ts.map +1 -1
  100. package/dist/mcp-commands.js +18 -4
  101. package/dist/mcp-commands.js.map +1 -1
  102. package/dist/mcp-interaction-ui.d.ts.map +1 -1
  103. package/dist/mcp-interaction-ui.js +11 -4
  104. package/dist/mcp-interaction-ui.js.map +1 -1
  105. package/dist/media-history.d.ts +1 -1
  106. package/dist/media-history.d.ts.map +1 -1
  107. package/dist/media-history.js +8 -2
  108. package/dist/media-history.js.map +1 -1
  109. package/dist/model-picker.d.ts.map +1 -1
  110. package/dist/model-picker.js +10 -11
  111. package/dist/model-picker.js.map +1 -1
  112. package/dist/model-transition.d.ts +11 -0
  113. package/dist/model-transition.d.ts.map +1 -0
  114. package/dist/model-transition.js +48 -0
  115. package/dist/model-transition.js.map +1 -0
  116. package/dist/model.d.ts +2 -2
  117. package/dist/model.d.ts.map +1 -1
  118. package/dist/model.js +8 -4
  119. package/dist/model.js.map +1 -1
  120. package/dist/onboarding-check.d.ts +3 -0
  121. package/dist/onboarding-check.d.ts.map +1 -0
  122. package/dist/onboarding-check.js +22 -0
  123. package/dist/onboarding-check.js.map +1 -0
  124. package/dist/onboarding.d.ts +6 -0
  125. package/dist/onboarding.d.ts.map +1 -0
  126. package/dist/onboarding.js +463 -0
  127. package/dist/onboarding.js.map +1 -0
  128. package/dist/plugins/application.d.ts +6 -4
  129. package/dist/plugins/application.d.ts.map +1 -1
  130. package/dist/plugins/application.js +106 -52
  131. package/dist/plugins/application.js.map +1 -1
  132. package/dist/plugins/instructions.d.ts +1 -1
  133. package/dist/plugins/instructions.d.ts.map +1 -1
  134. package/dist/plugins/instructions.js +24 -11
  135. package/dist/plugins/instructions.js.map +1 -1
  136. package/dist/plugins/resources.d.ts +2 -2
  137. package/dist/plugins/resources.d.ts.map +1 -1
  138. package/dist/plugins/resources.js +22 -12
  139. package/dist/plugins/resources.js.map +1 -1
  140. package/dist/policy.d.ts +1 -1
  141. package/dist/policy.d.ts.map +1 -1
  142. package/dist/policy.js +59 -11
  143. package/dist/policy.js.map +1 -1
  144. package/dist/run.d.ts +2 -0
  145. package/dist/run.d.ts.map +1 -1
  146. package/dist/run.js +38 -33
  147. package/dist/run.js.map +1 -1
  148. package/dist/runtime-instructions.d.ts +1 -1
  149. package/dist/runtime-instructions.d.ts.map +1 -1
  150. package/dist/runtime-instructions.js +15 -7
  151. package/dist/runtime-instructions.js.map +1 -1
  152. package/dist/session-navigation.d.ts +6 -0
  153. package/dist/session-navigation.d.ts.map +1 -0
  154. package/dist/session-navigation.js +64 -0
  155. package/dist/session-navigation.js.map +1 -0
  156. package/dist/session-picker.d.ts +1 -1
  157. package/dist/session-picker.d.ts.map +1 -1
  158. package/dist/session-picker.js +23 -32
  159. package/dist/session-picker.js.map +1 -1
  160. package/dist/settings.d.ts +718 -0
  161. package/dist/settings.d.ts.map +1 -0
  162. package/dist/settings.js +14 -0
  163. package/dist/settings.js.map +1 -0
  164. package/dist/skills.d.ts +1 -1
  165. package/dist/skills.d.ts.map +1 -1
  166. package/dist/skills.js +10 -12
  167. package/dist/skills.js.map +1 -1
  168. package/dist/slash-commands.d.ts +2 -2
  169. package/dist/slash-commands.d.ts.map +1 -1
  170. package/dist/slash-commands.js +149 -67
  171. package/dist/slash-commands.js.map +1 -1
  172. package/dist/team-execution.d.ts +10 -0
  173. package/dist/team-execution.d.ts.map +1 -0
  174. package/dist/team-execution.js +29 -0
  175. package/dist/team-execution.js.map +1 -0
  176. package/dist/team-patches.d.ts.map +1 -1
  177. package/dist/team-patches.js +149 -52
  178. package/dist/team-patches.js.map +1 -1
  179. package/dist/team-plan.d.ts +2 -2
  180. package/dist/team-plan.d.ts.map +1 -1
  181. package/dist/team-plan.js +115 -34
  182. package/dist/team-plan.js.map +1 -1
  183. package/dist/team-recovery.d.ts +1 -1
  184. package/dist/team-recovery.d.ts.map +1 -1
  185. package/dist/team-recovery.js +40 -10
  186. package/dist/team-recovery.js.map +1 -1
  187. package/dist/team-v2.d.ts.map +1 -1
  188. package/dist/team-v2.js +335 -104
  189. package/dist/team-v2.js.map +1 -1
  190. package/dist/team-verification.d.ts +4 -2
  191. package/dist/team-verification.d.ts.map +1 -1
  192. package/dist/team-verification.js +300 -97
  193. package/dist/team-verification.js.map +1 -1
  194. package/dist/team.d.ts +2 -2
  195. package/dist/team.d.ts.map +1 -1
  196. package/dist/team.js +172 -62
  197. package/dist/team.js.map +1 -1
  198. package/dist/terminal-web.d.ts +1 -0
  199. package/dist/terminal-web.d.ts.map +1 -1
  200. package/dist/terminal-web.js +28 -10
  201. package/dist/terminal-web.js.map +1 -1
  202. package/dist/ui/actions.d.ts.map +1 -1
  203. package/dist/ui/actions.js.map +1 -1
  204. package/dist/ui/retained-tui.d.ts.map +1 -1
  205. package/dist/ui/retained-tui.js +231 -173
  206. package/dist/ui/retained-tui.js.map +1 -1
  207. package/dist/ui/{prototype-view.d.ts → terminal-view.d.ts} +7 -7
  208. package/dist/ui/terminal-view.d.ts.map +1 -0
  209. package/dist/ui/{prototype-view.js → terminal-view.js} +185 -98
  210. package/dist/ui/terminal-view.js.map +1 -0
  211. package/dist/web-commands.d.ts.map +1 -1
  212. package/dist/web-commands.js +160 -57
  213. package/dist/web-commands.js.map +1 -1
  214. package/dist/web-extension.d.ts.map +1 -1
  215. package/dist/web-extension.js +14 -4
  216. package/dist/web-extension.js.map +1 -1
  217. package/dist/web-server.d.ts.map +1 -1
  218. package/dist/web-server.js +2 -1
  219. package/dist/web-server.js.map +1 -1
  220. package/dist/web-ui.d.ts.map +1 -1
  221. package/dist/web-ui.js +167 -40
  222. package/dist/web-ui.js.map +1 -1
  223. package/dist/workspace-configuration.d.ts +7 -0
  224. package/dist/workspace-configuration.d.ts.map +1 -0
  225. package/dist/workspace-configuration.js +134 -0
  226. package/dist/workspace-configuration.js.map +1 -0
  227. package/dist/workspace-state.d.ts +20 -0
  228. package/dist/workspace-state.d.ts.map +1 -0
  229. package/dist/workspace-state.js +2 -0
  230. package/dist/workspace-state.js.map +1 -0
  231. package/dist/workspace.d.ts +26 -43
  232. package/dist/workspace.d.ts.map +1 -1
  233. package/dist/workspace.js +261 -323
  234. package/dist/workspace.js.map +1 -1
  235. package/package.json +21 -31
  236. package/dist/cli/chunk-7ISOHFS7.js.map +0 -7
  237. package/dist/cli/chunk-F4XRPLUM.js.map +0 -7
  238. package/dist/cli/chunk-H7SNBFO4.js +0 -5522
  239. package/dist/cli/chunk-H7SNBFO4.js.map +0 -7
  240. package/dist/cli/chunk-HOU5ITUK.js.map +0 -7
  241. package/dist/cli/chunk-K5JWPNSY.js.map +0 -7
  242. package/dist/cli/chunk-LVTRXPDS.js.map +0 -7
  243. package/dist/cli/chunk-VAZMCNBB.js +0 -686
  244. package/dist/cli/chunk-VAZMCNBB.js.map +0 -7
  245. package/dist/cli/chunk-WOFEI42C.js +0 -7820
  246. package/dist/cli/chunk-WOFEI42C.js.map +0 -7
  247. package/dist/cli/file-type-R2T7TBHI.js.map +0 -7
  248. package/dist/cli/mcp-auth-UNRHSIKJ.js +0 -63
  249. package/dist/cli/mcp-auth-UNRHSIKJ.js.map +0 -7
  250. package/dist/cli/retained-tui-VJ3VX4R3.js.map +0 -7
  251. package/dist/cli/team-v2-JGBBQ7FR.js.map +0 -7
  252. package/dist/cli/tui-SA74DKMA.js +0 -1705
  253. package/dist/cli/tui-SA74DKMA.js.map +0 -7
  254. package/dist/cli/web-server-FOMNPY7Q.js.map +0 -7
  255. package/dist/delegation.d.ts +0 -2
  256. package/dist/delegation.d.ts.map +0 -1
  257. package/dist/delegation.js +0 -2
  258. package/dist/delegation.js.map +0 -1
  259. package/dist/history-memory.d.ts +0 -2
  260. package/dist/history-memory.d.ts.map +0 -1
  261. package/dist/history-memory.js +0 -2
  262. package/dist/history-memory.js.map +0 -1
  263. package/dist/subagent-budget.d.ts +0 -2
  264. package/dist/subagent-budget.d.ts.map +0 -1
  265. package/dist/subagent-budget.js +0 -2
  266. package/dist/subagent-budget.js.map +0 -1
  267. package/dist/subagent-files.d.ts +0 -2
  268. package/dist/subagent-files.d.ts.map +0 -1
  269. package/dist/subagent-files.js +0 -2
  270. package/dist/subagent-files.js.map +0 -1
  271. package/dist/subagent-host.d.ts +0 -2
  272. package/dist/subagent-host.d.ts.map +0 -1
  273. package/dist/subagent-host.js +0 -2
  274. package/dist/subagent-host.js.map +0 -1
  275. package/dist/subagent-instructions.d.ts +0 -2
  276. package/dist/subagent-instructions.d.ts.map +0 -1
  277. package/dist/subagent-instructions.js +0 -2
  278. package/dist/subagent-instructions.js.map +0 -1
  279. package/dist/subagents.d.ts +0 -2
  280. package/dist/subagents.d.ts.map +0 -1
  281. package/dist/subagents.js +0 -2
  282. package/dist/subagents.js.map +0 -1
  283. package/dist/summarizer.d.ts +0 -2
  284. package/dist/summarizer.d.ts.map +0 -1
  285. package/dist/summarizer.js +0 -2
  286. package/dist/summarizer.js.map +0 -1
  287. package/dist/tui.d.ts +0 -7
  288. package/dist/tui.d.ts.map +0 -1
  289. package/dist/tui.js +0 -1109
  290. package/dist/tui.js.map +0 -1
  291. package/dist/ui/prototype-view.d.ts.map +0 -1
  292. package/dist/ui/prototype-view.js.map +0 -1
  293. /package/dist/cli/{configured-WHY3GGAJ.js.map → configured-ACNM6TRQ.js.map} +0 -0
  294. /package/dist/cli/{team-T7G7PPNN.js.map → team-O2I5BXHM.js.map} +0 -0
  295. /package/dist/cli/{web-ui-COB6PKC5.js.map → web-ui-UWQUFE4W.js.map} +0 -0
@@ -0,0 +1,4057 @@
1
+ import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ createParser
4
+ } from "./chunk-UQDZ55LQ.js";
5
+ import {
6
+ __name
7
+ } from "./chunk-E732GDOI.js";
8
+
9
+ // packages/providers/dist/capabilities.js
10
+ import { createHash } from "node:crypto";
11
+ import { MODEL_CAPABILITY_KEYS, parseMayConfig } from "@sortedyuan/may/config";
12
+ import { omitUndefined } from "@sortedyuan/may/core";
13
+ var ModelCapabilityResolver = class {
14
+ static {
15
+ __name(this, "ModelCapabilityResolver");
16
+ }
17
+ discoveries;
18
+ ttl;
19
+ maxEntries;
20
+ maxRecords;
21
+ adapters;
22
+ cache = /* @__PURE__ */ new Map();
23
+ pending = /* @__PURE__ */ new Map();
24
+ records = [];
25
+ constructor(options = {}) {
26
+ this.discoveries = options.discoveries ?? [new ModelListCapabilityDiscovery(options.fetch ?? globalThis.fetch)];
27
+ this.ttl = positive(options.cacheTtlMs ?? 3e5, "cacheTtlMs");
28
+ this.maxEntries = positive(options.maxCacheEntries ?? 128, "maxCacheEntries");
29
+ this.maxRecords = positive(options.maxVerificationRecords ?? 256, "maxVerificationRecords");
30
+ this.adapters = structuredClone(options.adapterCapabilities ?? {});
31
+ for (const fields of Object.values(this.adapters))
32
+ assertCapabilityFields(fields);
33
+ }
34
+ async resolve(selection, options = {}) {
35
+ const requested = options.fields ?? MODEL_CAPABILITY_KEYS;
36
+ for (const field of requested)
37
+ if (!MODEL_CAPABILITY_KEYS.includes(field))
38
+ throw new TypeError(`Unknown capability field ${field}`);
39
+ const explicit = declaredFields(selection.capabilities, "user");
40
+ assertCapabilityFields(explicit);
41
+ const explicitReasoning = declaredReasoning(selection.capabilities, "user");
42
+ if (explicitReasoning !== void 0)
43
+ assertReasoningCapabilities(explicitReasoning);
44
+ const discovered = await this.discover(selection, options.refresh === true, explicitReasoning !== void 0, requested);
45
+ const model = {};
46
+ const adapter = this.adapters[selection.adapter] ?? builtinAdapterCapabilities(selection.adapter);
47
+ const connection = declaredFields(selection.providerConfig.capabilities, "user");
48
+ assertCapabilityFields(connection);
49
+ const connectionReasoning = declaredReasoning(selection.providerConfig.capabilities, "user");
50
+ if (connectionReasoning !== void 0)
51
+ assertReasoningCapabilities(connectionReasoning);
52
+ const effective = {};
53
+ for (const field of requested) {
54
+ const value = explicit[field] ?? declaredLimit(selection, field) ?? discovered.fields[field] ?? UNKNOWN;
55
+ model[field] = value;
56
+ effective[field] = intersectCapability(field, [value, adapter[field], connection[field]]);
57
+ }
58
+ const reasoning = explicitReasoning ?? discovered.reasoningEffort ?? builtinReasoningEffort(selection) ?? UNKNOWN;
59
+ const reasoningEffort = intersectReasoning(reasoning, connectionReasoning);
60
+ const layers = { model, adapter, connection };
61
+ return structuredClone({
62
+ reasoningEffort,
63
+ fields: effective,
64
+ layers,
65
+ version: digest({ reasoningEffort, fields: effective, layers }),
66
+ observedAt: discovered.observedAt,
67
+ expiresAt: discovered.expiresAt,
68
+ diagnostics: discovered.diagnostics
69
+ });
70
+ }
71
+ invalidate(selection) {
72
+ if (selection === void 0) {
73
+ this.cache.clear();
74
+ this.pending.clear();
75
+ return;
76
+ }
77
+ const prefix = connectionIdentity(selection);
78
+ for (const key of [...this.cache.keys(), ...this.pending.keys()]) {
79
+ if (!key.startsWith(prefix))
80
+ continue;
81
+ this.cache.delete(key);
82
+ this.pending.delete(key);
83
+ }
84
+ }
85
+ verificationRecords(selection) {
86
+ const connectionId = selection === void 0 ? void 0 : connectionIdentity(selection);
87
+ return this.records.filter((record) => connectionId === void 0 || record.connectionId === connectionId && record.model === selection?.model).map((record) => ({ ...record, parameters: { ...record.parameters } }));
88
+ }
89
+ recordVerification(selection, request, success, responseValidated = false, additionalCapabilities = []) {
90
+ const used = new Set(additionalCapabilities);
91
+ for (const message of request.messages)
92
+ for (const part of message.content) {
93
+ if (part.type === "text" || part.type === "json")
94
+ used.add("input.text");
95
+ if (["image", "audio", "file", "resource"].includes(part.type))
96
+ used.add(`input.${part.type}`);
97
+ }
98
+ if (request.tools.length > 0)
99
+ used.add("tools");
100
+ if (request.responseFormat !== void 0)
101
+ used.add(request.responseFormat.type === "json" ? "structuredOutput.json" : "structuredOutput.jsonSchema");
102
+ const thinking = selection.options.thinking;
103
+ const activeThinking = thinking !== void 0 && thinking !== "disabled" && !(isRecord(thinking) && thinking.type === "disabled");
104
+ if (selection.options.reasoningEffort !== void 0 || activeThinking || selection.options.reasoningSummary !== void 0)
105
+ used.add("reasoning.modes");
106
+ const parameters = {};
107
+ if (typeof selection.options.reasoningEffort === "string")
108
+ parameters.reasoningEffort = selection.options.reasoningEffort;
109
+ for (const key of ["maxTokens", "maxOutputTokens"])
110
+ if (typeof selection.options[key] === "number")
111
+ parameters[key] = selection.options[key];
112
+ if (parameters.maxTokens === void 0 && parameters.maxOutputTokens === void 0 && selection.limits?.maxOutputTokens !== void 0) {
113
+ parameters[["deepseek-chat", "kimi-chat", "zhipu-chat", "anthropic-messages"].includes(selection.adapter) ? "maxTokens" : "maxOutputTokens"] = selection.limits.maxOutputTokens;
114
+ }
115
+ if (typeof selection.options.reasoningSummary === "string")
116
+ parameters.reasoningSummary = selection.options.reasoningSummary;
117
+ if (typeof thinking === "string")
118
+ parameters.thinkingType = thinking;
119
+ else if (isRecord(thinking)) {
120
+ if (typeof thinking.type === "string")
121
+ parameters.thinkingType = thinking.type;
122
+ if (typeof thinking.budgetTokens === "number")
123
+ parameters.thinkingBudgetTokens = thinking.budgetTokens;
124
+ }
125
+ if (request.responseFormat?.type === "jsonSchema") {
126
+ parameters.schemaVersion = digest(request.responseFormat.schema);
127
+ parameters.strict = request.responseFormat.strict ?? false;
128
+ }
129
+ for (const capability of used) {
130
+ const observed = { ...parameters };
131
+ const parts = request.messages.flatMap((message) => message.content).filter((part) => capability === "input.text" ? part.type === "text" || part.type === "json" : capability === `input.${part.type}`);
132
+ if (capability.startsWith("input."))
133
+ observed.count = parts.length;
134
+ const media = parts.filter((part) => part.type === "image" || part.type === "audio" || part.type === "file");
135
+ if (media.length > 0) {
136
+ for (const source of ["url", "base64", "file"])
137
+ observed[`${source}Sources`] = media.filter((part) => part.source.type === source).length;
138
+ const base64 = media.flatMap((part) => part.source.type === "base64" ? [part.source] : []);
139
+ const bytes = base64.map((source) => Buffer.byteLength(source.data, "base64"));
140
+ observed.knownBytesCount = bytes.length;
141
+ if (bytes.length > 0) {
142
+ observed.minObservedBytes = Math.min(...bytes);
143
+ observed.maxObservedBytes = Math.max(...bytes);
144
+ }
145
+ observed.mediaTypesVersion = digest([...new Set(base64.map((source) => source.mediaType))].sort());
146
+ }
147
+ if (capability === "tools") {
148
+ observed.definitions = request.tools.length;
149
+ observed.definitionsVersion = digest(request.tools);
150
+ }
151
+ const evidence = !success ? "failed" : capability.startsWith("structuredOutput.") && responseValidated ? "response-validated" : "request-accepted";
152
+ this.records.push({
153
+ model: selection.model,
154
+ adapter: selection.adapter,
155
+ connectionId: connectionIdentity(selection),
156
+ capability,
157
+ observedAt: Date.now(),
158
+ success,
159
+ evidence,
160
+ parameters: observed
161
+ });
162
+ }
163
+ if (this.records.length > this.maxRecords)
164
+ this.records.splice(0, this.records.length - this.maxRecords);
165
+ }
166
+ async discover(selection, refresh, skipReasoning, fields) {
167
+ const key = `${connectionIdentity(selection)}:${digest({ model: selection.model, fields: [...fields].sort(), skipReasoning })}`;
168
+ if (refresh)
169
+ this.cache.delete(key);
170
+ const cached = this.cache.get(key);
171
+ if (cached !== void 0 && cached.expiresAt > Date.now()) {
172
+ this.cache.delete(key);
173
+ this.cache.set(key, cached);
174
+ return cached;
175
+ }
176
+ this.cache.delete(key);
177
+ const active = this.pending.get(key);
178
+ if (active !== void 0)
179
+ return active;
180
+ if (this.pending.size >= this.maxEntries)
181
+ throw new RangeError("Capability discovery concurrency limit exceeded");
182
+ const operation = this.query(selection, skipReasoning, fields);
183
+ this.pending.set(key, operation);
184
+ try {
185
+ const result = await operation;
186
+ if (this.pending.get(key) === operation && result.diagnostics.length === 0) {
187
+ this.cache.set(key, result);
188
+ while (this.cache.size > this.maxEntries)
189
+ this.cache.delete(this.cache.keys().next().value);
190
+ }
191
+ return result;
192
+ } finally {
193
+ if (this.pending.get(key) === operation)
194
+ this.pending.delete(key);
195
+ }
196
+ }
197
+ async query(selection, skipReasoning, requested) {
198
+ const fields = {};
199
+ let reasoningEffort;
200
+ const diagnostics = [];
201
+ for (const [index, discovery] of this.discoveries.entries()) {
202
+ let found;
203
+ let foundReasoning;
204
+ try {
205
+ found = await discovery.discoverCapabilities?.(selection, requested);
206
+ if (!skipReasoning && reasoningEffort === void 0)
207
+ foundReasoning = await discovery.discoverReasoningEffort?.(selection);
208
+ } catch {
209
+ diagnostics.push({
210
+ discovery: discovery.name ?? `discovery-${index + 1}`,
211
+ code: "DISCOVERY_FAILED",
212
+ observedAt: Date.now()
213
+ });
214
+ continue;
215
+ }
216
+ if (found !== void 0)
217
+ assertCapabilityFields(found);
218
+ if (foundReasoning !== void 0)
219
+ assertReasoningCapabilities(foundReasoning);
220
+ if (found !== void 0) {
221
+ for (const field of requested)
222
+ if (fields[field] === void 0 && found[field] !== void 0)
223
+ fields[field] = found[field];
224
+ }
225
+ reasoningEffort ??= foundReasoning;
226
+ }
227
+ const observedAt = Date.now();
228
+ return omitUndefined({ fields, reasoningEffort, observedAt, expiresAt: observedAt + this.ttl, diagnostics });
229
+ }
230
+ };
231
+ function createModelCapabilityResolver(options = {}) {
232
+ return new ModelCapabilityResolver(options);
233
+ }
234
+ __name(createModelCapabilityResolver, "createModelCapabilityResolver");
235
+ function connectionIdentity(selection) {
236
+ return digest({ provider: selection.provider, adapter: selection.adapter, config: selection.providerConfig });
237
+ }
238
+ __name(connectionIdentity, "connectionIdentity");
239
+ var UNKNOWN = { status: "unknown", source: "unknown" };
240
+ function known(value, source) {
241
+ return value === false ? { status: "unsupported", source } : { status: "known", source, value };
242
+ }
243
+ __name(known, "known");
244
+ function declaredFields(overrides, source) {
245
+ return Object.fromEntries(Object.entries(overrides?.fields ?? {}).map(([field, value]) => [field, known(value, source)]));
246
+ }
247
+ __name(declaredFields, "declaredFields");
248
+ function declaredLimit(selection, field) {
249
+ if (field !== "contextWindowTokens" && field !== "maxOutputTokens")
250
+ return void 0;
251
+ const value = selection.limits?.[field];
252
+ return value === void 0 ? void 0 : known(value, "user");
253
+ }
254
+ __name(declaredLimit, "declaredLimit");
255
+ function declaredReasoning(overrides, source) {
256
+ const reasoning = overrides?.reasoning;
257
+ if (reasoning === void 0)
258
+ return void 0;
259
+ if (reasoning === false || reasoning.efforts.length === 0)
260
+ return { status: "unsupported", source };
261
+ return omitUndefined({
262
+ status: "known",
263
+ source,
264
+ efforts: [...reasoning.efforts],
265
+ defaultEffort: reasoning.defaultEffort
266
+ });
267
+ }
268
+ __name(declaredReasoning, "declaredReasoning");
269
+ function intersectReasoning(model, connection) {
270
+ if (model.status === "unsupported")
271
+ return model;
272
+ if (connection?.status === "unsupported")
273
+ return connection;
274
+ if (model.status !== "known" || connection?.status === "unknown")
275
+ return UNKNOWN;
276
+ if (connection === void 0)
277
+ return model;
278
+ const efforts = model.efforts.filter((effort) => connection.efforts.includes(effort));
279
+ if (efforts.length === 0)
280
+ return { status: "unsupported", source: connection.source };
281
+ const defaultEffort = connection.defaultEffort ?? model.defaultEffort;
282
+ return {
283
+ status: "known",
284
+ source: connection.source,
285
+ efforts,
286
+ ...defaultEffort !== void 0 && efforts.includes(defaultEffort) ? { defaultEffort } : {}
287
+ };
288
+ }
289
+ __name(intersectReasoning, "intersectReasoning");
290
+ function intersectCapability(field, values) {
291
+ const unsupported = values.find((value2) => value2?.status === "unsupported");
292
+ if (unsupported !== void 0)
293
+ return unsupported;
294
+ if (values.some((value2) => value2?.status === "unknown"))
295
+ return UNKNOWN;
296
+ const concrete = values.filter((value2) => value2?.status === "known");
297
+ if (concrete.length === 0)
298
+ return UNKNOWN;
299
+ let value = concrete[0].value;
300
+ let source = concrete[0].source;
301
+ for (const next of concrete.slice(1)) {
302
+ const previous = JSON.stringify(value);
303
+ if (typeof value === "number" && typeof next.value === "number")
304
+ value = Math.min(value, next.value);
305
+ else if (Array.isArray(value) && Array.isArray(next.value))
306
+ value = value.filter((item) => next.value.includes(item));
307
+ else if (field === "parameters" || field === "structuredOutput.schemaConstraint")
308
+ value = { allOf: [value, next.value] };
309
+ if (JSON.stringify(value) !== previous)
310
+ source = next.source;
311
+ }
312
+ if (Array.isArray(value) && value.length === 0)
313
+ return { status: "unsupported", source: concrete.at(-1).source };
314
+ return { status: "known", source, value };
315
+ }
316
+ __name(intersectCapability, "intersectCapability");
317
+ function builtinAdapterCapabilities(adapter) {
318
+ if (adapter === "google-gemini")
319
+ return Object.fromEntries(Object.entries({
320
+ "input.text": true,
321
+ "input.image": true,
322
+ "input.audio": true,
323
+ "input.file": true,
324
+ "input.resource": false,
325
+ "input.image.sources": ["url", "base64"],
326
+ "input.audio.sources": ["url", "base64"],
327
+ "input.file.sources": ["url", "base64"],
328
+ "output.text": true,
329
+ "output.image": true,
330
+ "output.audio": true,
331
+ tools: true,
332
+ "structuredOutput.json": true,
333
+ "structuredOutput.jsonSchema": true,
334
+ "structuredOutput.schemaDialects": ["draft-07", "2020-12"],
335
+ contextCompaction: false,
336
+ "reasoning.modes": ["effort", "budget"]
337
+ }).map(([field, value]) => [field, known(value, "adapter")]));
338
+ if (![
339
+ "openai-responses",
340
+ "openai-chat-completions",
341
+ "deepseek-chat",
342
+ "kimi-chat",
343
+ "zhipu-chat",
344
+ "anthropic-messages"
345
+ ].includes(adapter))
346
+ return {};
347
+ const responses = adapter === "openai-responses";
348
+ const anthropic = adapter === "anthropic-messages";
349
+ const openaiChat = adapter === "openai-chat-completions";
350
+ const values = {
351
+ "input.text": true,
352
+ "input.image": true,
353
+ "input.audio": false,
354
+ "input.file": responses || anthropic,
355
+ "input.resource": false,
356
+ "input.image.sources": responses || anthropic ? ["url", "base64", "file"] : ["url", "base64"],
357
+ "input.file.sources": responses || anthropic ? ["url", "base64", "file"] : false,
358
+ "output.text": true,
359
+ "output.image": responses,
360
+ "output.audio": false,
361
+ tools: true,
362
+ "structuredOutput.json": responses || openaiChat,
363
+ "structuredOutput.jsonSchema": responses || openaiChat,
364
+ "structuredOutput.schemaDialects": responses || openaiChat ? ["draft-07", "2020-12"] : false,
365
+ contextCompaction: responses,
366
+ "reasoning.modes": anthropic ? ["effort", "budget", "adaptive"] : responses ? ["effort", "summary"] : openaiChat ? ["effort"] : ["effort", "thinking"]
367
+ };
368
+ return Object.fromEntries(Object.entries(values).map(([field, value]) => [field, known(value, "adapter")]));
369
+ }
370
+ __name(builtinAdapterCapabilities, "builtinAdapterCapabilities");
371
+ var BUILTIN_REASONING_EFFORTS = new Map([
372
+ ...["openai-responses", "openai-chat-completions"].flatMap((adapter) => ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"].map((model) => [
373
+ catalogKey(adapter, model),
374
+ { efforts: ["none", "low", "medium", "high", "xhigh", "max"], defaultEffort: "medium" }
375
+ ])),
376
+ ...["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-v4-flash-vision-exp"].map((model) => [catalogKey("deepseek-chat", model), { efforts: ["low", "high", "max"], defaultEffort: "high" }])
377
+ ]);
378
+ function builtinReasoningEffort(selection) {
379
+ const entry = BUILTIN_REASONING_EFFORTS.get(catalogKey(selection.adapter, selection.model));
380
+ return entry === void 0 ? void 0 : omitUndefined({
381
+ status: "known",
382
+ source: "builtin",
383
+ efforts: [...entry.efforts],
384
+ defaultEffort: entry.defaultEffort
385
+ });
386
+ }
387
+ __name(builtinReasoningEffort, "builtinReasoningEffort");
388
+ function catalogKey(adapter, model) {
389
+ return `${adapter}\0${model}`;
390
+ }
391
+ __name(catalogKey, "catalogKey");
392
+ var BEARER_DEFAULT_BASE_URLS = {
393
+ "openai-responses": "https://api.openai.com/v1",
394
+ "openai-chat-completions": "https://api.openai.com/v1",
395
+ "deepseek-chat": "https://api.deepseek.com",
396
+ "kimi-chat": "https://api.moonshot.ai/v1",
397
+ "zhipu-chat": "https://open.bigmodel.cn/api/paas/v4"
398
+ };
399
+ function trimBaseURL(value) {
400
+ return value.replace(/\/+$/u, "");
401
+ }
402
+ __name(trimBaseURL, "trimBaseURL");
403
+ function listEntry(model) {
404
+ return (body) => Array.isArray(body.models) ? body.models.find((entry) => isRecord(entry) && entry.slug === model) : Array.isArray(body.data) ? body.data.find((entry) => isRecord(entry) && entry.id === model) : void 0;
405
+ }
406
+ __name(listEntry, "listEntry");
407
+ function modelEndpoint(selection) {
408
+ const { adapter, model, providerConfig, options } = selection;
409
+ const apiKey = providerConfig.apiKey === void 0 || providerConfig.apiKey.trim() === "" ? void 0 : providerConfig.apiKey;
410
+ const bearer = BEARER_DEFAULT_BASE_URLS[adapter];
411
+ if (bearer !== void 0) {
412
+ return {
413
+ url: `${trimBaseURL(providerConfig.baseURL ?? bearer)}/models?client_version=may`,
414
+ headers: apiKey === void 0 ? {} : { Authorization: `Bearer ${apiKey}` },
415
+ entry: listEntry(model)
416
+ };
417
+ }
418
+ if (adapter === "anthropic-messages") {
419
+ return {
420
+ url: `${trimBaseURL(providerConfig.baseURL ?? "https://api.anthropic.com")}/v1/models?limit=1000`,
421
+ headers: {
422
+ "anthropic-version": typeof options.apiVersion === "string" ? options.apiVersion : "2023-06-01",
423
+ ...apiKey === void 0 ? {} : { "x-api-key": apiKey }
424
+ },
425
+ entry: listEntry(model)
426
+ };
427
+ }
428
+ if (adapter === "google-gemini") {
429
+ return {
430
+ url: `${trimBaseURL(providerConfig.baseURL ?? "https://generativelanguage.googleapis.com/v1beta")}/models/${encodeURIComponent(model)}`,
431
+ headers: apiKey === void 0 ? {} : { "x-goog-api-key": apiKey },
432
+ entry: /* @__PURE__ */ __name((body) => body, "entry")
433
+ };
434
+ }
435
+ return void 0;
436
+ }
437
+ __name(modelEndpoint, "modelEndpoint");
438
+ function effortNames(levels) {
439
+ return [
440
+ ...new Set(levels.flatMap((level) => {
441
+ const effort = typeof level === "string" ? level : isRecord(level) ? level.effort : void 0;
442
+ return typeof effort === "string" && effort.trim() !== "" ? [effort] : [];
443
+ }))
444
+ ];
445
+ }
446
+ __name(effortNames, "effortNames");
447
+ function entryReasoningEffort(entry) {
448
+ const effort = isRecord(entry.effort) ? entry.effort : void 0;
449
+ const levels = Array.isArray(entry.supported_reasoning_levels) ? entry.supported_reasoning_levels : Array.isArray(entry.reasoning_levels) ? entry.reasoning_levels : Array.isArray(effort?.supported_levels) ? effort.supported_levels : void 0;
450
+ if (levels === void 0)
451
+ return entry.thinking === false ? { status: "unsupported", source: "provider" } : void 0;
452
+ const efforts = effortNames(levels);
453
+ if (efforts.length === 0)
454
+ return void 0;
455
+ const defaultEffort = entry.default_reasoning_level ?? effort?.default_level;
456
+ return {
457
+ status: "known",
458
+ source: "provider",
459
+ efforts,
460
+ ...typeof defaultEffort === "string" && efforts.includes(defaultEffort) ? { defaultEffort } : {}
461
+ };
462
+ }
463
+ __name(entryReasoningEffort, "entryReasoningEffort");
464
+ var ModelListCapabilityDiscovery = class {
465
+ static {
466
+ __name(this, "ModelListCapabilityDiscovery");
467
+ }
468
+ fetchImplementation;
469
+ name = "model-list";
470
+ constructor(fetchImplementation) {
471
+ this.fetchImplementation = fetchImplementation;
472
+ }
473
+ async discoverReasoningEffort(selection) {
474
+ const endpoint = modelEndpoint(selection);
475
+ if (endpoint === void 0)
476
+ return void 0;
477
+ const response = await this.fetchImplementation(endpoint.url, {
478
+ signal: AbortSignal.timeout(1e4),
479
+ headers: endpoint.headers
480
+ });
481
+ if (response.status === 404)
482
+ return void 0;
483
+ if (!response.ok)
484
+ throw new Error("Capability catalog request failed");
485
+ const value = await response.json();
486
+ if (!isRecord(value))
487
+ return void 0;
488
+ const entry = endpoint.entry(value);
489
+ return isRecord(entry) ? entryReasoningEffort(entry) : void 0;
490
+ }
491
+ };
492
+ function isRecord(value) {
493
+ return typeof value === "object" && value !== null && !Array.isArray(value);
494
+ }
495
+ __name(isRecord, "isRecord");
496
+ function assertCapabilityFields(fields) {
497
+ const declarations = {};
498
+ for (const [field, capability] of Object.entries(fields)) {
499
+ if (!MODEL_CAPABILITY_KEYS.includes(field) || !isRecord(capability))
500
+ throw new TypeError("Invalid discovered capability field");
501
+ if (capability.status === "unknown" && capability.source === "unknown")
502
+ continue;
503
+ if (!["user", "provider", "builtin", "adapter"].includes(String(capability.source)))
504
+ throw new TypeError("Invalid capability source");
505
+ if (capability.status === "unsupported")
506
+ declarations[field] = false;
507
+ else if (capability.status === "known") {
508
+ if (capability.value === false)
509
+ throw new TypeError("False capability declarations require unsupported status");
510
+ declarations[field] = capability.value;
511
+ } else
512
+ throw new TypeError("Invalid capability status");
513
+ }
514
+ parseMayConfig({
515
+ providers: { metadata: { adapter: "metadata" } },
516
+ models: { metadata: { provider: "metadata", model: "metadata", capabilities: { fields: declarations } } }
517
+ });
518
+ }
519
+ __name(assertCapabilityFields, "assertCapabilityFields");
520
+ function assertReasoningCapabilities(capability) {
521
+ if (capability.status === "unknown" && capability.source === "unknown")
522
+ return;
523
+ if (!["user", "provider", "builtin", "adapter"].includes(capability.source))
524
+ throw new TypeError("Invalid reasoning capability source");
525
+ if (capability.status === "unsupported")
526
+ return;
527
+ if (capability.status !== "known")
528
+ throw new TypeError("Invalid reasoning capability status");
529
+ parseMayConfig({
530
+ providers: { metadata: { adapter: "metadata" } },
531
+ models: {
532
+ metadata: {
533
+ provider: "metadata",
534
+ model: "metadata",
535
+ capabilities: {
536
+ reasoning: omitUndefined({ efforts: capability.efforts, defaultEffort: capability.defaultEffort })
537
+ }
538
+ }
539
+ }
540
+ });
541
+ }
542
+ __name(assertReasoningCapabilities, "assertReasoningCapabilities");
543
+ function digest(value) {
544
+ return createHash("sha256").update(JSON.stringify(value)).digest("hex");
545
+ }
546
+ __name(digest, "digest");
547
+ function positive(value, field) {
548
+ if (!Number.isSafeInteger(value) || value < 1)
549
+ throw new RangeError(`${field} must be a positive safe integer`);
550
+ return value;
551
+ }
552
+ __name(positive, "positive");
553
+
554
+ // packages/providers/dist/anthropic/anthropic-model.js
555
+ import { executeRecordedRequest, requestEndpoint } from "@sortedyuan/may/core";
556
+
557
+ // packages/providers/dist/openai-compatible/http.js
558
+ async function* readSseData(response, signal, protocolError, providerName) {
559
+ if (!response.body) {
560
+ throw protocolError(`${providerName} response has no body`);
561
+ }
562
+ const reader = response.body.getReader();
563
+ const decoder = new TextDecoder();
564
+ const dataEvents = [];
565
+ const parser = createParser({
566
+ onEvent: /* @__PURE__ */ __name((event) => dataEvents.push(event.data), "onEvent")
567
+ });
568
+ const onAbort = /* @__PURE__ */ __name(() => {
569
+ void reader.cancel(signal.reason).catch(() => void 0);
570
+ }, "onAbort");
571
+ signal.addEventListener("abort", onAbort, { once: true });
572
+ try {
573
+ while (true) {
574
+ throwIfAborted(signal);
575
+ const { done, value } = await reader.read();
576
+ throwIfAborted(signal);
577
+ if (done) {
578
+ parser.feed(`${decoder.decode()}
579
+
580
+ `);
581
+ } else {
582
+ parser.feed(decoder.decode(value, { stream: true }));
583
+ }
584
+ for (const data of dataEvents) {
585
+ throwIfAborted(signal);
586
+ yield data;
587
+ }
588
+ dataEvents.length = 0;
589
+ if (done)
590
+ break;
591
+ }
592
+ throwIfAborted(signal);
593
+ } finally {
594
+ signal.removeEventListener("abort", onAbort);
595
+ void reader.cancel().catch(() => void 0);
596
+ reader.releaseLock();
597
+ }
598
+ }
599
+ __name(readSseData, "readSseData");
600
+ function parseRetryAfterMs(value) {
601
+ if (value === null)
602
+ return void 0;
603
+ const seconds = Number(value);
604
+ if (Number.isFinite(seconds) && seconds >= 0) {
605
+ return Math.round(seconds * 1e3);
606
+ }
607
+ const timestamp = Date.parse(value);
608
+ return Number.isFinite(timestamp) ? Math.max(0, timestamp - Date.now()) : void 0;
609
+ }
610
+ __name(parseRetryAfterMs, "parseRetryAfterMs");
611
+ function throwIfAborted(signal) {
612
+ if (!signal.aborted)
613
+ return;
614
+ if (signal.reason instanceof Error)
615
+ throw signal.reason;
616
+ throw new DOMException("The operation was aborted", "AbortError");
617
+ }
618
+ __name(throwIfAborted, "throwIfAborted");
619
+
620
+ // packages/providers/dist/anthropic/convert.js
621
+ import { UnsupportedContentError } from "@sortedyuan/may/core";
622
+
623
+ // packages/providers/dist/anthropic/errors.js
624
+ var AnthropicError = class extends Error {
625
+ static {
626
+ __name(this, "AnthropicError");
627
+ }
628
+ code;
629
+ constructor(code, message, options) {
630
+ super(message, options);
631
+ this.name = new.target.name;
632
+ this.code = code;
633
+ }
634
+ };
635
+ var AnthropicApiError = class extends AnthropicError {
636
+ static {
637
+ __name(this, "AnthropicApiError");
638
+ }
639
+ status;
640
+ providerType;
641
+ requestId;
642
+ retryAfterMs;
643
+ constructor(options) {
644
+ super("ANTHROPIC_API_ERROR", options.message);
645
+ this.status = options.status;
646
+ this.providerType = options.providerType;
647
+ this.requestId = options.requestId;
648
+ this.retryAfterMs = options.retryAfterMs;
649
+ }
650
+ };
651
+ var AnthropicStreamError = class extends AnthropicError {
652
+ static {
653
+ __name(this, "AnthropicStreamError");
654
+ }
655
+ providerType;
656
+ requestId;
657
+ constructor(options) {
658
+ super("ANTHROPIC_STREAM_ERROR", options.message);
659
+ this.providerType = options.providerType;
660
+ this.requestId = options.requestId;
661
+ }
662
+ };
663
+ var AnthropicProtocolError = class extends AnthropicError {
664
+ static {
665
+ __name(this, "AnthropicProtocolError");
666
+ }
667
+ constructor(message, options) {
668
+ super("ANTHROPIC_PROTOCOL_ERROR", message, options);
669
+ }
670
+ };
671
+ var AnthropicFinishReasonError = class extends AnthropicError {
672
+ static {
673
+ __name(this, "AnthropicFinishReasonError");
674
+ }
675
+ finishReason;
676
+ constructor(finishReason) {
677
+ super("ANTHROPIC_INCOMPLETE_RESPONSE", `Anthropic stopped with finish reason "${finishReason}"`);
678
+ this.finishReason = finishReason;
679
+ }
680
+ };
681
+
682
+ // packages/providers/dist/anthropic/protocol.js
683
+ var ANTHROPIC_MODEL_STATE_TYPE = "@may/provider-anthropic/message-v1";
684
+
685
+ // packages/providers/dist/anthropic/convert.js
686
+ function toAnthropicRequestParts(messages) {
687
+ const system = [];
688
+ const converted = [];
689
+ for (const message of messages) {
690
+ if (message.role === "system") {
691
+ const text = serializeVisibleContent(message.content);
692
+ if (text !== "")
693
+ system.push(text);
694
+ continue;
695
+ }
696
+ if (message.role === "user") {
697
+ converted.push({
698
+ role: "user",
699
+ content: toUserBlocks(message.content)
700
+ });
701
+ continue;
702
+ }
703
+ if (message.role === "tool") {
704
+ const toolResult = {
705
+ type: "tool_result",
706
+ tool_use_id: message.toolCallId,
707
+ content: hasMedia(message.content) ? toUserBlocks(message.content) : serializeVisibleContent(message.content, "tool")
708
+ };
709
+ if (message.isError !== void 0) {
710
+ toolResult.is_error = message.isError;
711
+ }
712
+ converted.push({ role: "user", content: [toolResult] });
713
+ continue;
714
+ }
715
+ const nativeContent = getAnthropicStateContent(message.modelState);
716
+ if (nativeContent !== void 0) {
717
+ converted.push({ role: "assistant", content: nativeContent });
718
+ continue;
719
+ }
720
+ const content = [...toAssistantTextBlocks(message.content)];
721
+ for (const call of message.toolCalls ?? []) {
722
+ if (!isRecord2(call.input)) {
723
+ throw new AnthropicProtocolError(`Anthropic tool call "${call.name}" input must be an object`);
724
+ }
725
+ content.push({
726
+ type: "tool_use",
727
+ id: call.id,
728
+ name: call.name,
729
+ input: call.input
730
+ });
731
+ }
732
+ converted.push({ role: "assistant", content });
733
+ }
734
+ const result = { messages: converted };
735
+ if (system.length > 0)
736
+ result.system = system.join("\n");
737
+ return result;
738
+ }
739
+ __name(toAnthropicRequestParts, "toAnthropicRequestParts");
740
+ function toAnthropicTools(tools) {
741
+ return tools.map((tool) => ({
742
+ name: tool.name,
743
+ description: tool.description,
744
+ input_schema: tool.inputSchema
745
+ }));
746
+ }
747
+ __name(toAnthropicTools, "toAnthropicTools");
748
+ function toAnthropicThinking(thinking) {
749
+ if (thinking.type === "enabled") {
750
+ const converted = {
751
+ type: "enabled",
752
+ budget_tokens: thinking.budgetTokens
753
+ };
754
+ if (thinking.display !== void 0)
755
+ converted.display = thinking.display;
756
+ return converted;
757
+ }
758
+ if (thinking.type === "adaptive") {
759
+ const converted = {
760
+ type: "adaptive"
761
+ };
762
+ if (thinking.display !== void 0)
763
+ converted.display = thinking.display;
764
+ return converted;
765
+ }
766
+ return { type: "disabled" };
767
+ }
768
+ __name(toAnthropicThinking, "toAnthropicThinking");
769
+ function getAnthropicStateContent(state) {
770
+ if (state?.type !== ANTHROPIC_MODEL_STATE_TYPE)
771
+ return void 0;
772
+ if (!isRecord2(state.data) || !Array.isArray(state.data.content)) {
773
+ throw new AnthropicProtocolError("Anthropic model state is malformed");
774
+ }
775
+ return state.data.content;
776
+ }
777
+ __name(getAnthropicStateContent, "getAnthropicStateContent");
778
+ function toAssistantTextBlocks(content) {
779
+ return content.flatMap((part) => {
780
+ if (part.type === "reasoning")
781
+ return [];
782
+ if (part.type !== "text" && part.type !== "json") {
783
+ throw new UnsupportedContentError("Anthropic adapter", part.type, "assistant");
784
+ }
785
+ return [
786
+ {
787
+ type: "text",
788
+ text: part.type === "text" ? part.text : serializeJson(part.value)
789
+ }
790
+ ];
791
+ });
792
+ }
793
+ __name(toAssistantTextBlocks, "toAssistantTextBlocks");
794
+ function toUserBlocks(content) {
795
+ return content.flatMap((part) => {
796
+ if (part.type === "reasoning")
797
+ return [];
798
+ if (part.type === "text")
799
+ return [{ type: "text", text: part.text }];
800
+ if (part.type === "json") {
801
+ return [{ type: "text", text: serializeJson(part.value) }];
802
+ }
803
+ if (part.type === "image") {
804
+ return [{ type: "image", source: toAnthropicSource(part.source) }];
805
+ }
806
+ if (part.type === "file") {
807
+ return [{ type: "document", source: toAnthropicSource(part.source) }];
808
+ }
809
+ throw new UnsupportedContentError("Anthropic adapter", part.type, "user");
810
+ });
811
+ }
812
+ __name(toUserBlocks, "toUserBlocks");
813
+ function serializeVisibleContent(content, role = "system") {
814
+ return content.filter((part) => part.type !== "reasoning").map((part) => {
815
+ if (part.type === "text")
816
+ return part.text;
817
+ if (part.type === "json")
818
+ return serializeJson(part.value);
819
+ throw new UnsupportedContentError("Anthropic adapter", part.type, role);
820
+ }).join("\n");
821
+ }
822
+ __name(serializeVisibleContent, "serializeVisibleContent");
823
+ function hasMedia(content) {
824
+ return content.some((part) => part.type === "image" || part.type === "file");
825
+ }
826
+ __name(hasMedia, "hasMedia");
827
+ function toAnthropicSource(source) {
828
+ if (source.type === "url")
829
+ return { type: "url", url: source.url };
830
+ if (source.type === "file")
831
+ return { type: "file", file_id: source.fileId };
832
+ return {
833
+ type: "base64",
834
+ media_type: source.mediaType,
835
+ data: source.data
836
+ };
837
+ }
838
+ __name(toAnthropicSource, "toAnthropicSource");
839
+ function serializeJson(value) {
840
+ const serialized = JSON.stringify(value);
841
+ return serialized === void 0 ? "null" : serialized;
842
+ }
843
+ __name(serializeJson, "serializeJson");
844
+ function isRecord2(value) {
845
+ return typeof value === "object" && value !== null && !Array.isArray(value);
846
+ }
847
+ __name(isRecord2, "isRecord");
848
+
849
+ // packages/providers/dist/anthropic/stream.js
850
+ async function* streamAnthropicResponse(response, signal) {
851
+ const blocks = /* @__PURE__ */ new Map();
852
+ let messageId;
853
+ let sawMessageStart = false;
854
+ let sawMessageStop = false;
855
+ let stopReason;
856
+ let inputTokens;
857
+ let outputTokens;
858
+ let cachedReadTokens;
859
+ let cachedWriteTokens;
860
+ const usageItems = /* @__PURE__ */ new Map();
861
+ for await (const data of readSseData(response, signal, (message2, options) => new AnthropicProtocolError(message2, options), "Anthropic")) {
862
+ const event = parseEvent(data);
863
+ if (event.type === "ping")
864
+ continue;
865
+ if (event.type === "error")
866
+ throw createStreamError(event);
867
+ if (event.type === "message_start") {
868
+ if (sawMessageStart) {
869
+ throw new AnthropicProtocolError("Anthropic emitted more than one message_start event");
870
+ }
871
+ const message2 = requireRecord(event.message, "message_start.message");
872
+ messageId = requireString(message2.id, "message_start.message.id");
873
+ const usage2 = optionalRecord(message2.usage);
874
+ inputTokens = optionalTokenCount(usage2?.input_tokens);
875
+ outputTokens = optionalTokenCount(usage2?.output_tokens);
876
+ cachedReadTokens = optionalTokenCount(usage2?.cache_read_input_tokens);
877
+ cachedWriteTokens = optionalTokenCount(usage2?.cache_creation_input_tokens);
878
+ collectUsageItems(usage2, usageItems);
879
+ sawMessageStart = true;
880
+ continue;
881
+ }
882
+ if (event.type === "content_block_start") {
883
+ requireActiveMessage(sawMessageStart, sawMessageStop);
884
+ const index = requireIndex(event.index);
885
+ if (blocks.has(index)) {
886
+ throw new AnthropicProtocolError(`Anthropic started content block ${index} more than once`);
887
+ }
888
+ blocks.set(index, createPendingBlock(event.content_block, index));
889
+ continue;
890
+ }
891
+ if (event.type === "content_block_delta") {
892
+ requireActiveMessage(sawMessageStart, sawMessageStop);
893
+ const index = requireIndex(event.index);
894
+ const block = requirePendingBlock(blocks, index);
895
+ const delta = requireRecord(event.delta, `content block ${index} delta`);
896
+ const deltaType = requireString(delta.type, `content block ${index} delta.type`);
897
+ if (deltaType === "text_delta") {
898
+ if (block.kind !== "text")
899
+ throw mismatchedDelta(index, deltaType);
900
+ const text = requireString(delta.text, `content block ${index} text`);
901
+ block.block.text += text;
902
+ if (text !== "")
903
+ yield { type: "text.delta", delta: text };
904
+ continue;
905
+ }
906
+ if (deltaType === "thinking_delta") {
907
+ if (block.kind !== "thinking")
908
+ throw mismatchedDelta(index, deltaType);
909
+ const thinking = requireString(delta.thinking, `content block ${index} thinking`);
910
+ block.block.thinking += thinking;
911
+ if (thinking !== "") {
912
+ yield { type: "reasoning.delta", delta: thinking };
913
+ }
914
+ continue;
915
+ }
916
+ if (deltaType === "signature_delta") {
917
+ if (block.kind !== "thinking")
918
+ throw mismatchedDelta(index, deltaType);
919
+ block.block.signature += requireString(delta.signature, `content block ${index} signature`);
920
+ continue;
921
+ }
922
+ if (deltaType === "input_json_delta") {
923
+ if (block.kind !== "tool_use")
924
+ throw mismatchedDelta(index, deltaType);
925
+ block.partialJson += requireString(delta.partial_json, `content block ${index} partial_json`);
926
+ }
927
+ continue;
928
+ }
929
+ if (event.type === "content_block_stop") {
930
+ requireActiveMessage(sawMessageStart, sawMessageStop);
931
+ const index = requireIndex(event.index);
932
+ const block = requirePendingBlock(blocks, index);
933
+ if (block.kind === "tool_use" && block.partialJson.trim() !== "") {
934
+ block.block.input = parseToolInput(block.partialJson, index);
935
+ }
936
+ block.stopped = true;
937
+ continue;
938
+ }
939
+ if (event.type === "message_delta") {
940
+ requireActiveMessage(sawMessageStart, sawMessageStop);
941
+ const delta = requireRecord(event.delta, "message_delta.delta");
942
+ if (delta.stop_reason !== void 0 && delta.stop_reason !== null) {
943
+ stopReason = requireString(delta.stop_reason, "message_delta.delta.stop_reason");
944
+ }
945
+ const usage2 = optionalRecord(event.usage);
946
+ inputTokens = optionalTokenCount(usage2?.input_tokens) ?? inputTokens;
947
+ outputTokens = optionalTokenCount(usage2?.output_tokens) ?? outputTokens;
948
+ cachedReadTokens = optionalTokenCount(usage2?.cache_read_input_tokens) ?? cachedReadTokens;
949
+ cachedWriteTokens = optionalTokenCount(usage2?.cache_creation_input_tokens) ?? cachedWriteTokens;
950
+ collectUsageItems(usage2, usageItems);
951
+ continue;
952
+ }
953
+ if (event.type === "message_stop") {
954
+ requireActiveMessage(sawMessageStart, sawMessageStop);
955
+ sawMessageStop = true;
956
+ }
957
+ }
958
+ if (!sawMessageStart || messageId === void 0) {
959
+ throw new AnthropicProtocolError("Anthropic stream ended without a message_start event");
960
+ }
961
+ if (!sawMessageStop) {
962
+ throw new AnthropicProtocolError("Anthropic stream ended without a message_stop event");
963
+ }
964
+ if (stopReason === void 0) {
965
+ throw new AnthropicProtocolError("Anthropic stream ended without a stop_reason");
966
+ }
967
+ if (stopReason !== "end_turn" && stopReason !== "tool_use") {
968
+ throw new AnthropicFinishReasonError(stopReason);
969
+ }
970
+ const content = [...blocks.entries()].sort(([left], [right]) => left - right).map(([index, block]) => {
971
+ if (!block.stopped) {
972
+ throw new AnthropicProtocolError(`Anthropic content block ${index} did not stop`);
973
+ }
974
+ return block.block;
975
+ });
976
+ const message = toAssistantMessage(messageId, content);
977
+ const calls = message.toolCalls ?? [];
978
+ if (stopReason === "tool_use" && calls.length === 0) {
979
+ throw new AnthropicProtocolError("Anthropic stopped for tool_use but emitted no tool calls");
980
+ }
981
+ if (stopReason !== "tool_use" && calls.length > 0) {
982
+ throw new AnthropicProtocolError(`Anthropic emitted tool calls with stop reason "${stopReason}"`);
983
+ }
984
+ const completed = {
985
+ type: "response.completed",
986
+ message
987
+ };
988
+ const usage = createUsage(inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, [...usageItems.values()]);
989
+ if (usage !== void 0)
990
+ completed.usage = usage;
991
+ yield completed;
992
+ }
993
+ __name(streamAnthropicResponse, "streamAnthropicResponse");
994
+ function parseEvent(data) {
995
+ try {
996
+ const event = JSON.parse(data);
997
+ const record = requireRecord(event, "stream event");
998
+ requireString(record.type, "stream event.type");
999
+ return record;
1000
+ } catch (error) {
1001
+ if (error instanceof AnthropicProtocolError)
1002
+ throw error;
1003
+ throw new AnthropicProtocolError("Anthropic emitted invalid SSE JSON", { cause: error });
1004
+ }
1005
+ }
1006
+ __name(parseEvent, "parseEvent");
1007
+ function createPendingBlock(value, index) {
1008
+ const block = requireRecord(value, `content block ${index}`);
1009
+ const type = requireString(block.type, `content block ${index}.type`);
1010
+ if (type === "text") {
1011
+ return {
1012
+ kind: "text",
1013
+ stopped: false,
1014
+ block: {
1015
+ type,
1016
+ text: requireString(block.text, `content block ${index}.text`)
1017
+ }
1018
+ };
1019
+ }
1020
+ if (type === "thinking") {
1021
+ return {
1022
+ kind: "thinking",
1023
+ stopped: false,
1024
+ block: {
1025
+ type,
1026
+ thinking: requireString(block.thinking, `content block ${index}.thinking`),
1027
+ signature: requireString(block.signature, `content block ${index}.signature`)
1028
+ }
1029
+ };
1030
+ }
1031
+ if (type === "redacted_thinking") {
1032
+ return {
1033
+ kind: "redacted_thinking",
1034
+ stopped: false,
1035
+ block: {
1036
+ type,
1037
+ data: requireString(block.data, `content block ${index}.data`)
1038
+ }
1039
+ };
1040
+ }
1041
+ if (type === "tool_use") {
1042
+ return {
1043
+ kind: "tool_use",
1044
+ stopped: false,
1045
+ partialJson: "",
1046
+ block: {
1047
+ type,
1048
+ id: requireString(block.id, `content block ${index}.id`),
1049
+ name: requireString(block.name, `content block ${index}.name`),
1050
+ input: requireObject(block.input, `content block ${index}.input`)
1051
+ }
1052
+ };
1053
+ }
1054
+ throw new AnthropicProtocolError(`Anthropic emitted unsupported content block type "${type}"`);
1055
+ }
1056
+ __name(createPendingBlock, "createPendingBlock");
1057
+ function toAssistantMessage(messageId, blocks) {
1058
+ const message = {
1059
+ role: "assistant",
1060
+ content: [],
1061
+ modelState: {
1062
+ type: ANTHROPIC_MODEL_STATE_TYPE,
1063
+ data: { messageId, content: blocks }
1064
+ }
1065
+ };
1066
+ const calls = [];
1067
+ for (const block of blocks) {
1068
+ if (block.type === "thinking") {
1069
+ message.content.push({ type: "reasoning", text: block.thinking });
1070
+ } else if (block.type === "text") {
1071
+ if (block.text !== "") {
1072
+ message.content.push({ type: "text", text: block.text });
1073
+ }
1074
+ } else if (block.type === "tool_use") {
1075
+ calls.push({ id: block.id, name: block.name, input: block.input });
1076
+ }
1077
+ }
1078
+ if (calls.length > 0)
1079
+ message.toolCalls = calls;
1080
+ return message;
1081
+ }
1082
+ __name(toAssistantMessage, "toAssistantMessage");
1083
+ function createStreamError(event) {
1084
+ const error = optionalRecord(event.error);
1085
+ const providerType = optionalString(error?.type);
1086
+ const requestId = optionalString(event.request_id);
1087
+ const message = optionalString(error?.message) ?? "Anthropic stream failed";
1088
+ const options = {
1089
+ message
1090
+ };
1091
+ if (providerType !== void 0)
1092
+ options.providerType = providerType;
1093
+ if (requestId !== void 0)
1094
+ options.requestId = requestId;
1095
+ return new AnthropicStreamError(options);
1096
+ }
1097
+ __name(createStreamError, "createStreamError");
1098
+ function parseToolInput(input, index) {
1099
+ try {
1100
+ return requireObject(JSON.parse(input), `content block ${index} tool input`);
1101
+ } catch (error) {
1102
+ if (error instanceof AnthropicProtocolError)
1103
+ throw error;
1104
+ throw new AnthropicProtocolError(`Anthropic emitted invalid tool input JSON at content block ${index}`, {
1105
+ cause: error
1106
+ });
1107
+ }
1108
+ }
1109
+ __name(parseToolInput, "parseToolInput");
1110
+ function requireActiveMessage(started, stopped) {
1111
+ if (!started) {
1112
+ throw new AnthropicProtocolError("Anthropic emitted content before message_start");
1113
+ }
1114
+ if (stopped) {
1115
+ throw new AnthropicProtocolError("Anthropic emitted content after message_stop");
1116
+ }
1117
+ }
1118
+ __name(requireActiveMessage, "requireActiveMessage");
1119
+ function requirePendingBlock(blocks, index) {
1120
+ const block = blocks.get(index);
1121
+ if (!block) {
1122
+ throw new AnthropicProtocolError(`Anthropic referenced unknown content block ${index}`);
1123
+ }
1124
+ if (block.stopped) {
1125
+ throw new AnthropicProtocolError(`Anthropic emitted a delta after content block ${index} stopped`);
1126
+ }
1127
+ return block;
1128
+ }
1129
+ __name(requirePendingBlock, "requirePendingBlock");
1130
+ function mismatchedDelta(index, deltaType) {
1131
+ return new AnthropicProtocolError(`Anthropic emitted ${deltaType} for incompatible content block ${index}`);
1132
+ }
1133
+ __name(mismatchedDelta, "mismatchedDelta");
1134
+ function requireRecord(value, name) {
1135
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1136
+ throw new AnthropicProtocolError(`Anthropic ${name} must be an object`);
1137
+ }
1138
+ return value;
1139
+ }
1140
+ __name(requireRecord, "requireRecord");
1141
+ function requireObject(value, name) {
1142
+ return requireRecord(value, name);
1143
+ }
1144
+ __name(requireObject, "requireObject");
1145
+ function optionalRecord(value) {
1146
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1147
+ }
1148
+ __name(optionalRecord, "optionalRecord");
1149
+ function requireString(value, name) {
1150
+ if (typeof value !== "string") {
1151
+ throw new AnthropicProtocolError(`Anthropic ${name} must be a string`);
1152
+ }
1153
+ return value;
1154
+ }
1155
+ __name(requireString, "requireString");
1156
+ function optionalString(value) {
1157
+ return typeof value === "string" ? value : void 0;
1158
+ }
1159
+ __name(optionalString, "optionalString");
1160
+ function requireIndex(value) {
1161
+ if (!Number.isSafeInteger(value) || value < 0) {
1162
+ throw new AnthropicProtocolError("Anthropic content block index must be a non-negative safe integer");
1163
+ }
1164
+ return value;
1165
+ }
1166
+ __name(requireIndex, "requireIndex");
1167
+ function optionalTokenCount(value) {
1168
+ if (value === void 0)
1169
+ return void 0;
1170
+ if (!Number.isSafeInteger(value) || value < 0)
1171
+ throw new AnthropicProtocolError("Anthropic usage token count must be a non-negative safe integer");
1172
+ return value;
1173
+ }
1174
+ __name(optionalTokenCount, "optionalTokenCount");
1175
+ function createUsage(inputTokens, outputTokens, cachedReadTokens, cachedWriteTokens, items) {
1176
+ if (inputTokens === void 0 && outputTokens === void 0 && cachedReadTokens === void 0 && cachedWriteTokens === void 0)
1177
+ return void 0;
1178
+ const usage = {};
1179
+ if (inputTokens !== void 0)
1180
+ usage.inputTokens = inputTokens;
1181
+ if (outputTokens !== void 0)
1182
+ usage.outputTokens = outputTokens;
1183
+ if (cachedReadTokens !== void 0)
1184
+ usage.cachedReadTokens = cachedReadTokens;
1185
+ if (cachedWriteTokens !== void 0)
1186
+ usage.cachedWriteTokens = cachedWriteTokens;
1187
+ if (items.length > 0)
1188
+ usage.items = items;
1189
+ if (cachedReadTokens !== void 0 || cachedWriteTokens !== void 0)
1190
+ usage.tokenRelations = {
1191
+ ...cachedReadTokens === void 0 ? {} : { cachedRead: "total" },
1192
+ ...cachedWriteTokens === void 0 ? {} : { cachedWrite: "total" }
1193
+ };
1194
+ if (inputTokens !== void 0 && outputTokens !== void 0) {
1195
+ usage.totalTokens = inputTokens + outputTokens + (cachedReadTokens ?? 0) + (cachedWriteTokens ?? 0);
1196
+ }
1197
+ if (inputTokens === void 0 || outputTokens === void 0)
1198
+ usage.completeness = { status: "partial", reason: "provider-token-components-missing" };
1199
+ return usage;
1200
+ }
1201
+ __name(createUsage, "createUsage");
1202
+ function collectUsageItems(usage, items) {
1203
+ if (usage === void 0)
1204
+ return;
1205
+ const cache = usage.cache_creation === void 0 || usage.cache_creation === null ? void 0 : requireRecord(usage.cache_creation, "usage.cache_creation");
1206
+ for (const [field, id] of [
1207
+ ["ephemeral_5m_input_tokens", "cache-write-5m"],
1208
+ ["ephemeral_1h_input_tokens", "cache-write-1h"]
1209
+ ]) {
1210
+ const quantity = optionalTokenCount(cache?.[field]);
1211
+ if (quantity !== void 0)
1212
+ items.set(id, { id, quantity, unit: "tokens", includedIn: "cachedWrite" });
1213
+ }
1214
+ const server = usage.server_tool_use === void 0 || usage.server_tool_use === null ? void 0 : requireRecord(usage.server_tool_use, "usage.server_tool_use");
1215
+ for (const [field, id] of [
1216
+ ["web_search_requests", "web-search"],
1217
+ ["web_fetch_requests", "web-fetch"]
1218
+ ]) {
1219
+ const quantity = optionalTokenCount(server?.[field]);
1220
+ if (quantity !== void 0)
1221
+ items.set(id, { id, quantity, unit: "requests", includedIn: "none" });
1222
+ }
1223
+ }
1224
+ __name(collectUsageItems, "collectUsageItems");
1225
+
1226
+ // packages/providers/dist/anthropic/anthropic-model.js
1227
+ var FILES_API_BETA = "files-api-2025-04-14";
1228
+ var AnthropicModel = class {
1229
+ static {
1230
+ __name(this, "AnthropicModel");
1231
+ }
1232
+ supportsRequestRecording = true;
1233
+ apiKey;
1234
+ promptCaching;
1235
+ model;
1236
+ baseURL;
1237
+ apiVersion;
1238
+ maxTokens;
1239
+ thinking;
1240
+ reasoningEffort;
1241
+ fetchImplementation;
1242
+ constructor(options) {
1243
+ if (options.apiKey.trim() === "") {
1244
+ throw new TypeError("apiKey must not be empty");
1245
+ }
1246
+ if (options.model.trim() === "") {
1247
+ throw new TypeError("model must not be empty");
1248
+ }
1249
+ const maxTokens = options.maxTokens ?? 4096;
1250
+ if (!Number.isSafeInteger(maxTokens) || maxTokens < 1) {
1251
+ throw new RangeError("maxTokens must be a positive safe integer");
1252
+ }
1253
+ if (options.apiVersion !== void 0 && options.apiVersion.trim() === "") {
1254
+ throw new TypeError("apiVersion must not be empty");
1255
+ }
1256
+ if (options.thinking?.type === "enabled") {
1257
+ if (!Number.isSafeInteger(options.thinking.budgetTokens) || options.thinking.budgetTokens < 1024) {
1258
+ throw new RangeError("thinking.budgetTokens must be a safe integer of at least 1024");
1259
+ }
1260
+ if (options.thinking.budgetTokens >= maxTokens) {
1261
+ throw new RangeError("thinking.budgetTokens must be less than maxTokens");
1262
+ }
1263
+ }
1264
+ this.apiKey = options.apiKey;
1265
+ if (options.promptCaching !== void 0 && options.promptCaching !== false) {
1266
+ if (typeof options.promptCaching !== "object" || options.promptCaching === null || Array.isArray(options.promptCaching)) {
1267
+ throw new TypeError("promptCaching must be false or an object");
1268
+ }
1269
+ if (options.promptCaching.ttl !== void 0 && !["5m", "1h"].includes(options.promptCaching.ttl)) {
1270
+ throw new TypeError("promptCaching.ttl must be 5m or 1h");
1271
+ }
1272
+ if (options.promptCaching.cacheInstructions !== void 0 && typeof options.promptCaching.cacheInstructions !== "boolean") {
1273
+ throw new TypeError("promptCaching.cacheInstructions must be a boolean");
1274
+ }
1275
+ }
1276
+ this.promptCaching = options.promptCaching === void 0 || options.promptCaching === false ? options.promptCaching : { ...options.promptCaching };
1277
+ this.model = options.model;
1278
+ this.baseURL = (options.baseURL ?? "https://api.anthropic.com").replace(/\/+$/, "");
1279
+ this.apiVersion = options.apiVersion ?? "2023-06-01";
1280
+ this.maxTokens = maxTokens;
1281
+ this.thinking = cloneThinking(options.thinking);
1282
+ this.reasoningEffort = options.reasoningEffort;
1283
+ this.fetchImplementation = options.fetch ?? globalThis.fetch;
1284
+ }
1285
+ async *stream(request, options) {
1286
+ if (request.responseFormat !== void 0)
1287
+ throw new TypeError("Anthropic adapter does not support responseFormat");
1288
+ const body = this.createRequest(request);
1289
+ yield* executeRecordedRequest({
1290
+ version: 1,
1291
+ adapter: "anthropic-messages",
1292
+ purpose: "generation",
1293
+ endpoint: requestEndpoint(`${this.baseURL}/v1/messages`),
1294
+ request,
1295
+ body,
1296
+ protocol: {
1297
+ "anthropic-version": this.apiVersion,
1298
+ ...usesFileId(request.messages) ? { "anthropic-beta": FILES_API_BETA } : {}
1299
+ }
1300
+ }, options.recordRequest, options.signal, (body2) => this.execute(body2, request, options));
1301
+ }
1302
+ async *execute(body, request, options) {
1303
+ const headers = {
1304
+ "anthropic-version": this.apiVersion,
1305
+ "content-type": "application/json",
1306
+ "x-api-key": this.apiKey
1307
+ };
1308
+ if (usesFileId(request.messages)) {
1309
+ headers["anthropic-beta"] = FILES_API_BETA;
1310
+ }
1311
+ const response = await this.fetchImplementation(`${this.baseURL}/v1/messages`, {
1312
+ method: "POST",
1313
+ headers,
1314
+ body,
1315
+ signal: options.signal
1316
+ });
1317
+ if (!response.ok)
1318
+ throw await createApiError(response);
1319
+ yield* streamAnthropicResponse(response, options.signal);
1320
+ }
1321
+ createRequest(request) {
1322
+ const parts = toAnthropicRequestParts(request.messages);
1323
+ const body = {
1324
+ model: this.model,
1325
+ max_tokens: this.maxTokens,
1326
+ messages: parts.messages,
1327
+ stream: true
1328
+ };
1329
+ if (parts.system !== void 0)
1330
+ body.system = parts.system;
1331
+ if (request.tools.length > 0) {
1332
+ body.tools = toAnthropicTools(request.tools);
1333
+ }
1334
+ if (this.promptCaching) {
1335
+ const cacheControl = { type: "ephemeral", ttl: this.promptCaching.ttl ?? "5m" };
1336
+ body.cache_control = cacheControl;
1337
+ if (this.promptCaching.cacheInstructions) {
1338
+ if (parts.system !== void 0)
1339
+ body.system = [{ type: "text", text: parts.system, cache_control: cacheControl }];
1340
+ const lastTool = body.tools?.at(-1);
1341
+ if (lastTool)
1342
+ lastTool.cache_control = cacheControl;
1343
+ }
1344
+ }
1345
+ if (this.thinking !== void 0) {
1346
+ body.thinking = toAnthropicThinking(this.thinking);
1347
+ }
1348
+ if (this.reasoningEffort !== void 0) {
1349
+ body.output_config = { effort: this.reasoningEffort };
1350
+ }
1351
+ return body;
1352
+ }
1353
+ };
1354
+ function usesFileId(messages) {
1355
+ return messages.some((message) => message.content.some((part) => (part.type === "image" || part.type === "file") && part.source.type === "file"));
1356
+ }
1357
+ __name(usesFileId, "usesFileId");
1358
+ function cloneThinking(thinking) {
1359
+ return thinking === void 0 ? void 0 : { ...thinking };
1360
+ }
1361
+ __name(cloneThinking, "cloneThinking");
1362
+ async function createApiError(response) {
1363
+ const text = await response.text();
1364
+ let message = text || `Anthropic request failed with status ${response.status}`;
1365
+ let providerType;
1366
+ let requestId = response.headers.get("request-id") ?? void 0;
1367
+ try {
1368
+ const parsed = JSON.parse(text);
1369
+ if (typeof parsed.error?.message === "string") {
1370
+ message = parsed.error.message;
1371
+ }
1372
+ if (typeof parsed.error?.type === "string") {
1373
+ providerType = parsed.error.type;
1374
+ }
1375
+ if (typeof parsed.request_id === "string") {
1376
+ requestId = parsed.request_id;
1377
+ }
1378
+ } catch {
1379
+ }
1380
+ const options = {
1381
+ status: response.status,
1382
+ message
1383
+ };
1384
+ if (providerType !== void 0)
1385
+ options.providerType = providerType;
1386
+ if (requestId !== void 0)
1387
+ options.requestId = requestId;
1388
+ const retryAfterMs2 = parseRetryAfterMs(response.headers.get("retry-after"));
1389
+ if (retryAfterMs2 !== void 0)
1390
+ options.retryAfterMs = retryAfterMs2;
1391
+ return new AnthropicApiError(options);
1392
+ }
1393
+ __name(createApiError, "createApiError");
1394
+
1395
+ // packages/providers/dist/deepseek/index.js
1396
+ import { omitUndefined as omitUndefined4 } from "@sortedyuan/may/core";
1397
+
1398
+ // packages/providers/dist/openai-compatible/chat-model.js
1399
+ import { assertModelResponseFormat, executeRecordedRequest as executeRecordedRequest2, omitUndefined as omitUndefined3, requestEndpoint as requestEndpoint2, validateStructuredModelResponse } from "@sortedyuan/may/core";
1400
+
1401
+ // packages/providers/dist/openai-compatible/convert.js
1402
+ import { UnsupportedContentError as UnsupportedContentError2, omitUndefined as omitUndefined2 } from "@sortedyuan/may/core";
1403
+ function toOpenAICompatibleMessages(messages, options = {}) {
1404
+ return messages.map((message) => {
1405
+ if (message.role === "system") {
1406
+ return {
1407
+ role: "system",
1408
+ content: serializeVisibleContent2(message.content, "system")
1409
+ };
1410
+ }
1411
+ if (message.role === "user") {
1412
+ return { role: "user", content: toUserContent(message.content) };
1413
+ }
1414
+ if (message.role === "tool") {
1415
+ const converted2 = {
1416
+ role: "tool",
1417
+ tool_call_id: message.toolCallId,
1418
+ content: serializeVisibleContent2(message.content, "tool")
1419
+ };
1420
+ if (options.includeToolName)
1421
+ converted2.name = message.name;
1422
+ return converted2;
1423
+ }
1424
+ const converted = {
1425
+ role: "assistant",
1426
+ content: serializeVisibleContent2(message.content, "assistant")
1427
+ };
1428
+ const reasoningParts = message.content.filter((part) => part.type === "reasoning");
1429
+ if (reasoningParts.length > 0) {
1430
+ converted.reasoning_content = reasoningParts.map((part) => part.text).join("");
1431
+ }
1432
+ if (message.toolCalls !== void 0) {
1433
+ converted.tool_calls = message.toolCalls.map(convertToolCall);
1434
+ }
1435
+ return converted;
1436
+ });
1437
+ }
1438
+ __name(toOpenAICompatibleMessages, "toOpenAICompatibleMessages");
1439
+ function toOpenAICompatibleTools(tools) {
1440
+ return tools.map((tool) => ({
1441
+ type: "function",
1442
+ function: {
1443
+ name: tool.name,
1444
+ description: tool.description,
1445
+ parameters: tool.inputSchema
1446
+ }
1447
+ }));
1448
+ }
1449
+ __name(toOpenAICompatibleTools, "toOpenAICompatibleTools");
1450
+ function convertToolCall(call) {
1451
+ return {
1452
+ id: call.id,
1453
+ type: "function",
1454
+ function: {
1455
+ name: call.name,
1456
+ arguments: serializeJson2(call.input)
1457
+ }
1458
+ };
1459
+ }
1460
+ __name(convertToolCall, "convertToolCall");
1461
+ function toUserContent(content) {
1462
+ const hasImages = content.some((part) => part.type === "image");
1463
+ if (!hasImages)
1464
+ return serializeVisibleContent2(content, "user");
1465
+ return content.flatMap((part) => {
1466
+ if (part.type === "reasoning")
1467
+ return [];
1468
+ if (part.type === "text")
1469
+ return [{ type: "text", text: part.text }];
1470
+ if (part.type === "json") {
1471
+ return [{ type: "text", text: serializeJson2(part.value) }];
1472
+ }
1473
+ if (part.type === "image") {
1474
+ const imageUrl = imageSourceUrl(part.source);
1475
+ return [
1476
+ {
1477
+ type: "image_url",
1478
+ image_url: omitUndefined2({ url: imageUrl, detail: part.detail })
1479
+ }
1480
+ ];
1481
+ }
1482
+ throw new UnsupportedContentError2("OpenAI-compatible chat adapter", part.type, "user");
1483
+ });
1484
+ }
1485
+ __name(toUserContent, "toUserContent");
1486
+ function serializeVisibleContent2(content, role) {
1487
+ return content.filter((part) => part.type !== "reasoning").map((part) => {
1488
+ if (part.type === "text")
1489
+ return part.text;
1490
+ if (part.type === "json")
1491
+ return serializeJson2(part.value);
1492
+ throw new UnsupportedContentError2("OpenAI-compatible chat adapter", part.type, role);
1493
+ }).join("\n");
1494
+ }
1495
+ __name(serializeVisibleContent2, "serializeVisibleContent");
1496
+ function imageSourceUrl(source) {
1497
+ if (source.type === "url")
1498
+ return source.url;
1499
+ if (source.type === "base64") {
1500
+ return `data:${source.mediaType};base64,${source.data}`;
1501
+ }
1502
+ throw new UnsupportedContentError2("OpenAI-compatible chat adapter", "image file-id source", "user");
1503
+ }
1504
+ __name(imageSourceUrl, "imageSourceUrl");
1505
+ function serializeJson2(value) {
1506
+ const serialized = JSON.stringify(value);
1507
+ return serialized === void 0 ? "null" : serialized;
1508
+ }
1509
+ __name(serializeJson2, "serializeJson");
1510
+
1511
+ // packages/providers/dist/openai-compatible/errors.js
1512
+ var OpenAICompatibleError = class extends Error {
1513
+ static {
1514
+ __name(this, "OpenAICompatibleError");
1515
+ }
1516
+ code;
1517
+ provider;
1518
+ constructor(provider, code, message, options) {
1519
+ super(message, options);
1520
+ this.name = new.target.name;
1521
+ this.provider = provider;
1522
+ this.code = code;
1523
+ }
1524
+ };
1525
+ var OpenAICompatibleApiError = class extends OpenAICompatibleError {
1526
+ static {
1527
+ __name(this, "OpenAICompatibleApiError");
1528
+ }
1529
+ status;
1530
+ providerType;
1531
+ providerCode;
1532
+ retryAfterMs;
1533
+ constructor(provider, codePrefix, options) {
1534
+ super(provider, `${codePrefix}_API_ERROR`, options.message);
1535
+ this.status = options.status;
1536
+ this.providerType = options.providerType;
1537
+ this.providerCode = options.providerCode;
1538
+ this.retryAfterMs = options.retryAfterMs;
1539
+ }
1540
+ };
1541
+ var OpenAICompatibleProtocolError = class extends OpenAICompatibleError {
1542
+ static {
1543
+ __name(this, "OpenAICompatibleProtocolError");
1544
+ }
1545
+ constructor(provider, codePrefix, message, options) {
1546
+ super(provider, `${codePrefix}_PROTOCOL_ERROR`, message, options);
1547
+ }
1548
+ };
1549
+ var OpenAICompatibleFinishReasonError = class extends OpenAICompatibleError {
1550
+ static {
1551
+ __name(this, "OpenAICompatibleFinishReasonError");
1552
+ }
1553
+ finishReason;
1554
+ constructor(provider, codePrefix, finishReason) {
1555
+ super(provider, `${codePrefix}_INCOMPLETE_RESPONSE`, `${provider} stopped with finish reason "${finishReason}"`);
1556
+ this.finishReason = finishReason;
1557
+ }
1558
+ };
1559
+
1560
+ // packages/providers/dist/openai-compatible/stream.js
1561
+ async function* streamOpenAICompatibleResponse(response, options) {
1562
+ let text = "";
1563
+ let reasoning = "";
1564
+ let hasReasoningContent = false;
1565
+ let usage;
1566
+ let finishReason;
1567
+ let receivedDone = false;
1568
+ const pendingCalls = /* @__PURE__ */ new Map();
1569
+ for await (const data of readSseData(response, options.signal, options.protocolError, options.providerName)) {
1570
+ if (data === "[DONE]") {
1571
+ receivedDone = true;
1572
+ break;
1573
+ }
1574
+ const chunk = parseChunk(data, options);
1575
+ if (chunk.error !== void 0) {
1576
+ throw options.protocolError(`${options.providerName} stream reported an error: ${describeStreamError(chunk.error)}`);
1577
+ }
1578
+ if (chunk.usage)
1579
+ usage = convertUsage(chunk.usage, options);
1580
+ for (const choice of chunk.choices ?? []) {
1581
+ if (choice.index !== 0)
1582
+ continue;
1583
+ const delta = choice.delta;
1584
+ if (typeof delta?.reasoning_content === "string") {
1585
+ hasReasoningContent = true;
1586
+ if (delta.reasoning_content !== "") {
1587
+ reasoning += delta.reasoning_content;
1588
+ yield { type: "reasoning.delta", delta: delta.reasoning_content };
1589
+ }
1590
+ }
1591
+ if (delta?.content) {
1592
+ text += delta.content;
1593
+ yield { type: "text.delta", delta: delta.content };
1594
+ }
1595
+ if (delta?.refusal) {
1596
+ text += delta.refusal;
1597
+ yield { type: "text.delta", delta: delta.refusal };
1598
+ }
1599
+ for (const toolDelta of delta?.tool_calls ?? []) {
1600
+ mergeToolCall(pendingCalls, toolDelta);
1601
+ }
1602
+ if (choice.finish_reason !== null && choice.finish_reason !== void 0) {
1603
+ finishReason = choice.finish_reason;
1604
+ }
1605
+ }
1606
+ }
1607
+ if (options.requireDone && !receivedDone) {
1608
+ throw options.protocolError(`${options.providerName} stream ended without [DONE]`);
1609
+ }
1610
+ if (finishReason === void 0) {
1611
+ throw options.protocolError(`${options.providerName} stream ended without a finish_reason`);
1612
+ }
1613
+ if (finishReason !== "stop" && finishReason !== "tool_calls") {
1614
+ throw options.finishReasonError(finishReason);
1615
+ }
1616
+ const toolCalls = completeToolCalls(pendingCalls, options);
1617
+ if (finishReason === "tool_calls" && toolCalls.length === 0) {
1618
+ throw options.protocolError(`${options.providerName} finished with tool_calls but emitted no tool calls`);
1619
+ }
1620
+ const message = { role: "assistant", content: [] };
1621
+ if (hasReasoningContent) {
1622
+ message.content.push({ type: "reasoning", text: reasoning });
1623
+ }
1624
+ if (text !== "")
1625
+ message.content.push({ type: "text", text });
1626
+ if (toolCalls.length > 0)
1627
+ message.toolCalls = toolCalls;
1628
+ const completed = {
1629
+ type: "response.completed",
1630
+ message
1631
+ };
1632
+ if (usage !== void 0)
1633
+ completed.usage = usage;
1634
+ yield completed;
1635
+ }
1636
+ __name(streamOpenAICompatibleResponse, "streamOpenAICompatibleResponse");
1637
+ function parseChunk(data, options) {
1638
+ try {
1639
+ const value = JSON.parse(data);
1640
+ if (typeof value !== "object" || value === null) {
1641
+ throw new TypeError("chunk is not an object");
1642
+ }
1643
+ return value;
1644
+ } catch (error) {
1645
+ throw options.protocolError(`${options.providerName} emitted invalid SSE JSON`, { cause: error });
1646
+ }
1647
+ }
1648
+ __name(parseChunk, "parseChunk");
1649
+ function describeStreamError(error) {
1650
+ if (typeof error === "string") {
1651
+ return error.trim() === "" ? "an empty error string" : error;
1652
+ }
1653
+ if (typeof error === "number" || typeof error === "boolean") {
1654
+ return `a ${typeof error} error value ${String(error)}`;
1655
+ }
1656
+ if (error === null)
1657
+ return "a null error value";
1658
+ if (Array.isArray(error))
1659
+ return "an array error value";
1660
+ if (typeof error !== "object")
1661
+ return `an unsupported ${typeof error} error value`;
1662
+ const payload = error;
1663
+ const details = [];
1664
+ const message = readText(payload.message);
1665
+ const type = readText(payload.type);
1666
+ const code = readText(payload.code) ?? readNumber(payload.code);
1667
+ if (message !== void 0)
1668
+ details.push(message);
1669
+ if (type !== void 0)
1670
+ details.push(`type: ${type}`);
1671
+ if (code !== void 0)
1672
+ details.push(`code: ${code}`);
1673
+ if (details.length === 0)
1674
+ return "an error object without message, type, or code";
1675
+ return details.join(" ");
1676
+ }
1677
+ __name(describeStreamError, "describeStreamError");
1678
+ function readText(value) {
1679
+ if (typeof value !== "string")
1680
+ return void 0;
1681
+ return value.trim() === "" ? void 0 : value;
1682
+ }
1683
+ __name(readText, "readText");
1684
+ function readNumber(value) {
1685
+ if (typeof value !== "number" || !Number.isFinite(value))
1686
+ return void 0;
1687
+ return String(value);
1688
+ }
1689
+ __name(readNumber, "readNumber");
1690
+ function mergeToolCall(calls, delta) {
1691
+ const call = calls.get(delta.index) ?? { id: "", name: "", arguments: "" };
1692
+ if (delta.id !== void 0)
1693
+ call.id = delta.id;
1694
+ if (delta.function?.name !== void 0)
1695
+ call.name += delta.function.name;
1696
+ if (delta.function?.arguments !== void 0) {
1697
+ call.arguments += delta.function.arguments;
1698
+ }
1699
+ calls.set(delta.index, call);
1700
+ }
1701
+ __name(mergeToolCall, "mergeToolCall");
1702
+ function completeToolCalls(calls, options) {
1703
+ return [...calls.entries()].sort(([left], [right]) => left - right).map(([index, call]) => {
1704
+ if (call.id === "" || call.name === "") {
1705
+ throw options.protocolError(`${options.providerName} emitted an incomplete tool call at index ${index}`);
1706
+ }
1707
+ return {
1708
+ id: call.id,
1709
+ name: call.name,
1710
+ input: parseToolInput2(call.arguments, options)
1711
+ };
1712
+ });
1713
+ }
1714
+ __name(completeToolCalls, "completeToolCalls");
1715
+ function parseToolInput2(input, options) {
1716
+ if (input === "")
1717
+ return {};
1718
+ try {
1719
+ return JSON.parse(input);
1720
+ } catch {
1721
+ throw options.protocolError(`${options.providerName} emitted invalid tool argument JSON`);
1722
+ }
1723
+ }
1724
+ __name(parseToolInput2, "parseToolInput");
1725
+ function convertUsage(usage, options) {
1726
+ const converted = {};
1727
+ const token = /* @__PURE__ */ __name((value, field) => {
1728
+ if (value === void 0)
1729
+ return void 0;
1730
+ if (!Number.isSafeInteger(value) || value < 0)
1731
+ throw options.protocolError(`${options.providerName} usage.${field} must be a non-negative safe integer`);
1732
+ return value;
1733
+ }, "token");
1734
+ if (usage.prompt_tokens !== void 0) {
1735
+ converted.inputTokens = token(usage.prompt_tokens, "prompt_tokens");
1736
+ }
1737
+ if (usage.completion_tokens !== void 0) {
1738
+ converted.outputTokens = token(usage.completion_tokens, "completion_tokens");
1739
+ }
1740
+ if (usage.total_tokens !== void 0) {
1741
+ converted.totalTokens = token(usage.total_tokens, "total_tokens");
1742
+ }
1743
+ const cachedReadTokens = token(usage.prompt_tokens_details?.cached_tokens ?? usage.prompt_cache_hit_tokens, "cached_tokens");
1744
+ const cachedWriteTokens = token(usage.prompt_tokens_details?.cache_write_tokens, "cache_write_tokens");
1745
+ const reasoningTokens = token(usage.completion_tokens_details?.reasoning_tokens, "reasoning_tokens");
1746
+ if (cachedReadTokens !== void 0)
1747
+ converted.cachedReadTokens = cachedReadTokens;
1748
+ if (cachedWriteTokens !== void 0)
1749
+ converted.cachedWriteTokens = cachedWriteTokens;
1750
+ if (reasoningTokens !== void 0)
1751
+ converted.reasoningTokens = reasoningTokens;
1752
+ if (cachedReadTokens !== void 0 || cachedWriteTokens !== void 0 || reasoningTokens !== void 0)
1753
+ converted.tokenRelations = {
1754
+ ...cachedReadTokens === void 0 ? {} : { cachedRead: "input" },
1755
+ ...cachedWriteTokens === void 0 ? {} : { cachedWrite: "input" },
1756
+ ...reasoningTokens === void 0 ? {} : { reasoning: "output" }
1757
+ };
1758
+ const items = [];
1759
+ const cachedMiss = token(usage.prompt_cache_miss_tokens, "prompt_cache_miss_tokens");
1760
+ if (cachedMiss !== void 0 && cachedReadTokens !== void 0 && converted.inputTokens !== void 0 && cachedReadTokens + cachedMiss !== converted.inputTokens)
1761
+ throw options.protocolError(`${options.providerName} cache token counts do not match prompt_tokens`);
1762
+ for (const [id, value] of [
1763
+ ["input-audio", usage.prompt_tokens_details?.audio_tokens],
1764
+ ["output-audio", usage.completion_tokens_details?.audio_tokens]
1765
+ ]) {
1766
+ const quantity = token(value, id);
1767
+ if (quantity !== void 0 && quantity > 0)
1768
+ items.push({ id, quantity, unit: "tokens", includedIn: id === "input-audio" ? "input" : "output" });
1769
+ }
1770
+ if (items.length > 0)
1771
+ converted.items = items;
1772
+ if (converted.inputTokens === void 0 || converted.outputTokens === void 0)
1773
+ converted.completeness = { status: "partial", reason: "provider-token-components-missing" };
1774
+ return converted;
1775
+ }
1776
+ __name(convertUsage, "convertUsage");
1777
+
1778
+ // packages/providers/dist/openai-compatible/chat-model.js
1779
+ var OpenAICompatibleChatModel = class {
1780
+ static {
1781
+ __name(this, "OpenAICompatibleChatModel");
1782
+ }
1783
+ dialect;
1784
+ supportsRequestRecording = true;
1785
+ apiKey;
1786
+ model;
1787
+ baseURL;
1788
+ maxOutputTokens;
1789
+ reasoningEffort;
1790
+ fetchImplementation;
1791
+ constructor(options, dialect) {
1792
+ this.dialect = dialect;
1793
+ if (options.apiKey.trim() === "")
1794
+ throw new TypeError("apiKey must not be empty");
1795
+ if (options.model.trim() === "")
1796
+ throw new TypeError("model must not be empty");
1797
+ if (options.maxOutputTokens !== void 0 && (!Number.isSafeInteger(options.maxOutputTokens) || options.maxOutputTokens < 1)) {
1798
+ throw new RangeError("Maximum output tokens must be a positive safe integer");
1799
+ }
1800
+ this.apiKey = options.apiKey;
1801
+ this.model = options.model;
1802
+ this.baseURL = (options.baseURL ?? dialect.defaultBaseURL).replace(/\/+$/, "");
1803
+ this.maxOutputTokens = options.maxOutputTokens;
1804
+ this.reasoningEffort = options.reasoningEffort;
1805
+ this.fetchImplementation = options.fetch ?? globalThis.fetch;
1806
+ }
1807
+ async *stream(request, options) {
1808
+ if (this.dialect.supportsResponseFormat)
1809
+ assertModelResponseFormat(request);
1810
+ else if (request.responseFormat !== void 0)
1811
+ throw new TypeError(`${this.dialect.provider} adapter does not support responseFormat`);
1812
+ yield* executeRecordedRequest2({
1813
+ version: 1,
1814
+ adapter: this.dialect.adapter,
1815
+ purpose: "generation",
1816
+ endpoint: requestEndpoint2(`${this.baseURL}/chat/completions`),
1817
+ request,
1818
+ body: this.createRequest(request)
1819
+ }, options.recordRequest, options.signal, (body) => this.execute(body, request, options));
1820
+ }
1821
+ async *execute(body, request, options) {
1822
+ const response = await this.fetchImplementation(`${this.baseURL}/chat/completions`, {
1823
+ method: "POST",
1824
+ headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
1825
+ body,
1826
+ signal: options.signal
1827
+ });
1828
+ if (!response.ok)
1829
+ throw await this.createApiError(response);
1830
+ const { provider, errorCodePrefix } = this.dialect;
1831
+ for await (const event of streamOpenAICompatibleResponse(response, {
1832
+ signal: options.signal,
1833
+ providerName: provider,
1834
+ requireDone: this.dialect.requireDone,
1835
+ protocolError: /* @__PURE__ */ __name((message, errorOptions) => new OpenAICompatibleProtocolError(provider, errorCodePrefix, message, errorOptions), "protocolError"),
1836
+ finishReasonError: /* @__PURE__ */ __name((finishReason) => new OpenAICompatibleFinishReasonError(provider, errorCodePrefix, finishReason), "finishReasonError")
1837
+ })) {
1838
+ if (event.type === "response.completed" && this.dialect.supportsResponseFormat)
1839
+ validateStructuredModelResponse(event.message, request, event);
1840
+ yield event;
1841
+ }
1842
+ }
1843
+ createRequest(request) {
1844
+ const body = {
1845
+ model: this.model,
1846
+ messages: toOpenAICompatibleMessages(request.messages, { includeToolName: this.dialect.includeToolName }),
1847
+ stream: true
1848
+ };
1849
+ if (this.dialect.streamUsage)
1850
+ body.stream_options = { include_usage: true };
1851
+ if (request.tools.length > 0)
1852
+ body.tools = toOpenAICompatibleTools(request.tools);
1853
+ if (this.maxOutputTokens !== void 0)
1854
+ body[this.dialect.maxTokensField] = this.maxOutputTokens;
1855
+ if (this.reasoningEffort !== void 0)
1856
+ body.reasoning_effort = this.reasoningEffort;
1857
+ if (request.responseFormat !== void 0) {
1858
+ const format = request.responseFormat;
1859
+ body.response_format = format.type === "json" ? { type: "json_object" } : {
1860
+ type: "json_schema",
1861
+ json_schema: omitUndefined3({ name: format.name, schema: format.schema, strict: format.strict })
1862
+ };
1863
+ }
1864
+ this.dialect.extendRequest?.(body, request);
1865
+ return body;
1866
+ }
1867
+ async createApiError(response) {
1868
+ const text = await response.text();
1869
+ let message = text || `${this.dialect.provider} request failed with status ${response.status}`;
1870
+ let providerType;
1871
+ let providerCode;
1872
+ let parsed;
1873
+ try {
1874
+ parsed = JSON.parse(text);
1875
+ } catch (error) {
1876
+ if (!(error instanceof SyntaxError))
1877
+ throw error;
1878
+ }
1879
+ if (typeof parsed?.error?.message === "string")
1880
+ message = parsed.error.message;
1881
+ if (typeof parsed?.error?.type === "string")
1882
+ providerType = parsed.error.type;
1883
+ if (typeof parsed?.error?.code === "string" || typeof parsed?.error?.code === "number")
1884
+ providerCode = parsed.error.code;
1885
+ const retryAfterMs2 = parseRetryAfterMs(response.headers.get("retry-after"));
1886
+ return new OpenAICompatibleApiError(this.dialect.provider, this.dialect.errorCodePrefix, omitUndefined3({
1887
+ status: response.status,
1888
+ message,
1889
+ providerType,
1890
+ providerCode,
1891
+ retryAfterMs: retryAfterMs2
1892
+ }));
1893
+ }
1894
+ };
1895
+
1896
+ // packages/providers/dist/deepseek/index.js
1897
+ var DeepSeekModel = class extends OpenAICompatibleChatModel {
1898
+ static {
1899
+ __name(this, "DeepSeekModel");
1900
+ }
1901
+ constructor(options) {
1902
+ const { thinking, maxTokens, ...shared } = options;
1903
+ super(omitUndefined4({ ...shared, maxOutputTokens: maxTokens }), {
1904
+ provider: "DeepSeek",
1905
+ adapter: "deepseek-chat",
1906
+ errorCodePrefix: "DEEPSEEK",
1907
+ defaultBaseURL: "https://api.deepseek.com",
1908
+ maxTokensField: "max_tokens",
1909
+ streamUsage: true,
1910
+ includeToolName: false,
1911
+ requireDone: false,
1912
+ supportsResponseFormat: false,
1913
+ ...thinking === void 0 ? {} : {
1914
+ extendRequest: /* @__PURE__ */ __name((body) => {
1915
+ body.thinking = { type: thinking };
1916
+ }, "extendRequest")
1917
+ }
1918
+ });
1919
+ }
1920
+ };
1921
+
1922
+ // packages/providers/dist/kimi/index.js
1923
+ import { omitUndefined as omitUndefined5 } from "@sortedyuan/may/core";
1924
+ var KimiModel = class extends OpenAICompatibleChatModel {
1925
+ static {
1926
+ __name(this, "KimiModel");
1927
+ }
1928
+ constructor(options) {
1929
+ const { thinking, maxTokens, ...shared } = options;
1930
+ const configured = thinking === void 0 ? void 0 : { ...thinking };
1931
+ super(omitUndefined5({ ...shared, maxOutputTokens: maxTokens }), {
1932
+ provider: "Kimi",
1933
+ adapter: "kimi-chat",
1934
+ errorCodePrefix: "KIMI",
1935
+ defaultBaseURL: "https://api.moonshot.ai/v1",
1936
+ maxTokensField: "max_completion_tokens",
1937
+ streamUsage: true,
1938
+ includeToolName: true,
1939
+ requireDone: true,
1940
+ supportsResponseFormat: false,
1941
+ ...configured === void 0 ? {} : {
1942
+ extendRequest: /* @__PURE__ */ __name((body) => {
1943
+ body.thinking = { ...configured };
1944
+ }, "extendRequest")
1945
+ }
1946
+ });
1947
+ }
1948
+ };
1949
+
1950
+ // packages/providers/dist/openai/errors.js
1951
+ import { omitUndefined as omitUndefined6 } from "@sortedyuan/may/core";
1952
+ var OpenAIResponsesError = class extends Error {
1953
+ static {
1954
+ __name(this, "OpenAIResponsesError");
1955
+ }
1956
+ status;
1957
+ providerType;
1958
+ providerCode;
1959
+ requestId;
1960
+ retryAfterMs;
1961
+ constructor(message, options = {}) {
1962
+ super(message, omitUndefined6({ cause: options.cause }));
1963
+ this.name = "OpenAIResponsesError";
1964
+ this.status = options.status;
1965
+ this.providerType = options.providerType;
1966
+ this.providerCode = options.providerCode;
1967
+ this.requestId = options.requestId;
1968
+ this.retryAfterMs = options.retryAfterMs;
1969
+ }
1970
+ };
1971
+ var OpenAIResponsesProtocolError = class extends OpenAIResponsesError {
1972
+ static {
1973
+ __name(this, "OpenAIResponsesProtocolError");
1974
+ }
1975
+ constructor(message, options = {}) {
1976
+ super(message, omitUndefined6({ cause: options.cause }));
1977
+ this.name = "OpenAIResponsesProtocolError";
1978
+ }
1979
+ };
1980
+
1981
+ // packages/providers/dist/openai/openai-responses-model.js
1982
+ import { executeRecordedRequest as executeRecordedRequest3, executeRecordedOperation, requestEndpoint as requestEndpoint3 } from "@sortedyuan/may/core";
1983
+ import { assertModelResponseFormat as assertModelResponseFormat2, omitUndefined as omitUndefined9, validateStructuredModelResponse as validateStructuredModelResponse2 } from "@sortedyuan/may/core";
1984
+
1985
+ // packages/providers/dist/openai/convert.js
1986
+ import { UnsupportedContentError as UnsupportedContentError3, omitUndefined as omitUndefined7 } from "@sortedyuan/may/core";
1987
+
1988
+ // packages/providers/dist/openai/protocol.js
1989
+ var OPENAI_RESPONSES_MODEL_STATE_TYPE = "openai.responses.output.v1";
1990
+
1991
+ // packages/providers/dist/openai/convert.js
1992
+ function toOpenAIResponsesRequestParts(messages, baseInstructions) {
1993
+ const instructions = [];
1994
+ if (baseInstructions?.trim())
1995
+ instructions.push(baseInstructions);
1996
+ const input = [];
1997
+ for (const message of messages) {
1998
+ if (message.role === "system") {
1999
+ const text2 = visibleText(message.content);
2000
+ if (text2 !== "")
2001
+ instructions.push(text2);
2002
+ continue;
2003
+ }
2004
+ if (message.role === "user") {
2005
+ input.push({
2006
+ role: "user",
2007
+ content: toInputContent(message.content, "user")
2008
+ });
2009
+ continue;
2010
+ }
2011
+ if (message.role === "tool") {
2012
+ input.push({
2013
+ type: "function_call_output",
2014
+ call_id: message.toolCallId,
2015
+ output: hasMedia2(message.content) ? toInputContent(message.content, "tool") : visibleText(message.content, "tool")
2016
+ });
2017
+ continue;
2018
+ }
2019
+ const native = nativeItems(message.modelState);
2020
+ if (native !== void 0) {
2021
+ input.push(...native);
2022
+ continue;
2023
+ }
2024
+ const text = visibleText(message.content, "assistant");
2025
+ if (text !== "") {
2026
+ input.push({
2027
+ type: "message",
2028
+ role: "assistant",
2029
+ status: "completed",
2030
+ content: [{ type: "output_text", text, annotations: [] }]
2031
+ });
2032
+ }
2033
+ for (const call of message.toolCalls ?? []) {
2034
+ input.push({
2035
+ type: "function_call",
2036
+ call_id: call.id,
2037
+ name: call.name,
2038
+ arguments: serializeJson3(call.input),
2039
+ status: "completed"
2040
+ });
2041
+ }
2042
+ }
2043
+ return {
2044
+ input,
2045
+ ...instructions.length === 0 ? {} : { instructions: instructions.join("\n\n") }
2046
+ };
2047
+ }
2048
+ __name(toOpenAIResponsesRequestParts, "toOpenAIResponsesRequestParts");
2049
+ function toOpenAIResponsesTools(tools) {
2050
+ return tools.map((tool) => ({
2051
+ type: "function",
2052
+ name: tool.name,
2053
+ description: tool.description,
2054
+ parameters: tool.inputSchema,
2055
+ strict: false
2056
+ }));
2057
+ }
2058
+ __name(toOpenAIResponsesTools, "toOpenAIResponsesTools");
2059
+ function nativeItems(state) {
2060
+ if (state?.type !== OPENAI_RESPONSES_MODEL_STATE_TYPE)
2061
+ return void 0;
2062
+ if (!isRecord3(state.data) || !Array.isArray(state.data.items)) {
2063
+ throw new OpenAIResponsesProtocolError("OpenAI Responses model state is malformed");
2064
+ }
2065
+ return [...state.data.items];
2066
+ }
2067
+ __name(nativeItems, "nativeItems");
2068
+ function toInputContent(content, role) {
2069
+ return content.flatMap((part) => {
2070
+ if (part.type === "reasoning")
2071
+ return [];
2072
+ if (part.type === "text") {
2073
+ return [{ type: "input_text", text: part.text }];
2074
+ }
2075
+ if (part.type === "json") {
2076
+ return [{ type: "input_text", text: serializeJson3(part.value) }];
2077
+ }
2078
+ if (part.type === "image") {
2079
+ const source = toOpenAIImageSource(part.source);
2080
+ return [
2081
+ omitUndefined7({
2082
+ type: "input_image",
2083
+ ...source,
2084
+ detail: part.detail
2085
+ })
2086
+ ];
2087
+ }
2088
+ if (part.type === "file") {
2089
+ return [{ type: "input_file", ...toOpenAIFileSource(part.source, part.name) }];
2090
+ }
2091
+ throw new UnsupportedContentError3("OpenAI Responses adapter", part.type, role);
2092
+ });
2093
+ }
2094
+ __name(toInputContent, "toInputContent");
2095
+ function visibleText(content, role = "system") {
2096
+ return content.filter((part) => part.type !== "reasoning").map((part) => {
2097
+ if (part.type === "text")
2098
+ return part.text;
2099
+ if (part.type === "json")
2100
+ return serializeJson3(part.value);
2101
+ throw new UnsupportedContentError3("OpenAI Responses adapter", part.type, role);
2102
+ }).join("\n");
2103
+ }
2104
+ __name(visibleText, "visibleText");
2105
+ function hasMedia2(content) {
2106
+ return content.some((part) => part.type === "image" || part.type === "file");
2107
+ }
2108
+ __name(hasMedia2, "hasMedia");
2109
+ function toOpenAIImageSource(source) {
2110
+ if (source.type === "url")
2111
+ return { image_url: source.url };
2112
+ if (source.type === "file")
2113
+ return { file_id: source.fileId };
2114
+ return {
2115
+ image_url: `data:${source.mediaType};base64,${source.data}`
2116
+ };
2117
+ }
2118
+ __name(toOpenAIImageSource, "toOpenAIImageSource");
2119
+ function toOpenAIFileSource(source, name) {
2120
+ if (source.type === "url")
2121
+ return { file_url: source.url };
2122
+ if (source.type === "file")
2123
+ return { file_id: source.fileId };
2124
+ return {
2125
+ filename: name ?? "file",
2126
+ file_data: `data:${source.mediaType};base64,${source.data}`
2127
+ };
2128
+ }
2129
+ __name(toOpenAIFileSource, "toOpenAIFileSource");
2130
+ function serializeJson3(value) {
2131
+ const serialized = JSON.stringify(value);
2132
+ return serialized === void 0 ? "null" : serialized;
2133
+ }
2134
+ __name(serializeJson3, "serializeJson");
2135
+ function isRecord3(value) {
2136
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2137
+ }
2138
+ __name(isRecord3, "isRecord");
2139
+
2140
+ // packages/providers/dist/openai/stream.js
2141
+ import { omitUndefined as omitUndefined8 } from "@sortedyuan/may/core";
2142
+ async function* streamOpenAIResponse(response, signal) {
2143
+ let completed;
2144
+ for await (const data of readSseData(response, signal, (message, options) => new OpenAIResponsesProtocolError(message, options), "OpenAI Responses")) {
2145
+ if (data === "[DONE]")
2146
+ continue;
2147
+ const event = parseJson(data, "stream event");
2148
+ const type = requireString2(event.type, "stream event.type");
2149
+ if (type === "response.output_text.delta") {
2150
+ const delta = requireString2(event.delta, `${type}.delta`);
2151
+ if (delta !== "")
2152
+ yield { type: "text.delta", delta };
2153
+ continue;
2154
+ }
2155
+ if (type === "response.refusal.delta") {
2156
+ const delta = requireString2(event.delta, `${type}.delta`);
2157
+ if (delta !== "")
2158
+ yield { type: "text.delta", delta };
2159
+ continue;
2160
+ }
2161
+ if (type === "response.reasoning_summary_text.delta") {
2162
+ const delta = requireString2(event.delta, `${type}.delta`);
2163
+ if (delta !== "")
2164
+ yield { type: "reasoning.delta", delta };
2165
+ continue;
2166
+ }
2167
+ if (type === "response.completed") {
2168
+ if (completed !== void 0) {
2169
+ throw new OpenAIResponsesProtocolError("OpenAI Responses emitted more than one response.completed event");
2170
+ }
2171
+ completed = event.response;
2172
+ continue;
2173
+ }
2174
+ if (type === "response.failed" || type === "response.incomplete") {
2175
+ throw responseFailure(event.response, type);
2176
+ }
2177
+ if (type === "error")
2178
+ throw streamError(event);
2179
+ }
2180
+ if (completed === void 0) {
2181
+ throw new OpenAIResponsesProtocolError("OpenAI Responses stream ended without response.completed");
2182
+ }
2183
+ const parsed = parseCompletedOpenAIResponse(completed);
2184
+ yield omitUndefined8({ type: "response.completed", message: parsed.message, usage: parsed.usage });
2185
+ }
2186
+ __name(streamOpenAIResponse, "streamOpenAIResponse");
2187
+ function parseCompletedOpenAIResponse(value) {
2188
+ const response = requireRecord2(value, "response.completed.response");
2189
+ const output = requireArray(response.output, "response.output");
2190
+ const content = [];
2191
+ const toolCalls = [];
2192
+ for (const raw of output) {
2193
+ const item = requireRecord2(raw, "response.output item");
2194
+ const type = requireString2(item.type, "response.output item.type");
2195
+ if (type === "image_generation_call" && item.result != null) {
2196
+ const format = item.output_format ?? "png";
2197
+ if (format !== "png" && format !== "jpeg" && format !== "webp")
2198
+ throw new OpenAIResponsesProtocolError("Unsupported generated image format");
2199
+ const data = requireString2(item.result, "image_generation_call.result");
2200
+ if (data === "")
2201
+ throw new OpenAIResponsesProtocolError("Generated image is empty");
2202
+ content.push({ type: "image", source: { type: "base64", mediaType: `image/${format}`, data } });
2203
+ continue;
2204
+ }
2205
+ if (type === "reasoning") {
2206
+ for (const rawSummary of optionalArray(item.summary) ?? []) {
2207
+ const summary = requireRecord2(rawSummary, "reasoning summary");
2208
+ if (summary.type === "summary_text") {
2209
+ const text = requireString2(summary.text, "reasoning summary.text");
2210
+ if (text !== "")
2211
+ content.push({ type: "reasoning", text });
2212
+ }
2213
+ }
2214
+ continue;
2215
+ }
2216
+ if (type === "message") {
2217
+ if (item.role !== "assistant")
2218
+ continue;
2219
+ for (const rawPart of requireArray(item.content, "message.content")) {
2220
+ const part = requireRecord2(rawPart, "message content part");
2221
+ if (part.type === "output_text") {
2222
+ const text = requireString2(part.text, "output_text.text");
2223
+ if (text !== "")
2224
+ content.push({ type: "text", text });
2225
+ }
2226
+ if (part.type === "refusal") {
2227
+ const refusal = requireString2(part.refusal, "refusal.refusal");
2228
+ if (refusal !== "")
2229
+ content.push({ type: "text", text: refusal });
2230
+ }
2231
+ }
2232
+ continue;
2233
+ }
2234
+ if (type === "function_call") {
2235
+ const id = requireString2(item.call_id, "function_call.call_id");
2236
+ const name = requireString2(item.name, "function_call.name");
2237
+ const argumentsJson = requireString2(item.arguments, "function_call.arguments");
2238
+ toolCalls.push({ id, name, input: parseArguments(argumentsJson, id) });
2239
+ }
2240
+ }
2241
+ const message = {
2242
+ role: "assistant",
2243
+ content,
2244
+ ...toolCalls.length === 0 ? {} : { toolCalls },
2245
+ modelState: {
2246
+ type: OPENAI_RESPONSES_MODEL_STATE_TYPE,
2247
+ data: { items: output }
2248
+ }
2249
+ };
2250
+ const usage = parseUsage(response.usage);
2251
+ return omitUndefined8({ message, usage });
2252
+ }
2253
+ __name(parseCompletedOpenAIResponse, "parseCompletedOpenAIResponse");
2254
+ function openAIResponseContent(message) {
2255
+ if (message.content.some((part) => part.type === "image") || message.modelState?.type !== OPENAI_RESPONSES_MODEL_STATE_TYPE)
2256
+ return message.content;
2257
+ const state = requireRecord2(message.modelState.data, "modelState.data");
2258
+ const items = requireArray(state.items, "modelState.data.items");
2259
+ if (!items.some((item) => typeof item === "object" && item !== null && "type" in item && item.type === "image_generation_call"))
2260
+ return message.content;
2261
+ return parseCompletedOpenAIResponse({ output: items }).message.content;
2262
+ }
2263
+ __name(openAIResponseContent, "openAIResponseContent");
2264
+ function parseUsage(value) {
2265
+ if (value === void 0 || value === null)
2266
+ return void 0;
2267
+ const usage = requireRecord2(value, "response.usage");
2268
+ const inputTokens = optionalTokenCount2(usage.input_tokens, "input_tokens");
2269
+ const outputTokens = optionalTokenCount2(usage.output_tokens, "output_tokens");
2270
+ const totalTokens = optionalTokenCount2(usage.total_tokens, "total_tokens");
2271
+ const inputDetails = optionalRecord2(usage.input_tokens_details);
2272
+ const outputDetails = optionalRecord2(usage.output_tokens_details);
2273
+ const cachedReadTokens = optionalTokenCount2(inputDetails?.cached_tokens, "input_tokens_details.cached_tokens");
2274
+ const reasoningTokens = optionalTokenCount2(outputDetails?.reasoning_tokens, "output_tokens_details.reasoning_tokens");
2275
+ if (inputTokens === void 0 && outputTokens === void 0 && totalTokens === void 0 && cachedReadTokens === void 0 && reasoningTokens === void 0) {
2276
+ return void 0;
2277
+ }
2278
+ return omitUndefined8({
2279
+ inputTokens,
2280
+ outputTokens,
2281
+ totalTokens,
2282
+ cachedReadTokens,
2283
+ reasoningTokens,
2284
+ ...cachedReadTokens === void 0 && reasoningTokens === void 0 ? {} : {
2285
+ tokenRelations: {
2286
+ ...cachedReadTokens === void 0 ? {} : { cachedRead: "input" },
2287
+ ...reasoningTokens === void 0 ? {} : { reasoning: "output" }
2288
+ }
2289
+ },
2290
+ ...inputTokens === void 0 || outputTokens === void 0 ? { completeness: { status: "partial", reason: "provider-token-components-missing" } } : {}
2291
+ });
2292
+ }
2293
+ __name(parseUsage, "parseUsage");
2294
+ function parseArguments(value, callId) {
2295
+ try {
2296
+ return JSON.parse(value === "" ? "{}" : value);
2297
+ } catch (error) {
2298
+ throw new OpenAIResponsesProtocolError(`OpenAI Responses function call "${callId}" has invalid arguments JSON`, {
2299
+ cause: error
2300
+ });
2301
+ }
2302
+ }
2303
+ __name(parseArguments, "parseArguments");
2304
+ function responseFailure(value, type) {
2305
+ const response = requireRecord2(value, type);
2306
+ const error = optionalRecord2(response.error);
2307
+ const details = optionalRecord2(response.incomplete_details);
2308
+ const message = typeof error?.message === "string" ? error.message : typeof details?.reason === "string" ? details.reason : `OpenAI Responses emitted ${type}`;
2309
+ return new OpenAIResponsesError(message, {
2310
+ ...typeof error?.code === "string" ? { providerType: error.code } : {}
2311
+ });
2312
+ }
2313
+ __name(responseFailure, "responseFailure");
2314
+ function streamError(event) {
2315
+ const error = optionalRecord2(event.error) ?? event;
2316
+ return new OpenAIResponsesError(typeof error.message === "string" ? error.message : "OpenAI Responses stream error", {
2317
+ ...typeof error.code === "string" ? { providerType: error.code } : typeof error.type === "string" ? { providerType: error.type } : {},
2318
+ ...typeof event.request_id === "string" ? { requestId: event.request_id } : {}
2319
+ });
2320
+ }
2321
+ __name(streamError, "streamError");
2322
+ function parseJson(value, field) {
2323
+ try {
2324
+ return requireRecord2(JSON.parse(value), field);
2325
+ } catch (error) {
2326
+ if (error instanceof OpenAIResponsesProtocolError)
2327
+ throw error;
2328
+ throw new OpenAIResponsesProtocolError(`OpenAI Responses emitted invalid JSON for ${field}`, { cause: error });
2329
+ }
2330
+ }
2331
+ __name(parseJson, "parseJson");
2332
+ function optionalTokenCount2(value, field) {
2333
+ if (value === void 0)
2334
+ return void 0;
2335
+ if (!Number.isSafeInteger(value) || value < 0) {
2336
+ throw new OpenAIResponsesProtocolError(`response.usage.${field} is invalid`);
2337
+ }
2338
+ return value;
2339
+ }
2340
+ __name(optionalTokenCount2, "optionalTokenCount");
2341
+ function requireRecord2(value, field) {
2342
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2343
+ throw new OpenAIResponsesProtocolError(`${field} must be an object`);
2344
+ }
2345
+ return value;
2346
+ }
2347
+ __name(requireRecord2, "requireRecord");
2348
+ function optionalRecord2(value) {
2349
+ return value === void 0 || value === null ? void 0 : requireRecord2(value, "value");
2350
+ }
2351
+ __name(optionalRecord2, "optionalRecord");
2352
+ function requireArray(value, field) {
2353
+ if (!Array.isArray(value)) {
2354
+ throw new OpenAIResponsesProtocolError(`${field} must be an array`);
2355
+ }
2356
+ return value;
2357
+ }
2358
+ __name(requireArray, "requireArray");
2359
+ function optionalArray(value) {
2360
+ return value === void 0 ? void 0 : requireArray(value, "value");
2361
+ }
2362
+ __name(optionalArray, "optionalArray");
2363
+ function requireString2(value, field) {
2364
+ if (typeof value !== "string") {
2365
+ throw new OpenAIResponsesProtocolError(`${field} must be a string`);
2366
+ }
2367
+ return value;
2368
+ }
2369
+ __name(requireString2, "requireString");
2370
+
2371
+ // packages/providers/dist/openai/openai-responses-model.js
2372
+ var OpenAIResponsesModel = class {
2373
+ static {
2374
+ __name(this, "OpenAIResponsesModel");
2375
+ }
2376
+ supportsRequestRecording = true;
2377
+ contextCompactor;
2378
+ apiKey;
2379
+ model;
2380
+ baseURL;
2381
+ maxOutputTokens;
2382
+ reasoningEffort;
2383
+ reasoningSummary;
2384
+ serverCompactThreshold;
2385
+ store;
2386
+ fetchImplementation;
2387
+ constructor(options) {
2388
+ if (options.apiKey.trim() === "")
2389
+ throw new TypeError("apiKey must not be empty");
2390
+ if (options.model.trim() === "")
2391
+ throw new TypeError("model must not be empty");
2392
+ validateOptionalPositiveInteger(options.maxOutputTokens, "maxOutputTokens");
2393
+ validateOptionalPositiveInteger(options.serverCompactThreshold, "serverCompactThreshold");
2394
+ this.apiKey = options.apiKey;
2395
+ this.model = options.model;
2396
+ this.baseURL = (options.baseURL ?? "https://api.openai.com/v1").replace(/\/+$/u, "");
2397
+ this.maxOutputTokens = options.maxOutputTokens;
2398
+ this.reasoningEffort = options.reasoningEffort;
2399
+ this.reasoningSummary = options.reasoningSummary;
2400
+ this.serverCompactThreshold = options.serverCompactThreshold;
2401
+ this.store = options.store ?? false;
2402
+ this.fetchImplementation = options.fetch ?? globalThis.fetch;
2403
+ this.contextCompactor = {
2404
+ name: "openai-responses-compact",
2405
+ compact: /* @__PURE__ */ __name((snapshot, compactOptions) => this.compact(snapshot, compactOptions.signal, compactOptions.recordRequest), "compact")
2406
+ };
2407
+ }
2408
+ async *stream(request, options) {
2409
+ assertModelResponseFormat2(request);
2410
+ const parts = toOpenAIResponsesRequestParts(request.messages);
2411
+ const body = {
2412
+ model: this.model,
2413
+ input: parts.input,
2414
+ stream: true,
2415
+ store: this.store,
2416
+ include: ["reasoning.encrypted_content"]
2417
+ };
2418
+ if (parts.instructions !== void 0)
2419
+ body.instructions = parts.instructions;
2420
+ if (request.tools.length > 0)
2421
+ body.tools = toOpenAIResponsesTools(request.tools);
2422
+ if (request.responseFormat !== void 0) {
2423
+ const format = request.responseFormat;
2424
+ body.text = {
2425
+ format: format.type === "json" ? { type: "json_object" } : omitUndefined9({ type: "json_schema", name: format.name, schema: format.schema, strict: format.strict })
2426
+ };
2427
+ }
2428
+ if (this.maxOutputTokens !== void 0) {
2429
+ body.max_output_tokens = this.maxOutputTokens;
2430
+ }
2431
+ const reasoning = this.reasoningConfig();
2432
+ if (reasoning !== void 0)
2433
+ body.reasoning = reasoning;
2434
+ if (this.serverCompactThreshold !== void 0) {
2435
+ body.context_management = [
2436
+ {
2437
+ type: "compaction",
2438
+ compact_threshold: this.serverCompactThreshold
2439
+ }
2440
+ ];
2441
+ }
2442
+ yield* executeRecordedRequest3({
2443
+ version: 1,
2444
+ adapter: "openai-responses",
2445
+ purpose: "generation",
2446
+ endpoint: requestEndpoint3(`${this.baseURL}/responses`),
2447
+ request,
2448
+ body
2449
+ }, options.recordRequest, options.signal, (body2) => this.execute(body2, request, options));
2450
+ }
2451
+ async *execute(body, request, options) {
2452
+ const response = await this.fetch("/responses", body, options.signal);
2453
+ for await (const event of streamOpenAIResponse(response, options.signal)) {
2454
+ if (event.type === "response.completed")
2455
+ validateStructuredModelResponse2(event.message, request, event);
2456
+ yield event;
2457
+ }
2458
+ }
2459
+ async compact(snapshot, signal, recorder) {
2460
+ const effectiveSignal = signal ?? new AbortController().signal;
2461
+ const parts = toOpenAIResponsesRequestParts(snapshot.messages, snapshot.instructions);
2462
+ const body = {
2463
+ model: this.model,
2464
+ input: parts.input
2465
+ };
2466
+ if (parts.instructions !== void 0)
2467
+ body.instructions = parts.instructions;
2468
+ const request = {
2469
+ messages: snapshot.instructions === void 0 ? snapshot.messages : [{ role: "system", content: [{ type: "text", text: snapshot.instructions }] }, ...snapshot.messages],
2470
+ tools: []
2471
+ };
2472
+ return executeRecordedOperation({
2473
+ version: 1,
2474
+ adapter: "openai-responses",
2475
+ purpose: "compaction",
2476
+ endpoint: requestEndpoint3(`${this.baseURL}/responses/compact`),
2477
+ request,
2478
+ body
2479
+ }, recorder, effectiveSignal, (serialized) => this.executeCompact(serialized, effectiveSignal));
2480
+ }
2481
+ async executeCompact(body, effectiveSignal) {
2482
+ const response = await this.fetch("/responses/compact", body, effectiveSignal);
2483
+ const value = await response.json().catch((error) => {
2484
+ throw new OpenAIResponsesProtocolError("OpenAI Responses compact returned invalid JSON", { cause: error });
2485
+ });
2486
+ const compacted = requireRecord3(value, "compacted response");
2487
+ if (compacted.object !== "response.compaction") {
2488
+ throw new OpenAIResponsesProtocolError("OpenAI Responses compact returned an unexpected object");
2489
+ }
2490
+ if (!Array.isArray(compacted.output)) {
2491
+ throw new OpenAIResponsesProtocolError("OpenAI Responses compact output must be an array");
2492
+ }
2493
+ if (!compacted.output.some((item) => typeof item === "object" && item !== null && "type" in item && item.type === "compaction")) {
2494
+ throw new OpenAIResponsesProtocolError("OpenAI Responses compact output has no compaction item");
2495
+ }
2496
+ const usage = parseUsage(compacted.usage);
2497
+ const messages = [
2498
+ {
2499
+ role: "assistant",
2500
+ content: [],
2501
+ modelState: {
2502
+ type: OPENAI_RESPONSES_MODEL_STATE_TYPE,
2503
+ data: { items: compacted.output }
2504
+ }
2505
+ }
2506
+ ];
2507
+ return omitUndefined9({
2508
+ messages,
2509
+ // 压缩请求本身就是一次 provider 调用,它的 usage 一并上报给计账方。
2510
+ usage,
2511
+ effectiveTokens: usage?.outputTokens
2512
+ });
2513
+ }
2514
+ reasoningConfig() {
2515
+ if (this.reasoningEffort === void 0 && this.reasoningSummary === void 0) {
2516
+ return void 0;
2517
+ }
2518
+ return omitUndefined9({
2519
+ effort: this.reasoningEffort,
2520
+ generate_summary: this.reasoningSummary
2521
+ });
2522
+ }
2523
+ async fetch(path, body, signal) {
2524
+ const response = await this.fetchImplementation(`${this.baseURL}${path}`, {
2525
+ method: "POST",
2526
+ headers: {
2527
+ authorization: `Bearer ${this.apiKey}`,
2528
+ "content-type": "application/json"
2529
+ },
2530
+ body: typeof body === "string" ? body : JSON.stringify(body),
2531
+ signal
2532
+ });
2533
+ if (!response.ok)
2534
+ throw await createApiError2(response);
2535
+ return response;
2536
+ }
2537
+ };
2538
+ async function createApiError2(response) {
2539
+ const text = await response.text();
2540
+ let message = text || `OpenAI request failed with status ${response.status}`;
2541
+ let providerType;
2542
+ let providerCode;
2543
+ let requestId = response.headers.get("x-request-id") ?? void 0;
2544
+ try {
2545
+ const body = requireRecord3(JSON.parse(text), "error response");
2546
+ const error = requireRecord3(body.error, "error response.error");
2547
+ if (typeof error.message === "string")
2548
+ message = error.message;
2549
+ if (typeof error.type === "string")
2550
+ providerType = error.type;
2551
+ if (typeof error.code === "string")
2552
+ providerCode = error.code;
2553
+ if (typeof body.request_id === "string")
2554
+ requestId = body.request_id;
2555
+ } catch {
2556
+ }
2557
+ const retryAfterMs2 = parseRetryAfterMs(response.headers.get("retry-after"));
2558
+ return new OpenAIResponsesError(message, omitUndefined9({
2559
+ status: response.status,
2560
+ providerType,
2561
+ providerCode,
2562
+ requestId,
2563
+ retryAfterMs: retryAfterMs2
2564
+ }));
2565
+ }
2566
+ __name(createApiError2, "createApiError");
2567
+ function requireRecord3(value, field) {
2568
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2569
+ throw new OpenAIResponsesProtocolError(`${field} must be an object`);
2570
+ }
2571
+ return value;
2572
+ }
2573
+ __name(requireRecord3, "requireRecord");
2574
+ function validateOptionalPositiveInteger(value, name) {
2575
+ if (value !== void 0 && (!Number.isSafeInteger(value) || value < 1)) {
2576
+ throw new RangeError(`${name} must be a positive safe integer`);
2577
+ }
2578
+ }
2579
+ __name(validateOptionalPositiveInteger, "validateOptionalPositiveInteger");
2580
+
2581
+ // packages/providers/dist/openai-compatible/openai-chat-completions-model.js
2582
+ var OpenAIChatCompletionsModel = class extends OpenAICompatibleChatModel {
2583
+ static {
2584
+ __name(this, "OpenAIChatCompletionsModel");
2585
+ }
2586
+ constructor(options) {
2587
+ const { store, ...shared } = options;
2588
+ super(shared, {
2589
+ provider: "OpenAI-compatible chat",
2590
+ adapter: "openai-chat-completions",
2591
+ errorCodePrefix: "OPENAI_CHAT_COMPLETIONS",
2592
+ defaultBaseURL: "https://api.openai.com/v1",
2593
+ maxTokensField: "max_completion_tokens",
2594
+ streamUsage: true,
2595
+ includeToolName: false,
2596
+ requireDone: true,
2597
+ supportsResponseFormat: true,
2598
+ ...store === void 0 ? {} : {
2599
+ extendRequest: /* @__PURE__ */ __name((body) => {
2600
+ body.store = store;
2601
+ }, "extendRequest")
2602
+ }
2603
+ });
2604
+ }
2605
+ };
2606
+
2607
+ // packages/providers/dist/zhipu/index.js
2608
+ import { omitUndefined as omitUndefined10 } from "@sortedyuan/may/core";
2609
+ var ZhipuModel = class extends OpenAICompatibleChatModel {
2610
+ static {
2611
+ __name(this, "ZhipuModel");
2612
+ }
2613
+ constructor(options) {
2614
+ const { thinking = "enabled", clearThinking = false, maxTokens, ...shared } = options;
2615
+ super(omitUndefined10({ ...shared, maxOutputTokens: maxTokens }), {
2616
+ provider: "Zhipu",
2617
+ adapter: "zhipu-chat",
2618
+ errorCodePrefix: "ZHIPU",
2619
+ defaultBaseURL: "https://open.bigmodel.cn/api/paas/v4",
2620
+ maxTokensField: "max_tokens",
2621
+ streamUsage: false,
2622
+ includeToolName: false,
2623
+ requireDone: false,
2624
+ supportsResponseFormat: false,
2625
+ extendRequest: /* @__PURE__ */ __name((body, request) => {
2626
+ body.thinking = thinking === "enabled" ? { type: thinking, clear_thinking: clearThinking } : { type: thinking };
2627
+ if (request.tools.length > 0)
2628
+ body.tool_stream = true;
2629
+ }, "extendRequest")
2630
+ });
2631
+ }
2632
+ };
2633
+
2634
+ // packages/providers/dist/builtins.js
2635
+ import { omitUndefined as omitUndefined15 } from "@sortedyuan/may/core";
2636
+
2637
+ // packages/providers/dist/gemini/gemini-model.js
2638
+ import { randomUUID } from "node:crypto";
2639
+ import { executeRecordedRequest as executeRecordedRequest4, omitUndefined as omitUndefined12, requestEndpoint as requestEndpoint4 } from "@sortedyuan/may/core";
2640
+ import { assertModelResponseFormat as assertModelResponseFormat3, validateStructuredModelResponse as validateStructuredModelResponse3 } from "@sortedyuan/may/core";
2641
+
2642
+ // packages/providers/dist/gemini/convert.js
2643
+ import { UnsupportedContentError as UnsupportedContentError4, omitUndefined as omitUndefined11 } from "@sortedyuan/may/core";
2644
+
2645
+ // packages/providers/dist/gemini/errors.js
2646
+ var GeminiProtocolError = class extends Error {
2647
+ static {
2648
+ __name(this, "GeminiProtocolError");
2649
+ }
2650
+ code = "GEMINI_PROTOCOL_ERROR";
2651
+ constructor(message, options) {
2652
+ super(message, options);
2653
+ this.name = "GeminiProtocolError";
2654
+ }
2655
+ };
2656
+ var GeminiApiError = class extends Error {
2657
+ static {
2658
+ __name(this, "GeminiApiError");
2659
+ }
2660
+ status;
2661
+ retryAfterMs;
2662
+ code = "GEMINI_API_ERROR";
2663
+ constructor(status, message, retryAfterMs2) {
2664
+ super(message);
2665
+ this.status = status;
2666
+ this.retryAfterMs = retryAfterMs2;
2667
+ this.name = "GeminiApiError";
2668
+ }
2669
+ };
2670
+ var GeminiFinishReasonError = class extends Error {
2671
+ static {
2672
+ __name(this, "GeminiFinishReasonError");
2673
+ }
2674
+ finishReason;
2675
+ code = "GEMINI_INCOMPLETE_RESPONSE";
2676
+ constructor(finishReason) {
2677
+ super(`Gemini stopped with finish reason "${finishReason}"`);
2678
+ this.finishReason = finishReason;
2679
+ this.name = "GeminiFinishReasonError";
2680
+ }
2681
+ };
2682
+
2683
+ // packages/providers/dist/gemini/protocol.js
2684
+ var GEMINI_MODEL_STATE_TYPE = "google-gemini.content.v1";
2685
+
2686
+ // packages/providers/dist/gemini/convert.js
2687
+ function toGeminiRequestParts(messages) {
2688
+ const contents = [];
2689
+ const system = [];
2690
+ const nativeCalls = /* @__PURE__ */ new Map();
2691
+ for (const message of messages) {
2692
+ if (message.role === "system") {
2693
+ system.push(...message.content.map((part) => {
2694
+ if (part.type === "text")
2695
+ return { text: part.text };
2696
+ if (part.type === "json")
2697
+ return { text: JSON.stringify(part.value) };
2698
+ throw new UnsupportedContentError4("Google Gemini", part.type, "system");
2699
+ }));
2700
+ continue;
2701
+ }
2702
+ if (message.role === "tool") {
2703
+ const call = nativeCalls.get(message.toolCallId);
2704
+ if (call === void 0 || call.name !== message.name)
2705
+ throw new GeminiProtocolError(`Unmatched Gemini tool result "${message.toolCallId}"`);
2706
+ const response = {
2707
+ [message.isError ? "error" : "output"]: message.content.map((part) => {
2708
+ if (part.type === "text")
2709
+ return part.text;
2710
+ if (part.type === "json")
2711
+ return part.value;
2712
+ throw new UnsupportedContentError4("Google Gemini", part.type, "tool");
2713
+ })
2714
+ };
2715
+ appendContent(contents, "user", [
2716
+ { functionResponse: omitUndefined11({ name: call.name, id: call.id, response }) }
2717
+ ]);
2718
+ continue;
2719
+ }
2720
+ if (message.role === "assistant") {
2721
+ let parts;
2722
+ if (message.modelState?.type === GEMINI_MODEL_STATE_TYPE) {
2723
+ const state = message.modelState.data;
2724
+ if (!isRecord4(state) || !Array.isArray(state.parts) || !Array.isArray(state.toolCallIds))
2725
+ throw new GeminiProtocolError("Malformed Gemini model state");
2726
+ parts = structuredClone(state.parts);
2727
+ let index = 0;
2728
+ for (const part of parts) {
2729
+ if (!isRecord4(part))
2730
+ throw new GeminiProtocolError("Malformed Gemini model state part");
2731
+ if (part.functionCall === void 0)
2732
+ continue;
2733
+ if (!isRecord4(part.functionCall) || typeof part.functionCall.name !== "string" || part.functionCall.args !== void 0 && !isRecord4(part.functionCall.args))
2734
+ throw new GeminiProtocolError("Malformed Gemini model state functionCall");
2735
+ const functionCall = part.functionCall;
2736
+ const callId = state.toolCallIds[index++];
2737
+ const toolCall = message.toolCalls?.find((call) => call.id === callId);
2738
+ if (typeof callId !== "string" || toolCall === void 0 || toolCall.name !== functionCall.name || JSON.stringify(toolCall.input) !== JSON.stringify(functionCall.args ?? {}))
2739
+ throw new GeminiProtocolError("Gemini model state does not match tool calls");
2740
+ nativeCalls.set(callId, functionCall);
2741
+ }
2742
+ if (index !== state.toolCallIds.length || index !== (message.toolCalls?.length ?? 0))
2743
+ throw new GeminiProtocolError("Gemini model state has inconsistent tool calls");
2744
+ } else {
2745
+ parts = message.content.flatMap((part) => part.type === "reasoning" ? [] : [toGeminiPart(part, "assistant")]);
2746
+ for (const call of message.toolCalls ?? []) {
2747
+ if (!isRecord4(call.input))
2748
+ throw new GeminiProtocolError("Gemini tool input must be an object");
2749
+ const functionCall = { id: call.id, name: call.name, args: call.input };
2750
+ parts.push({ functionCall });
2751
+ nativeCalls.set(call.id, functionCall);
2752
+ }
2753
+ }
2754
+ appendContent(contents, "model", parts);
2755
+ continue;
2756
+ }
2757
+ appendContent(contents, "user", message.content.map((part) => toGeminiPart(part, "user")));
2758
+ }
2759
+ return { contents, ...system.length === 0 ? {} : { systemInstruction: { parts: system } } };
2760
+ }
2761
+ __name(toGeminiRequestParts, "toGeminiRequestParts");
2762
+ function appendContent(contents, role, parts) {
2763
+ if (parts.length === 0)
2764
+ return;
2765
+ const previous = contents.at(-1);
2766
+ if (previous?.role === role)
2767
+ previous.parts.push(...parts);
2768
+ else
2769
+ contents.push({ role, parts });
2770
+ }
2771
+ __name(appendContent, "appendContent");
2772
+ function toGeminiPart(part, role) {
2773
+ if (part.type === "text")
2774
+ return { text: part.text };
2775
+ if (part.type === "json")
2776
+ return { text: JSON.stringify(part.value) };
2777
+ if (part.type === "image" || part.type === "audio" || part.type === "file") {
2778
+ if (part.source.type === "base64")
2779
+ return { inlineData: { mimeType: part.source.mediaType, data: part.source.data } };
2780
+ if (part.source.type === "url")
2781
+ return { fileData: { fileUri: part.source.url } };
2782
+ }
2783
+ throw new UnsupportedContentError4("Google Gemini", part.type, role);
2784
+ }
2785
+ __name(toGeminiPart, "toGeminiPart");
2786
+ function convertGeminiUsage(metadata) {
2787
+ const input = tokenCount(metadata.promptTokenCount, "promptTokenCount");
2788
+ const candidates = tokenCount(metadata.candidatesTokenCount, "candidatesTokenCount");
2789
+ const reasoning = tokenCount(metadata.thoughtsTokenCount, "thoughtsTokenCount");
2790
+ const cached = tokenCount(metadata.cachedContentTokenCount, "cachedContentTokenCount");
2791
+ const total = tokenCount(metadata.totalTokenCount, "totalTokenCount");
2792
+ const toolPrompt = tokenCount(metadata.toolUsePromptTokenCount, "toolUsePromptTokenCount");
2793
+ const usage = { tokenRelations: { cachedRead: "input", reasoning: "output" } };
2794
+ if (input !== void 0)
2795
+ usage.inputTokens = input;
2796
+ if (candidates !== void 0 || reasoning !== void 0)
2797
+ usage.outputTokens = tokenCount((candidates ?? 0) + (reasoning ?? 0), "outputTokens");
2798
+ if (reasoning !== void 0)
2799
+ usage.reasoningTokens = reasoning;
2800
+ if (cached !== void 0)
2801
+ usage.cachedReadTokens = cached;
2802
+ if (total !== void 0)
2803
+ usage.totalTokens = total;
2804
+ if (toolPrompt !== void 0 && toolPrompt > 0)
2805
+ usage.items = [
2806
+ { id: "gemini.toolUsePromptTokenCount", quantity: toolPrompt, unit: "token", includedIn: "unknown" }
2807
+ ];
2808
+ if (input !== void 0 && cached !== void 0 && cached > input)
2809
+ throw new GeminiProtocolError("Gemini cachedContentTokenCount exceeds promptTokenCount");
2810
+ if (input === void 0 || usage.outputTokens === void 0 || (toolPrompt ?? 0) > 0)
2811
+ usage.completeness = {
2812
+ status: "partial",
2813
+ reason: "Gemini usage does not completely describe input and output tokens"
2814
+ };
2815
+ return usage;
2816
+ }
2817
+ __name(convertGeminiUsage, "convertGeminiUsage");
2818
+ function tokenCount(value, field) {
2819
+ if (value !== void 0 && (!Number.isSafeInteger(value) || value < 0))
2820
+ throw new GeminiProtocolError(`${field} must be a non-negative safe integer`);
2821
+ return value;
2822
+ }
2823
+ __name(tokenCount, "tokenCount");
2824
+ function isRecord4(value) {
2825
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2826
+ }
2827
+ __name(isRecord4, "isRecord");
2828
+
2829
+ // packages/providers/dist/gemini/gemini-model.js
2830
+ var GeminiModel = class {
2831
+ static {
2832
+ __name(this, "GeminiModel");
2833
+ }
2834
+ supportsRequestRecording = true;
2835
+ baseURL;
2836
+ fetchImplementation;
2837
+ options;
2838
+ constructor(options) {
2839
+ if (typeof options.apiKey !== "string" || options.apiKey.trim() === "")
2840
+ throw new TypeError("apiKey must not be empty");
2841
+ if (typeof options.model !== "string" || options.model.trim() === "")
2842
+ throw new TypeError("model must not be empty");
2843
+ if (options.maxOutputTokens !== void 0 && (!Number.isSafeInteger(options.maxOutputTokens) || options.maxOutputTokens < 1))
2844
+ throw new RangeError("maxOutputTokens must be a positive safe integer");
2845
+ if (options.thinkingBudget !== void 0 && (!Number.isSafeInteger(options.thinkingBudget) || options.thinkingBudget < -1))
2846
+ throw new RangeError("thinkingBudget must be an integer greater than or equal to -1");
2847
+ if (options.reasoningEffort !== void 0 && (typeof options.reasoningEffort !== "string" || options.reasoningEffort.trim() === ""))
2848
+ throw new TypeError("reasoningEffort must not be empty");
2849
+ if (options.reasoningEffort !== void 0 && options.thinkingBudget !== void 0)
2850
+ throw new TypeError("reasoningEffort and thinkingBudget are mutually exclusive");
2851
+ if (options.includeThoughts !== void 0 && typeof options.includeThoughts !== "boolean")
2852
+ throw new TypeError("includeThoughts must be a boolean");
2853
+ this.options = { ...options };
2854
+ this.baseURL = (options.baseURL ?? "https://generativelanguage.googleapis.com/v1beta").replace(/\/+$/u, "");
2855
+ const url = new URL(this.baseURL);
2856
+ if (!["https:", "http:"].includes(url.protocol) || url.search || url.hash || url.username || url.password)
2857
+ throw new TypeError("baseURL must be an HTTP URL without credentials, query, or fragment");
2858
+ this.fetchImplementation = options.fetch ?? globalThis.fetch;
2859
+ }
2860
+ async *stream(request, options) {
2861
+ assertModelResponseFormat3(request);
2862
+ const body = toGeminiRequestParts(request.messages);
2863
+ if (body.contents.length === 0)
2864
+ throw new GeminiProtocolError("Gemini requires non-empty contents");
2865
+ if (request.tools.length > 0)
2866
+ body.tools = [
2867
+ {
2868
+ functionDeclarations: request.tools.map((tool) => ({
2869
+ name: tool.name,
2870
+ description: tool.description,
2871
+ parametersJsonSchema: tool.inputSchema
2872
+ }))
2873
+ }
2874
+ ];
2875
+ const config = {};
2876
+ if (this.options.maxOutputTokens !== void 0)
2877
+ config.maxOutputTokens = this.options.maxOutputTokens;
2878
+ if (this.options.reasoningEffort !== void 0 || this.options.thinkingBudget !== void 0 || this.options.includeThoughts !== void 0) {
2879
+ config.thinkingConfig = omitUndefined12({
2880
+ thinkingLevel: this.options.reasoningEffort,
2881
+ thinkingBudget: this.options.thinkingBudget,
2882
+ includeThoughts: this.options.includeThoughts
2883
+ });
2884
+ }
2885
+ if (request.responseFormat !== void 0) {
2886
+ config.responseMimeType = "application/json";
2887
+ if (request.responseFormat.type === "jsonSchema")
2888
+ config.responseJsonSchema = request.responseFormat.schema;
2889
+ }
2890
+ if (Object.keys(config).length > 0)
2891
+ body.generationConfig = config;
2892
+ const model = this.options.model.replace(/^models\//u, "");
2893
+ yield* executeRecordedRequest4({
2894
+ version: 1,
2895
+ adapter: "gemini",
2896
+ purpose: "generation",
2897
+ endpoint: requestEndpoint4(`${this.baseURL}/models/${encodeURIComponent(model)}:streamGenerateContent`),
2898
+ request,
2899
+ body,
2900
+ protocol: { model, alt: "sse" }
2901
+ }, options.recordRequest, options.signal, (body2) => this.execute(body2, model, request, options));
2902
+ }
2903
+ async *execute(body, model, request, options) {
2904
+ const response = await this.fetchImplementation(`${this.baseURL}/models/${encodeURIComponent(model)}:streamGenerateContent?alt=sse`, {
2905
+ method: "POST",
2906
+ headers: {
2907
+ "x-goog-api-key": this.options.apiKey,
2908
+ "content-type": "application/json",
2909
+ accept: "text/event-stream"
2910
+ },
2911
+ body,
2912
+ signal: options.signal
2913
+ });
2914
+ if (!response.ok)
2915
+ throw new GeminiApiError(response.status, await response.text(), parseRetryAfterMs(response.headers.get("retry-after")));
2916
+ const message = { role: "assistant", content: [] };
2917
+ const parts = [];
2918
+ const toolCalls = [];
2919
+ let metadata;
2920
+ let finishReason;
2921
+ for await (const data of readSseData(response, options.signal, (message2, cause) => new GeminiProtocolError(message2, cause), "Google Gemini")) {
2922
+ if (data === "[DONE]")
2923
+ break;
2924
+ const chunk = JSON.parse(data);
2925
+ if (!isRecord4(chunk))
2926
+ throw new GeminiProtocolError("Gemini stream chunk must be an object");
2927
+ if (chunk.error !== void 0)
2928
+ throw new GeminiProtocolError(`Gemini stream error: ${describeError(chunk.error)}`);
2929
+ if (isRecord4(chunk.promptFeedback) && chunk.promptFeedback.blockReason !== void 0)
2930
+ throw new GeminiFinishReasonError(String(chunk.promptFeedback.blockReason));
2931
+ if (chunk.usageMetadata !== void 0) {
2932
+ if (!isRecord4(chunk.usageMetadata))
2933
+ throw new GeminiProtocolError("Gemini usageMetadata must be an object");
2934
+ metadata = { ...metadata, ...chunk.usageMetadata };
2935
+ convertGeminiUsage(metadata);
2936
+ }
2937
+ if (chunk.candidates === void 0)
2938
+ continue;
2939
+ if (!Array.isArray(chunk.candidates))
2940
+ throw new GeminiProtocolError("Gemini candidates must be an array");
2941
+ for (const candidate of chunk.candidates) {
2942
+ if (!isRecord4(candidate))
2943
+ throw new GeminiProtocolError("Gemini candidate must be an object");
2944
+ if (candidate.index !== void 0 && candidate.index !== 0)
2945
+ continue;
2946
+ if (candidate.finishReason !== void 0) {
2947
+ if (typeof candidate.finishReason !== "string")
2948
+ throw new GeminiProtocolError("Gemini finishReason must be a string");
2949
+ if (finishReason !== void 0 && finishReason !== candidate.finishReason)
2950
+ throw new GeminiProtocolError("Gemini emitted conflicting finish reasons");
2951
+ finishReason = candidate.finishReason;
2952
+ }
2953
+ if (candidate.content === void 0)
2954
+ continue;
2955
+ if (!isRecord4(candidate.content) || !Array.isArray(candidate.content.parts))
2956
+ throw new GeminiProtocolError("Gemini content.parts must be an array");
2957
+ for (const rawPart of candidate.content.parts) {
2958
+ if (!isRecord4(rawPart))
2959
+ throw new GeminiProtocolError("Gemini part must be an object");
2960
+ if (rawPart.thoughtSignature !== void 0 && typeof rawPart.thoughtSignature !== "string")
2961
+ throw new GeminiProtocolError("Gemini thoughtSignature must be a string");
2962
+ if (rawPart.thought !== void 0 && typeof rawPart.thought !== "boolean")
2963
+ throw new GeminiProtocolError("Gemini thought must be a boolean");
2964
+ const part = rawPart;
2965
+ parts.push(structuredClone(part));
2966
+ if (part.text !== void 0) {
2967
+ if (typeof part.text !== "string")
2968
+ throw new GeminiProtocolError("Gemini text must be a string");
2969
+ const type = part.thought ? "reasoning" : "text";
2970
+ message.content.push({ type, text: part.text });
2971
+ if (part.text !== "")
2972
+ yield { type: part.thought ? "reasoning.delta" : "text.delta", delta: part.text };
2973
+ } else if (part.functionCall !== void 0) {
2974
+ const call = part.functionCall;
2975
+ if (!isRecord4(call) || typeof call.name !== "string" || call.name.trim() === "" || call.args !== void 0 && !isRecord4(call.args) || call.id !== void 0 && (typeof call.id !== "string" || call.id === ""))
2976
+ throw new GeminiProtocolError("Malformed Gemini functionCall");
2977
+ const id = call.id ?? randomUUID();
2978
+ if (toolCalls.some((existing) => existing.id === id))
2979
+ throw new GeminiProtocolError("Gemini emitted duplicate function call IDs");
2980
+ toolCalls.push({ id, name: call.name, input: call.args ?? {} });
2981
+ } else if (part.inlineData !== void 0) {
2982
+ const media = part.inlineData;
2983
+ if (!isRecord4(media) || typeof media.mimeType !== "string" || typeof media.data !== "string")
2984
+ throw new GeminiProtocolError("Malformed Gemini inlineData");
2985
+ const type = media.mimeType.startsWith("image/") ? "image" : media.mimeType.startsWith("audio/") ? "audio" : "file";
2986
+ message.content.push({ type, source: { type: "base64", mediaType: media.mimeType, data: media.data } });
2987
+ } else if (part.thoughtSignature === void 0) {
2988
+ throw new GeminiProtocolError("Unsupported Gemini response part");
2989
+ }
2990
+ }
2991
+ }
2992
+ }
2993
+ options.signal.throwIfAborted();
2994
+ if (finishReason === void 0)
2995
+ throw new GeminiProtocolError("Gemini stream ended without finishReason");
2996
+ if (finishReason !== "STOP")
2997
+ throw new GeminiFinishReasonError(finishReason);
2998
+ if (parts.length === 0)
2999
+ throw new GeminiProtocolError("Gemini completed without content");
3000
+ if (toolCalls.length > 0)
3001
+ message.toolCalls = toolCalls;
3002
+ message.modelState = {
3003
+ type: GEMINI_MODEL_STATE_TYPE,
3004
+ data: { parts, toolCallIds: toolCalls.map((call) => call.id) }
3005
+ };
3006
+ const event = {
3007
+ type: "response.completed",
3008
+ message,
3009
+ ...metadata === void 0 ? {} : { usage: convertGeminiUsage(metadata) }
3010
+ };
3011
+ validateStructuredModelResponse3(message, request, event);
3012
+ yield event;
3013
+ }
3014
+ };
3015
+ function describeError(error) {
3016
+ if (isRecord4(error) && typeof error.message === "string")
3017
+ return error.message;
3018
+ if (typeof error === "string")
3019
+ return error;
3020
+ return "The server returned an error without a message";
3021
+ }
3022
+ __name(describeError, "describeError");
3023
+
3024
+ // packages/providers/dist/errors.js
3025
+ var ProviderAdapterRegistryError = class extends Error {
3026
+ static {
3027
+ __name(this, "ProviderAdapterRegistryError");
3028
+ }
3029
+ constructor(message, options) {
3030
+ super(message, options);
3031
+ this.name = "ProviderAdapterRegistryError";
3032
+ }
3033
+ };
3034
+ var ProviderConfigurationError = class extends ProviderAdapterRegistryError {
3035
+ static {
3036
+ __name(this, "ProviderConfigurationError");
3037
+ }
3038
+ constructor(message, options) {
3039
+ super(message, options);
3040
+ this.name = "ProviderConfigurationError";
3041
+ }
3042
+ };
3043
+
3044
+ // packages/providers/dist/options.js
3045
+ import { omitUndefined as omitUndefined13 } from "@sortedyuan/may/core";
3046
+ function providerField(selection, name) {
3047
+ return `providers.${selection.provider}.${name}`;
3048
+ }
3049
+ __name(providerField, "providerField");
3050
+ function tuningOption(selection, name) {
3051
+ return selection.options[name];
3052
+ }
3053
+ __name(tuningOption, "tuningOption");
3054
+ function modelOption(selection, name) {
3055
+ return Object.hasOwn(selection.options, name) ? selection.options[name] : void 0;
3056
+ }
3057
+ __name(modelOption, "modelOption");
3058
+ function optionField(selection, name) {
3059
+ return `models.${selection.profile}.options.${name}`;
3060
+ }
3061
+ __name(optionField, "optionField");
3062
+ function requiredString(value, field) {
3063
+ if (typeof value !== "string" || value.trim() === "") {
3064
+ throw new ProviderConfigurationError(`${field} must be a non-empty string`);
3065
+ }
3066
+ return value;
3067
+ }
3068
+ __name(requiredString, "requiredString");
3069
+ function optionalString2(value, field) {
3070
+ if (value === void 0)
3071
+ return void 0;
3072
+ return requiredString(value, field);
3073
+ }
3074
+ __name(optionalString2, "optionalString");
3075
+ function optionalEnum(value, field, allowed) {
3076
+ if (value === void 0)
3077
+ return void 0;
3078
+ if (typeof value !== "string" || !allowed.has(value)) {
3079
+ throw new ProviderConfigurationError(`${field} must be one of: ${[...allowed].join(", ")}`);
3080
+ }
3081
+ return value;
3082
+ }
3083
+ __name(optionalEnum, "optionalEnum");
3084
+ function optionalPositiveInteger(value, field) {
3085
+ if (value === void 0)
3086
+ return void 0;
3087
+ if (!Number.isSafeInteger(value) || value < 1) {
3088
+ throw new ProviderConfigurationError(`${field} must be a positive safe integer`);
3089
+ }
3090
+ return value;
3091
+ }
3092
+ __name(optionalPositiveInteger, "optionalPositiveInteger");
3093
+ function optionalBoolean(value, field) {
3094
+ if (value === void 0)
3095
+ return void 0;
3096
+ if (typeof value !== "boolean") {
3097
+ throw new ProviderConfigurationError(`${field} must be a boolean`);
3098
+ }
3099
+ return value;
3100
+ }
3101
+ __name(optionalBoolean, "optionalBoolean");
3102
+ function requireRecord4(value, field) {
3103
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3104
+ throw new ProviderConfigurationError(`${field} must be an object`);
3105
+ }
3106
+ return value;
3107
+ }
3108
+ __name(requireRecord4, "requireRecord");
3109
+ function attachModelLimits(model, limits, maxOutputTokens) {
3110
+ const effectiveLimits = mergeLimits(limits, maxOutputTokens);
3111
+ if (effectiveLimits === void 0)
3112
+ return model;
3113
+ return {
3114
+ limits: effectiveLimits,
3115
+ supportsRequestRecording: model.supportsRequestRecording === true,
3116
+ reportsAttempts: model.reportsAttempts,
3117
+ capabilityVersion: model.capabilityVersion,
3118
+ configuration: model.configuration,
3119
+ contextCompactor: model.contextCompactor,
3120
+ ...model.preflight === void 0 ? {} : {
3121
+ preflight: /* @__PURE__ */ __name((request, streamOptions) => model.preflight(request, streamOptions), "preflight")
3122
+ },
3123
+ stream: /* @__PURE__ */ __name((request, streamOptions) => model.stream(request, streamOptions), "stream")
3124
+ };
3125
+ }
3126
+ __name(attachModelLimits, "attachModelLimits");
3127
+ function mergeLimits(limits, maxOutputTokens) {
3128
+ if (limits === void 0 && maxOutputTokens === void 0)
3129
+ return void 0;
3130
+ const effectiveOutputTokens = maxOutputTokens ?? limits?.maxOutputTokens;
3131
+ return omitUndefined13({
3132
+ contextWindowTokens: limits?.contextWindowTokens,
3133
+ maxOutputTokens: effectiveOutputTokens
3134
+ });
3135
+ }
3136
+ __name(mergeLimits, "mergeLimits");
3137
+
3138
+ // packages/providers/dist/capability-validated-model.js
3139
+ import { ModelProtocolError, ModelResponseValidationError, assertModelResponseFormat as assertModelResponseFormat5, omitUndefined as omitUndefined14 } from "@sortedyuan/may/core";
3140
+
3141
+ // packages/providers/dist/validation.js
3142
+ import { assertModelResponseFormat as assertModelResponseFormat4, compileModelSchema, modelSchemaDialect } from "@sortedyuan/may/core";
3143
+ import { validateStructuredModelResponse as validateStructuredModelResponse4 } from "@sortedyuan/may/core";
3144
+ var ModelRequestValidationError = class extends TypeError {
3145
+ static {
3146
+ __name(this, "ModelRequestValidationError");
3147
+ }
3148
+ result;
3149
+ code = "MODEL_REQUEST_VALIDATION_FAILED";
3150
+ constructor(result) {
3151
+ super(result.issues.map((issue) => `${issue.field}: ${issue.message}`).join("; "));
3152
+ this.result = result;
3153
+ this.name = "ModelRequestValidationError";
3154
+ }
3155
+ };
3156
+ function validateModelRequest(request, capabilities, options = {}) {
3157
+ assertModelResponseFormat4(request);
3158
+ if (options.unknownPolicy !== void 0 && options.unknownPolicy !== "allow" && options.unknownPolicy !== "require-known")
3159
+ throw new TypeError("unknownPolicy must be allow or require-known");
3160
+ const issues = [];
3161
+ const report = /* @__PURE__ */ __name((field, capability, code, message) => issues.push({ field, capability, code, message }), "report");
3162
+ const values = /* @__PURE__ */ __name((key) => [capabilities.fields?.[key], ...Object.values(capabilities.layers ?? {}).map((layer) => layer[key])].filter((value) => value !== void 0), "values");
3163
+ const requireCapability = /* @__PURE__ */ __name((key, field) => {
3164
+ const candidates = values(key);
3165
+ if (candidates.some((value) => value.status === "unsupported"))
3166
+ report(field, key, "unsupported", `${key} is unsupported`);
3167
+ else if (capabilities.fields?.[key]?.status !== "known")
3168
+ report(field, key, "unknown", `${key} is unknown`);
3169
+ }, "requireCapability");
3170
+ const knownValues = /* @__PURE__ */ __name((key) => values(key).flatMap((value) => value.status === "known" ? [value.value] : []), "knownValues");
3171
+ const limit = /* @__PURE__ */ __name((key, amount, field) => {
3172
+ if (amount > 0 && values(key).some((value) => value.status === "unsupported"))
3173
+ report(field, key, "unsupported", `${key} is unsupported`);
3174
+ const limits = knownValues(key).filter((value) => typeof value === "number");
3175
+ if (limits.length > 0 && amount > Math.min(...limits))
3176
+ report(field, key, "limit", `${key} must not exceed ${Math.min(...limits)}`);
3177
+ }, "limit");
3178
+ let images = 0;
3179
+ let attachments = 0;
3180
+ request.messages.forEach((message, messageIndex) => message.content.forEach((part, partIndex) => {
3181
+ const field = `messages.${messageIndex}.content.${partIndex}`;
3182
+ if (part.type === "reasoning")
3183
+ return;
3184
+ if (part.type === "text" || part.type === "json") {
3185
+ requireCapability("input.text", field);
3186
+ return;
3187
+ }
3188
+ if (part.type === "resource") {
3189
+ requireCapability("input.resource", field);
3190
+ return;
3191
+ }
3192
+ requireCapability(`input.${part.type}`, field);
3193
+ attachments += 1;
3194
+ if (part.type === "image")
3195
+ images += 1;
3196
+ const sourceKey = `input.${part.type}.sources`;
3197
+ requireCapability(sourceKey, `${field}.source`);
3198
+ for (const allowed of knownValues(sourceKey)) {
3199
+ if (Array.isArray(allowed) && !allowed.includes(part.source.type))
3200
+ report(`${field}.source.type`, sourceKey, "unsupported", `${part.source.type} source is unsupported`);
3201
+ }
3202
+ const supplied = options.mediaMetadata?.(part, field);
3203
+ const bytes = part.source.type === "base64" ? Buffer.byteLength(part.source.data, "base64") : supplied?.bytes;
3204
+ const mediaType = part.source.type === "base64" ? part.source.mediaType : supplied?.mediaType;
3205
+ if (bytes !== void 0) {
3206
+ if (!Number.isSafeInteger(bytes) || bytes < 0)
3207
+ throw new TypeError(`${field} media bytes must be a non-negative safe integer`);
3208
+ limit("maxAttachmentBytes", bytes, field);
3209
+ } else if (knownValues("maxAttachmentBytes").length > 0)
3210
+ report(field, "maxAttachmentBytes", "unknown", "Attachment size is unknown");
3211
+ if (part.type === "file") {
3212
+ if (values("fileTypes").some((value) => value.status === "unsupported"))
3213
+ report(field, "fileTypes", "unsupported", "File media types are unsupported");
3214
+ for (const allowed of knownValues("fileTypes")) {
3215
+ if (!Array.isArray(allowed))
3216
+ continue;
3217
+ if (mediaType === void 0)
3218
+ report(field, "fileTypes", "unknown", "File media type is unknown");
3219
+ else if (!allowed.includes(mediaType))
3220
+ report(field, "fileTypes", "unsupported", "File media type is unsupported");
3221
+ }
3222
+ }
3223
+ }));
3224
+ limit("maxImages", images, "messages");
3225
+ limit("maxAttachments", attachments, "messages");
3226
+ if (request.tools.length > 0)
3227
+ requireCapability("tools", "tools");
3228
+ const parameters = options.parameters ?? {};
3229
+ if (Object.keys(parameters).length > 0)
3230
+ requireCapability("parameters", "parameters");
3231
+ const effort = parameters.reasoningEffort;
3232
+ const thinking = parameters.thinking;
3233
+ if (thinking !== void 0 && thinking !== "disabled" && !(typeof thinking === "object" && thinking !== null && "type" in thinking && thinking.type === "disabled")) {
3234
+ const mode = typeof thinking === "object" && thinking !== null && "type" in thinking && thinking.type === "adaptive" ? "adaptive" : typeof thinking === "object" && thinking !== null && "budgetTokens" in thinking ? "budget" : "thinking";
3235
+ requireCapability("reasoning.modes", "parameters.thinking");
3236
+ for (const modes of knownValues("reasoning.modes"))
3237
+ if (Array.isArray(modes) && !modes.includes(mode))
3238
+ report("parameters.thinking", "reasoning.modes", "unsupported", `${mode} reasoning mode is unsupported`);
3239
+ }
3240
+ if (parameters.reasoningSummary !== void 0) {
3241
+ requireCapability("reasoning.modes", "parameters.reasoningSummary");
3242
+ for (const modes of knownValues("reasoning.modes"))
3243
+ if (Array.isArray(modes) && !modes.includes("summary"))
3244
+ report("parameters.reasoningSummary", "reasoning.modes", "unsupported", "reasoning summary mode is unsupported");
3245
+ }
3246
+ if (effort !== void 0) {
3247
+ for (const modes of values("reasoning.modes")) {
3248
+ if (modes.status === "unsupported" || modes.status === "known" && Array.isArray(modes.value) && !modes.value.includes("effort"))
3249
+ report("parameters.reasoningEffort", "reasoning.modes", "unsupported", "effort reasoning mode is unsupported");
3250
+ }
3251
+ const reasoning = capabilities.reasoningEffort;
3252
+ if (reasoning.status === "unsupported")
3253
+ report("parameters.reasoningEffort", "reasoningEffort", "unsupported", "reasoning effort is unsupported");
3254
+ else if (reasoning.status === "unknown")
3255
+ report("parameters.reasoningEffort", "reasoningEffort", "unknown", "reasoning effort is unknown");
3256
+ else if (typeof effort !== "string" || !reasoning.efforts.includes(effort))
3257
+ report("parameters.reasoningEffort", "reasoningEffort", "parameter", `reasoningEffort must be one of ${reasoning.efforts.join(", ")}`);
3258
+ }
3259
+ for (const key of ["maxTokens", "maxOutputTokens"])
3260
+ if (parameters[key] !== void 0) {
3261
+ if (!Number.isSafeInteger(parameters[key]) || parameters[key] < 1)
3262
+ report(`parameters.${key}`, "maxOutputTokens", "parameter", "Output token limit must be a positive safe integer");
3263
+ else
3264
+ limit("maxOutputTokens", parameters[key], `parameters.${key}`);
3265
+ }
3266
+ if (options.estimatedInputTokens !== void 0) {
3267
+ if (!Number.isSafeInteger(options.estimatedInputTokens) || options.estimatedInputTokens < 0)
3268
+ throw new TypeError("estimatedInputTokens must be a non-negative safe integer");
3269
+ const outputTokens = parameters.maxOutputTokens ?? parameters.maxTokens;
3270
+ const reservedOutput = typeof outputTokens === "number" && Number.isSafeInteger(outputTokens) && outputTokens >= 0 ? outputTokens : 0;
3271
+ limit("contextWindowTokens", options.estimatedInputTokens + reservedOutput, "messages");
3272
+ if (knownValues("contextWindowTokens").length > 0 && outputTokens === void 0)
3273
+ report("parameters", "maxOutputTokens", "unknown", "Requested output token reservation is unknown");
3274
+ } else if (knownValues("contextWindowTokens").length > 0) {
3275
+ report("messages", "contextWindowTokens", "unknown", "Input token estimate is unavailable");
3276
+ }
3277
+ for (const schema of knownValues("parameters")) {
3278
+ const validator = compileModelSchema(schema);
3279
+ if (!validator(parameters))
3280
+ report("parameters", "parameters", "parameter", "Parameters do not satisfy the declared constraints");
3281
+ }
3282
+ const format = request.responseFormat;
3283
+ if (format !== void 0) {
3284
+ const key = format.type === "json" ? "structuredOutput.json" : "structuredOutput.jsonSchema";
3285
+ requireCapability(key, "responseFormat");
3286
+ if (format.type === "jsonSchema") {
3287
+ if (typeof format.name !== "string" || !/^[A-Za-z0-9_-]{1,64}$/u.test(format.name))
3288
+ report("responseFormat.name", key, "schema", "Schema name must contain 1 through 64 letters, digits, underscores, or hyphens");
3289
+ const dialect = modelSchemaDialect(format.schema);
3290
+ requireCapability("structuredOutput.schemaDialects", "responseFormat.schema");
3291
+ requireCapability("structuredOutput.schemaConstraint", "responseFormat.schema");
3292
+ for (const allowed of knownValues("structuredOutput.schemaDialects"))
3293
+ if (Array.isArray(allowed) && !allowed.includes(dialect))
3294
+ report("responseFormat.schema", "structuredOutput.schemaDialects", "schema", "Schema dialect is unsupported");
3295
+ for (const constraint of knownValues("structuredOutput.schemaConstraint"))
3296
+ if (!compileModelSchema(constraint)(format.schema))
3297
+ report("responseFormat.schema", "structuredOutput.schemaConstraint", "schema", "Schema exceeds the declared supported scope");
3298
+ compileModelSchema(format.schema);
3299
+ }
3300
+ }
3301
+ const unique = issues.filter((issue, index) => issues.findIndex((other) => other.field === issue.field && other.capability === issue.capability && other.code === issue.code) === index);
3302
+ const invalid = unique.some((issue) => issue.code !== "unknown") || options.unknownPolicy === "require-known" && unique.length > 0;
3303
+ return { status: invalid ? "invalid" : unique.length > 0 ? "unknown" : "valid", issues: unique };
3304
+ }
3305
+ __name(validateModelRequest, "validateModelRequest");
3306
+
3307
+ // packages/providers/dist/capability-validated-model.js
3308
+ var CapabilityValidatedModel = class {
3309
+ static {
3310
+ __name(this, "CapabilityValidatedModel");
3311
+ }
3312
+ model;
3313
+ options;
3314
+ contextCompactor;
3315
+ resolver;
3316
+ capabilities;
3317
+ validation;
3318
+ selection;
3319
+ responseFormat;
3320
+ unknownPolicy;
3321
+ constructor(model, selection, options = {}) {
3322
+ this.model = model;
3323
+ this.options = options;
3324
+ this.resolver = options.resolver ?? createModelCapabilityResolver();
3325
+ this.selection = structuredClone(selection);
3326
+ const responseFormat = selection.options.responseFormat;
3327
+ if (responseFormat !== void 0) {
3328
+ if (typeof responseFormat !== "object" || responseFormat === null || !("type" in responseFormat) || responseFormat.type !== "json" && responseFormat.type !== "jsonSchema") {
3329
+ throw new TypeError("options.responseFormat must be a JSON or JSON Schema response format");
3330
+ }
3331
+ this.responseFormat = structuredClone(responseFormat);
3332
+ assertModelResponseFormat5({ messages: [], tools: [], responseFormat: this.responseFormat });
3333
+ }
3334
+ const unknownPolicy = options.unknownPolicy ?? selection.options.unknownCapabilityPolicy ?? "allow";
3335
+ if (unknownPolicy !== "allow" && unknownPolicy !== "require-known")
3336
+ throw new TypeError("unknownCapabilityPolicy must be allow or require-known");
3337
+ this.unknownPolicy = unknownPolicy;
3338
+ const compactor = model.contextCompactor;
3339
+ if (compactor !== void 0)
3340
+ this.contextCompactor = {
3341
+ name: compactor.name,
3342
+ compact: /* @__PURE__ */ __name(async (snapshot, compactOptions) => {
3343
+ compactOptions.signal?.throwIfAborted();
3344
+ const capabilities = await this.getModelCapabilities();
3345
+ compactOptions.signal?.throwIfAborted();
3346
+ const capability = capabilities.fields?.contextCompaction;
3347
+ if (capability?.status === "unsupported" || this.unknownPolicy === "require-known" && capability?.status !== "known") {
3348
+ this.validation = {
3349
+ status: "invalid",
3350
+ issues: [
3351
+ {
3352
+ field: "contextCompactor",
3353
+ capability: "contextCompaction",
3354
+ code: capability?.status === "unsupported" ? "unsupported" : "unknown",
3355
+ message: "Native Context compaction capability is unavailable"
3356
+ }
3357
+ ]
3358
+ };
3359
+ throw new ModelRequestValidationError(this.validation);
3360
+ }
3361
+ const request = {
3362
+ messages: snapshot.instructions === void 0 ? snapshot.messages : [{ role: "system", content: [{ type: "text", text: snapshot.instructions }] }, ...snapshot.messages],
3363
+ tools: []
3364
+ };
3365
+ this.validate(request, capabilities, { ...this.options, unknownPolicy: this.unknownPolicy });
3366
+ if (capability?.status !== "known")
3367
+ this.validation = {
3368
+ status: "unknown",
3369
+ issues: [
3370
+ ...this.validation.issues,
3371
+ {
3372
+ field: "contextCompactor",
3373
+ capability: "contextCompaction",
3374
+ code: "unknown",
3375
+ message: "Native Context compaction capability is unknown"
3376
+ }
3377
+ ]
3378
+ };
3379
+ let success = false;
3380
+ try {
3381
+ const result = await compactor.compact(snapshot, compactOptions);
3382
+ success = true;
3383
+ return result;
3384
+ } finally {
3385
+ this.resolver.recordVerification(this.selection, request, success, false, ["contextCompaction"]);
3386
+ }
3387
+ }, "compact")
3388
+ };
3389
+ }
3390
+ get limits() {
3391
+ const limits = {};
3392
+ for (const key of ["contextWindowTokens", "maxOutputTokens"]) {
3393
+ const declarations = [
3394
+ this.model.limits?.[key],
3395
+ this.selection.capabilities?.fields?.[key],
3396
+ this.selection.providerConfig.capabilities?.fields?.[key]
3397
+ ];
3398
+ const resolved = [
3399
+ this.capabilities?.fields?.[key],
3400
+ ...Object.values(this.capabilities?.layers ?? {}).map((layer) => layer[key])
3401
+ ].flatMap((capability) => capability?.status === "known" && typeof capability.value === "number" ? [capability.value] : []);
3402
+ const values = [...declarations, ...resolved].filter((value) => typeof value === "number");
3403
+ if (values.length > 0)
3404
+ limits[key] = Math.min(...values);
3405
+ }
3406
+ return Object.keys(limits).length === 0 ? void 0 : limits;
3407
+ }
3408
+ get reportsAttempts() {
3409
+ return this.model.reportsAttempts;
3410
+ }
3411
+ get supportsRequestRecording() {
3412
+ return this.model.supportsRequestRecording === true;
3413
+ }
3414
+ get capabilityVersion() {
3415
+ return this.capabilities?.version;
3416
+ }
3417
+ get configuration() {
3418
+ const reasoningEffort = this.selection.options.reasoningEffort;
3419
+ return omitUndefined14({
3420
+ provider: this.selection.provider,
3421
+ adapter: this.selection.adapter,
3422
+ model: this.selection.model,
3423
+ profile: this.selection.profile,
3424
+ reasoningEffort: typeof reasoningEffort === "string" ? reasoningEffort : void 0,
3425
+ capabilityVersion: this.capabilityVersion
3426
+ });
3427
+ }
3428
+ get lastValidation() {
3429
+ return this.validation;
3430
+ }
3431
+ async getModelCapabilities() {
3432
+ this.capabilities = await this.resolver.resolve(this.selection);
3433
+ return this.capabilities;
3434
+ }
3435
+ async refreshCapabilities() {
3436
+ this.capabilities = await this.resolver.resolve(this.selection, { refresh: true });
3437
+ return this.capabilities;
3438
+ }
3439
+ async preflight(request, options) {
3440
+ request = this.effectiveRequest(request);
3441
+ options.signal.throwIfAborted();
3442
+ const capabilities = await this.getModelCapabilities();
3443
+ options.signal.throwIfAborted();
3444
+ const { responseFormat: configuredFormat, unknownCapabilityPolicy: configuredPolicy, ...configuredParameters } = this.selection.options;
3445
+ const parameters = configuredParameters;
3446
+ if (parameters.maxTokens === void 0 && parameters.maxOutputTokens === void 0 && this.selection.limits?.maxOutputTokens !== void 0) {
3447
+ const key = ["deepseek-chat", "kimi-chat", "zhipu-chat", "anthropic-messages"].includes(this.selection.adapter) ? "maxTokens" : "maxOutputTokens";
3448
+ parameters[key] = this.selection.limits.maxOutputTokens;
3449
+ }
3450
+ this.validate(request, capabilities, {
3451
+ ...this.options,
3452
+ unknownPolicy: this.unknownPolicy,
3453
+ parameters: this.options.parameters ?? parameters
3454
+ });
3455
+ }
3456
+ async *stream(request, options) {
3457
+ request = this.effectiveRequest(request);
3458
+ await this.preflight(request, options);
3459
+ const capabilities = this.capabilities;
3460
+ let completed = false;
3461
+ let verified = false;
3462
+ let responseValidated = false;
3463
+ try {
3464
+ for await (const event of this.model.stream(request, options)) {
3465
+ if (event.type === "response.completed") {
3466
+ if (completed)
3467
+ throw new ModelProtocolError("Model emitted more than one response.completed event");
3468
+ completed = true;
3469
+ validateStructuredModelResponse4(event.message, request, event);
3470
+ responseValidated = request.responseFormat !== void 0 && (event.message.toolCalls?.length ?? 0) === 0;
3471
+ const limits = [
3472
+ capabilities.fields?.["tools.maxCalls"],
3473
+ ...Object.values(capabilities.layers ?? {}).map((layer) => layer["tools.maxCalls"])
3474
+ ].flatMap((limit) => limit?.status === "known" && typeof limit.value === "number" ? [limit.value] : []);
3475
+ if ((event.message.toolCalls?.length ?? 0) > 0 && capabilities.fields?.["tools.maxCalls"]?.status === "unsupported")
3476
+ throw new ModelResponseValidationError("Model response uses unsupported tools.maxCalls", event);
3477
+ if (limits.length > 0 && (event.message.toolCalls?.length ?? 0) > Math.min(...limits)) {
3478
+ throw new ModelResponseValidationError("Model response exceeds tools.maxCalls", event);
3479
+ }
3480
+ }
3481
+ yield event;
3482
+ }
3483
+ if (!completed)
3484
+ throw new ModelProtocolError("Model stream ended without a response.completed event");
3485
+ verified = true;
3486
+ } finally {
3487
+ this.resolver.recordVerification(this.selection, request, verified, responseValidated);
3488
+ }
3489
+ }
3490
+ validate(request, capabilities, options) {
3491
+ this.validation = validateModelRequest(request, capabilities, options);
3492
+ if (this.validation.status === "invalid")
3493
+ throw new ModelRequestValidationError(this.validation);
3494
+ }
3495
+ effectiveRequest(request) {
3496
+ return request.responseFormat === void 0 && this.responseFormat !== void 0 ? { ...request, responseFormat: this.responseFormat } : request;
3497
+ }
3498
+ };
3499
+ function createCapabilityValidatedModel(model, selection, options = {}) {
3500
+ return new CapabilityValidatedModel(model, selection, options);
3501
+ }
3502
+ __name(createCapabilityValidatedModel, "createCapabilityValidatedModel");
3503
+
3504
+ // packages/providers/dist/registry.js
3505
+ var ProviderAdapterRegistry = class {
3506
+ static {
3507
+ __name(this, "ProviderAdapterRegistry");
3508
+ }
3509
+ validationOptions;
3510
+ factories = /* @__PURE__ */ new Map();
3511
+ constructor(validationOptions = {}) {
3512
+ this.validationOptions = validationOptions;
3513
+ }
3514
+ register(name, factory2) {
3515
+ validateAdapterName(name);
3516
+ if (typeof factory2 !== "object" || factory2 === null) {
3517
+ throw new TypeError("adapter factory must be an object");
3518
+ }
3519
+ if (typeof factory2.create !== "function") {
3520
+ throw new TypeError("adapter factory must define create(selection)");
3521
+ }
3522
+ if (this.factories.has(name)) {
3523
+ throw new ProviderAdapterRegistryError(`Adapter "${name}" is already registered`);
3524
+ }
3525
+ this.factories.set(name, factory2);
3526
+ return this;
3527
+ }
3528
+ has(name) {
3529
+ return this.factories.has(name);
3530
+ }
3531
+ names() {
3532
+ return [...this.factories.keys()];
3533
+ }
3534
+ create(selection) {
3535
+ const factory2 = this.factories.get(selection.adapter);
3536
+ if (factory2 === void 0) {
3537
+ const available = this.names();
3538
+ throw new ProviderAdapterRegistryError(`Unsupported adapter "${selection.adapter}"` + (available.length === 0 ? "; no adapters are registered" : `; available adapters: ${available.join(", ")}`));
3539
+ }
3540
+ const model = factory2.create(selection);
3541
+ return this.validationOptions.validateRequests === true ? createCapabilityValidatedModel(model, selection, this.validationOptions) : model;
3542
+ }
3543
+ };
3544
+ function validateAdapterName(name) {
3545
+ if (typeof name !== "string" || name.trim() === "") {
3546
+ throw new TypeError("adapter name must be a non-empty string");
3547
+ }
3548
+ if (name !== name.trim()) {
3549
+ throw new TypeError("adapter name must not have surrounding whitespace");
3550
+ }
3551
+ }
3552
+ __name(validateAdapterName, "validateAdapterName");
3553
+
3554
+ // packages/providers/dist/builtins.js
3555
+ var OPENAI_REASONING_SUMMARIES = /* @__PURE__ */ new Set(["auto", "concise", "detailed"]);
3556
+ var THINKING_TYPES = /* @__PURE__ */ new Set(["enabled", "disabled"]);
3557
+ var ANTHROPIC_THINKING_TYPES = /* @__PURE__ */ new Set(["enabled", "adaptive", "disabled"]);
3558
+ var THINKING_DISPLAYS = /* @__PURE__ */ new Set(["summarized", "omitted"]);
3559
+ var ANTHROPIC_CACHE_TTLS = /* @__PURE__ */ new Set(["5m", "1h"]);
3560
+ function createBuiltinProviderAdapterRegistry(options = {}) {
3561
+ const registry = new ProviderAdapterRegistry({
3562
+ ...options,
3563
+ validateRequests: true,
3564
+ resolver: options.resolver ?? createModelCapabilityResolver(omitUndefined15({ fetch: options.fetch }))
3565
+ });
3566
+ const zhipu = factory((selection) => createZhipuModel(selection, options));
3567
+ registry.register("google-gemini", factory((selection) => createGeminiModel(selection, options))).register("deepseek-chat", factory((selection) => createDeepSeekModel(selection, options))).register("zhipu-chat", zhipu).register("kimi-chat", factory((selection) => createKimiModel(selection, options))).register("anthropic-messages", factory((selection) => createAnthropicModel(selection, options))).register("openai-responses", factory((selection) => createOpenAIModel(selection, options))).register("openai-chat-completions", factory((selection) => createOpenAIChatCompletionsModel(selection, options)));
3568
+ return registry;
3569
+ }
3570
+ __name(createBuiltinProviderAdapterRegistry, "createBuiltinProviderAdapterRegistry");
3571
+ function createBuiltinProviderModel(selection, options = {}) {
3572
+ return createBuiltinProviderAdapterRegistry(options).create(selection);
3573
+ }
3574
+ __name(createBuiltinProviderModel, "createBuiltinProviderModel");
3575
+ function createGeminiModel(selection, dependencies) {
3576
+ const maxOutputTokens = optionalPositiveInteger(modelOption(selection, "maxOutputTokens"), optionField(selection, "maxOutputTokens")) ?? selection.limits?.maxOutputTokens;
3577
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3578
+ const includeThoughts = optionalBoolean(tuningOption(selection, "includeThoughts"), optionField(selection, "includeThoughts"));
3579
+ const thinkingBudget = tuningOption(selection, "thinkingBudget");
3580
+ if (thinkingBudget !== void 0 && (typeof thinkingBudget !== "number" || !Number.isSafeInteger(thinkingBudget) || thinkingBudget < -1))
3581
+ throw new ProviderConfigurationError(`${optionField(selection, "thinkingBudget")} must be an integer greater than or equal to -1`);
3582
+ const baseURL = providerBaseURL(selection);
3583
+ const options = omitUndefined15({
3584
+ ...credentials(selection),
3585
+ baseURL,
3586
+ maxOutputTokens,
3587
+ reasoningEffort,
3588
+ includeThoughts,
3589
+ thinkingBudget,
3590
+ fetch: dependencies.fetch
3591
+ });
3592
+ return attachModelLimits(new GeminiModel(options), selection.limits, maxOutputTokens);
3593
+ }
3594
+ __name(createGeminiModel, "createGeminiModel");
3595
+ function createDeepSeekModel(selection, dependencies) {
3596
+ const thinking = optionalEnum(tuningOption(selection, "thinking"), optionField(selection, "thinking"), THINKING_TYPES);
3597
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3598
+ const maxTokens = optionalPositiveInteger(tuningOption(selection, "maxTokens"), optionField(selection, "maxTokens")) ?? selection.limits?.maxOutputTokens;
3599
+ const baseURL = providerBaseURL(selection);
3600
+ const options = omitUndefined15({
3601
+ ...credentials(selection),
3602
+ baseURL,
3603
+ thinking,
3604
+ reasoningEffort,
3605
+ maxTokens,
3606
+ fetch: dependencies.fetch
3607
+ });
3608
+ return attachModelLimits(new DeepSeekModel(options), selection.limits, maxTokens);
3609
+ }
3610
+ __name(createDeepSeekModel, "createDeepSeekModel");
3611
+ function createZhipuModel(selection, dependencies) {
3612
+ const thinking = optionalEnum(tuningOption(selection, "thinking"), optionField(selection, "thinking"), THINKING_TYPES);
3613
+ const clearThinking = optionalBoolean(tuningOption(selection, "clearThinking"), optionField(selection, "clearThinking"));
3614
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3615
+ const maxTokens = optionalPositiveInteger(tuningOption(selection, "maxTokens"), optionField(selection, "maxTokens")) ?? selection.limits?.maxOutputTokens;
3616
+ const baseURL = providerBaseURL(selection);
3617
+ const options = omitUndefined15({
3618
+ ...credentials(selection),
3619
+ baseURL,
3620
+ thinking,
3621
+ clearThinking,
3622
+ reasoningEffort,
3623
+ maxTokens,
3624
+ fetch: dependencies.fetch
3625
+ });
3626
+ return attachModelLimits(new ZhipuModel(options), selection.limits, maxTokens);
3627
+ }
3628
+ __name(createZhipuModel, "createZhipuModel");
3629
+ function createKimiModel(selection, dependencies) {
3630
+ const thinking = optionalKimiThinking(tuningOption(selection, "thinking"), optionField(selection, "thinking"));
3631
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3632
+ const maxTokens = optionalPositiveInteger(tuningOption(selection, "maxTokens"), optionField(selection, "maxTokens")) ?? selection.limits?.maxOutputTokens;
3633
+ const baseURL = providerBaseURL(selection);
3634
+ const options = omitUndefined15({
3635
+ ...credentials(selection),
3636
+ baseURL,
3637
+ thinking,
3638
+ reasoningEffort,
3639
+ maxTokens,
3640
+ fetch: dependencies.fetch
3641
+ });
3642
+ return attachModelLimits(new KimiModel(options), selection.limits, maxTokens);
3643
+ }
3644
+ __name(createKimiModel, "createKimiModel");
3645
+ function createAnthropicModel(selection, dependencies) {
3646
+ const thinking = optionalAnthropicThinking(tuningOption(selection, "thinking"), optionField(selection, "thinking"));
3647
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3648
+ const maxTokens = optionalPositiveInteger(tuningOption(selection, "maxTokens"), optionField(selection, "maxTokens")) ?? selection.limits?.maxOutputTokens;
3649
+ const baseURL = providerBaseURL(selection);
3650
+ const apiVersion = optionalString2(tuningOption(selection, "apiVersion"), optionField(selection, "apiVersion"));
3651
+ const caching = Object.hasOwn(selection.options, "promptCaching") ? tuningOption(selection, "promptCaching") : selection.providerConfig.options?.promptCaching;
3652
+ const cachingRecord = caching === void 0 || caching === false ? void 0 : requireRecord4(caching, optionField(selection, "promptCaching"));
3653
+ const promptCaching = caching === false ? false : cachingRecord === void 0 ? void 0 : omitUndefined15({
3654
+ ttl: optionalEnum(cachingRecord.ttl, `${optionField(selection, "promptCaching")}.ttl`, ANTHROPIC_CACHE_TTLS),
3655
+ cacheInstructions: optionalBoolean(cachingRecord.cacheInstructions, `${optionField(selection, "promptCaching")}.cacheInstructions`)
3656
+ });
3657
+ const options = omitUndefined15({
3658
+ ...credentials(selection),
3659
+ baseURL,
3660
+ apiVersion,
3661
+ promptCaching,
3662
+ thinking,
3663
+ reasoningEffort,
3664
+ maxTokens,
3665
+ fetch: dependencies.fetch
3666
+ });
3667
+ return attachModelLimits(new AnthropicModel(options), selection.limits, maxTokens);
3668
+ }
3669
+ __name(createAnthropicModel, "createAnthropicModel");
3670
+ function createOpenAIModel(selection, dependencies) {
3671
+ const maxOutputTokens = optionalPositiveInteger(modelOption(selection, "maxOutputTokens"), optionField(selection, "maxOutputTokens")) ?? selection.limits?.maxOutputTokens;
3672
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3673
+ const reasoningSummary = optionalEnum(tuningOption(selection, "reasoningSummary"), optionField(selection, "reasoningSummary"), OPENAI_REASONING_SUMMARIES);
3674
+ const serverCompactThreshold = optionalPositiveInteger(tuningOption(selection, "serverCompactThreshold"), optionField(selection, "serverCompactThreshold"));
3675
+ const store = optionalBoolean(tuningOption(selection, "store"), optionField(selection, "store"));
3676
+ const baseURL = providerBaseURL(selection);
3677
+ const options = omitUndefined15({
3678
+ ...credentials(selection),
3679
+ baseURL,
3680
+ maxOutputTokens,
3681
+ reasoningEffort,
3682
+ reasoningSummary,
3683
+ serverCompactThreshold,
3684
+ store,
3685
+ fetch: dependencies.fetch
3686
+ });
3687
+ return attachModelLimits(new OpenAIResponsesModel(options), selection.limits, maxOutputTokens);
3688
+ }
3689
+ __name(createOpenAIModel, "createOpenAIModel");
3690
+ function createOpenAIChatCompletionsModel(selection, dependencies) {
3691
+ const maxOutputTokens = optionalPositiveInteger(modelOption(selection, "maxOutputTokens"), optionField(selection, "maxOutputTokens")) ?? selection.limits?.maxOutputTokens;
3692
+ const reasoningEffort = optionalString2(tuningOption(selection, "reasoningEffort"), optionField(selection, "reasoningEffort"));
3693
+ const store = optionalBoolean(tuningOption(selection, "store"), optionField(selection, "store"));
3694
+ const baseURL = providerBaseURL(selection);
3695
+ const options = omitUndefined15({
3696
+ ...credentials(selection),
3697
+ baseURL,
3698
+ maxOutputTokens,
3699
+ reasoningEffort,
3700
+ store,
3701
+ fetch: dependencies.fetch
3702
+ });
3703
+ return attachModelLimits(new OpenAIChatCompletionsModel(options), selection.limits, maxOutputTokens);
3704
+ }
3705
+ __name(createOpenAIChatCompletionsModel, "createOpenAIChatCompletionsModel");
3706
+ function credentials(selection) {
3707
+ return {
3708
+ apiKey: requiredString(selection.providerConfig.apiKey, providerField(selection, "apiKey")),
3709
+ model: requiredString(selection.model, "model")
3710
+ };
3711
+ }
3712
+ __name(credentials, "credentials");
3713
+ function providerBaseURL(selection) {
3714
+ return optionalString2(selection.providerConfig.baseURL, providerField(selection, "baseURL"));
3715
+ }
3716
+ __name(providerBaseURL, "providerBaseURL");
3717
+ function optionalKimiThinking(value, field) {
3718
+ if (value === void 0)
3719
+ return void 0;
3720
+ const record = requireRecord4(value, field);
3721
+ const type = optionalEnum(record.type, `${field}.type`, THINKING_TYPES);
3722
+ if (type === void 0) {
3723
+ throw new ProviderConfigurationError(`${field}.type is required`);
3724
+ }
3725
+ const keep = record.keep;
3726
+ if (keep === void 0)
3727
+ return { type };
3728
+ if (keep !== "all" && keep !== null) {
3729
+ throw new ProviderConfigurationError(`${field}.keep must be "all" or null`);
3730
+ }
3731
+ return { type, keep };
3732
+ }
3733
+ __name(optionalKimiThinking, "optionalKimiThinking");
3734
+ function optionalAnthropicThinking(value, field) {
3735
+ if (value === void 0)
3736
+ return void 0;
3737
+ const record = requireRecord4(value, field);
3738
+ const type = optionalEnum(record.type, `${field}.type`, ANTHROPIC_THINKING_TYPES);
3739
+ if (type === void 0) {
3740
+ throw new ProviderConfigurationError(`${field}.type is required`);
3741
+ }
3742
+ const display = optionalEnum(record.display, `${field}.display`, THINKING_DISPLAYS);
3743
+ if (type === "enabled") {
3744
+ const budgetTokens = optionalPositiveInteger(record.budgetTokens, `${field}.budgetTokens`);
3745
+ if (budgetTokens === void 0) {
3746
+ throw new ProviderConfigurationError(`${field}.budgetTokens is required when thinking is enabled`);
3747
+ }
3748
+ return omitUndefined15({ type, budgetTokens, display });
3749
+ }
3750
+ return omitUndefined15({ type, display: type === "disabled" ? void 0 : display });
3751
+ }
3752
+ __name(optionalAnthropicThinking, "optionalAnthropicThinking");
3753
+ function factory(create) {
3754
+ return { create };
3755
+ }
3756
+ __name(factory, "factory");
3757
+
3758
+ // packages/providers/dist/retrying-model.js
3759
+ import { serializeError, traceError, ModelProtocolError as ModelProtocolError2, ModelResponseValidationError as ModelResponseValidationError2, omitUndefined as omitUndefined16 } from "@sortedyuan/may/core";
3760
+ var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 409, 429]);
3761
+ var RETRYABLE_CODES = /* @__PURE__ */ new Set([
3762
+ "ECONNABORTED",
3763
+ "ECONNREFUSED",
3764
+ "ECONNRESET",
3765
+ "EHOSTUNREACH",
3766
+ "ENETDOWN",
3767
+ "ENETRESET",
3768
+ "ENETUNREACH",
3769
+ "EPIPE",
3770
+ "ETIMEDOUT",
3771
+ "EAI_AGAIN",
3772
+ "UND_ERR_CONNECT_TIMEOUT",
3773
+ "UND_ERR_HEADERS_TIMEOUT",
3774
+ "UND_ERR_SOCKET"
3775
+ ]);
3776
+ var RETRYABLE_PROVIDER_TYPES = /* @__PURE__ */ new Set([
3777
+ "api_error",
3778
+ "internal_error",
3779
+ "overloaded_error",
3780
+ "rate_limit_error",
3781
+ "server_error"
3782
+ ]);
3783
+ var RetryingModel = class {
3784
+ static {
3785
+ __name(this, "RetryingModel");
3786
+ }
3787
+ model;
3788
+ get supportsRequestRecording() {
3789
+ return this.model.supportsRequestRecording === true;
3790
+ }
3791
+ reportsAttempts = true;
3792
+ get capabilityVersion() {
3793
+ return this.model.capabilityVersion;
3794
+ }
3795
+ get configuration() {
3796
+ return this.model.configuration ?? {};
3797
+ }
3798
+ get limits() {
3799
+ return this.model.limits;
3800
+ }
3801
+ contextCompactor;
3802
+ maxAttempts;
3803
+ baseDelayMs;
3804
+ maxDelayMs;
3805
+ jitterRatio;
3806
+ shouldRetry;
3807
+ sleep;
3808
+ random;
3809
+ constructor(model, options = {}) {
3810
+ this.model = model;
3811
+ if (model.contextCompactor !== void 0) {
3812
+ this.contextCompactor = model.contextCompactor;
3813
+ }
3814
+ this.maxAttempts = positiveInteger(options.maxAttempts ?? 3, "maxAttempts");
3815
+ this.baseDelayMs = nonNegativeNumber(options.baseDelayMs ?? 500, "baseDelayMs");
3816
+ this.maxDelayMs = nonNegativeNumber(options.maxDelayMs ?? 8e3, "maxDelayMs");
3817
+ if (this.baseDelayMs > this.maxDelayMs) {
3818
+ throw new RangeError("baseDelayMs cannot exceed maxDelayMs");
3819
+ }
3820
+ this.jitterRatio = ratio(options.jitterRatio ?? 0.2, "jitterRatio");
3821
+ this.shouldRetry = options.shouldRetry ?? defaultShouldRetryModelError;
3822
+ this.sleep = options.sleep ?? abortableSleep;
3823
+ this.random = options.random ?? Math.random;
3824
+ }
3825
+ async preflight(request, options) {
3826
+ await this.model.preflight?.(request, options);
3827
+ }
3828
+ async *stream(request, options) {
3829
+ await this.preflight(request, options);
3830
+ for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
3831
+ let completed = false;
3832
+ let emittedContent = false;
3833
+ let usage;
3834
+ const telemetry = options.attemptObserver?.start(attempt);
3835
+ try {
3836
+ for await (const event of this.model.stream(request, {
3837
+ ...options,
3838
+ ...telemetry?.traceContext === void 0 ? {} : { traceContext: telemetry.traceContext }
3839
+ })) {
3840
+ if (options.signal.aborted)
3841
+ throw abortReason(options.signal);
3842
+ if ((event.type === "text.delta" || event.type === "reasoning.delta") && event.delta.length > 0) {
3843
+ emittedContent = true;
3844
+ telemetry?.content(event.type === "text.delta" ? "text" : "reasoning");
3845
+ }
3846
+ if (event.type === "response.completed") {
3847
+ if (completed)
3848
+ throw new ModelProtocolError2("Model emitted more than one response.completed event");
3849
+ completed = true;
3850
+ usage = event.usage;
3851
+ if (event.message.content.some((part) => part.type === "text" && part.text.length > 0))
3852
+ telemetry?.content("text");
3853
+ if ((event.message.toolCalls?.length ?? 0) > 0)
3854
+ telemetry?.content("tool");
3855
+ if (event.message.content.some((part) => part.type !== "text"))
3856
+ telemetry?.content("other");
3857
+ }
3858
+ yield event;
3859
+ }
3860
+ if (!completed)
3861
+ throw new ModelProtocolError2("Model stream ended without a response.completed event");
3862
+ telemetry?.end(omitUndefined16({ status: "ok", completed, usage }));
3863
+ return;
3864
+ } catch (error) {
3865
+ if (error instanceof Error && "code" in error && error.code === "RUN_CHECKPOINT_FAILED")
3866
+ throw error;
3867
+ if (error instanceof ModelResponseValidationError2) {
3868
+ completed = error.responseCompleted;
3869
+ usage = error.usage;
3870
+ }
3871
+ telemetry?.end(omitUndefined16({
3872
+ status: options.signal.aborted ? "cancelled" : "error",
3873
+ error: traceError(error),
3874
+ completed,
3875
+ usage
3876
+ }));
3877
+ const context = {
3878
+ attempt,
3879
+ maxAttempts: this.maxAttempts,
3880
+ signal: options.signal
3881
+ };
3882
+ if (options.signal.aborted || completed || emittedContent || attempt >= this.maxAttempts || !this.shouldRetry(error, context)) {
3883
+ throw error;
3884
+ }
3885
+ const delayMs = this.retryDelay(error, attempt);
3886
+ yield {
3887
+ type: "retrying",
3888
+ attempt: attempt + 1,
3889
+ maxAttempts: this.maxAttempts,
3890
+ delayMs,
3891
+ error: serializeError(error)
3892
+ };
3893
+ const waitStarted = performance.now();
3894
+ try {
3895
+ await this.sleep(delayMs, options.signal);
3896
+ } finally {
3897
+ options.attemptObserver?.retryWait?.(performance.now() - waitStarted);
3898
+ }
3899
+ } finally {
3900
+ telemetry?.end(omitUndefined16({ status: options.signal.aborted ? "cancelled" : "error", completed, usage }));
3901
+ }
3902
+ }
3903
+ }
3904
+ retryDelay(error, failedAttempt) {
3905
+ const requested = retryAfterMs(error);
3906
+ if (requested !== void 0) {
3907
+ if (requested > this.maxDelayMs)
3908
+ throw error;
3909
+ return requested;
3910
+ }
3911
+ const exponential = Math.min(this.baseDelayMs * 2 ** (failedAttempt - 1), this.maxDelayMs);
3912
+ if (exponential === 0 || this.jitterRatio === 0)
3913
+ return exponential;
3914
+ const random = this.random();
3915
+ if (!Number.isFinite(random) || random < 0 || random > 1) {
3916
+ throw new RangeError("random must return a number from 0 through 1");
3917
+ }
3918
+ const factor = 1 - this.jitterRatio + random * this.jitterRatio * 2;
3919
+ return Math.round(Math.min(exponential * factor, this.maxDelayMs));
3920
+ }
3921
+ };
3922
+ function withModelRetry(model, options = {}) {
3923
+ return new RetryingModel(model, options);
3924
+ }
3925
+ __name(withModelRetry, "withModelRetry");
3926
+ function defaultShouldRetryModelError(error) {
3927
+ return classifyRetryable(error, /* @__PURE__ */ new Set());
3928
+ }
3929
+ __name(defaultShouldRetryModelError, "defaultShouldRetryModelError");
3930
+ function classifyRetryable(error, seen) {
3931
+ if (typeof error !== "object" || error === null || seen.has(error))
3932
+ return false;
3933
+ seen.add(error);
3934
+ const candidate = error;
3935
+ if (candidate.name === "AbortError" || candidate.name === "RunCancelledError") {
3936
+ return false;
3937
+ }
3938
+ const status = candidate.status;
3939
+ if (typeof status === "number") {
3940
+ return RETRYABLE_STATUSES.has(status) || status >= 500;
3941
+ }
3942
+ for (const value of [candidate.code, candidate.errno]) {
3943
+ if (typeof value === "string" && RETRYABLE_CODES.has(value.toUpperCase())) {
3944
+ return true;
3945
+ }
3946
+ }
3947
+ if (typeof candidate.providerType === "string" && RETRYABLE_PROVIDER_TYPES.has(candidate.providerType.toLowerCase())) {
3948
+ return true;
3949
+ }
3950
+ if (candidate.name === "TimeoutError")
3951
+ return true;
3952
+ if (candidate.name === "TypeError" && typeof candidate.message === "string" && /fetch|network|socket|timed?\s*out/i.test(candidate.message)) {
3953
+ return true;
3954
+ }
3955
+ return classifyRetryable(candidate.cause, seen);
3956
+ }
3957
+ __name(classifyRetryable, "classifyRetryable");
3958
+ function retryAfterMs(error) {
3959
+ if (typeof error !== "object" || error === null)
3960
+ return void 0;
3961
+ const value = error.retryAfterMs;
3962
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
3963
+ }
3964
+ __name(retryAfterMs, "retryAfterMs");
3965
+ function abortableSleep(delayMs, signal) {
3966
+ if (signal.aborted)
3967
+ return Promise.reject(abortReason(signal));
3968
+ if (delayMs === 0)
3969
+ return Promise.resolve();
3970
+ return new Promise((resolve, reject) => {
3971
+ const timer = setTimeout(() => {
3972
+ signal.removeEventListener("abort", onAbort);
3973
+ resolve();
3974
+ }, delayMs);
3975
+ const onAbort = /* @__PURE__ */ __name(() => {
3976
+ clearTimeout(timer);
3977
+ reject(abortReason(signal));
3978
+ }, "onAbort");
3979
+ signal.addEventListener("abort", onAbort, { once: true });
3980
+ });
3981
+ }
3982
+ __name(abortableSleep, "abortableSleep");
3983
+ function abortReason(signal) {
3984
+ if (signal.reason instanceof Error)
3985
+ return signal.reason;
3986
+ return new DOMException(typeof signal.reason === "string" ? signal.reason : "The operation was aborted", "AbortError");
3987
+ }
3988
+ __name(abortReason, "abortReason");
3989
+ function positiveInteger(value, field) {
3990
+ if (!Number.isSafeInteger(value) || value < 1) {
3991
+ throw new RangeError(`${field} must be a positive safe integer`);
3992
+ }
3993
+ return value;
3994
+ }
3995
+ __name(positiveInteger, "positiveInteger");
3996
+ function nonNegativeNumber(value, field) {
3997
+ if (!Number.isFinite(value) || value < 0) {
3998
+ throw new RangeError(`${field} must be a non-negative finite number`);
3999
+ }
4000
+ return value;
4001
+ }
4002
+ __name(nonNegativeNumber, "nonNegativeNumber");
4003
+ function ratio(value, field) {
4004
+ if (!Number.isFinite(value) || value < 0 || value > 1) {
4005
+ throw new RangeError(`${field} must be a number from 0 through 1`);
4006
+ }
4007
+ return value;
4008
+ }
4009
+ __name(ratio, "ratio");
4010
+
4011
+ // packages/providers/dist/selection.js
4012
+ import { resolveModelProfile } from "@sortedyuan/may/config";
4013
+ import { omitUndefined as omitUndefined17 } from "@sortedyuan/may/core";
4014
+ function selectProviderModel(config, selector = {}, resolveOptions = {}) {
4015
+ const profileName = selector.model ?? config.defaultModel ?? onlyModel(config);
4016
+ const profile = resolveModelProfile(config, profileName, resolveOptions);
4017
+ return omitUndefined17({
4018
+ profile: profile.name,
4019
+ provider: profile.provider,
4020
+ adapter: profile.adapter,
4021
+ model: profile.model,
4022
+ providerConfig: profile.providerConfig,
4023
+ options: profile.options,
4024
+ capabilities: profile.capabilities,
4025
+ limits: modelLimits(profile.contextWindowTokens, profile.maxOutputTokens)
4026
+ });
4027
+ }
4028
+ __name(selectProviderModel, "selectProviderModel");
4029
+ function modelLimits(contextWindowTokens, maxOutputTokens) {
4030
+ if (contextWindowTokens === void 0 && maxOutputTokens === void 0)
4031
+ return void 0;
4032
+ return omitUndefined17({ contextWindowTokens, maxOutputTokens });
4033
+ }
4034
+ __name(modelLimits, "modelLimits");
4035
+ function onlyModel(config) {
4036
+ const models = Object.keys(config.models);
4037
+ if (models.length === 0) {
4038
+ throw new ProviderConfigurationError(`No model profiles are configured in ${config.path}`);
4039
+ }
4040
+ if (models.length > 1) {
4041
+ throw new ProviderConfigurationError("Select a model with --model or configure defaultModel");
4042
+ }
4043
+ return models[0];
4044
+ }
4045
+ __name(onlyModel, "onlyModel");
4046
+
4047
+ export {
4048
+ openAIResponseContent,
4049
+ ProviderAdapterRegistryError,
4050
+ ProviderConfigurationError,
4051
+ createModelCapabilityResolver,
4052
+ createBuiltinProviderAdapterRegistry,
4053
+ createBuiltinProviderModel,
4054
+ withModelRetry,
4055
+ selectProviderModel
4056
+ };
4057
+ //# sourceMappingURL=chunk-WVIRS76R.js.map