@browser-ai/core 2.1.2 → 2.1.3

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
@@ -484,6 +484,91 @@ var ToolCallFenceDetector = class {
484
484
  }
485
485
  };
486
486
 
487
+ // ../shared/src/streaming/tool-call-stream-utils.ts
488
+ function extractToolName(content) {
489
+ const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
490
+ if (jsonMatch) {
491
+ return jsonMatch[1];
492
+ }
493
+ return null;
494
+ }
495
+ var ARGUMENTS_FIELD_REGEX = /"arguments"\s*:\s*/g;
496
+ var ARGUMENTS_SEARCH_OVERLAP = 32;
497
+ function createArgumentsStreamState() {
498
+ return {
499
+ searchFrom: 0,
500
+ valueStartIndex: null,
501
+ parseIndex: 0,
502
+ started: false,
503
+ depth: 0,
504
+ inString: false,
505
+ escaped: false,
506
+ complete: false
507
+ };
508
+ }
509
+ function extractArgumentsDelta(content, state) {
510
+ if (state.complete) {
511
+ return "";
512
+ }
513
+ if (state.valueStartIndex === null) {
514
+ ARGUMENTS_FIELD_REGEX.lastIndex = state.searchFrom;
515
+ const match = ARGUMENTS_FIELD_REGEX.exec(content);
516
+ ARGUMENTS_FIELD_REGEX.lastIndex = 0;
517
+ if (!match || match.index === void 0) {
518
+ state.searchFrom = Math.max(0, content.length - ARGUMENTS_SEARCH_OVERLAP);
519
+ return "";
520
+ }
521
+ state.valueStartIndex = match.index + match[0].length;
522
+ state.parseIndex = state.valueStartIndex;
523
+ state.searchFrom = state.valueStartIndex;
524
+ }
525
+ if (state.parseIndex >= content.length) {
526
+ return "";
527
+ }
528
+ let delta = "";
529
+ for (let i = state.parseIndex; i < content.length; i++) {
530
+ const char = content[i];
531
+ delta += char;
532
+ if (!state.started) {
533
+ if (!/\s/.test(char)) {
534
+ state.started = true;
535
+ if (char === "{" || char === "[") {
536
+ state.depth = 1;
537
+ }
538
+ }
539
+ continue;
540
+ }
541
+ if (state.escaped) {
542
+ state.escaped = false;
543
+ continue;
544
+ }
545
+ if (char === "\\") {
546
+ state.escaped = true;
547
+ continue;
548
+ }
549
+ if (char === '"') {
550
+ state.inString = !state.inString;
551
+ continue;
552
+ }
553
+ if (!state.inString) {
554
+ if (char === "{" || char === "[") {
555
+ state.depth += 1;
556
+ } else if (char === "}" || char === "]") {
557
+ if (state.depth > 0) {
558
+ state.depth -= 1;
559
+ if (state.depth === 0) {
560
+ state.parseIndex = i + 1;
561
+ state.complete = true;
562
+ return delta;
563
+ }
564
+ }
565
+ }
566
+ }
567
+ }
568
+ state.parseIndex = content.length;
569
+ return delta;
570
+ }
571
+
487
572
  // src/convert-to-browser-ai-messages.ts
488
573
  var import_provider = require("@ai-sdk/provider");
