@buoy-gg/agent-core 7.0.41 → 7.0.43

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 (201) hide show
  1. package/lib/commonjs/blocks/receipts.js +1 -761
  2. package/lib/commonjs/blocks/runId.js +1 -31
  3. package/lib/commonjs/blocks/types.js +1 -140
  4. package/lib/commonjs/blocks/uiTool.js +6 -1405
  5. package/lib/commonjs/catalog/catalog.g.js +5 -4556
  6. package/lib/commonjs/catalog/catalog.source.json +249 -0
  7. package/lib/commonjs/catalog/catalog.types.g.js +1 -46
  8. package/lib/commonjs/catalog/normalizeParams.js +2 -332
  9. package/lib/commonjs/catalog/signature.js +1 -68
  10. package/lib/commonjs/catalog/snapshotReads.js +1 -263
  11. package/lib/commonjs/catalog/toProviderTools.js +2 -145
  12. package/lib/commonjs/catalog/validateParams.js +1 -129
  13. package/lib/commonjs/context/buildContextPack.js +1 -489
  14. package/lib/commonjs/effects/digest.js +1 -34
  15. package/lib/commonjs/effects/ledger.js +1 -345
  16. package/lib/commonjs/engine/askGate.js +1 -287
  17. package/lib/commonjs/engine/effectFor.js +1 -223
  18. package/lib/commonjs/engine/evidence.js +3 -111
  19. package/lib/commonjs/engine/historyBudget.js +1 -363
  20. package/lib/commonjs/engine/retrieve.js +1 -214
  21. package/lib/commonjs/engine/runAgentTurn.js +8 -1836
  22. package/lib/commonjs/engine/systemPrompt.js +54 -163
  23. package/lib/commonjs/engine/textToolCalls.js +1 -276
  24. package/lib/commonjs/engine/tokenCalibration.js +1 -81
  25. package/lib/commonjs/engine/verify.js +4 -297
  26. package/lib/commonjs/index.js +1 -384
  27. package/lib/commonjs/policy/labels.js +1 -319
  28. package/lib/commonjs/policy/policy.js +1 -148
  29. package/lib/commonjs/policy/redact.js +1 -172
  30. package/lib/commonjs/providers/anthropic.js +3 -445
  31. package/lib/commonjs/providers/openai.js +4 -324
  32. package/lib/commonjs/providers/problem.js +1 -98
  33. package/lib/commonjs/providers/sse.js +1 -240
  34. package/lib/commonjs/providers/streamTimer.js +1 -123
  35. package/lib/commonjs/providers/transport.js +1 -123
  36. package/lib/commonjs/providers/types.js +1 -6
  37. package/lib/commonjs/providers/xhrStream.js +1 -212
  38. package/lib/commonjs/realNow.js +1 -0
  39. package/lib/commonjs/session.js +1 -393
  40. package/lib/commonjs/types.js +0 -1
  41. package/lib/module/blocks/receipts.js +1 -755
  42. package/lib/module/blocks/runId.js +1 -26
  43. package/lib/module/blocks/types.js +1 -134
  44. package/lib/module/blocks/uiTool.js +6 -1396
  45. package/lib/module/catalog/catalog.g.js +5 -4552
  46. package/lib/module/catalog/catalog.source.json +249 -0
  47. package/lib/module/catalog/catalog.types.g.js +1 -42
  48. package/lib/module/catalog/normalizeParams.js +2 -326
  49. package/lib/module/catalog/signature.js +1 -63
  50. package/lib/module/catalog/snapshotReads.js +1 -259
  51. package/lib/module/catalog/toProviderTools.js +2 -139
  52. package/lib/module/catalog/validateParams.js +1 -124
  53. package/lib/module/context/buildContextPack.js +1 -485
  54. package/lib/module/effects/digest.js +1 -29
  55. package/lib/module/effects/ledger.js +1 -339
  56. package/lib/module/engine/askGate.js +1 -280
  57. package/lib/module/engine/effectFor.js +1 -220
  58. package/lib/module/engine/evidence.js +3 -105
  59. package/lib/module/engine/historyBudget.js +1 -355
  60. package/lib/module/engine/retrieve.js +1 -210
  61. package/lib/module/engine/runAgentTurn.js +8 -1827
  62. package/lib/module/engine/systemPrompt.js +54 -157
  63. package/lib/module/engine/textToolCalls.js +1 -270
  64. package/lib/module/engine/tokenCalibration.js +1 -75
  65. package/lib/module/engine/verify.js +4 -289
  66. package/lib/module/index.js +1 -35
  67. package/lib/module/policy/labels.js +1 -312
  68. package/lib/module/policy/policy.js +1 -142
  69. package/lib/module/policy/redact.js +1 -165
  70. package/lib/module/providers/anthropic.js +3 -441
  71. package/lib/module/providers/openai.js +4 -320
  72. package/lib/module/providers/problem.js +1 -92
  73. package/lib/module/providers/sse.js +1 -231
  74. package/lib/module/providers/streamTimer.js +1 -118
  75. package/lib/module/providers/transport.js +1 -119
  76. package/lib/module/providers/types.js +1 -4
  77. package/lib/module/providers/xhrStream.js +1 -207
  78. package/lib/module/realNow.js +1 -0
  79. package/lib/module/session.js +1 -369
  80. package/lib/module/types.js +0 -1
  81. package/lib/typescript/catalog/catalog.g.d.ts +3 -3
  82. package/lib/typescript/catalog/catalog.types.g.d.ts +3 -2
  83. package/lib/typescript/providers/problem.d.ts +0 -20
  84. package/lib/typescript/providers/streamTimer.d.ts +0 -24
  85. package/lib/typescript/realNow.d.ts +18 -0
  86. package/lib/web/index.mjs +52 -53
  87. package/package.json +1 -1
  88. package/lib/commonjs/blocks/receipts.js.map +0 -1
  89. package/lib/commonjs/blocks/runId.js.map +0 -1
  90. package/lib/commonjs/blocks/types.js.map +0 -1
  91. package/lib/commonjs/blocks/uiTool.js.map +0 -1
  92. package/lib/commonjs/catalog/catalog.g.js.map +0 -1
  93. package/lib/commonjs/catalog/catalog.types.g.js.map +0 -1
  94. package/lib/commonjs/catalog/normalizeParams.js.map +0 -1
  95. package/lib/commonjs/catalog/signature.js.map +0 -1
  96. package/lib/commonjs/catalog/snapshotReads.js.map +0 -1
  97. package/lib/commonjs/catalog/toProviderTools.js.map +0 -1
  98. package/lib/commonjs/catalog/validateParams.js.map +0 -1
  99. package/lib/commonjs/context/buildContextPack.js.map +0 -1
  100. package/lib/commonjs/effects/digest.js.map +0 -1
  101. package/lib/commonjs/effects/ledger.js.map +0 -1
  102. package/lib/commonjs/engine/askGate.js.map +0 -1
  103. package/lib/commonjs/engine/effectFor.js.map +0 -1
  104. package/lib/commonjs/engine/evidence.js.map +0 -1
  105. package/lib/commonjs/engine/historyBudget.js.map +0 -1
  106. package/lib/commonjs/engine/retrieve.js.map +0 -1
  107. package/lib/commonjs/engine/runAgentTurn.js.map +0 -1
  108. package/lib/commonjs/engine/systemPrompt.js.map +0 -1
  109. package/lib/commonjs/engine/textToolCalls.js.map +0 -1
  110. package/lib/commonjs/engine/tokenCalibration.js.map +0 -1
  111. package/lib/commonjs/engine/verify.js.map +0 -1
  112. package/lib/commonjs/index.js.map +0 -1
  113. package/lib/commonjs/policy/labels.js.map +0 -1
  114. package/lib/commonjs/policy/policy.js.map +0 -1
  115. package/lib/commonjs/policy/redact.js.map +0 -1
  116. package/lib/commonjs/providers/anthropic.js.map +0 -1
  117. package/lib/commonjs/providers/openai.js.map +0 -1
  118. package/lib/commonjs/providers/problem.js.map +0 -1
  119. package/lib/commonjs/providers/sse.js.map +0 -1
  120. package/lib/commonjs/providers/streamTimer.js.map +0 -1
  121. package/lib/commonjs/providers/transport.js.map +0 -1
  122. package/lib/commonjs/providers/types.js.map +0 -1
  123. package/lib/commonjs/providers/xhrStream.js.map +0 -1
  124. package/lib/commonjs/session.js.map +0 -1
  125. package/lib/commonjs/types.js.map +0 -1
  126. package/lib/module/blocks/receipts.js.map +0 -1
  127. package/lib/module/blocks/runId.js.map +0 -1
  128. package/lib/module/blocks/types.js.map +0 -1
  129. package/lib/module/blocks/uiTool.js.map +0 -1
  130. package/lib/module/catalog/catalog.g.js.map +0 -1
  131. package/lib/module/catalog/catalog.types.g.js.map +0 -1
  132. package/lib/module/catalog/normalizeParams.js.map +0 -1
  133. package/lib/module/catalog/signature.js.map +0 -1
  134. package/lib/module/catalog/snapshotReads.js.map +0 -1
  135. package/lib/module/catalog/toProviderTools.js.map +0 -1
  136. package/lib/module/catalog/validateParams.js.map +0 -1
  137. package/lib/module/context/buildContextPack.js.map +0 -1
  138. package/lib/module/effects/digest.js.map +0 -1
  139. package/lib/module/effects/ledger.js.map +0 -1
  140. package/lib/module/engine/askGate.js.map +0 -1
  141. package/lib/module/engine/effectFor.js.map +0 -1
  142. package/lib/module/engine/evidence.js.map +0 -1
  143. package/lib/module/engine/historyBudget.js.map +0 -1
  144. package/lib/module/engine/retrieve.js.map +0 -1
  145. package/lib/module/engine/runAgentTurn.js.map +0 -1
  146. package/lib/module/engine/systemPrompt.js.map +0 -1
  147. package/lib/module/engine/textToolCalls.js.map +0 -1
  148. package/lib/module/engine/tokenCalibration.js.map +0 -1
  149. package/lib/module/engine/verify.js.map +0 -1
  150. package/lib/module/index.js.map +0 -1
  151. package/lib/module/policy/labels.js.map +0 -1
  152. package/lib/module/policy/policy.js.map +0 -1
  153. package/lib/module/policy/redact.js.map +0 -1
  154. package/lib/module/providers/anthropic.js.map +0 -1
  155. package/lib/module/providers/openai.js.map +0 -1
  156. package/lib/module/providers/problem.js.map +0 -1
  157. package/lib/module/providers/sse.js.map +0 -1
  158. package/lib/module/providers/streamTimer.js.map +0 -1
  159. package/lib/module/providers/transport.js.map +0 -1
  160. package/lib/module/providers/types.js.map +0 -1
  161. package/lib/module/providers/xhrStream.js.map +0 -1
  162. package/lib/module/session.js.map +0 -1
  163. package/lib/module/types.js.map +0 -1
  164. package/lib/typescript/blocks/receipts.d.ts.map +0 -1
  165. package/lib/typescript/blocks/runId.d.ts.map +0 -1
  166. package/lib/typescript/blocks/types.d.ts.map +0 -1
  167. package/lib/typescript/blocks/uiTool.d.ts.map +0 -1
  168. package/lib/typescript/catalog/catalog.g.d.ts.map +0 -1
  169. package/lib/typescript/catalog/catalog.types.g.d.ts.map +0 -1
  170. package/lib/typescript/catalog/normalizeParams.d.ts.map +0 -1
  171. package/lib/typescript/catalog/signature.d.ts.map +0 -1
  172. package/lib/typescript/catalog/snapshotReads.d.ts.map +0 -1
  173. package/lib/typescript/catalog/toProviderTools.d.ts.map +0 -1
  174. package/lib/typescript/catalog/validateParams.d.ts.map +0 -1
  175. package/lib/typescript/context/buildContextPack.d.ts.map +0 -1
  176. package/lib/typescript/effects/digest.d.ts.map +0 -1
  177. package/lib/typescript/effects/ledger.d.ts.map +0 -1
  178. package/lib/typescript/engine/askGate.d.ts.map +0 -1
  179. package/lib/typescript/engine/effectFor.d.ts.map +0 -1
  180. package/lib/typescript/engine/evidence.d.ts.map +0 -1
  181. package/lib/typescript/engine/historyBudget.d.ts.map +0 -1
  182. package/lib/typescript/engine/retrieve.d.ts.map +0 -1
  183. package/lib/typescript/engine/runAgentTurn.d.ts.map +0 -1
  184. package/lib/typescript/engine/systemPrompt.d.ts.map +0 -1
  185. package/lib/typescript/engine/textToolCalls.d.ts.map +0 -1
  186. package/lib/typescript/engine/tokenCalibration.d.ts.map +0 -1
  187. package/lib/typescript/engine/verify.d.ts.map +0 -1
  188. package/lib/typescript/index.d.ts.map +0 -1
  189. package/lib/typescript/policy/labels.d.ts.map +0 -1
  190. package/lib/typescript/policy/policy.d.ts.map +0 -1
  191. package/lib/typescript/policy/redact.d.ts.map +0 -1
  192. package/lib/typescript/providers/anthropic.d.ts.map +0 -1
  193. package/lib/typescript/providers/openai.d.ts.map +0 -1
  194. package/lib/typescript/providers/problem.d.ts.map +0 -1
  195. package/lib/typescript/providers/sse.d.ts.map +0 -1
  196. package/lib/typescript/providers/streamTimer.d.ts.map +0 -1
  197. package/lib/typescript/providers/transport.d.ts.map +0 -1
  198. package/lib/typescript/providers/types.d.ts.map +0 -1
  199. package/lib/typescript/providers/xhrStream.d.ts.map +0 -1
  200. package/lib/typescript/session.d.ts.map +0 -1
  201. package/lib/typescript/types.d.ts.map +0 -1
