@cogitator-ai/express 0.9.5 → 0.10.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 (49) hide show
  1. package/README.md +65 -8
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/middleware/auth.d.ts +6 -0
  7. package/dist/middleware/auth.d.ts.map +1 -1
  8. package/dist/middleware/auth.js +17 -6
  9. package/dist/middleware/auth.js.map +1 -1
  10. package/dist/middleware/error-handler.d.ts.map +1 -1
  11. package/dist/middleware/error-handler.js +16 -36
  12. package/dist/middleware/error-handler.js.map +1 -1
  13. package/dist/middleware/index.d.ts +1 -1
  14. package/dist/middleware/index.d.ts.map +1 -1
  15. package/dist/middleware/index.js +1 -1
  16. package/dist/middleware/index.js.map +1 -1
  17. package/dist/middleware/json-body.d.ts.map +1 -1
  18. package/dist/middleware/json-body.js +2 -1
  19. package/dist/middleware/json-body.js.map +1 -1
  20. package/dist/middleware/rate-limit.d.ts.map +1 -1
  21. package/dist/middleware/rate-limit.js +6 -6
  22. package/dist/middleware/rate-limit.js.map +1 -1
  23. package/dist/routes/agents.d.ts.map +1 -1
  24. package/dist/routes/agents.js +13 -1
  25. package/dist/routes/agents.js.map +1 -1
  26. package/dist/routes/swarms.d.ts.map +1 -1
  27. package/dist/routes/swarms.js +8 -4
  28. package/dist/routes/swarms.js.map +1 -1
  29. package/dist/routes/threads.d.ts.map +1 -1
  30. package/dist/routes/threads.js +15 -18
  31. package/dist/routes/threads.js.map +1 -1
  32. package/dist/routes/utils.d.ts +26 -8
  33. package/dist/routes/utils.d.ts.map +1 -1
  34. package/dist/routes/utils.js +52 -12
  35. package/dist/routes/utils.js.map +1 -1
  36. package/dist/routes/workflows.d.ts.map +1 -1
  37. package/dist/routes/workflows.js +6 -5
  38. package/dist/routes/workflows.js.map +1 -1
  39. package/dist/server.d.ts +2 -1
  40. package/dist/server.d.ts.map +1 -1
  41. package/dist/server.js +11 -6
  42. package/dist/server.js.map +1 -1
  43. package/dist/types.d.ts +48 -2
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/websocket/ws-handler.d.ts +2 -2
  46. package/dist/websocket/ws-handler.d.ts.map +1 -1
  47. package/dist/websocket/ws-handler.js +123 -28
  48. package/dist/websocket/ws-handler.js.map +1 -1
  49. package/package.json +8 -8
package/README.md CHANGED
@@ -69,13 +69,25 @@ Run/stream body: `{ input: string; context?: object; threadId?: string }`. `inpu
69
69
  ### Threads (Memory)
70
70
 
71
71
  ```
72
- GET /api/threads/:id - Get thread messages
72
+ GET /api/threads/:id - Get thread messages, a page at a time with ?limit&cursor
73
73
  POST /api/threads/:id/messages - Add message to thread
74
74
  DELETE /api/threads/:id - Delete thread
75
75
  ```
76
76
 
77
77
  The routes use `cogitator.getMemory()`, which connects the configured memory adapter on first use, so threads can be read on a fresh server before any agent has run. Only a `Cogitator` without `memory` configured answers `503 UNAVAILABLE`. New messages need `role` (`user` or `assistant`, more with `threadMessageRoles`) and a non-empty string `content`, optional `metadata` is stored on the memory entry.
78
78
 
79
+ `GET /threads/:id` answers the whole thread by default. With `?limit=50` it answers the newest 50 messages (oldest first within the page) and a `nextCursor`, and `?limit=50&cursor=<nextCursor>` the 50 before them, until an answer has no `nextCursor`. Messages written in the same millisecond are never skipped or repeated across pages. A `limit` outside 1 to 1000 or a cursor the server never gave is refused with `400 INVALID_INPUT`.
80
+
81
+ ```typescript
82
+ let cursor: string | undefined;
83
+ do {
84
+ const query = new URLSearchParams({ limit: '50', ...(cursor && { cursor }) });
85
+ const page = await (await fetch(`/api/threads/${threadId}?${query}`)).json();
86
+ render(page.messages);
87
+ cursor = page.nextCursor;
88
+ } while (cursor);
89
+ ```
90
+
79
91
  ### Workflows
80
92
 
81
93
  ```
@@ -84,7 +96,7 @@ POST /api/workflows/:name/run - Run workflow
84
96
  POST /api/workflows/:name/stream - Stream workflow events