489
574
  function convertBase64ToUint8Array(base64) {
@@ -977,63 +1062,6 @@ var SessionManager = class {
977
1062
  function doesBrowserSupportBrowserAI() {
978
1063
  return typeof LanguageModel !== "undefined";
979
1064
  }
980
- function extractToolName(content) {
981
- const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
982
- if (jsonMatch) {
983
- return jsonMatch[1];
984
- }
985
- return null;
986
- }
987
- function extractArgumentsContent(content) {
988
- const match = content.match(/"arguments"\s*:\s*/);
989
- if (!match || match.index === void 0) {
990
- return "";
991
- }
992
- const startIndex = match.index + match[0].length;
993
- let result = "";
994
- let depth = 0;
995
- let inString = false;
996
- let escaped = false;
997
- let started = false;
998
- for (let i = startIndex; i < content.length; i++) {
999
- const char = content[i];
1000
- result += char;
1001
- if (!started) {
1002
- if (!/\s/.test(char)) {
1003
- started = true;
1004
- if (char === "{" || char === "[") {
1005
- depth = 1;
1006
- }
1007
- }
1008
- continue;
1009
- }
1010
- if (escaped) {
1011
- escaped = false;
1012
- continue;
1013
- }
1014
- if (char === "\\") {
1015
- escaped = true;
1016
- continue;
1017
- }
1018
- if (char === '"') {
1019
- inString = !inString;
1020
- continue;
1021
- }
1022
- if (!inString) {
1023
- if (char === "{" || char === "[") {
1024
- depth += 1;
1025
- } else if (char === "}" || char === "]") {
1026
- if (depth > 0) {
1027
- depth -= 1;
1028
- if (depth === 0) {
1029
- break;
1030
- }
1031
- }
1032
- }
1033
- }
1034
- }
1035
- return result;
1036
- }
1037
1065
  var BrowserAIChatLanguageModel = class {
1038
1066
  constructor(modelId, options = {}) {
1039
1067
  this.specificationVersion = "v3";
@@ -1384,7 +1412,7 @@ var BrowserAIChatLanguageModel = class {
1384
1412
  let currentToolCallId = null;
1385
1413
  let toolInputStartEmitted = false;
1386
1414
  let accumulatedFenceContent = "";
1387
- let streamedArgumentsLength = 0;
1415
+ let argumentsStreamState = createArgumentsStreamState();
1388
1416
  let insideFence = false;
1389
1417
  while (!aborted) {
1390
1418
  const { done, value } = await currentReader.read();
@@ -1405,7 +1433,7 @@ var BrowserAIChatLanguageModel = class {
1405
1433
  currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1406
1434
  toolInputStartEmitted = false;
1407
1435
  accumulatedFenceContent = "";
1408
- streamedArgumentsLength = 0;
1436
+ argumentsStreamState = createArgumentsStreamState();
1409
1437
  insideFence = true;
1410
1438
  continue;
1411
1439
  }
@@ -1415,19 +1443,16 @@ var BrowserAIChatLanguageModel = class {
1415
1443
  accumulatedFenceContent += result.safeContent;
1416
1444
  }
1417
1445
  if (toolInputStartEmitted && currentToolCallId) {
1418
- const argsContent = extractArgumentsContent(
1419
- accumulatedFenceContent
1446
+ const delta = extractArgumentsDelta(
1447
+ accumulatedFenceContent,
1448
+ argumentsStreamState
1420
1449
  );
1421
- if (argsContent.length > streamedArgumentsLength) {
1422
- const delta = argsContent.slice(streamedArgumentsLength);
1423
- streamedArgumentsLength = argsContent.length;
1424
- if (delta.length > 0) {
1425
- controller.enqueue({
1426
- type: "tool-input-delta",
1427
- id: currentToolCallId,
1428
- delta
1429
- });
1430
- }
1450
+ if (delta.length > 0) {
1451
+ controller.enqueue({
1452
+ type: "tool-input-delta",
1453
+ id: currentToolCallId,
1454
+ delta
1455
+ });
1431
1456
  }
1432
1457
  }
1433
1458
  const parsed = parseJsonFunctionCalls(result.completeFence);
@@ -1443,7 +1468,7 @@ var BrowserAIChatLanguageModel = class {
1443
1468
  currentToolCallId = null;
1444
1469
  toolInputStartEmitted = false;
1445
1470
  accumulatedFenceContent = "";
1446
- streamedArgumentsLength = 0;
1471
+ argumentsStreamState = createArgumentsStreamState();
1447
1472
  insideFence = false;
1448
1473
  continue;
1449
1474
  }
@@ -1465,21 +1490,16 @@ var BrowserAIChatLanguageModel = class {
1465
1490
  });
1466
1491
  toolInputStartEmitted = true;
1467
1492
  }
1468
- const argsContent = extractArgumentsContent(
1469
- accumulatedFenceContent
1493
+ const delta = extractArgumentsDelta(
1494
+ accumulatedFenceContent,
1495
+ argumentsStreamState
1470
1496
  );
1471
- if (argsContent.length > streamedArgumentsLength) {
1472
- const delta = argsContent.slice(
1473
- streamedArgumentsLength
1474
- );
1475
- streamedArgumentsLength = argsContent.length;
1476
- if (delta.length > 0) {
1477
- controller.enqueue({
1478
- type: "tool-input-delta",
1479
- id: toolCallId,
1480
- delta
1481
- });
1482
- }
1497
+ if (delta.length > 0) {
1498
+ controller.enqueue({
1499
+ type: "tool-input-delta",
1500
+ id: toolCallId,
1501
+ delta
1502
+ });
1483
1503
  }
1484
1504
  } else {
1485
1505
  controller.enqueue({
@@ -1516,7 +1536,7 @@ var BrowserAIChatLanguageModel = class {
1516
1536
  currentToolCallId = null;
1517
1537
  toolInputStartEmitted = false;
1518
1538
  accumulatedFenceContent = "";
1519
- streamedArgumentsLength = 0;
1539
+ argumentsStreamState = createArgumentsStreamState();
1520
1540
  insideFence = false;
1521
1541
  continue;
1522
1542
  }
@@ -1534,21 +1554,16 @@ var BrowserAIChatLanguageModel = class {
1534
1554
  toolInputStartEmitted = true;
1535
1555
  }
1536
1556
  if (toolInputStartEmitted && currentToolCallId) {
1537
- const argsContent = extractArgumentsContent(
1538
- accumulatedFenceContent
1557
+ const delta = extractArgumentsDelta(
1558
+ accumulatedFenceContent,
1559
+ argumentsStreamState
1539
1560
  );
1540
- if (argsContent.length > streamedArgumentsLength) {
1541
- const delta = argsContent.slice(
1542
- streamedArgumentsLength
1543
- );
1544
- streamedArgumentsLength = argsContent.length;
1545
- if (delta.length > 0) {
1546
- controller.enqueue({
1547
- type: "tool-input-delta",
1548
- id: currentToolCallId,
1549
- delta
1550
- });
1551
- }
1561
+ if (delta.length > 0) {
1562
+ controller.enqueue({
1563
+ type: "tool-input-delta",
1564
+ id: currentToolCallId,
1565
+ delta
1566
+ });
1552
1567
  }
1553
1568
  }
1554
1569
  }