@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
|
@@ -351,7 +351,7 @@ async function* tapStream(source, params, providerName) {
|
|
|
351
351
|
let lastUsage;
|
|
352
352
|
try {
|
|
353
353
|
for await (const chunk of source) {
|
|
354
|
-
if (chunk.type === "done" && chunk.usage) {
|
|
354
|
+
if ((chunk.type === "done" || chunk.type === "usage_update" && chunk.final) && chunk.usage) {
|
|
355
355
|
lastUsage = chunk.usage;
|
|
356
356
|
}
|
|
357
357
|
yield chunk;
|
|
@@ -597,7 +597,6 @@ var API_VERSION = "2023-06-01";
|
|
|
597
597
|
var DEFAULT_MAX_TOKENS = 32000;
|
|
598
598
|
var EVENT_PREFIX_LENGTH = 7;
|
|
599
599
|
var DATA_PREFIX_LENGTH = 6;
|
|
600
|
-
var EMPTY_CHUNKS = [];
|
|
601
600
|
var isRecord = (val) => typeof val === "object" && val !== null;
|
|
602
601
|
var mapContentBlock = (block) => {
|
|
603
602
|
if (block.type === "thinking") {
|
|
@@ -876,14 +875,79 @@ var getNumber = (obj, key) => {
|
|
|
876
875
|
}
|
|
877
876
|
return 0;
|
|
878
877
|
};
|
|
878
|
+
var TOOL_INPUT_PROGRESS_CHARS = 2048;
|
|
879
|
+
var TOOL_INPUT_FIELD_MAX_CHARS = 200;
|
|
880
|
+
var readJsonString = (json, start) => {
|
|
881
|
+
for (let index = start + 1;index < json.length; index += 1) {
|
|
882
|
+
if (json[index] === "\\")
|
|
883
|
+
index += 1;
|
|
884
|
+
else if (json[index] === '"')
|
|
885
|
+
return { end: index + 1, raw: json.slice(start + 1, index) };
|
|
886
|
+
}
|
|
887
|
+
return;
|
|
888
|
+
};
|
|
889
|
+
var decodeJsonString = (raw) => {
|
|
890
|
+
try {
|
|
891
|
+
const value = JSON.parse(`"${raw}"`);
|
|
892
|
+
return typeof value === "string" ? value : undefined;
|
|
893
|
+
} catch {
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
var completeStringFields = (partialJson) => {
|
|
898
|
+
const fields = {};
|
|
899
|
+
let depth = 0;
|
|
900
|
+
let key;
|
|
901
|
+
let index = 0;
|
|
902
|
+
while (index < partialJson.length) {
|
|
903
|
+
const character = partialJson[index];
|
|
904
|
+
if (character === '"') {
|
|
905
|
+
const text = readJsonString(partialJson, index);
|
|
906
|
+
if (!text)
|
|
907
|
+
break;
|
|
908
|
+
if (depth === 1 && key === undefined) {
|
|
909
|
+
const after = partialJson.slice(text.end).trimStart();
|
|
910
|
+
if (after.startsWith(":"))
|
|
911
|
+
key = text.raw;
|
|
912
|
+
} else if (depth === 1 && key !== undefined) {
|
|
913
|
+
const value = decodeJsonString(text.raw);
|
|
914
|
+
if (value !== undefined && value.length <= TOOL_INPUT_FIELD_MAX_CHARS)
|
|
915
|
+
fields[key] = value;
|
|
916
|
+
key = undefined;
|
|
917
|
+
}
|
|
918
|
+
index = text.end;
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
if (character === "{" || character === "[")
|
|
922
|
+
depth += 1;
|
|
923
|
+
else if (character === "}" || character === "]")
|
|
924
|
+
depth -= 1;
|
|
925
|
+
else if (character === "," && depth === 1)
|
|
926
|
+
key = undefined;
|
|
927
|
+
index += 1;
|
|
928
|
+
}
|
|
929
|
+
return fields;
|
|
930
|
+
};
|
|
931
|
+
var toolInputProgress = (state) => {
|
|
932
|
+
state.toolInputReported = state.toolInputJson.length;
|
|
933
|
+
return {
|
|
934
|
+
fields: completeStringFields(state.toolInputJson),
|
|
935
|
+
id: state.currentToolId,
|
|
936
|
+
name: state.currentToolName,
|
|
937
|
+
receivedChars: state.toolInputJson.length,
|
|
938
|
+
type: "tool_input"
|
|
939
|
+
};
|
|
940
|
+
};
|
|
879
941
|
var handleContentBlockStart = (parsed, state) => {
|
|
880
942
|
const block = getRecord(parsed, "content_block");
|
|
881
943
|
if (block && block.type === "tool_use") {
|
|
882
944
|
state.currentToolId = getString(block, "id");
|
|
883
945
|
state.currentToolName = getString(block, "name");
|
|
884
946
|
state.toolInputJson = "";
|
|
947
|
+
state.toolInputReported = 0;
|
|
885
948
|
state.isThinkingBlock = false;
|
|
886
949
|
state.currentProviderBlock = undefined;
|
|
950
|
+
return toolInputProgress(state);
|
|
887
951
|
} else if (block && block.type === "thinking") {
|
|
888
952
|
state.isThinkingBlock = true;
|
|
889
953
|
state.thinkingSignature = "";
|
|
@@ -893,6 +957,7 @@ var handleContentBlockStart = (parsed, state) => {
|
|
|
893
957
|
state.currentProviderBlock = block && block.type !== "text" ? { ...block } : undefined;
|
|
894
958
|
state.providerBlockInputJson = "";
|
|
895
959
|
}
|
|
960
|
+
return;
|
|
896
961
|
};
|
|
897
962
|
var handleContentBlockDelta = (parsed, state) => {
|
|
898
963
|
const delta = getRecord(parsed, "delta");
|
|
@@ -927,6 +992,8 @@ var handleContentBlockDelta = (parsed, state) => {
|
|
|
927
992
|
state.providerBlockInputJson += getString(delta, "partial_json");
|
|
928
993
|
} else {
|
|
929
994
|
state.toolInputJson += getString(delta, "partial_json");
|
|
995
|
+
if (state.toolInputJson.length - state.toolInputReported >= TOOL_INPUT_PROGRESS_CHARS)
|
|
996
|
+
return toolInputProgress(state);
|
|
930
997
|
}
|
|
931
998
|
}
|
|
932
999
|
if (delta.type === "signature_delta") {
|
|
@@ -1046,8 +1113,7 @@ var handleError = (parsed, state) => {
|
|
|
1046
1113
|
var processEvent = (eventType, parsed, state) => {
|
|
1047
1114
|
switch (eventType) {
|
|
1048
1115
|
case "content_block_start": {
|
|
1049
|
-
handleContentBlockStart(parsed, state);
|
|
1050
|
-
return;
|
|
1116
|
+
return handleContentBlockStart(parsed, state);
|
|
1051
1117
|
}
|
|
1052
1118
|
case "content_block_delta": {
|
|
1053
1119
|
return handleContentBlockDelta(parsed, state);
|
|
@@ -1058,11 +1124,21 @@ var processEvent = (eventType, parsed, state) => {
|
|
|
1058
1124
|
case "message_delta": {
|
|
1059
1125
|
handleMessageDelta(parsed, state);
|
|
1060
1126
|
mergeMetadata(parsed, state);
|
|
1061
|
-
return
|
|
1127
|
+
return state.usage ? {
|
|
1128
|
+
type: "usage_update",
|
|
1129
|
+
usage: state.usage,
|
|
1130
|
+
metadata: state.metadata,
|
|
1131
|
+
final: false
|
|
1132
|
+
} : undefined;
|
|
1062
1133
|
}
|
|
1063
1134
|
case "message_start": {
|
|
1064
1135
|
handleMessageStart(parsed, state);
|
|
1065
|
-
return
|
|
1136
|
+
return state.usage ? {
|
|
1137
|
+
type: "usage_update",
|
|
1138
|
+
usage: state.usage,
|
|
1139
|
+
metadata: state.metadata,
|
|
1140
|
+
final: false
|
|
1141
|
+
} : undefined;
|
|
1066
1142
|
}
|
|
1067
1143
|
case "message_stop": {
|
|
1068
1144
|
mergeMetadata(parsed, state);
|
|
@@ -1096,49 +1172,6 @@ var processSingleEvent = (event, state) => {
|
|
|
1096
1172
|
}
|
|
1097
1173
|
return processEvent(eventType, parsed, state);
|
|
1098
1174
|
};
|
|
1099
|
-
var collectChunk = (event, state) => {
|
|
1100
|
-
const chunk = processSingleEvent(event, state);
|
|
1101
|
-
return chunk ? [chunk] : [];
|
|
1102
|
-
};
|
|
1103
|
-
var processBufferedEvents = (eventsText, state) => {
|
|
1104
|
-
const events = eventsText.split(`
|
|
1105
|
-
|
|
1106
|
-
`);
|
|
1107
|
-
state.buffer = events.pop() ?? "";
|
|
1108
|
-
return events.flatMap((event) => collectChunk(event, state));
|
|
1109
|
-
};
|
|
1110
|
-
var readNextChunks = async (reader, decoder, state, signal) => {
|
|
1111
|
-
if (signal?.aborted) {
|
|
1112
|
-
return { chunks: EMPTY_CHUNKS, done: true };
|
|
1113
|
-
}
|
|
1114
|
-
const { done, value } = await reader.read();
|
|
1115
|
-
if (done) {
|
|
1116
|
-
return { chunks: EMPTY_CHUNKS, done: true };
|
|
1117
|
-
}
|
|
1118
|
-
const rawText = state.buffer + decoder.decode(value, { stream: true });
|
|
1119
|
-
const chunks = processBufferedEvents(rawText, state);
|
|
1120
|
-
return { chunks, done: false };
|
|
1121
|
-
};
|
|
1122
|
-
var findDoneChunk = (chunks) => chunks.findIndex((c) => c.type === "done");
|
|
1123
|
-
var sseStreamLoop = async (reader, decoder, state, signal) => {
|
|
1124
|
-
const result = await readNextChunks(reader, decoder, state, signal);
|
|
1125
|
-
if (result.done) {
|
|
1126
|
-
return { chunks: result.chunks, finished: true };
|
|
1127
|
-
}
|
|
1128
|
-
const doneIdx = findDoneChunk(result.chunks);
|
|
1129
|
-
if (doneIdx >= 0) {
|
|
1130
|
-
return { chunks: result.chunks.slice(0, doneIdx + 1), finished: true };
|
|
1131
|
-
}
|
|
1132
|
-
return { chunks: result.chunks, finished: false };
|
|
1133
|
-
};
|
|
1134
|
-
async function* streamChunks(reader, decoder, state, signal) {
|
|
1135
|
-
let finished = false;
|
|
1136
|
-
while (!finished) {
|
|
1137
|
-
const result = await sseStreamLoop(reader, decoder, state, signal);
|
|
1138
|
-
({ finished } = result);
|
|
1139
|
-
yield* result.chunks;
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
1175
|
async function* parseSSEStream(body, providerName, signal) {
|
|
1143
1176
|
const reader = body.getReader();
|
|
1144
1177
|
const decoder = new TextDecoder;
|
|
@@ -1150,13 +1183,40 @@ async function* parseSSEStream(body, providerName, signal) {
|
|
|
1150
1183
|
stopReason: "",
|
|
1151
1184
|
thinkingSignature: "",
|
|
1152
1185
|
toolInputJson: "",
|
|
1186
|
+
toolInputReported: 0,
|
|
1153
1187
|
usage: undefined,
|
|
1154
1188
|
providerName,
|
|
1155
1189
|
providerBlockInputJson: ""
|
|
1156
1190
|
};
|
|
1157
1191
|
try {
|
|
1158
|
-
|
|
1192
|
+
while (true) {
|
|
1193
|
+
signal?.throwIfAborted();
|
|
1194
|
+
const { done, value } = await reader.read();
|
|
1195
|
+
if (done)
|
|
1196
|
+
return;
|
|
1197
|
+
const events = (state.buffer + decoder.decode(value, { stream: true })).split(`
|
|
1198
|
+
|
|
1199
|
+
`);
|
|
1200
|
+
state.buffer = events.pop() ?? "";
|
|
1201
|
+
for (const event of events) {
|
|
1202
|
+
const chunk = processSingleEvent(event, state);
|
|
1203
|
+
if (!chunk)
|
|
1204
|
+
continue;
|
|
1205
|
+
if (chunk.type === "tool_input" && chunk.receivedChars === 0)
|
|
1206
|
+
yield {
|
|
1207
|
+
type: "tool_input_start",
|
|
1208
|
+
id: chunk.id,
|
|
1209
|
+
name: chunk.name
|
|
1210
|
+
};
|
|
1211
|
+
yield chunk;
|
|
1212
|
+
if (chunk.type === "done")
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1159
1216
|
} finally {
|
|
1217
|
+
await reader.cancel().catch(() => {
|
|
1218
|
+
return;
|
|
1219
|
+
});
|
|
1160
1220
|
reader.releaseLock();
|
|
1161
1221
|
}
|
|
1162
1222
|
}
|
|
@@ -1278,5 +1338,5 @@ export {
|
|
|
1278
1338
|
anthropic
|
|
1279
1339
|
};
|
|
1280
1340
|
|
|
1281
|
-
//# debugId=
|
|
1341
|
+
//# debugId=E2C338FD75B8D35664756E2164756E21
|
|
1282
1342
|
//# sourceMappingURL=anthropic.js.map
|