@providerprotocol/ai 0.0.33 → 0.0.35

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 (133) hide show
  1. package/README.md +542 -3
  2. package/dist/anthropic/index.d.ts +2 -1
  3. package/dist/anthropic/index.js +151 -145
  4. package/dist/anthropic/index.js.map +1 -1
  5. package/dist/cerebras/index.d.ts +392 -0
  6. package/dist/cerebras/index.js +648 -0
  7. package/dist/cerebras/index.js.map +1 -0
  8. package/dist/chunk-3GWM5GR3.js +153 -0
  9. package/dist/chunk-3GWM5GR3.js.map +1 -0
  10. package/dist/chunk-4OGB7JZA.js +157 -0
  11. package/dist/chunk-4OGB7JZA.js.map +1 -0
  12. package/dist/chunk-7DXVRILR.js +49 -0
  13. package/dist/chunk-7DXVRILR.js.map +1 -0
  14. package/dist/{chunk-3C7O2RNO.js → chunk-A2IM7PGT.js} +6 -4
  15. package/dist/{chunk-3C7O2RNO.js.map → chunk-A2IM7PGT.js.map} +1 -1
  16. package/dist/{chunk-3D6XGGVG.js → chunk-ARVM24K2.js} +2 -2
  17. package/dist/{chunk-4J6OFUKX.js → chunk-AY55T37A.js} +70 -162
  18. package/dist/chunk-AY55T37A.js.map +1 -0
  19. package/dist/{chunk-ILR2D5PN.js → chunk-BRP5XJ6Q.js} +2 -86
  20. package/dist/chunk-BRP5XJ6Q.js.map +1 -0
  21. package/dist/chunk-C4JP64VW.js +298 -0
  22. package/dist/chunk-C4JP64VW.js.map +1 -0
  23. package/dist/chunk-COS4ON4G.js +111 -0
  24. package/dist/chunk-COS4ON4G.js.map +1 -0
  25. package/dist/chunk-ETBFOLQN.js +34 -0
  26. package/dist/chunk-ETBFOLQN.js.map +1 -0
  27. package/dist/chunk-HB4ZIH3T.js +31 -0
  28. package/dist/chunk-HB4ZIH3T.js.map +1 -0
  29. package/dist/chunk-I53CI6ZZ.js +142 -0
  30. package/dist/chunk-I53CI6ZZ.js.map +1 -0
  31. package/dist/chunk-IDZOVWP3.js +29 -0
  32. package/dist/chunk-IDZOVWP3.js.map +1 -0
  33. package/dist/chunk-JA3UZALR.js +88 -0
  34. package/dist/chunk-JA3UZALR.js.map +1 -0
  35. package/dist/{chunk-WAKD3OO5.js → chunk-N5DX5JW3.js} +31 -31
  36. package/dist/chunk-N5DX5JW3.js.map +1 -0
  37. package/dist/chunk-OIEWDFQU.js +97 -0
  38. package/dist/chunk-OIEWDFQU.js.map +1 -0
  39. package/dist/{chunk-TOJCZMVU.js → chunk-PMK5LZ5Z.js} +40 -40
  40. package/dist/chunk-PMK5LZ5Z.js.map +1 -0
  41. package/dist/chunk-UFFJDYCE.js +94 -0
  42. package/dist/chunk-UFFJDYCE.js.map +1 -0
  43. package/dist/chunk-VGKZIGVI.js +222 -0
  44. package/dist/chunk-VGKZIGVI.js.map +1 -0
  45. package/dist/chunk-VOEWHQUB.js +31 -0
  46. package/dist/chunk-VOEWHQUB.js.map +1 -0
  47. package/dist/{chunk-KUPF5KHT.js → chunk-Y5H7C5J4.js} +2 -2
  48. package/dist/chunk-ZI67WIQS.js +30 -0
  49. package/dist/chunk-ZI67WIQS.js.map +1 -0
  50. package/dist/{embedding-D2BYIehX.d.ts → embedding-CW6SaOOz.d.ts} +1 -1
  51. package/dist/google/index.d.ts +2 -1
  52. package/dist/google/index.js +202 -199
  53. package/dist/google/index.js.map +1 -1
  54. package/dist/groq/index.d.ts +410 -0
  55. package/dist/groq/index.js +649 -0
  56. package/dist/groq/index.js.map +1 -0
  57. package/dist/http/index.d.ts +3 -2
  58. package/dist/http/index.js +5 -4
  59. package/dist/image-stream-C0ciACM2.d.ts +11 -0
  60. package/dist/index.d.ts +8 -118
  61. package/dist/index.js +518 -767
  62. package/dist/index.js.map +1 -1
  63. package/dist/{llm-BQJZj3cD.d.ts → llm-DwbUK7un.d.ts} +12 -1632
  64. package/dist/middleware/logging/index.d.ts +76 -0
  65. package/dist/middleware/logging/index.js +74 -0
  66. package/dist/middleware/logging/index.js.map +1 -0
  67. package/dist/middleware/parsed-object/index.d.ts +45 -0
  68. package/dist/middleware/parsed-object/index.js +73 -0
  69. package/dist/middleware/parsed-object/index.js.map +1 -0
  70. package/dist/middleware/pubsub/index.d.ts +104 -0
  71. package/dist/middleware/pubsub/index.js +230 -0
  72. package/dist/middleware/pubsub/index.js.map +1 -0
  73. package/dist/middleware/pubsub/server/express/index.d.ts +52 -0
  74. package/dist/middleware/pubsub/server/express/index.js +11 -0
  75. package/dist/middleware/pubsub/server/express/index.js.map +1 -0
  76. package/dist/middleware/pubsub/server/fastify/index.d.ts +53 -0
  77. package/dist/middleware/pubsub/server/fastify/index.js +11 -0
  78. package/dist/middleware/pubsub/server/fastify/index.js.map +1 -0
  79. package/dist/middleware/pubsub/server/h3/index.d.ts +56 -0
  80. package/dist/middleware/pubsub/server/h3/index.js +11 -0
  81. package/dist/middleware/pubsub/server/h3/index.js.map +1 -0
  82. package/dist/middleware/pubsub/server/index.d.ts +78 -0
  83. package/dist/middleware/pubsub/server/index.js +34 -0
  84. package/dist/middleware/pubsub/server/index.js.map +1 -0
  85. package/dist/middleware/pubsub/server/webapi/index.d.ts +53 -0
  86. package/dist/middleware/pubsub/server/webapi/index.js +11 -0
  87. package/dist/middleware/pubsub/server/webapi/index.js.map +1 -0
  88. package/dist/ollama/index.d.ts +2 -1
  89. package/dist/ollama/index.js +48 -45
  90. package/dist/ollama/index.js.map +1 -1
  91. package/dist/openai/index.d.ts +2 -1
  92. package/dist/openai/index.js +319 -313
  93. package/dist/openai/index.js.map +1 -1
  94. package/dist/openrouter/index.d.ts +2 -1
  95. package/dist/openrouter/index.js +379 -383
  96. package/dist/openrouter/index.js.map +1 -1
  97. package/dist/proxy/index.d.ts +10 -914
  98. package/dist/proxy/index.js +275 -1007
  99. package/dist/proxy/index.js.map +1 -1
  100. package/dist/proxy/server/express/index.d.ts +161 -0
  101. package/dist/proxy/server/express/index.js +24 -0
  102. package/dist/proxy/server/express/index.js.map +1 -0
  103. package/dist/proxy/server/fastify/index.d.ts +162 -0
  104. package/dist/proxy/server/fastify/index.js +24 -0
  105. package/dist/proxy/server/fastify/index.js.map +1 -0
  106. package/dist/proxy/server/h3/index.d.ts +189 -0
  107. package/dist/proxy/server/h3/index.js +28 -0
  108. package/dist/proxy/server/h3/index.js.map +1 -0
  109. package/dist/proxy/server/index.d.ts +151 -0
  110. package/dist/proxy/server/index.js +48 -0
  111. package/dist/proxy/server/index.js.map +1 -0
  112. package/dist/proxy/server/webapi/index.d.ts +278 -0
  113. package/dist/proxy/server/webapi/index.js +32 -0
  114. package/dist/proxy/server/webapi/index.js.map +1 -0
  115. package/dist/responses/index.d.ts +650 -0
  116. package/dist/responses/index.js +930 -0
  117. package/dist/responses/index.js.map +1 -0
  118. package/dist/{retry-8Ch-WWgX.d.ts → retry-YayV42GV.d.ts} +1 -1
  119. package/dist/stream-CecfVCPO.d.ts +1632 -0
  120. package/dist/types-C8Gciizr.d.ts +168 -0
  121. package/dist/utils/index.d.ts +53 -0
  122. package/dist/utils/index.js +7 -0
  123. package/dist/utils/index.js.map +1 -0
  124. package/dist/xai/index.d.ts +2 -1
  125. package/dist/xai/index.js +310 -310
  126. package/dist/xai/index.js.map +1 -1
  127. package/package.json +94 -4
  128. package/dist/chunk-4J6OFUKX.js.map +0 -1
  129. package/dist/chunk-ILR2D5PN.js.map +0 -1
  130. package/dist/chunk-TOJCZMVU.js.map +0 -1
  131. package/dist/chunk-WAKD3OO5.js.map +0 -1
  132. /package/dist/{chunk-3D6XGGVG.js.map → chunk-ARVM24K2.js.map} +0 -0
  133. /package/dist/{chunk-KUPF5KHT.js.map → chunk-Y5H7C5J4.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ import {
2
+ ExponentialBackoff,
3
+ LinearBackoff,
4
+ NoRetry,
5
+ RetryAfterStrategy,
6
+ TokenBucket
7
+ } from "./chunk-Y5H7C5J4.js";
1
8
  import {
2
9
  aggregateUsage,
3
10
  createTurn,
@@ -5,54 +12,52 @@ import {
5
12
  } from "./chunk-NSE7QN3P.js";
6
13
  import {
7
14
  Image
8
- } from "./chunk-WAKD3OO5.js";
15
+ } from "./chunk-N5DX5JW3.js";
16
+ import "./chunk-PMK5LZ5Z.js";
9
17
  import {
10
- StreamEventType,
11
- contentBlockStart,
12
- contentBlockStop,
13
- createStreamResult,
14
- messageStart,
15
- messageStop,
16
- objectDelta,
17
- textDelta,
18
- toolCallDelta,
19
- toolExecutionEnd,
20
- toolExecutionStart
21
- } from "./chunk-6S222DHN.js";
18
+ DynamicKey,
19
+ RoundRobinKeys,
20
+ WeightedKeys
21
+ } from "./chunk-ARVM24K2.js";
22
+ import {
23
+ createProvider,
24
+ resolveEmbeddingHandler,
25
+ resolveImageHandler,
26
+ resolveLLMHandler
27
+ } from "./chunk-JA3UZALR.js";
22
28
  import {
23
29
  AssistantMessage,
24
30
  Message,
25
31
  MessageRole,
26
32
  ToolResultMessage,
27
33
  UserMessage,
28
- createProvider,
29
34
  generateId,
30
35
  isAssistantMessage,
31
36
  isToolResultMessage,
32
- isUserMessage,
33
- resolveEmbeddingHandler,
34
- resolveImageHandler,
35
- resolveLLMHandler
36
- } from "./chunk-ILR2D5PN.js";
37
- import {
38
- ExponentialBackoff,
39
- LinearBackoff,
40
- NoRetry,
41
- RetryAfterStrategy,
42
- TokenBucket
43
- } from "./chunk-KUPF5KHT.js";
44
- import "./chunk-TOJCZMVU.js";
37
+ isUserMessage
38
+ } from "./chunk-BRP5XJ6Q.js";
45
39
  import {
46
- DynamicKey,
47
- RoundRobinKeys,
48
- WeightedKeys
49
- } from "./chunk-3D6XGGVG.js";
40
+ isCancelledError,
41
+ toError
42
+ } from "./chunk-AY55T37A.js";
50
43
  import {
51
44
  ErrorCode,
52
45
  ModalityType,
53
- UPPError,
54
- toError
55
- } from "./chunk-4J6OFUKX.js";
46
+ UPPError
47
+ } from "./chunk-COS4ON4G.js";
48
+ import {
49
+ StreamEventType,
50
+ contentBlockStart,
51
+ contentBlockStop,
52
+ createStreamResult,
53
+ messageStart,
54
+ messageStop,
55
+ objectDelta,
56
+ textDelta,
57
+ toolCallDelta,
58
+ toolExecutionEnd,
59
+ toolExecutionStart
60
+ } from "./chunk-6S222DHN.js";
56
61
 
