@cogitator-ai/koa 0.8.5 → 0.9.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 (58) hide show
  1. package/README.md +93 -34
  2. package/dist/app.d.ts +7 -0
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +31 -14
  5. package/dist/app.js.map +1 -1
  6. package/dist/index.d.ts +2 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/middleware/auth.d.ts +6 -0
  11. package/dist/middleware/auth.d.ts.map +1 -1
  12. package/dist/middleware/auth.js +17 -2
  13. package/dist/middleware/auth.js.map +1 -1
  14. package/dist/middleware/body-parser.d.ts.map +1 -1
  15. package/dist/middleware/body-parser.js +3 -4
  16. package/dist/middleware/body-parser.js.map +1 -1
  17. package/dist/middleware/context.d.ts +5 -0
  18. package/dist/middleware/context.d.ts.map +1 -1
  19. package/dist/middleware/context.js +10 -1
  20. package/dist/middleware/context.js.map +1 -1
  21. package/dist/middleware/error-handler.d.ts.map +1 -1
  22. package/dist/middleware/error-handler.js +16 -36
  23. package/dist/middleware/error-handler.js.map +1 -1
  24. package/dist/middleware/index.d.ts +1 -1
  25. package/dist/middleware/index.d.ts.map +1 -1
  26. package/dist/middleware/index.js +1 -1
  27. package/dist/middleware/index.js.map +1 -1
  28. package/dist/middleware/unmatched.d.ts +20 -0
  29. package/dist/middleware/unmatched.d.ts.map +1 -0
  30. package/dist/middleware/unmatched.js +83 -0
  31. package/dist/middleware/unmatched.js.map +1 -0
  32. package/dist/routes/agents.d.ts.map +1 -1
  33. package/dist/routes/agents.js +33 -22
  34. package/dist/routes/agents.js.map +1 -1
  35. package/dist/routes/swarms.d.ts.map +1 -1
  36. package/dist/routes/swarms.js +32 -26
  37. package/dist/routes/swarms.js.map +1 -1
  38. package/dist/routes/threads.d.ts.map +1 -1
  39. package/dist/routes/threads.js +25 -26
  40. package/dist/routes/threads.js.map +1 -1
  41. package/dist/routes/workflows.d.ts.map +1 -1
  42. package/dist/routes/workflows.js +16 -25
  43. package/dist/routes/workflows.js.map +1 -1
  44. package/dist/types.d.ts +66 -2
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/utils/errors.d.ts +14 -6
  47. package/dist/utils/errors.d.ts.map +1 -1
  48. package/dist/utils/errors.js +29 -12
  49. package/dist/utils/errors.js.map +1 -1
  50. package/dist/utils/request.d.ts +10 -0
  51. package/dist/utils/request.d.ts.map +1 -1
  52. package/dist/utils/request.js +14 -0
  53. package/dist/utils/request.js.map +1 -1
  54. package/dist/websocket/handler.d.ts +6 -0
  55. package/dist/websocket/handler.d.ts.map +1 -1
  56. package/dist/websocket/handler.js +48 -18
  57. package/dist/websocket/handler.js.map +1 -1
  58. package/package.json +9 -9
package/README.md CHANGED
@@ -32,7 +32,6 @@ const router = cogitatorApp({
32
32
  });
33
33
 
34
34
  app.use(router.routes());
35
- app.use(router.allowedMethods());
36
35
 
37
36
  app.listen(3000);
