@absolutejs/ai 0.3.4 → 0.4.1

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.
@@ -567,7 +567,7 @@ async function* tapStream(source, params, providerName) {
567
567
  let lastUsage;
568
568
  try {
569
569
  for await (const chunk of source) {
570
- if (chunk.type === "done" && chunk.usage) {
570
+ if ((chunk.type === "done" || chunk.type === "usage_update" && chunk.final) && chunk.usage) {
571
571
  lastUsage = chunk.usage;
572
572
  }
573
573
  yield chunk;
@@ -1180,6 +1180,8 @@ var processCompleted = function* (parsed) {
1180
1180
  const { response } = parsed;
1181
1181
  const usage = extractUsage(response);
1182
1182
  const metadata = extractResponseMetadata(response);
1183
+ if (usage)
1184
+ yield { type: "usage_update", usage, metadata, final: true };
1183
1185
  if (isRecordArray(response.output)) {
1184
1186
  yield* extractCitationsFromOutput(response.output);
1185
1187
  yield* extractImageFromOutput(response.output);
@@ -1218,6 +1220,15 @@ var processSSEEvent = function* (eventType, parsed, pendingCalls, providerName)
1218
1220
  break;
1219
1221
  case "response.output_item.added":
1220
1222
  processOutputItemAdded(parsed, pendingCalls);
1223
+ if (isRecord(parsed.item) && parsed.item.type === "function_call" && typeof parsed.item.name === "string") {
1224
+ const id = typeof parsed.item.call_id === "string" ? parsed.item.call_id : parsed.item.id;
1225
+ if (typeof id === "string")
1226
+ yield {
1227
+ type: "tool_input_start",
1228
+ id,
1229
+ name: parsed.item.name
1230
+ };
1231
+ }
1221
1232
  break;
1222
1233
  case "response.output_item.done":
1223
1234
  yield* processOutputItemDone(parsed);
@@ -1234,8 +1245,19 @@ var processSSEEvent = function* (eventType, parsed, pendingCalls, providerName)
1234
1245
  case "response.failed":
1235
1246
  case "response.incomplete":
1236
1247
  case "response.error":
1237
- case "error":
1248
+ case "error": {
1249
+ if (isRecord(parsed.response)) {
1250
+ const usage = extractUsage(parsed.response);
1251
+ if (usage)
1252
+ yield {
1253
+ type: "usage_update",
1254
+ usage,
1255
+ metadata: extractResponseMetadata(parsed.response),
1256
+ final: false
1257
+ };
1258
+ }
1238
1259
  throw responseFailure(eventType, parsed, providerName);
1260
+ }
1239
1261
  }
1240
1262
  };
1241
1263
  var flushSSEBuffer = function* (state) {
@@ -1657,6 +1679,14 @@ var processDelta = function* (delta, pendingToolCalls) {
1657
1679
  }
1658
1680
  if (isRecordArray2(delta.tool_calls)) {
1659
1681
  processToolCallDeltas(delta.tool_calls, pendingToolCalls);
1682
+ for (const call of delta.tool_calls) {
1683
+ if (isRecord2(call.function) && typeof call.function.name === "string" && call.function.name)
1684
+ yield {
1685
+ type: "tool_input_start",
1686
+ id: typeof call.id === "string" ? call.id : String(call.index),
1687
+ name: call.function.name
1688
+ };
1689
+ }
1660
1690
  }
1661
1691
  if (Array.isArray(delta.annotations)) {
1662
1692
  for (const annotation of delta.annotations) {
@@ -1755,7 +1785,12 @@ var processSSELine2 = function* (line, pendingToolCalls, providerName) {
1755
1785
  }
1756
1786
  const usageUpdate = narrowUsageRecord(parsed);
1757
1787
  if (usageUpdate) {
1758
- yield { type: "usage_update", usage: usageUpdate };
1788
+ yield {
1789
+ type: "usage_update",
1790
+ usage: usageUpdate,
1791
+ final: Array.isArray(parsed.choices) && parsed.choices.length === 0,
1792
+ metadata: narrowResponseMetadata(parsed)
1793
+ };
1759
1794
  }
1760
1795
  const metadata = narrowResponseMetadata(parsed);
1761
1796
  if (metadata) {
@@ -1784,10 +1819,9 @@ var processSSELine2 = function* (line, pendingToolCalls, providerName) {
1784
1819
  }
1785
1820
  yield* processChoice(firstChoice, pendingToolCalls);
1786
1821
  };
1787
- var isUsageUpdate = (chunk) => chunk.type === "usage_update";
1788
1822
  var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef, providerName) => {
1789
1823
  const allChunks = Array.from(processSSELine2(line, pendingToolCalls, providerName));
1790
- const usageChunks = allChunks.filter(isUsageUpdate);
1824
+ const usageChunks = allChunks.filter((chunk) => chunk.type === "usage_update");
1791
1825
  const lastUsage = usageChunks.at(NOT_FOUND);
1792
1826
  if (lastUsage) {
1793
1827
  usageRef.current = lastUsage.usage;
@@ -1804,7 +1838,7 @@ var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef, pro
1804
1838
  }
1805
1839
  };
1806
1840
  }
1807
- return allChunks.filter((chunk) => !isUsageUpdate(chunk) && chunk.type !== "response_metadata");
1841
+ return allChunks.filter((chunk) => chunk.type !== "response_metadata").map((chunk) => chunk.type === "usage_update" ? { ...chunk, metadata: metadataRef.current } : chunk);
1808
1842
  };
1809
1843
  var processSSELines2 = function* (lines, pendingToolCalls, usageRef, metadataRef, providerName) {
1810
1844
  for (const line of lines) {
@@ -1922,7 +1956,6 @@ var API_VERSION = "2023-06-01";
1922
1956
  var DEFAULT_MAX_TOKENS = 32000;
1923
1957
  var EVENT_PREFIX_LENGTH2 = 7;
1924
1958
  var DATA_PREFIX_LENGTH2 = 6;
1925
- var EMPTY_CHUNKS = [];
1926
1959
  var isRecord3 = (val) => typeof val === "object" && val !== null;
1927
1960
  var mapContentBlock = (block) => {
1928
1961
  if (block.type === "thinking") {
@@ -2201,14 +2234,79 @@ var getNumber = (obj, key) => {
2201
2234
  }
2202
2235
  return 0;
2203
2236
  };
2237
+ var TOOL_INPUT_PROGRESS_CHARS = 2048;
2238
+ var TOOL_INPUT_FIELD_MAX_CHARS = 200;
2239
+ var readJsonString = (json, start) => {
2240
+ for (let index = start + 1;index < json.length; index += 1) {
2241
+ if (json[index] === "\\")
2242
+ index += 1;
2243
+ else if (json[index] === '"')
2244
+ return { end: index + 1, raw: json.slice(start + 1, index) };
2245
+ }
2246
+ return;
2247
+ };
2248
+ var decodeJsonString = (raw) => {
2249
+ try {
2250
+ const value = JSON.parse(`"${raw}"`);
2251
+ return typeof value === "string" ? value : undefined;
2252
+ } catch {
2253
+ return;
2254
+ }
2255
+ };
2256
+ var completeStringFields = (partialJson) => {
2257
+ const fields = {};
2258
+ let depth = 0;
2259
+ let key;
2260
+ let index = 0;
2261
+ while (index < partialJson.length) {
2262
+ const character = partialJson[index];
2263
+ if (character === '"') {
2264
+ const text = readJsonString(partialJson, index);
2265
+ if (!text)
2266
+ break;
2267
+ if (depth === 1 && key === undefined) {
2268
+ const after = partialJson.slice(text.end).trimStart();
2269
+ if (after.startsWith(":"))
2270
+ key = text.raw;
2271
+ } else if (depth === 1 && key !== undefined) {
2272
+ const value = decodeJsonString(text.raw);
2273
+ if (value !== undefined && value.length <= TOOL_INPUT_FIELD_MAX_CHARS)
2274
+ fields[key] = value;
2275
+ key = undefined;
2276
+ }
2277
+ index = text.end;
2278
+ continue;
2279
+ }
2280
+ if (character === "{" || character === "[")
2281
+ depth += 1;
2282
+ else if (character === "}" || character === "]")
2283
+ depth -= 1;
2284
+ else if (character === "," && depth === 1)
2285
+ key = undefined;
2286
+ index += 1;
2287
+ }
2288
+ return fields;
2289
+ };
2290
+ var toolInputProgress = (state) => {
2291
+ state.toolInputReported = state.toolInputJson.length;
2292
+ return {
2293
+ fields: completeStringFields(state.toolInputJson),
2294
+ id: state.currentToolId,
2295
+ name: state.currentToolName,
2296
+ receivedChars: state.toolInputJson.length,
2297
+ type: "tool_input"
2298
+ };
2299
+ };
2204
2300
  var handleContentBlockStart = (parsed, state) => {
2205
2301
  const block = getRecord(parsed, "content_block");
2206
2302
  if (block && block.type === "tool_use") {
2207
2303
  state.currentToolId = getString(block, "id");
2208
2304
  state.currentToolName = getString(block, "name");
2209
2305
  state.toolInputJson = "";
2306
+ state.toolInputReported = 0;
2210
2307
  state.isThinkingBlock = false;
2211
2308
  state.currentProviderBlock = undefined;
2309
+ return toolInputProgress(state);
2212
2310
  } else if (block && block.type === "thinking") {
2213
2311
  state.isThinkingBlock = true;
2214
2312
  state.thinkingSignature = "";
@@ -2218,6 +2316,7 @@ var handleContentBlockStart = (parsed, state) => {
2218
2316
  state.currentProviderBlock = block && block.type !== "text" ? { ...block } : undefined;
2219
2317
  state.providerBlockInputJson = "";
2220
2318
  }
2319
+ return;
2221
2320
  };
2222
2321
  var handleContentBlockDelta = (parsed, state) => {
2223
2322
  const delta = getRecord(parsed, "delta");
@@ -2252,6 +2351,8 @@ var handleContentBlockDelta = (parsed, state) => {
2252
2351
  state.providerBlockInputJson += getString(delta, "partial_json");
2253
2352
  } else {
2254
2353
  state.toolInputJson += getString(delta, "partial_json");
2354
+ if (state.toolInputJson.length - state.toolInputReported >= TOOL_INPUT_PROGRESS_CHARS)
2355
+ return toolInputProgress(state);
2255
2356
  }
2256
2357
  }
2257
2358
  if (delta.type === "signature_delta") {
@@ -2371,8 +2472,7 @@ var handleError = (parsed, state) => {
2371
2472
  var processEvent = (eventType, parsed, state) => {
2372
2473
  switch (eventType) {
2373
2474
  case "content_block_start": {
2374
- handleContentBlockStart(parsed, state);
2375
- return;
2475
+ return handleContentBlockStart(parsed, state);
2376
2476
  }
2377
2477
  case "content_block_delta": {
2378
2478
  return handleContentBlockDelta(parsed, state);
@@ -2383,11 +2483,21 @@ var processEvent = (eventType, parsed, state) => {
2383
2483
  case "message_delta": {
2384
2484
  handleMessageDelta(parsed, state);
2385
2485
  mergeMetadata(parsed, state);
2386
- return;
2486
+ return state.usage ? {
2487
+ type: "usage_update",
2488
+ usage: state.usage,
2489
+ metadata: state.metadata,
2490
+ final: false
2491
+ } : undefined;
2387
2492
  }
2388
2493
  case "message_start": {
2389
2494
  handleMessageStart(parsed, state);
2390
- return;
2495
+ return state.usage ? {
2496
+ type: "usage_update",
2497
+ usage: state.usage,
2498
+ metadata: state.metadata,
2499
+ final: false
2500
+ } : undefined;
2391
2501
  }
2392
2502
  case "message_stop": {
2393
2503
  mergeMetadata(parsed, state);
@@ -2421,49 +2531,6 @@ var processSingleEvent = (event, state) => {
2421
2531
  }
2422
2532
  return processEvent(eventType, parsed, state);
2423
2533
  };
2424
- var collectChunk = (event, state) => {
2425
- const chunk = processSingleEvent(event, state);
2426
- return chunk ? [chunk] : [];
2427
- };
2428
- var processBufferedEvents = (eventsText, state) => {
2429
- const events = eventsText.split(`
2430
-
2431
- `);
2432
- state.buffer = events.pop() ?? "";
2433
- return events.flatMap((event) => collectChunk(event, state));
2434
- };
2435
- var readNextChunks = async (reader, decoder, state, signal) => {
2436
- if (signal?.aborted) {
2437
- return { chunks: EMPTY_CHUNKS, done: true };
2438
- }
2439
- const { done, value } = await reader.read();
2440
- if (done) {
2441
- return { chunks: EMPTY_CHUNKS, done: true };
2442
- }
2443
- const rawText = state.buffer + decoder.decode(value, { stream: true });
2444
- const chunks = processBufferedEvents(rawText, state);
2445
- return { chunks, done: false };
2446
- };
2447
- var findDoneChunk = (chunks) => chunks.findIndex((c) => c.type === "done");
2448
- var sseStreamLoop = async (reader, decoder, state, signal) => {
2449
- const result = await readNextChunks(reader, decoder, state, signal);
2450
- if (result.done) {
2451
- return { chunks: result.chunks, finished: true };
2452
- }
2453
- const doneIdx = findDoneChunk(result.chunks);
2454
- if (doneIdx >= 0) {
2455
- return { chunks: result.chunks.slice(0, doneIdx + 1), finished: true };
2456
- }
2457
- return { chunks: result.chunks, finished: false };
2458
- };
2459
- async function* streamChunks(reader, decoder, state, signal) {
2460
- let finished = false;
2461
- while (!finished) {
2462
- const result = await sseStreamLoop(reader, decoder, state, signal);
2463
- ({ finished } = result);
2464
- yield* result.chunks;
2465
- }
2466
- }
2467
2534
  async function* parseSSEStream3(body, providerName, signal) {
2468
2535
  const reader = body.getReader();
2469
2536
  const decoder = new TextDecoder;
@@ -2475,13 +2542,40 @@ async function* parseSSEStream3(body, providerName, signal) {
2475
2542
  stopReason: "",
2476
2543
  thinkingSignature: "",
2477
2544
  toolInputJson: "",
2545
+ toolInputReported: 0,
2478
2546
  usage: undefined,
2479
2547
  providerName,
2480
2548
  providerBlockInputJson: ""
2481
2549
  };
2482
2550
  try {
2483
- yield* streamChunks(reader, decoder, state, signal);
2551
+ while (true) {
2552
+ signal?.throwIfAborted();
2553
+ const { done, value } = await reader.read();
2554
+ if (done)
2555
+ return;
2556
+ const events = (state.buffer + decoder.decode(value, { stream: true })).split(`
2557
+
2558
+ `);
2559
+ state.buffer = events.pop() ?? "";
2560
+ for (const event of events) {
2561
+ const chunk = processSingleEvent(event, state);
2562
+ if (!chunk)
2563
+ continue;
2564
+ if (chunk.type === "tool_input" && chunk.receivedChars === 0)
2565
+ yield {
2566
+ type: "tool_input_start",
2567
+ id: chunk.id,
2568
+ name: chunk.name
2569
+ };
2570
+ yield chunk;
2571
+ if (chunk.type === "done")
2572
+ return;
2573
+ }
2574
+ }
2484
2575
  } finally {
2576
+ await reader.cancel().catch(() => {
2577
+ return;
2578
+ });
2485
2579
  reader.releaseLock();
2486
2580
  }
2487
2581
  }
@@ -3518,5 +3612,5 @@ export {
3518
3612
  verifyOpenRouterWebhookSignature
3519
3613
  };
3520
3614
 
3521
- //# debugId=47F788AD8F60934664756E2164756E21
3615
+ //# debugId=197F4FFE0DB1613B64756E2164756E21
3522
3616
  //# sourceMappingURL=openrouter.js.map