@radaros/transport 0.3.32 → 0.3.35

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.cjs CHANGED
@@ -851,7 +851,11 @@ var SCHEMAS = {
851
851
  properties: {
852
852
  promptTokens: { type: "number" },
853
853
  completionTokens: { type: "number" },
854
- totalTokens: { type: "number" }
854
+ totalTokens: { type: "number" },
855
+ reasoningTokens: { type: "number", description: "Tokens used for chain-of-thought reasoning" },
856
+ cachedTokens: { type: "number", description: "Prompt tokens served from cache" },
857
+ audioInputTokens: { type: "number", description: "Audio input tokens" },
858
+ audioOutputTokens: { type: "number", description: "Audio output tokens" }
855
859
  }
856
860
  },
857
861
  structured: { description: "Parsed structured output (if schema is configured)" },
@@ -987,7 +991,11 @@ function generateOpenAPISpec(routerOpts, swaggerOpts = {}) {
987
991
  properties: {
988
992
  promptTokens: { type: "number" },
989
993
  completionTokens: { type: "number" },
990
- totalTokens: { type: "number" }
994
+ totalTokens: { type: "number" },
995
+ reasoningTokens: { type: "number", description: "Tokens used for chain-of-thought reasoning" },
996
+ cachedTokens: { type: "number", description: "Prompt tokens served from cache" },
997
+ audioInputTokens: { type: "number", description: "Audio input tokens" },
998
+ audioOutputTokens: { type: "number", description: "Audio output tokens" }
991
999
  }
992
1000
  },
993
1001
  structured: {
@@ -1606,6 +1614,99 @@ function createAgentRouter(opts) {
1606
1614
  router.get("/registry", (_req, res) => {
1607
1615
  res.json(reg.list());
1608
1616
  });
1617
+ router.get("/agents/:name/card", (req, res) => {
1618
+ const r = reg;
1619
+ if (typeof r.getAgentCard !== "function") return res.status(501).json({ error: "Discovery cards not available" });
1620
+ const card = r.getAgentCard(req.params.name);
1621
+ if (!card) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1622
+ res.json(card);
1623
+ });
1624
+ router.get("/.well-known/agent-cards.json", (_req, res) => {
1625
+ const r = reg;
1626
+ if (typeof r.getAllAgentCards !== "function") return res.json([]);
1627
+ res.json(r.getAllAgentCards());
1628
+ });
1629
+ router.get("/approvals/pending", (_req, res) => {
1630
+ const pending = [];
1631
+ for (const agent of reg.agents.values()) {
1632
+ const mgr = agent.approvalManager;
1633
+ if (mgr && typeof mgr.listPending === "function") {
1634
+ pending.push(...mgr.listPending());
1635
+ }
1636
+ }
1637
+ res.json(pending);
1638
+ });
1639
+ router.post("/approvals/:requestId/approve", (req, res) => {
1640
+ const { requestId } = req.params;
1641
+ const { reason } = req.body ?? {};
1642
+ for (const agent of reg.agents.values()) {
1643
+ const mgr = agent.approvalManager;
1644
+ if (mgr && typeof mgr.approve === "function") {
1645
+ mgr.approve(requestId, reason);
1646
+ }
1647
+ }
1648
+ res.json({ status: "approved", requestId });
1649
+ });
1650
+ router.post("/approvals/:requestId/deny", (req, res) => {
1651
+ const { requestId } = req.params;
1652
+ const { reason } = req.body ?? {};
1653
+ for (const agent of reg.agents.values()) {
1654
+ const mgr = agent.approvalManager;
1655
+ if (mgr && typeof mgr.deny === "function") {
1656
+ mgr.deny(requestId, reason);
1657
+ }
1658
+ }
1659
+ res.json({ status: "denied", requestId });
1660
+ });
1661
+ router.get("/agents/:name/checkpoints", async (req, res) => {
1662
+ const agent = reg.getAgent(req.params.name);
1663
+ if (!agent) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1664
+ const config = agent.config;
1665
+ const checkpointMgr = config?._checkpointManager;
1666
+ if (!checkpointMgr) return res.json([]);
1667
+ const runId = req.query.runId;
1668
+ if (!runId) return res.status(400).json({ error: "runId query param required" });
1669
+ try {
1670
+ const checkpoints = await checkpointMgr.list(runId);
1671
+ res.json(checkpoints);
1672
+ } catch (err) {
1673
+ res.status(500).json({ error: err.message });
1674
+ }
1675
+ });
1676
+ router.post("/agents/:name/rollback/:checkpointId", async (req, res) => {
1677
+ const agent = reg.getAgent(req.params.name);
1678
+ if (!agent) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1679
+ const config = agent.config;
1680
+ const checkpointMgr = config?._checkpointManager;
1681
+ if (!checkpointMgr) return res.status(400).json({ error: "Checkpointing not enabled for this agent" });
1682
+ try {
1683
+ const checkpoint = await checkpointMgr.rollback(req.params.checkpointId);
1684
+ if (!checkpoint) return res.status(404).json({ error: "Checkpoint not found" });
1685
+ res.json(checkpoint);
1686
+ } catch (err) {
1687
+ res.status(500).json({ error: err.message });
1688
+ }
1689
+ });
1690
+ router.get("/approvals/stream", (req, res) => {
1691
+ res.writeHead(200, {
1692
+ "Content-Type": "text/event-stream",
1693
+ "Cache-Control": "no-cache",
1694
+ Connection: "keep-alive"
1695
+ });
1696
+ const listener = (data) => {
1697
+ res.write(`data: ${JSON.stringify(data)}
1698
+
1699
+ `);
1700
+ };
1701
+ for (const agent of reg.agents.values()) {
1702
+ agent.eventBus.on("tool.approval.request", listener);
1703
+ }
1704
+ req.on("close", () => {
1705
+ for (const agent of reg.agents.values()) {
1706
+ agent.eventBus.off("tool.approval.request", listener);
1707
+ }
1708
+ });
1709
+ });
1609
1710
  }
1610
1711
  if (opts.scheduler) {
1611
1712
  const queue = opts.scheduler;
@@ -1636,6 +1737,38 @@ function createAgentRouter(opts) {
1636
1737
  }
1637
1738
  });