38
37
  ```
@@ -45,22 +44,28 @@ Creates a Koa Router with all Cogitator endpoints.
45
44
 
46
45
  **Options:**
47
46
 
48
- | Option | Type | Description |
49
- | -------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
50
- | `cogitator` | `Cogitator` | **Required.** Cogitator runtime instance |
51
- | `agents` | `Record<string, Agent>` | Named agents to expose |
52
- | `workflows` | `Record<string, Workflow>` | Named workflows |
53
- | `swarms` | `Record<string, SwarmConfig>` | Named swarms |
54
- | `auth` | `AuthFunction` | `(ctx) => AuthContext \| undefined` (sync or async), receives the Koa Context, throw to answer `401 UNAUTHORIZED` |
55
- | `enableSwagger` | `boolean` | Serve `/openapi.json` and Swagger UI at `/docs` |
56
- | `swagger` | `SwaggerConfig` | Swagger configuration |
57
- | `bodyLimit` | `number` | Max JSON body size in bytes (default 1 MiB) |
58
- | `sseHeartbeatMs` | `number` | How often SSE streams write a `: keep-alive` comment while a run is silent (default `5000`, `0` turns it off) |
59
- | `acceptContext` | `boolean \| string[]` | Keys of a run `context` clients may send: none by default, a list, or `true` for any (the model reads it as data from the application) |
60
- | `threadMessageRoles` | `ThreadMessageRole[]` | Roles `POST /threads/:id/messages` accepts (default `user` and `assistant`) |
47
+ | Option | Type | Description |
48
+ | -------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
49
+ | `cogitator` | `Cogitator` | **Required.** Cogitator runtime instance |
50
+ | `agents` | `Record<string, Agent>` | Named agents to expose |
51
+ | `workflows` | `Record<string, Workflow>` | Named workflows |
52
+ | `swarms` | `Record<string, SwarmConfig>` | Named swarms |
53
+ | `auth` | `AuthFunction` | `(ctx) => AuthContext \| undefined` (sync or async), receives the Koa Context, throw to answer `401 UNAUTHORIZED` |
54
+ | `enableSwagger` | `boolean` | Serve `/openapi.json` and Swagger UI at `/docs` |
55
+ | `swagger` | `SwaggerConfig` | Swagger configuration |
56
+ | `bodyLimit` | `number` | Max JSON body size in bytes (default 1 MiB) |
57
+ | `sseHeartbeatMs` | `number` | How often SSE streams write a `: keep-alive` comment while a run is silent (default `5000`, `0` turns it off) |
58
+ | `acceptContext` | `boolean \| string[]` | Keys of a run `context` clients may send: none by default, a list, or `true` for any (the model reads it as data from the application) |
59
+ | `threadMessageRoles` | `ThreadMessageRole[]` | Roles `POST /threads/:id/messages` accepts (default `user` and `assistant`) |
60
+ | `limits` | `RunLimits` | `{ swarmTimeout?, workflowMaxIterations?, workflowMaxConcurrency? }`: caps on what a request may ask a swarm or workflow run for (see [Run limits](#run-limits)) |
61
+ | `anonymous` | `'allow' \| 'deny'` | Whether callers without a `userId` may use the API (default `'allow'`), `'deny'` answers `401 UNAUTHORIZED` |
62
+ | `authorizeThread` | `(auth, threadId) => boolean \| Promise<boolean>` | Decides whether a caller may touch a thread, on top of the owner check, `false` answers `403 THREAD_FORBIDDEN` |
63
+ | `deps` | `(ctx) => unknown \| Promise<unknown>` | Builds the `deps` agent runs pass to their tools, from the Koa Context (see [Run deps](#run-deps)) |
61
64
 
62
65
  WebSocket support is attached to the HTTP server with [`setupWebSocket`](#websocket), not through router options.
63
66
 
67
+ The router answers `OPTIONS` for its own paths with `204` and the methods they serve in `Allow`, so it needs no `router.allowedMethods()`. A CORS middleware (such as `@koa/cors`) goes before the router, so it answers preflight requests itself.
68
+
64
69
  ## Request Handling
65
70
 
66
71
  - Request bodies are validated before anything reaches the runtime: `input` must contain more than whitespace (`""` and `" "` are refused before the model is called), `context` an object, `threadId` a non-empty string, swarm `timeout` a positive number. Invalid bodies return `400 INVALID_INPUT` with the offending field in the message. The validator comes from `@cogitator-ai/server-shared`, so Express, Fastify, Hono and Koa refuse exactly the same bodies.
@@ -74,7 +79,8 @@ WebSocket support is attached to the HTTP server with [`setupWebSocket`](#websoc
74
79
  - The `start` event of an agent stream names the run's thread (the request's `threadId`, or a new one), and `finish` repeats it with the run's outcome, so a client that sent no thread continues the conversation with this one.
75
80
  - Swarm routes close each swarm they build once its run ends, so a distributed swarm leaves no Redis connections behind and its state expires. `GET /swarms` lists every agent, the router and pipeline stages included.
76
81
  - Thread 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`.
77
- - `CogitatorError`s are returned with their HTTP status and code (for example `429 LLM_RATE_LIMITED`). Any other error is logged and returned as `500 Internal server error` (code `INTERNAL_ERROR`) without internal details; the same masking applies to SSE `error` events, `node_error`/`agent_error` stream events and WebSocket errors. A workflow that finishes with an error is answered like a thrown error (its `CogitatorError` status, otherwise `500`), never as a successful result. Missing optional packages (`@cogitator-ai/workflows`, `@cogitator-ai/swarms`) answer `501 UNIMPLEMENTED`.
82
+ - `GET /threads/:id` answers the whole thread, or one page of it with `?limit=50`: the newest 50 messages (oldest first within the page) and a `nextCursor`. Pass it back as `?limit=50&cursor=<nextCursor>` for the 50 before them, until an answer has no `nextCursor`. Messages written in the same millisecond are neither skipped nor repeated across pages. A `limit` outside 1 to 1000 or a cursor the server did not give answers `400 INVALID_INPUT`.
83
+ - Every error answer has the same envelope, `{ error: { message, code } }`, the one Express, Fastify, Hono and Next use. A `CogitatorError` is answered with its HTTP status and code (for example `429 LLM_RATE_LIMITED`), plus a `Retry-After` header in whole seconds when the provider said when to retry. A swarm that ran out of time answers `504 RUN_TIMEOUT`. Any other error is logged and answered as `500 Internal server error` (code `INTERNAL_ERROR`) without internal details, and the same masking applies to SSE `error` events, `node_error` and `agent_error` stream events and WebSocket errors. A workflow that finishes with an error is answered like a thrown error (its `CogitatorError` status, otherwise `500`), never as a successful result. Missing optional packages (`@cogitator-ai/workflows`, `@cogitator-ai/swarms`) answer `501 UNIMPLEMENTED`.
78
84
  - When the client disconnects, the running agent, workflow or swarm is aborted, for both JSON and SSE endpoints.
79
85
  - `GET /agents` returns each agent's `description` and never exposes its `instructions`.
80
86
  - `GET /tools` returns tool parameters as JSON Schema.
