@radaros/transport 0.3.12 → 0.3.13

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 ADDED
@@ -0,0 +1,45 @@
1
+ # @radaros/transport
2
+
3
+ HTTP and WebSocket transport layer for deploying RadarOS agents as APIs.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @radaros/transport
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import express from "express";
15
+ import { Agent, openai } from "@radaros/core";
16
+ import { createAgentRouter } from "@radaros/transport";
17
+
18
+ const app = express();
19
+ app.use(express.json());
20
+
21
+ const agent = new Agent({
22
+ name: "assistant",
23
+ model: openai("gpt-4o"),
24
+ });
25
+
26
+ app.use("/api", createAgentRouter({ agents: { assistant: agent } }));
27
+ app.listen(3000);
28
+ ```
29
+
30
+ ## Features
31
+
32
+ - **Express Router** — REST API with streaming support
33
+ - **Socket.IO Gateway** — Real-time WebSocket communication
34
+ - **A2A Server** — Agent-to-Agent protocol support
35
+ - **CORS & Rate Limiting** — Built-in security middleware
36
+ - **Swagger** — Auto-generated API documentation
37
+ - **File Upload** — Multipart form data support
38
+
39
+ ## Documentation
40
+
41
+ Full docs at [radaros.mintlify.dev](https://radaros.mintlify.dev)
42
+
43
+ ## License
44
+
45
+ MIT
package/dist/index.d.ts CHANGED
@@ -42,8 +42,12 @@ interface FileUploadOptions {
42
42
  declare function createFileUploadMiddleware(opts?: FileUploadOptions): any;
43
43
  declare function buildMultiModalInput(body: any, files?: any[]): string | any[];
44
44
 
45
- declare function errorHandler(): (err: any, _req: any, res: any, _next: any) => void;
46
- declare function requestLogger(): (req: any, _res: any, next: any) => void;
45
+ declare function errorHandler(options?: {
46
+ logger?: Pick<Console, "error">;
47
+ }): (err: any, _req: any, res: any, _next: any) => void;
48
+ declare function requestLogger(options?: {
49
+ logger?: Pick<Console, "log">;
50
+ }): (req: any, _res: any, next: any) => void;
47
51
 
48
52
  interface SwaggerOptions {
49
53
  /** Enable Swagger UI at /docs. Default: false */
@@ -75,6 +79,13 @@ interface RouterOptions {
75
79
  swagger?: SwaggerOptions;
76
80
  /** File upload configuration for multi-modal inputs */
77
81
  fileUpload?: boolean | FileUploadOptions;
82
+ /** CORS configuration. Pass true or '*' for permissive, a string for a single origin, or an array for multiple origins. */
83
+ cors?: string | string[] | boolean;
84
+ /** Rate limiting configuration. Pass true for defaults (100 req/min), or an object to customize. */
85
+ rateLimit?: {
86
+ windowMs?: number;
87
+ max?: number;
88
+ } | boolean;
78
89
  }
79
90
 
80
91
  declare function createAgentRouter(opts: RouterOptions): any;
@@ -169,6 +180,8 @@ interface GatewayOptions {
169
180
  io: any;
170
181
  namespace?: string;
171
182
  authMiddleware?: (socket: any, next: (err?: Error) => void) => void;
183
+ /** Max requests per minute per socket. Default: 60 */
184
+ maxRequestsPerMinute?: number;
172
185
  }
173
186
 
174
187
  declare function createAgentGateway(opts: GatewayOptions): void;
package/dist/index.js CHANGED
@@ -412,17 +412,19 @@ function buildMultiModalInput(body, files) {
412
412
  }
413
413
 
414
414
  // src/express/middleware.ts
415
- function errorHandler() {
415
+ function errorHandler(options) {
416
+ const log = options?.logger ?? console;
416
417
  return (err, _req, res, _next) => {
417
- console.error("[radaros:transport] Error:", err.message);
418
+ log.error("[radaros:transport] Error:", err.message);
418
419
  res.status(err.statusCode ?? 500).json({
419
420
  error: err.message ?? "Internal server error"
420
421
  });
421
422
  };
422
423
  }
423
- function requestLogger() {
424
+ function requestLogger(options) {
425
+ const log = options?.logger ?? console;
424
426
  return (req, _res, next) => {
425
- console.log(`[radaros:transport] ${req.method} ${req.path}`);
427
+ log.log(`[radaros:transport] ${req.method} ${req.path}`);
426
428
  next();
427
429
  };
428
430
  }
@@ -873,6 +875,53 @@ function serveSwaggerUI(spec) {
873
875
 
874
876
  // src/express/router-factory.ts
875
877
  var _require4 = createRequire4(import.meta.url);
878
+ function corsMiddleware(origins) {
879
+ return (req, res, next) => {
880
+ const origin = req.headers.origin;
881
+ let allowed = false;
882
+ if (origins === true || origins === "*") {
883
+ allowed = true;
884
+ res.setHeader("Access-Control-Allow-Origin", "*");
885
+ } else if (typeof origins === "string") {
886
+ allowed = origin === origins;
887
+ if (allowed) res.setHeader("Access-Control-Allow-Origin", origin);
888
+ } else if (Array.isArray(origins)) {
889
+ allowed = origins.includes(origin);
890
+ if (allowed) res.setHeader("Access-Control-Allow-Origin", origin);
891
+ }
892
+ if (allowed) {
893
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
894
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-API-Key");
895
+ res.setHeader("Access-Control-Max-Age", "86400");
896
+ }
897
+ if (req.method === "OPTIONS") {
898
+ res.status(204).end();
899
+ return;
900
+ }
901
+ next();
902
+ };
903
+ }
904
+ function rateLimitMiddleware(config = {}) {
905
+ const windowMs = config.windowMs ?? 6e4;
906
+ const max = config.max ?? 100;
907
+ const hits = /* @__PURE__ */ new Map();
908
+ return (req, res, next) => {
909
+ const key = req.ip ?? req.socket?.remoteAddress ?? "unknown";
910
+ const now = Date.now();
911
+ const record = hits.get(key);
912
+ if (!record || now > record.resetTime) {
913
+ hits.set(key, { count: 1, resetTime: now + windowMs });
914
+ next();
915
+ return;
916
+ }
917
+ record.count++;
918
+ if (record.count > max) {
919
+ res.status(429).json({ error: "Too many requests, please try again later" });
920
+ return;
921
+ }
922
+ next();
923
+ };
924
+ }
876
925
  var API_KEY_HEADERS = {
877
926
  "x-openai-api-key": "openai",
878
927
  "x-google-api-key": "google",
@@ -913,6 +962,13 @@ function createAgentRouter(opts) {
913
962
  throw new Error("express is required for createAgentRouter. Install it: npm install express");
914
963
  }
915
964
  const router = express.Router();
965
+ if (opts.cors) {
966
+ router.use(corsMiddleware(opts.cors));
967
+ }
968
+ if (opts.rateLimit) {
969
+ const config = opts.rateLimit === true ? {} : opts.rateLimit;
970
+ router.use(rateLimitMiddleware(config));
971
+ }
916
972
  if (opts.middleware) {
917
973
  for (const mw of opts.middleware) {
918
974
  router.use(mw);
@@ -1205,13 +1261,34 @@ function createBrowserGateway(opts) {
1205
1261
  }
1206
1262
 
1207
1263
  // src/socketio/gateway.ts
1264
+ function createSocketRateLimiter(maxPerMinute = 60) {
1265
+ return () => {
1266
+ let count = 0;
1267
+ let resetTime = Date.now() + 6e4;
1268
+ return () => {
1269
+ const now = Date.now();
1270
+ if (now > resetTime) {
1271
+ count = 0;
1272
+ resetTime = now + 6e4;
1273
+ }
1274
+ count++;
1275
+ return count <= maxPerMinute;
1276
+ };
1277
+ };
1278
+ }
1208
1279
  function createAgentGateway(opts) {
1209
1280
  const ns = opts.io.of(opts.namespace ?? "/radaros");
1210
1281
  if (opts.authMiddleware) {
1211
1282
  ns.use(opts.authMiddleware);
1212
1283
  }
1284
+ const rateLimiterFactory = createSocketRateLimiter(opts.maxRequestsPerMinute ?? 60);
1213
1285
  ns.on("connection", (socket) => {
1286
+ const checkRate = rateLimiterFactory();
1214
1287
  socket.on("agent.run", async (data) => {
1288
+ if (!checkRate()) {
1289
+ socket.emit("agent.error", { error: "Rate limit exceeded" });
1290
+ return;
1291
+ }
1215
1292
  if (!data || typeof data.input !== "string" || !data.input.trim()) {
1216
1293
  socket.emit("agent.error", { error: "Invalid input: must be a non-empty string" });
1217
1294
  return;
@@ -1380,7 +1457,11 @@ function createVoiceGateway(opts) {
1380
1457
  if (session) {
1381
1458
  try {
1382
1459
  await session.close();
1383
- } catch {
1460
+ } catch (err) {
1461
+ console.warn(
1462
+ "[radaros/voice-gateway] Error closing session on disconnect:",
1463
+ err instanceof Error ? err.message : err
1464
+ );
1384
1465
  }
1385
1466
  activeSessions.delete(socket.id);
1386
1467
  }
package/package.json CHANGED
@@ -1,6 +1,21 @@
1
1
  {
2
2
  "name": "@radaros/transport",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
+ "description": "HTTP and WebSocket transport layer for RadarOS agents",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/xhipment/agentOs.git",
9
+ "directory": "packages/transport"
10
+ },
11
+ "keywords": [
12
+ "ai",
13
+ "agents",
14
+ "express",
15
+ "socketio",
16
+ "api",
17
+ "transport"
18
+ ],
4
19
  "type": "module",
5
20
  "main": "./dist/index.js",
6
21
  "types": "./dist/index.d.ts",
@@ -24,7 +39,7 @@
24
39
  "typescript": "^5.6.0"
25
40
  },
26
41
  "peerDependencies": {
27
- "@radaros/core": "^0.3.12",
42
+ "@radaros/core": "^0.3.13",
28
43
  "@types/express": "^4.0.0 || ^5.0.0",
29
44
  "express": "^4.0.0 || ^5.0.0",
30
45
  "multer": ">=2.0.0",