@browser-ai/web-llm 2.1.3 → 2.1.4

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 CHANGED
@@ -804,6 +804,91 @@ var ToolCallFenceDetector = class {
804
804
  }
805
805
  };
806
806
 
807
+ // ../shared/src/streaming/tool-call-stream-utils.ts
808
+ function extractToolName(content) {
809
+ const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
810
+ if (jsonMatch) {
811
+ return jsonMatch[1];
812
+ }
813
+ return null;
814
+ }
815
+ var ARGUMENTS_FIELD_REGEX = /"arguments"\s*:\s*/g;
816
+ var ARGUMENTS_SEARCH_OVERLAP = 32;
817
+ function createArgumentsStreamState() {
818
+ return {
819
+ searchFrom: 0,
820
+ valueStartIndex: null,
821
+ parseIndex: 0,
822
+ started: false,
823
+ depth: 0,
824
+ inString: false,
825
+ escaped: false,
826
+ complete: false
827
+ };
828
+ }
829
+ function extractArgumentsDelta(content, state) {
830
+ if (state.complete) {
831
+ return "";
832
+ }
833
+ if (state.valueStartIndex === null) {
834
+ ARGUMENTS_FIELD_REGEX.lastIndex = state.searchFrom;
835
+ const match = ARGUMENTS_FIELD_REGEX.exec(content);
836
+ ARGUMENTS_FIELD_REGEX.lastIndex = 0;
837
+ if (!match || match.index === void 0) {
838
+ state.searchFrom = Math.max(0, content.length - ARGUMENTS_SEARCH_OVERLAP);
839
+ return "";
840
+ }
841
+ state.valueStartIndex = match.index + match[0].length;
842
+ state.parseIndex = state.valueStartIndex;
843
+ state.searchFrom = state.valueStartIndex;
844
+ }
845
+ if (state.parseIndex >= content.length) {
846
+ return "";
847
+ }
848
+ let delta = "";
849
+ for (let i = state.parseIndex; i < content.length; i++) {
850
+ const char = content[i];
851
+ delta += char;
852
+ if (!state.started) {
853
+ if (!/\s/.test(char)) {
854
+ state.started = true;
855
+ if (char === "{" || char === "[") {
856
+ state.depth = 1;
857
+ }
858
+ }
859
+ continue;
860
+ }
861
+ if (state.escaped) {
862
+ state.escaped = false;
863
+ continue;
864
+ }
865
+ if (char === "\\") {
866
+ state.escaped = true;
867
+ continue;
868
+ }
869
+ if (char === '"') {
870
+ state.inString = !state.inString;
871
+ continue;
872
+ }
873
+ if (!state.inString) {
874
+ if (char === "{" || char === "[") {
875
+ state.depth += 1;
876
+ } else if (char === "}" || char === "]") {
877
+ if (state.depth > 0) {
878
+ state.depth -= 1;
879
+ if (state.depth === 0) {
880
+ state.parseIndex = i + 1;
881
+ state.complete = true;
882
+ return delta;
883
+ }
884
+ }
885
+ }
886
+ }
887
+ }
888
+ state.parseIndex = content.length;
889
+ return delta;
890
+ }
891
+
807
892
  // src/convert-to-webllm-messages.tsx