@@ -1,327 +1,7 @@
1
- "use strict";
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.createOpenAIProvider=createOpenAIProvider;var _sse=require("./sse");var _streamTimer=require("./streamTimer");var _transport=require("./transport");var _problem=require("./problem");function toWireMessages(o,d){const e=[{role:"system",content:o}];for(const t of d){if(t.role==="user"){e.push({role:"user",content:t.text})}else if(t.role==="assistant"){e.push({role:"assistant",content:t.text||null,...t.toolCalls?.length?{tool_calls:t.toolCalls.map(a=>({id:a.id,type:"function",function:{name:a.name,arguments:JSON.stringify(a.input)}}))}:{}})}else{for(const a of t.results){e.push({role:"tool",tool_call_id:a.toolCallId,content:a.content})}}}return e}function withActionsBlock(o){const d=o.inputSchema.properties.action;return{...o.inputSchema,properties:{...o.inputSchema.properties,action:{...d,description:`Which action to run.
2
2
 
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.createOpenAIProvider = createOpenAIProvider;
7
- var _sse = require("./sse");
8
- var _streamTimer = require("./streamTimer");
9
- var _transport = require("./transport");
10
- var _problem = require("./problem");
11
- /**
12
- * OpenAI chat-completions protocol.
13
- *
14
- * The differences from Anthropic that actually matter to the code:
15
- * - Tool results are their own `{role:"tool", tool_call_id, content}` MESSAGE,
16
- * not blocks inside a user message.
17
- * - Tool arguments arrive as a JSON STRING, streamed in fragments, and are
18
- * keyed by an `index` that is stable across deltas while `id`/`name` only
19
- * appear on the first fragment.
20
- * - The stream DOES have a `data: [DONE]` sentinel, unlike Anthropic's.
21
- *
22
- * This adapter also serves Azure and any OpenAI-compatible org gateway, which
23
- * is the common shape for an internal LLM proxy. Note Anthropic's own
24
- * OpenAI-compatibility endpoint is explicitly not production-ready and silently
25
- * ignores several fields — use the native Anthropic adapter for Anthropic.
26
- *
27
- * THE 1024-CHAR TRAP. Azure caps a function description at 1024 chars, so
28
- * this adapter trims to fit. The catalog renders a tool's summary FIRST and
29
- * its `Actions:` list LAST, and every tool's full description is longer than
30
- * the cap — so trimming `t.description` silently removed every action line
31
- * for 23 of the 24 tools — the 24th kept one line of sixteen — measured
32
- * against the catalog as it is. A model on this protocol (api.openai.com, Azure,
33
- * OpenRouter, fal — every row of the model-floor sweep) saw a summary cut
34
- * mid-sentence and a bare `action` enum: no per-action summary, no
35
- * [DESTRUCTIVE] / [changes state] tag, no "prefer X over Y" guidance, and a
36
- * catalog wording change could not move its score. So the description is
37
- * the SUMMARY only, and the `Actions:` block goes into
38
- * `parameters.properties.action.description`, which nothing caps.
39
- */
3
+ ${o.actionsBlock}`}}}}function createOpenAIProvider(o){const d=(0,_transport.createTransport)(o);return{protocol:"openai",async*send(e){const t=(0,_streamTimer.createStreamTimer)(e.signal,o);const a={truncated:false};try{const l={"content-type":"application/json",...await(o.headers?.()??{})};if(o.apiKey&&!l.Authorization&&!l["api-key"]){l.Authorization=`Bearer ${o.apiKey}`}const c=await d.open({headers:l,signal:t.signal,body:JSON.stringify({model:e.model,max_tokens:e.maxTokens,stream:true,stream_options:{include_usage:true},messages:toWireMessages(e.systemVolatile?`${e.system}
40
4
 
41
- function toWireMessages(system, messages) {
42
- const out = [{
43
- role: "system",
44
- content: system
45
- }];
46
- for (const m of messages) {
47
- if (m.role === "user") {
48
- out.push({
49
- role: "user",
50
- content: m.text
51
- });
52
- } else if (m.role === "assistant") {
53
- out.push({
54
- role: "assistant",
55
- content: m.text || null,
56
- ...(m.toolCalls?.length ? {
57
- tool_calls: m.toolCalls.map(c => ({
58
- id: c.id,
59
- type: "function",
60
- function: {
61
- name: c.name,
62
- arguments: JSON.stringify(c.input)
63
- }
64
- }))
65
- } : {})
66
- });
67
- } else {
68
- // One message per result, not one message with many.
69
- for (const r of m.results) {
70
- out.push({
71
- role: "tool",
72
- tool_call_id: r.toolCallId,
73
- content: r.content
74
- });
75
- }
76
- }
77
- }
78
- return out;
79
- }
5
+ ---
80
6
 
81
- /**
82
- * The tool's input schema with the `Actions:` block on the `action`
83
- * property — the uncapped home for the per-action lines (header note).
84
- */
85
- function withActionsBlock(t) {
86
- const action = t.inputSchema.properties.action;
87
- return {
88
- ...t.inputSchema,
89
- properties: {
90
- ...t.inputSchema.properties,
91
- action: {
92
- ...action,
93
- description: `Which action to run.\n\n${t.actionsBlock}`
94
- }
95
- }
96
- };
97
- }
98
- function createOpenAIProvider(config) {
99
- // One per provider, so the `auto` transport decision is made once and not
100
- // re-learned (and re-buffered) at the start of every turn.
101
- const transport = (0, _transport.createTransport)(config);
102
- return {
103
- protocol: "openai",
104
- async *send(req) {
105
- const timer = (0, _streamTimer.createStreamTimer)(req.signal, config);
106
- const status = {
107
- truncated: false
108
- };
109
- try {
110
- const headers = {
111
- "content-type": "application/json",
112
- ...(await (config.headers?.() ?? {}))
113
- };
114
- if (config.apiKey && !headers.Authorization && !headers["api-key"]) {
115
- headers.Authorization = `Bearer ${config.apiKey}`;
116
- }
117
- const stream = await transport.open({
118
- headers,
119
- // The timer's signal, not the caller's: it aborts on the user's Stop
120
- // AND on either clock running out. See providers/streamTimer.ts.
121
- signal: timer.signal,
122
- body: JSON.stringify({
123
- model: req.model,
124
- max_tokens: req.maxTokens,
125
- stream: true,
126
- stream_options: {
127
- include_usage: true
128
- },
129
- messages: toWireMessages(req.systemVolatile ? `${req.system}\n\n---\n\n${req.systemVolatile}` : req.system, req.messages),
130
- tools: req.tools.map(t => ({
131
- type: "function",
132
- function: {
133
- name: t.name,
134
- // Azure caps function descriptions at 1024 chars while Anthropic's
135
- // guidance asks for several sentences. Trim rather than 400 — but
136
- // trim the SUMMARY only: the action lines travel on `parameters`
137
- // (withActionsBlock), where nothing is capped. See the header.
138
- description: t.summaryDescription.slice(0, 1024),
139
- parameters: withActionsBlock(t)
140
- }
141
- })),
142
- ...config.requestOverrides
143
- })
144
- });
145
-
146
- // Headers are in: the connect clock stops here and the idle one starts.
147
- timer.connected();
148
- if (stream.problem) {
149
- yield {
150
- type: "error",
151
- message: stream.problem,
152
- kind: "provider",
153
- problem: stream.problemInfo
154
- };
155
- return;
156
- }
157
-
158
- // Keyed by the stream's `index`; id and name arrive only on the first
159
- // fragment, arguments accumulate across all of them.
160
- const pending = new Map();
161
- let stopReason;
162
- let usage;
163
- // The served model id, from the first chunk that names one. A gateway
164
- // resolves `gpt-4.1` to a dated snapshot, and that is the id a cost
165
- // table or a benchmark has to attribute a drift to.
166
- let model;
167
- /** The `[DONE]` sentinel; ends the read. See `sawTerminal` below. */
168
- let sawDone = false;
169
- const flush = function* () {
170
- for (const [, slot] of pending) {
171
- let input = {};
172
- try {
173
- input = slot.args ? JSON.parse(slot.args) : {};
174
- } catch {
175
- yield {
176
- type: "error",
177
- kind: "provider",
178
- // Carry the evidence. Without it this error says only THAT the
179
- // arguments were bad, and diagnosing it needs a live repro of a
180
- // model that may not be reachable any more — a Sonnet bench run
181
- // produced 15 of these and left nothing to read. `length` here
182
- // means the model was cut off mid-argument and `max_tokens` is
183
- // the fix; anything else is a genuinely malformed stream.
184
- message: (0, _sse.unparseableMessage)(slot.name, slot.args, stopReason)
185
- };
186
- continue;
187
- }
188
- yield {
189
- type: "tool-call",
190
- call: {
191
- id: slot.id,
192
- name: slot.name,
193
- input
194
- }
195
- };
196
- }
197
- pending.clear();
198
- };
199
- for await (const ev of stream.frames({
200
- status,
201
- onFrame: timer.activity,
202
- signal: timer.signal
203
- })) {
204
- if (ev.data === "[DONE]") {
205
- sawDone = true;
206
- break;
207
- }
208
- let payload;
209
- try {
210
- payload = JSON.parse(ev.data);
211
- } catch {
212
- continue;
213
- }
214
- if (payload.error) {
215
- const err = payload.error;
216
- const message = err.message ?? "Provider error";
217
- const type = typeof err.code === "string" ? err.code : typeof err.type === "string" ? err.type : undefined;
218
- yield {
219
- type: "error",
220
- message,
221
- kind: "provider",
222
- problem: (0, _problem.classifyProblem)({
223
- type,
224
- message
225
- })
226
- };
227
- return;
228
- }
229
- if (!model && typeof payload.model === "string" && payload.model) model = payload.model;
230
- const u = payload.usage;
231
- if (u) {
232
- // `prompt_tokens_details.cached_tokens` is this protocol's cache
233
- // counter. Unlike Anthropic's it is INCLUDED in `prompt_tokens`
234
- // rather than reported beside it; it is still carried as
235
- // `cacheRead` so a cost table can price that slice at the
236
- // discounted rate.
237
- const details = u.prompt_tokens_details;
238
- const cached = details?.cached_tokens;
239
- usage = {
240
- input: typeof u.prompt_tokens === "number" ? u.prompt_tokens : 0,
241
- output: typeof u.completion_tokens === "number" ? u.completion_tokens : 0,
242
- ...(typeof cached === "number" ? {
243
- cacheRead: cached
244
- } : {})
245
- };
246
- }
247
- const choice = payload.choices?.[0];
248
- if (!choice) continue;
249
- if (choice.finish_reason) stopReason = choice.finish_reason;
250
- const delta = choice.delta;
251
- if (typeof delta?.content === "string" && delta.content) {
252
- yield {
253
- type: "text",
254
- delta: delta.content
255
- };
256
- }
257
- const calls = delta?.tool_calls;
258
- for (const c of calls ?? []) {
259
- const index = c.index ?? 0;
260
- const fn = c.function;
261
- const slot = pending.get(index) ?? {
262
- id: "",
263
- name: "",
264
- args: ""
265
- };
266
- if (c.id) slot.id = c.id;
267
- if (fn?.name) slot.name = fn.name;
268
- if (typeof fn?.arguments === "string") slot.args += fn.arguments;
269
- pending.set(index, slot);
270
- }
271
- }
272
-
273
- /**
274
- * Did the provider actually say it was finished?
275
- *
276
- * `[DONE]` is the transport sentinel. `finish_reason` counts too, and is
277
- * the stronger claim: it is the model's own statement of why it stopped,
278
- * while `[DONE]` only says the SSE stream closed. Plenty of
279
- * OpenAI-compatible gateways send one and not the other, and refusing
280
- * either shape would break working endpoints for no safety gain. NEITHER
281
- * arriving is the case that matters — bare EOF, which used to be read as
282
- * success, and which is how a complete-looking `storage.setItem` came out
283
- * of a cut connection and ran.
284
- */
285
- const sawTerminal = sawDone || stopReason !== undefined;
286
- if (!sawTerminal) {
287
- // Nothing is flushed: the accumulated arguments may be a whole JSON
288
- // object and still be half a plan. Text already yielded stays on
289
- // screen; the engine shows it and offers Continue.
290
- yield {
291
- type: "error",
292
- message: (0, _sse.truncatedMessage)(status.truncated),
293
- kind: "truncated"
294
- };
295
- return;
296
- }
297
- yield* flush();
298
- yield {
299
- type: "done",
300
- outcome: stopReason === "length" ? "output-limited" : "completed",
301
- stopReason,
302
- usage,
303
- model
304
- };
305
- } catch (err) {
306
- // The user's Stop wins the label even if a clock fired in the same
307
- // tick: they know why the turn ended, and "timed out" would be a lie.
308
- if (req.signal?.aborted) throw err;
309
- const message = timer.message();
310
- if (message) {
311
- yield {
312
- type: "error",
313
- message,
314
- kind: "timeout"
315
- };
316
- return;
317
- }
318
- // A genuine transport failure — DNS, refused connection, TLS. It has
319
- // always propagated to the failed-turn card, and still does.
320
- throw err;
321
- } finally {
322
- timer.dispose();
323
- }
324
- }
325
- };
326
- }
327
- //# sourceMappingURL=openai.js.map
7
+ ${e.systemVolatile}`:e.system,e.messages),tools:e.tools.map(n=>({type:"function",function:{name:n.name,description:n.summaryDescription.slice(0,1024),parameters:withActionsBlock(n)}})),...o.requestOverrides})});t.connected();if(c.problem){yield{type:"error",message:c.problem,kind:"provider",problem:c.problemInfo};return}const f=new Map;let u;let k;let _;let b=false;const v=function*(){for(const[,n]of f){let r={};try{r=n.args?JSON.parse(n.args):{}}catch{yield{type:"error",kind:"provider",message:(0,_sse.unparseableMessage)(n.name,n.args,u)};continue}yield{type:"tool-call",call:{id:n.id,name:n.name,input:r}}}f.clear()};for await(const n of c.frames({status:a,onFrame:t.activity,signal:t.signal})){if(n.data==="[DONE]"){b=true;break}let r;try{r=JSON.parse(n.data)}catch{continue}if(r.error){const s=r.error;const i=s.message??"Provider error";const m=typeof s.code==="string"?s.code:typeof s.type==="string"?s.type:void 0;yield{type:"error",message:i,kind:"provider",problem:(0,_problem.classifyProblem)({type:m,message:i})};return}if(!_&&typeof r.model==="string"&&r.model)_=r.model;const p=r.usage;if(p){const s=p.prompt_tokens_details;const i=s?.cached_tokens;k={input:typeof p.prompt_tokens==="number"?p.prompt_tokens:0,output:typeof p.completion_tokens==="number"?p.completion_tokens:0,...typeof i==="number"?{cacheRead:i}:{}}}const y=r.choices?.[0];if(!y)continue;if(y.finish_reason)u=y.finish_reason;const g=y.delta;if(typeof g?.content==="string"&&g.content){yield{type:"text",delta:g.content}}const x=g?.tool_calls;for(const s of x??[]){const i=s.index??0;const m=s.function;const h=f.get(i)??{id:"",name:"",args:""};if(s.id)h.id=s.id;if(m?.name)h.name=m.name;if(typeof m?.arguments==="string")h.args+=m.arguments;f.set(i,h)}}const w=b||u!==void 0;if(!w){yield{type:"error",message:(0,_sse.truncatedMessage)(a.truncated),kind:"truncated"};return}yield*v();yield{type:"done",outcome:u==="length"?"output-limited":"completed",stopReason:u,usage:k,model:_}}catch(l){if(e.signal?.aborted)throw l;const c=t.message();if(c){yield{type:"error",message:c,kind:"timeout"};return}throw l}finally{t.dispose()}}}}
@@ -1,98 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.classifyProblem = classifyProblem;
7
- exports.errorTypeOf = errorTypeOf;
8
- exports.parseRetryAfter = parseRetryAfter;
9
- /**
10
- * What kind of failure a provider reported — decided once, from the status,
11
- * the error type and the message, so the engine can act on the KIND rather
12
- * than grep a string.
13
- *
14
- * Only two kinds are acted on, and both only when nothing has been generated:
15
- *
16
- * - `throttled` — 429 / 529 / 503, a `rate_limit_error` or `overloaded_error`
17
- * frame, or a body that says so. Waiting and asking again is the right move;
18
- * the request never reached a model.
19
- * - `overflow` — the provider refused the request as too big. Trimming older
20
- * history and asking once more is the right move; the proactive budget is
21
- * an estimate (chars ÷ 4) and JSON tokenizes worse than prose.
22
- *
23
- * Everything else — auth, a bad schema, an unknown model, a mid-answer
24
- * `api_error` — is reported and NOT retried. The phrase lists are the union
25
- * observed across provider responses by the Strands SDK (harness-sdk
26
- * `381ab48`, `models/anthropic.ts` + `models/openai/errors.ts`, Apache-2.0),
27
- * matched case-insensitively on the lowered message.
28
- */
29
-
30
- const THROTTLE_STATUSES = new Set([429, 503, 529]);
31
- const AUTH_STATUSES = new Set([401, 403]);
32
-
33
- /** Provider error `type` values (Anthropic frames, OpenAI `error.type` / `code`). */
34
- const THROTTLE_TYPES = new Set(["overloaded_error", "rate_limit_error", "rate_limit_exceeded", "insufficient_quota", "server_overloaded"]);
35
- const AUTH_TYPES = new Set(["authentication_error", "permission_error", "invalid_api_key"]);
36
- const OVERFLOW_TYPES = new Set(["request_too_large", "context_length_exceeded"]);
37
- const THROTTLE_PHRASES = ["rate_limit_exceeded", "rate limit", "too many requests", "overloaded", "capacity", "try again later"];
38
- const OVERFLOW_PHRASES = [
39
- // Anthropic
40
- "prompt is too long", "input too long", "input is too long", "input length exceeds context window", "input and output tokens exceed your context limit",
41
- // OpenAI and compatible gateways
42
- "maximum context length", "context_length_exceeded", "too many tokens", "context length", "input is too long for requested model", "input length and `max_tokens` exceed context limit", "too many total text bytes", "exceed customer model maximum"];
43
- function classifyProblem(input) {
44
- const lowered = input.message.toLowerCase();
45
- const type = input.type?.toLowerCase();
46
- const retryAfterMs = parseRetryAfter(input.retryAfter);
47
- const withStatus = kind => ({
48
- kind,
49
- ...(input.status !== undefined ? {
50
- status: input.status
51
- } : {}),
52
- ...(retryAfterMs !== undefined ? {
53
- retryAfterMs
54
- } : {})
55
- });
56
- if (input.status !== undefined && AUTH_STATUSES.has(input.status)) return withStatus("auth");
57
- if (type && AUTH_TYPES.has(type)) return withStatus("auth");
58
- if (input.status !== undefined && THROTTLE_STATUSES.has(input.status)) return withStatus("throttled");
59
- if (type && THROTTLE_TYPES.has(type)) return withStatus("throttled");
60
- if (type && OVERFLOW_TYPES.has(type)) return withStatus("overflow");
61
- // Overflow before throttling on phrases: "context length" is more specific
62
- // than "capacity", and a 400 that says both is about the size.
63
- if (OVERFLOW_PHRASES.some(p => lowered.includes(p))) return withStatus("overflow");
64
- if (THROTTLE_PHRASES.some(p => lowered.includes(p))) return withStatus("throttled");
65
- return withStatus("other");
66
- }
67
-
68
- /**
69
- * `Retry-After` is either delay-seconds or an HTTP-date. Anything unparseable
70
- * or in the past is undefined, so the caller falls back to its own backoff.
71
- */
72
- function parseRetryAfter(value) {
73
- if (!value) return undefined;
74
- const trimmed = value.trim();
75
- if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1000;
76
- const at = Date.parse(trimmed);
77
- if (Number.isNaN(at)) return undefined;
78
- const ms = at - Date.now();
79
- return ms > 0 ? ms : undefined;
80
- }
81
-
82
- /**
83
- * Pull the provider's error `type` out of an error body, for the HTTP path
84
- * where the body is JSON like `{"error":{"type":"overloaded_error",…}}` or
85
- * `{"error":{"code":"context_length_exceeded",…}}`. Returns undefined for
86
- * anything that is not that shape; the message phrases still apply.
87
- */
88
- function errorTypeOf(body) {
89
- try {
90
- const parsed = JSON.parse(body);
91
- const err = typeof parsed.error === "object" && parsed.error ? parsed.error : undefined;
92
- const type = err?.type ?? err?.code ?? parsed.type;
93
- return typeof type === "string" ? type : undefined;
94
- } catch {
95
- return undefined;
96
- }
97
- }
98
- //# sourceMappingURL=problem.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.classifyProblem=classifyProblem;exports.errorTypeOf=errorTypeOf;exports.parseRetryAfter=parseRetryAfter;var _realNow=require("../realNow");const THROTTLE_STATUSES=new Set([429,503,529]);const AUTH_STATUSES=new Set([401,403]);const THROTTLE_TYPES=new Set(["overloaded_error","rate_limit_error","rate_limit_exceeded","insufficient_quota","server_overloaded"]);const AUTH_TYPES=new Set(["authentication_error","permission_error","invalid_api_key"]);const OVERFLOW_TYPES=new Set(["request_too_large","context_length_exceeded"]);const THROTTLE_PHRASES=["rate_limit_exceeded","rate limit","too many requests","overloaded","capacity","try again later"];const OVERFLOW_PHRASES=["prompt is too long","input too long","input is too long","input length exceeds context window","input and output tokens exceed your context limit","maximum context length","context_length_exceeded","too many tokens","context length","input is too long for requested model","input length and `max_tokens` exceed context limit","too many total text bytes","exceed customer model maximum"];function classifyProblem(e){const r=e.message.toLowerCase();const t=e.type?.toLowerCase();const o=parseRetryAfter(e.retryAfter);const n=s=>({kind:s,...e.status!==void 0?{status:e.status}:{},...o!==void 0?{retryAfterMs:o}:{}});if(e.status!==void 0&&AUTH_STATUSES.has(e.status))return n("auth");if(t&&AUTH_TYPES.has(t))return n("auth");if(e.status!==void 0&&THROTTLE_STATUSES.has(e.status))return n("throttled");if(t&&THROTTLE_TYPES.has(t))return n("throttled");if(t&&OVERFLOW_TYPES.has(t))return n("overflow");if(OVERFLOW_PHRASES.some(s=>r.includes(s)))return n("overflow");if(THROTTLE_PHRASES.some(s=>r.includes(s)))return n("throttled");return n("other")}function parseRetryAfter(e){if(!e)return void 0;const r=e.trim();if(/^\d+$/.test(r))return Number(r)*1e3;const t=Date.parse(r);if(Number.isNaN(t))return void 0;const o=t-(0,_realNow.realNow)();return o>0?o:void 0}function errorTypeOf(e){try{const r=JSON.parse(e);const t=typeof r.error==="object"&&r.error?r.error:void 0;const o=t?.type??t?.code??r.type;return typeof o==="string"?o:void 0}catch{return void 0}}
@@ -1,240 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.errorBody = errorBody;
7
- exports.framesFrom = framesFrom;
8
- exports.nonStreamProblem = nonStreamProblem;
9
- exports.readSse = readSse;
10
- exports.truncatedMessage = truncatedMessage;
11
- exports.unparseableMessage = unparseableMessage;
12
- /**
13
- * SSE reading, with the React Native reality baked in.
14
- *
15
- * RN's built-in `fetch` does not implement `response.body`. Under Expo you get
16
- * a real `ReadableStream` because `expo/fetch` is the global — but
17
- * `EXPO_PUBLIC_USE_RN_FETCH=1` reverts that, and the bare-RN, NativeScript and
18
- * TV-CLI lanes never had it. So `readSse` degrades to reading the whole body
19
- * and replaying it as events rather than failing: a non-streaming answer is a
20
- * slower chat, while a hard failure is no chat at all.
21
- *
22
- * THE TWO PATHS MUST AGREE. They did not. The buffered path appended "\n\n" to
23
- * the body before parsing, which turns an unterminated final frame — the exact
24
- * signature of a cut connection — into a well-formed event. The streaming path
25
- * discarded that same frame, as the SSE spec requires. So one lane invented a
26
- * complete answer where the other saw a broken one. Now both discard it and
27
- * both RECORD it (`SseReadStatus.truncated`), because "was this reply whole?"
28
- * is a question the engine has to answer before it runs anything.
29
- */
30
-
31
- function* parseChunk(buffer, onFrame) {
32
- let rest = buffer;
33
- let idx;
34
- // Frames are separated by a blank line. \r\n\r\n is legal too.
35
- while ((idx = rest.search(/\r?\n\r?\n/)) !== -1) {
36
- const raw = rest.slice(0, idx);
37
- rest = rest.slice(idx + (rest[idx] === "\r" ? 4 : 2));
38
- onFrame?.();
39
- let event;
40
- const dataLines = [];
41
- for (const line of raw.split(/\r?\n/)) {
42
- if (line.startsWith(":")) continue; // comment / keepalive
43
- if (line.startsWith("event:")) event = line.slice(6).trim();else if (line.startsWith("data:")) dataLines.push(line.slice(5).replace(/^ /, ""));
44
- }
45
- if (dataLines.length) yield {
46
- event,
47
- data: dataLines.join("\n")
48
- };
49
- }
50
- return rest;
51
- }
52
-
53
- /**
54
- * Drain complete frames out of `buffer`, returning what is left over.
55
- *
56
- * Shared by both paths so a framing fix can only ever be made in one place.
57
- */
58
- function* drain(buffer, out, onFrame) {
59
- const gen = parseChunk(buffer, onFrame);
60
- let next = gen.next();
61
- while (!next.done) {
62
- yield next.value;
63
- next = gen.next();
64
- }
65
- out.rest = next.value;
66
- }
67
-
68
- /**
69
- * Turn a stream of TEXT chunks into SSE frames.
70
- *
71
- * The one place framing happens, whatever produced the bytes: a `fetch` body
72
- * reader, an `XMLHttpRequest` progress slice, or a whole body read at once on
73
- * a runtime that cannot stream. Splitting it out is what lets the XHR
74
- * transport exist without a second parser to keep in step with this one.
75
- */
76
- async function* framesFrom(chunks, options = {}) {
77
- const {
78
- status,
79
- onFrame
80
- } = options;
81
- const leftover = {
82
- rest: ""
83
- };
84
- let buffer = "";
85
- for await (const chunk of chunks) {
86
- buffer += chunk;
87
- yield* drain(buffer, leftover, onFrame);
88
- buffer = leftover.rest;
89
- }
90
- if (status && leftover.rest.trim()) status.truncated = true;
91
- }
92
- async function* readSse(response, options = {}) {
93
- const {
94
- status,
95
- onFrame,
96
- signal
97
- } = options;
98
- const body = response.body;
99
- const leftover = {
100
- rest: ""
101
- };
102
- if (!body || typeof body.getReader !== "function") {
103
- // No streaming on this platform — read it all, then replay. Note there is
104
- // no "\n\n" here any more: an unterminated tail is discarded exactly as
105
- // the streaming path discards it (see the header).
106
- const text = await response.text();
107
- yield* drain(text, leftover, onFrame);
108
- if (status && leftover.rest.trim()) status.truncated = true;
109
- return;
110
- }
111
- const reader = body.getReader();
112
- const decoder = new TextDecoder();
113
- let buffer = "";
114
- let finished = false;
115
- /**
116
- * One promise for the whole read, not one per chunk.
117
- *
118
- * It never resolves — only rejects — so racing it is free apart from the
119
- * `Promise.race` allocation, and an answer of a few hundred frames pays far
120
- * more for `JSON.parse` than for this.
121
- */
122
- const aborted = signal ? new Promise((_resolve, reject) => {
123
- const fail = () => {
124
- const err = new Error("Aborted");
125
- err.name = "AbortError";
126
- reject(err);
127
- };
128
- if (signal.aborted) fail();else signal.addEventListener?.("abort", fail, {
129
- once: true
130
- });
131
- }) : undefined;
132
- // Nothing awaits this until the race below, and a rejection with no handler
133
- // is an unhandled rejection on some runtimes. This is the handler.
134
- aborted?.catch(() => {});
135
- try {
136
- for (;;) {
137
- const read = reader.read();
138
- const {
139
- done,
140
- value
141
- } = aborted ? await Promise.race([read, aborted]) : await read;
142
- if (done) break;
143
- buffer += decoder.decode(value, {
144
- stream: true
145
- });
146
- yield* drain(buffer, leftover, onFrame);
147
- buffer = leftover.rest;
148
- }
149
- // Flush the decoder: a multi-byte character split across the last two
150
- // chunks is only completed here, and an INCOMPLETE one at EOF is itself
151
- // evidence the connection was cut.
152
- buffer += decoder.decode();
153
- yield* drain(buffer, leftover, onFrame);
154
- if (status && leftover.rest.trim()) status.truncated = true;
155
- finished = true;
156
- } finally {
157
- if (!finished) {
158
- // The consumer left early — an abort, a timeout, or a `break` in the
159
- // provider. `releaseLock` alone leaves the socket open; only `cancel`
160
- // tears the request down, and it must come first because cancelling a
161
- // locked reader is the only way to reach the underlying stream.
162
- try {
163
- // Not awaited: the consumer is already leaving, and a cancel that
164
- // rejects (an errored stream) must not become an unhandled rejection.
165
- void Promise.resolve(reader.cancel()).catch(() => {});
166
- } catch {
167
- /* already cancelled or errored */
168
- }
169
- }
170
- try {
171
- reader.releaseLock();
172
- } catch {
173
- /* already released */
174
- }
175
- }
176
- }
177
-
178
- /**
179
- * A 200 that is not a stream at all.
180
- *
181
- * Gateways in front of a model do this: an auth proxy that has lost its
182
- * upstream serves an HTML error page, a misrouted path serves an SPA shell,
183
- * and a gateway that ignored `stream: true` serves one JSON object. Every one
184
- * of those parses to zero SSE frames, so the old code read it as a model that
185
- * had nothing to say and ended the turn with a blank bubble.
186
- *
187
- * Returns a message when the body should be treated as an error, and undefined
188
- * when it looks like something the SSE reader can work with. Consumes the body
189
- * only in the failing case.
190
- */
191
- async function nonStreamProblem(response) {
192
- const type = response.headers?.get?.("content-type") ?? "";
193
- if (!type) return undefined; // No header to judge by — let the parser try.
194
- const lowered = type.toLowerCase();
195
- if (lowered.includes("event-stream")) return undefined;
196
- // A JSON body is either a non-streaming reply or a structured error; both
197
- // are worth reporting with their own text rather than guessing.
198
- const detail = (await response.text().catch(() => "")).slice(0, 600);
199
- if (lowered.includes("json")) {
200
- return `The endpoint answered with JSON instead of a stream — it may not support "stream": true.${detail ? ` — ${detail}` : ""}`;
201
- }
202
- return `The endpoint answered with ${type} instead of an event stream.${detail ? ` — ${detail}` : ""}`;
203
- }
204
-
205
- /**
206
- * Body text for a failed response, trimmed to something a user can read.
207
- * The detail alone — the transport prefixes the status and classifies it.
208
- */
209
- async function errorBody(response) {
210
- try {
211
- return (await response.text()).slice(0, 600);
212
- } catch {
213
- return ""; // body already consumed or unreadable
214
- }
215
- }
216
-
217
- /**
218
- * The message for a stream that stopped before the provider said it was done.
219
- *
220
- * `truncated` distinguishes the two shapes: cut mid-frame (a dropped
221
- * connection) versus a clean frame boundary with no terminal marker (a gateway
222
- * that closes the socket instead of sending one). The second is a
223
- * compatibility problem worth naming, because retrying it will not help.
224
- */
225
- function truncatedMessage(truncated) {
226
- return truncated ? "The connection dropped before the answer finished." : "The endpoint closed the stream without saying the answer was finished.";
227
- }
228
-
229
- /**
230
- * The message for arguments that would not parse, with enough in it to act on.
231
- * `stopReason` "length" is the common cause — a reasoning model spends its
232
- * budget thinking and the tool call is truncated mid-JSON — and the tail of
233
- * the raw arguments says immediately whether that is what happened.
234
- */
235
- function unparseableMessage(name, args, stopReason) {
236
- const truncated = stopReason === "length";
237
- const tail = args.length > 160 ? `…${args.slice(-160)}` : args;
238
- return `Model sent unparseable arguments for ${name}` + (truncated ? " (cut off at max_tokens — raise it or reduce thinking budget)" : "") + ` [stop: ${stopReason ?? "none"}, ${args.length} chars] ${tail}`;
239
- }
240
- //# sourceMappingURL=sse.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.errorBody=errorBody;exports.framesFrom=framesFrom;exports.nonStreamProblem=nonStreamProblem;exports.readSse=readSse;exports.truncatedMessage=truncatedMessage;exports.unparseableMessage=unparseableMessage;function*parseChunk(r,n){let e=r;let t;while((t=e.search(/\r?\n\r?\n/))!==-1){const s=e.slice(0,t);e=e.slice(t+(e[t]==="\r"?4:2));n?.();let a;const o=[];for(const i of s.split(/\r?\n/)){if(i.startsWith(":"))continue;if(i.startsWith("event:"))a=i.slice(6).trim();else if(i.startsWith("data:"))o.push(i.slice(5).replace(/^ /,""))}if(o.length)yield{event:a,data:o.join("\n")}}return e}function*drain(r,n,e){const t=parseChunk(r,e);let s=t.next();while(!s.done){yield s.value;s=t.next()}n.rest=s.value}async function*framesFrom(r,n={}){const{status:e,onFrame:t}=n;const s={rest:""};let a="";for await(const o of r){a+=o;yield*drain(a,s,t);a=s.rest}if(e&&s.rest.trim())e.truncated=true}async function*readSse(r,n={}){const{status:e,onFrame:t,signal:s}=n;const a=r.body;const o={rest:""};if(!a||typeof a.getReader!=="function"){const d=await r.text();yield*drain(d,o,t);if(e&&o.rest.trim())e.truncated=true;return}const i=a.getReader();const h=new TextDecoder;let c="";let m=false;const l=s?new Promise((d,f)=>{const u=()=>{const y=new Error("Aborted");y.name="AbortError";f(y)};if(s.aborted)u();else s.addEventListener?.("abort",u,{once:true})}):void 0;l?.catch(()=>{});try{for(;;){const d=i.read();const{done:f,value:u}=l?await Promise.race([d,l]):await d;if(f)break;c+=h.decode(u,{stream:true});yield*drain(c,o,t);c=o.rest}c+=h.decode();yield*drain(c,o,t);if(e&&o.rest.trim())e.truncated=true;m=true}finally{if(!m){try{void Promise.resolve(i.cancel()).catch(()=>{})}catch{}}try{i.releaseLock()}catch{}}}async function nonStreamProblem(r){const n=r.headers?.get?.("content-type")??"";if(!n)return void 0;const e=n.toLowerCase();if(e.includes("event-stream"))return void 0;const t=(await r.text().catch(()=>"")).slice(0,600);if(e.includes("json")){return`The endpoint answered with JSON instead of a stream \u2014 it may not support "stream": true.${t?` \u2014 ${t}`:""}`}return`The endpoint answered with ${n} instead of an event stream.${t?` \u2014 ${t}`:""}`}async function errorBody(r){try{return(await r.text()).slice(0,600)}catch{return""}}function truncatedMessage(r){return r?"The connection dropped before the answer finished.":"The endpoint closed the stream without saying the answer was finished."}function unparseableMessage(r,n,e){const t=e==="length";const s=n.length>160?`\u2026${n.slice(-160)}`:n;return`Model sent unparseable arguments for ${r}`+(t?" (cut off at max_tokens \u2014 raise it or reduce thinking budget)":"")+` [stop: ${e??"none"}, ${n.length} chars] ${s}`}