@@ -92,11 +98,11 @@ WebSocket support is attached to the HTTP server with [`setupWebSocket`](#websoc
92
98
 
93
99
  ### Threads (Memory)
94
100
 
95
- | Method | Path | Description |
96
- | -------- | ----------------------- | --------------------- |
97
- | `GET` | `/threads/:id` | Get thread messages |
98
- | `POST` | `/threads/:id/messages` | Add message to thread |
99
- | `DELETE` | `/threads/:id` | Delete thread |
101
+ | Method | Path | Description |
102
+ | -------- | ----------------------- | ------------------------------------------------ |
103
+ | `GET` | `/threads/:id` | Get thread messages, a page with `?limit&cursor` |
104
+ | `POST` | `/threads/:id/messages` | Add message to thread |
105
+ | `DELETE` | `/threads/:id` | Delete thread |
100
106
 
101
107
  ### Workflows
102
108
 
@@ -156,6 +162,51 @@ When `auth` returns a `userId`, everything a caller does with threads is scoped
156
162
  - Another user's thread answers `403` with code `THREAD_ACCESS_DENIED`, and its messages are neither returned nor changed.
157
163
  - Threads created earlier without an owner (no `userId`) stay open only to callers without a `userId`, such as servers with no `auth` configured.
158
164
 
165
+ ### Anonymous callers
166
+
167
+ By default a caller without a `userId` (no `auth`, or `auth` returned none) may use the API as an anonymous user. With `anonymous: 'deny'` such a caller gets `401 UNAUTHORIZED` on every API route. `/health`, `/ready`, `/openapi.json` and `/docs` stay open, so probes and API docs keep working. A path under the router that nothing answers gets `401` under `'deny'` too, so an anonymous caller cannot tell which paths exist, and `404 NOT_FOUND` in the error envelope under `'allow'`. WebSocket connections take the `anonymous` option of `setupWebSocket`, or the `anonymous` of its route context when the option is not set.
168
+
169
+ ### Thread authorization
170
+
171
+ Core lets a caller touch only threads they own. `authorizeThread` adds your own rule on top, for example a tenant check:
172
+
173
+ ```typescript
174
+ const router = cogitatorApp({
175
+ cogitator,
176
+ agents,
177
+ auth,
178
+ authorizeThread: (auth, threadId) => tenants.ownsThread(auth?.metadata?.tenant, threadId),
179
+ });
180
+ ```
181
+
182
+ It is called with what `auth` returned and the thread a request names: the body `threadId` of agent runs, streams and resumes and of swarm runs and streams, and the `:id` of `GET`, `DELETE` and `POST /threads/:id/messages`. It runs after the body is validated and before the owner check, and `false` answers `403 THREAD_FORBIDDEN` without starting a run. WebSocket runs and resumes are checked by the `authorizeThread` of the route context given to `setupWebSocket`, and a refusal is an `error` message.
183
+
184
+ ### Run deps
185
+
186
+ `deps` builds what an agent's tools get as `context.deps` for one request: a database handle, the tenant, a client with the caller's credentials. The model never sees them, and they never come from the request body.
187
+
188
+ ```typescript
189
+ const router = cogitatorApp({
190
+ cogitator,
191
+ agents,
192
+ deps: async (ctx) => ({ db: await pool.connect(), tenant: ctx.get('x-tenant') }),
193
+ });
194
+ ```
195
+
196
+ Agent runs, streams and resumes call it once per run. WebSocket runs take the `deps` option of `setupWebSocket`, called with the upgrade request.
197
+
198
+ ### Run limits
199
+
200
+ `limits` caps what a request may ask a run for: `swarmTimeout` (ms) for swarm runs, `workflowMaxIterations` and `workflowMaxConcurrency` for workflow runs. A request that asks for more is held to the cap, and one that asks for nothing gets the cap. Each limit must be a positive integer, or `cogitatorApp` throws. The OpenAPI spec shows each limit as the default of its field. WebSocket runs take the `limits` of the route context given to `setupWebSocket`.
201
+
202
+ ```typescript
203
+ const router = cogitatorApp({
204
+ cogitator,
205
+ swarms: { research: researchSwarm },
206
+ limits: { swarmTimeout: 120_000, workflowMaxIterations: 50, workflowMaxConcurrency: 4 },
207
+ });
208
+ ```
209
+
159
210
  ### Approvals
160
211
 
161
212
  A tool with `requiresApproval` (`true`, or a function of the arguments) pauses the run before that turn executes:
@@ -189,7 +240,7 @@ const app = new Koa();
189
240
  const main = new Router();
190
241
  const api = cogitatorApp({ cogitator, agents });
191
242
 
192
- main.use('/api/v1', api.routes(), api.allowedMethods());
243
+ main.use('/api/v1', api.routes());
193
244
  app.use(main.routes());
194
245
  ```
195
246
 
@@ -204,12 +255,11 @@ import { cogitatorApp, setupWebSocket } from '@cogitator-ai/koa';
204
255
  const app = new Koa();
205
256
  const router = cogitatorApp({ cogitator, agents });
206
257
  app.use(router.routes());
207
- app.use(router.allowedMethods());
208
258
 
209
259
  const server = createServer(app.callback());
210
260
  await setupWebSocket(
211
261
  server,
212
- { runtime: cogitator, agents, workflows: {}, swarms: {} },
262
+ { runtime: cogitator, agents, workflows: {}, swarms: {}, limits: { swarmTimeout: 120_000 } },
213
263
  {
214
264
  path: '/ws',
215
265
  pingInterval: 30000,
@@ -221,13 +271,15 @@ await setupWebSocket(
221
271
  }
222
272
  return { userId: 'api' };
223
273
  },
274
+ anonymous: 'deny',
275
+ deps: (req) => ({ tenant: req.headers['x-tenant'] }),
224
276
  }
225
277
  );
226
278
 
227
279
  server.listen(3000);
228
280
  ```
229
281
 
230
- The router's `auth` option does not cover WebSocket connections, so pass `auth` to `setupWebSocket` to protect them: it receives the upgrade `IncomingMessage`, and throwing rejects the handshake with `401` (or `500` when the error carries a `status >= 500`). Upgrades on other paths are left to other `upgrade` listeners (or rejected with `404` when there are none), so the socket can share the HTTP server with other WebSocket servers. A client that does not answer a ping within `pingTimeout` (defaults to `pingInterval`) is terminated, and closing a connection aborts its active run.
282
+ The router's `auth` option does not cover WebSocket connections, so pass `auth` to `setupWebSocket` to protect them: it receives the upgrade `IncomingMessage`, and throwing rejects the handshake with `401` (or `500` when the error carries a `status >= 500`). With `anonymous: 'deny'` a connection without a `userId` is refused with `401` too. `deps` builds the deps of each agent run on the connection from its upgrade request, called for each run. The route context can carry `limits` and `authorizeThread`, which WebSocket runs and resumes follow like the HTTP routes, and `anonymous`, which the handshake follows when the `anonymous` option is not set (the option wins). Its `deps` builds the deps of HTTP runs from a Koa `Context`, which an upgrade request does not have, so `setupWebSocket` ignores it and takes the `deps` option instead. Upgrades on other paths are left to other `upgrade` listeners (or rejected with `404` when there are none), so the socket can share the HTTP server with other WebSocket servers. A client that does not answer a ping within `pingTimeout` (defaults to `pingInterval`) is terminated, and closing a connection aborts its active run.
231
283
 
232
284
  **Message types:**
233
285
 
@@ -238,11 +290,11 @@ The router's `auth` option does not cover WebSocket connections, so pass `auth`
238
290
  | `stop` | Cancels the current run |
239
291
  | `ping` | Answered with `pong` (echoes `id`) |
240
292
 
241
- | Server sends | Description |
242
- | ------------ | ------------------------------------------------------------------------------------------------------ |
243
- | `event` | `token`, `reasoning`, `tool-call`, `tool-result`, `complete` (with the serialized result), `cancelled` |
244
- | `error` | Invalid message, unknown resource, run already in progress, or a masked run failure |
245
- | `pong` | Heartbeat reply |
293
+ | Server sends | Description |
294
+ | ------------ | ----------------------------------------------------------------------------------------------------------------------- |
295
+ | `event` | `token`, `reasoning`, `tool-call`, `tool-result`, `complete` (with the serialized result), `cancelled` |
296
+ | `error` | Invalid message, unknown resource, a thread `authorizeThread` refused, run already in progress, or a masked run failure |
297
+ | `pong` | Heartbeat reply |
246
298
 
247
299
  ## SSE Streaming
248
300
 
@@ -307,21 +359,28 @@ import {
307
359
 
308
360
  Built-in middleware stack (applied automatically by `cogitatorApp`):
309
361
 
310
- - **Error handler** — catches errors and returns structured `ErrorResponse`
311
- - **Body parser** — parses JSON for POST, PUT, PATCH requests (`bodyLimit`, 1 MiB by default, returns `413` above it). A body already parsed by upstream middleware such as `koa-bodyparser` is reused
312
- - **Context** — injects `RouteContext` with `runtime`, `agents`, `workflows`, `swarms` into Koa state
313
- - **Auth** — optional authentication via the `auth` callback
362
+ - **Error handler**, catches errors and returns structured `ErrorResponse`
363
+ - **Body parser**, parses JSON for POST, PUT, PATCH requests (`bodyLimit`, 1 MiB by default, returns `413` above it). A body already parsed by upstream middleware such as `koa-bodyparser` is reused
364
+ - **Context**, injects `RouteContext` with `runtime`, `agents`, `workflows`, `swarms` into Koa state
365
+ - **Auth**, optional authentication via the `auth` callback
366
+ - **Anonymous policy**, after the health and docs routes, answers `401` to callers without a `userId` under `anonymous: 'deny'` (`createAnonymousMiddleware`)
367
+ - **Unmatched paths**, a request no route serves skips the middleware above and goes on to the middleware after the router untouched. What nothing answers goes through auth and the anonymous policy and gets `404 NOT_FOUND` in the error envelope, or `401` under `anonymous: 'deny'`. A method a path does not take is answered the same way. Under a prefix, only paths under it are answered
314
368
 
315
369
  ## Key Types
316
370
 
317
371
  ```typescript
318
372
  import type {
319
- RouteContext, // { runtime, agents, workflows, swarms }
373
+ RouteContext, // { runtime, agents, workflows, swarms, limits?, authorizeThread?, anonymous?, deps? }, deps is for HTTP runs only
320
374
  CogitatorAppOptions,
321
375
  AuthContext,
322
376
  AuthFunction,
377
+ DepsFunction,
378
+ RunLimits,
379
+ AnonymousPolicy,
380
+ AuthorizeThread,
323
381
  WebSocketConfig,
324
382
  WebSocketAuthFunction,
383
+ WebSocketDepsFunction,
325
384
  WebSocketRunPayload,
326
385
  BodyParserOptions,
327
386
  WorkflowStatusResponse,
package/dist/app.d.ts CHANGED
@@ -1,4 +1,11 @@
1
1
  import Router from '@koa/router';
2
2
  import type { CogitatorAppOptions, CogitatorState } from './types.js';
3
+ /**
4
+ * The Cogitator API as a Koa router. A request no route serves passes on to the middleware
5
+ * after the router, and what is left unanswered gets `404 NOT_FOUND` in the error envelope, or
6
+ * `401 UNAUTHORIZED` for an anonymous caller under `anonymous: 'deny'`.
7
+ *
8
+ * @throws Error when `opts.limits` holds a limit that is not a positive integer
9
+ */
3
10
  export declare function cogitatorApp(opts: CogitatorAppOptions): Router<CogitatorState>;
4
11
  //# sourceMappingURL=app.d.ts.map
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAiBtE,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAAC,cAAc,CAAC,CAgC9E"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAmBtE;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAAC,cAAc,CAAC,CAsC9E"}
package/dist/app.js CHANGED
@@ -1,30 +1,47 @@
1
1
  import Router from '@koa/router';
2
- import { createContextMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
2
+ import { createContextMiddleware, createAnonymousMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
3
3
  import { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
4
4
  import { createSwaggerRoutes } from './swagger/index.js';
5
+ import { forRoutes, routeUnmatched } from './middleware/unmatched.js';
6
+ /**
7
+ * The Cogitator API as a Koa router. A request no route serves passes on to the middleware
8
+ * after the router, and what is left unanswered gets `404 NOT_FOUND` in the error envelope, or
9
+ * `401 UNAUTHORIZED` for an anonymous caller under `anonymous: 'deny'`.
10
+ *
11
+ * @throws Error when `opts.limits` holds a limit that is not a positive integer
12
+ */
5
13
  export function cogitatorApp(opts) {
6
14
  const router = new Router();
7
- router.use(createErrorHandler());
8
- router.use(createBodyParser({ limit: opts.bodyLimit }));
9
- router.use(createContextMiddleware(opts));
10
- if (opts.auth) {
11
- router.use(createAuthMiddleware(opts.auth));
15
+ const errorHandler = createErrorHandler();
16
+ const context = createContextMiddleware(opts);
17
+ const authenticate = opts.auth ? [createAuthMiddleware(opts.auth)] : [];
18
+ const anonymous = createAnonymousMiddleware(opts.anonymous);
19
+ router.use(forRoutes(errorHandler));
20
+ router.use(forRoutes(createBodyParser({ limit: opts.bodyLimit })));
21
+ router.use(forRoutes(context));
22
+ for (const middleware of authenticate)
23
+ router.use(forRoutes(middleware));
24
+ const publicRouters = [createHealthRoutes()];
25
+ if (opts.enableSwagger) {
26
+ publicRouters.push(createSwaggerRoutes({
27
+ ...opts.swagger,
28
+ auth: opts.swagger?.auth ?? Boolean(opts.auth),
29
+ ...(opts.limits && { limits: opts.limits }),
30
+ }));
12
31
  }
13
- const subrouters = [
14
- createHealthRoutes(),
32
+ const apiRouters = [
15
33
  createAgentRoutes(),
16
34
  createThreadRoutes(),
17
35
  createToolRoutes(),
18
36
  createWorkflowRoutes(),
19
37
  createSwarmRoutes(),
20
38
  ];
21
- if (opts.enableSwagger) {
22
- subrouters.push(createSwaggerRoutes({ ...opts.swagger, auth: opts.swagger?.auth ?? Boolean(opts.auth) }));
23
- }
24
- for (const sub of subrouters) {
39
+ for (const sub of publicRouters)
25
40
  router.use(sub.routes());
26
- router.use(sub.allowedMethods());
27
- }
41
+ router.use(forRoutes(anonymous));
42
+ for (const sub of apiRouters)
43
+ router.use(sub.routes());
44
+ routeUnmatched(router, [errorHandler, context, ...authenticate, anonymous]);
28
45
  return router;
29
46
  }
30
47
  //# sourceMappingURL=app.js.map
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,MAAM,MAAM,GAAG,IAAI,MAAM,EAAkB,CAAC;IAE5C,MAAM,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;IAE1C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,kBAAkB,EAAE;QACpB,iBAAiB,EAAE;QACnB,kBAAkB,EAAE;QACpB,gBAAgB,EAAE;QAClB,oBAAoB,EAAE;QACtB,iBAAiB,EAAE;KACpB,CAAC;IAEF,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,UAAU,CAAC,IAAI,CACb,mBAAmB,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CACzF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtE;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,MAAM,MAAM,GAAG,IAAI,MAAM,EAAkB,CAAC;IAC5C,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,MAAM,SAAS,GAAG,yBAAyB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE5D,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/B,KAAK,MAAM,UAAU,IAAI,YAAY;QAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAEzE,MAAM,aAAa,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,aAAa,CAAC,IAAI,CAChB,mBAAmB,CAAC;YAClB,GAAG,IAAI,CAAC,OAAO;YACf,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAC9C,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;SAC5C,CAAC,CACH,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,iBAAiB,EAAE;QACnB,kBAAkB,EAAE;QACpB,gBAAgB,EAAE;QAClB,oBAAoB,EAAE;QACtB,iBAAiB,EAAE;KACpB,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,aAAa;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,UAAU;QAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvD,cAAc,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAE5E,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { cogitatorApp } from './app.js';
2
- export type { AuthContext, AuthFunction, CogitatorAppOptions, CogitatorState, RouteContext, WebSocketConfig, WebSocketAuthFunction, AgentListResponse, AgentRunRequest, AgentRunResponse, AgentResumeRequest, PendingApproval, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ReadinessResponse, ReadinessCheckStatus, ErrorResponse, SwaggerConfig, WebSocketMessage, WebSocketResponse, WebSocketRunPayload, WebSocketResumePayload, } from './types.js';
3
- export { createContextMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
2
+ export type { AuthContext, AuthFunction, CogitatorAppOptions, CogitatorState, RouteContext, WebSocketConfig, WebSocketAuthFunction, WebSocketDepsFunction, DepsFunction, RunLimits, AnonymousPolicy, AuthorizeThread, AgentListResponse, AgentRunRequest, AgentRunResponse, AgentResumeRequest, PendingApproval, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ReadinessResponse, ReadinessCheckStatus, ErrorResponse, SwaggerConfig, WebSocketMessage, WebSocketResponse, WebSocketRunPayload, WebSocketResumePayload, } from './types.js';
3
+ export { createContextMiddleware, createAnonymousMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
4
4
  export type { BodyParserOptions } from './middleware/body-parser.js';
5
5
  export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
6
6
  export { createSwaggerRoutes } from './swagger/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,YAAY,EACV,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,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,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACpF,YAAY,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE/E,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,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,6BAA6B,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,YAAY,EACV,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACZ,SAAS,EACT,eAAe,EACf,eAAe,EACf,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,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACpF,YAAY,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE/E,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,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,6BAA6B,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { cogitatorApp } from './app.js';
2
- export { createContextMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
2
+ export { createContextMiddleware, createAnonymousMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
3
3
  export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
4
4
  export { createSwaggerRoutes } from './swagger/index.js';
5
5
  export { KoaStreamWriter, setupSSEHeaders } from './streaming/koa-stream-writer.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,YAAY,EAAE,MAAM,UAAU,CAAC;AAqCxC,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGpF,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAqBrC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AA0CxC,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGpF,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC3B,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAqBrC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -1,4 +1,10 @@
1
1
  import type { Context, Next } from 'koa';
2
+ import { type AnonymousPolicy } from '@cogitator-ai/server-shared';
2
3
  import type { AuthFunction } from '../types.js';
3
4
  export declare function createAuthMiddleware(authFn: AuthFunction): (ctx: Context, next: Next) => Promise<void>;
5
+ /**
6
+ * Turns away callers without a `userId` when `anonymous` is `'deny'`, with
7
+ * `401 UNAUTHORIZED`. Routes registered before it, such as health and docs, stay open.
8
+ */
9
+ export declare function createAnonymousMiddleware(anonymous: AnonymousPolicy | undefined): (ctx: Context, next: Next) => Promise<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,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAe,YAAY,EAAkB,MAAM,aAAa,CAAC;AAE7E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,IACzC,KAAK,OAAO,EAAE,MAAM,IAAI,mBAiBvC"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9F,OAAO,KAAK,EAAe,YAAY,EAAkB,MAAM,aAAa,CAAC;AAG7E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,IACzC,KAAK,OAAO,EAAE,MAAM,IAAI,mBAgBvC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,eAAe,GAAG,SAAS,IAChE,KAAK,OAAO,EAAE,MAAM,IAAI,mBAQvC"}
@@ -1,3 +1,5 @@
1
+ import { UNAUTHORIZED, admitCaller } from '@cogitator-ai/server-shared';
2
+ import { sendError } from '../utils/errors.js';
1
3
  export function createAuthMiddleware(authFn) {
2
4
  return async (ctx, next) => {
3
5
  let auth;
@@ -9,12 +11,25 @@ export function createAuthMiddleware(authFn) {
9
11
  if (status !== undefined && status >= 500) {
10
12
  throw err;
11
13
  }
12
- ctx.status = 401;
13
- ctx.body = { error: { message: 'Unauthorized', code: 'UNAUTHORIZED' } };
14
+ sendError(ctx, { ...UNAUTHORIZED, message: 'Unauthorized' });
14
15
  return;
15
16
  }
16
17
  ctx.state.auth = auth;
17
18
  await next();
18
19
  };
19
20
  }
21
+ /**
22
+ * Turns away callers without a `userId` when `anonymous` is `'deny'`, with
23
+ * `401 UNAUTHORIZED`. Routes registered before it, such as health and docs, stay open.
24
+ */
25
+ export function createAnonymousMiddleware(anonymous) {
26
+ return async (ctx, next) => {
27
+ const refusal = admitCaller(ctx.state.auth?.userId, anonymous);
28
+ if (refusal) {
29
+ sendError(ctx, refusal);
30
+ return;
31
+ }
32
+ await next();
33
+ };
34
+ }
20
35
  //# sourceMappingURL=auth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,IAAI,IAA6B,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAI,GAAkC,EAAE,MAAM,CAAC;YAC3D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC1C,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC;YACxE,OAAO;QACT,CAAC;QAEA,GAAG,CAAC,KAAwB,CAAC,IAAI,GAAG,IAAI,CAAC;QAC1C,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAwB,MAAM,6BAA6B,CAAC;AAE9F,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,IAAI,IAA6B,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAI,GAAkC,EAAE,MAAM,CAAC;YAC3D,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC1C,MAAM,GAAG,CAAC;YACZ,CAAC;YACD,SAAS,CAAC,GAAG,EAAE,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QAEA,GAAG,CAAC,KAAwB,CAAC,IAAI,GAAG,IAAI,CAAC;QAC1C,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,SAAsC;IAC9E,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,WAAW,CAAE,GAAG,CAAC,KAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACnF,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEzC,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,IAGhD,KAAK,OAAO,EAAE,MAAM,IAAI,mBA4BvC"}
1
+ {"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAGzC,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,IAGhD,KAAK,OAAO,EAAE,MAAM,IAAI,mBA0BvC"}
@@ -1,4 +1,5 @@
1
1
  import { refuseNonJsonBody } from '@cogitator-ai/server-shared';
2
+ import { invalidInput, sendError } from '../utils/errors.js';
2
3
  export const DEFAULT_BODY_LIMIT = 1024 * 1024;
3
4
  const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
4
5
  export function createBodyParser(options = {}) {
@@ -7,8 +8,7 @@ export function createBodyParser(options = {}) {
7
8
  const refusal = refuseNonJsonBody(ctx.method, ctx.headers);
8
9
  if (refusal) {
9
10
  await discardBody(ctx);
10
- ctx.status = refusal.status;
11
- ctx.body = { error: { message: refusal.message, code: refusal.code } };
11
+ sendError(ctx, refusal);
12
12
  return;
13
13
  }
14
14
  if (BODY_METHODS.has(ctx.method) && ctx.is('application/json') && !isBodyConsumed(ctx)) {
@@ -23,8 +23,7 @@ export function createBodyParser(options = {}) {
23
23
  ctx.request.body = JSON.parse(raw);
24
24
  }
25
25
  catch {
26
- ctx.status = 400;
27
- ctx.body = { error: { message: 'Invalid JSON body', code: 'INVALID_INPUT' } };
26
+ invalidInput(ctx, 'Invalid JSON body');
28
27
  return;
29
28
  }
30
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
1
  import type { Context, Next } from 'koa';
2
2
  import type { CogitatorAppOptions } from '../types.js';
3
+ /**
4
+ * Sets the Cogitator state of each request.
5
+ *
6
+ * @throws Error when `opts.limits` holds a limit that is not a positive integer
7
+ */
3
8
  export declare function createContextMiddleware(opts: CogitatorAppOptions): (ctx: Context, next: Next) => Promise<void>;
4
9
  //# sourceMappingURL=context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/middleware/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAgC,MAAM,aAAa,CAAC;AAOrF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,mBAAmB,IAWjD,KAAK,OAAO,EAAE,MAAM,IAAI,mBAOvC"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/middleware/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAgC,MAAM,aAAa,CAAC;AAQrF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,mBAAmB,IAejD,KAAK,OAAO,EAAE,MAAM,IAAI,mBAOvC"}
@@ -1,4 +1,9 @@
1
- import { DEFAULT_THREAD_MESSAGE_ROLES, generateId, resolveSseHeartbeatMs, } from '@cogitator-ai/server-shared';
1
+ import { DEFAULT_THREAD_MESSAGE_ROLES, checkRunLimits, generateId, resolveSseHeartbeatMs, } from '@cogitator-ai/server-shared';
2
+ /**
3
+ * Sets the Cogitator state of each request.
4
+ *
5
+ * @throws Error when `opts.limits` holds a limit that is not a positive integer
6
+ */
2
7
  export function createContextMiddleware(opts) {
3
8
  const routeCtx = {
4
9
  runtime: opts.cogitator,
@@ -8,6 +13,10 @@ export function createContextMiddleware(opts) {
8
13
  sseHeartbeatMs: resolveSseHeartbeatMs(opts.sseHeartbeatMs),
9
14
  acceptContext: opts.acceptContext ?? false,
10
15
  threadMessageRoles: opts.threadMessageRoles ?? DEFAULT_THREAD_MESSAGE_ROLES,
16
+ limits: checkRunLimits(opts.limits),
17
+ authorizeThread: opts.authorizeThread,
18
+ anonymous: opts.anonymous,
19
+ deps: opts.deps,
11
20
  };
12
21
  return async (ctx, next) => {
13
22
  const state = ctx.state;
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/middleware/context.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,4BAA4B,EAC5B,UAAU,EACV,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAErC,MAAM,UAAU,uBAAuB,CAAC,IAAyB;IAC/D,MAAM,QAAQ,GAAiB;QAC7B,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;QACzB,cAAc,EAAE,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;QAC1D,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,KAAK;QAC1C,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,4BAA4B;KAC5E,CAAC;IAEF,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAuB,CAAC;QAC1C,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC3B,KAAK,CAAC,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACpC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/middleware/context.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,UAAU,EACV,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAErC;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAyB;IAC/D,MAAM,QAAQ,GAAiB;QAC7B,OAAO,EAAE,IAAI,CAAC,SAAS;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;QACzB,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;QAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;QACzB,cAAc,EAAE,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;QAC1D,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,KAAK;QAC1C,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,4BAA4B;QAC3E,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;QACnC,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,IAAI,EAAE,IAAI,CAAC,IAAI;KAChB,CAAC;IAEF,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAuB,CAAC;QAC1C,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC3B,KAAK,CAAC,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACpC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,IAAI,EAAE,CAAC;IACf,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,IAAI,EAAE,MAAM,KAAK,CAAC;AAGzC,wBAAgB,kBAAkB,KAClB,KAAK,OAAO,EAAE,MAAM,IAAI,mBAkDvC"}
1
+ {"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAIzC,wBAAgB,kBAAkB,KAClB,KAAK,OAAO,EAAE,MAAM,IAAI,mBA6BvC"}
@@ -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 } from '../utils/errors.js';
2
3
  export function createErrorHandler() {
3
4
  return async (ctx, next) => {
4
5
  try {
@@ -7,46 +8,25 @@ export function createErrorHandler() {
7
8
  catch (err) {
8
9
  if (ctx.headerSent)
9
10
  return;
10
- if (CogitatorError.isCogitatorError(err)) {
11
- ctx.status = err.statusCode ?? ERROR_STATUS_CODES[err.code] ?? 500;
12
- ctx.body = {
13
- error: {
14
- message: err.message,
15
- code: err.code,
16
- },
17
- };
11
+ const described = describeHttpError(err);
12
+ if (described) {
13
+ sendError(ctx, described);
18
14
  return;
19
15
  }
20
- const status = err.status;
21
- if (status && status >= 400 && status < 600) {
22
- ctx.status = status;
23
- if (status >= 500) {
24
- console.error('[CogitatorKoa] Unhandled error:', err);
25
- ctx.body = {
26
- error: {
27
- message: 'Internal server error',
28
- code: ErrorCode.INTERNAL_ERROR,
29
- },
30
- };
31
- }
32
- else {
33
- ctx.body = {
34
- error: {
35
- message: err instanceof Error ? err.message : 'HTTP error',
36
- code: status === 413 ? 'PAYLOAD_TOO_LARGE' : 'HTTP_ERROR',
37
- },
38
- };
39
- }
16
+ const status = err?.status;
17
+ if (status && status >= 400 && status < 500) {
18
+ sendError(ctx, {
19
+ status,
20
+ code: status === 413 ? 'PAYLOAD_TOO_LARGE' : 'HTTP_ERROR',
21
+ message: err instanceof Error ? err.message : 'HTTP error',
22
+ });
40
23
  return;
41
24
  }
42
25
  console.error('[CogitatorKoa] Unhandled error:', err);
43
- ctx.status = 500;
44
- ctx.body = {
45
- error: {
46
- message: 'Internal server error',
47
- code: ErrorCode.INTERNAL_ERROR,
48
- },
49
- };
26
+ sendError(ctx, {
27
+ ...INTERNAL_ERROR,
28
+ ...(status && status >= 500 && status < 600 && { status }),
29
+ });
50
30
  }
51
31
  };
52
32
  }
@@ -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,kBAAkB;IAChC,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,CAAC,UAAU;gBAAE,OAAO;YAE3B,IAAI,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;gBACnE,GAAG,CAAC,IAAI,GAAG;oBACT,KAAK,EAAE;wBACL,OAAO,EAAE,GAAG,CAAC,OAAO;wBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;qBACf;iBACF,CAAC;gBACF,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,CAAC;YACnD,IAAI,MAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC5C,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;gBACpB,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;oBAClB,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;oBACtD,GAAG,CAAC,IAAI,GAAG;wBACT,KAAK,EAAE;4BACL,OAAO,EAAE,uBAAuB;4BAChC,IAAI,EAAE,SAAS,CAAC,cAAc;yBAC/B;qBACF,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,IAAI,GAAG;wBACT,KAAK,EAAE;4BACL,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;4BAC1D,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,YAAY;yBAC1D;qBACF,CAAC;gBACJ,CAAC;gBACD,OAAO;YACT,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;YAEtD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG;gBACT,KAAK,EAAE;oBACL,OAAO,EAAE,uBAAuB;oBAChC,IAAI,EAAE,SAAS,CAAC,cAAc;iBAC/B;aACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,UAAU,kBAAkB;IAChC,OAAO,KAAK,EAAE,GAAY,EAAE,IAAU,EAAE,EAAE;QACxC,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,CAAC,UAAU;gBAAE,OAAO;YAE3B,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;YACzC,IAAI,SAAS,EAAE,CAAC;gBACd,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAI,GAAkC,EAAE,MAAM,CAAC;YAC3D,IAAI,MAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,EAAE,CAAC;gBAC5C,SAAS,CAAC,GAAG,EAAE;oBACb,MAAM;oBACN,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,YAAY;oBACzD,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY;iBAC3D,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;YACtD,SAAS,CAAC,GAAG,EAAE;gBACb,GAAG,cAAc;gBACjB,GAAG,CAAC,MAAM,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC;aAC3D,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}