1638
1739
  }
1740
+ if (opts.metricsExporter) {
1741
+ const exporter = opts.metricsExporter;
1742
+ router.get("/metrics", (_req, res) => {
1743
+ res.set("Content-Type", "text/plain; version=0.0.4; charset=utf-8");
1744
+ res.send(exporter.toPrometheus());
1745
+ });
1746
+ router.get("/metrics/json", (req, res) => {
1747
+ const agent = req.query.agent;
1748
+ if (agent) {
1749
+ res.json(exporter.getMetrics(agent));
1750
+ } else {
1751
+ res.json(exporter.toJSON());
1752
+ }
1753
+ });
1754
+ router.get("/metrics/stream", (req, res) => {
1755
+ res.writeHead(200, {
1756
+ "Content-Type": "text/event-stream",
1757
+ "Cache-Control": "no-cache",
1758
+ Connection: "keep-alive"
1759
+ });
1760
+ const handler = (event) => {
1761
+ res.write(`data: ${JSON.stringify(event)}
1762
+
1763
+ `);
1764
+ };
1765
+ const subscribers = exporter.subscribers;
1766
+ subscribers.add(handler);
1767
+ req.on("close", () => {
1768
+ subscribers.delete(handler);
1769
+ });
1770
+ });
1771
+ }
1639
1772
  if (opts.admin) {
1640
1773
  const adminOpts = typeof opts.admin === "object" ? opts.admin : {};
1641
1774
  const { router: adminRouter } = createAdminRouter({
@@ -2000,9 +2133,12 @@ function createVoiceGateway(opts) {
2000
2133
  result: ev.result
2001
2134
  });
2002
2135
  });
2003
- session.on("usage", (ev) => {
2004
- socket.emit("voice.usage", ev);
2005
- });
2136
+ session.on(
2137
+ "usage",
2138
+ (ev) => {
2139
+ socket.emit("voice.usage", ev);
2140
+ }
2141
+ );
2006
2142
  session.on("interrupted", () => {
2007
2143
  socket.emit("voice.interrupted");
2008
2144
  });
package/dist/index.d.cts CHANGED
@@ -206,6 +206,10 @@ interface RouterOptions {
206
206
  * Pass an AgentQueue instance from `@radaros/queue`.
207
207
  */
208
208
  scheduler?: any;
209
+ /**
210
+ * MetricsExporter instance from `@radaros/observability` for `/metrics` endpoints.
211
+ */
212
+ metricsExporter?: any;
209
213
  }
210
214
 
211
215
  declare function createAgentRouter(opts: RouterOptions): any;
package/dist/index.d.ts CHANGED
@@ -206,6 +206,10 @@ interface RouterOptions {
206
206
  * Pass an AgentQueue instance from `@radaros/queue`.
207
207
  */
208
208
  scheduler?: any;
209
+ /**
210
+ * MetricsExporter instance from `@radaros/observability` for `/metrics` endpoints.
211
+ */
212
+ metricsExporter?: any;
209
213
  }
