@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.mjs CHANGED
@@ -454,6 +454,91 @@ var ToolCallFenceDetector = class {
454
454
  }
455
455
  };
456
456
 
457
+ // ../shared/src/streaming/tool-call-stream-utils.ts
458
+ function extractToolName(content) {
459
+ const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
460
+ if (jsonMatch) {
461
+ return jsonMatch[1];
462
+ }
463
+ return null;
464
+ }
465
+ var ARGUMENTS_FIELD_REGEX = /"arguments"\s*:\s*/g;
466
+ var ARGUMENTS_SEARCH_OVERLAP = 32;
467
+ function createArgumentsStreamState() {
468
+ return {
469
+ searchFrom: 0,
470
+ valueStartIndex: null,
471
+ parseIndex: 0,
472
+ started: false,
473
+ depth: 0,
474
+ inString: false,
475
+ escaped: false,
476
+ complete: false
477
+ };
478
+ }
479
+ function extractArgumentsDelta(content, state) {
480
+ if (state.complete) {
481
+ return "";
482
+ }
483
+ if (state.valueStartIndex === null) {
484
+ ARGUMENTS_FIELD_REGEX.lastIndex = state.searchFrom;
485
+ const match = ARGUMENTS_FIELD_REGEX.exec(content);
486
+ ARGUMENTS_FIELD_REGEX.lastIndex = 0;
487
+ if (!match || match.index === void 0) {
488
+ state.searchFrom = Math.max(0, content.length - ARGUMENTS_SEARCH_OVERLAP);
489
+ return "";
490
+ }
491
+ state.valueStartIndex = match.index + match[0].length;
492
+ state.parseIndex = state.valueStartIndex;
493
+ state.searchFrom = state.valueStartIndex;
494
+ }
495
+ if (state.parseIndex >= content.length) {
496
+ return "";
497
+ }
498
+ let delta = "";
499
+ for (let i = state.parseIndex; i < content.length; i++) {
500
+ const char = content[i];
501
+ delta += char;
502
+ if (!state.started) {
503
+ if (!/\s/.test(char)) {
504
+ state.started = true;
505
+ if (char === "{" || char === "[") {
506
+ state.depth = 1;
507
+ }
508
+ }
509
+ continue;
510
+ }
511
+ if (state.escaped) {
512
+ state.escaped = false;
513
+ continue;
514
+ }
515
+ if (char === "\\") {
516
+ state.escaped = true;
517
+ continue;
518
+ }
519
+ if (char === '"') {
520
+ state.inString = !state.inString;
521
+ continue;
522
+ }
523
+ if (!state.inString) {
524
+ if (char === "{" || char === "[") {
525
+ state.depth += 1;
526
+ } else if (char === "}" || char === "]") {
527
+ if (state.depth > 0) {
528
+ state.depth -= 1;
529
+ if (state.depth === 0) {
530
+ state.parseIndex = i + 1;
531
+ state.complete = true;
532
+ return delta;
533
+ }
534
+ }
535
+ }
536
+ }
537
+ }
538
+ state.parseIndex = content.length;
539
+ return delta;
540
+ }
541
+
457
542
  // src/convert-to-browser-ai-messages.ts