808
893
  function convertToolResultOutput(output) {
809
894
  switch (output.type) {
@@ -1004,63 +1089,6 @@ function doesBrowserSupportWebLLM() {
1004
1089
  }
1005
1090
 
1006
1091
  // src/web-llm-language-model.ts
1007
- function extractToolName(content) {
1008
- const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
1009
- if (jsonMatch) {
1010
- return jsonMatch[1];
1011
- }
1012
- return null;
1013
- }
1014
- function extractArgumentsContent(content) {
1015
- const match = content.match(/"arguments"\s*:\s*/);
1016
- if (!match || match.index === void 0) {
1017
- return "";
1018
- }
1019
- const startIndex = match.index + match[0].length;
1020
- let result = "";
1021
- let depth = 0;
1022
- let inString = false;
1023
- let escaped = false;
1024
- let started = false;
1025
- for (let i = startIndex; i < content.length; i++) {
1026
- const char = content[i];
1027
- result += char;
1028
- if (!started) {
1029
- if (!/\s/.test(char)) {
1030
- started = true;
1031
- if (char === "{" || char === "[") {
1032
- depth = 1;
1033
- }
1034
- }
1035
- continue;
1036
- }
1037
- if (escaped) {
1038
- escaped = false;
1039
- continue;
1040
- }
1041
- if (char === "\\") {
1042
- escaped = true;
1043
- continue;
1044
- }
1045
- if (char === '"') {
1046
- inString = !inString;
1047
- continue;
1048
- }
1049
- if (!inString) {
1050
- if (char === "{" || char === "[") {
1051
- depth += 1;
1052
- } else if (char === "}" || char === "]") {
1053
- if (depth > 0) {
1054
- depth -= 1;
1055
- if (depth === 0) {
1056
- break;
1057
- }
1058
- }
1059
- }
1060
- }
1061
- }
1062
- return result;
1063
- }
1064
1092
  var WebLLMLanguageModel = class {
1065
1093
  constructor(modelId, options = {}) {
1066
1094
  this.specificationVersion = "v3";
@@ -1509,7 +1537,7 @@ var WebLLMLanguageModel = class {
1509
1537
  let currentToolCallId = null;
1510
1538
  let toolInputStartEmitted = false;
1511
1539
  let accumulatedFenceContent = "";
1512
- let streamedArgumentsLength = 0;
1540
+ let argumentsStreamState = createArgumentsStreamState();
1513
1541
  let insideFence = false;
1514
1542
  for await (const chunk of response) {
1515
1543
  const choice = chunk.choices[0];
@@ -1531,7 +1559,7 @@ var WebLLMLanguageModel = class {
1531
1559
  currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1532
1560
  toolInputStartEmitted = false;
1533
1561
  accumulatedFenceContent = "";
1534
- streamedArgumentsLength = 0;
1562
+ argumentsStreamState = createArgumentsStreamState();
1535
1563
  insideFence = true;
1536
1564
  continue;
1537
1565
  }
@@ -1541,19 +1569,16 @@ var WebLLMLanguageModel = class {
1541
1569
  accumulatedFenceContent += result.safeContent;
1542
1570
  }
1543
1571
  if (toolInputStartEmitted && currentToolCallId) {
1544
- const argsContent = extractArgumentsContent(
1545
- accumulatedFenceContent
1572
+ const delta2 = extractArgumentsDelta(
1573
+ accumulatedFenceContent,
1574
+ argumentsStreamState
1546
1575
  );
1547
- if (argsContent.length > streamedArgumentsLength) {
1548
- const delta2 = argsContent.slice(streamedArgumentsLength);
1549
- streamedArgumentsLength = argsContent.length;
1550
- if (delta2.length > 0) {
1551
- controller.enqueue({
1552
- type: "tool-input-delta",
1553
- id: currentToolCallId,
1554
- delta: delta2
1555
- });
1556
- }
1576
+ if (delta2.length > 0) {
1577
+ controller.enqueue({
1578
+ type: "tool-input-delta",
1579
+ id: currentToolCallId,
1580
+ delta: delta2
1581
+ });
1557
1582
  }
1558
1583
  }
1559
1584
  const parsed = parseJsonFunctionCalls(result.completeFence);
@@ -1567,7 +1592,7 @@ var WebLLMLanguageModel = class {
1567
1592
  currentToolCallId = null;
1568
1593
  toolInputStartEmitted = false;
1569
1594
  accumulatedFenceContent = "";
1570
- streamedArgumentsLength = 0;
1595
+ argumentsStreamState = createArgumentsStreamState();
1571
1596
  insideFence = false;
1572
1597
  continue;
1573
1598
  }
@@ -1587,21 +1612,16 @@ var WebLLMLanguageModel = class {
1587
1612
  });
1588
1613
  toolInputStartEmitted = true;
1589
1614
  }
1590
- const argsContent = extractArgumentsContent(
1591
- accumulatedFenceContent
1615
+ const delta2 = extractArgumentsDelta(
1616
+ accumulatedFenceContent,
1617
+ argumentsStreamState
1592
1618
  );
1593
- if (argsContent.length > streamedArgumentsLength) {
1594
- const delta2 = argsContent.slice(
1595
- streamedArgumentsLength
1596
- );
1597
- streamedArgumentsLength = argsContent.length;
1598
- if (delta2.length > 0) {
1599
- controller.enqueue({
1600
- type: "tool-input-delta",
1601
- id: toolCallId,
1602
- delta: delta2
1603
- });
1604
- }
1619
+ if (delta2.length > 0) {
1620
+ controller.enqueue({
1621
+ type: "tool-input-delta",
1622
+ id: toolCallId,
1623
+ delta: delta2
1624
+ });
1605
1625
  }
1606
1626
  } else {
1607
1627
  controller.enqueue({
@@ -1636,7 +1656,7 @@ var WebLLMLanguageModel = class {
1636
1656
  currentToolCallId = null;
1637
1657
  toolInputStartEmitted = false;
1638
1658
  accumulatedFenceContent = "";
1639
- streamedArgumentsLength = 0;
1659
+ argumentsStreamState = createArgumentsStreamState();
1640
1660
  insideFence = false;
1641
1661
  continue;
1642
1662
  }
@@ -1654,21 +1674,16 @@ var WebLLMLanguageModel = class {
1654
1674
  toolInputStartEmitted = true;
1655
1675
  }
1656
1676
  if (toolInputStartEmitted && currentToolCallId) {
1657
- const argsContent = extractArgumentsContent(
1658
- accumulatedFenceContent
1677
+ const delta2 = extractArgumentsDelta(
1678
+ accumulatedFenceContent,
1679
+ argumentsStreamState
1659
1680
  );
1660
- if (argsContent.length > streamedArgumentsLength) {
1661
- const delta2 = argsContent.slice(
1662
- streamedArgumentsLength
1663
- );
1664
- streamedArgumentsLength = argsContent.length;
1665
- if (delta2.length > 0) {
1666
- controller.enqueue({
1667
- type: "tool-input-delta",
1668
- id: currentToolCallId,
1669
- delta: delta2
1670
- });
1671
- }
1681
+ if (delta2.length > 0) {
1682
+ controller.enqueue({
1683
+ type: "tool-input-delta",
1684
+ id: currentToolCallId,
1685
+ delta: delta2
1686
+ });
1672
1687
  }
1673
1688
  }
1674
1689
  }