85
97
  ```
86
98
 
87
- Body: `{ input?: object; options?: { maxConcurrency?: number; maxIterations?: number } }`. `maxConcurrency`/`maxIterations` must be positive integers (400 otherwise). Other options are dropped, and `checkpoint: true` is refused, since the server keeps no checkpoint store to resume from. A failed workflow returns `500` with code `WORKFLOW_FAILED` (the stream ends with an `error` event instead of `workflow_completed`). Disconnecting aborts the workflow.
99
+ Body: `{ input?: object; options?: { maxConcurrency?: number; maxIterations?: number } }`. `maxConcurrency`/`maxIterations` must be positive integers (400 otherwise). With `limits.workflowMaxIterations` or `limits.workflowMaxConcurrency` set, a larger value is held to the limit, and a request that asks for nothing gets the limit. Other options are dropped, and `checkpoint: true` is refused, since the server keeps no checkpoint store to resume from. A failed workflow answers the error it failed with, mapped like any other run error (a node that hit `LLM_RATE_LIMITED` answers `429` with `Retry-After`, an internal error `500 INTERNAL_ERROR`), and its stream ends with an `error` event carrying that code instead of `workflow_completed`. Disconnecting aborts the workflow.
88
100
 
89
101
  The stream sends `{ type: 'workflow', event, data }` events: `node_started`, `node_completed`, `node_error`, `node_progress` and finally `workflow_completed`.
90
102
 
@@ -97,7 +109,7 @@ POST /api/swarms/:name/stream - Stream swarm events
97
109
  GET /api/swarms/:name/blackboard - Get configured blackboard sections
98
110
  ```
99
111
 
100
- Run/stream body: `{ input: string; context?: object; threadId?: string; timeout?: number }` (`timeout` must be positive, at most `2147483647` ms). Disconnecting aborts the swarm. The stream sends `{ type: 'swarm', event, data }` events (`agent_start`, `agent_complete`, `agent_error`, `message`, the swarm's own events, and finally `swarm_completed` with the output and usage). Each run creates a fresh swarm, so the blackboard endpoint returns the configured initial sections.
112
+ Run/stream body: `{ input: string; context?: object; threadId?: string; timeout?: number }` (`timeout` must be positive, at most `2147483647` ms). With `limits.swarmTimeout` set, a longer timeout is held to it and a run without one gets it, and a swarm that runs out of time answers `504 RUN_TIMEOUT`. Disconnecting aborts the swarm. The stream sends `{ type: 'swarm', event, data }` events (`agent_start`, `agent_complete`, `agent_error`, `message`, the swarm's own events, and finally `swarm_completed` with the output and usage). Each run creates a fresh swarm, so the blackboard endpoint returns the configured initial sections.
101
113
 
102
114
  ### Tools & Docs
103
115
 
@@ -155,6 +167,24 @@ const server = new CogitatorServer({
155
167
  description: 'AI-powered API endpoints',
156
168
  version: '1.0.0',
157
169
  },
170
+
171
+ // Caps on what a request may ask a run for. A larger value is held to the cap,
172
+ // a request without one gets the cap. Checked when the server is created.
173
+ limits: { swarmTimeout: 120_000, workflowMaxIterations: 50, workflowMaxConcurrency: 4 },
174
+
175
+ // 'deny' answers 401 to callers without a userId. Health, ready and the docs stay open.
176
+ anonymous: 'deny',
177
+
178
+ // Called with the auth context and the thread of every request that names one.
179
+ // false answers 403 THREAD_FORBIDDEN and no run starts.
180
+ authorizeThread: (auth, threadId) => threadId.startsWith(`${auth?.userId}:`),
181
+
182
+ // Dependencies for the tools of HTTP agent runs, streams and resumes (context.deps).
183
+ // Built from the request on the server, never read from the body.
184
+ deps: async (req) => ({ db: await tenantDb(req.get('x-tenant')) }),
185
+
186
+ // WebSocket runs build theirs from the upgrade request, a plain Node IncomingMessage.
187
+ websocket: { deps: async (req) => ({ db: await tenantDb(req.headers['x-tenant']) }) },
158
188
  },
159
189
  });
