@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.mjs
CHANGED
|
@@ -539,7 +539,182 @@ function extractArgumentsDelta(content, state) {
|
|
|
539
539
|
return delta;
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
-
// src/
|
|
542
|
+
// ../shared/src/streaming/stream-processor.ts
|
|
543
|
+
function generateToolCallId2() {
|
|
544
|
+
return `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
545
|
+
}
|
|
546
|
+
async function processToolCallStream(chunks, emitTextDelta, controller, options) {
|
|
547
|
+
const fenceDetector = new ToolCallFenceDetector();
|
|
548
|
+
let currentToolCallId = null;
|
|
549
|
+
let toolInputStartEmitted = false;
|
|
550
|
+
let accumulatedFenceContent = "";
|
|
551
|
+
let argumentsStreamState = createArgumentsStreamState();
|
|
552
|
+
let insideFence = false;
|
|
553
|
+
let toolCallDetected = false;
|
|
554
|
+
let toolCalls = [];
|
|
555
|
+
let trailingText = "";
|
|
556
|
+
const resetFenceState = () => {
|
|
557
|
+
currentToolCallId = null;
|
|
558
|
+
toolInputStartEmitted = false;
|
|
559
|
+
accumulatedFenceContent = "";
|
|
560
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
561
|
+
insideFence = false;
|
|
562
|
+
};
|
|
563
|
+
for await (const chunk of chunks) {
|
|
564
|
+
if (toolCallDetected) {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
fenceDetector.addChunk(chunk);
|
|
568
|
+
while (fenceDetector.hasContent()) {
|
|
569
|
+
const wasInsideFence = insideFence;
|
|
570
|
+
const result = fenceDetector.detectStreamingFence();
|
|
571
|
+
insideFence = result.inFence;
|
|
572
|
+
let madeProgress = false;
|
|
573
|
+
if (!wasInsideFence && result.inFence) {
|
|
574
|
+
if (result.safeContent) {
|
|
575
|
+
emitTextDelta(result.safeContent);
|
|
576
|
+
madeProgress = true;
|
|
577
|
+
}
|
|
578
|
+
currentToolCallId = generateToolCallId2();
|
|
579
|
+
toolInputStartEmitted = false;
|
|
580
|
+
accumulatedFenceContent = "";
|
|
581
|
+
argumentsStreamState = createArgumentsStreamState();
|
|
582
|
+
insideFence = true;
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
if (result.completeFence) {
|
|
586
|
+
madeProgress = true;
|
|
587
|
+
if (result.safeContent) {
|
|
588
|
+
accumulatedFenceContent += result.safeContent;
|
|
589
|
+
}
|
|
590
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
591
|
+
const delta = extractArgumentsDelta(
|
|
592
|
+
accumulatedFenceContent,
|
|
593
|
+
argumentsStreamState
|
|
594
|
+
);
|
|
595
|
+
if (delta.length > 0) {
|
|
596
|
+
controller.enqueue({
|
|
597
|
+
type: "tool-input-delta",
|
|
598
|
+
id: currentToolCallId,
|
|
599
|
+
delta
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
604
|
+
const selectedToolCalls = parsed.toolCalls.slice(0, 1);
|
|
605
|
+
if (selectedToolCalls.length === 0) {
|
|
606
|
+
emitTextDelta(result.completeFence);
|
|
607
|
+
if (result.textAfterFence) {
|
|
608
|
+
emitTextDelta(result.textAfterFence);
|
|
609
|
+
}
|
|
610
|
+
resetFenceState();
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (currentToolCallId) {
|
|
614
|
+
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
615
|
+
}
|
|
616
|
+
for (const [index, call] of selectedToolCalls.entries()) {
|
|
617
|
+
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
618
|
+
const toolName = call.toolName;
|
|
619
|
+
const argsJson = JSON.stringify(call.args ?? {});
|
|
620
|
+
if (toolCallId === currentToolCallId) {
|
|
621
|
+
if (!toolInputStartEmitted) {
|
|
622
|
+
controller.enqueue({
|
|
623
|
+
type: "tool-input-start",
|
|
624
|
+
id: toolCallId,
|
|
625
|
+
toolName
|
|
626
|
+
});
|
|
627
|
+
toolInputStartEmitted = true;
|
|
628
|
+
}
|
|
629
|
+
const delta = extractArgumentsDelta(
|
|
630
|
+
accumulatedFenceContent,
|
|
631
|
+
argumentsStreamState
|
|
632
|
+
);
|
|
633
|
+
if (delta.length > 0) {
|
|
634
|
+
controller.enqueue({
|
|
635
|
+
type: "tool-input-delta",
|
|
636
|
+
id: toolCallId,
|
|
637
|
+
delta
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
} else {
|
|
641
|
+
controller.enqueue({
|
|
642
|
+
type: "tool-input-start",
|
|
643
|
+
id: toolCallId,
|
|
644
|
+
toolName
|
|
645
|
+
});
|
|
646
|
+
if (argsJson.length > 0) {
|
|
647
|
+
controller.enqueue({
|
|
648
|
+
type: "tool-input-delta",
|
|
649
|
+
id: toolCallId,
|
|
650
|
+
delta: argsJson
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
controller.enqueue({ type: "tool-input-end", id: toolCallId });
|
|
655
|
+
controller.enqueue({
|
|
656
|
+
type: "tool-call",
|
|
657
|
+
toolCallId,
|
|
658
|
+
toolName,
|
|
659
|
+
input: argsJson,
|
|
660
|
+
providerExecuted: false
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
trailingText = result.textAfterFence ?? "";
|
|
664
|
+
toolCalls = selectedToolCalls;
|
|
665
|
+
toolCallDetected = true;
|
|
666
|
+
resetFenceState();
|
|
667
|
+
break;
|
|
668
|
+
}
|
|
669
|
+
if (insideFence) {
|
|
670
|
+
if (result.safeContent) {
|
|
671
|
+
accumulatedFenceContent += result.safeContent;
|
|
672
|
+
madeProgress = true;
|
|
673
|
+
const toolName = extractToolName(accumulatedFenceContent);
|
|
674
|
+
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
675
|
+
controller.enqueue({
|
|
676
|
+
type: "tool-input-start",
|
|
677
|
+
id: currentToolCallId,
|
|
678
|
+
toolName
|
|
679
|
+
});
|
|
680
|
+
toolInputStartEmitted = true;
|
|
681
|
+
}
|
|
682
|
+
if (toolInputStartEmitted && currentToolCallId) {
|
|
683
|
+
const delta = extractArgumentsDelta(
|
|
684
|
+
accumulatedFenceContent,
|
|
685
|
+
argumentsStreamState
|
|
686
|
+
);
|
|
687
|
+
if (delta.length > 0) {
|
|
688
|
+
controller.enqueue({
|
|
689
|
+
type: "tool-input-delta",
|
|
690
|
+
id: currentToolCallId,
|
|
691
|
+
delta
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
if (!insideFence && result.safeContent) {
|
|
699
|
+
emitTextDelta(result.safeContent);
|
|
700
|
+
madeProgress = true;
|
|
701
|
+
}
|
|
702
|
+
if (!madeProgress) {
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
if (toolCallDetected && options?.stopEarlyOnToolCall) {
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
if (!toolCallDetected && fenceDetector.hasContent()) {
|
|
711
|
+
emitTextDelta(fenceDetector.getBuffer());
|
|
712
|
+
fenceDetector.clearBuffer();
|
|
713
|
+
}
|
|
714
|
+
return { toolCallDetected, toolCalls, trailingText };
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// src/utils/convert-to-browser-ai-messages.ts
|
|
543
718
|
import {
|
|
544
719
|
UnsupportedFunctionalityError
|
|
545
720
|
} from "@ai-sdk/provider";
|
|
@@ -846,7 +1021,7 @@ function getExpectedInputs(prompt) {
|
|
|
846
1021
|
return Array.from(inputs).map((type) => ({ type }));
|
|
847
1022
|
}
|
|
848
1023
|
|
|
849
|
-
// src/
|
|
1024
|
+
// src/chat/session-manager.ts
|
|
850
1025
|
import { LoadSettingError } from "@ai-sdk/provider";
|
|
851
1026
|
var SessionManager = class {
|
|
852
1027
|
/**
|
|
@@ -1030,7 +1205,7 @@ var SessionManager = class {
|
|
|
1030
1205
|
}
|
|
1031
1206
|
};
|
|
1032
1207
|
|
|
1033
|
-
// src/browser-ai-language-model.ts
|
|
1208
|
+
// src/chat/browser-ai-language-model.ts
|
|
1034
1209
|
function doesBrowserSupportBrowserAI() {
|
|
1035
1210
|
return typeof LanguageModel !== "undefined";
|
|
1036
1211
|
}
|
|
@@ -1367,213 +1542,40 @@ var BrowserAIChatLanguageModel = class {
|
|
|
1367
1542
|
if (options.abortSignal) {
|
|
1368
1543
|
options.abortSignal.addEventListener("abort", abortHandler);
|
|
1369
1544
|
}
|
|
1370
|
-
const maxIterations = 10;
|
|
1371
|
-
let iteration = 0;
|
|
1372
1545
|
try {
|
|
1373
|
-
const
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
);
|
|
1380
|
-
currentReader = promptStream.getReader();
|
|
1381
|
-
let toolCalls = [];
|
|
1382
|
-
let toolBlockDetected = false;
|
|
1383
|
-
let trailingTextAfterBlock = "";
|
|
1384
|
-
let currentToolCallId = null;
|
|
1385
|
-
let toolInputStartEmitted = false;
|
|
1386
|
-
let accumulatedFenceContent = "";
|
|
1387
|
-
let argumentsStreamState = createArgumentsStreamState();
|
|
1388
|
-
let insideFence = false;
|
|
1546
|
+
const promptStream = session.promptStreaming(
|
|
1547
|
+
conversationHistory,
|
|
1548
|
+
streamOptions
|
|
1549
|
+
);
|
|
1550
|
+
currentReader = promptStream.getReader();
|
|
1551
|
+
const chunks = (async function* () {
|
|
1389
1552
|
while (!aborted) {
|
|
1390
1553
|
const { done, value } = await currentReader.read();
|
|
1391
|
-
if (done)
|
|
1392
|
-
|
|
1393
|
-
}
|
|
1394
|
-
fenceDetector.addChunk(value);
|
|
1395
|
-
while (fenceDetector.hasContent()) {
|
|
1396
|
-
const wasInsideFence = insideFence;
|
|
1397
|
-
const result = fenceDetector.detectStreamingFence();
|
|
1398
|
-
insideFence = result.inFence;
|
|
1399
|
-
let madeProgress = false;
|
|
1400
|
-
if (!wasInsideFence && result.inFence) {
|
|
1401
|
-
if (result.safeContent) {
|
|
1402
|
-
emitTextDelta(result.safeContent);
|
|
1403
|
-
madeProgress = true;
|
|
1404
|
-
}
|
|
1405
|
-
currentToolCallId = `call_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1406
|
-
toolInputStartEmitted = false;
|
|
1407
|
-
accumulatedFenceContent = "";
|
|
1408
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1409
|
-
insideFence = true;
|
|
1410
|
-
continue;
|
|
1411
|
-
}
|
|
1412
|
-
if (result.completeFence) {
|
|
1413
|
-
madeProgress = true;
|
|
1414
|
-
if (result.safeContent) {
|
|
1415
|
-
accumulatedFenceContent += result.safeContent;
|
|
1416
|
-
}
|
|
1417
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1418
|
-
const delta = extractArgumentsDelta(
|
|
1419
|
-
accumulatedFenceContent,
|
|
1420
|
-
argumentsStreamState
|
|
1421
|
-
);
|
|
1422
|
-
if (delta.length > 0) {
|
|
1423
|
-
controller.enqueue({
|
|
1424
|
-
type: "tool-input-delta",
|
|
1425
|
-
id: currentToolCallId,
|
|
1426
|
-
delta
|
|
1427
|
-
});
|
|
1428
|
-
}
|
|
1429
|
-
}
|
|
1430
|
-
const parsed = parseJsonFunctionCalls(result.completeFence);
|
|
1431
|
-
const parsedToolCalls = parsed.toolCalls;
|
|
1432
|
-
const selectedToolCalls = parsedToolCalls.slice(0, 1);
|
|
1433
|
-
if (selectedToolCalls.length === 0) {
|
|
1434
|
-
toolCalls = [];
|
|
1435
|
-
toolBlockDetected = false;
|
|
1436
|
-
emitTextDelta(result.completeFence);
|
|
1437
|
-
if (result.textAfterFence) {
|
|
1438
|
-
emitTextDelta(result.textAfterFence);
|
|
1439
|
-
}
|
|
1440
|
-
currentToolCallId = null;
|
|
1441
|
-
toolInputStartEmitted = false;
|
|
1442
|
-
accumulatedFenceContent = "";
|
|
1443
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1444
|
-
insideFence = false;
|
|
1445
|
-
continue;
|
|
1446
|
-
}
|
|
1447
|
-
if (selectedToolCalls.length > 0 && currentToolCallId) {
|
|
1448
|
-
selectedToolCalls[0].toolCallId = currentToolCallId;
|
|
1449
|
-
}
|
|
1450
|
-
toolCalls = selectedToolCalls;
|
|
1451
|
-
toolBlockDetected = toolCalls.length > 0;
|
|
1452
|
-
for (const [index, call] of toolCalls.entries()) {
|
|
1453
|
-
const toolCallId = index === 0 && currentToolCallId ? currentToolCallId : call.toolCallId;
|
|
1454
|
-
const toolName = call.toolName;
|
|
1455
|
-
const argsJson = JSON.stringify(call.args ?? {});
|
|
1456
|
-
if (toolCallId === currentToolCallId) {
|
|
1457
|
-
if (!toolInputStartEmitted) {
|
|
1458
|
-
controller.enqueue({
|
|
1459
|
-
type: "tool-input-start",
|
|
1460
|
-
id: toolCallId,
|
|
1461
|
-
toolName
|
|
1462
|
-
});
|
|
1463
|
-
toolInputStartEmitted = true;
|
|
1464
|
-
}
|
|
1465
|
-
const delta = extractArgumentsDelta(
|
|
1466
|
-
accumulatedFenceContent,
|
|
1467
|
-
argumentsStreamState
|
|
1468
|
-
);
|
|
1469
|
-
if (delta.length > 0) {
|
|
1470
|
-
controller.enqueue({
|
|
1471
|
-
type: "tool-input-delta",
|
|
1472
|
-
id: toolCallId,
|
|
1473
|
-
delta
|
|
1474
|
-
});
|
|
1475
|
-
}
|
|
1476
|
-
} else {
|
|
1477
|
-
controller.enqueue({
|
|
1478
|
-
type: "tool-input-start",
|
|
1479
|
-
id: toolCallId,
|
|
1480
|
-
toolName
|
|
1481
|
-
});
|
|
1482
|
-
if (argsJson.length > 0) {
|
|
1483
|
-
controller.enqueue({
|
|
1484
|
-
type: "tool-input-delta",
|
|
1485
|
-
id: toolCallId,
|
|
1486
|
-
delta: argsJson
|
|
1487
|
-
});
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
controller.enqueue({
|
|
1491
|
-
type: "tool-input-end",
|
|
1492
|
-
id: toolCallId
|
|
1493
|
-
});
|
|
1494
|
-
controller.enqueue({
|
|
1495
|
-
type: "tool-call",
|
|
1496
|
-
toolCallId,
|
|
1497
|
-
toolName,
|
|
1498
|
-
input: argsJson,
|
|
1499
|
-
providerExecuted: false
|
|
1500
|
-
});
|
|
1501
|
-
}
|
|
1502
|
-
trailingTextAfterBlock += result.textAfterFence;
|
|
1503
|
-
madeProgress = true;
|
|
1504
|
-
if (toolBlockDetected && currentReader) {
|
|
1505
|
-
await currentReader.cancel().catch(() => void 0);
|
|
1506
|
-
break;
|
|
1507
|
-
}
|
|
1508
|
-
currentToolCallId = null;
|
|
1509
|
-
toolInputStartEmitted = false;
|
|
1510
|
-
accumulatedFenceContent = "";
|
|
1511
|
-
argumentsStreamState = createArgumentsStreamState();
|
|
1512
|
-
insideFence = false;
|
|
1513
|
-
continue;
|
|
1514
|
-
}
|
|
1515
|
-
if (insideFence) {
|
|
1516
|
-
if (result.safeContent) {
|
|
1517
|
-
accumulatedFenceContent += result.safeContent;
|
|
1518
|
-
madeProgress = true;
|
|
1519
|
-
const toolName = extractToolName(accumulatedFenceContent);
|
|
1520
|
-
if (toolName && !toolInputStartEmitted && currentToolCallId) {
|
|
1521
|
-
controller.enqueue({
|
|
1522
|
-
type: "tool-input-start",
|
|
1523
|
-
id: currentToolCallId,
|
|
1524
|
-
toolName
|
|
1525
|
-
});
|
|
1526
|
-
toolInputStartEmitted = true;
|
|
1527
|
-
}
|
|
1528
|
-
if (toolInputStartEmitted && currentToolCallId) {
|
|
1529
|
-
const delta = extractArgumentsDelta(
|
|
1530
|
-
accumulatedFenceContent,
|
|
1531
|
-
argumentsStreamState
|
|
1532
|
-
);
|
|
1533
|
-
if (delta.length > 0) {
|
|
1534
|
-
controller.enqueue({
|
|
1535
|
-
type: "tool-input-delta",
|
|
1536
|
-
id: currentToolCallId,
|
|
1537
|
-
delta
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
continue;
|
|
1543
|
-
}
|
|
1544
|
-
if (!insideFence && result.safeContent) {
|
|
1545
|
-
emitTextDelta(result.safeContent);
|
|
1546
|
-
madeProgress = true;
|
|
1547
|
-
}
|
|
1548
|
-
if (!madeProgress) {
|
|
1549
|
-
break;
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
if (toolBlockDetected) {
|
|
1553
|
-
break;
|
|
1554
|
-
}
|
|
1554
|
+
if (done) break;
|
|
1555
|
+
yield value;
|
|
1555
1556
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
finishStream({ unified: "
|
|
1557
|
+
})();
|
|
1558
|
+
const result = await processToolCallStream(
|
|
1559
|
+
chunks,
|
|
1560
|
+
emitTextDelta,
|
|
1561
|
+
controller,
|
|
1562
|
+
{ stopEarlyOnToolCall: true }
|
|
1563
|
+
);
|
|
1564
|
+
if (result.toolCallDetected && currentReader) {
|
|
1565
|
+
await currentReader.cancel().catch(() => void 0);
|
|
1566
|
+
}
|
|
1567
|
+
currentReader = null;
|
|
1568
|
+
if (aborted) {
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
if (!result.toolCallDetected || result.toolCalls.length === 0) {
|
|
1572
|
+
finishStream({ unified: "stop", raw: "stop" });
|
|
1572
1573
|
return;
|
|
1573
1574
|
}
|
|
1574
|
-
if (
|
|
1575
|
-
|
|
1575
|
+
if (result.trailingText) {
|
|
1576
|
+
emitTextDelta(result.trailingText);
|
|
1576
1577
|
}
|
|
1578
|
+
finishStream({ unified: "tool-calls", raw: "tool-calls" });
|
|
1577
1579
|
} catch (error) {
|
|
1578
1580
|
controller.enqueue({ type: "error", error });
|
|
1579
1581
|
controller.close();
|
|
@@ -1591,7 +1593,7 @@ var BrowserAIChatLanguageModel = class {
|
|
|
1591
1593
|
}
|
|
1592
1594
|
};
|
|
1593
1595
|
|
|
1594
|
-
// src/browser-ai-embedding-model.ts
|
|
1596
|
+
// src/embedding/browser-ai-embedding-model.ts
|
|
1595
1597
|
import { TextEmbedder } from "@mediapipe/tasks-text";
|
|
1596
1598
|
var BrowserAIEmbeddingModel = class {
|
|
1597
1599
|
constructor(settings = {}) {
|