210
214
 
211
215
  declare function createAgentRouter(opts: RouterOptions): any;
package/dist/index.js CHANGED
@@ -808,7 +808,11 @@ var SCHEMAS = {
808
808
  properties: {
809
809
  promptTokens: { type: "number" },
810
810
  completionTokens: { type: "number" },
811
- totalTokens: { type: "number" }
811
+ totalTokens: { type: "number" },
812
+ reasoningTokens: { type: "number", description: "Tokens used for chain-of-thought reasoning" },
813
+ cachedTokens: { type: "number", description: "Prompt tokens served from cache" },
814
+ audioInputTokens: { type: "number", description: "Audio input tokens" },
815
+ audioOutputTokens: { type: "number", description: "Audio output tokens" }
812
816
  }
813
817
  },
814
818
  structured: { description: "Parsed structured output (if schema is configured)" },
@@ -944,7 +948,11 @@ function generateOpenAPISpec(routerOpts, swaggerOpts = {}) {
944
948
  properties: {
945
949
  promptTokens: { type: "number" },
946
950
  completionTokens: { type: "number" },
947
- totalTokens: { type: "number" }
951
+ totalTokens: { type: "number" },
952
+ reasoningTokens: { type: "number", description: "Tokens used for chain-of-thought reasoning" },
953
+ cachedTokens: { type: "number", description: "Prompt tokens served from cache" },
954
+ audioInputTokens: { type: "number", description: "Audio input tokens" },
955
+ audioOutputTokens: { type: "number", description: "Audio output tokens" }
948
956
  }
949
957
  },
950
958
  structured: {
@@ -1563,6 +1571,99 @@ function createAgentRouter(opts) {
1563
1571
  router.get("/registry", (_req, res) => {
1564
1572
  res.json(reg.list());
1565
1573
  });
1574
+ router.get("/agents/:name/card", (req, res) => {
1575
+ const r = reg;
1576
+ if (typeof r.getAgentCard !== "function") return res.status(501).json({ error: "Discovery cards not available" });
1577
+ const card = r.getAgentCard(req.params.name);
1578
+ if (!card) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1579
+ res.json(card);
1580
+ });
1581
+ router.get("/.well-known/agent-cards.json", (_req, res) => {
1582
+ const r = reg;
1583
+ if (typeof r.getAllAgentCards !== "function") return res.json([]);
1584
+ res.json(r.getAllAgentCards());
1585
+ });
1586
+ router.get("/approvals/pending", (_req, res) => {
1587
+ const pending = [];
1588
+ for (const agent of reg.agents.values()) {
1589
+ const mgr = agent.approvalManager;
1590
+ if (mgr && typeof mgr.listPending === "function") {
1591
+ pending.push(...mgr.listPending());
1592
+ }
1593
+ }
1594
+ res.json(pending);
1595
+ });
1596
+ router.post("/approvals/:requestId/approve", (req, res) => {
1597
+ const { requestId } = req.params;
1598
+ const { reason } = req.body ?? {};
1599
+ for (const agent of reg.agents.values()) {
1600
+ const mgr = agent.approvalManager;
1601
+ if (mgr && typeof mgr.approve === "function") {
1602
+ mgr.approve(requestId, reason);
1603
+ }
1604
+ }
1605
+ res.json({ status: "approved", requestId });
1606
+ });
1607
+ router.post("/approvals/:requestId/deny", (req, res) => {
1608
+ const { requestId } = req.params;
1609
+ const { reason } = req.body ?? {};
1610
+ for (const agent of reg.agents.values()) {
1611
+ const mgr = agent.approvalManager;
1612
+ if (mgr && typeof mgr.deny === "function") {
1613
+ mgr.deny(requestId, reason);
1614
+ }
1615
+ }
1616
+ res.json({ status: "denied", requestId });
1617
+ });
1618
+ router.get("/agents/:name/checkpoints", async (req, res) => {
1619
+ const agent = reg.getAgent(req.params.name);
1620
+ if (!agent) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1621
+ const config = agent.config;
1622
+ const checkpointMgr = config?._checkpointManager;
1623
+ if (!checkpointMgr) return res.json([]);
1624
+ const runId = req.query.runId;
1625
+ if (!runId) return res.status(400).json({ error: "runId query param required" });
1626
+ try {
1627
+ const checkpoints = await checkpointMgr.list(runId);
1628
+ res.json(checkpoints);
1629
+ } catch (err) {
1630
+ res.status(500).json({ error: err.message });
1631
+ }
1632
+ });
1633
+ router.post("/agents/:name/rollback/:checkpointId", async (req, res) => {
1634
+ const agent = reg.getAgent(req.params.name);
1635
+ if (!agent) return res.status(404).json({ error: `Agent "${req.params.name}" not found` });
1636
+ const config = agent.config;
1637
+ const checkpointMgr = config?._checkpointManager;
1638
+ if (!checkpointMgr) return res.status(400).json({ error: "Checkpointing not enabled for this agent" });
1639
+ try {
1640
+ const checkpoint = await checkpointMgr.rollback(req.params.checkpointId);
1641
+ if (!checkpoint) return res.status(404).json({ error: "Checkpoint not found" });
1642
+ res.json(checkpoint);
1643
+ } catch (err) {
1644
+ res.status(500).json({ error: err.message });
1645
+ }
1646
+ });
1647
+ router.get("/approvals/stream", (req, res) => {
1648
+ res.writeHead(200, {
1649
+ "Content-Type": "text/event-stream",
1650
+ "Cache-Control": "no-cache",
1651
+ Connection: "keep-alive"
1652
+ });
1653
+ const listener = (data) => {
1654
+ res.write(`data: ${JSON.stringify(data)}
1655
+
1656
+ `);
1657
+ };
1658
+ for (const agent of reg.agents.values()) {
1659
+ agent.eventBus.on("tool.approval.request", listener);
1660
+ }
1661
+ req.on("close", () => {
1662
+ for (const agent of reg.agents.values()) {
1663
+ agent.eventBus.off("tool.approval.request", listener);
1664
+ }
1665
+ });
1666
+ });
1566
1667
  }
1567
1668
  if (opts.scheduler) {
1568
1669
  const queue = opts.scheduler;
@@ -1593,6 +1694,38 @@ function createAgentRouter(opts) {
1593
1694
  }
1594
1695
  });