160
190
  ```
@@ -167,6 +197,16 @@ When `auth` returns a `userId`, everything a caller does with threads is scoped
167
197
  - `GET /threads/:id`, `POST /threads/:id/messages` and `DELETE /threads/:id` check the thread's owner first; `POST` to an unknown id creates the thread owned by the caller.
168
198
  - Another user's thread answers `403` with code `THREAD_ACCESS_DENIED`, and its messages are neither returned nor changed.
169
199
  - Threads created earlier without an owner (no `userId`) stay open only to callers without a `userId`, such as servers with no `auth` configured.
200
+ - `authorizeThread(auth, threadId)` adds your own rule on top of ownership, for shared or team threads. It runs on every route that names a thread (agent run, stream and resume, swarm run and stream, `GET`, `DELETE` and `POST /threads/:id/messages`) and on WebSocket runs with a `threadId`, after the body is validated and before core checks the owner. Answering `false` refuses with `403 THREAD_FORBIDDEN`, and no run starts.
201
+ - `anonymous: 'deny'` refuses every caller whose `auth` gave no `userId` with `401 UNAUTHORIZED`, WebSocket upgrades included. `/health`, `/ready`, `/openapi.json` and `/docs` stay open. An unknown path under the base path answers `401` too, so an anonymous caller cannot probe which routes exist, and `404 NOT_FOUND` once the caller has a `userId`. The default, `'allow'`, lets anonymous callers in as before, and an unknown path answers `404 NOT_FOUND` in the error envelope.
202
+
203
+ ### Limits and deps
204
+
205
+ `limits` caps what a client may ask a run for: `swarmTimeout` (ms), `workflowMaxIterations` and `workflowMaxConcurrency`. A request is never refused over a limit: it gets the smaller of what it asked for and the limit, or the limit when it asked for nothing, over HTTP and SSE alike. The OpenAPI spec shows each limit as the default of its field. Each limit must be a positive integer, or the constructor throws.
206
+
207
+ `deps: (req) => deps` builds the dependencies agent tools read as `context.deps` (a database handle, a tenant, a client), and the HTTP run, stream or resume gets them as `deps`. They are built on the server for each request and never come from the body. An error the hook throws is answered like a run error, before a stream starts.
208
+
209
+ WebSocket runs and resumes take theirs from `websocket.deps: (req) => deps`, called for each run with the upgrade request. That request is a plain Node `IncomingMessage` that never went through Express, so it has `headers`, `url` and `socket` but no `req.get()` and nothing a middleware adds, which is why it gets a hook of its own. Without `websocket.deps` WebSocket runs get no deps. An error it throws (or one `authorizeThread` throws) answers `{ type: 'error', id, error }` and starts no run.
170
210
 
171
211
  ### Approvals
172
212
 
@@ -248,7 +288,7 @@ await server.attachWebSocket(httpServer); // defaults to `${basePath}/ws`
248
288
  httpServer.listen(3000);
249
289
  ```
250
290
 
251
- `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.
291
+ `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, or when it gives no `userId` under `anonymous: 'deny'`). A `run` or `resume` on a thread `authorizeThread` refuses answers `{ type: 'error', id, error }` without starting, and `websocket.deps` is called with the upgrade request. For custom setups, `setupWebSocket(httpServer, routeContext, config)` is also exported.
252
292
 
253
293
  Protocol:
254
294
 
@@ -257,13 +297,15 @@ Protocol:
257
297
  | `{ type: 'run', id, payload: { type: 'agent', name, input, context?, threadId? } }` | Client→Server | Run an agent; events arrive as `{ type: 'event', id, payload }` (`token`, `reasoning`, `tool-call`, `tool-result`, `complete`, `cancelled`) |
258
298
  | `{ type: 'resume', id, payload: { name, threadId, decisions?, defaultDecision? } }` | Client→Server | Resume a run paused for tool approvals; events arrive like those of `run` |
259
299
  | `{ type: 'stop' }` | Client→Server | Abort the client's running agent (emits `cancelled`) |
260
- | `{ type: 'subscribe', channel: 'agent:<name>' }` | Client→Server | Receive events of runs of that agent started by the same user elsewhere |
300
+ | `{ type: 'subscribe', channel: 'agent:<name>' }` | Client→Server | Receive events of runs of that agent started by the same user elsewhere, on threads `authorizeThread` allows |
261
301
  | `{ type: 'unsubscribe', channel }` | Client→Server | Stop receiving channel events |
262
302
  | `{ type: 'ping' }` | Client→Server | Answered with `{ type: 'pong' }` |
263
303
  | `{ type: 'subscribed' \| 'unsubscribed', id, channel }` | Server→Client | Subscription confirmed (at most 64 channels per connection) |
264
304
  | `{ type: 'error', id?, error }` | Server→Client | Invalid message or payload, unknown agent, or a failed run |
265
305
 
