@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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 (109) hide show
  1. package/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
  2. package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
  3. package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
  4. package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
  5. package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
  6. package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
  7. package/lib/behavior-BwvTUtag.mjs +111 -0
  8. package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
  9. package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
  10. package/lib/cascade-BWjRTD1q.mjs +30265 -0
  11. package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
  12. package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
  13. package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
  14. package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
  15. package/lib/collapse-_nkb2dn7.mjs +1945 -0
  16. package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
  17. package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
  18. package/lib/cursor-BgOuV7Qf.mjs +794 -0
  19. package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
  20. package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
  21. package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
  22. package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
  23. package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
  24. package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
  25. package/lib/factory-droid-ChhmsGWb.mjs +71 -0
  26. package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
  27. package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
  28. package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
  29. package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
  30. package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
  31. package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
  32. package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
  33. package/lib/google-validation-CdvRj4ec.mjs +126 -0
  34. package/lib/id-EJwVLDHE.mjs +2548 -0
  35. package/lib/index.mjs +248 -258
  36. package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
  37. package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
  38. package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
  39. package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
  40. package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
  41. package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
  42. package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
  43. package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
  44. package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
  45. package/lib/pricing-DusBEhwm.mjs +593 -0
  46. package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
  47. package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
  48. package/lib/slugify-ynYWBIA5.mjs +11 -0
  49. package/lib/snowflake-B_jap6lz.mjs +666 -0
  50. package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
  51. package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
  52. package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
  53. package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
  54. package/lib/types/tools/hashline/native/index.d.ts +2 -2
  55. package/lib/types/tools/hashline/native/policy.d.ts +19 -21
  56. package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
  57. package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
  58. package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
  59. package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
  60. package/lib/utils-D2tK38xq.mjs +34006 -0
  61. package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
  62. package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
  63. package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
  64. package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
  65. package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
  66. package/package.json +8 -8
  67. package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
  68. package/lib/anthropic-ClCw0PV_.mjs +0 -3624
  69. package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
  70. package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
  71. package/lib/bundled-references-DY3EJxZV.mjs +0 -56
  72. package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
  73. package/lib/collapse-CkMNRNr7.mjs +0 -2304
  74. package/lib/cursor-C6jaIJDg.mjs +0 -283
  75. package/lib/cursor-D-XZYDf_.mjs +0 -4544
  76. package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
  77. package/lib/devin-ExGIghmx.mjs +0 -69
  78. package/lib/devin-u0ljw5P6.mjs +0 -628
  79. package/lib/effort-BdtQMN-_.mjs +0 -23
  80. package/lib/event-stream-BKEtb45Y.mjs +0 -167
  81. package/lib/gemini-headers-Co9cVvex.mjs +0 -54
  82. package/lib/google-auth-qAN-6DMW.mjs +0 -232
  83. package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
  84. package/lib/google-lTxuq28n.mjs +0 -38
  85. package/lib/google-shared-Y01j9xOr.mjs +0 -856
  86. package/lib/google-validation-BEkNs-Bx.mjs +0 -18
  87. package/lib/google-vertex-DcM-FRC5.mjs +0 -99
  88. package/lib/hosts-00rjRzUD.mjs +0 -203
  89. package/lib/id-AL5obQzR.mjs +0 -71
  90. package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
  91. package/lib/ollama-6R0oXZks.mjs +0 -574
  92. package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
  93. package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
  94. package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
  95. package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
  96. package/lib/openai-responses-CjpafAEr.mjs +0 -861
  97. package/lib/protobuf-BMgDYu_U.mjs +0 -717
  98. package/lib/provider-response-SqKSkkUc.mjs +0 -22
  99. package/lib/proxy-DxvCQOCA.mjs +0 -230
  100. package/lib/request-debug-BwPOqN_j.mjs +0 -183
  101. package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
  102. package/lib/sse-debug-B-tkLCPW.mjs +0 -11
  103. package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
  104. package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
  105. package/lib/taxonomy-DSIM99rS.mjs +0 -15392
  106. package/lib/thinking-ngMwf_1Y.mjs +0 -336
  107. package/lib/type-guards-CttAANEx.mjs +0 -11
  108. package/lib/utils-CE3DSebh.mjs +0 -11763
  109. package/lib/vision-guard-BCpXWUj3.mjs +0 -77