1595
1696
  }
1697
+ if (opts.metricsExporter) {
1698
+ const exporter = opts.metricsExporter;
1699
+ router.get("/metrics", (_req, res) => {
1700
+ res.set("Content-Type", "text/plain; version=0.0.4; charset=utf-8");
1701
+ res.send(exporter.toPrometheus());
1702
+ });
1703
+ router.get("/metrics/json", (req, res) => {
1704
+ const agent = req.query.agent;
1705
+ if (agent) {
1706
+ res.json(exporter.getMetrics(agent));
1707
+ } else {
1708
+ res.json(exporter.toJSON());
1709
+ }
1710
+ });
1711
+ router.get("/metrics/stream", (req, res) => {
1712
+ res.writeHead(200, {
1713
+ "Content-Type": "text/event-stream",
1714
+ "Cache-Control": "no-cache",
1715
+ Connection: "keep-alive"
1716
+ });
1717
+ const handler = (event) => {
1718
+ res.write(`data: ${JSON.stringify(event)}
1719
+
1720
+ `);
1721
+ };
1722
+ const subscribers = exporter.subscribers;
1723
+ subscribers.add(handler);
1724
+ req.on("close", () => {
1725
+ subscribers.delete(handler);
1726
+ });
1727
+ });
1728
+ }
1596
1729
  if (opts.admin) {
1597
1730
  const adminOpts = typeof opts.admin === "object" ? opts.admin : {};
1598
1731
  const { router: adminRouter } = createAdminRouter({
@@ -1957,9 +2090,12 @@ function createVoiceGateway(opts) {
1957
2090
  result: ev.result
1958
2091
  });
1959
2092
  });
1960
- session.on("usage", (ev) => {
1961
- socket.emit("voice.usage", ev);
1962
- });
2093
+ session.on(
2094
+ "usage",
2095
+ (ev) => {
2096
+ socket.emit("voice.usage", ev);
2097
+ }
2098
+ );
1963
2099
  session.on("interrupted", () => {
1964
2100
  socket.emit("voice.interrupted");
1965
2101
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radaros/transport",
3
- "version": "0.3.32",
3
+ "version": "0.3.35",
4
4
  "description": "HTTP and WebSocket transport layer for RadarOS agents",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,7 +42,7 @@
42
42
  "typescript": "^5.6.0"
43
43
  },
44
44
  "peerDependencies": {
45
- "@radaros/core": "^0.3.32",
45
+ "@radaros/core": "^0.3.35",
46
46
  "@types/express": "^4.0.0 || ^5.0.0",
47
47
  "express": "^4.0.0 || ^5.0.0",
48
48
  "multer": ">=2.0.0",