@browser-ai/web-llm 2.1.2 → 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.mjs CHANGED
@@ -773,6 +773,91 @@ var ToolCallFenceDetector = class {
773
773
  }
774
774
  };
775
775
 
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
+
776
861
  // src/convert-to-webllm-messages.tsx
777
862
  function convertToolResultOutput(output) {
778
863
  switch (output.type) {
@@ -976,63 +1061,6 @@ function doesBrowserSupportWebLLM() {
976
1061
  }
977
1062
 
978
1063
  // 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
- }
1036
1064
  var WebLLMLanguageModel = class {
1037
1065
  constructor(modelId, options = {}) {
1038
1066
  this.specificationVersion = "v3";
@@ -1481,7 +1509,7 @@ var WebLLMLanguageModel = class {
1481
1509
  let currentToolCallId = null;
1482
1510
  let toolInputStartEmitted = false;
1483
1511
  let accumulatedFenceContent = "";
1484
- let streamedArgumentsLength = 0;
1512
+ let argumentsStreamState = createArgumentsStreamState();
1485
1513
  let insideFence = false;
1486
1514
  for await (const chunk of response) {
1487
1515
  const choice = chunk.choices[0];
@@ -1503,7 +1531,7 @@ var WebLLMLanguageModel = class {
1503
1531
  currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1504
1532
  toolInputStartEmitted = false;
1505
1533
  accumulatedFenceContent = "";
1506
- streamedArgumentsLength = 0;
1534
+ argumentsStreamState = createArgumentsStreamState();
1507
1535
  insideFence = true;
1508
1536
  continue;
1509
1537
  }
@@ -1513,19 +1541,16 @@ var WebLLMLanguageModel = class {
1513
1541
  accumulatedFenceContent += result.safeContent;
1514
1542
  }
1515
1543
  if (toolInputStartEmitted && currentToolCallId) {
1516
- const argsContent = extractArgumentsContent(
1517
- accumulatedFenceContent
1544
+ const delta2 = extractArgumentsDelta(
1545
+ accumulatedFenceContent,
1546
+ argumentsStreamState
1518
1547
  );
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
- }
1548
+ if (delta2.length > 0) {
1549
+ controller.enqueue({
1550
+ type: "tool-input-delta",
1551
+ id: currentToolCallId,
1552
+ delta: delta2
1553
+ });
1529
1554
  }
1530
1555
  }
1531
1556
  const parsed = parseJsonFunctionCalls(result.completeFence);
@@ -1539,7 +1564,7 @@ var WebLLMLanguageModel = class {
1539
1564
  currentToolCallId = null;
1540
1565
  toolInputStartEmitted = false;
1541
1566
  accumulatedFenceContent = "";
1542
- streamedArgumentsLength = 0;
1567
+ argumentsStreamState = createArgumentsStreamState();
1543
1568
  insideFence = false;
1544
1569
  continue;
1545
1570
  }
@@ -1559,21 +1584,16 @@ var WebLLMLanguageModel = class {
1559
1584
  });
1560
1585
  toolInputStartEmitted = true;
1561
1586
  }
1562
- const argsContent = extractArgumentsContent(
1563
- accumulatedFenceContent
1587
+ const delta2 = extractArgumentsDelta(
1588
+ accumulatedFenceContent,
1589
+ argumentsStreamState
1564
1590
  );
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
- }
1591
+ if (delta2.length > 0) {
1592
+ controller.enqueue({
1593
+ type: "tool-input-delta",
1594
+ id: toolCallId,
1595
+ delta: delta2
1596
+ });
1577
1597
  }
1578
1598
  } else {
1579
1599
  controller.enqueue({
@@ -1608,7 +1628,7 @@ var WebLLMLanguageModel = class {
1608
1628
  currentToolCallId = null;
1609
1629
  toolInputStartEmitted = false;
1610
1630
  accumulatedFenceContent = "";
1611
- streamedArgumentsLength = 0;
1631
+ argumentsStreamState = createArgumentsStreamState();
1612
1632
  insideFence = false;
1613
1633
  continue;
1614
1634
  }
@@ -1626,21 +1646,16 @@ var WebLLMLanguageModel = class {
1626
1646
  toolInputStartEmitted = true;
1627
1647
  }
1628
1648
  if (toolInputStartEmitted && currentToolCallId) {
1629
- const argsContent = extractArgumentsContent(
1630
- accumulatedFenceContent
1649
+ const delta2 = extractArgumentsDelta(
1650
+ accumulatedFenceContent,
1651
+ argumentsStreamState
1631
1652
  );
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
- }
1653
+ if (delta2.length > 0) {
1654
+ controller.enqueue({
1655
+ type: "tool-input-delta",
1656
+ id: currentToolCallId,
1657
+ delta: delta2
1658
+ });
1644
1659
  }
1645
1660
  }
1646
1661
  }