@cogitator-ai/koa 0.1.14 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -25
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +1 -4
- package/dist/app.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +8 -11
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/body-parser.d.ts +5 -1
- package/dist/middleware/body-parser.d.ts.map +1 -1
- package/dist/middleware/body-parser.js +70 -25
- package/dist/middleware/body-parser.js.map +1 -1
- package/dist/middleware/error-handler.js +1 -1
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +38 -34
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/swarms.d.ts.map +1 -1
- package/dist/routes/swarms.js +49 -53
- package/dist/routes/swarms.js.map +1 -1
- package/dist/routes/threads.d.ts.map +1 -1
- package/dist/routes/threads.js +33 -37
- package/dist/routes/threads.js.map +1 -1
- package/dist/routes/tools.d.ts.map +1 -1
- package/dist/routes/tools.js +11 -17
- package/dist/routes/tools.js.map +1 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/routes/workflows.js +55 -28
- package/dist/routes/workflows.js.map +1 -1
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +8 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +21 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/lookup.d.ts +2 -0
- package/dist/utils/lookup.d.ts.map +1 -0
- package/dist/utils/lookup.js +4 -0
- package/dist/utils/lookup.js.map +1 -0
- package/dist/utils/request.d.ts +4 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +11 -0
- package/dist/utils/request.js.map +1 -0
- package/dist/utils/results.d.ts +22 -0
- package/dist/utils/results.d.ts.map +1 -0
- package/dist/utils/results.js +37 -0
- package/dist/utils/results.js.map +1 -0
- package/dist/utils/validation.d.ts +14 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +103 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/websocket/handler.d.ts +1 -1
- package/dist/websocket/handler.d.ts.map +1 -1
- package/dist/websocket/handler.js +260 -151
- package/dist/websocket/handler.js.map +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -41,17 +41,28 @@ Creates a Koa Router with all Cogitator endpoints.
|
|
|
41
41
|
|
|
42
42
|
**Options:**
|
|
43
43
|
|
|
44
|
-
| Option
|
|
45
|
-
|
|
|
46
|
-
| `cogitator`
|
|
47
|
-
| `agents`
|
|
48
|
-
| `workflows`
|
|
49
|
-
| `swarms`
|
|
50
|
-
| `auth`
|
|
51
|
-
| `enableSwagger`
|
|
52
|
-
| `swagger`
|
|
53
|
-
| `
|
|
54
|
-
|
|
44
|
+
| Option | Type | Description |
|
|
45
|
+
| --------------- | ------------------------------- | ---------------------------------------------- |
|
|
46
|
+
| `cogitator` | `Cogitator` | **Required.** Cogitator runtime instance |
|
|
47
|
+
| `agents` | `Record<string, Agent>` | Named agents to expose |
|
|
48
|
+
| `workflows` | `Record<string, Workflow>` | Named workflows |
|
|
49
|
+
| `swarms` | `Record<string, SwarmConfig>` | Named swarms |
|
|
50
|
+
| `auth` | `(ctx: Context) => AuthContext` | Authentication function (receives Koa Context) |
|
|
51
|
+
| `enableSwagger` | `boolean` | Enable Swagger/OpenAPI docs |
|
|
52
|
+
| `swagger` | `SwaggerConfig` | Swagger configuration |
|
|
53
|
+
| `bodyLimit` | `number` | Max JSON body size in bytes (default 1 MiB) |
|
|
54
|
+
|
|
55
|
+
WebSocket support is attached to the HTTP server with [`setupWebSocket`](#websocket), not through router options.
|
|
56
|
+
|
|
57
|
+
## Request Handling
|
|
58
|
+
|
|
59
|
+
- Request bodies are validated before anything reaches the runtime: `input` must be a non-empty string, `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.
|
|
60
|
+
- Workflow runs accept an optional body. `options` is limited to `maxConcurrency`, `maxIterations` (positive integers) and `checkpoint` (boolean); any other option is dropped, and a wrongly typed one returns `400 INVALID_INPUT`.
|
|
61
|
+
- Thread messages accept `role` of `user`, `assistant` or `system`; `metadata` is stored with the entry and a token estimate is recorded.
|
|
62
|
+
- `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` without internal details. A workflow that finishes with an error is reported as an error, never as a successful result.
|
|
63
|
+
- When the client disconnects, the running agent, workflow or swarm is aborted, for both JSON and SSE endpoints.
|
|
64
|
+
- `GET /agents` returns each agent's `description` and never exposes its `instructions`.
|
|
65
|
+
- `GET /tools` returns tool parameters as JSON Schema.
|
|
55
66
|
|
|
56
67
|
## Endpoints
|
|
57
68
|
|
|
@@ -127,14 +138,14 @@ app.use(main.routes());
|
|
|
127
138
|
|
|
128
139
|
## WebSocket
|
|
129
140
|
|
|
130
|
-
Requires the optional `ws`
|
|
141
|
+
Requires the optional `ws` dependency. Supports agent, workflow, and swarm runs over a persistent connection.
|
|
131
142
|
|
|
132
143
|
```typescript
|
|
133
144
|
import { createServer } from 'http';
|
|
134
145
|
import { cogitatorApp, setupWebSocket } from '@cogitator-ai/koa';
|
|
135
146
|
|
|
136
147
|
const app = new Koa();
|
|
137
|
-
const router = cogitatorApp({ cogitator, agents
|
|
148
|
+
const router = cogitatorApp({ cogitator, agents });
|
|
138
149
|
app.use(router.routes());
|
|
139
150
|
app.use(router.allowedMethods());
|
|
140
151
|
|
|
@@ -145,29 +156,39 @@ await setupWebSocket(
|
|
|
145
156
|
{
|
|
146
157
|
path: '/ws',
|
|
147
158
|
pingInterval: 30000,
|
|
159
|
+
pingTimeout: 10000,
|
|
160
|
+
maxPayloadSize: 1024 * 1024,
|
|
161
|
+
auth: (req) => {
|
|
162
|
+
if (req.headers.authorization !== `Bearer ${process.env.API_TOKEN}`) {
|
|
163
|
+
throw new Error('Unauthorized');
|
|
164
|
+
}
|
|
165
|
+
return { userId: 'api' };
|
|
166
|
+
},
|
|
148
167
|
}
|
|
149
168
|
);
|
|
150
169
|
|
|
151
170
|
server.listen(3000);
|
|
152
171
|
```
|
|
153
172
|
|
|
173
|
+
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.
|
|
174
|
+
|
|
154
175
|
**Message types:**
|
|
155
176
|
|
|
156
|
-
| Client sends |
|
|
157
|
-
| ------------ |
|
|
158
|
-
| `run` |
|
|
159
|
-
| `stop` |
|
|
160
|
-
| `ping` |
|
|
177
|
+
| Client sends | Payload |
|
|
178
|
+
| ------------ | ------------------------------------------------------------------------------ |
|
|
179
|
+
| `run` | `{ type: 'agent' \| 'workflow' \| 'swarm', name, input, context?, threadId? }` |
|
|
180
|
+
| `stop` | Cancels the current run |
|
|
181
|
+
| `ping` | Answered with `pong` (echoes `id`) |
|
|
161
182
|
|
|
162
|
-
| Server sends | Description
|
|
163
|
-
| ------------ |
|
|
164
|
-
| `event` |
|
|
165
|
-
| `error` |
|
|
166
|
-
| `pong` | Heartbeat
|
|
183
|
+
| Server sends | Description |
|
|
184
|
+
| ------------ | ----------------------------------------------------------------------------------------- |
|
|
185
|
+
| `event` | `token`, `tool-call`, `tool-result`, `complete` (with the serialized result), `cancelled` |
|
|
186
|
+
| `error` | Invalid message, unknown resource, run already in progress, or a masked run failure |
|
|
187
|
+
| `pong` | Heartbeat reply |
|
|
167
188
|
|
|
168
189
|
## SSE Streaming
|
|
169
190
|
|
|
170
|
-
The adapter includes `KoaStreamWriter` for Server-Sent Events with structured event types (text deltas, tool calls, workflow/swarm events).
|
|
191
|
+
The adapter includes `KoaStreamWriter` for Server-Sent Events with structured event types (text deltas, tool calls, workflow/swarm events). Agent streams emit `tool-call-start`, `tool-call-delta` (the JSON arguments) and `tool-call-end` with the provider's tool call id, so `tool-result.toolCallId` always matches the call it belongs to.
|
|
171
192
|
|
|
172
193
|
## Event Factories
|
|
173
194
|
|
|
@@ -205,7 +226,7 @@ import {
|
|
|
205
226
|
Built-in middleware stack (applied automatically by `cogitatorApp`):
|
|
206
227
|
|
|
207
228
|
- **Error handler** — catches errors and returns structured `ErrorResponse`
|
|
208
|
-
- **Body parser** — parses JSON for POST, PUT, PATCH requests (1
|
|
229
|
+
- **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
|
|
209
230
|
- **Context** — injects `RouteContext` with `runtime`, `agents`, `workflows`, `swarms` into Koa state
|
|
210
231
|
- **Auth** — optional authentication via the `auth` callback
|
|
211
232
|
|
|
@@ -218,6 +239,9 @@ import type {
|
|
|
218
239
|
AuthContext,
|
|
219
240
|
AuthFunction,
|
|
220
241
|
WebSocketConfig,
|
|
242
|
+
WebSocketAuthFunction,
|
|
243
|
+
WebSocketRunPayload,
|
|
244
|
+
BodyParserOptions,
|
|
221
245
|
WorkflowStatusResponse,
|
|
222
246
|
AgentRunRequest,
|
|
223
247
|
AgentRunResponse,
|
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,
|
|
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,CA8B9E"}
|
package/dist/app.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createSwaggerRoutes } from './swagger/index.js';
|
|
|
5
5
|
export function cogitatorApp(opts) {
|
|
6
6
|
const router = new Router();
|
|
7
7
|
router.use(createErrorHandler());
|
|
8
|
-
router.use(createBodyParser());
|
|
8
|
+
router.use(createBodyParser({ limit: opts.bodyLimit }));
|
|
9
9
|
router.use(createContextMiddleware(opts));
|
|
10
10
|
if (opts.auth) {
|
|
11
11
|
router.use(createAuthMiddleware(opts.auth));
|
|
@@ -25,9 +25,6 @@ export function cogitatorApp(opts) {
|
|
|
25
25
|
router.use(sub.routes());
|
|
26
26
|
router.use(sub.allowedMethods());
|
|
27
27
|
}
|
|
28
|
-
if (opts.enableWebSocket) {
|
|
29
|
-
console.log('[CogitatorKoa] WebSocket support enabled — call setupWebSocket() with your HTTP server');
|
|
30
|
-
}
|
|
31
28
|
return router;
|
|
32
29
|
}
|
|
33
30
|
//# 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,EAAE,CAAC,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,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,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { cogitatorApp } from './app.js';
|
|
2
|
-
export type { AuthContext, AuthFunction, CogitatorAppOptions, CogitatorState, RouteContext, WebSocketConfig, AgentListResponse, AgentRunRequest, AgentRunResponse, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ErrorResponse, SwaggerConfig, WebSocketMessage, WebSocketResponse, } from './types.js';
|
|
2
|
+
export type { AuthContext, AuthFunction, CogitatorAppOptions, CogitatorState, RouteContext, WebSocketConfig, WebSocketAuthFunction, AgentListResponse, AgentRunRequest, AgentRunResponse, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ErrorResponse, SwaggerConfig, WebSocketMessage, WebSocketResponse, WebSocketRunPayload, } from './types.js';
|
|
3
3
|
export { createContextMiddleware, createAuthMiddleware, createBodyParser, createErrorHandler, } from './middleware/index.js';
|
|
4
|
+
export type { BodyParserOptions } from './middleware/body-parser.js';
|
|
4
5
|
export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
|
|
5
6
|
export { createSwaggerRoutes } from './swagger/index.js';
|
|
6
7
|
export { KoaStreamWriter, setupSSEHeaders } from './streaming/koa-stream-writer.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,iBAAiB,
|
|
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,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,GACpB,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;AAEpF,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAErC,YAAY,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,WAAW,EACX,KAAK,GACN,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAgCxC,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;AAEpF,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,6BAA6B,CAAC;AAiBrC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -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,
|
|
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"}
|
package/dist/middleware/auth.js
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
export function createAuthMiddleware(authFn) {
|
|
2
2
|
return async (ctx, next) => {
|
|
3
|
+
let auth;
|
|
3
4
|
try {
|
|
4
|
-
|
|
5
|
-
ctx.state.auth = auth;
|
|
6
|
-
await next();
|
|
5
|
+
auth = await authFn(ctx);
|
|
7
6
|
}
|
|
8
7
|
catch (err) {
|
|
9
|
-
const status = err
|
|
10
|
-
if (status && status >= 500) {
|
|
8
|
+
const status = err?.status;
|
|
9
|
+
if (status !== undefined && status >= 500) {
|
|
11
10
|
throw err;
|
|
12
11
|
}
|
|
13
12
|
ctx.status = 401;
|
|
14
|
-
ctx.body = {
|
|
15
|
-
|
|
16
|
-
message: 'Unauthorized',
|
|
17
|
-
code: 'UNAUTHORIZED',
|
|
18
|
-
},
|
|
19
|
-
};
|
|
13
|
+
ctx.body = { error: { message: 'Unauthorized', code: 'UNAUTHORIZED' } };
|
|
14
|
+
return;
|
|
20
15
|
}
|
|
16
|
+
ctx.state.auth = auth;
|
|
17
|
+
await next();
|
|
21
18
|
};
|
|
22
19
|
}
|
|
23
20
|
//# 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,CAAC;YACH,
|
|
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,3 +1,7 @@
|
|
|
1
1
|
import type { Context, Next } from 'koa';
|
|
2
|
-
export declare
|
|
2
|
+
export declare const DEFAULT_BODY_LIMIT: number;
|
|
3
|
+
export interface BodyParserOptions {
|
|
4
|
+
limit?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function createBodyParser(options?: BodyParserOptions): (ctx: Context, next: Next) => Promise<void>;
|
|
3
7
|
//# sourceMappingURL=body-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"AAAA,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,mBAqBvC"}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
1
|
+
export const DEFAULT_BODY_LIMIT = 1024 * 1024;
|
|
2
|
+
const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
|
|
3
|
+
export function createBodyParser(options = {}) {
|
|
4
|
+
const limit = options.limit ?? DEFAULT_BODY_LIMIT;
|
|
3
5
|
return async (ctx, next) => {
|
|
4
|
-
if (
|
|
5
|
-
const
|
|
6
|
-
if (
|
|
6
|
+
if (BODY_METHODS.has(ctx.method) && ctx.is('application/json') && !isBodyConsumed(ctx)) {
|
|
7
|
+
const declaredLength = Number(ctx.get('content-length'));
|
|
8
|
+
if (Number.isFinite(declaredLength) && declaredLength > limit) {
|
|
9
|
+
await discardBody(ctx);
|
|
10
|
+
throw new PayloadTooLargeError();
|
|
11
|
+
}
|
|
12
|
+
const raw = await readBody(ctx, limit);
|
|
13
|
+
if (raw.trim()) {
|
|
7
14
|
try {
|
|
8
|
-
ctx.request.body = JSON.parse(
|
|
15
|
+
ctx.request.body = JSON.parse(raw);
|
|
9
16
|
}
|
|
10
17
|
catch {
|
|
11
18
|
ctx.status = 400;
|
|
@@ -17,42 +24,80 @@ export function createBodyParser() {
|
|
|
17
24
|
await next();
|
|
18
25
|
};
|
|
19
26
|
}
|
|
20
|
-
function
|
|
27
|
+
function isBodyConsumed(ctx) {
|
|
28
|
+
return (ctx.request.body !== undefined ||
|
|
29
|
+
ctx.req.readableEnded);
|
|
30
|
+
}
|
|
31
|
+
function discardBody(ctx) {
|
|
32
|
+
const req = ctx.req;
|
|
33
|
+
if (req.readableEnded || req.destroyed)
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const done = () => {
|
|
37
|
+
req.off('end', done);
|
|
38
|
+
req.off('close', done);
|
|
39
|
+
req.off('error', done);
|
|
40
|
+
resolve();
|
|
41
|
+
};
|
|
42
|
+
req.on('end', done);
|
|
43
|
+
req.on('close', done);
|
|
44
|
+
req.on('error', done);
|
|
45
|
+
req.resume();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function readBody(ctx, limit) {
|
|
21
49
|
return new Promise((resolve, reject) => {
|
|
50
|
+
const req = ctx.req;
|
|
22
51
|
const chunks = [];
|
|
23
52
|
let size = 0;
|
|
24
53
|
let settled = false;
|
|
25
|
-
|
|
54
|
+
const cleanup = () => {
|
|
55
|
+
req.off('data', onData);
|
|
56
|
+
req.off('end', onEnd);
|
|
57
|
+
req.off('error', onError);
|
|
58
|
+
req.off('close', onClose);
|
|
59
|
+
};
|
|
60
|
+
const settle = (action) => {
|
|
26
61
|
if (settled)
|
|
27
62
|
return;
|
|
63
|
+
settled = true;
|
|
64
|
+
cleanup();
|
|
65
|
+
action();
|
|
66
|
+
};
|
|
67
|
+
const onData = (chunk) => {
|
|
28
68
|
size += chunk.length;
|
|
29
|
-
if (size >
|
|
30
|
-
settled = true;
|
|
69
|
+
if (size > limit) {
|
|
31
70
|
chunks.length = 0;
|
|
32
|
-
|
|
33
|
-
|
|
71
|
+
settle(() => {
|
|
72
|
+
void discardBody(ctx).then(() => reject(new PayloadTooLargeError()));
|
|
73
|
+
});
|
|
34
74
|
return;
|
|
35
75
|
}
|
|
36
76
|
chunks.push(chunk);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (settled)
|
|
46
|
-
return;
|
|
47
|
-
settled = true;
|
|
48
|
-
reject(err);
|
|
49
|
-
});
|
|
77
|
+
};
|
|
78
|
+
const onEnd = () => settle(() => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
79
|
+
const onError = (err) => settle(() => reject(err));
|
|
80
|
+
const onClose = () => settle(() => reject(new RequestAbortedError()));
|
|
81
|
+
req.on('data', onData);
|
|
82
|
+
req.on('end', onEnd);
|
|
83
|
+
req.on('error', onError);
|
|
84
|
+
req.on('close', onClose);
|
|
50
85
|
});
|
|
51
86
|
}
|
|
52
87
|
class PayloadTooLargeError extends Error {
|
|
53
88
|
status = 413;
|
|
89
|
+
expose = true;
|
|
54
90
|
constructor() {
|
|
55
91
|
super('Payload too large');
|
|
92
|
+
this.name = 'PayloadTooLargeError';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
class RequestAbortedError extends Error {
|
|
96
|
+
status = 400;
|
|
97
|
+
expose = true;
|
|
98
|
+
constructor() {
|
|
99
|
+
super('Request aborted');
|
|
100
|
+
this.name = 'RequestAbortedError';
|
|
56
101
|
}
|
|
57
102
|
}
|
|
58
103
|
//# sourceMappingURL=body-parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"AAEA,MAAM,
|
|
1
|
+
{"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/middleware/body-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ export function createErrorHandler() {
|
|
|
8
8
|
if (ctx.headerSent)
|
|
9
9
|
return;
|
|
10
10
|
if (CogitatorError.isCogitatorError(err)) {
|
|
11
|
-
ctx.status = ERROR_STATUS_CODES[err.code]
|
|
11
|
+
ctx.status = err.statusCode ?? ERROR_STATUS_CODES[err.code] ?? 500;
|
|
12
12
|
ctx.body = {
|
|
13
13
|
error: {
|
|
14
14
|
message: err.message,
|
|
@@ -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,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAuC,MAAM,aAAa,CAAC;AASvF,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,cAAc,CAAC,CAkI1D"}
|
package/dist/routes/agents.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import Router from '@koa/router';
|
|
2
2
|
import { KoaStreamWriter, setupSSEHeaders } from '../streaming/index.js';
|
|
3
3
|
import { generateId } from '@cogitator-ai/server-shared';
|
|
4
|
+
import { getOwn } from '../utils/lookup.js';
|
|
5
|
+
import { resolveError } from '../utils/errors.js';
|
|
6
|
+
import { getRequestBody, onClientDisconnect } from '../utils/request.js';
|
|
7
|
+
import { parseAgentRunRequest } from '../utils/validation.js';
|
|
4
8
|
export function createAgentRoutes() {
|
|
5
9
|
const router = new Router();
|
|
6
10
|
router.get('/agents', (ctx) => {
|
|
7
11
|
const { agents } = ctx.state.cogitator;
|
|
8
12
|
const agentList = Object.entries(agents).map(([name, agent]) => ({
|
|
9
13
|
name,
|
|
10
|
-
description: agent.config.
|
|
11
|
-
tools: agent.config.tools?.map((t) => t.name)
|
|
14
|
+
description: agent.config.description,
|
|
15
|
+
tools: agent.config.tools?.map((t) => t.name) ?? [],
|
|
12
16
|
}));
|
|
13
17
|
const response = { agents: agentList };
|
|
14
18
|
ctx.body = response;
|
|
@@ -16,23 +20,24 @@ export function createAgentRoutes() {
|
|
|
16
20
|
router.post('/agents/:name/run', async (ctx) => {
|
|
17
21
|
const { agents, runtime } = ctx.state.cogitator;
|
|
18
22
|
const { name } = ctx.params;
|
|
19
|
-
const agent = agents
|
|
23
|
+
const agent = getOwn(agents, name);
|
|
20
24
|
if (!agent) {
|
|
21
25
|
ctx.status = 404;
|
|
22
26
|
ctx.body = { error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' } };
|
|
23
27
|
return;
|
|
24
28
|
}
|
|
25
|
-
const
|
|
26
|
-
if (!
|
|
29
|
+
const parsed = parseAgentRunRequest(getRequestBody(ctx));
|
|
30
|
+
if (!parsed.ok) {
|
|
27
31
|
ctx.status = 400;
|
|
28
|
-
ctx.body = { error: { message:
|
|
32
|
+
ctx.body = { error: { message: parsed.message, code: 'INVALID_INPUT' } };
|
|
29
33
|
return;
|
|
30
34
|
}
|
|
35
|
+
const abortController = new AbortController();
|
|
36
|
+
onClientDisconnect(ctx, () => abortController.abort());
|
|
31
37
|
try {
|
|
32
38
|
const result = await runtime.run(agent, {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
threadId: body.threadId,
|
|
39
|
+
...parsed.value,
|
|
40
|
+
signal: abortController.signal,
|
|
36
41
|
});
|
|
37
42
|
const response = {
|
|
38
43
|
output: result.output,
|
|
@@ -47,55 +52,54 @@ export function createAgentRoutes() {
|
|
|
47
52
|
ctx.body = response;
|
|
48
53
|
}
|
|
49
54
|
catch (error) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
if (abortController.signal.aborted)
|
|
56
|
+
return;
|
|
57
|
+
const { status, body } = resolveError(error, 'Agent run error');
|
|
58
|
+
ctx.status = status;
|
|
59
|
+
ctx.body = body;
|
|
53
60
|
}
|
|
54
61
|
});
|
|
55
62
|
router.post('/agents/:name/stream', async (ctx) => {
|
|
56
63
|
const { agents, runtime } = ctx.state.cogitator;
|
|
57
64
|
const { name } = ctx.params;
|
|
58
|
-
const agent = agents
|
|
65
|
+
const agent = getOwn(agents, name);
|
|
59
66
|
if (!agent) {
|
|
60
67
|
ctx.status = 404;
|
|
61
68
|
ctx.body = { error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' } };
|
|
62
69
|
return;
|
|
63
70
|
}
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
71
|
+
const parsed = parseAgentRunRequest(getRequestBody(ctx));
|
|
72
|
+
if (!parsed.ok) {
|
|
66
73
|
ctx.status = 400;
|
|
67
|
-
ctx.body = { error: { message:
|
|
74
|
+
ctx.body = { error: { message: parsed.message, code: 'INVALID_INPUT' } };
|
|
68
75
|
return;
|
|
69
76
|
}
|
|
70
77
|
setupSSEHeaders(ctx);
|
|
71
78
|
const writer = new KoaStreamWriter(ctx);
|
|
72
79
|
const messageId = generateId('msg');
|
|
73
|
-
|
|
80
|
+
const textId = generateId('txt');
|
|
81
|
+
const abortController = new AbortController();
|
|
82
|
+
onClientDisconnect(ctx, () => {
|
|
74
83
|
writer.close();
|
|
84
|
+
abortController.abort();
|
|
75
85
|
});
|
|
76
|
-
|
|
77
|
-
|
|
86
|
+
writer.start(messageId);
|
|
87
|
+
writer.textStart(textId);
|
|
78
88
|
try {
|
|
79
|
-
writer.start(messageId);
|
|
80
|
-
textId = generateId('txt');
|
|
81
|
-
textStarted = true;
|
|
82
|
-
writer.textStart(textId);
|
|
83
89
|
const result = await runtime.run(agent, {
|
|
84
|
-
|
|
85
|
-
context: body.context,
|
|
86
|
-
threadId: body.threadId,
|
|
90
|
+
...parsed.value,
|
|
87
91
|
stream: true,
|
|
92
|
+
signal: abortController.signal,
|
|
88
93
|
onToken: (token) => {
|
|
89
94
|
writer.textDelta(textId, token);
|
|
90
95
|
},
|
|
91
96
|
onToolCall: (toolCall) => {
|
|
92
|
-
|
|
93
|
-
writer.
|
|
94
|
-
writer.toolCallEnd(
|
|
97
|
+
writer.toolCallStart(toolCall.id, toolCall.name);
|
|
98
|
+
writer.toolCallDelta(toolCall.id, JSON.stringify(toolCall.arguments));
|
|
99
|
+
writer.toolCallEnd(toolCall.id);
|
|
95
100
|
},
|
|
96
101
|
onToolResult: (toolResult) => {
|
|
97
|
-
|
|
98
|
-
writer.toolResult(resultId, toolResult.callId, toolResult.result);
|
|
102
|
+
writer.toolResult(generateId('res'), toolResult.callId, toolResult.result);
|
|
99
103
|
},
|
|
100
104
|
});
|
|
101
105
|
writer.textEnd(textId);
|
|
@@ -106,11 +110,11 @@ export function createAgentRoutes() {
|
|
|
106
110
|
});
|
|
107
111
|
}
|
|
108
112
|
catch (error) {
|
|
109
|
-
if (
|
|
113
|
+
if (!abortController.signal.aborted) {
|
|
110
114
|
writer.textEnd(textId);
|
|
115
|
+
const { body } = resolveError(error, 'Agent stream error');
|
|
116
|
+
writer.error(body.error.message, body.error.code);
|
|
111
117
|
}
|
|
112
|
-
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
113
|
-
writer.error(message, 'INTERNAL');
|
|
114
118
|
}
|
|
115
119
|
finally {
|
|
116
120
|
writer.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;
|
|
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,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"swarms.d.ts","sourceRoot":"","sources":["../../src/routes/swarms.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,aAAa,CAAC;AAUzF,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,cAAc,CAAC,CAqL1D"}
|