458
543
  import {
459
544
  UnsupportedFunctionalityError
@@ -949,63 +1034,6 @@ var SessionManager = class {
949
1034
  function doesBrowserSupportBrowserAI() {
950
1035
  return typeof LanguageModel !== "undefined";
951
1036
  }
952
- function extractToolName(content) {
953
- const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
954
- if (jsonMatch) {
955
- return jsonMatch[1];
956
- }
957
- return null;
958
- }
959
- function extractArgumentsContent(content) {
960
- const match = content.match(/"arguments"\s*:\s*/);
961
- if (!match || match.index === void 0) {
962
- return "";
963
- }
964
- const startIndex = match.index + match[0].length;
965
- let result = "";
966
- let depth = 0;
967
- let inString = false;
968
- let escaped = false;
969
- let started = false;
970
- for (let i = startIndex; i < content.length; i++) {
971
- const char = content[i];
972
- result += char;
973
- if (!started) {
974
- if (!/\s/.test(char)) {
975
- started = true;
976
- if (char === "{" || char === "[") {
977
- depth = 1;
978
- }
979
- }
980
- continue;
981
- }
982
- if (escaped) {
983
- escaped = false;
984
- continue;
985
- }
986
- if (char === "\\") {
987
- escaped = true;
988
- continue;
989
- }
990
- if (char === '"') {
991
- inString = !inString;
992
- continue;
993
- }
994
- if (!inString) {
995
- if (char === "{" || char === "[") {
996
- depth += 1;
997
- } else if (char === "}" || char === "]") {
998
- if (depth > 0) {
999
- depth -= 1;
1000
- if (depth === 0) {
1001
- break;
1002
- }
1003
- }
1004
- }
1005
- }
1006
- }
1007
- return result;
1008
- }
1009
1037
  var BrowserAIChatLanguageModel = class {
1010
1038
  constructor(modelId, options = {}) {
1011
1039
  this.specificationVersion = "v3";
@@ -1356,7 +1384,7 @@ var BrowserAIChatLanguageModel = class {
1356
1384
  let currentToolCallId = null;
1357
1385
  let toolInputStartEmitted = false;
1358
1386
  let accumulatedFenceContent = "";
1359
- let streamedArgumentsLength = 0;
1387
+ let argumentsStreamState = createArgumentsStreamState();
1360
1388
  let insideFence = false;
1361
1389
  while (!aborted) {
1362
1390
  const { done, value } = await currentReader.read();
@@ -1377,7 +1405,7 @@ var BrowserAIChatLanguageModel = class {
1377
1405
  currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
1378
1406
  toolInputStartEmitted = false;
1379
1407
  accumulatedFenceContent = "";
1380
- streamedArgumentsLength = 0;
1408
+ argumentsStreamState = createArgumentsStreamState();
1381
1409
  insideFence = true;
1382
1410
  continue;
1383
1411
  }
@@ -1387,19 +1415,16 @@ var BrowserAIChatLanguageModel = class {
1387
1415
  accumulatedFenceContent += result.safeContent;
1388
1416
  }
1389
1417
  if (toolInputStartEmitted && currentToolCallId) {
1390
- const argsContent = extractArgumentsContent(
1391
- accumulatedFenceContent
1418
+ const delta = extractArgumentsDelta(
1419
+ accumulatedFenceContent,
1420
+ argumentsStreamState
1392
1421
  );
1393
- if (argsContent.length > streamedArgumentsLength) {
1394
- const delta = argsContent.slice(streamedArgumentsLength);
1395
- streamedArgumentsLength = argsContent.length;
1396
- if (delta.length > 0) {
1397
- controller.enqueue({
1398
- type: "tool-input-delta",
1399
- id: currentToolCallId,
1400
- delta
1401
- });
1402
- }
1422
+ if (delta.length > 0) {
1423
+ controller.enqueue({
1424
+ type: "tool-input-delta",
1425
+ id: currentToolCallId,
1426
+ delta
1427
+ });
1403
1428
  }
1404
1429
  }
1405
1430
  const parsed = parseJsonFunctionCalls(result.completeFence);
@@ -1415,7 +1440,7 @@ var BrowserAIChatLanguageModel = class {
1415
1440
  currentToolCallId = null;
1416
1441
  toolInputStartEmitted = false;
1417
1442
  accumulatedFenceContent = "";
1418
- streamedArgumentsLength = 0;
1443
+ argumentsStreamState = createArgumentsStreamState();
1419
1444
  insideFence = false;
1420
1445
  continue;
1421
1446
  }
@@ -1437,21 +1462,16 @@ var BrowserAIChatLanguageModel = class {
1437
1462
  });
1438
1463
  toolInputStartEmitted = true;
1439
1464
  }
1440
- const argsContent = extractArgumentsContent(
1441
- accumulatedFenceContent
1465
+ const delta = extractArgumentsDelta(
1466
+ accumulatedFenceContent,
1467
+ argumentsStreamState
1442
1468
  );
1443
- if (argsContent.length > streamedArgumentsLength) {
1444
- const delta = argsContent.slice(
1445
- streamedArgumentsLength
1446
- );
1447
- streamedArgumentsLength = argsContent.length;
1448
- if (delta.length > 0) {
1449
- controller.enqueue({
1450
- type: "tool-input-delta",
1451
- id: toolCallId,
1452
- delta
1453
- });
1454
- }
1469
+ if (delta.length > 0) {
1470
+ controller.enqueue({
1471
+ type: "tool-input-delta",
1472
+ id: toolCallId,
1473
+ delta
1474
+ });
1455
1475
  }
1456
1476
  } else {
1457
1477
  controller.enqueue({
@@ -1488,7 +1508,7 @@ var BrowserAIChatLanguageModel = class {
1488
1508
  currentToolCallId = null;
1489
1509
  toolInputStartEmitted = false;
1490
1510
  accumulatedFenceContent = "";
1491
- streamedArgumentsLength = 0;
1511
+ argumentsStreamState = createArgumentsStreamState();
1492
1512
  insideFence = false;
1493
1513
  continue;
1494
1514
  }
@@ -1506,21 +1526,16 @@ var BrowserAIChatLanguageModel = class {
1506
1526
  toolInputStartEmitted = true;
1507
1527
  }
1508
1528
  if (toolInputStartEmitted && currentToolCallId) {
1509
- const argsContent = extractArgumentsContent(
1510
- accumulatedFenceContent
1529
+ const delta = extractArgumentsDelta(
1530
+ accumulatedFenceContent,
1531
+ argumentsStreamState
1511
1532
  );
1512
- if (argsContent.length > streamedArgumentsLength) {
1513
- const delta = argsContent.slice(
1514
- streamedArgumentsLength
1515
- );
1516
- streamedArgumentsLength = argsContent.length;
1517
- if (delta.length > 0) {
1518
- controller.enqueue({
1519
- type: "tool-input-delta",
1520
- id: currentToolCallId,
1521
- delta
1522
- });
1523
- }
1533
+ if (delta.length > 0) {
1534
+ controller.enqueue({
1535
+ type: "tool-input-delta",
1536
+ id: currentToolCallId,
1537
+ delta
1538
+ });
1524
1539
  }
1525
1540
  }
1526
1541
  }