@@ -1,856 +0,0 @@
1
- import { installBunShim as __installBunShim } from "./bun-shim.mjs";
2
- __installBunShim();
3
- import { o as readSseJson } from "./src-AELUUb5U.mjs";
4
- import { R as GoogleApiError, _ as AbortError, c as finalize, r as ValidationError, s as ProviderResponseError, t as ConfigurationError } from "./error-O63pC8zg.mjs";
5
- import { A as toolWireSchema, N as normalizeSchemaForCCA, P as normalizeSchemaForGoogle, T as renderDemotedThinking, h as transformMessages, o as normalizeSystemPrompts } from "./utils-cZX3f_Ls.mjs";
6
- import { t as calculateCost } from "./models-DnXMYGcJ.mjs";
7
- import { o as shouldSendServiceTier, t as NON_VISION_IMAGE_PLACEHOLDER } from "./vision-guard-BCpXWUj3.mjs";
8
- import { t as AssistantMessageEventStream } from "./event-stream-BKEtb45Y.mjs";
9
- import { scheduler } from "node:timers/promises";
10
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/dialect/thinking-fence-strip.ts
11
- /**
12
- * Strip self-referential reasoning-fence delimiters that a provider leaks
13
- * *inside* a structured thinking part.
14
- *
15
- * The visible-channel healers ({@link ../utils/leaked-thinking-stream},
16
- * {@link ./fenced-thinking}) split leaked ` ```thinking ` fences out of the
17
- * *text* stream. They never run over parts a provider already flags as
18
- * thinking, so when a model (observed on Gemini thought summaries — issue
19
- * #8719) emits a bare ` ```thinking ` / ` ``````thinking ` opener line between
20
- * summaries, that delimiter reaches display and persistence verbatim as fence
21
- * spam inside the reasoning block.
22
- *
23
- * This stripper removes only a *standalone* reasoning-fence opener line — a line
24
- * that is nothing but a run of ≥3 backticks immediately followed by the info
25
- * string `thinking` or `reasoning`. Such a line is always redundant inside an
26
- * already-structured thinking block and never carries content. Inline mentions
27
- * (prose on the same line), language-tagged code fences (` ```rs `), and bare
28
- * closers (` ``` `) are left untouched so legitimate fenced code inside the
29
- * reasoning survives.
30
- *
31
- * Streaming-safe: deltas may split a line anywhere. A trailing partial line is
32
- * held only while it remains a viable opener prefix; the moment it cannot be an
33
- * opener it is flushed and the rest of the line passes through character-level.
34
- * Correctness never depends on the prefix heuristic — every held line is
35
- * classified strictly on its newline (or on {@link ThinkingFenceStripper.flush})
36
- * before it is dropped.
37
- */
38
- /**
39
- * A complete standalone reasoning-fence opener: ≤3 lead spaces, ≥3 backticks,
40
- * `thinking`/`reasoning`, optional trailing spaces, tolerating a trailing CR
41
- * from a CRLF newline.
42
- */
43
- const OPENER_LINE = /^ {0,3}`{3,}(?:thinking|reasoning)[ \t]*\r?$/i;
44
- /** Could `line` (a partial, newline-not-yet-seen) still grow into {@link OPENER_LINE}? */
45
- function couldBeOpenerPrefix(line) {
46
- const s = line.endsWith("\r") ? line.slice(0, -1) : line;
47
- const m = /^ {0,3}(`*)([\s\S]*)$/.exec(s);
48
- if (!m) return false;
49
- const ticks = m[1].length;
50
- const rest = m[2];
51
- if (rest === "") return true;
52
- if (ticks < 3) return false;
53
- const word = rest.replace(/[ \t]+$/, "").toLowerCase();
54
- return "thinking".startsWith(word) || "reasoning".startsWith(word);
55
- }
56
- /**
57
- * Stateful, line-oriented stripper for leaked reasoning-fence openers in one
58
- * structured thinking block. One instance per thinking block; feed every
59
- * thinking delta through {@link push} and drain the tail with {@link flush}.
60
- */
61
- var ThinkingFenceStripper = class {
62
- /** Buffered content of the current line still being classified. */
63
- #carry = "";
64
- /** True once the current line is known not to be an opener; passes through until newline. */
65
- #passthrough = false;
66
- /** Consume one thinking delta; returns the sanitized text to emit (may be empty). */
67
- push(chunk) {
68
- let out = "";
69
- for (const ch of chunk) {
70
- if (this.#passthrough) {
71
- out += ch;
72
- if (ch === "\n") this.#passthrough = false;
73
- continue;
74
- }
75
- if (ch === "\n") {
76
- if (!OPENER_LINE.test(this.#carry)) out += `${this.#carry}\n`;
77
- this.#carry = "";
78
- continue;
79
- }
80
- this.#carry += ch;
81
- if (!couldBeOpenerPrefix(this.#carry)) {
82
- out += this.#carry;
83
- this.#carry = "";
84
- this.#passthrough = true;
85
- }
86
- }
87
- return out;
88
- }
89
- /** Drain any held partial line at block end; returns text to emit (may be empty). */
90
- flush() {
91
- const carry = this.#carry;
92
- this.#carry = "";
93
- this.#passthrough = false;
94
- return OPENER_LINE.test(carry) ? "" : carry;
95
- }
96
- };
97
- //#endregion
98
- //#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/providers/google-shared.ts
99
- /**
100
- * Shared utilities for Google Generative AI and Google Cloud Code Assist providers.
101
- */
102
- function convertGoogleImagePart(image) {
103
- if (image.providerFile?.provider === "google" && image.providerFile.uri) return { fileData: {
104
- fileUri: image.providerFile.uri,
105
- mimeType: image.mimeType
106
- } };
107
- return image.url ? { fileData: {
108
- fileUri: image.url,
109
- mimeType: image.mimeType
110
- } } : { inlineData: {
111
- mimeType: image.mimeType,
112
- data: image.data
113
- } };
114
- }
115
- /**
116
- * Determines whether a streamed Gemini `Part` should be treated as "thinking".
117
- *
118
- * Protocol note (Gemini / Vertex AI thought signatures):
119
- * - `thought: true` is the definitive marker for thinking content (thought summaries).
120
- * - `thoughtSignature` is an encrypted representation of the model's internal thought process
121
- * used to preserve reasoning context across multi-turn interactions.
122
- * - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
123
- * indicate the part itself is thinking content.
124
- * - For non-functionCall responses, the signature appears on the last part for context replay.
125
- * - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
126
- * do not merge/move signatures across parts.
127
- *
128
- * See: https://ai.google.dev/gemini-api/docs/thought-signatures
129
- */
130
- function isThinkingPart(part) {
131
- return part.thought === true;
132
- }
133
- /**
134
- * Retain thought signatures during streaming.
135
- *
136
- * Some backends only send `thoughtSignature` on the first delta for a given part/block; later deltas may omit it.
137
- * This helper preserves the last non-empty signature for the current block.
138
- *
139
- * Note: this does NOT merge or move signatures across distinct response parts. It only prevents
140
- * a signature from being overwritten with `undefined` within the same streamed block.
141
- */
142
- function retainThoughtSignature(existing, incoming) {
143
- if (typeof incoming === "string" && incoming.length > 0) return incoming;
144
- return existing;
145
- }
146
- const base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
147
- const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
148
- function isValidThoughtSignature(signature) {
149
- if (!signature) return false;
150
- if (signature.length % 4 !== 0) return false;
151
- return base64SignaturePattern.test(signature);
152
- }
153
- /**
154
- * Only keep signatures from the same provider/model and with valid base64.
155
- */
156
- function resolveThoughtSignature(isSameProviderAndModel, signature) {
157
- return isSameProviderAndModel && isValidThoughtSignature(signature) ? signature : void 0;
158
- }
159
- /**
160
- * Convert internal messages to Gemini Content[] format.
161
- */
162
- function convertMessages(model, context) {
163
- const contents = [];
164
- const emittedToolCallNames = /* @__PURE__ */ new Map();
165
- const normalizeToolCallId = (id) => {
166
- return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
167
- };
168
- const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
169
- let pendingToolImageParts = [];
170
- const flushPendingToolImages = () => {
171
- if (pendingToolImageParts.length === 0) return;
172
- contents.push({
173
- role: "user",
174
- parts: pendingToolImageParts
175
- });
176
- pendingToolImageParts = [];
177
- };
178
- for (const msg of transformedMessages) {
179
- if (msg.role !== "toolResult") flushPendingToolImages();
180
- if (msg.role === "user" || msg.role === "developer") {
181
- if (typeof msg.content === "string") {
182
- if (!msg.content || msg.content.trim() === "") continue;
183
- contents.push({
184
- role: "user",
185
- parts: [{ text: msg.content.toWellFormed() }]
186
- });
187
- } else {
188
- const supportsImages = model.input.includes("image");
189
- const parts = [];
190
- let omittedImages = false;
191
- for (const item of msg.content) if (item.type === "text") {
192
- const text = item.text.toWellFormed();
193
- if (text.trim().length === 0) continue;
194
- parts.push({ text });
195
- } else if (supportsImages) parts.push(convertGoogleImagePart(item));
196
- else omittedImages = true;
197
- if (omittedImages) parts.push({ text: NON_VISION_IMAGE_PLACEHOLDER });
198
- if (parts.length === 0) continue;
199
- contents.push({
200
- role: "user",
201
- parts
202
- });
203
- }
204
- } else if (msg.role === "assistant") {
205
- const parts = [];
206
- const isSameProviderAndModel = msg.provider === model.provider && msg.model === model.id;
207
- const dropsUnsignedThinking = model.compat.dropUnsignedThinking;
208
- let isFirstToolCall = true;
209
- for (const block of msg.content) if (block.type === "text") {
210
- if (!block.text || block.text.trim() === "") continue;
211
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.textSignature);
212
- parts.push({
213
- text: block.text.toWellFormed(),
214
- ...thoughtSignature && { thoughtSignature }
215
- });
216
- } else if (block.type === "thinking") {
217
- if (!block.thinking || block.thinking.trim() === "") continue;
218
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
219
- if (dropsUnsignedThinking && !thoughtSignature) continue;
220
- if (thoughtSignature) parts.push({
221
- thought: true,
222
- text: block.thinking.toWellFormed(),
223
- thoughtSignature
224
- });
225
- else parts.push({ text: renderDemotedThinking(model.id, block.thinking) });
226
- } else if (block.type === "toolCall") {
227
- emittedToolCallNames.set(block.id, block.name);
228
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature);
229
- const requiresFallback = model.compat.requiresSkipThoughtSignature || isFirstToolCall && model.compat.requiresSkipThoughtSignatureOnFirstFunctionCall;
230
- const effectiveSignature = thoughtSignature || (requiresFallback ? SKIP_THOUGHT_SIGNATURE : void 0);
231
- isFirstToolCall = false;
232
- const part = { functionCall: {
233
- name: block.name,
234
- args: block.arguments ?? {},
235
- ...model.compat.supportsFunctionPartId ? { id: block.id } : {}
236
- } };
237
- if (effectiveSignature) part.thoughtSignature = effectiveSignature;
238
- parts.push(part);
239
- }
240
- if (parts.length === 0) continue;
241
- contents.push({
242
- role: "model",
243
- parts
244
- });
245
- } else if (msg.role === "toolResult") {
246
- const supportsImages = model.input.includes("image");
247
- const textResult = msg.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
248
- const imageContent = supportsImages ? msg.content.filter((c) => c.type === "image") : [];
249
- const omittedImages = !supportsImages && msg.content.some((c) => c.type === "image");
250
- const hasText = textResult.length > 0;
251
- const hasImages = imageContent.length > 0;
252
- const modelSupportsMultimodalFunctionResponse = model.compat.multimodalFunctionResponse;
253
- const responseValue = omittedImages ? [hasText ? textResult.toWellFormed() : "", NON_VISION_IMAGE_PLACEHOLDER].filter(Boolean).join("\n") : hasText ? textResult.toWellFormed() : hasImages ? "(see attached image)" : "";
254
- const imageParts = imageContent.map(convertGoogleImagePart);
255
- const includeId = model.compat.supportsFunctionPartId;
256
- const functionResponsePart = { functionResponse: {
257
- name: emittedToolCallNames.get(msg.toolCallId) ?? msg.toolName,
258
- response: msg.isError ? { error: responseValue } : { output: responseValue },
259
- ...hasImages && modelSupportsMultimodalFunctionResponse && { parts: imageParts },
260
- ...includeId ? { id: msg.toolCallId } : {}
261
- } };
262
- const lastContent = contents[contents.length - 1];
263
- if (lastContent?.role === "user" && lastContent.parts?.some((p) => p.functionResponse)) lastContent.parts.push(functionResponsePart);
264
- else contents.push({
265
- role: "user",
266
- parts: [functionResponsePart]
267
- });
268
- if (hasImages && !modelSupportsMultimodalFunctionResponse) pendingToolImageParts.push({ text: "Tool result image:" }, ...imageParts);
269
- }
270
- }
271
- flushPendingToolImages();
272
- return contents;
273
- }
274
- /**
275
- * Convert tools to Gemini function declarations format.
276
- *
277
- * We prefer `parametersJsonSchema` (full JSON Schema: anyOf/oneOf/const/etc.).
278
- *
279
- * Claude models via Cloud Code Assist require the legacy `parameters` field; the API
280
- * translates it into Anthropic's `input_schema`. When using that path, we sanitize the
281
- * schema to remove Google-unsupported JSON Schema keywords.
282
- */
283
- function convertTools(tools, model) {
284
- if (tools.length === 0) return void 0;
285
- /**
286
- * Claude models on Cloud Code Assist need the legacy `parameters` field;
287
- * the API translates it into Anthropic's `input_schema`.
288
- */
289
- const useParameters = model.compat.ccaLegacyParametersSchema;
290
- return [{ functionDeclarations: tools.map((tool) => ({
291
- name: tool.name,
292
- description: tool.description || "",
293
- ...useParameters ? { parameters: normalizeSchemaForCCA(toolWireSchema(tool)) } : { parametersJsonSchema: normalizeSchemaForGoogle(toolWireSchema(tool)) }
294
- })) }];
295
- }
296
- /**
297
- * Map tool choice string to Gemini FunctionCallingConfigMode.
298
- */
299
- function mapToolChoice(choice) {
300
- switch (choice) {
301
- case "auto": return "AUTO";
302
- case "none": return "NONE";
303
- case "any": return "ANY";
304
- default: return "AUTO";
305
- }
306
- }
307
- /**
308
- * Map Gemini FinishReason to our StopReason.
309
- */
310
- function mapStopReason(reason) {
311
- switch (reason) {
312
- case "STOP": return "stop";
313
- case "MAX_TOKENS": return "length";
314
- case "BLOCKLIST":
315
- case "PROHIBITED_CONTENT":
316
- case "SPII":
317
- case "SAFETY":
318
- case "IMAGE_SAFETY":
319
- case "IMAGE_PROHIBITED_CONTENT":
320
- case "IMAGE_RECITATION":
321
- case "IMAGE_OTHER":
322
- case "RECITATION":
323
- case "FINISH_REASON_UNSPECIFIED":
324
- case "OTHER":
325
- case "LANGUAGE":
326
- case "MALFORMED_FUNCTION_CALL":
327
- case "UNEXPECTED_TOOL_CALL":
328
- case "NO_IMAGE": return "error";
329
- default: throw new ConfigurationError(`Unhandled stop reason: ${reason}`);
330
- }
331
- }
332
- /**
333
- * Map string finish reason to our StopReason (for raw API responses).
334
- */
335
- function mapStopReasonString(reason) {
336
- switch (reason) {
337
- case "STOP": return "stop";
338
- case "MAX_TOKENS": return "length";
339
- default: return "error";
340
- }
341
- }
342
- /**
343
- * Whether a completed Google assistant message carries content worth delivering.
344
- *
345
- * A tool call or any non-whitespace text counts as meaningful. An empty/whitespace-only
346
- * text part — or thinking that never produced an answer — is the "empty response" failure:
347
- * delivered as-is the agent loop has nothing to act on and silently halts, so the request
348
- * must be retried instead of surfaced.
349
- */
350
- function hasMeaningfulGoogleContent(output) {
351
- for (const block of output.content) {
352
- if (block.type === "toolCall") return true;
353
- if (block.type === "text" && block.text.trim().length > 0) return true;
354
- }
355
- return false;
356
- }
357
- /** Wipe a streamed message between empty-response retries so the next attempt starts clean. */
358
- function resetGoogleStreamOutputForRetry(output) {
359
- output.content = [];
360
- output.usage = {
361
- input: 0,
362
- output: 0,
363
- cacheRead: 0,
364
- cacheWrite: 0,
365
- totalTokens: 0,
366
- cost: {
367
- input: 0,
368
- output: 0,
369
- cacheRead: 0,
370
- cacheWrite: 0,
371
- total: 0
372
- }
373
- };
374
- output.stopReason = "stop";
375
- output.errorMessage = void 0;
376
- output.timestamp = Date.now();
377
- }
378
- /**
379
- * Module-local counter for generating unique tool call IDs across Google providers.
380
- * Shared so that a single monotonically-increasing sequence is used regardless of which
381
- * Google API surface produced the stream — purely for uniqueness, not ordering semantics.
382
- */
383
- let toolCallCounter = 0;
384
- function nextToolCallId(name) {
385
- return `${name}_${Date.now()}_${++toolCallCounter}`;
386
- }
387
- /**
388
- * Push the appropriate `text_end` / `thinking_end` event for the given block.
389
- * Shared between the SDK-backed stream consumer and the gemini-cli SSE consumer so
390
- * the end-of-block event shape stays in lockstep.
391
- */
392
- function pushBlockEndEvent(block, contentIndex, output, stream) {
393
- if (block.type === "text") stream.push({
394
- type: "text_end",
395
- contentIndex,
396
- content: block.text,
397
- partial: output
398
- });
399
- else stream.push({
400
- type: "thinking_end",
401
- contentIndex,
402
- content: block.thinking,
403
- partial: output
404
- });
405
- }
406
- /**
407
- * Push the three lifecycle events (`toolcall_start` / `toolcall_delta` / `toolcall_end`) for a
408
- * fully-assembled `ToolCall`. Caller is responsible for appending the toolCall to `output.content`
409
- * before invoking — this helper does not mutate `output.content`.
410
- */
411
- function pushToolCallEvents(toolCall, contentIndex, output, stream) {
412
- stream.push({
413
- type: "toolcall_start",
414
- contentIndex,
415
- partial: output
416
- });
417
- stream.push({
418
- type: "toolcall_delta",
419
- contentIndex,
420
- delta: JSON.stringify(toolCall.arguments),
421
- partial: output
422
- });
423
- stream.push({
424
- type: "toolcall_end",
425
- contentIndex,
426
- toolCall,
427
- partial: output
428
- });
429
- }
430
- function startTextOrThinkingBlock(isThinking, output, stream, onBeforeStartEvent) {
431
- const block = isThinking ? {
432
- type: "thinking",
433
- thinking: "",
434
- thinkingSignature: void 0
435
- } : {
436
- type: "text",
437
- text: ""
438
- };
439
- output.content.push(block);
440
- onBeforeStartEvent?.();
441
- const contentIndex = output.content.length - 1;
442
- if (isThinking) stream.push({
443
- type: "thinking_start",
444
- contentIndex,
445
- partial: output
446
- });
447
- else stream.push({
448
- type: "text_start",
449
- contentIndex,
450
- partial: output
451
- });
452
- return block;
453
- }
454
- /**
455
- * Drives the chunked `generateContentStream` iterator into an `AssistantMessage` and
456
- * the corresponding `AssistantMessageEventStream`. Shared between `streamGoogle` and
457
- * `streamGoogleVertex` — every observable event order and stop-reason rule is preserved.
458
- *
459
- * The caller still owns: `output` construction, timing fields (`duration`/`ttft`),
460
- * `rawRequestDump`, the `client.models.generateContentStream(params)` call itself,
461
- * pushing `start`/`done`/`error` events, and the surrounding try/catch that translates
462
- * thrown errors into `output.stopReason`/`errorMessage`.
463
- *
464
- * This helper handles: the chunk loop, currentBlock flush transitions, usage metadata
465
- * decoding (`calculateCost` included), tool-call id collision avoidance, finish-reason
466
- * mapping, and the abort/stop-reason post-checks that re-throw to bubble into the
467
- * caller's catch.
468
- */
469
- async function consumeGoogleStream(args) {
470
- const { googleStream, output, stream, model, options, retainTextSignature, onFirstToken } = args;
471
- const blocks = output.content;
472
- const blockIndex = () => blocks.length - 1;
473
- let currentBlock = null;
474
- let thinkingStripper = null;
475
- let firstTokenSeen = false;
476
- let sawFinishReason = false;
477
- const flushCurrent = () => {
478
- if (!currentBlock) return;
479
- if (currentBlock.type === "thinking" && thinkingStripper) {
480
- const tail = thinkingStripper.flush();
481
- if (tail) {
482
- currentBlock.thinking += tail;
483
- stream.push({
484
- type: "thinking_delta",
485
- contentIndex: blockIndex(),
486
- delta: tail,
487
- partial: output
488
- });
489
- }
490
- }
491
- thinkingStripper = null;
492
- pushBlockEndEvent(currentBlock, blockIndex(), output, stream);
493
- };
494
- for await (const chunk of googleStream) {
495
- if (chunk.error) {
496
- const message = `Google API stream error: ${chunk.error.message || chunk.error.status || "unknown error"}`;
497
- throw typeof chunk.error.code === "number" && chunk.error.code >= 400 ? new GoogleApiError(message, chunk.error.code) : new ProviderResponseError(message, {
498
- provider: model.provider,
499
- kind: "output"
500
- });
501
- }
502
- if (!chunk.candidates?.length && chunk.promptFeedback?.blockReason) {
503
- const detail = chunk.promptFeedback.blockReasonMessage;
504
- throw new ProviderResponseError(`Request blocked by Google (${chunk.promptFeedback.blockReason})${detail ? `: ${detail}` : ""}`, {
505
- provider: model.provider,
506
- kind: "content-blocked"
507
- });
508
- }
509
- const candidate = chunk.candidates?.[0];
510
- if (candidate?.content?.parts) for (const part of candidate.content.parts) {
511
- if (part.text !== void 0 && part.text !== "") {
512
- if (!firstTokenSeen) {
513
- firstTokenSeen = true;
514
- onFirstToken?.();
515
- }
516
- const isThinking = isThinkingPart(part);
517
- if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
518
- flushCurrent();
519
- currentBlock = startTextOrThinkingBlock(isThinking, output, stream);
520
- }
521
- if (currentBlock.type === "thinking") {
522
- thinkingStripper ??= new ThinkingFenceStripper();
523
- const cleaned = thinkingStripper.push(part.text);
524
- currentBlock.thinking += cleaned;
525
- currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
526
- if (cleaned) stream.push({
527
- type: "thinking_delta",
528
- contentIndex: blockIndex(),
529
- delta: cleaned,
530
- partial: output
531
- });
532
- } else {
533
- currentBlock.text += part.text;
534
- if (retainTextSignature) currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
535
- stream.push({
536
- type: "text_delta",
537
- contentIndex: blockIndex(),
538
- delta: part.text,
539
- partial: output
540
- });
541
- }
542
- } else if (part.text === "" && part.thoughtSignature && currentBlock && !part.functionCall) {
543
- if (currentBlock.type === "thinking") currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
544
- else if (retainTextSignature) currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
545
- }
546
- if (part.functionCall) {
547
- if (currentBlock) {
548
- flushCurrent();
549
- currentBlock = null;
550
- }
551
- const providedId = part.functionCall.id;
552
- const toolCall = {
553
- type: "toolCall",
554
- id: !providedId || output.content.some((b) => b.type === "toolCall" && b.id === providedId) ? nextToolCallId(part.functionCall.name || "tool") : providedId,
555
- name: part.functionCall.name || "",
556
- arguments: part.functionCall.args ?? {},
557
- ...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
558
- };
559
- output.content.push(toolCall);
560
- pushToolCallEvents(toolCall, blockIndex(), output, stream);
561
- }
562
- }
563
- if (candidate?.finishReason) {
564
- sawFinishReason = true;
565
- const mapped = mapStopReason(candidate.finishReason);
566
- if ((mapped === "stop" || mapped === "length") && output.content.some((b) => b.type === "toolCall")) output.stopReason = "toolUse";
567
- else {
568
- output.stopReason = mapped;
569
- if (mapped === "error") output.errorMessage = `Generation failed with finish reason: ${candidate.finishReason}`;
570
- }
571
- }
572
- if (chunk.usageMetadata) {
573
- const cachedTokens = chunk.usageMetadata.cachedContentTokenCount || 0;
574
- const thinkingTokens = chunk.usageMetadata.thoughtsTokenCount || 0;
575
- output.usage = {
576
- input: (chunk.usageMetadata.promptTokenCount || 0) - cachedTokens,
577
- output: (chunk.usageMetadata.candidatesTokenCount || 0) + thinkingTokens,
578
- cacheRead: cachedTokens,
579
- cacheWrite: 0,
580
- totalTokens: chunk.usageMetadata.totalTokenCount || 0,
581
- ...thinkingTokens > 0 ? { reasoningTokens: thinkingTokens } : {},
582
- cost: {
583
- input: 0,
584
- output: 0,
585
- cacheRead: 0,
586
- cacheWrite: 0,
587
- total: 0
588
- }
589
- };
590
- calculateCost(model, output.usage, output.timestamp);
591
- }
592
- }
593
- flushCurrent();
594
- if (options?.signal?.aborted) throw new AbortError();
595
- if (!sawFinishReason) throw new ProviderResponseError("Google API stream ended without a finish reason (connection dropped or response truncated)", {
596
- provider: model.provider,
597
- kind: "incomplete-stream"
598
- });
599
- if (output.stopReason === "aborted" || output.stopReason === "error") throw new ProviderResponseError(output.errorMessage ?? "An unknown error occurred", {
600
- provider: model.provider,
601
- kind: "output"
602
- });
603
- }
604
- /**
605
- * Build the `GenerateContentParameters` payload for the public Gemini API and Vertex AI.
606
- * Both surfaces accept the same `GenerateContentConfig` shape — every numeric/string knob,
607
- * tool-config, thinking-config, and system-instruction conversion is identical.
608
- *
609
- * `google-gemini-cli` is NOT routed through here: its `CloudCodeAssistRequest` body has a
610
- * distinct top-level shape (project/request/requestType) and a different thinking-config
611
- * placement on `generationConfig`.
612
- */
613
- function buildGoogleGenerateContentParams(model, context, options) {
614
- const systemPrompts = normalizeSystemPrompts(context.systemPrompt);
615
- const contents = convertMessages(model, context);
616
- const generationConfig = {};
617
- if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
618
- if (options.maxTokens !== void 0) generationConfig.maxOutputTokens = options.maxTokens;
619
- if (options.topP !== void 0) generationConfig.topP = options.topP;
620
- if (options.topK !== void 0) generationConfig.topK = options.topK;
621
- if (options.minP !== void 0) generationConfig.minP = options.minP;
622
- if (options.presencePenalty !== void 0) generationConfig.presencePenalty = options.presencePenalty;
623
- if (options.repetitionPenalty !== void 0) generationConfig.repetitionPenalty = options.repetitionPenalty;
624
- const config = {
625
- ...Object.keys(generationConfig).length > 0 && generationConfig,
626
- ...systemPrompts.length > 0 && { systemInstruction: { parts: systemPrompts.map((text) => ({ text })) } },
627
- ...context.tools && context.tools.length > 0 && { tools: convertTools(context.tools, model) }
628
- };
629
- if (model.provider === "google" && shouldSendServiceTier(options.serviceTier, model.provider)) config.serviceTier = options.serviceTier;
630
- if (context.tools && context.tools.length > 0 && options.toolChoice) {
631
- const choice = options.toolChoice;
632
- if (typeof choice === "string") {
633
- const mode = mapToolChoice(choice);
634
- if (mode !== "AUTO") config.toolConfig = { functionCallingConfig: { mode } };
635
- } else config.toolConfig = { functionCallingConfig: {
636
- mode: "ANY",
637
- allowedFunctionNames: [...choice.allowedFunctionNames]
638
- } };
639
- } else config.toolConfig = void 0;
640
- const thinking = options.thinking;
641
- if (thinking && model.reasoning && (thinking.enabled || thinking.level !== void 0 || thinking.budgetTokens !== void 0)) {
642
- const cfg = { includeThoughts: thinking.enabled && !options.hideThinkingSummary };
643
- if (thinking.level !== void 0) cfg.thinkingLevel = thinking.level;
644
- else if (thinking.budgetTokens !== void 0) cfg.thinkingBudget = thinking.budgetTokens;
645
- config.thinkingConfig = cfg;
646
- }
647
- if (options.signal) {
648
- if (options.signal.aborted) throw new AbortError("Request aborted");
649
- config.abortSignal = options.signal;
650
- }
651
- if (options.cachedContent !== void 0) {
652
- if (options.cachedContent.trim().length === 0) throw new ValidationError("cachedContent must not be blank");
653
- const incompatibleFields = [
654
- config.systemInstruction !== void 0 && "systemInstruction",
655
- config.tools !== void 0 && "tools",
656
- config.toolConfig !== void 0 && "toolConfig"
657
- ].filter((field) => Boolean(field));
658
- if (incompatibleFields.length > 0) throw new ValidationError(`cachedContent cannot be combined with request-level ${incompatibleFields.join(", ")}`);
659
- config.cachedContent = options.cachedContent;
660
- }
661
- return {
662
- model: model.id,
663
- contents,
664
- config
665
- };
666
- }
667
- function streamGoogleGenAI(args) {
668
- const { model, options, api, retainTextSignature, prepare } = args;
669
- const stream = new AssistantMessageEventStream();
670
- (async () => {
671
- const startTime = performance.now();
672
- let firstTokenTime;
673
- const output = {
674
- role: "assistant",
675
- content: [],
676
- api,
677
- provider: model.provider,
678
- model: model.id,
679
- usage: {
680
- input: 0,
681
- output: 0,
682
- cacheRead: 0,
683
- cacheWrite: 0,
684
- totalTokens: 0,
685
- cost: {
686
- input: 0,
687
- output: 0,
688
- cacheRead: 0,
689
- cacheWrite: 0,
690
- total: 0
691
- }
692
- },
693
- stopReason: "stop",
694
- timestamp: Date.now()
695
- };
696
- let rawRequestDump;
697
- try {
698
- const plan = await prepare();
699
- let params = plan.params;
700
- const replacement = await options?.onPayload?.(params, model);
701
- if (replacement !== void 0) params = replacement;
702
- rawRequestDump = {
703
- provider: model.provider,
704
- api: output.api,
705
- model: model.id,
706
- method: "POST",
707
- url: plan.url,
708
- body: params,
709
- headers: plan.headers
710
- };
711
- const bodyJson = JSON.stringify(paramsToWireBody(params));
712
- const fetchImpl = plan.fetch ?? options?.fetch ?? globalThis.fetch.bind(globalThis);
713
- const openStreamAt = async (requestUrl) => {
714
- const response = await fetchImpl(requestUrl, {
715
- method: "POST",
716
- headers: {
717
- ...plan.headers,
718
- "Content-Type": "application/json",
719
- Accept: "text/event-stream"
720
- },
721
- body: bodyJson,
722
- signal: options?.signal
723
- });
724
- if (!response.ok) {
725
- const errorText = await response.text().catch(() => "");
726
- throw new GoogleApiError(`Google API error (${response.status}): ${extractGoogleErrorMessage(errorText)}`, response.status, { headers: response.headers });
727
- }
728
- if (!response.body) throw new ProviderResponseError("Google API returned an empty response body", {
729
- provider: model.provider,
730
- kind: "empty-body"
731
- });
732
- return response.body;
733
- };
734
- const openStream = async () => {
735
- if (!plan.fallbackUrl) return openStreamAt(plan.url);
736
- try {
737
- return await openStreamAt(plan.url);
738
- } catch (error) {
739
- if (error instanceof GoogleApiError && error.status === 404) return openStreamAt(plan.fallbackUrl);
740
- throw error;
741
- }
742
- };
743
- let body = await openStream();
744
- stream.push({
745
- type: "start",
746
- partial: output
747
- });
748
- for (let emptyAttempt = 0;; emptyAttempt++) {
749
- await consumeGoogleStream({
750
- googleStream: readSseJson(body, options?.signal, (event) => options?.onSseEvent?.({
751
- event: event.event,
752
- data: event.data,
753
- raw: [...event.raw]
754
- }, model)),
755
- output,
756
- stream,
757
- model,
758
- options,
759
- retainTextSignature,
760
- onFirstToken: () => {
761
- firstTokenTime = performance.now();
762
- }
763
- });
764
- if (output.stopReason !== "stop" || hasMeaningfulGoogleContent(output) || options?.acceptEmptyResponse === true) break;
765
- if (emptyAttempt >= 2) throw new ProviderResponseError(`Google API returned an empty response (finishReason STOP with no content) after 3 attempts`, {
766
- provider: model.provider,
767
- kind: "empty-body"
768
- });
769
- try {
770
- await scheduler.wait(500 * 2 ** emptyAttempt, { signal: options?.signal });
771
- } catch {
772
- throw new AbortError();
773
- }
774
- resetGoogleStreamOutputForRetry(output);
775
- body = await openStream();
776
- }
777
- output.duration = performance.now() - startTime;
778
- if (firstTokenTime) output.ttft = firstTokenTime - startTime;
779
- stream.push({
780
- type: "done",
781
- reason: output.stopReason,
782
- message: output
783
- });
784
- stream.end();
785
- } catch (error) {
786
- const result = await finalize(error, {
787
- api: model.api,
788
- signal: options?.signal,
789
- rawRequestDump
790
- });
791
- output.stopReason = result.stopReason;
792
- output.errorStatus = result.status;
793
- output.errorId = result.id;
794
- output.errorMessage = result.message;
795
- output.duration = performance.now() - startTime;
796
- if (firstTokenTime) output.ttft = firstTokenTime - startTime;
797
- stream.push({
798
- type: "error",
799
- reason: output.stopReason,
800
- error: output
801
- });
802
- stream.end();
803
- }
804
- })();
805
- return stream;
806
- }
807
- /**
808
- * Lift the SDK's `params.config` fields out of `config` and place them where the
809
- * Gemini / Vertex AI REST API expects them on the request body. Mirrors the
810
- * generateContentParametersTo{Mldev,Vertex} transformation in @google/genai
811
- * for the subset of fields this codebase actually sets.
812
- *
813
- * `abortSignal` is intentionally dropped — the SDK propagates it via `fetch.signal`,
814
- * which our caller already wires up through `options.signal`.
815
- */
816
- function paramsToWireBody(params) {
817
- const body = { contents: params.contents };
818
- const config = params.config;
819
- if (!config) return body;
820
- if (config.systemInstruction !== void 0) body.systemInstruction = config.systemInstruction;
821
- if (config.tools !== void 0) body.tools = config.tools;
822
- if (config.toolConfig !== void 0) body.toolConfig = config.toolConfig;
823
- if (config.safetySettings !== void 0) body.safetySettings = config.safetySettings;
824
- if (config.cachedContent !== void 0) body.cachedContent = config.cachedContent;
825
- if (config.serviceTier !== void 0) body.serviceTier = config.serviceTier;
826
- const gen = {};
827
- if (config.temperature !== void 0) gen.temperature = config.temperature;
828
- if (config.maxOutputTokens !== void 0) gen.maxOutputTokens = config.maxOutputTokens;
829
- if (config.topP !== void 0) gen.topP = config.topP;
830
- if (config.topK !== void 0) gen.topK = config.topK;
831
- if (config.candidateCount !== void 0) gen.candidateCount = config.candidateCount;
832
- if (config.stopSequences !== void 0) gen.stopSequences = config.stopSequences;
833
- if (config.presencePenalty !== void 0) gen.presencePenalty = config.presencePenalty;
834
- if (config.frequencyPenalty !== void 0) gen.frequencyPenalty = config.frequencyPenalty;
835
- if (config.seed !== void 0) gen.seed = config.seed;
836
- if (config.responseMimeType !== void 0) gen.responseMimeType = config.responseMimeType;
837
- if (config.responseSchema !== void 0) gen.responseSchema = config.responseSchema;
838
- if (config.responseJsonSchema !== void 0) gen.responseJsonSchema = config.responseJsonSchema;
839
- if (config.responseModalities !== void 0) gen.responseModalities = config.responseModalities;
840
- if (config.thinkingConfig !== void 0) gen.thinkingConfig = config.thinkingConfig;
841
- const generationConfig = config;
842
- if (generationConfig.minP !== void 0) gen.minP = generationConfig.minP;
843
- if (generationConfig.repetitionPenalty !== void 0) gen.repetitionPenalty = generationConfig.repetitionPenalty;
844
- if (Object.keys(gen).length > 0) body.generationConfig = gen;
845
- return body;
846
- }
847
- function extractGoogleErrorMessage(errorText) {
848
- if (!errorText) return "Unknown error";
849
- try {
850
- const parsed = JSON.parse(errorText);
851
- if (parsed.error?.message) return parsed.error.message;
852
- } catch {}
853
- return errorText;
854
- }
855
- //#endregion
856
- export { isThinkingPart as a, nextToolCallId as c, retainThoughtSignature as d, startTextOrThinkingBlock as f, hasMeaningfulGoogleContent as i, pushBlockEndEvent as l, convertMessages as n, mapStopReasonString as o, streamGoogleGenAI as p, convertTools as r, mapToolChoice as s, buildGoogleGenerateContentParams as t, pushToolCallEvents as u };