@yourgpt/llm-sdk 1.3.0 → 1.4.0
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/README.md +34 -0
- package/dist/index.d.mts +424 -13
- package/dist/index.d.ts +424 -13
- package/dist/index.js +505 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +499 -24
- package/dist/index.mjs.map +1 -1
- package/dist/providers/openai/index.d.mts +17 -8
- package/dist/providers/openai/index.d.ts +17 -8
- package/dist/providers/openai/index.js.map +1 -1
- package/dist/providers/openai/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1363,6 +1363,12 @@ function createSSEHeaders() {
|
|
|
1363
1363
|
"X-Accel-Buffering": "no"
|
|
1364
1364
|
};
|
|
1365
1365
|
}
|
|
1366
|
+
function createTextStreamHeaders() {
|
|
1367
|
+
return {
|
|
1368
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
1369
|
+
"Cache-Control": "no-cache"
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1366
1372
|
function formatSSEData(event) {
|
|
1367
1373
|
return `data: ${JSON.stringify(event)}
|
|
1368
1374
|
|
|
@@ -1390,11 +1396,407 @@ function createEventStream(generator) {
|
|
|
1390
1396
|
}
|
|
1391
1397
|
});
|
|
1392
1398
|
}
|
|
1393
|
-
function createSSEResponse(generator) {
|
|
1399
|
+
function createSSEResponse(generator, options) {
|
|
1394
1400
|
return new Response(createEventStream(generator), {
|
|
1395
|
-
headers:
|
|
1401
|
+
headers: {
|
|
1402
|
+
...createSSEHeaders(),
|
|
1403
|
+
...options?.headers
|
|
1404
|
+
}
|
|
1396
1405
|
});
|
|
1397
1406
|
}
|
|
1407
|
+
function createTextStreamResponse(generator, options) {
|
|
1408
|
+
const encoder = new TextEncoder();
|
|
1409
|
+
const stream = new ReadableStream({
|
|
1410
|
+
async start(controller) {
|
|
1411
|
+
try {
|
|
1412
|
+
for await (const event of generator) {
|
|
1413
|
+
if (event.type === "message:delta") {
|
|
1414
|
+
controller.enqueue(encoder.encode(event.content));
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
} catch (error) {
|
|
1418
|
+
console.error("[Streaming] Text stream error:", error);
|
|
1419
|
+
} finally {
|
|
1420
|
+
controller.close();
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
return new Response(stream, {
|
|
1425
|
+
headers: {
|
|
1426
|
+
...createTextStreamHeaders(),
|
|
1427
|
+
...options?.headers
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
async function pipeSSEToResponse(generator, res, options) {
|
|
1432
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
1433
|
+
res.setHeader("Cache-Control", "no-cache, no-transform");
|
|
1434
|
+
res.setHeader("Connection", "keep-alive");
|
|
1435
|
+
res.setHeader("X-Accel-Buffering", "no");
|
|
1436
|
+
if (options?.headers) {
|
|
1437
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
1438
|
+
res.setHeader(key, value);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
try {
|
|
1442
|
+
for await (const event of generator) {
|
|
1443
|
+
res.write(formatSSEData(event));
|
|
1444
|
+
}
|
|
1445
|
+
} catch (error) {
|
|
1446
|
+
const errorEvent = {
|
|
1447
|
+
type: "error",
|
|
1448
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1449
|
+
};
|
|
1450
|
+
res.write(formatSSEData(errorEvent));
|
|
1451
|
+
} finally {
|
|
1452
|
+
res.write("data: [DONE]\n\n");
|
|
1453
|
+
res.end();
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
async function pipeTextToResponse(generator, res, options) {
|
|
1457
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
1458
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
1459
|
+
if (options?.headers) {
|
|
1460
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
1461
|
+
res.setHeader(key, value);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
try {
|
|
1465
|
+
for await (const event of generator) {
|
|
1466
|
+
if (event.type === "message:delta") {
|
|
1467
|
+
res.write(event.content);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
} finally {
|
|
1471
|
+
res.end();
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
// src/server/stream-result.ts
|
|
1476
|
+
var StreamResult = class {
|
|
1477
|
+
constructor(generator) {
|
|
1478
|
+
this.consumed = false;
|
|
1479
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
1480
|
+
this.generator = generator;
|
|
1481
|
+
}
|
|
1482
|
+
// ============================================
|
|
1483
|
+
// Async Iteration (base pattern)
|
|
1484
|
+
// ============================================
|
|
1485
|
+
/**
|
|
1486
|
+
* Iterate over stream events
|
|
1487
|
+
*
|
|
1488
|
+
* @example
|
|
1489
|
+
* ```typescript
|
|
1490
|
+
* const result = runtime.stream(body);
|
|
1491
|
+
* for await (const event of result) {
|
|
1492
|
+
* if (event.type === 'message:delta') {
|
|
1493
|
+
* console.log(event.content);
|
|
1494
|
+
* }
|
|
1495
|
+
* }
|
|
1496
|
+
* ```
|
|
1497
|
+
*/
|
|
1498
|
+
[Symbol.asyncIterator]() {
|
|
1499
|
+
this.ensureNotConsumed();
|
|
1500
|
+
return this.generator;
|
|
1501
|
+
}
|
|
1502
|
+
// ============================================
|
|
1503
|
+
// Web API Response Methods (Next.js, Cloudflare, Deno)
|
|
1504
|
+
// ============================================
|
|
1505
|
+
/**
|
|
1506
|
+
* Returns SSE Response for Web API frameworks
|
|
1507
|
+
*
|
|
1508
|
+
* @example
|
|
1509
|
+
* ```typescript
|
|
1510
|
+
* // Next.js App Router
|
|
1511
|
+
* export async function POST(req: Request) {
|
|
1512
|
+
* const body = await req.json();
|
|
1513
|
+
* return runtime.stream(body).toResponse();
|
|
1514
|
+
* }
|
|
1515
|
+
* ```
|
|
1516
|
+
*/
|
|
1517
|
+
toResponse(options) {
|
|
1518
|
+
this.ensureNotConsumed();
|
|
1519
|
+
const headers = {
|
|
1520
|
+
...createSSEHeaders(),
|
|
1521
|
+
...options?.headers
|
|
1522
|
+
};
|
|
1523
|
+
return new Response(createEventStream(this.generator), { headers });
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Alias for toResponse() - returns SSE Response
|
|
1527
|
+
*/
|
|
1528
|
+
toSSEResponse(options) {
|
|
1529
|
+
return this.toResponse(options);
|
|
1530
|
+
}
|
|
1531
|
+
/**
|
|
1532
|
+
* Returns text-only Response (no SSE events, just text content)
|
|
1533
|
+
*
|
|
1534
|
+
* @example
|
|
1535
|
+
* ```typescript
|
|
1536
|
+
* // Simple text streaming
|
|
1537
|
+
* return runtime.stream(body).toTextResponse();
|
|
1538
|
+
* ```
|
|
1539
|
+
*/
|
|
1540
|
+
toTextResponse(options) {
|
|
1541
|
+
this.ensureNotConsumed();
|
|
1542
|
+
const encoder = new TextEncoder();
|
|
1543
|
+
const generator = this.generator;
|
|
1544
|
+
const stream = new ReadableStream({
|
|
1545
|
+
async start(controller) {
|
|
1546
|
+
try {
|
|
1547
|
+
for await (const event of generator) {
|
|
1548
|
+
if (event.type === "message:delta") {
|
|
1549
|
+
controller.enqueue(encoder.encode(event.content));
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
} catch (error) {
|
|
1553
|
+
console.error("[StreamResult] Text stream error:", error);
|
|
1554
|
+
} finally {
|
|
1555
|
+
controller.close();
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
return new Response(stream, {
|
|
1560
|
+
headers: {
|
|
1561
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
1562
|
+
"Cache-Control": "no-cache",
|
|
1563
|
+
...options?.headers
|
|
1564
|
+
}
|
|
1565
|
+
});
|
|
1566
|
+
}
|
|
1567
|
+
/**
|
|
1568
|
+
* Returns the underlying ReadableStream
|
|
1569
|
+
*
|
|
1570
|
+
* @example
|
|
1571
|
+
* ```typescript
|
|
1572
|
+
* const stream = runtime.stream(body).toReadableStream();
|
|
1573
|
+
* // Use with custom handling
|
|
1574
|
+
* ```
|
|
1575
|
+
*/
|
|
1576
|
+
toReadableStream() {
|
|
1577
|
+
this.ensureNotConsumed();
|
|
1578
|
+
return createEventStream(this.generator);
|
|
1579
|
+
}
|
|
1580
|
+
// ============================================
|
|
1581
|
+
// Node.js/Express Response Methods
|
|
1582
|
+
// ============================================
|
|
1583
|
+
/**
|
|
1584
|
+
* Pipe SSE stream to Node.js ServerResponse
|
|
1585
|
+
*
|
|
1586
|
+
* @example
|
|
1587
|
+
* ```typescript
|
|
1588
|
+
* // Express - one-liner
|
|
1589
|
+
* app.post('/chat', async (req, res) => {
|
|
1590
|
+
* await runtime.stream(req.body).pipeToResponse(res);
|
|
1591
|
+
* });
|
|
1592
|
+
* ```
|
|
1593
|
+
*/
|
|
1594
|
+
async pipeToResponse(res, options) {
|
|
1595
|
+
this.ensureNotConsumed();
|
|
1596
|
+
res.setHeader("Content-Type", "text/event-stream");
|
|
1597
|
+
res.setHeader("Cache-Control", "no-cache, no-transform");
|
|
1598
|
+
res.setHeader("Connection", "keep-alive");
|
|
1599
|
+
res.setHeader("X-Accel-Buffering", "no");
|
|
1600
|
+
if (options?.headers) {
|
|
1601
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
1602
|
+
res.setHeader(key, value);
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
const collected = this.createCollector();
|
|
1606
|
+
try {
|
|
1607
|
+
for await (const event of this.generator) {
|
|
1608
|
+
this.collectEvent(event, collected);
|
|
1609
|
+
this.callEventHandlers(event, collected);
|
|
1610
|
+
res.write(formatSSEData(event));
|
|
1611
|
+
}
|
|
1612
|
+
} catch (error) {
|
|
1613
|
+
const errorEvent = {
|
|
1614
|
+
type: "error",
|
|
1615
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
1616
|
+
};
|
|
1617
|
+
res.write(formatSSEData(errorEvent));
|
|
1618
|
+
const errorHandler = this.eventHandlers.get("error");
|
|
1619
|
+
if (errorHandler) {
|
|
1620
|
+
errorHandler(error instanceof Error ? error : new Error(String(error)));
|
|
1621
|
+
}
|
|
1622
|
+
} finally {
|
|
1623
|
+
res.write("data: [DONE]\n\n");
|
|
1624
|
+
res.end();
|
|
1625
|
+
}
|
|
1626
|
+
const doneHandler = this.eventHandlers.get("done");
|
|
1627
|
+
if (doneHandler) {
|
|
1628
|
+
doneHandler(collected);
|
|
1629
|
+
}
|
|
1630
|
+
return collected;
|
|
1631
|
+
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Pipe text-only stream to Node.js ServerResponse
|
|
1634
|
+
*
|
|
1635
|
+
* @example
|
|
1636
|
+
* ```typescript
|
|
1637
|
+
* // Express - text-only streaming
|
|
1638
|
+
* app.post('/chat', async (req, res) => {
|
|
1639
|
+
* await runtime.stream(req.body).pipeTextToResponse(res);
|
|
1640
|
+
* });
|
|
1641
|
+
* ```
|
|
1642
|
+
*/
|
|
1643
|
+
async pipeTextToResponse(res, options) {
|
|
1644
|
+
this.ensureNotConsumed();
|
|
1645
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
1646
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
1647
|
+
if (options?.headers) {
|
|
1648
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
1649
|
+
res.setHeader(key, value);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
const collected = this.createCollector();
|
|
1653
|
+
try {
|
|
1654
|
+
for await (const event of this.generator) {
|
|
1655
|
+
this.collectEvent(event, collected);
|
|
1656
|
+
this.callEventHandlers(event, collected);
|
|
1657
|
+
if (event.type === "message:delta") {
|
|
1658
|
+
res.write(event.content);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
} catch (error) {
|
|
1662
|
+
const errorHandler = this.eventHandlers.get("error");
|
|
1663
|
+
if (errorHandler) {
|
|
1664
|
+
errorHandler(error instanceof Error ? error : new Error(String(error)));
|
|
1665
|
+
}
|
|
1666
|
+
} finally {
|
|
1667
|
+
res.end();
|
|
1668
|
+
}
|
|
1669
|
+
const doneHandler = this.eventHandlers.get("done");
|
|
1670
|
+
if (doneHandler) {
|
|
1671
|
+
doneHandler(collected);
|
|
1672
|
+
}
|
|
1673
|
+
return collected;
|
|
1674
|
+
}
|
|
1675
|
+
// ============================================
|
|
1676
|
+
// Collection Methods
|
|
1677
|
+
// ============================================
|
|
1678
|
+
/**
|
|
1679
|
+
* Collect all events and return final result
|
|
1680
|
+
*
|
|
1681
|
+
* @example
|
|
1682
|
+
* ```typescript
|
|
1683
|
+
* const { text, messages, toolCalls } = await runtime.stream(body).collect();
|
|
1684
|
+
* console.log('Response:', text);
|
|
1685
|
+
* ```
|
|
1686
|
+
*/
|
|
1687
|
+
async collect() {
|
|
1688
|
+
this.ensureNotConsumed();
|
|
1689
|
+
const collected = this.createCollector();
|
|
1690
|
+
for await (const event of this.generator) {
|
|
1691
|
+
this.collectEvent(event, collected);
|
|
1692
|
+
this.callEventHandlers(event, collected);
|
|
1693
|
+
}
|
|
1694
|
+
const doneHandler = this.eventHandlers.get("done");
|
|
1695
|
+
if (doneHandler) {
|
|
1696
|
+
doneHandler(collected);
|
|
1697
|
+
}
|
|
1698
|
+
return collected;
|
|
1699
|
+
}
|
|
1700
|
+
/**
|
|
1701
|
+
* Get final text (convenience method)
|
|
1702
|
+
*
|
|
1703
|
+
* @example
|
|
1704
|
+
* ```typescript
|
|
1705
|
+
* const text = await runtime.stream(body).text();
|
|
1706
|
+
* ```
|
|
1707
|
+
*/
|
|
1708
|
+
async text() {
|
|
1709
|
+
const result = await this.collect();
|
|
1710
|
+
return result.text;
|
|
1711
|
+
}
|
|
1712
|
+
on(event, handler) {
|
|
1713
|
+
this.eventHandlers.set(event, handler);
|
|
1714
|
+
return this;
|
|
1715
|
+
}
|
|
1716
|
+
// ============================================
|
|
1717
|
+
// Internal Methods
|
|
1718
|
+
// ============================================
|
|
1719
|
+
/**
|
|
1720
|
+
* Ensure stream hasn't been consumed
|
|
1721
|
+
*/
|
|
1722
|
+
ensureNotConsumed() {
|
|
1723
|
+
if (this.consumed) {
|
|
1724
|
+
throw new Error(
|
|
1725
|
+
"StreamResult has already been consumed. Each StreamResult can only be consumed once."
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
this.consumed = true;
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Create empty collector object
|
|
1732
|
+
*/
|
|
1733
|
+
createCollector() {
|
|
1734
|
+
return {
|
|
1735
|
+
text: "",
|
|
1736
|
+
messages: [],
|
|
1737
|
+
toolCalls: [],
|
|
1738
|
+
requiresAction: false,
|
|
1739
|
+
events: []
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Collect event into result
|
|
1744
|
+
*/
|
|
1745
|
+
collectEvent(event, collected) {
|
|
1746
|
+
collected.events.push(event);
|
|
1747
|
+
switch (event.type) {
|
|
1748
|
+
case "message:delta":
|
|
1749
|
+
collected.text += event.content;
|
|
1750
|
+
break;
|
|
1751
|
+
case "tool_calls":
|
|
1752
|
+
collected.toolCalls.push(...event.toolCalls);
|
|
1753
|
+
break;
|
|
1754
|
+
case "done":
|
|
1755
|
+
if (event.messages) {
|
|
1756
|
+
collected.messages.push(...event.messages);
|
|
1757
|
+
}
|
|
1758
|
+
if (event.requiresAction) {
|
|
1759
|
+
collected.requiresAction = true;
|
|
1760
|
+
}
|
|
1761
|
+
break;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Call registered event handlers
|
|
1766
|
+
*/
|
|
1767
|
+
callEventHandlers(event, collected) {
|
|
1768
|
+
switch (event.type) {
|
|
1769
|
+
case "message:delta": {
|
|
1770
|
+
const textHandler = this.eventHandlers.get("text");
|
|
1771
|
+
if (textHandler) {
|
|
1772
|
+
textHandler(event.content);
|
|
1773
|
+
}
|
|
1774
|
+
break;
|
|
1775
|
+
}
|
|
1776
|
+
case "tool_calls": {
|
|
1777
|
+
const toolCallHandler = this.eventHandlers.get(
|
|
1778
|
+
"toolCall"
|
|
1779
|
+
);
|
|
1780
|
+
if (toolCallHandler) {
|
|
1781
|
+
for (const toolCall of event.toolCalls) {
|
|
1782
|
+
toolCallHandler(toolCall);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
break;
|
|
1786
|
+
}
|
|
1787
|
+
case "error": {
|
|
1788
|
+
const errorHandler = this.eventHandlers.get("error");
|
|
1789
|
+
if (errorHandler) {
|
|
1790
|
+
errorHandler(new Error(event.message));
|
|
1791
|
+
}
|
|
1792
|
+
break;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
function createStreamResult(generator) {
|
|
1798
|
+
return new StreamResult(generator);
|
|
1799
|
+
}
|
|
1398
1800
|
|
|
1399
1801
|
// src/server/runtime.ts
|
|
1400
1802
|
function buildToolResultForAI(tool2, result, args) {
|
|
@@ -2464,6 +2866,89 @@ var Runtime = class {
|
|
|
2464
2866
|
}
|
|
2465
2867
|
return parameters;
|
|
2466
2868
|
}
|
|
2869
|
+
// ============================================
|
|
2870
|
+
// StreamResult API (Industry Standard Pattern)
|
|
2871
|
+
// ============================================
|
|
2872
|
+
/**
|
|
2873
|
+
* Stream chat and return StreamResult with helper methods
|
|
2874
|
+
*
|
|
2875
|
+
* This is the recommended API for new projects. It returns a StreamResult
|
|
2876
|
+
* object with multiple ways to consume the response:
|
|
2877
|
+
* - `pipeToResponse(res)` for Express/Node.js
|
|
2878
|
+
* - `toResponse()` for Next.js/Web API
|
|
2879
|
+
* - `collect()` for non-streaming use cases
|
|
2880
|
+
*
|
|
2881
|
+
* @example
|
|
2882
|
+
* ```typescript
|
|
2883
|
+
* // Express - one-liner
|
|
2884
|
+
* app.post('/chat', async (req, res) => {
|
|
2885
|
+
* await runtime.stream(req.body).pipeToResponse(res);
|
|
2886
|
+
* });
|
|
2887
|
+
*
|
|
2888
|
+
* // Next.js App Router
|
|
2889
|
+
* export async function POST(req: Request) {
|
|
2890
|
+
* const body = await req.json();
|
|
2891
|
+
* return runtime.stream(body).toResponse();
|
|
2892
|
+
* }
|
|
2893
|
+
*
|
|
2894
|
+
* // With event handlers
|
|
2895
|
+
* const result = runtime.stream(body)
|
|
2896
|
+
* .on('text', (text) => console.log(text))
|
|
2897
|
+
* .on('done', (result) => console.log('Done:', result.text));
|
|
2898
|
+
* await result.pipeToResponse(res);
|
|
2899
|
+
* ```
|
|
2900
|
+
*/
|
|
2901
|
+
stream(request, options) {
|
|
2902
|
+
const generator = this.processChatWithLoop(request, options?.signal);
|
|
2903
|
+
return new StreamResult(generator);
|
|
2904
|
+
}
|
|
2905
|
+
/**
|
|
2906
|
+
* Chat and collect the full response (non-streaming)
|
|
2907
|
+
*
|
|
2908
|
+
* Convenience method that calls stream().collect() for you.
|
|
2909
|
+
* Use this when you need the complete response before responding.
|
|
2910
|
+
*
|
|
2911
|
+
* @example
|
|
2912
|
+
* ```typescript
|
|
2913
|
+
* const { text, messages, toolCalls } = await runtime.chat(body);
|
|
2914
|
+
* console.log('Response:', text);
|
|
2915
|
+
* res.json({ response: text });
|
|
2916
|
+
* ```
|
|
2917
|
+
*/
|
|
2918
|
+
async chat(request, options) {
|
|
2919
|
+
return this.stream(request, options).collect();
|
|
2920
|
+
}
|
|
2921
|
+
/**
|
|
2922
|
+
* Create Express-compatible handler middleware
|
|
2923
|
+
*
|
|
2924
|
+
* Returns a function that can be used directly as Express middleware.
|
|
2925
|
+
*
|
|
2926
|
+
* @example
|
|
2927
|
+
* ```typescript
|
|
2928
|
+
* // Simple usage
|
|
2929
|
+
* app.post('/chat', runtime.expressHandler());
|
|
2930
|
+
*
|
|
2931
|
+
* // With options
|
|
2932
|
+
* app.post('/chat', runtime.expressHandler({ format: 'text' }));
|
|
2933
|
+
* ```
|
|
2934
|
+
*/
|
|
2935
|
+
expressHandler(options) {
|
|
2936
|
+
return async (req, res) => {
|
|
2937
|
+
try {
|
|
2938
|
+
const result = this.stream(req.body);
|
|
2939
|
+
if (options?.format === "text") {
|
|
2940
|
+
await result.pipeTextToResponse(res, { headers: options?.headers });
|
|
2941
|
+
} else {
|
|
2942
|
+
await result.pipeToResponse(res, { headers: options?.headers });
|
|
2943
|
+
}
|
|
2944
|
+
} catch (error) {
|
|
2945
|
+
console.error("[Runtime] Express handler error:", error);
|
|
2946
|
+
res.status(500).json({
|
|
2947
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
2948
|
+
});
|
|
2949
|
+
}
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2467
2952
|
};
|
|
2468
2953
|
function createRuntime(config) {
|
|
2469
2954
|
return new Runtime(config);
|
|
@@ -2551,38 +3036,28 @@ function createNextHandler(config) {
|
|
|
2551
3036
|
return runtime.handleRequest(request);
|
|
2552
3037
|
};
|
|
2553
3038
|
}
|
|
2554
|
-
function createExpressMiddleware(config) {
|
|
3039
|
+
function createExpressMiddleware(config, options) {
|
|
2555
3040
|
const runtime = createRuntime(config);
|
|
2556
|
-
createHonoApp(runtime);
|
|
2557
3041
|
return async (req, res) => {
|
|
2558
3042
|
try {
|
|
2559
|
-
const
|
|
2560
|
-
const
|
|
2561
|
-
|
|
2562
|
-
headers:
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
const response = await runtime.handleRequest(request);
|
|
2566
|
-
response.headers.forEach((value, key) => {
|
|
2567
|
-
res.setHeader(key, value);
|
|
2568
|
-
});
|
|
2569
|
-
if (response.body) {
|
|
2570
|
-
const reader = response.body.getReader();
|
|
2571
|
-
const decoder = new TextDecoder();
|
|
2572
|
-
while (true) {
|
|
2573
|
-
const { done, value } = await reader.read();
|
|
2574
|
-
if (done) break;
|
|
2575
|
-
res.write(decoder.decode(value));
|
|
2576
|
-
}
|
|
3043
|
+
const result = runtime.stream(req.body);
|
|
3044
|
+
const nodeRes = res;
|
|
3045
|
+
if (options?.format === "text") {
|
|
3046
|
+
await result.pipeTextToResponse(nodeRes, { headers: options?.headers });
|
|
3047
|
+
} else {
|
|
3048
|
+
await result.pipeToResponse(nodeRes, { headers: options?.headers });
|
|
2577
3049
|
}
|
|
2578
|
-
res.end();
|
|
2579
3050
|
} catch (error) {
|
|
3051
|
+
console.error("[Express Middleware] Error:", error);
|
|
2580
3052
|
res.status(500).json({
|
|
2581
3053
|
error: error instanceof Error ? error.message : "Unknown error"
|
|
2582
3054
|
});
|
|
2583
3055
|
}
|
|
2584
3056
|
};
|
|
2585
3057
|
}
|
|
3058
|
+
function createExpressHandler(runtime, options) {
|
|
3059
|
+
return runtime.expressHandler(options);
|
|
3060
|
+
}
|
|
2586
3061
|
function createNodeHandler(config) {
|
|
2587
3062
|
const runtime = createRuntime(config);
|
|
2588
3063
|
const app = createHonoApp(runtime);
|
|
@@ -3149,7 +3624,9 @@ async function executeToolCalls(toolCalls, tools, executeServerTool, waitForClie
|
|
|
3149
3624
|
exports.DEFAULT_CAPABILITIES = DEFAULT_CAPABILITIES;
|
|
3150
3625
|
exports.DEFAULT_MAX_ITERATIONS = DEFAULT_MAX_ITERATIONS;
|
|
3151
3626
|
exports.Runtime = Runtime;
|
|
3627
|
+
exports.StreamResult = StreamResult;
|
|
3152
3628
|
exports.createEventStream = createEventStream;
|
|
3629
|
+
exports.createExpressHandler = createExpressHandler;
|
|
3153
3630
|
exports.createExpressMiddleware = createExpressMiddleware;
|
|
3154
3631
|
exports.createHonoApp = createHonoApp;
|
|
3155
3632
|
exports.createNextHandler = createNextHandler;
|
|
@@ -3157,11 +3634,16 @@ exports.createNodeHandler = createNodeHandler;
|
|
|
3157
3634
|
exports.createRuntime = createRuntime;
|
|
3158
3635
|
exports.createSSEHeaders = createSSEHeaders;
|
|
3159
3636
|
exports.createSSEResponse = createSSEResponse;
|
|
3637
|
+
exports.createStreamResult = createStreamResult;
|
|
3638
|
+
exports.createTextStreamHeaders = createTextStreamHeaders;
|
|
3639
|
+
exports.createTextStreamResponse = createTextStreamResponse;
|
|
3160
3640
|
exports.formatSSEData = formatSSEData;
|
|
3161
3641
|
exports.formatToolsForAnthropic = formatToolsForAnthropic;
|
|
3162
3642
|
exports.formatToolsForGoogle = formatToolsForGoogle;
|
|
3163
3643
|
exports.formatToolsForOpenAI = formatToolsForOpenAI;
|
|
3164
3644
|
exports.generateText = generateText;
|
|
3645
|
+
exports.pipeSSEToResponse = pipeSSEToResponse;
|
|
3646
|
+
exports.pipeTextToResponse = pipeTextToResponse;
|
|
3165
3647
|
exports.runAgentLoop = runAgentLoop;
|
|
3166
3648
|
exports.streamText = streamText;
|
|
3167
3649
|
exports.tool = tool;
|