@cogitator-ai/express 0.2.15 → 0.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.
Files changed (41) hide show
  1. package/README.md +68 -22
  2. package/dist/middleware/cors.d.ts.map +1 -1
  3. package/dist/middleware/cors.js +17 -18
  4. package/dist/middleware/cors.js.map +1 -1
  5. package/dist/middleware/error-handler.d.ts.map +1 -1
  6. package/dist/middleware/error-handler.js +34 -0
  7. package/dist/middleware/error-handler.js.map +1 -1
  8. package/dist/middleware/rate-limit.d.ts.map +1 -1
  9. package/dist/middleware/rate-limit.js +14 -4
  10. package/dist/middleware/rate-limit.js.map +1 -1
  11. package/dist/routes/agents.d.ts.map +1 -1
  12. package/dist/routes/agents.js +59 -43
  13. package/dist/routes/agents.js.map +1 -1
  14. package/dist/routes/swarms.d.ts.map +1 -1
  15. package/dist/routes/swarms.js +53 -48
  16. package/dist/routes/swarms.js.map +1 -1
  17. package/dist/routes/threads.d.ts.map +1 -1
  18. package/dist/routes/threads.js +27 -45
  19. package/dist/routes/threads.js.map +1 -1
  20. package/dist/routes/utils.d.ts +36 -0
  21. package/dist/routes/utils.d.ts.map +1 -0
  22. package/dist/routes/utils.js +95 -0
  23. package/dist/routes/utils.js.map +1 -0
  24. package/dist/routes/workflows.d.ts.map +1 -1
  25. package/dist/routes/workflows.js +49 -38
  26. package/dist/routes/workflows.js.map +1 -1
  27. package/dist/server.d.ts +8 -0
  28. package/dist/server.d.ts.map +1 -1
  29. package/dist/server.js +27 -14
  30. package/dist/server.js.map +1 -1
  31. package/dist/streaming/express-stream-writer.d.ts +1 -0
  32. package/dist/streaming/express-stream-writer.d.ts.map +1 -1
  33. package/dist/streaming/express-stream-writer.js +14 -1
  34. package/dist/streaming/express-stream-writer.js.map +1 -1
  35. package/dist/types.d.ts +1 -1
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/websocket/ws-handler.d.ts +7 -0
  38. package/dist/websocket/ws-handler.d.ts.map +1 -1
  39. package/dist/websocket/ws-handler.js +238 -124
  40. package/dist/websocket/ws-handler.js.map +1 -1
  41. package/package.json +21 -18
package/README.md CHANGED
@@ -20,14 +20,17 @@ import { CogitatorServer } from '@cogitator-ai/express';
20
20
  const app = express();
21
21
 
22
22
  const cogitator = new Cogitator({
23
- defaultBackend: 'openai',
24
- backends: { openai: { apiKey: process.env.OPENAI_API_KEY } },
23
+ llm: {
24
+ defaultModel: 'openai/gpt-6-luna',
25
+ providers: { openai: { apiKey: process.env.OPENAI_API_KEY } },
26
+ },
25
27
  });
26
28
 
27
29
  const chatAgent = new Agent({
28
30
  name: 'chat',
31
+ description: 'General-purpose chat assistant',
29
32
  instructions: 'You are a helpful assistant.',
30
- model: 'gpt-4o-mini',
33
+ model: 'openai/gpt-6-luna',
31
34
  });
32
35
 
