@browser-ai/web-llm 2.1.3 → 2.1.5
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/dist/index.js +283 -261
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +283 -261
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -773,7 +773,267 @@ var ToolCallFenceDetector = class {
|
|
|
773
773
|
}
|
|
774
774
|
};
|
|
775
775
|
|
|
776
|
-
// src/
|
|
776
|
+
// ../shared/src/streaming/tool-call-stream-utils.ts
|
|
777
|
+
function extractToolName(content) {
|
|
778
|
+
const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
|
|
779
|
+
if (jsonMatch) {
|
|
780
|
+
return jsonMatch[1];
|
|
781
|
+
}
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
var ARGUMENTS_FIELD_REGEX = /"arguments"\s*:\s*/g;
|
|
785
|
+
var ARGUMENTS_SEARCH_OVERLAP = 32;
|
|
786
|
+
function createArgumentsStreamState() {
|
|
787
|
+
return {
|
|
788
|
+
searchFrom: 0,
|
|
789
|
+
valueStartIndex: null,
|
|
790
|
+
parseIndex: 0,
|
|
791
|
+
started: false,
|
|
792
|
+
depth: 0,
|
|
793
|
+
inString: false,
|
|
794
|
+
escaped: false,
|
|
795
|
+
complete: false
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
function extractArgumentsDelta(content, state) {
|
|
799
|
+
if (state.complete) {
|
|
800
|
+
return "";
|
|
801
|
+
}
|
|
802
|
+
if (state.valueStartIndex === null) {
|
|
803
|
+
ARGUMENTS_FIELD_REGEX.lastIndex = state.searchFrom;
|
|
804
|
+
const match = ARGUMENTS_FIELD_REGEX.exec(content);
|
|
805
|
+
ARGUMENTS_FIELD_REGEX.lastIndex = 0;
|
|
806
|
+
if (!match || match.index === void 0) {
|
|
807
|
+
state.searchFrom = Math.max(0, content.length - ARGUMENTS_SEARCH_OVERLAP);
|
|
808
|
+
return "";
|
|
809
|
+
}
|
|
810
|
+
state.valueStartIndex = match.index + match[0].length;
|
|
811
|
+
state.parseIndex = state.valueStartIndex;
|
|
812
|
+
state.searchFrom = state.valueStartIndex;
|
|
813
|
+
}
|
|
814
|
+
if (state.parseIndex >= content.length) {
|
|
815
|
+
return "";
|
|
816
|
+
}
|
|
817
|
+
let delta = "";
|
|
818
|
+
for (let i = state.parseIndex; i < content.length; i++) {
|
|
819
|
+
const char = content[i];
|
|
820
|
+
delta += char;
|
|
821
|
+
if (!state.started) {
|
|
822
|
+
if (!/\s/.test(char)) {
|
|
823
|
+
state.started = true;
|
|
824
|
+
if (char === "{" || char === "[") {
|
|
825
|
+
state.depth = 1;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (state.escaped) {
|
|
831
|
+
state.escaped = false;
|
|
832
|
+
continue;
|
|
833
|
+
}
|
|
834
|
+
if (char === "\\") {
|
|
835
|
+
state.escaped = true;
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
if (char === '"') {
|
|
839
|
+
state.inString = !state.inString;
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
if (!state.inString) {
|
|
843
|
+
if (char === "{" || char === "[") {
|
|
844
|
+
state.depth += 1;
|
|
845
|
+
} else if (char === "}" || char === "]") {
|
|
846
|
+
if (state.depth > 0) {
|
|
847
|
+
state.depth -= 1;
|
|
848
|
+
if (state.depth === 0) {
|
|
849
|
+
state.parseIndex = i + 1;
|
|
850
|
+
state.complete = true;
|
|
851
|
+
return delta;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
state.parseIndex = content.length;
|
|
858
|
+
return delta;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// ../shared/src/streaming/stream-processor.ts
|
|
862
|
+
function generateToolCallId2() {
|
|
863
|
+
return `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
864
|
+
}
|
|
865
|
+
async function processToolCallStream(chunks, emitTextDelta, controller, options) {
|
|
866
|
+
const fenceDetector = new ToolCallFenceDetector();
|
|
867
|
+
let currentToolCallId = null;
|
|
868
|
+
let toolInputStartEmitted = false;
|
|
869
|
+
let accumulatedFenceContent = "";
|
|
870
|
+
let argumentsStreamState = createArgumentsStreamState();
|
|
871
|
+
let insideFence = false;
|
|
872
|
+
let toolCallDetected = false;
|
|
873
|
+
let toolCalls = [];
|
|
874
|
+
let trailingText = "";
|
|
875
|
+
const resetFenceState = () => {
|
|
876
|
+
currentToolCallId = null;
|
|
877
|
+
toolInputStartEmitted = false;
|
|
878
|
+
accumulatedFenceContent = "";
|
|
879
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
880
|
+
insideFence = false;
|
|
881
|
+
};
|
|
882
|
+
for await (const chunk of chunks) {
|
|
883
|
+
if (toolCallDetected) {
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
fenceDetector.addChunk(chunk);
|
|
887
|
+
while (fenceDetector.hasContent()) {
|
|
888
|
+
const wasInsideFence = insideFence;
|
|
889
|
+
const result = fenceDetector.detectStreamingFence();
|
|
890
|
+
insideFence = result.inFence;
|
|
891
|
+
let madeProgress = false;
|
|
892
|
+
if (!wasInsideFence && result.inFence) {
|
|
893
|
+
if (result.safeContent) {
|
|
894
|
+
emitTextDelta(result.safeContent);
|
|
895
|
+
madeProgress = true;
|
|
896
|
+
}
|
|
897
|
+
currentToolCallId = generateToolCallId2();
|
|
898
|
+
toolInputStartEmitted = false;
|
|
899
|
+
accumulatedFenceContent = "";
|
|
900
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
901
|
+
insideFence = true;
|
|
902
|
+
continue;
|
|
903
|
+
}
|
|
904
|
+
if (result.completeFence) {
|
|
905
|
+
madeProgress = true;
|
|
906
|
+
if (result.safeContent) {
|
|
907
|
+
accumulatedFenceContent += result.safeContent;
|
|
908
|
+
}
|
|
909
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
910
|
+
const delta = extractArgumentsDelta(
|
|
911
|
+
accumulatedFenceContent,
|
|
912
|
+
argumentsStreamState
|
|
913
|
+
);
|
|
914
|
+
if (delta.length > 0) {
|
|
915
|
+
controller.enqueue({
|
|
916
|
+
type: "tool-input-delta",
|
|
917
|
+
id: currentToolCallId,
|
|
918
|
+
delta
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
923
|
+
const selectedToolCalls = parsed.toolCalls.slice(0, 1);
|
|
924
|
+
if (selectedToolCalls.length === 0) {
|
|
925
|
+
emitTextDelta(result.completeFence);
|
|
926
|
+
if (result.textAfterFence) {
|
|
927
|
+
emitTextDelta(result.textAfterFence);
|
|
928
|
+
}
|
|
929
|
+
resetFenceState();
|
|
930
|
+
continue;
|
|
931
|
+
}
|
|
932
|
+
if (currentToolCallId) {
|
|
933
|
+
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
934
|
+
}
|
|
935
|
+
for (const [index, call] of selectedToolCalls.entries()) {
|
|
936
|
+
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
937
|
+
const toolName = call.toolName;
|
|
938
|
+
const argsJson = JSON.stringify(call.args ?? {});
|
|
939
|
+
if (toolCallId === currentToolCallId) {
|
|
940
|
+
if (!toolInputStartEmitted) {
|
|
941
|
+
controller.enqueue({
|
|
942
|
+
type: "tool-input-start",
|
|
943
|
+
id: toolCallId,
|
|
944
|
+
toolName
|
|
945
|
+
});
|
|
946
|
+
toolInputStartEmitted = true;
|
|
947
|
+
}
|
|
948
|
+
const delta = extractArgumentsDelta(
|
|
949
|
+
accumulatedFenceContent,
|
|
950
|
+
argumentsStreamState
|
|
951
|
+
);
|
|
952
|
+
if (delta.length > 0) {
|
|
953
|
+
controller.enqueue({
|
|
954
|
+
type: "tool-input-delta",
|
|
955
|
+
id: toolCallId,
|
|
956
|
+
delta
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
} else {
|
|
960
|
+
controller.enqueue({
|
|
961
|
+
type: "tool-input-start",
|
|
962
|
+
id: toolCallId,
|
|
963
|
+
toolName
|
|
964
|
+
});
|
|
965
|
+
if (argsJson.length > 0) {
|
|
966
|
+
controller.enqueue({
|
|
967
|
+
type: "tool-input-delta",
|
|
968
|
+
id: toolCallId,
|
|
969
|
+
delta: argsJson
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
controller.enqueue({ type: "tool-input-end", id: toolCallId });
|
|
974
|
+
controller.enqueue({
|
|
975
|
+
type: "tool-call",
|
|
976
|
+
toolCallId,
|
|
977
|
+
toolName,
|
|
978
|
+
input: argsJson,
|
|
979
|
+
providerExecuted: false
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
trailingText = result.textAfterFence ?? "";
|
|
983
|
+
toolCalls = selectedToolCalls;
|
|
984
|
+
toolCallDetected = true;
|
|
985
|
+
resetFenceState();
|
|
986
|
+
break;
|
|
987
|
+
}
|
|
988
|
+
if (insideFence) {
|
|
989
|
+
if (result.safeContent) {
|
|
990
|
+
accumulatedFenceContent += result.safeContent;
|
|
991
|
+
madeProgress = true;
|
|
992
|
+
const toolName = extractToolName(accumulatedFenceContent);
|
|
993
|
+
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
994
|
+
controller.enqueue({
|
|
995
|
+
type: "tool-input-start",
|
|
996
|
+
id: currentToolCallId,
|
|
997
|
+
toolName
|
|
998
|
+
});
|
|
999
|
+
toolInputStartEmitted = true;
|
|
1000
|
+
}
|
|
1001
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
1002
|
+
const delta = extractArgumentsDelta(
|
|
1003
|
+
accumulatedFenceContent,
|
|
1004
|
+
argumentsStreamState
|
|
1005
|
+
);
|
|
1006
|
+
if (delta.length > 0) {
|
|
1007
|
+
controller.enqueue({
|
|
1008
|
+
type: "tool-input-delta",
|
|
1009
|
+
id: currentToolCallId,
|
|
1010
|
+
delta
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
if (!insideFence && result.safeContent) {
|
|
1018
|
+
emitTextDelta(result.safeContent);
|
|
1019
|
+
madeProgress = true;
|
|
1020
|
+
}
|
|
1021
|
+
if (!madeProgress) {
|
|
1022
|
+
break;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
if (toolCallDetected && options?.stopEarlyOnToolCall) {
|
|
1026
|
+
break;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (!toolCallDetected && fenceDetector.hasContent()) {
|
|
1030
|
+
emitTextDelta(fenceDetector.getBuffer());
|
|
1031
|
+
fenceDetector.clearBuffer();
|
|
1032
|
+
}
|
|
1033
|
+
return { toolCallDetected, toolCalls, trailingText };
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// src/utils/convert-to-webllm-messages.tsx
|
|
777
1037
|
function convertToolResultOutput(output) {
|
|
778
1038
|
switch (output.type) {
|
|
779
1039
|
case "text":
|
|
@@ -912,7 +1172,7 @@ function convertToWebLLMMessages(prompt) {
|
|
|
912
1172
|
return messages;
|
|
913
1173
|
}
|
|
914
1174
|
|
|
915
|
-
// src/web-llm-language-model.ts
|
|
1175
|
+
// src/chat/web-llm-language-model.ts
|
|
916
1176
|
import {
|
|
917
1177
|
CreateWebWorkerMLCEngine,
|
|
918
1178
|
MLCEngine
|
|
@@ -975,64 +1235,7 @@ function doesBrowserSupportWebLLM() {
|
|
|
975
1235
|
return checkWebGPU();
|
|
976
1236
|
}
|
|
977
1237
|
|
|
978
|
-
// src/web-llm-language-model.ts
|
|
979
|
-
function extractToolName(content) {
|
|
980
|
-
const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
|
|
981
|
-
if (jsonMatch) {
|
|
982
|
-
return jsonMatch[1];
|
|
983
|
-
}
|
|
984
|
-
return null;
|
|
985
|
-
}
|
|
986
|
-
function extractArgumentsContent(content) {
|
|
987
|
-
const match = content.match(/"arguments"\s*:\s*/);
|
|
988
|
-
if (!match || match.index === void 0) {
|
|
989
|
-
return "";
|
|
990
|
-
}
|
|
991
|
-
const startIndex = match.index + match[0].length;
|
|
992
|
-
let result = "";
|
|
993
|
-
let depth = 0;
|
|
994
|
-
let inString = false;
|
|
995
|
-
let escaped = false;
|
|
996
|
-
let started = false;
|
|
997
|
-
for (let i = startIndex; i < content.length; i++) {
|
|
998
|
-
const char = content[i];
|
|
999
|
-
result += char;
|
|
1000
|
-
if (!started) {
|
|
1001
|
-
if (!/\s/.test(char)) {
|
|
1002
|
-
started = true;
|
|
1003
|
-
if (char === "{" || char === "[") {
|
|
1004
|
-
depth = 1;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
continue;
|
|
1008
|
-
}
|
|
1009
|
-
if (escaped) {
|
|
1010
|
-
escaped = false;
|
|
1011
|
-
continue;
|
|
1012
|
-
}
|
|
1013
|
-
if (char === "\\") {
|
|
1014
|
-
escaped = true;
|
|
1015
|
-
continue;
|
|
1016
|
-
}
|
|
1017
|
-
if (char === '"') {
|
|
1018
|
-
inString = !inString;
|
|
1019
|
-
continue;
|
|
1020
|
-
}
|
|
1021
|
-
if (!inString) {
|
|
1022
|
-
if (char === "{" || char === "[") {
|
|
1023
|
-
depth += 1;
|
|
1024
|
-
} else if (char === "}" || char === "]") {
|
|
1025
|
-
if (depth > 0) {
|
|
1026
|
-
depth -= 1;
|
|
1027
|
-
if (depth === 0) {
|
|
1028
|
-
break;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
return result;
|
|
1035
|
-
}
|
|
1238
|
+
// src/chat/web-llm-language-model.ts
|
|
1036
1239
|
var WebLLMLanguageModel = class {
|
|
1037
1240
|
constructor(modelId, options = {}) {
|
|
1038
1241
|
this.specificationVersion = "v3";
|
|
@@ -1476,208 +1679,27 @@ var WebLLMLanguageModel = class {
|
|
|
1476
1679
|
...options.abortSignal && !useWorker && { signal: options.abortSignal }
|
|
1477
1680
|
};
|
|
1478
1681
|
const response = await engine.chat.completions.create(streamingRequest);
|
|
1479
|
-
|
|
1480
|
-
let
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
if (!choice) continue;
|
|
1489
|
-
if (choice.delta.content) {
|
|
1490
|
-
const delta = choice.delta.content;
|
|
1491
|
-
accumulatedText += delta;
|
|
1492
|
-
fenceDetector.addChunk(delta);
|
|
1493
|
-
while (fenceDetector.hasContent()) {
|
|
1494
|
-
const wasInsideFence = insideFence;
|
|
1495
|
-
const result = fenceDetector.detectStreamingFence();
|
|
1496
|
-
insideFence = result.inFence;
|
|
1497
|
-
let madeProgress = false;
|
|
1498
|
-
if (!wasInsideFence && result.inFence) {
|
|
1499
|
-
if (result.safeContent) {
|
|
1500
|
-
emitTextDelta(result.safeContent);
|
|
1501
|
-
madeProgress = true;
|
|
1502
|
-
}
|
|
1503
|
-
currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1504
|
-
toolInputStartEmitted = false;
|
|
1505
|
-
accumulatedFenceContent = "";
|
|
1506
|
-
streamedArgumentsLength = 0;
|
|
1507
|
-
insideFence = true;
|
|
1508
|
-
continue;
|
|
1509
|
-
}
|
|
1510
|
-
if (result.completeFence) {
|
|
1511
|
-
madeProgress = true;
|
|
1512
|
-
if (result.safeContent) {
|
|
1513
|
-
accumulatedFenceContent += result.safeContent;
|
|
1514
|
-
}
|
|
1515
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1516
|
-
const argsContent = extractArgumentsContent(
|
|
1517
|
-
accumulatedFenceContent
|
|
1518
|
-
);
|
|
1519
|
-
if (argsContent.length > streamedArgumentsLength) {
|
|
1520
|
-
const delta2 = argsContent.slice(streamedArgumentsLength);
|
|
1521
|
-
streamedArgumentsLength = argsContent.length;
|
|
1522
|
-
if (delta2.length > 0) {
|
|
1523
|
-
controller.enqueue({
|
|
1524
|
-
type: "tool-input-delta",
|
|
1525
|
-
id: currentToolCallId,
|
|
1526
|
-
delta: delta2
|
|
1527
|
-
});
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
}
|
|
1531
|
-
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
1532
|
-
const parsedToolCalls = parsed.toolCalls;
|
|
1533
|
-
const selectedToolCalls = parsedToolCalls.slice(0, 1);
|
|
1534
|
-
if (selectedToolCalls.length === 0) {
|
|
1535
|
-
emitTextDelta(result.completeFence);
|
|
1536
|
-
if (result.textAfterFence) {
|
|
1537
|
-
emitTextDelta(result.textAfterFence);
|
|
1538
|
-
}
|
|
1539
|
-
currentToolCallId = null;
|
|
1540
|
-
toolInputStartEmitted = false;
|
|
1541
|
-
accumulatedFenceContent = "";
|
|
1542
|
-
streamedArgumentsLength = 0;
|
|
1543
|
-
insideFence = false;
|
|
1544
|
-
continue;
|
|
1545
|
-
}
|
|
1546
|
-
if (selectedToolCalls.length > 0 && currentToolCallId) {
|
|
1547
|
-
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
1548
|
-
}
|
|
1549
|
-
for (const [index, call] of selectedToolCalls.entries()) {
|
|
1550
|
-
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
1551
|
-
const toolName = call.toolName;
|
|
1552
|
-
const argsJson = JSON.stringify(call.args ?? {});
|
|
1553
|
-
if (toolCallId === currentToolCallId) {
|
|
1554
|
-
if (!toolInputStartEmitted) {
|
|
1555
|
-
controller.enqueue({
|
|
1556
|
-
type: "tool-input-start",
|
|
1557
|
-
id: toolCallId,
|
|
1558
|
-
toolName
|
|
1559
|
-
});
|
|
1560
|
-
toolInputStartEmitted = true;
|
|
1561
|
-
}
|
|
1562
|
-
const argsContent = extractArgumentsContent(
|
|
1563
|
-
accumulatedFenceContent
|
|
1564
|
-
);
|
|
1565
|
-
if (argsContent.length > streamedArgumentsLength) {
|
|
1566
|
-
const delta2 = argsContent.slice(
|
|
1567
|
-
streamedArgumentsLength
|
|
1568
|
-
);
|
|
1569
|
-
streamedArgumentsLength = argsContent.length;
|
|
1570
|
-
if (delta2.length > 0) {
|
|
1571
|
-
controller.enqueue({
|
|
1572
|
-
type: "tool-input-delta",
|
|
1573
|
-
id: toolCallId,
|
|
1574
|
-
delta: delta2
|
|
1575
|
-
});
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
} else {
|
|
1579
|
-
controller.enqueue({
|
|
1580
|
-
type: "tool-input-start",
|
|
1581
|
-
id: toolCallId,
|
|
1582
|
-
toolName
|
|
1583
|
-
});
|
|
1584
|
-
if (argsJson.length > 0) {
|
|
1585
|
-
controller.enqueue({
|
|
1586
|
-
type: "tool-input-delta",
|
|
1587
|
-
id: toolCallId,
|
|
1588
|
-
delta: argsJson
|
|
1589
|
-
});
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
controller.enqueue({
|
|
1593
|
-
type: "tool-input-end",
|
|
1594
|
-
id: toolCallId
|
|
1595
|
-
});
|
|
1596
|
-
controller.enqueue({
|
|
1597
|
-
type: "tool-call",
|
|
1598
|
-
toolCallId,
|
|
1599
|
-
toolName,
|
|
1600
|
-
input: argsJson,
|
|
1601
|
-
providerExecuted: false
|
|
1602
|
-
});
|
|
1603
|
-
}
|
|
1604
|
-
if (result.textAfterFence) {
|
|
1605
|
-
emitTextDelta(result.textAfterFence);
|
|
1606
|
-
}
|
|
1607
|
-
madeProgress = true;
|
|
1608
|
-
currentToolCallId = null;
|
|
1609
|
-
toolInputStartEmitted = false;
|
|
1610
|
-
accumulatedFenceContent = "";
|
|
1611
|
-
streamedArgumentsLength = 0;
|
|
1612
|
-
insideFence = false;
|
|
1613
|
-
continue;
|
|
1614
|
-
}
|
|
1615
|
-
if (insideFence) {
|
|
1616
|
-
if (result.safeContent) {
|
|
1617
|
-
accumulatedFenceContent += result.safeContent;
|
|
1618
|
-
madeProgress = true;
|
|
1619
|
-
const toolName = extractToolName(accumulatedFenceContent);
|
|
1620
|
-
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
1621
|
-
controller.enqueue({
|
|
1622
|
-
type: "tool-input-start",
|
|
1623
|
-
id: currentToolCallId,
|
|
1624
|
-
toolName
|
|
1625
|
-
});
|
|
1626
|
-
toolInputStartEmitted = true;
|
|
1627
|
-
}
|
|
1628
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1629
|
-
const argsContent = extractArgumentsContent(
|
|
1630
|
-
accumulatedFenceContent
|
|
1631
|
-
);
|
|
1632
|
-
if (argsContent.length > streamedArgumentsLength) {
|
|
1633
|
-
const delta2 = argsContent.slice(
|
|
1634
|
-
streamedArgumentsLength
|
|
1635
|
-
);
|
|
1636
|
-
streamedArgumentsLength = argsContent.length;
|
|
1637
|
-
if (delta2.length > 0) {
|
|
1638
|
-
controller.enqueue({
|
|
1639
|
-
type: "tool-input-delta",
|
|
1640
|
-
id: currentToolCallId,
|
|
1641
|
-
delta: delta2
|
|
1642
|
-
});
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
continue;
|
|
1648
|
-
}
|
|
1649
|
-
if (!insideFence && result.safeContent) {
|
|
1650
|
-
emitTextDelta(result.safeContent);
|
|
1651
|
-
madeProgress = true;
|
|
1652
|
-
}
|
|
1653
|
-
if (!madeProgress) {
|
|
1654
|
-
break;
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
if (choice.finish_reason) {
|
|
1659
|
-
if (fenceDetector.hasContent()) {
|
|
1660
|
-
emitTextDelta(fenceDetector.getBuffer());
|
|
1661
|
-
fenceDetector.clearBuffer();
|
|
1662
|
-
}
|
|
1663
|
-
let finishReason = {
|
|
1664
|
-
unified: "stop",
|
|
1665
|
-
raw: "stop"
|
|
1666
|
-
};
|
|
1667
|
-
if (choice.finish_reason === "abort") {
|
|
1668
|
-
finishReason = { unified: "other", raw: "abort" };
|
|
1669
|
-
} else {
|
|
1670
|
-
const { toolCalls } = parseJsonFunctionCalls(accumulatedText);
|
|
1671
|
-
if (toolCalls.length > 0) {
|
|
1672
|
-
finishReason = { unified: "tool-calls", raw: "tool-calls" };
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
finishStream(finishReason, chunk.usage);
|
|
1682
|
+
let lastUsage;
|
|
1683
|
+
let isAbort = false;
|
|
1684
|
+
const chunks = (async function* () {
|
|
1685
|
+
for await (const chunk of response) {
|
|
1686
|
+
const choice = chunk.choices[0];
|
|
1687
|
+
if (!choice) continue;
|
|
1688
|
+
if (choice.delta.content) yield choice.delta.content;
|
|
1689
|
+
if (chunk.usage) lastUsage = chunk.usage;
|
|
1690
|
+
if (choice.finish_reason === "abort") isAbort = true;
|
|
1676
1691
|
}
|
|
1692
|
+
})();
|
|
1693
|
+
const result = await processToolCallStream(
|
|
1694
|
+
chunks,
|
|
1695
|
+
emitTextDelta,
|
|
1696
|
+
controller
|
|
1697
|
+
);
|
|
1698
|
+
if (result.trailingText) {
|
|
1699
|
+
emitTextDelta(result.trailingText);
|
|
1677
1700
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
}
|
|
1701
|
+
const finishReason = isAbort ? { unified: "other", raw: "abort" } : result.toolCallDetected ? { unified: "tool-calls", raw: "tool-calls" } : { unified: "stop", raw: "stop" };
|
|
1702
|
+
finishStream(finishReason, lastUsage);
|
|
1681
1703
|
} catch (error) {
|
|
1682
1704
|
controller.error(error);
|
|
1683
1705
|
} finally {
|
|
@@ -1697,7 +1719,7 @@ var WebLLMLanguageModel = class {
|
|
|
1697
1719
|
}
|
|
1698
1720
|
};
|
|
1699
1721
|
|
|
1700
|
-
// src/web-llm-embedding-model.ts
|
|
1722
|
+
// src/embedding/web-llm-embedding-model.ts
|
|
1701
1723
|
import {
|
|
1702
1724
|
CreateWebWorkerMLCEngine as CreateWebWorkerMLCEngine2,
|
|
1703
1725
|
MLCEngine as MLCEngine2
|