57
62
  // src/types/content.ts
58
63
  var ContentBlockType = {
@@ -136,6 +141,17 @@ async function runErrorHook(middlewares, error, ctx) {
136
141
  }
137
142
  }
138
143
  }
144
+ async function runAbortHook(middlewares, error, ctx) {
145
+ for (const mw of middlewares) {
146
+ if (mw.onAbort) {
147
+ try {
148
+ await mw.onAbort(error, ctx);
149
+ } catch (hookError) {
150
+ console.error(`[${mw.name}] Error in onAbort hook:`, hookError);
151
+ }
152
+ }
153
+ }
154
+ }
139
155
  async function runToolHook(middlewares, hook, tool, data, ctx) {
140
156
  for (const mw of middlewares) {
141
157
  const fn = mw[hook];
@@ -202,99 +218,44 @@ function createStreamContext(state) {
202
218
 
203
219
  // src/core/llm.ts
204
220
  var DEFAULT_MAX_ITERATIONS = 10;
205
- function llm(options) {
206
- const {
207
- model: modelRef,
208
- config: explicitConfig = {},
209
- params,
210
- system,
211
- tools,
212
- toolStrategy,
213
- structure,
214
- middleware = []
215
- } = options;
216
- const providerConfig = modelRef.providerConfig ?? {};
217
- const config = {
218
- ...providerConfig,
219
- ...explicitConfig,
220
- headers: {
221
- ...providerConfig.headers,
222
- ...explicitConfig.headers
223
- }
224
- };
225
- const provider = modelRef.provider;
226
- const llmHandler = resolveLLMHandler(provider, modelRef.options);
227
- if (!llmHandler) {
228
- throw new UPPError(
229
- `Provider '${provider.name}' does not support LLM modality`,
230
- ErrorCode.InvalidRequest,
231
- provider.name,
232
- ModalityType.LLM
233
- );
234
- }
235
- const boundModel = llmHandler.bind(modelRef.modelId);
236
- const capabilities = boundModel.capabilities;
237
- if (structure && !capabilities.structuredOutput) {
238
- throw new UPPError(
239
- `Provider '${provider.name}' does not support structured output`,
240
- ErrorCode.InvalidRequest,
241
- provider.name,
242
- ModalityType.LLM
243
- );
244
- }
245
- if (tools && tools.length > 0 && !capabilities.tools) {
246
- throw new UPPError(
247
- `Provider '${provider.name}' does not support tools`,
248
- ErrorCode.InvalidRequest,
249
- provider.name,
250
- ModalityType.LLM
251
- );
252
- }
253
- const instance = {
254
- model: boundModel,
255
- system,
256
- params,
257
- capabilities,
258
- async generate(historyOrInput, ...inputs) {
259
- const { history, messages } = parseInputs(historyOrInput, inputs);
260
- return executeGenerate(
261
- boundModel,
262
- config,
263
- system,
264
- params,
265
- tools,
266
- toolStrategy,
267
- structure,
268
- history,
269
- messages,
270
- middleware
271
- );
272
- },
273
- stream(historyOrInput, ...inputs) {
274
- if (!capabilities.streaming) {
221
+ function validateMediaCapabilities(messages, capabilities, providerName) {
222
+ for (const msg of messages) {
223
+ if (!isUserMessage(msg)) continue;
224
+ for (const block of msg.content) {
225
+ if (block.type === "image" && !capabilities.imageInput) {
275
226
  throw new UPPError(
276
- `Provider '${provider.name}' does not support streaming`,
227
+ `Provider '${providerName}' does not support image input`,
277
228
  ErrorCode.InvalidRequest,
278
- provider.name,
229
+ providerName,
230
+ ModalityType.LLM
231
+ );
232
+ }
233
+ if (block.type === "document" && !capabilities.documentInput) {
234
+ throw new UPPError(
235
+ `Provider '${providerName}' does not support document input`,
236
+ ErrorCode.InvalidRequest,
237
+ providerName,
238
+ ModalityType.LLM
239
+ );
240
+ }
241
+ if (block.type === "video" && !capabilities.videoInput) {
242
+ throw new UPPError(
243
+ `Provider '${providerName}' does not support video input`,
244
+ ErrorCode.InvalidRequest,
245
+ providerName,
246
+ ModalityType.LLM
247
+ );
248
+ }
249
+ if (block.type === "audio" && !capabilities.audioInput) {
250
+ throw new UPPError(
251
+ `Provider '${providerName}' does not support audio input`,
252
+ ErrorCode.InvalidRequest,
253
+ providerName,
279
254
  ModalityType.LLM
280
255
  );
281
256
  }
282
- const { history, messages } = parseInputs(historyOrInput, inputs);
283
- return executeStream(
284
- boundModel,
285
- config,
286
- system,
287
- params,
288
- tools,
289
- toolStrategy,
290
- structure,
291
- history,
292
- messages,
293
- middleware
294
- );
295
257
  }
296
- };
297
- return instance;
258
+ }
298
259
  }
299
260
  function isMessageInstance(value) {
300
261
  if (value instanceof Message) {
@@ -318,6 +279,25 @@ function isMessageInstance(value) {
318
279
  }
319
280
  return false;
320
281
  }
282
+ function inputToMessage(input) {
283
+ if (typeof input === "string") {
284
+ return new UserMessage(input);
285
+ }
286
+ if ("type" in input && "id" in input && "timestamp" in input) {
287
+ return input;
288
+ }
289
+ if (typeof input !== "object" || input === null || !("type" in input)) {
290
+ throw new Error("Invalid inference input");
291
+ }
292
+ const block = input;
293
+ if (isTextBlock(block)) {
294
+ return new UserMessage(block.text);
295
+ }
296
+ if (isImageBlock(block) || isDocumentBlock(block) || isAudioBlock(block) || isVideoBlock(block) || isBinaryBlock(block)) {
297
+ return new UserMessage([block]);
298
+ }
299
+ throw new Error("Invalid inference input");
300
+ }
321
301
  function parseInputs(historyOrInput, inputs) {
322
302
  if (typeof historyOrInput === "object" && historyOrInput !== null && "messages" in historyOrInput && Array.isArray(historyOrInput.messages)) {
323
303
  const thread = historyOrInput;
@@ -339,61 +319,185 @@ function parseInputs(historyOrInput, inputs) {
339
319
  const newMessages = allInputs.map(inputToMessage);
340
320
  return { history: [], messages: newMessages };
341
321
  }
342
- function inputToMessage(input) {
343
- if (typeof input === "string") {
344
- return new UserMessage(input);
345
- }
346
- if ("type" in input && "id" in input && "timestamp" in input) {
347
- return input;
348
- }
349
- if (typeof input !== "object" || input === null || !("type" in input)) {
350
- throw new Error("Invalid inference input");
351
- }
352
- const block = input;
353
- if (isTextBlock(block)) {
354
- return new UserMessage(block.text);
355
- }
356
- if (isImageBlock(block) || isDocumentBlock(block) || isAudioBlock(block) || isVideoBlock(block) || isBinaryBlock(block)) {
357
- return new UserMessage([block]);
358
- }
359
- throw new Error("Invalid inference input");
360
- }
361
- async function executeGenerate(model, config, system, params, tools, toolStrategy, structure, history, newMessages, middleware) {
362
- validateMediaCapabilities(
363
- [...history, ...newMessages],
364
- model.capabilities,
365
- model.provider.name
366
- );
367
- const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
368
- const allMessages = [...history, ...newMessages];
369
- const toolExecutions = [];
370
- const usages = [];
371
- let cycles = 0;
372
- let structuredData;
373
- const initialRequest = {
374
- messages: allMessages,
375
- system,
376
- params,
377
- tools,
378
- structure,
379
- config
380
- };
381
- const ctx = createMiddlewareContext(
382
- "llm",
383
- model.modelId,
384
- model.provider.name,
385
- false,
386
- initialRequest
387
- );
388
- try {
389
- await runHook(middleware, "onStart", ctx);
390
- await runHook(middleware, "onRequest", ctx);
391
- while (cycles < maxIterations + 1) {
392
- cycles++;
393
- const request = {
394
- messages: allMessages,
395
- system,
396
- params,
322
+ async function executeTools(assistantMessage, tools, toolStrategy, executions, onEvent, middleware = [], ctx) {
323
+ const toolCalls = assistantMessage.toolCalls ?? [];
324
+ const results = [];
325
+ const toolMap = new Map(tools.map((t) => [t.name, t]));
326
+ const promises = toolCalls.map(async (call, index) => {
327
+ const tool = toolMap.get(call.toolName);
328
+ const toolName = tool?.name ?? call.toolName;
329
+ const startTime = Date.now();
330
+ onEvent?.(toolExecutionStart(call.toolCallId, toolName, startTime, index));
331
+ let effectiveParams = call.arguments;
332
+ const endWithError = async (errorMessage, approved2) => {
333
+ const endTime = Date.now();
334
+ if (tool) {
335
+ await toolStrategy?.onError?.(tool, effectiveParams, new Error(errorMessage));
336
+ }
337
+ const execution = {
338
+ toolName,
339
+ toolCallId: call.toolCallId,
340
+ arguments: effectiveParams,
341
+ result: errorMessage,
342
+ isError: true,
343
+ duration: endTime - startTime,
344
+ approved: approved2
345
+ };
346
+ executions.push(execution);
347
+ onEvent?.(toolExecutionEnd(call.toolCallId, toolName, errorMessage, true, endTime, index));
348
+ return {
349
+ toolCallId: call.toolCallId,
350
+ result: errorMessage,
351
+ isError: true
352
+ };
353
+ };
354
+ if (!tool) {
355
+ return endWithError(`Tool '${call.toolName}' not found`);
356
+ }
357
+ try {
358
+ await toolStrategy?.onToolCall?.(tool, effectiveParams);
359
+ if (ctx) {
360
+ await runToolHook(middleware, "onToolCall", tool, effectiveParams, ctx);
361
+ }
362
+ } catch (error) {
363
+ return endWithError(toError(error).message);
364
+ }
365
+ if (toolStrategy?.onBeforeCall) {
366
+ let beforeResult;
367
+ try {
368
+ beforeResult = await toolStrategy.onBeforeCall(tool, effectiveParams);
369
+ } catch (error) {
370
+ return endWithError(toError(error).message);
371
+ }
372
+ const isBeforeCallResult = (value) => typeof value === "object" && value !== null && "proceed" in value;
373
+ if (isBeforeCallResult(beforeResult)) {
374
+ if (!beforeResult.proceed) {
375
+ return endWithError("Tool execution skipped");
376
+ }
377
+ if (beforeResult.params !== void 0) {
378
+ effectiveParams = beforeResult.params;
379
+ }
380
+ } else if (!beforeResult) {
381
+ return endWithError("Tool execution skipped");
382
+ }
383
+ }
384
+ let approved = true;
385
+ if (tool.approval) {
386
+ try {
387
+ approved = await tool.approval(effectiveParams);
388
+ } catch (error) {
389
+ return endWithError(toError(error).message);
390
+ }
391
+ }
392
+ if (!approved) {
393
+ const endTime = Date.now();
394
+ const execution = {
395
+ toolName,
396
+ toolCallId: call.toolCallId,
397
+ arguments: effectiveParams,
398
+ result: "Tool execution denied",
399
+ isError: true,
400
+ duration: endTime - startTime,
401
+ approved: false
402
+ };
403
+ executions.push(execution);
404
+ onEvent?.(toolExecutionEnd(call.toolCallId, toolName, "Tool execution denied by approval handler", true, endTime, index));
405
+ return {
406
+ toolCallId: call.toolCallId,
407
+ result: "Tool execution denied by approval handler",
408
+ isError: true
409
+ };
410
+ }
411
+ try {
412
+ let result = await tool.run(effectiveParams);
413
+ const endTime = Date.now();
414
+ if (toolStrategy?.onAfterCall) {
415
+ const afterResult = await toolStrategy.onAfterCall(tool, effectiveParams, result);
416
+ const isAfterCallResult = (value) => typeof value === "object" && value !== null && "result" in value;
417
+ if (isAfterCallResult(afterResult)) {
418
+ result = afterResult.result;
419
+ }
420
+ }
421
+ if (ctx) {
422
+ await runToolHook(middleware, "onToolResult", tool, result, ctx);
423
+ }
424
+ const execution = {
425
+ toolName,
426
+ toolCallId: call.toolCallId,
427
+ arguments: effectiveParams,
428
+ result,
429
+ isError: false,
430
+ duration: endTime - startTime,
431
+ approved
432
+ };
433
+ executions.push(execution);
434
+ onEvent?.(toolExecutionEnd(call.toolCallId, toolName, result, false, endTime, index));
435
+ return {
436
+ toolCallId: call.toolCallId,
437
+ result,
438
+ isError: false
439
+ };
440
+ } catch (error) {
441
+ const endTime = Date.now();
442
+ const err = toError(error);
443
+ await toolStrategy?.onError?.(tool, effectiveParams, err);
444
+ const execution = {
445
+ toolName,
446
+ toolCallId: call.toolCallId,
447
+ arguments: effectiveParams,
448
+ result: err.message,
449
+ isError: true,
450
+ duration: endTime - startTime,
451
+ approved
452
+ };
453
+ executions.push(execution);
454
+ onEvent?.(toolExecutionEnd(call.toolCallId, toolName, err.message, true, endTime, index));
455
+ return {
456
+ toolCallId: call.toolCallId,
457
+ result: err.message,
458
+ isError: true
459
+ };
460
+ }
461
+ });
462
+ results.push(...await Promise.all(promises));
463
+ return results;
464
+ }
465
+ async function executeGenerate(model, config, system, params, tools, toolStrategy, structure, history, newMessages, middleware) {
466
+ validateMediaCapabilities(
467
+ [...history, ...newMessages],
468
+ model.capabilities,
469
+ model.provider.name
470
+ );
471
+ const maxIterations = toolStrategy?.maxIterations ?? DEFAULT_MAX_ITERATIONS;
472
+ const allMessages = [...history, ...newMessages];
473
+ const toolExecutions = [];
474
+ const usages = [];
475
+ let cycles = 0;
476
+ let structuredData;
477
+ const initialRequest = {
478
+ messages: allMessages,
479
+ system,
480
+ params,
481
+ tools,
482
+ structure,
483
+ config
484
+ };
485
+ const ctx = createMiddlewareContext(
486
+ "llm",
487
+ model.modelId,
488
+ model.provider.name,
489
+ false,
490
+ initialRequest
491
+ );
492
+ try {
493
+ await runHook(middleware, "onStart", ctx);
494
+ await runHook(middleware, "onRequest", ctx);
495
+ while (cycles < maxIterations + 1) {
496
+ cycles++;
497
+ const request = {
498
+ messages: allMessages,
499
+ system,
500
+ params,
397
501
  tools,
398
502
  structure,
399
503
  config
@@ -602,7 +706,11 @@ function executeStream(model, config, system, params, tools, toolStrategy, struc
602
706
  } catch (error) {
603
707
  const err = toError(error);
604
708
  generatorError = err;
605
- await runErrorHook(middleware, err, ctx);
709
+ if (isCancelledError(err)) {
710
+ await runAbortHook(middleware, err, ctx);
711
+ } else {
712
+ await runErrorHook(middleware, err, ctx);
713
+ }
606
714
  rejectGenerator(err);
607
715
  throw err;
608
716
  } finally {
@@ -613,6 +721,7 @@ function executeStream(model, config, system, params, tools, toolStrategy, struc
613
721
  if (!abortController.signal.aborted) {
614
722
  abortController.abort();
615
723
  }
724
+ await runAbortHook(middleware, error, ctx);
616
725
  rejectGenerator(error);
617
726
  }
618
727
  }
@@ -643,223 +752,143 @@ function executeStream(model, config, system, params, tools, toolStrategy, struc
643
752
  };
644
753
  return createStreamResult(generateStream(), createTurnPromise, abortController);
645
754
  }
646
- async function executeTools(message, tools, toolStrategy, executions, onEvent, middleware = [], ctx) {
647
- const toolCalls = message.toolCalls ?? [];
648
- const results = [];
649
- const toolMap = new Map(tools.map((t) => [t.name, t]));
650
- const promises = toolCalls.map(async (call, index) => {
651
- const tool = toolMap.get(call.toolName);
652
- const toolName = tool?.name ?? call.toolName;
653
- const startTime = Date.now();
654
- onEvent?.(toolExecutionStart(call.toolCallId, toolName, startTime, index));
655
- let effectiveParams = call.arguments;
656
- const endWithError = async (message2, approved2) => {
657
- const endTime = Date.now();
658
- if (tool) {
659
- await toolStrategy?.onError?.(tool, effectiveParams, new Error(message2));
660
- }
661
- const execution = {
662
- toolName,
663
- toolCallId: call.toolCallId,
664
- arguments: effectiveParams,
665
- result: message2,
666
- isError: true,
667
- duration: endTime - startTime,
668
- approved: approved2
669
- };
670
- executions.push(execution);
671
- onEvent?.(toolExecutionEnd(call.toolCallId, toolName, message2, true, endTime, index));
672
- return {
673
- toolCallId: call.toolCallId,
674
- result: message2,
675
- isError: true
676
- };
677
- };
678
- if (!tool) {
679
- return endWithError(`Tool '${call.toolName}' not found`);
680
- }
681
- try {
682
- await toolStrategy?.onToolCall?.(tool, effectiveParams);
683
- if (ctx) {
684
- await runToolHook(middleware, "onToolCall", tool, effectiveParams, ctx);
685
- }
686
- } catch (error) {
687
- return endWithError(toError(error).message);
688
- }
689
- if (toolStrategy?.onBeforeCall) {
690
- let beforeResult;
691
- try {
692
- beforeResult = await toolStrategy.onBeforeCall(tool, effectiveParams);
693
- } catch (error) {
694
- return endWithError(toError(error).message);
695
- }
696
- const isBeforeCallResult = (value) => typeof value === "object" && value !== null && "proceed" in value;
697
- if (isBeforeCallResult(beforeResult)) {
698
- if (!beforeResult.proceed) {
699
- return endWithError("Tool execution skipped");
700
- }
701
- if (beforeResult.params !== void 0) {
702
- effectiveParams = beforeResult.params;
703
- }
704
- } else if (!beforeResult) {
705
- return endWithError("Tool execution skipped");
706
- }
707
- }
708
- let approved = true;
709
- if (tool.approval) {
710
- try {
711
- approved = await tool.approval(effectiveParams);
712
- } catch (error) {
713
- return endWithError(toError(error).message);
714
- }
755
+ function llm(options) {
756
+ const {
757
+ model: modelRef,
758
+ config: explicitConfig = {},
759
+ params,
760
+ system,
761
+ tools,
762
+ toolStrategy,
763
+ structure,
764
+ middleware = []
765
+ } = options;
766
+ const providerConfig = modelRef.providerConfig ?? {};
767
+ const config = {
768
+ ...providerConfig,
769
+ ...explicitConfig,
770
+ headers: {
771
+ ...providerConfig.headers,
772
+ ...explicitConfig.headers
715
773
  }
716
- if (!approved) {
717
- const endTime = Date.now();
718
- const execution = {
719
- toolName,
720
- toolCallId: call.toolCallId,
721
- arguments: effectiveParams,
722
- result: "Tool execution denied",
723
- isError: true,
724
- duration: endTime - startTime,
725
- approved: false
726
- };
727
- executions.push(execution);
728
- onEvent?.(toolExecutionEnd(call.toolCallId, toolName, "Tool execution denied by approval handler", true, endTime, index));
729
- return {
730
- toolCallId: call.toolCallId,
731
- result: "Tool execution denied by approval handler",
732
- isError: true
733
- };
734
- }
735
- try {
736
- let result = await tool.run(effectiveParams);
737
- const endTime = Date.now();
738
- if (toolStrategy?.onAfterCall) {
739
- const afterResult = await toolStrategy.onAfterCall(tool, effectiveParams, result);
740
- const isAfterCallResult = (value) => typeof value === "object" && value !== null && "result" in value;
741
- if (isAfterCallResult(afterResult)) {
742
- result = afterResult.result;
743
- }
744
- }
745
- if (ctx) {
746
- await runToolHook(middleware, "onToolResult", tool, result, ctx);
747
- }
748
- const execution = {
749
- toolName,
750
- toolCallId: call.toolCallId,
751
- arguments: effectiveParams,
752
- result,
753
- isError: false,
754
- duration: endTime - startTime,
755
- approved
756
- };
757
- executions.push(execution);
758
- onEvent?.(toolExecutionEnd(call.toolCallId, toolName, result, false, endTime, index));
759
- return {
760
- toolCallId: call.toolCallId,
761
- result,
762
- isError: false
763
- };
764
- } catch (error) {
765
- const endTime = Date.now();
766
- const err = toError(error);
767
- await toolStrategy?.onError?.(tool, effectiveParams, err);
768
- const execution = {
769
- toolName,
770
- toolCallId: call.toolCallId,
771
- arguments: effectiveParams,
772
- result: err.message,
773
- isError: true,
774
- duration: endTime - startTime,
775
- approved
776
- };
777
- executions.push(execution);
778
- onEvent?.(toolExecutionEnd(call.toolCallId, toolName, err.message, true, endTime, index));
779
- return {
780
- toolCallId: call.toolCallId,
781
- result: err.message,
782
- isError: true
783
- };
784
- }
785
- });
786
- results.push(...await Promise.all(promises));
787
- return results;
788
- }
789
- function validateMediaCapabilities(messages, capabilities, providerName) {
790
- for (const msg of messages) {
791
- if (!isUserMessage(msg)) continue;
792
- for (const block of msg.content) {
793
- if (block.type === "image" && !capabilities.imageInput) {
794
- throw new UPPError(
795
- `Provider '${providerName}' does not support image input`,
796
- ErrorCode.InvalidRequest,
797
- providerName,
798
- ModalityType.LLM
799
- );
800
- }
801
- if (block.type === "document" && !capabilities.documentInput) {
802
- throw new UPPError(
803
- `Provider '${providerName}' does not support document input`,
804
- ErrorCode.InvalidRequest,
805
- providerName,
806
- ModalityType.LLM
807
- );
808
- }
809
- if (block.type === "video" && !capabilities.videoInput) {
810
- throw new UPPError(
811
- `Provider '${providerName}' does not support video input`,
812
- ErrorCode.InvalidRequest,
813
- providerName,
814
- ModalityType.LLM
815
- );
816
- }
817
- if (block.type === "audio" && !capabilities.audioInput) {
774
+ };
775
+ const provider = modelRef.provider;
776
+ const llmHandler = resolveLLMHandler(provider, modelRef.options);
777
+ if (!llmHandler) {
778
+ throw new UPPError(
779
+ `Provider '${provider.name}' does not support LLM modality`,
780
+ ErrorCode.InvalidRequest,
781
+ provider.name,
782
+ ModalityType.LLM
783
+ );
784
+ }
785
+ const boundModel = llmHandler.bind(modelRef.modelId);
786
+ const capabilities = boundModel.capabilities;
787
+ if (structure && !capabilities.structuredOutput) {
788
+ throw new UPPError(
789
+ `Provider '${provider.name}' does not support structured output`,
790
+ ErrorCode.InvalidRequest,
791
+ provider.name,
792
+ ModalityType.LLM
793
+ );
794
+ }
795
+ if (tools && tools.length > 0 && !capabilities.tools) {
796
+ throw new UPPError(
797
+ `Provider '${provider.name}' does not support tools`,
798
+ ErrorCode.InvalidRequest,
799
+ provider.name,
800
+ ModalityType.LLM
801
+ );
802
+ }
803
+ const instance = {
804
+ model: boundModel,
805
+ system,
806
+ params,
807
+ capabilities,
808
+ async generate(historyOrInput, ...inputs) {
809
+ const { history, messages } = parseInputs(historyOrInput, inputs);
810
+ return executeGenerate(
811
+ boundModel,
812
+ config,
813
+ system,
814
+ params,
815
+ tools,
816
+ toolStrategy,
817
+ structure,
818
+ history,
819
+ messages,
820
+ middleware
821
+ );
822
+ },
823
+ stream(historyOrInput, ...inputs) {
824
+ if (!capabilities.streaming) {
818
825
  throw new UPPError(
819
- `Provider '${providerName}' does not support audio input`,
826
+ `Provider '${provider.name}' does not support streaming`,
820
827
  ErrorCode.InvalidRequest,
821
- providerName,
828
+ provider.name,
822
829
  ModalityType.LLM
823
830
  );
824
831
  }
832
+ const { history, messages } = parseInputs(historyOrInput, inputs);
833
+ return executeStream(
834
+ boundModel,
835
+ config,
836
+ system,
837
+ params,
838
+ tools,
839
+ toolStrategy,
840
+ structure,
841
+ history,
842
+ messages,
843
+ middleware
844
+ );
825
845
  }
826
- }
846
+ };
847
+ return instance;
827
848
  }
828
849
 
829
850
  // src/core/embedding.ts
830
- function embedding(options) {
831
- const { model: modelRef, config: explicitConfig = {}, params, middleware = [] } = options;
832
- const providerConfig = modelRef.providerConfig ?? {};
833
- const config = {
834
- ...providerConfig,
835
- ...explicitConfig,
836
- headers: {
837
- ...providerConfig.headers,
838
- ...explicitConfig.headers
851
+ function decodeBase64(b64, providerName) {
852
+ try {
853
+ const binary = atob(b64);
854
+ const bytes = new Uint8Array(binary.length);
855
+ for (let i = 0; i < binary.length; i++) {
856
+ bytes[i] = binary.charCodeAt(i);
839
857
  }
840
- };
841
- const provider = modelRef.provider;
842
- const handler = resolveEmbeddingHandler(provider);
843
- if (!handler) {
858
+ const floats = new Float32Array(bytes.buffer);
859
+ return Array.from(floats);
860
+ } catch (error) {
861
+ const cause = error instanceof Error ? error : new Error("Failed to decode base64 vector");
844
862
  throw new UPPError(
845
- `Provider '${provider.name}' does not support embedding modality`,
846
- ErrorCode.InvalidRequest,
847
- provider.name,
848
- ModalityType.Embedding
863
+ "Invalid base64 embedding vector",
864
+ ErrorCode.InvalidResponse,
865
+ providerName,
866
+ ModalityType.Embedding,
867
+ void 0,
868
+ cause
849
869
  );
850
870
  }
851
- const boundModel = handler.bind(modelRef.modelId);
852
- function embed(input, embedOptions) {
853
- const inputs = Array.isArray(input) ? input : [input];
854
- if (embedOptions?.chunked) {
855
- return createChunkedStream(boundModel, inputs, params, config, embedOptions, middleware);
856
- }
857
- return executeEmbed(boundModel, inputs, params, config, embedOptions?.signal, embedOptions?.inputType, middleware);
871
+ }
872
+ function normalizeVector(vector, providerName) {
873
+ if (Array.isArray(vector)) {
874
+ return vector;
858
875
  }
876
+ return decodeBase64(vector, providerName);
877
+ }
878
+ function normalizeResponse(response, providerName) {
859
879
  return {
860
- model: boundModel,
861
- params,
862
- embed
880
+ embeddings: response.embeddings.map((vec, i) => {
881
+ const vector = normalizeVector(vec.vector, providerName);
882
+ return {
883
+ vector,
884
+ dimensions: vector.length,
885
+ index: vec.index ?? i,
886
+ tokens: vec.tokens,
887
+ metadata: vec.metadata
888
+ };
889
+ }),
890
+ usage: response.usage,
891
+ metadata: response.metadata
863
892
  };
864
893
  }
865
894
  async function executeEmbed(model, inputs, params, config, signal, inputType, middleware = []) {
@@ -881,59 +910,16 @@ async function executeEmbed(model, inputs, params, config, signal, inputType, mi
881
910
  await runHook(middleware, "onStart", ctx);
882
911
  await runHook(middleware, "onRequest", ctx);
883
912
  const response = await model.embed(request);
884
- const result = normalizeResponse(response, model.provider.name);
885
- ctx.response = response;
886
- ctx.endTime = Date.now();
887
- await runHook(middleware, "onResponse", ctx, true);
888
- await runHook(middleware, "onEnd", ctx, true);
889
- return result;
890
- } catch (error) {
891
- const err = toError(error);
892
- await runErrorHook(middleware, err, ctx);
893
- throw err;
894
- }
895
- }
896
- function normalizeResponse(response, providerName) {
897
- return {
898
- embeddings: response.embeddings.map((vec, i) => {
899
- const vector = normalizeVector(vec.vector, providerName);
900
- return {
901
- vector,
902
- dimensions: vector.length,
903
- index: vec.index ?? i,
904
- tokens: vec.tokens,
905
- metadata: vec.metadata
906
- };
907
- }),
908
- usage: response.usage,
909
- metadata: response.metadata
910
- };
911
- }
912
- function normalizeVector(vector, providerName) {
913
- if (Array.isArray(vector)) {
914
- return vector;
915
- }
916
- return decodeBase64(vector, providerName);
917
- }
918
- function decodeBase64(b64, providerName) {
919
- try {
920
- const binary = atob(b64);
921
- const bytes = new Uint8Array(binary.length);
922
- for (let i = 0; i < binary.length; i++) {
923
- bytes[i] = binary.charCodeAt(i);
924
- }
925
- const floats = new Float32Array(bytes.buffer);
926
- return Array.from(floats);
913
+ const result = normalizeResponse(response, model.provider.name);
914
+ ctx.response = response;
915
+ ctx.endTime = Date.now();
916
+ await runHook(middleware, "onResponse", ctx, true);
917
+ await runHook(middleware, "onEnd", ctx, true);
918
+ return result;
927
919
  } catch (error) {
928
- const cause = error instanceof Error ? error : new Error("Failed to decode base64 vector");
929
- throw new UPPError(
930
- "Invalid base64 embedding vector",
931
- ErrorCode.InvalidResponse,
932
- providerName,
933
- ModalityType.Embedding,
934
- void 0,
935
- cause
936
- );
920
+ const err = toError(error);
921
+ await runErrorHook(middleware, err, ctx);
922
+ throw err;
937
923
  }
938
924
  }
939
925
  function createChunkedStream(model, inputs, params, config, options, middleware = []) {
@@ -1072,8 +1058,49 @@ function createChunkedStream(model, inputs, params, config, options, middleware
1072
1058
  abort: () => abortController.abort()
1073
1059
  };
1074
1060
  }
1061
+ function embedding(options) {
1062
+ const { model: modelRef, config: explicitConfig = {}, params, middleware = [] } = options;
1063
+ const providerConfig = modelRef.providerConfig ?? {};
1064
+ const config = {
1065
+ ...providerConfig,
1066
+ ...explicitConfig,
1067
+ headers: {
1068
+ ...providerConfig.headers,
1069
+ ...explicitConfig.headers
1070
+ }
1071
+ };
1072
+ const provider = modelRef.provider;
1073
+ const handler = resolveEmbeddingHandler(provider);
1074
+ if (!handler) {
1075
+ throw new UPPError(
1076
+ `Provider '${provider.name}' does not support embedding modality`,
1077
+ ErrorCode.InvalidRequest,
1078
+ provider.name,
1079
+ ModalityType.Embedding
1080
+ );
1081
+ }
1082
+ const boundModel = handler.bind(modelRef.modelId);
1083
+ function embed(input, embedOptions) {
1084
+ const inputs = Array.isArray(input) ? input : [input];
1085
+ if (embedOptions?.chunked) {
1086
+ return createChunkedStream(boundModel, inputs, params, config, embedOptions, middleware);
1087
+ }
1088
+ return executeEmbed(boundModel, inputs, params, config, embedOptions?.signal, embedOptions?.inputType, middleware);
1089
+ }
1090
+ return {
1091
+ model: boundModel,
1092
+ params,
1093
+ embed
1094
+ };
1095
+ }
1075
1096
 
1076
1097
  // src/core/image.ts
1098
+ function normalizeInput(input) {
1099
+ if (typeof input === "string") {
1100
+ return input;
1101
+ }
1102
+ return input.prompt;
1103
+ }
1077
1104
  function image(options) {
1078
1105
  const { model: modelRef, config: explicitConfig = {}, params, middleware = [] } = options;
1079
1106
  const providerConfig = modelRef.providerConfig ?? {};
@@ -1108,13 +1135,13 @@ function image(options) {
1108
1135
  model: boundModel,
1109
1136
  params,
1110
1137
  capabilities,
1111
- async generate(input, options2) {
1138
+ async generate(input, generateOptions) {
1112
1139
  const prompt = normalizeInput(input);
1113
1140
  const request = {
1114
1141
  prompt,
1115
1142
  params,
1116
1143
  config,
1117
- signal: options2?.signal
1144
+ signal: generateOptions?.signal
1118
1145
  };
1119
1146
  const ctx = createMiddlewareContext(
1120
1147
  "image",
@@ -1225,14 +1252,22 @@ function image(options) {
1225
1252
  }
1226
1253
  return instance;
1227
1254
  }
1228
- function normalizeInput(input) {
1229
- if (typeof input === "string") {
1230
- return input;
1231
- }
1232
- return input.prompt;
1233
- }
1234
1255
 
1235
1256
  // src/core/media/document.ts
1257
+ function detectMimeType(path) {
1258
+ const ext = path.split(".").pop()?.toLowerCase();
1259
+ switch (ext) {
1260
+ case "pdf":
1261
+ return "application/pdf";
1262
+ case "txt":
1263
+ case "text":
1264
+ case "md":
1265
+ case "markdown":
1266
+ return "text/plain";
1267
+ default:
1268
+ return "application/octet-stream";
1269
+ }
1270
+ }
1236
1271
  var Document = class _Document {
1237
1272
  /** The underlying document source (base64, url, or text) */
1238
1273
  source;
@@ -1443,22 +1478,33 @@ var Document = class _Document {
1443
1478
  );
1444
1479
  }
1445
1480
  };
1446
- function detectMimeType(path) {
1481
+
1482
+ // src/core/media/Audio.ts
1483
+ function detectMimeType2(path) {
1447
1484
  const ext = path.split(".").pop()?.toLowerCase();
1448
1485
  switch (ext) {
1449
- case "pdf":
1450
- return "application/pdf";
1451
- case "txt":
1452
- case "text":
1453
- case "md":
1454
- case "markdown":
1455
- return "text/plain";
1486
+ case "mp3":
1487
+ return "audio/mp3";
1488
+ case "wav":
1489
+ return "audio/wav";
1490
+ case "ogg":
1491
+ case "oga":
1492
+ return "audio/ogg";
1493
+ case "flac":
1494
+ return "audio/flac";
1495
+ case "aac":
1496
+ return "audio/aac";
1497
+ case "m4a":
1498
+ return "audio/mp4";
1499
+ case "webm":
1500
+ return "audio/webm";
1501
+ case "aiff":
1502
+ case "aif":
1503
+ return "audio/aiff";
1456
1504
  default:
1457
1505
  return "application/octet-stream";
1458
1506
  }
1459
1507
  }
1460
-
1461
- // src/core/media/Audio.ts
1462
1508
  var Audio = class _Audio {
1463
1509
  /** The audio data as raw bytes */
1464
1510
  data;
@@ -1609,33 +1655,37 @@ var Audio = class _Audio {
1609
1655
  );
1610
1656
  }
1611
1657
  };
1612
- function detectMimeType2(path) {
1658
+
1659
+ // src/core/media/Video.ts
1660
+ function detectMimeType3(path) {
1613
1661
  const ext = path.split(".").pop()?.toLowerCase();
1614
1662
  switch (ext) {
1615
- case "mp3":
1616
- return "audio/mp3";
1617
- case "wav":
1618
- return "audio/wav";
1619
- case "ogg":
1620
- case "oga":
1621
- return "audio/ogg";
1622
- case "flac":
1623
- return "audio/flac";
1624
- case "aac":
1625
- return "audio/aac";
1626
- case "m4a":
1627
- return "audio/mp4";
1663
+ case "mp4":
1664
+ case "m4v":
1665
+ return "video/mp4";
1628
1666
  case "webm":
1629
- return "audio/webm";
1630
- case "aiff":
1631
- case "aif":
1632
- return "audio/aiff";
1667
+ return "video/webm";
1668
+ case "ogv":
1669
+ case "ogg":
1670
+ return "video/ogg";
1671
+ case "mov":
1672
+ return "video/quicktime";
1673
+ case "avi":
1674
+ return "video/x-msvideo";
1675
+ case "mpeg":
1676
+ case "mpg":
1677
+ return "video/mpeg";
1678
+ case "wmv":
1679
+ return "video/x-ms-wmv";
1680
+ case "3gp":
1681
+ case "3gpp":
1682
+ return "video/3gpp";
1683
+ case "flv":
1684
+ return "video/x-flv";
1633
1685
  default:
1634
1686
  return "application/octet-stream";
1635
1687
  }
1636
1688
  }
1637
-
1638
- // src/core/media/Video.ts
1639
1689
  var Video = class _Video {
1640
1690
  /** The video data as raw bytes */
1641
1691
  data;
@@ -1800,35 +1850,6 @@ var Video = class _Video {
1800
1850
  );
1801
1851
  }
1802
1852
  };
1803
- function detectMimeType3(path) {
1804
- const ext = path.split(".").pop()?.toLowerCase();
1805
- switch (ext) {
1806
- case "mp4":
1807
- case "m4v":
1808
- return "video/mp4";
1809
- case "webm":
1810
- return "video/webm";
1811
- case "ogv":
1812
- case "ogg":
1813
- return "video/ogg";
1814
- case "mov":
1815
- return "video/quicktime";
1816
- case "avi":
1817
- return "video/x-msvideo";
1818
- case "mpeg":
1819
- case "mpg":
1820
- return "video/mpeg";
1821
- case "wmv":
1822
- return "video/x-ms-wmv";
1823
- case "3gp":
1824
- case "3gpp":
1825
- return "video/3gpp";
1826
- case "flv":
1827
- return "video/x-flv";
1828
- default:
1829
- return "application/octet-stream";
1830
- }
1831
- }
1832
1853
 
1833
1854
  // src/types/thread.ts
1834
1855
  var Thread = class _Thread {
@@ -2091,274 +2112,6 @@ var EmbeddingInputType = {
2091
2112
  Query: "query"
2092
2113
  };
2093
2114
 
2094
- // src/utils/partial-json.ts
2095
- function parsePartialJson(json) {
2096
- const trimmed = json.trim();
2097
- if (trimmed === "") {
2098
- return { value: void 0, isComplete: false };
2099
- }
2100
- try {
2101
- const value = JSON.parse(trimmed);
2102
- return { value, isComplete: true };
2103
- } catch {
2104
- }
2105
- try {
2106
- const repaired = repairJson(trimmed);
2107
- const value = JSON.parse(repaired);
2108
- return { value, isComplete: false };
2109
- } catch {
2110
- return { value: void 0, isComplete: false };
2111
- }
2112
- }
2113
- function repairJson(json) {
2114
- let result = json;
2115
- const stack = [];
2116
- let inString = false;
2117
- let escape = false;
2118
- for (let i = 0; i < result.length; i++) {
2119
- const char = result[i];
2120
- if (escape) {
2121
- escape = false;
2122
- continue;
2123
- }
2124
- if (char === "\\" && inString) {
2125
- escape = true;
2126
- continue;
2127
- }
2128
- if (char === '"' && !escape) {
2129
- inString = !inString;
2130
- }
2131
- if (!inString) {
2132
- if (char === "{") {
2133
- stack.push("{");
2134
- } else if (char === "[") {
2135
- stack.push("[");
2136
- } else if (char === "}") {
2137
- if (stack.length > 0 && stack[stack.length - 1] === "{") {
2138
- stack.pop();
2139
- }
2140
- } else if (char === "]") {
2141
- if (stack.length > 0 && stack[stack.length - 1] === "[") {
2142
- stack.pop();
2143
- }
2144
- }
2145
- }
2146
- }
2147
- if (inString) {
2148
- const unicodeMatch = result.match(/\\u[0-9a-fA-F]{0,3}$/);
2149
- if (unicodeMatch) {
2150
- result = result.slice(0, -unicodeMatch[0].length);
2151
- }
2152
- if (result.endsWith("\\")) {
2153
- result = result.slice(0, -1);
2154
- }
2155
- result += '"';
2156
- inString = false;
2157
- }
2158
- result = cleanupTrailingIncomplete(result);
2159
- while (stack.length > 0) {
2160
- const open = stack.pop();
2161
- if (open === "{") {
2162
- result += "}";
2163
- } else {
2164
- result += "]";
2165
- }
2166
- }
2167
- return result;
2168
- }
2169
- function cleanupTrailingIncomplete(json) {
2170
- let result = json.trim();
2171
- let changed = true;
2172
- while (changed) {
2173
- changed = false;
2174
- const trimmed = result.trim();
2175
- if (trimmed.endsWith(",")) {
2176
- result = trimmed.slice(0, -1);
2177
- changed = true;
2178
- continue;
2179
- }
2180
- if (trimmed.endsWith(":")) {
2181
- const colonIndex = trimmed.length - 1;
2182
- let keyStart = colonIndex - 1;
2183
- while (keyStart >= 0 && /\s/.test(trimmed[keyStart])) {
2184
- keyStart--;
2185
- }
2186
- if (keyStart >= 0 && trimmed[keyStart] === '"') {
2187
- keyStart--;
2188
- while (keyStart >= 0 && trimmed[keyStart] !== '"') {
2189
- keyStart--;
2190
- }
2191
- keyStart--;
2192
- while (keyStart >= 0 && /\s/.test(trimmed[keyStart])) {
2193
- keyStart--;
2194
- }
2195
- if (keyStart >= 0 && trimmed[keyStart] === ",") {
2196
- result = trimmed.slice(0, keyStart);
2197
- } else {
2198
- result = trimmed.slice(0, keyStart + 1);
2199
- }
2200
- changed = true;
2201
- continue;
2202
- }
2203
- }
2204
- const literalMatch = trimmed.match(/(,?\s*)(t(?:r(?:ue?)?)?|f(?:a(?:l(?:se?)?)?)?|n(?:u(?:ll?)?)?)$/i);
2205
- if (literalMatch && literalMatch[2]) {
2206
- const partial = literalMatch[2].toLowerCase();
2207
- const literals = ["true", "false", "null"];
2208
- const match = literals.find((lit) => lit.startsWith(partial) && partial !== lit);
2209
- if (match) {
2210
- result = trimmed.slice(0, -literalMatch[2].length) + match;
2211
- changed = true;
2212
- continue;
2213
- }
2214
- }
2215
- const numberMatch = trimmed.match(/(,?\s*)(-?(?:\d+\.|\d*\.?\d+[eE][+-]?|\d+[eE]|-))$/);
2216
- if (numberMatch && numberMatch[2]) {
2217
- const partial = numberMatch[2];
2218
- if (/[.eE+-]$/.test(partial)) {
2219
- if (partial === "-") {
2220
- result = trimmed.slice(0, -(numberMatch[0]?.length ?? 0)).trimEnd();
2221
- } else {
2222
- result = trimmed.slice(0, -1);
2223
- }
2224
- changed = true;
2225
- continue;
2226
- }
2227
- }
2228
- }
2229
- return result;
2230
- }
2231
-
2232
- // src/middleware/parsed-object.ts
2233
- var ACCUMULATED_TEXT_KEY = "parsedObject:text";
2234
- var ACCUMULATED_ARGS_KEY = "parsedObject:args";
2235
- function getAccumulatedText(state) {
2236
- let map = state.get(ACCUMULATED_TEXT_KEY);
2237
- if (!map) {
2238
- map = /* @__PURE__ */ new Map();
2239
- state.set(ACCUMULATED_TEXT_KEY, map);
2240
- }
2241
- return map;
2242
- }
2243
- function getAccumulatedArgs(state) {
2244
- let map = state.get(ACCUMULATED_ARGS_KEY);
2245
- if (!map) {
2246
- map = /* @__PURE__ */ new Map();
2247
- state.set(ACCUMULATED_ARGS_KEY, map);
2248
- }
2249
- return map;
2250
- }
2251
- function parsedObjectMiddleware(options = {}) {
2252
- const { parseObjects = true, parseToolCalls = true } = options;
2253
- return {
2254
- name: "parsed-object",
2255
- onStreamEvent(event, ctx) {
2256
- if (parseObjects && event.type === StreamEventType.ObjectDelta) {
2257
- const accumulatedText = getAccumulatedText(ctx.state);
2258
- const current = accumulatedText.get(event.index) ?? "";
2259
- const newText = current + (event.delta.text ?? "");
2260
- accumulatedText.set(event.index, newText);
2261
- const parseResult = parsePartialJson(newText);
2262
- const parsedEvent = {
2263
- ...event,
2264
- delta: {
2265
- ...event.delta,
2266
- parsed: parseResult.value
2267
- }
2268
- };
2269
- return parsedEvent;
2270
- }
2271
- if (parseToolCalls && event.type === StreamEventType.ToolCallDelta) {
2272
- const accumulatedArgs = getAccumulatedArgs(ctx.state);
2273
- const current = accumulatedArgs.get(event.index) ?? "";
2274
- const newJson = current + (event.delta.argumentsJson ?? "");
2275
- accumulatedArgs.set(event.index, newJson);
2276
- const parseResult = parsePartialJson(newJson);
2277
- const parsedEvent = {
2278
- ...event,
2279
- delta: {
2280
- ...event.delta,
2281
- parsed: parseResult.value
2282
- }
2283
- };
2284
- return parsedEvent;
2285
- }
2286
- return event;
2287
- },
2288
- onStreamEnd(ctx) {
2289
- ctx.state.delete(ACCUMULATED_TEXT_KEY);
2290
- ctx.state.delete(ACCUMULATED_ARGS_KEY);
2291
- }
2292
- };
2293
- }
2294
-
2295
- // src/middleware/logging.ts
2296
- var LOG_LEVELS = {
2297
- debug: 0,
2298
- info: 1,
2299
- warn: 2,
2300
- error: 3
2301
- };
2302
- function loggingMiddleware(options = {}) {
2303
- const {
2304
- level = "info",
2305
- logStreamEvents = false,
2306
- logToolCalls = true,
2307
- logger,
2308
- prefix = "[PP]"
2309
- } = options;
2310
- const minLevel = LOG_LEVELS[level];
2311
- const log = (logLevel, message, data) => {
2312
- if (LOG_LEVELS[logLevel] < minLevel) {
2313
- return;
2314
- }
2315
- const fullMessage = `${prefix} ${message}`;
2316
- if (logger) {
2317
- logger(logLevel, fullMessage, data);
2318
- } else {
2319
- const consoleMethod = logLevel === "error" ? console.error : logLevel === "warn" ? console.warn : console.log;
2320
- if (data) {
2321
- consoleMethod(fullMessage, data);
2322
- } else {
2323
- consoleMethod(fullMessage);
2324
- }
2325
- }
2326
- };
2327
- return {
2328
- name: "logging",
2329
- onStart(ctx) {
2330
- const streamingLabel = ctx.streaming ? "(streaming)" : "";
2331
- log("info", `[${ctx.provider}] Starting ${ctx.modality} request ${streamingLabel}`.trim());
2332
- log("debug", `[${ctx.provider}] Model: ${ctx.modelId}`);
2333
- },
2334
- onEnd(ctx) {
2335
- const duration = ctx.endTime ? ctx.endTime - ctx.startTime : 0;
2336
- log("info", `[${ctx.provider}] Completed in ${duration}ms`);
2337
- },
2338
- onError(error, ctx) {
2339
- const duration = Date.now() - ctx.startTime;
2340
- log("error", `[${ctx.provider}] Error after ${duration}ms: ${error.message}`);
2341
- },
2342
- onStreamEvent(event, ctx) {
2343
- if (logStreamEvents) {
2344
- log("debug", `Stream event: ${event.type}`, { index: event.index });
2345
- }
2346
- return event;
2347
- },
2348
- onToolCall(tool, params, ctx) {
2349
- if (logToolCalls) {
2350
- log("info", `[${ctx.provider}] Tool call: ${tool.name}`);
2351
- log("debug", `[${ctx.provider}] Tool params:`, { params });
2352
- }
2353
- },
2354
- onToolResult(tool, result, ctx) {
2355
- if (logToolCalls) {
2356
- log("debug", `[${ctx.provider}] Tool result: ${tool.name}`, { result });
2357
- }
2358
- }
2359
- };
2360
- }
2361
-
2362
2115
  // src/index.ts
2363
2116
  var ai = {
2364
2117
  /** LLM instance factory */
@@ -2416,11 +2169,9 @@ export {
2416
2169
  isUserMessage,
2417
2170
  isVideoBlock,
2418
2171
  llm,
2419
- loggingMiddleware,
2420
2172
  messageStart,
2421
2173
  messageStop,
2422
2174
  objectDelta,
2423
- parsedObjectMiddleware,
2424
2175
  reasoning,
2425
2176
  text,
2426
2177
  textDelta,