33
36
  const server = new CogitatorServer({
@@ -54,6 +57,8 @@ POST /api/agents/:name/run - Run agent (JSON response)
54
57
  POST /api/agents/:name/stream - Run agent (SSE stream)
55
58
  ```
56
59
 
60
+ Run/stream body: `{ input: string; context?: object; threadId?: string }` — `input` must be a non-empty string (400 otherwise). The agent list exposes `config.description`, never the agent instructions. The authenticated `userId` (from `auth`) is passed to the run, and the run is aborted when the client disconnects.
61
+
57
62
  ### Threads (Memory)
58
63
 
59
64
  ```
@@ -62,6 +67,8 @@ POST /api/threads/:id/messages - Add message to thread
62
67
  DELETE /api/threads/:id - Delete thread
63
68
  ```
64
69
 
70
+ Requires `memory` on the `Cogitator` instance (503 otherwise). New messages need `role` (`user` | `assistant` | `system`) and a non-empty string `content`; optional `metadata` is stored on the memory entry.
71
+
65
72
  ### Workflows
66
73
 
67
74
  ```
@@ -70,15 +77,19 @@ POST /api/workflows/:name/run - Run workflow
70
77
  POST /api/workflows/:name/stream - Stream workflow events
71
78
  ```
72
79
 
80
+ Body: `{ input?: object; options?: { maxConcurrency?: number; maxIterations?: number; checkpoint?: boolean } }`. `maxConcurrency`/`maxIterations` must be positive integers and `checkpoint` a boolean (400 otherwise); other options are dropped. A failed workflow returns `500` with code `WORKFLOW_FAILED` (the stream ends with an `error` event instead of `workflow_completed`). Disconnecting aborts the workflow.
81
+
73
82
  ### Swarms
74
83
 
75
84
  ```
76
85
  GET /api/swarms - List all swarms
77
86
  POST /api/swarms/:name/run - Run swarm
78
87
  POST /api/swarms/:name/stream - Stream swarm events
79
- GET /api/swarms/:name/blackboard - Get shared state
88
+ GET /api/swarms/:name/blackboard - Get configured blackboard sections
80
89
  ```
81
90
 
91
+ Run/stream body: `{ input: string; context?: object; threadId?: string; timeout?: number }` (`timeout` must be positive). Disconnecting aborts the swarm. Each run creates a fresh swarm, so the blackboard endpoint returns the configured initial sections.
92
+
82
93
  ### Tools & Docs
83
94
 
84
95
  ```
@@ -102,20 +113,27 @@ const server = new CogitatorServer({
102
113
  enableWebSocket: true,
103
114
  enableSwagger: true,
104
115
 
105
- // Authentication
116
+ // Authentication — throw to reject (401); the returned context is available
117
+ // as req.cogitator.auth and its userId is passed to agent runs.
118
+ // Also applied to WebSocket upgrade requests.
106
119
  auth: async (req) => {
107
120
  const token = req.headers.authorization?.replace('Bearer ', '');
108
121
  const user = await validateToken(token);
109
122
  return { userId: user.id, roles: user.roles };
110
123
  },
111
124
 
112
- // Rate limiting
125
+ // Rate limiting (in-memory, per process). windowMs must be positive and max
126
+ // non-negative, otherwise the constructor throws. Requests without a client
127
+ // address share a single bucket.
113
128
  rateLimit: {
114
129
  windowMs: 60000, // 1 minute
115
130
  max: 100, // 100 requests per window
131
+ trustProxy: false, // true: key by the nearest X-Forwarded-For hop
116
132
  },
117
133
 
118
- // CORS
134
+ // CORS — credentials default to true for explicit origins and to false for '*'.
135
+ // `origin: '*'` with `credentials: true` reflects any origin with credentials;
136
+ // only do that for trusted, non-cookie setups.
119
137
  cors: {
120
138
  origin: ['https://myapp.com'],
121
139
  credentials: true,
@@ -163,23 +181,40 @@ while (true) {
163
181
 
164
182
  ## WebSocket Support
165
183
 
166
- Enable real-time bidirectional communication:
184
+ Enable real-time bidirectional communication (requires the optional `ws` package):
167
185
 
168
186
  ```typescript
187
+ import { createServer } from 'http';
188
+
169
189
  const server = new CogitatorServer({
170
190
  // ...
171
- config: { enableWebSocket: true },
191
+ config: {
192
+ enableWebSocket: true,
193
+ websocket: { path: '/api/ws', pingInterval: 30000, maxPayloadSize: 1024 * 1024 },
194
+ },
172
195
  });
173
196
 
174
- // After init, setup WebSocket on HTTP server
175
- import { setupWebSocket } from '@cogitator-ai/express';
176
- import { createServer } from 'http';
197
+ await server.init();
177
198
 
178
199
  const httpServer = createServer(app);
179
- await setupWebSocket(httpServer, routeContext, { path: '/api/ws' });
200
+ await server.attachWebSocket(httpServer); // defaults to `${basePath}/ws`
180
201
  httpServer.listen(3000);
181
202
  ```
182
203
 
204
+ `attachWebSocket` throws if `enableWebSocket` is off, `init()` has not run, or `ws` is not installed. The configured `auth` function runs on the upgrade request (rejected with 401 when it throws). For custom setups, `setupWebSocket(httpServer, routeContext, config)` is also exported.
205
+
206
+ Protocol:
207
+
208
+ | Message | Direction | Description |
209
+ | ----------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
210
+ | `{ type: 'run', id, payload: { type: 'agent', name, input, context?, threadId? } }` | Client→Server | Run an agent; events arrive as `{ type: 'event', id, payload }` (`token`, `tool-call`, `tool-result`, `complete`, `cancelled`) |
211
+ | `{ type: 'stop' }` | Client→Server | Abort the client's running agent (emits `cancelled`) |
212
+ | `{ type: 'subscribe', channel: 'agent:<name>' }` | Client→Server | Receive events of runs of that agent started by other clients |
213
+ | `{ type: 'unsubscribe', channel }` | Client→Server | Stop receiving channel events |
214
+ | `{ type: 'ping' }` | Client→Server | Answered with `{ type: 'pong' }` |
215
+
216
+ Only agent runs are supported over WebSocket; use the HTTP endpoints for workflows and swarms. A new `run` from the same connection aborts the previous one.
217
+
183
218
  Client usage:
184
219
 
185
220
  ```typescript
@@ -249,15 +284,19 @@ router.post('/custom/stream', async (req, res) => {
249
284
  setupSSEHeaders(res);
250
285
  const writer = new ExpressStreamWriter(res);
251
286
  const messageId = generateId('msg');
287
+ const textId = generateId('txt');
288
+
289
+ // Use res.on('close') (not req.on('close'), which fires once the body is read)
290
+ res.on('close', () => writer.close());
252
291
 
253
292
  writer.start(messageId);
254
- writer.textStart(generateId('txt'));
293
+ writer.textStart(textId);
255
294
 
256
295
  // Your streaming logic
257
- writer.textDelta('txt-1', 'Hello ');
258
- writer.textDelta('txt-1', 'World!');
296
+ writer.textDelta(textId, 'Hello ');
297
+ writer.textDelta(textId, 'World!');
259
298
 
260
- writer.textEnd('txt-1');
299
+ writer.textEnd(textId);
261
300
  writer.finish(messageId);
262
301
  writer.close();
263
302
  });
@@ -271,6 +310,7 @@ router.post('/custom/stream', async (req, res) => {
271
310
  class CogitatorServer {
272
311
  constructor(options: CogitatorServerConfig);
273
312
  init(): Promise<void>;
313
+ attachWebSocket(server: http.Server): Promise<WebSocketServer>;
274
314
  readonly isInitialized: boolean;
275
315
  }
276
316
  ```
@@ -293,7 +333,6 @@ interface CogitatorServerConfig {
293
333
  cors?: CorsConfig;
294
334
  swagger?: SwaggerConfig;
295
335
  websocket?: WebSocketConfig;
296
- requestTimeout?: number; // Default: 30000
297
336
  };
298
337
  }
299
338
  ```
@@ -316,9 +355,12 @@ class ExpressStreamWriter {
316
355
  error(message: string, code?: string): void;
317
356
  finish(messageId: string, usage?: Usage): void;
318
357
  close(): void;
358
+ readonly isClosed: boolean;
319
359
  }
320
360
  ```
321
361
 
362
+ Writes after the response has ended (or the client disconnected) are ignored.
363
+
322
364
  ## Error Handling
323
365
 
324
366
  All endpoints return consistent error responses:
@@ -334,13 +376,17 @@ All endpoints return consistent error responses:
334
376
 
335
377
  Error codes map to HTTP status codes:
336
378
 
337
- - `INVALID_INPUT` → 400
379
+ - `INVALID_INPUT` → 400 (validation errors and malformed JSON bodies)
338
380
  - `UNAUTHORIZED` → 401
339
- - `PERMISSION_DENIED` → 403
340
381
  - `NOT_FOUND` → 404
382
+ - `PAYLOAD_TOO_LARGE` → 413
341
383
  - `RATE_LIMIT_EXCEEDED` → 429
342
- - `INTERNAL` → 500
343
- - `UNAVAILABLE` → 503
384
+ - `WORKFLOW_FAILED` → 500
385
+ - `INTERNAL` → 500 (details are logged, not returned)
386
+ - `UNIMPLEMENTED` → 501 (optional workflows/swarms package missing)
387
+ - `UNAVAILABLE` → 503 (memory not configured)
388
+
389
+ `CogitatorError`s thrown by runs keep their own code and use its mapped status (for example `LLM_RATE_LIMITED` → 429).
344
390
 
345
391
  ## License
346
392
 
@@ -1 +1 @@
1
- {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAoB9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,IAU7C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAiCxD"}
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAkB9C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,IAU7C,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAmCxD"}
@@ -1,6 +1,4 @@
1
1
  function isOriginAllowed(origin, allowed) {
2
- if (!origin)
3
- return false;
4
2
  if (typeof allowed === 'string') {
5
3
  return allowed === '*' || allowed === origin;
6
4
  }
@@ -13,32 +11,33 @@ function isOriginAllowed(origin, allowed) {
13
11
  return false;
14
12
  }
15
13
  export function createCorsMiddleware(config) {
16
- const { origin, credentials = true, methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allowedHeaders = ['Content-Type', 'Authorization', 'X-Request-ID'], exposedHeaders = ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'], maxAge = 86400, } = config;
14
+ const { origin, credentials = origin !== '*', methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], allowedHeaders = ['Content-Type', 'Authorization', 'X-Request-ID'], exposedHeaders = ['X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-RateLimit-Reset'], maxAge = 86400, } = config;
17
15
  return (req, res, next) => {
18
16
  const requestOrigin = req.headers.origin;
19
- if (origin === '*') {
20
- if (credentials && requestOrigin) {
21
- res.setHeader('Access-Control-Allow-Origin', requestOrigin);
22
- res.setHeader('Vary', 'Origin');
23
- }
24
- else {
25
- res.setHeader('Access-Control-Allow-Origin', '*');
26
- }
17
+ let allowed = false;
18
+ if (origin === '*' && !credentials) {
19
+ res.setHeader('Access-Control-Allow-Origin', '*');
20
+ allowed = true;
27
21
  }
28
- else if (isOriginAllowed(requestOrigin, origin)) {
29
- res.setHeader('Access-Control-Allow-Origin', requestOrigin);
22
+ else {
30
23
  res.setHeader('Vary', 'Origin');
24
+ if (requestOrigin && (origin === '*' || isOriginAllowed(requestOrigin, origin))) {
25
+ res.setHeader('Access-Control-Allow-Origin', requestOrigin);
26
+ allowed = true;
27
+ }
31
28
  }
32
- if (credentials) {
29
+ if (allowed && credentials) {
33
30
  res.setHeader('Access-Control-Allow-Credentials', 'true');
34
31
  }
35
- if (exposedHeaders.length > 0) {
32
+ if (allowed && exposedHeaders.length > 0) {
36
33
  res.setHeader('Access-Control-Expose-Headers', exposedHeaders.join(', '));
37
34
  }
38
35
  if (req.method === 'OPTIONS') {
39
- res.setHeader('Access-Control-Allow-Methods', methods.join(', '));
40
- res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));
41
- res.setHeader('Access-Control-Max-Age', maxAge.toString());
36
+ if (allowed) {
37
+ res.setHeader('Access-Control-Allow-Methods', methods.join(', '));
38
+ res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));
39
+ res.setHeader('Access-Control-Max-Age', maxAge.toString());
40
+ }
42
41
  res.status(204).end();
43
42
  return;
44
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAGA,SAAS,eAAe,CAAC,MAA0B,EAAE,OAA6B;IAChF,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAE1B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,MAAM,CAAC;IAC/C,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,MAAM,EACJ,MAAM,EACN,WAAW,GAAG,IAAI,EAClB,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAC9D,cAAc,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,cAAc,CAAC,EAClE,cAAc,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,mBAAmB,CAAC,EACpF,MAAM,GAAG,KAAK,GACf,GAAG,MAAM,CAAC;IAEX,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QAEzC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,IAAI,WAAW,IAAI,aAAa,EAAE,CAAC;gBACjC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;gBAC5D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;aAAM,IAAI,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,aAAc,CAAC,CAAC;YAC7D,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YAChB,GAAG,CAAC,SAAS,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,SAAS,CAAC,+BAA+B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAClE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACzE,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAGA,SAAS,eAAe,CAAC,MAAc,EAAE,OAA6B;IACpE,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,MAAM,CAAC;IAC/C,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,MAAM,EACJ,MAAM,EACN,WAAW,GAAG,MAAM,KAAK,GAAG,EAC5B,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAC9D,cAAc,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,cAAc,CAAC,EAClE,cAAc,GAAG,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,mBAAmB,CAAC,EACpF,MAAM,GAAG,KAAK,GACf,GAAG,MAAM,CAAC;IAEX,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,MAAM,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACnC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;YAClD,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAChC,IAAI,aAAa,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAChF,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;gBAC5D,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;QACH,CAAC;QAED,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;YAC3B,GAAG,CAAC,SAAS,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,OAAO,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,SAAS,CAAC,+BAA+B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAClE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzE,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG/D,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAwBhG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAOlE"}
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgC/D,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAqChG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAOlE"}
@@ -1,4 +1,27 @@
1
1
  import { CogitatorError, ERROR_STATUS_CODES, ErrorCode } from '@cogitator-ai/types';
2
+ const CLIENT_ERROR_CODES = {
3
+ 400: 'INVALID_INPUT',
4
+ 401: 'UNAUTHORIZED',
5
+ 403: 'FORBIDDEN',
6
+ 404: 'NOT_FOUND',
7
+ 413: 'PAYLOAD_TOO_LARGE',
8
+ 415: 'UNSUPPORTED_MEDIA_TYPE',
9
+ 429: 'RATE_LIMIT_EXCEEDED',
10
+ };
11
+ function asClientError(err) {
12
+ if (typeof err !== 'object' || err === null)
13
+ return null;
14
+ const rawStatus = Reflect.get(err, 'status') ?? Reflect.get(err, 'statusCode');
15
+ if (typeof rawStatus !== 'number' || rawStatus < 400 || rawStatus >= 500)
16
+ return null;
17
+ const message = Reflect.get(err, 'message');
18
+ const type = Reflect.get(err, 'type');
19
+ return {
20
+ status: rawStatus,
21
+ message: typeof message === 'string' ? message : 'Bad request',
22
+ type: typeof type === 'string' ? type : undefined,
23
+ };
24
+ }
2
25
  export function errorHandler(err, _req, res, _next) {
3
26
  if (res.headersSent) {
4
27
  return;
@@ -13,6 +36,17 @@ export function errorHandler(err, _req, res, _next) {
13
36
  });
14
37
  return;
15
38
  }
39
+ const clientError = asClientError(err);
40
+ if (clientError) {
41
+ const message = clientError.type === 'entity.parse.failed' ? 'Invalid JSON body' : clientError.message;
42
+ res.status(clientError.status).json({
43
+ error: {
44
+ message,
45
+ code: CLIENT_ERROR_CODES[clientError.status] ?? 'BAD_REQUEST',
46
+ },
47
+ });
48
+ return;
49
+ }
16
50
  console.error('[CogitatorServer] Unhandled error:', err);
17
51
  res.status(500).json({
18
52
  error: {
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEpF,MAAM,UAAU,YAAY,CAAC,GAAU,EAAE,IAAa,EAAE,GAAa,EAAE,KAAmB;IACxF,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IAED,IAAI,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QACvD,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC1B,KAAK,EAAE;gBACL,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;IAEzD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE;YACL,OAAO,EAAE,uBAAuB;YAChC,IAAI,EAAE,SAAS,CAAC,cAAc;SAC/B;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,GAAa;IAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE;YACL,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,WAAW;SAClB;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAQpF,MAAM,kBAAkB,GAA2B;IACjD,GAAG,EAAE,eAAe;IACpB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,wBAAwB;IAC7B,GAAG,EAAE,qBAAqB;CAC3B,CAAC;AAEF,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,SAAS,GAAY,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACxF,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,GAAG,GAAG,IAAI,SAAS,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACtF,MAAM,OAAO,GAAY,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,IAAI,GAAY,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC/C,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa;QAC9D,IAAI,EAAE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;KAClD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAU,EAAE,IAAa,EAAE,GAAa,EAAE,KAAmB;IACxF,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IAED,IAAI,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QACvD,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;YAC1B,KAAK,EAAE;gBACL,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;aACf;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,OAAO,GACX,WAAW,CAAC,IAAI,KAAK,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC;QACzF,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAClC,KAAK,EAAE;gBACL,OAAO;gBACP,IAAI,EAAE,kBAAkB,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,aAAa;aAC9D;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;IAEzD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE;YACL,OAAO,EAAE,uBAAuB;YAChC,IAAI,EAAE,SAAS,CAAC,cAAc;SAC/B;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,GAAa;IAC1D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;QACnB,KAAK,EAAE;YACL,OAAO,EAAE,WAAW;YACpB,IAAI,EAAE,WAAW;SAClB;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAW,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmBrE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,IAqBvD,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAoCjE"}
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAW,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAsBrE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,IA4BvD,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAoCjE"}
@@ -2,15 +2,25 @@ function buildKeyGenerator(trustProxy) {
2
2
  return (req) => {
3
3
  if (trustProxy) {
4
4
  const forwarded = req.headers['x-forwarded-for'];
5
- if (typeof forwarded === 'string') {
6
- return forwarded.split(',')[0].trim();
7
- }
5
+ const hops = (Array.isArray(forwarded) ? forwarded.join(',') : (forwarded ?? ''))
6
+ .split(',')
7
+ .map((hop) => hop.trim())
8
+ .filter(Boolean);
9
+ const nearest = hops.at(-1);
10
+ if (nearest)
11
+ return nearest;
8
12
  }
9
- return req.ip || req.socket.remoteAddress || `unknown-${Math.random()}`;
13
+ return req.ip || req.socket.remoteAddress || 'unknown';
10
14
  };
11
15
  }
12
16
  export function createRateLimitMiddleware(config) {
13
17
  const { windowMs, max, message = 'Too many requests, please try again later', keyGenerator = buildKeyGenerator(config.trustProxy ?? false), skip, } = config;
18
+ if (!Number.isFinite(windowMs) || windowMs <= 0) {
19
+ throw new Error('RateLimitConfig.windowMs must be a positive number');
20
+ }
21
+ if (!Number.isFinite(max) || max < 0) {
22
+ throw new Error('RateLimitConfig.max must be a non-negative number');
23
+ }
14
24
  const store = new Map();
15
25
  const cleanup = setInterval(() => {
16
26
  const now = Date.now();
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAQA,SAAS,iBAAiB,CAAC,UAAmB;IAC5C,OAAO,CAAC,GAAY,EAAU,EAAE;QAC9B,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;iBAC9E,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;iBACxB,MAAM,CAAC,OAAO,CAAC,CAAC;YACnB,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;QAC9B,CAAC;QACD,OAAO,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,SAAS,CAAC;IACzD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAuB;IAC/D,MAAM,EACJ,QAAQ,EACR,GAAG,EACH,OAAO,GAAG,2CAA2C,EACrD,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,UAAU,IAAI,KAAK,CAAC,EAC5D,IAAI,GACL,GAAG,MAAM,CAAC;IAEX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEhD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;gBAC3B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC,EAAE,KAAK,CAAC,CAAC;IACV,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,OAAO,CAAC,GAAqB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAClE,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;YAChB,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YACrC,KAAK,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,GAAG,QAAQ,EAAE,CAAC;YAChD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;QAED,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QAE/D,GAAG,CAAC,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnD,GAAG,CAAC,SAAS,CAAC,uBAAuB,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC7D,GAAG,CAAC,SAAS,CAAC,mBAAmB,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE5D,IAAI,KAAK,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC;YACtB,GAAG,CAAC,SAAS,CAAC,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC;YACtD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE;oBACL,OAAO;oBACP,IAAI,EAAE,qBAAqB;iBAC5B;aACF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EAKb,MAAM,aAAa,CAAC;AAIrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAoI3D"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,aAAa,CAAC;AAUrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CA6J3D"}
@@ -1,12 +1,13 @@
1
1
  import { Router } from 'express';
2
2
  import { ExpressStreamWriter, setupSSEHeaders, generateId } from '../streaming/index.js';
3
- import { CogitatorError } from '@cogitator-ai/types';
3
+ import { handleRouteError, onClientDisconnect, parseRunBody, resolveError, sendError, } from './utils.js';
4
4
  export function createAgentRoutes(ctx) {
5
5
  const router = Router();
6
+ const findAgent = (name) => Object.hasOwn(ctx.agents, name) ? ctx.agents[name] : undefined;
6
7
  router.get('/agents', (_req, res) => {
7
8
  const agentList = Object.entries(ctx.agents).map(([name, agent]) => ({
8
9
  name,
9
- description: agent.config.instructions?.slice(0, 100),
10
+ description: agent.config.description,
10
11
  tools: agent.config.tools?.map((t) => t.name) || [],
11
12
  }));
12
13
  const response = { agents: agentList };
@@ -14,25 +15,26 @@ export function createAgentRoutes(ctx) {
14
15
  });
15
16
  router.post('/agents/:name/run', async (req, res) => {
16
17
  const { name } = req.params;
17
- const agent = Object.hasOwn(ctx.agents, name) ? ctx.agents[name] : undefined;
18
+ const agent = findAgent(name);
18
19
  if (!agent) {
19
- res.status(404).json({
20
- error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' },
21
- });
20
+ sendError(res, 404, `Agent '${name}' not found`, 'NOT_FOUND');
22
21
  return;
23
22
  }
24
- const body = req.body;
25
- if (!body?.input) {
26
- res.status(400).json({
27
- error: { message: 'Missing required field: input', code: 'INVALID_INPUT' },
28
- });
23
+ const parsed = parseRunBody(req.body);
24
+ if (!parsed.ok) {
25
+ sendError(res, 400, parsed.message, 'INVALID_INPUT');
29
26
  return;
30
27
  }
28
+ const body = parsed.value;
29
+ const abortController = new AbortController();
30
+ onClientDisconnect(res, () => abortController.abort());
31
31
  try {
32
32
  const result = await ctx.cogitator.run(agent, {
33
33
  input: body.input,
34
34
  context: body.context,
35
35
  threadId: body.threadId,
36
+ userId: req.cogitator?.auth?.userId,
37
+ signal: abortController.signal,
36
38
  });
37
39
  const response = {
38
40
  output: result.output,
@@ -47,60 +49,76 @@ export function createAgentRoutes(ctx) {
47
49
  res.json(response);
48
50
  }
49
51
  catch (error) {
50
- if (CogitatorError.isCogitatorError(error)) {
51
- res.status(500).json({ error: { message: error.message, code: error.code } });
52
- }
53
- else {
54
- console.error('[CogitatorServer] Agent run error:', error);
55
- res.status(500).json({ error: { message: 'Internal server error', code: 'INTERNAL' } });
56
- }
52
+ if (abortController.signal.aborted)
53
+ return;
54
+ handleRouteError(res, error, 'Agent run error');
57
55
  }
58
56
  });
59
57
  router.post('/agents/:name/stream', async (req, res) => {
60
58
  const { name } = req.params;
61
- const agent = Object.hasOwn(ctx.agents, name) ? ctx.agents[name] : undefined;
59
+ const agent = findAgent(name);
62
60
  if (!agent) {
63
- res.status(404).json({
64
- error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' },
65
- });
61
+ sendError(res, 404, `Agent '${name}' not found`, 'NOT_FOUND');
66
62
  return;
67
63
  }
68
- const body = req.body;
69
- if (!body?.input) {
70
- res.status(400).json({
71
- error: { message: 'Missing required field: input', code: 'INVALID_INPUT' },
72
- });
64
+ const parsed = parseRunBody(req.body);
65
+ if (!parsed.ok) {
66
+ sendError(res, 400, parsed.message, 'INVALID_INPUT');
73
67
  return;
74
68
  }
69
+ const body = parsed.value;
75
70
  setupSSEHeaders(res);
76
71
  const writer = new ExpressStreamWriter(res);
77
72
  const messageId = generateId('msg');
78
- req.on('close', () => {
73
+ const abortController = new AbortController();
74
+ onClientDisconnect(res, () => {
75
+ abortController.abort();
79
76
  writer.close();
80
77
  });
78
+ let textId = null;
79
+ let streamedText = false;
80
+ const writeText = (delta) => {
81
+ if (!delta)
82
+ return;
83
+ if (textId === null) {
84
+ textId = generateId('txt');
85
+ writer.textStart(textId);
86
+ }
87
+ writer.textDelta(textId, delta);
88
+ };
89
+ const endText = () => {
90
+ if (textId === null)
91
+ return;
92
+ writer.textEnd(textId);
93
+ textId = null;
94
+ };
81
95
  try {
82
96
  writer.start(messageId);
83
- const textId = generateId('txt');
84
- writer.textStart(textId);
85
97
  const result = await ctx.cogitator.run(agent, {
86
98
  input: body.input,
87
99
  context: body.context,
88
100
  threadId: body.threadId,
101
+ userId: req.cogitator?.auth?.userId,
102
+ signal: abortController.signal,
89
103
  stream: true,
90
104
  onToken: (token) => {
91
- writer.textDelta(textId, token);
105
+ if (token)
106
+ streamedText = true;
107
+ writeText(token);
92
108
  },
93
109
  onToolCall: (toolCall) => {
94
- const toolId = generateId('tool');
95
- writer.toolCallStart(toolId, toolCall.name);
96
- writer.toolCallEnd(toolId);
110
+ endText();
111
+ writer.toolCallStart(toolCall.id, toolCall.name);
112
+ writer.toolCallDelta(toolCall.id, JSON.stringify(toolCall.arguments));
113
+ writer.toolCallEnd(toolCall.id);
97
114
  },
98
115
  onToolResult: (toolResult) => {
99
- const resultId = generateId('res');
100
- writer.toolResult(resultId, toolResult.callId, toolResult.result);
116
+ writer.toolResult(generateId('res'), toolResult.callId, toolResult.result);
101
117
  },
102
118
  });
103
- writer.textEnd(textId);
119
+ if (!streamedText)
120
+ writeText(result.output);
121
+ endText();
104
122
  writer.finish(messageId, {
105
123
  inputTokens: result.usage.inputTokens,
106
124
  outputTokens: result.usage.outputTokens,
@@ -108,12 +126,10 @@ export function createAgentRoutes(ctx) {
108
126
  });
109
127
  }
110
128
  catch (error) {
111
- if (CogitatorError.isCogitatorError(error)) {
112
- writer.error(error.message, error.code);
113
- }
114
- else {
115
- console.error('[CogitatorServer] Agent stream error:', error);
116
- writer.error('Internal server error', 'INTERNAL');
129
+ if (!abortController.signal.aborted) {
130
+ const resolved = resolveError(error, 'Agent stream error');
131
+ endText();
132
+ writer.error(resolved.message, resolved.code);
117
133
  }
118
134
  }
119
135
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"swarms.d.ts","sourceRoot":"","sources":["../../src/routes/swarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EAMb,MAAM,aAAa,CAAC;AASrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAuM3D"}
1
+ {"version":3,"file":"swarms.d.ts","sourceRoot":"","sources":["../../src/routes/swarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,KAAK,EACV,YAAY,EAKb,MAAM,aAAa,CAAC;AAcrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAqN3D"}