@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.
- package/CHANGELOG.md +18 -0
- package/README.md +15 -0
- package/changelog.json +43 -0
- package/dist/ai/index.js +170 -60
- package/dist/ai/index.js.map +9 -9
- package/dist/ai/providers/anthropic.js +111 -51
- package/dist/ai/providers/anthropic.js.map +4 -4
- package/dist/ai/providers/gemini.js +2 -2
- package/dist/ai/providers/gemini.js.map +3 -3
- package/dist/ai/providers/ollama.js +2 -2
- package/dist/ai/providers/ollama.js.map +4 -4
- package/dist/ai/providers/openai.js +41 -7
- package/dist/ai/providers/openai.js.map +5 -5
- package/dist/ai/providers/openaiCompatible.js +41 -7
- package/dist/ai/providers/openaiCompatible.js.map +5 -5
- package/dist/ai/providers/openaiResponses.js +25 -3
- package/dist/ai/providers/openaiResponses.js.map +4 -4
- package/dist/ai/providers/openrouter.js +150 -56
- package/dist/ai/providers/openrouter.js.map +6 -6
- package/dist/angular/ai/index.js +9 -7
- package/dist/angular/ai/index.js.map +2 -2
- package/dist/src/ai/streamAIWithTools.d.ts +4 -0
- package/dist/types/ai.d.ts +26 -1
- package/dist/types/anthropic.d.ts +2 -0
- package/package.json +1 -1
|
@@ -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 {
|
|
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(
|
|
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) =>
|
|
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
|
-
|
|
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=
|
|
3615
|
+
//# debugId=197F4FFE0DB1613B64756E2164756E21
|
|
3522
3616
|
//# sourceMappingURL=openrouter.js.map
|