@browser-ai/core 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 +206 -204
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +206 -204
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -569,7 +569,182 @@ function extractArgumentsDelta(content, state) {
|
|
|
569
569
|
return delta;
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
-
// src/
|
|
572
|
+
// ../shared/src/streaming/stream-processor.ts
|
|
573
|
+
function generateToolCallId2() {
|
|
574
|
+
return `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
575
|
+
}
|
|
576
|
+
async function processToolCallStream(chunks, emitTextDelta, controller, options) {
|
|
577
|
+
const fenceDetector = new ToolCallFenceDetector();
|
|
578
|
+
let currentToolCallId = null;
|
|
579
|
+
let toolInputStartEmitted = false;
|
|
580
|
+
let accumulatedFenceContent = "";
|
|
581
|
+
let argumentsStreamState = createArgumentsStreamState();
|
|
582
|
+
let insideFence = false;
|
|
583
|
+
let toolCallDetected = false;
|
|
584
|
+
let toolCalls = [];
|
|
585
|
+
let trailingText = "";
|
|
586
|
+
const resetFenceState = () => {
|
|
587
|
+
currentToolCallId = null;
|
|
588
|
+
toolInputStartEmitted = false;
|
|
589
|
+
accumulatedFenceContent = "";
|
|
590
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
591
|
+
insideFence = false;
|
|
592
|
+
};
|
|
593
|
+
for await (const chunk of chunks) {
|
|
594
|
+
if (toolCallDetected) {
|
|
595
|
+
continue;
|
|
596
|
+
}
|
|
597
|
+
fenceDetector.addChunk(chunk);
|
|
598
|
+
while (fenceDetector.hasContent()) {
|
|
599
|
+
const wasInsideFence = insideFence;
|
|
600
|
+
const result = fenceDetector.detectStreamingFence();
|
|
601
|
+
insideFence = result.inFence;
|
|
602
|
+
let madeProgress = false;
|
|
603
|
+
if (!wasInsideFence && result.inFence) {
|
|
604
|
+
if (result.safeContent) {
|
|
605
|
+
emitTextDelta(result.safeContent);
|
|
606
|
+
madeProgress = true;
|
|
607
|
+
}
|
|
608
|
+
currentToolCallId = generateToolCallId2();
|
|
609
|
+
toolInputStartEmitted = false;
|
|
610
|
+
accumulatedFenceContent = "";
|
|
611
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
612
|
+
insideFence = true;
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
if (result.completeFence) {
|
|
616
|
+
madeProgress = true;
|
|
617
|
+
if (result.safeContent) {
|
|
618
|
+
accumulatedFenceContent += result.safeContent;
|
|
619
|
+
}
|
|
620
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
621
|
+
const delta = extractArgumentsDelta(
|
|
622
|
+
accumulatedFenceContent,
|
|
623
|
+
argumentsStreamState
|
|
624
|
+
);
|
|
625
|
+
if (delta.length > 0) {
|
|
626
|
+
controller.enqueue({
|
|
627
|
+
type: "tool-input-delta",
|
|
628
|
+
id: currentToolCallId,
|
|
629
|
+
delta
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
634
|
+
const selectedToolCalls = parsed.toolCalls.slice(0, 1);
|
|
635
|
+
if (selectedToolCalls.length === 0) {
|
|
636
|
+
emitTextDelta(result.completeFence);
|
|
637
|
+
if (result.textAfterFence) {
|
|
638
|
+
emitTextDelta(result.textAfterFence);
|
|
639
|
+
}
|
|
640
|
+
resetFenceState();
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
if (currentToolCallId) {
|
|
644
|
+
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
645
|
+
}
|
|
646
|
+
for (const [index, call] of selectedToolCalls.entries()) {
|
|
647
|
+
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
648
|
+
const toolName = call.toolName;
|
|
649
|
+
const argsJson = JSON.stringify(call.args ?? {});
|
|
650
|
+
if (toolCallId === currentToolCallId) {
|
|
651
|
+
if (!toolInputStartEmitted) {
|
|
652
|
+
controller.enqueue({
|
|
653
|
+
type: "tool-input-start",
|
|
654
|
+
id: toolCallId,
|
|
655
|
+
toolName
|
|
656
|
+
});
|
|
657
|
+
toolInputStartEmitted = true;
|
|
658
|
+
}
|
|
659
|
+
const delta = extractArgumentsDelta(
|
|
660
|
+
accumulatedFenceContent,
|
|
661
|
+
argumentsStreamState
|
|
662
|
+
);
|
|
663
|
+
if (delta.length > 0) {
|
|
664
|
+
controller.enqueue({
|
|
665
|
+
type: "tool-input-delta",
|
|
666
|
+
id: toolCallId,
|
|
667
|
+
delta
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
} else {
|
|
671
|
+
controller.enqueue({
|
|
672
|
+
type: "tool-input-start",
|
|
673
|
+
id: toolCallId,
|
|
674
|
+
toolName
|
|
675
|
+
});
|
|
676
|
+
if (argsJson.length > 0) {
|
|
677
|
+
controller.enqueue({
|
|
678
|
+
type: "tool-input-delta",
|
|
679
|
+
id: toolCallId,
|
|
680
|
+
delta: argsJson
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
controller.enqueue({ type: "tool-input-end", id: toolCallId });
|
|
685
|
+
controller.enqueue({
|
|
686
|
+
type: "tool-call",
|
|
687
|
+
toolCallId,
|
|
688
|
+
toolName,
|
|
689
|
+
input: argsJson,
|
|
690
|
+
providerExecuted: false
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
trailingText = result.textAfterFence ?? "";
|
|
694
|
+
toolCalls = selectedToolCalls;
|
|
695
|
+
toolCallDetected = true;
|
|
696
|
+
resetFenceState();
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
if (insideFence) {
|
|
700
|
+
if (result.safeContent) {
|
|
701
|
+
accumulatedFenceContent += result.safeContent;
|
|
702
|
+
madeProgress = true;
|
|
703
|
+
const toolName = extractToolName(accumulatedFenceContent);
|
|
704
|
+
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
705
|
+
controller.enqueue({
|
|
706
|
+
type: "tool-input-start",
|
|
707
|
+
id: currentToolCallId,
|
|
708
|
+
toolName
|
|
709
|
+
});
|
|
710
|
+
toolInputStartEmitted = true;
|
|
711
|
+
}
|
|
712
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
713
|
+
const delta = extractArgumentsDelta(
|
|
714
|
+
accumulatedFenceContent,
|
|
715
|
+
argumentsStreamState
|
|
716
|
+
);
|
|
717
|
+
if (delta.length > 0) {
|
|
718
|
+
controller.enqueue({
|
|
719
|
+
type: "tool-input-delta",
|
|
720
|
+
id: currentToolCallId,
|
|
721
|
+
delta
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if (!insideFence && result.safeContent) {
|
|
729
|
+
emitTextDelta(result.safeContent);
|
|
730
|
+
madeProgress = true;
|
|
731
|
+
}
|
|
732
|
+
if (!madeProgress) {
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (toolCallDetected && options?.stopEarlyOnToolCall) {
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
if (!toolCallDetected && fenceDetector.hasContent()) {
|
|
741
|
+
emitTextDelta(fenceDetector.getBuffer());
|
|
742
|
+
fenceDetector.clearBuffer();
|
|
743
|
+
}
|
|
744
|
+
return { toolCallDetected, toolCalls, trailingText };
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/utils/convert-to-browser-ai-messages.ts
|
|
573
748
|
var import_provider = require("@ai-sdk/provider");
|
|
574
749
|
function convertBase64ToUint8Array(base64) {
|
|
575
750
|
try {
|
|
@@ -874,7 +1049,7 @@ function getExpectedInputs(prompt) {
|
|
|
874
1049
|
return Array.from(inputs).map((type) => ({ type }));
|
|
875
1050
|
}
|
|
876
1051
|
|
|
877
|
-
// src/
|
|
1052
|
+
// src/chat/session-manager.ts
|
|
878
1053
|
var import_provider2 = require("@ai-sdk/provider");
|
|
879
1054
|
var SessionManager = class {
|
|
880
1055
|
/**
|
|
@@ -1058,7 +1233,7 @@ var SessionManager = class {
|
|
|
1058
1233
|
}
|
|
1059
1234
|
};
|
|
1060
1235
|
|
|
1061
|
-
// src/browser-ai-language-model.ts
|
|
1236
|
+
// src/chat/browser-ai-language-model.ts
|
|
1062
1237
|
function doesBrowserSupportBrowserAI() {
|
|
1063
1238
|
return typeof LanguageModel !== "undefined";
|
|
1064
1239
|
}
|
|
@@ -1395,213 +1570,40 @@ var BrowserAIChatLanguageModel = class {
|
|
|
1395
1570
|
if (options.abortSignal) {
|
|
1396
1571
|
options.abortSignal.addEventListener("abort", abortHandler);
|
|
1397
1572
|
}
|
|
1398
|
-
const maxIterations = 10;
|
|
1399
|
-
let iteration = 0;
|
|
1400
1573
|
try {
|
|
1401
|
-
const
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
);
|
|
1408
|
-
currentReader = promptStream.getReader();
|
|
1409
|
-
let toolCalls = [];
|
|
1410
|
-
let toolBlockDetected = false;
|
|
1411
|
-
let trailingTextAfterBlock = "";
|
|
1412
|
-
let currentToolCallId = null;
|
|
1413
|
-
let toolInputStartEmitted = false;
|
|
1414
|
-
let accumulatedFenceContent = "";
|
|
1415
|
-
let argumentsStreamState = createArgumentsStreamState();
|
|
1416
|
-
let insideFence = false;
|
|
1574
|
+
const promptStream = session.promptStreaming(
|
|
1575
|
+
conversationHistory,
|
|
1576
|
+
streamOptions
|
|
1577
|
+
);
|
|
1578
|
+
currentReader = promptStream.getReader();
|
|
1579
|
+
const chunks = (async function* () {
|
|
1417
1580
|
while (!aborted) {
|
|
1418
1581
|
const { done, value } = await currentReader.read();
|
|
1419
|
-
if (done)
|
|
1420
|
-
|
|
1421
|
-
}
|
|
1422
|
-
fenceDetector.addChunk(value);
|
|
1423
|
-
while (fenceDetector.hasContent()) {
|
|
1424
|
-
const wasInsideFence = insideFence;
|
|
1425
|
-
const result = fenceDetector.detectStreamingFence();
|
|
1426
|
-
insideFence = result.inFence;
|
|
1427
|
-
let madeProgress = false;
|
|
1428
|
-
if (!wasInsideFence && result.inFence) {
|
|
1429
|
-
if (result.safeContent) {
|
|
1430
|
-
emitTextDelta(result.safeContent);
|
|
1431
|
-
madeProgress = true;
|
|
1432
|
-
}
|
|
1433
|
-
currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1434
|
-
toolInputStartEmitted = false;
|
|
1435
|
-
accumulatedFenceContent = "";
|
|
1436
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1437
|
-
insideFence = true;
|
|
1438
|
-
continue;
|
|
1439
|
-
}
|
|
1440
|
-
if (result.completeFence) {
|
|
1441
|
-
madeProgress = true;
|
|
1442
|
-
if (result.safeContent) {
|
|
1443
|
-
accumulatedFenceContent += result.safeContent;
|
|
1444
|
-
}
|
|
1445
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1446
|
-
const delta = extractArgumentsDelta(
|
|
1447
|
-
accumulatedFenceContent,
|
|
1448
|
-
argumentsStreamState
|
|
1449
|
-
);
|
|
1450
|
-
if (delta.length > 0) {
|
|
1451
|
-
controller.enqueue({
|
|
1452
|
-
type: "tool-input-delta",
|
|
1453
|
-
id: currentToolCallId,
|
|
1454
|
-
delta
|
|
1455
|
-
});
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
1459
|
-
const parsedToolCalls = parsed.toolCalls;
|
|
1460
|
-
const selectedToolCalls = parsedToolCalls.slice(0, 1);
|
|
1461
|
-
if (selectedToolCalls.length === 0) {
|
|
1462
|
-
toolCalls = [];
|
|
1463
|
-
toolBlockDetected = false;
|
|
1464
|
-
emitTextDelta(result.completeFence);
|
|
1465
|
-
if (result.textAfterFence) {
|
|
1466
|
-
emitTextDelta(result.textAfterFence);
|
|
1467
|
-
}
|
|
1468
|
-
currentToolCallId = null;
|
|
1469
|
-
toolInputStartEmitted = false;
|
|
1470
|
-
accumulatedFenceContent = "";
|
|
1471
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1472
|
-
insideFence = false;
|
|
1473
|
-
continue;
|
|
1474
|
-
}
|
|
1475
|
-
if (selectedToolCalls.length > 0 && currentToolCallId) {
|
|
1476
|
-
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
1477
|
-
}
|
|
1478
|
-
toolCalls = selectedToolCalls;
|
|
1479
|
-
toolBlockDetected = toolCalls.length > 0;
|
|
1480
|
-
for (const [index, call] of toolCalls.entries()) {
|
|
1481
|
-
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
1482
|
-
const toolName = call.toolName;
|
|
1483
|
-
const argsJson = JSON.stringify(call.args ?? {});
|
|
1484
|
-
if (toolCallId === currentToolCallId) {
|
|
1485
|
-
if (!toolInputStartEmitted) {
|
|
1486
|
-
controller.enqueue({
|
|
1487
|
-
type: "tool-input-start",
|
|
1488
|
-
id: toolCallId,
|
|
1489
|
-
toolName
|
|
1490
|
-
});
|
|
1491
|
-
toolInputStartEmitted = true;
|
|
1492
|
-
}
|
|
1493
|
-
const delta = extractArgumentsDelta(
|
|
1494
|
-
accumulatedFenceContent,
|
|
1495
|
-
argumentsStreamState
|
|
1496
|
-
);
|
|
1497
|
-
if (delta.length > 0) {
|
|
1498
|
-
controller.enqueue({
|
|
1499
|
-
type: "tool-input-delta",
|
|
1500
|
-
id: toolCallId,
|
|
1501
|
-
delta
|
|
1502
|
-
});
|
|
1503
|
-
}
|
|
1504
|
-
} else {
|
|
1505
|
-
controller.enqueue({
|
|
1506
|
-
type: "tool-input-start",
|
|
1507
|
-
id: toolCallId,
|
|
1508
|
-
toolName
|
|
1509
|
-
});
|
|
1510
|
-
if (argsJson.length > 0) {
|
|
1511
|
-
controller.enqueue({
|
|
1512
|
-
type: "tool-input-delta",
|
|
1513
|
-
id: toolCallId,
|
|
1514
|
-
delta: argsJson
|
|
1515
|
-
});
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
controller.enqueue({
|
|
1519
|
-
type: "tool-input-end",
|
|
1520
|
-
id: toolCallId
|
|
1521
|
-
});
|
|
1522
|
-
controller.enqueue({
|
|
1523
|
-
type: "tool-call",
|
|
1524
|
-
toolCallId,
|
|
1525
|
-
toolName,
|
|
1526
|
-
input: argsJson,
|
|
1527
|
-
providerExecuted: false
|
|
1528
|
-
});
|
|
1529
|
-
}
|
|
1530
|
-
trailingTextAfterBlock += result.textAfterFence;
|
|
1531
|
-
madeProgress = true;
|
|
1532
|
-
if (toolBlockDetected && currentReader) {
|
|
1533
|
-
await currentReader.cancel().catch(() => void 0);
|
|
1534
|
-
break;
|
|
1535
|
-
}
|
|
1536
|
-
currentToolCallId = null;
|
|
1537
|
-
toolInputStartEmitted = false;
|
|
1538
|
-
accumulatedFenceContent = "";
|
|
1539
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1540
|
-
insideFence = false;
|
|
1541
|
-
continue;
|
|
1542
|
-
}
|
|
1543
|
-
if (insideFence) {
|
|
1544
|
-
if (result.safeContent) {
|
|
1545
|
-
accumulatedFenceContent += result.safeContent;
|
|
1546
|
-
madeProgress = true;
|
|
1547
|
-
const toolName = extractToolName(accumulatedFenceContent);
|
|
1548
|
-
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
1549
|
-
controller.enqueue({
|
|
1550
|
-
type: "tool-input-start",
|
|
1551
|
-
id: currentToolCallId,
|
|
1552
|
-
toolName
|
|
1553
|
-
});
|
|
1554
|
-
toolInputStartEmitted = true;
|
|
1555
|
-
}
|
|
1556
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1557
|
-
const delta = extractArgumentsDelta(
|
|
1558
|
-
accumulatedFenceContent,
|
|
1559
|
-
argumentsStreamState
|
|
1560
|
-
);
|
|
1561
|
-
if (delta.length > 0) {
|
|
1562
|
-
controller.enqueue({
|
|
1563
|
-
type: "tool-input-delta",
|
|
1564
|
-
id: currentToolCallId,
|
|
1565
|
-
delta
|
|
1566
|
-
});
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
continue;
|
|
1571
|
-
}
|
|
1572
|
-
if (!insideFence && result.safeContent) {
|
|
1573
|
-
emitTextDelta(result.safeContent);
|
|
1574
|
-
madeProgress = true;
|
|
1575
|
-
}
|
|
1576
|
-
if (!madeProgress) {
|
|
1577
|
-
break;
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
if (toolBlockDetected) {
|
|
1581
|
-
break;
|
|
1582
|
-
}
|
|
1582
|
+
if (done) break;
|
|
1583
|
+
yield value;
|
|
1583
1584
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
finishStream({ unified: "
|
|
1585
|
+
})();
|
|
1586
|
+
const result = await processToolCallStream(
|
|
1587
|
+
chunks,
|
|
1588
|
+
emitTextDelta,
|
|
1589
|
+
controller,
|
|
1590
|
+
{ stopEarlyOnToolCall: true }
|
|
1591
|
+
);
|
|
1592
|
+
if (result.toolCallDetected && currentReader) {
|
|
1593
|
+
await currentReader.cancel().catch(() => void 0);
|
|
1594
|
+
}
|
|
1595
|
+
currentReader = null;
|
|
1596
|
+
if (aborted) {
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
if (!result.toolCallDetected || result.toolCalls.length === 0) {
|
|
1600
|
+
finishStream({ unified: "stop", raw: "stop" });
|
|
1600
1601
|
return;
|
|
1601
1602
|
}
|
|
1602
|
-
if (
|
|
1603
|
-
|
|
1603
|
+
if (result.trailingText) {
|
|
1604
|
+
emitTextDelta(result.trailingText);
|
|
1604
1605
|
}
|
|
1606
|
+
finishStream({ unified: "tool-calls", raw: "tool-calls" });
|
|
1605
1607
|
} catch (error) {
|
|
1606
1608
|
controller.enqueue({ type: "error", error });
|
|
1607
1609
|
controller.close();
|
|
@@ -1619,7 +1621,7 @@ var BrowserAIChatLanguageModel = class {
|
|
|
1619
1621
|
}
|
|
1620
1622
|
};
|
|
1621
1623
|
|
|
1622
|
-
// src/browser-ai-embedding-model.ts
|
|
1624
|
+
// src/embedding/browser-ai-embedding-model.ts
|
|
1623
1625
|
var import_tasks_text = require("@mediapipe/tasks-text");
|
|
1624
1626
|
var BrowserAIEmbeddingModel = class {
|
|
1625
1627
|
constructor(settings = {}) {
|