266
- 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. A failed run reports a `CogitatorError`'s message; any other error is logged and sent as `Internal server error`. The server pings every `pingInterval` ms and terminates clients that miss a pong.
306
+ 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. A failed run reports a `CogitatorError`'s message, any other error is logged and sent as `Internal server error`. The server pings every `pingInterval` ms and terminates clients that miss a pong.
307
+
308
+ A subscriber gets the events of a run only when it has the `userId` of the caller who started it and, with `authorizeThread` set, when `authorizeThread(subscriberAuth, threadId)` allows it on the run's thread (the `threadId` of the run, or the one core created for it). The answer is asked once per subscriber and run, and a subscriber it refuses, or throws for, gets none of the run's events. Without `authorizeThread`, callers without a `userId` share the events of each other's runs, so set `authorizeThread` or `anonymous: 'deny'` when anonymous callers must not see each other.
267
309
 
268
310
  Client usage:
269
311
 
@@ -386,8 +428,22 @@ interface CogitatorServerConfig {
386
428
  sseHeartbeatMs?: number; // Default: 5000, 0 turns SSE heartbeats off
387
429
  acceptContext?: boolean | string[]; // context keys clients may send: none by default, a list, or true for any
388
430
  threadMessageRoles?: ('user' | 'assistant' | 'system')[]; // roles of POST /threads/:id/messages, default user and assistant
431
+ limits?: RunLimits; // { swarmTimeout?, workflowMaxIterations?, workflowMaxConcurrency? }
432
+ anonymous?: 'allow' | 'deny'; // Default: 'allow'
433
+ authorizeThread?: (
434
+ auth: AuthContext | undefined,
435
+ threadId: string
436
+ ) => boolean | Promise<boolean>;
437
+ deps?: (req: Request) => unknown | Promise<unknown>; // HTTP runs, WebSocket runs use websocket.deps
389
438
  };
390
439
  }
440
+
441
+ interface WebSocketConfig {
442
+ path?: string; // Default: `${basePath}/ws`
443
+ pingInterval?: number; // Default: 30000
444
+ maxPayloadSize?: number; // Default: 1 MiB
445
+ deps?: (req: IncomingMessage) => unknown | Promise<unknown>; // deps of WebSocket runs, from the upgrade request
446
+ }
391
447
  ```
392
448
 
393
449
  `CogitatorServer` writes nothing to the console when it starts. `init()` and the WebSocket setup report through the core logger at `debug` level (`getLogger()` from `@cogitator-ai/core`, `LOG_LEVEL=debug` to see them, or `setLogger()` to route them into your own logger). Errors are still logged.
@@ -438,16 +494,17 @@ Error codes map to HTTP status codes:
438
494
  - `INVALID_INPUT` → 400 (validation errors and malformed JSON bodies)
439
495
  - `UNAUTHORIZED` → 401
440
496
  - `THREAD_ACCESS_DENIED` → 403 (another user's thread)
497
+ - `THREAD_FORBIDDEN` → 403 (`authorizeThread` refused the thread)
441
498
  - `NOT_FOUND` → 404
442
499
  - `RUN_NOT_PAUSED` → 409 (resume of a thread without a paused run)
443
500
  - `PAYLOAD_TOO_LARGE` → 413
444
501
  - `RATE_LIMIT_EXCEEDED` → 429
445
- - `WORKFLOW_FAILED` → 500
446
502
  - `INTERNAL_ERROR` → 500
447
503
  - `UNIMPLEMENTED` → 501 (optional workflows/swarms package missing)
448
504
  - `UNAVAILABLE` → 503 (no memory configured)
505
+ - `RUN_TIMEOUT` → 504 (a swarm ran out of time)
449
506
 
450
- A `CogitatorError` keeps its message and code and uses the code's mapped status (for example `LLM_RATE_LIMITED` → 429). Any other error is logged on the server and answered as `500 Internal server error`, so connection strings, file paths and other internals never reach the client. The same masking applies to SSE `error` events, the `node_error`/`agent_error` stream events, `Workflow failed: …` messages and WebSocket run errors.
507
+ A `CogitatorError` keeps its message and code and answers with its own `statusCode`, which is the code's mapped status unless the error was given another (for example `LLM_RATE_LIMITED` → 429). When it says when to retry (`retryAfter`, as provider rate limits do), the answer carries `Retry-After` in whole seconds. The mapping is `describeHttpError` of `@cogitator-ai/server-shared`, so Express, Fastify, Hono, Koa and Next answer the same error the same way. Any other error is logged on the server and answered as `500 Internal server error`, so connection strings, file paths and other internals never reach the client. The same mapping applies to a failed workflow, and the same masking to SSE `error` events, the `node_error`/`agent_error` stream events and WebSocket run errors.
451
508
 
452
509
  ## Documentation
453
510
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { CogitatorServer } from './server.js';
2
- export type { AuthContext, AuthFunction, CogitatorRequest, CogitatorServerConfig, RateLimitConfig, CorsConfig, SwaggerConfig, WebSocketConfig, RouteContext, AgentListResponse, AgentRunRequest, AgentRunResponse, AgentResumeRequest, PendingApproval, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ReadinessResponse, ReadinessCheckStatus, ErrorResponse, WebSocketMessage, WebSocketResponse, OpenAPISpec, ExpressMiddleware, } from './types.js';
3
- export { createAuthMiddleware, createRateLimitMiddleware, createCorsMiddleware, errorHandler, notFoundHandler, } from './middleware/index.js';
2
+ export type { AuthContext, AuthFunction, DepsFunction, WebSocketDepsFunction, CogitatorRequest, CogitatorServerConfig, RateLimitConfig, CorsConfig, SwaggerConfig, WebSocketConfig, RouteContext, ResolvedServerConfig, AgentListResponse, AgentRunRequest, AgentRunResponse, AgentResumeRequest, PendingApproval, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ReadinessResponse, ReadinessCheckStatus, ErrorResponse, WebSocketMessage, WebSocketResponse, OpenAPISpec, ExpressMiddleware, } from './types.js';
3
+ export { createAuthMiddleware, createAnonymousGuard, createRateLimitMiddleware, createCorsMiddleware, errorHandler, notFoundHandler, } from './middleware/index.js';
4
4
  export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
5
5
  export { ExpressStreamWriter, setupSSEHeaders, generateId, encodeSSE, encodeDone, } from './streaming/index.js';
6
6
  export type { ExpressStreamWriterOptions } from './streaming/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,YAAY,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,WAAW,EACX,KAAK,GACN,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,YAAY,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEvE,YAAY,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,WAAW,EACX,KAAK,GACN,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { CogitatorServer } from './server.js';
2
- export { createAuthMiddleware, createRateLimitMiddleware, createCorsMiddleware, errorHandler, notFoundHandler, } from './middleware/index.js';
2
+ export { createAuthMiddleware, createAnonymousGuard, createRateLimitMiddleware, createCorsMiddleware, errorHandler, notFoundHandler, } from './middleware/index.js';
3
3
  export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
4
4
  export { ExpressStreamWriter, setupSSEHeaders, generateId, encodeSSE, encodeDone, } from './streaming/index.js';
5
5
  export { generateOpenAPISpec, serveSwaggerUI } from './swagger/index.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAsC9C,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAsB9B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAyC9C,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,YAAY,EACZ,eAAe,GAChB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,sBAAsB,CAAC;AAsB9B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,4 +1,10 @@
1
1
  import type { Response, NextFunction } from 'express';
2
+ import { type AnonymousPolicy } from '@cogitator-ai/server-shared';
2
3
  import type { CogitatorRequest, AuthFunction } from '../types.js';
3
4
  export declare function createAuthMiddleware(authFn?: AuthFunction): (req: CogitatorRequest, res: Response, next: NextFunction) => Promise<void>;
5
+ /**
6
+ * Answers `401 UNAUTHORIZED` to a caller without a user id when `anonymous` is `'deny'`.
7
+ * Mounted after the public routes (health, ready, docs), so only the API is closed.
8
+ */
9
+ export declare function createAnonymousGuard(anonymous: AnonymousPolicy | undefined): (req: CogitatorRequest, res: Response, next: NextFunction) => void;
4
10
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGlE,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,YAAY,IAC1C,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAuBvE"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIlE,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,YAAY,IAC1C,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,mBAkBvE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,eAAe,GAAG,SAAS,IACjE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAQjE"}
@@ -1,4 +1,6 @@
1
+ import { admitCaller } from '@cogitator-ai/server-shared';
1
2
  import { generateId } from '../streaming/helpers.js';
3
+ import { sendError, sendFailure } from '../routes/utils.js';
2
4
  export function createAuthMiddleware(authFn) {
3
5
  return async (req, res, next) => {
4
6
  req.cogitator = {
@@ -14,13 +16,22 @@ export function createAuthMiddleware(authFn) {
14
16
  next();
15
17
  }
16
18
  catch {
17
- res.status(401).json({
18
- error: {
19
- message: 'Unauthorized',
20
- code: 'UNAUTHORIZED',
21
- },
22
- });
19
+ sendError(res, 401, 'Unauthorized', 'UNAUTHORIZED');
23
20
  }
24
21
  };
25
22
  }
23
+ /**
24
+ * Answers `401 UNAUTHORIZED` to a caller without a user id when `anonymous` is `'deny'`.
25
+ * Mounted after the public routes (health, ready, docs), so only the API is closed.
26
+ */
27
+ export function createAnonymousGuard(anonymous) {
28
+ return (req, res, next) => {
29
+ const refusal = admitCaller(req.cogitator?.auth?.userId, anonymous);
30
+ if (!refusal) {
31
+ next();
32
+ return;
33
+ }
34
+ sendFailure(res, refusal);
35
+ };
36
+ }
26
37
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,OAAO,KAAK,EAAE,GAAqB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACxE,GAAG,CAAC,SAAS,GAAG;YACd,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC;YAC5B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;YAC1B,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,KAAK,EAAE;oBACL,OAAO,EAAE,cAAc;oBACvB,IAAI,EAAE,cAAc;iBACrB;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAwB,MAAM,6BAA6B,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,OAAO,KAAK,EAAE,GAAqB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACxE,GAAG,CAAC,SAAS,GAAG;YACd,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC;YAC5B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QAEF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,EAAE,CAAC;QAChB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;YAC1B,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAsC;IACzE,OAAO,CAAC,GAAqB,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QAClE,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5B,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;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
+ {"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;AAqC/D,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAahG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAElE"}
@@ -1,4 +1,5 @@
1
- import { CogitatorError, ERROR_STATUS_CODES, ErrorCode } from '@cogitator-ai/types';
1
+ import { INTERNAL_ERROR, describeHttpError, } from '@cogitator-ai/server-shared';
2
+ import { sendError, sendFailure } from '../routes/utils.js';
2
3
  const CLIENT_ERROR_CODES = {
3
4
  400: 'INVALID_INPUT',
4
5
  401: 'UNAUTHORIZED',
@@ -8,59 +9,38 @@ const CLIENT_ERROR_CODES = {
8
9
  415: 'UNSUPPORTED_MEDIA_TYPE',
9
10
  429: 'RATE_LIMIT_EXCEEDED',
10
11
  };
12
+ /** A 4xx error of Express or its body parser, told to the client as it is */
11
13
  function asClientError(err) {
12
14
  if (typeof err !== 'object' || err === null)
13
- return null;
15
+ return undefined;
14
16
  const rawStatus = Reflect.get(err, 'status') ?? Reflect.get(err, 'statusCode');
15
17
  if (typeof rawStatus !== 'number' || rawStatus < 400 || rawStatus >= 500)
16
- return null;
18
+ return undefined;
17
19
  const message = Reflect.get(err, 'message');
18
20
  const type = Reflect.get(err, 'type');
19
21
  return {
20
22
  status: rawStatus,
21
- message: typeof message === 'string' ? message : 'Bad request',
22
- type: typeof type === 'string' ? type : undefined,
23
+ code: CLIENT_ERROR_CODES[rawStatus] ?? 'BAD_REQUEST',
24
+ message: type === 'entity.parse.failed'
25
+ ? 'Invalid JSON body'
26
+ : typeof message === 'string'
27
+ ? message
28
+ : 'Bad request',
23
29
  };
24
30
  }
25
31
  export function errorHandler(err, _req, res, _next) {
26
32
  if (res.headersSent) {
27
33
  return;
28
34
  }
29
- if (CogitatorError.isCogitatorError(err)) {
30
- const statusCode = ERROR_STATUS_CODES[err.code] || 500;
31
- res.status(statusCode).json({
32
- error: {
33
- message: err.message,
34
- code: err.code,
35
- },
36
- });
37
- return;
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
- });
35
+ const described = describeHttpError(err) ?? asClientError(err);
36
+ if (described) {
37
+ sendFailure(res, described);
48
38
  return;
49
39
  }
50
40
  console.error('[CogitatorServer] Unhandled error:', err);
51
- res.status(500).json({
52
- error: {
53
- message: 'Internal server error',
54
- code: ErrorCode.INTERNAL_ERROR,
55
- },
56
- });
41
+ sendFailure(res, INTERNAL_ERROR);
57
42
  }
58
43
  export function notFoundHandler(_req, res) {
59
- res.status(404).json({
60
- error: {
61
- message: 'Not found',
62
- code: 'NOT_FOUND',
63
- },
64
- });
44
+ sendError(res, 404, 'Not found', 'NOT_FOUND');
65
45
  }
66
46
  //# sourceMappingURL=error-handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,iBAAiB,GAElB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAE5D,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,6EAA6E;AAC7E,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC9D,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,SAAS,CAAC;IAC3F,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,IAAI,EAAE,kBAAkB,CAAC,SAAS,CAAC,IAAI,aAAa;QACpD,OAAO,EACL,IAAI,KAAK,qBAAqB;YAC5B,CAAC,CAAC,mBAAmB;YACrB,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ;gBAC3B,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,aAAa;KACtB,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,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,SAAS,EAAE,CAAC;QACd,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC5B,OAAO;IACT,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;IACzD,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,GAAa;IAC1D,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC"}
@@ -1,4 +1,4 @@
1
- export { createAuthMiddleware } from './auth.js';
1
+ export { createAuthMiddleware, createAnonymousGuard } from './auth.js';
2
2
  export { createRateLimitMiddleware } from './rate-limit.js';
3
3
  export { createCorsMiddleware } from './cors.js';
4
4
  export { errorHandler, notFoundHandler } from './error-handler.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,4 +1,4 @@
1
- export { createAuthMiddleware } from './auth.js';
1
+ export { createAuthMiddleware, createAnonymousGuard } from './auth.js';
2
2
  export { createRateLimitMiddleware } from './rate-limit.js';
3
3
  export { createCorsMiddleware } from './cors.js';
4
4
  export { errorHandler, notFoundHandler } from './error-handler.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"json-body.d.ts","sourceRoot":"","sources":["../../src/middleware/json-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CASpD"}
1
+ {"version":3,"file":"json-body.d.ts","sourceRoot":"","sources":["../../src/middleware/json-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CASpD"}
@@ -1,4 +1,5 @@
1
1
  import { refuseNonJsonBody } from '@cogitator-ai/server-shared';
2
+ import { sendFailure } from '../routes/utils.js';
2
3
  /**
3
4
  * Refuses a request whose body is not JSON with `415 UNSUPPORTED_MEDIA_TYPE` before any
4
5
  * route reads it. Browsers send `text/plain` and form bodies across origins without a
@@ -11,7 +12,7 @@ export function createJsonBodyGuard() {
11
12
  next();
12
13
  return;
13
14
  }
14
- res.status(refusal.status).json({ error: { message: refusal.message, code: refusal.code } });
15
+ sendFailure(res, refusal);
15
16
  };
16
17
  }
17
18
  //# sourceMappingURL=json-body.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-body.js","sourceRoot":"","sources":["../../src/middleware/json-body.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/F,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"json-body.js","sourceRoot":"","sources":["../../src/middleware/json-body.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,EAAE,CAAC;YACP,OAAO;QACT,CAAC;QACD,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC5B,CAAC,CAAC;AACJ,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;AAsBrE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,IA4BvD,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;AAuBrE,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,IA4BvD,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UAmCjE"}
@@ -1,3 +1,4 @@
1
+ import { sendFailure } from '../routes/utils.js';
1
2
  function buildKeyGenerator(trustProxy) {
2
3
  return (req) => {
3
4
  if (trustProxy) {
@@ -49,12 +50,11 @@ export function createRateLimitMiddleware(config) {
49
50
  res.setHeader('X-RateLimit-Remaining', remaining.toString());
50
51
  res.setHeader('X-RateLimit-Reset', resetSeconds.toString());
51
52
  if (entry.count > max) {
52
- res.setHeader('Retry-After', resetSeconds.toString());
53
- res.status(429).json({
54
- error: {
55
- message,
56
- code: 'RATE_LIMIT_EXCEEDED',
57
- },
53
+ sendFailure(res, {
54
+ status: 429,
55
+ code: 'RATE_LIMIT_EXCEEDED',
56
+ message,
57
+ retryAfter: resetSeconds,
58
58
  });
59
59
  return;
60
60
  }
@@ -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":"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"}
@@ -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,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AAUrF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAmJ3D"}
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,EAAE,YAAY,EAAuC,MAAM,aAAa,CAAC;AAgBrF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CA+J3D"}
@@ -1,7 +1,7 @@
1
1
  import { Router } from 'express';
2
2
  import { AgentStreamSession, parseResumeRequest, parseRunRequest, toAgentRunResponse, } from '@cogitator-ai/server-shared';
3
3
  import { ExpressStreamWriter, setupSSEHeaders } from '../streaming/index.js';
4
- import { handleRouteError, onClientDisconnect, resolveError, sendError } from './utils.js';
4
+ import { admitAgentRun, handleRouteError, onClientDisconnect, resolveError, sendError, } from './utils.js';
5
5
  export function createAgentRoutes(ctx) {
6
6
  const router = Router();
7
7
  const runRequestOptions = { acceptContext: ctx.config.acceptContext };
@@ -28,6 +28,9 @@ export function createAgentRoutes(ctx) {
28
28
  return;
29
29
  }
30
30
  const body = parsed.value;
31
+ const admitted = await admitAgentRun(ctx, req, res, body.threadId, 'Agent run error');
32
+ if (!admitted)
33
+ return;
31
34
  const abortController = new AbortController();
32
35
  onClientDisconnect(res, () => abortController.abort());
33
36
  try {
@@ -37,6 +40,7 @@ export function createAgentRoutes(ctx) {
37
40
  threadId: body.threadId,
38
41
  userId: req.cogitator?.auth?.userId,
39
42
  signal: abortController.signal,
43
+ ...admitted,
40
44
  });
41
45
  res.json(toAgentRunResponse(result));
42
46
  }
@@ -59,6 +63,9 @@ export function createAgentRoutes(ctx) {
59
63
  return;
60
64
  }
61
65
  const { threadId, decisions, defaultDecision } = parsed.value;
66
+ const admitted = await admitAgentRun(ctx, req, res, threadId, 'Agent resume error');
67
+ if (!admitted)
68
+ return;
62
69
  const abortController = new AbortController();
63
70
  onClientDisconnect(res, () => abortController.abort());
64
71
  try {
@@ -67,6 +74,7 @@ export function createAgentRoutes(ctx) {
67
74
  decisions,
68
75
  defaultDecision,
69
76
  signal: abortController.signal,
77
+ ...admitted,
70
78
  });
71
79
  res.json(toAgentRunResponse(result));
72
80
  }
@@ -89,6 +97,9 @@ export function createAgentRoutes(ctx) {
89
97
  return;
90
98
  }
91
99
  const body = parsed.value;
100
+ const admitted = await admitAgentRun(ctx, req, res, body.threadId, 'Agent stream error');
101
+ if (!admitted)
102
+ return;
92
103
  setupSSEHeaders(res);
93
104
  const writer = new ExpressStreamWriter(res, { heartbeatMs: ctx.config.sseHeartbeatMs });
94
105
  const session = new AgentStreamSession((event) => writer.send(event), {
@@ -109,6 +120,7 @@ export function createAgentRoutes(ctx) {
109
120
  signal: abortController.signal,
110
121
  stream: true,
111
122
  ...session.callbacks,
123
+ ...admitted,
112
124
  });
113
125
  session.complete(result);
114
126
  }
@@ -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,EAKb,MAAM,aAAa,CAAC;AAcrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CA2N3D"}
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;AAoBrB,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CA+N3D"}
@@ -1,7 +1,7 @@
1
1
  import { Router } from 'express';
2
- import { parseSwarmRunRequest, swarmAgentNames, withSwarm } from '@cogitator-ai/server-shared';
2
+ import { parseSwarmRunRequest, swarmAgentNames, swarmTimeoutWithin, withSwarm, } from '@cogitator-ai/server-shared';
3
3
  import { ExpressStreamWriter, setupSSEHeaders, generateId } from '../streaming/index.js';
4
- import { handleRouteError, isModuleNotFound, onClientDisconnect, resolveError, sendError, } from './utils.js';
4
+ import { admitThread, handleRouteError, isModuleNotFound, onClientDisconnect, resolveError, sendError, } from './utils.js';
5
5
  const SWARMS_MISSING = 'Swarms package not installed';
6
6
  export function createSwarmRoutes(ctx) {
7
7
  const router = Router();
@@ -32,6 +32,8 @@ export function createSwarmRoutes(ctx) {
32
32
  return;
33
33
  }
34
34
  const body = parsed.value;
35
+ if (!(await admitThread(ctx, req, res, body.threadId, 'Swarm run error')))
36
+ return;
35
37
  let disconnected = false;
36
38
  let abortSwarm;
37
39
  onClientDisconnect(res, () => {
@@ -49,7 +51,7 @@ export function createSwarmRoutes(ctx) {
49
51
  context: body.context,
50
52
  threadId: body.threadId,
51
53
  userId: req.cogitator?.auth?.userId,
52
- timeout: body.timeout,
54
+ timeout: swarmTimeoutWithin(body.timeout, ctx.config.limits),
53
55
  });
54
56
  const agentResults = {};
55
57
  for (const [agentName, agentResult] of result.agentResults.entries()) {
@@ -99,6 +101,8 @@ export function createSwarmRoutes(ctx) {
99
101
  return;
100
102
  }
101
103
  const body = parsed.value;
104
+ if (!(await admitThread(ctx, req, res, body.threadId, 'Swarm stream error')))
105
+ return;
102
106
  setupSSEHeaders(res);
103
107
  const writer = new ExpressStreamWriter(res, { heartbeatMs: ctx.config.sseHeartbeatMs });
104
108
  const messageId = generateId('swarm');
@@ -121,7 +125,7 @@ export function createSwarmRoutes(ctx) {
121
125
  context: body.context,
122
126
  threadId: body.threadId,
123
127
  userId: req.cogitator?.auth?.userId,
124
- timeout: body.timeout,
128
+ timeout: swarmTimeoutWithin(body.timeout, ctx.config.limits),
125
129
  onAgentStart: (agentName) => {
126
130
  writer.swarmEvent('agent_start', { agentName, timestamp: Date.now() });
127
131
  },