@cogitator-ai/hono 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 +67 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +3 -1
- 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 +1 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/body-limit.d.ts +5 -0
- package/dist/middleware/body-limit.d.ts.map +1 -0
- package/dist/middleware/body-limit.js +9 -0
- package/dist/middleware/body-limit.js.map +1 -0
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +7 -3
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +43 -56
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/swarms.d.ts.map +1 -1
- package/dist/routes/swarms.js +50 -71
- package/dist/routes/swarms.js.map +1 -1
- package/dist/routes/threads.d.ts.map +1 -1
- package/dist/routes/threads.js +35 -53
- package/dist/routes/threads.js.map +1 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/routes/workflows.js +53 -45
- package/dist/routes/workflows.js.map +1 -1
- package/dist/streaming/hono-stream-writer.d.ts +0 -1
- package/dist/streaming/hono-stream-writer.d.ts.map +1 -1
- package/dist/streaming/hono-stream-writer.js +0 -10
- package/dist/streaming/hono-stream-writer.js.map +1 -1
- package/dist/types.d.ts +19 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +11 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +28 -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 +15 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +37 -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 +4 -12
- package/dist/websocket/handler.d.ts.map +1 -1
- package/dist/websocket/handler.js +204 -131
- package/dist/websocket/handler.js.map +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -49,8 +49,20 @@ Creates a Hono sub-application with all Cogitator endpoints.
|
|
|
49
49
|
| `auth` | `(c: Context) => AuthContext` | Authentication function (receives Hono Context) |
|
|
50
50
|
| `enableSwagger` | `boolean` | Enable Swagger/OpenAPI docs |
|
|
51
51
|
| `swagger` | `SwaggerConfig` | Swagger configuration |
|
|
52
|
-
| `enableWebSocket` | `boolean` | Enable WebSocket
|
|
53
|
-
| `websocket` | `WebSocketConfig` | WebSocket configuration
|
|
52
|
+
| `enableWebSocket` | `boolean` | Enable the WebSocket endpoint |
|
|
53
|
+
| `websocket` | `WebSocketConfig` | WebSocket configuration (see below) |
|
|
54
|
+
| `bodyLimit` | `number` | Max request body size in bytes (default 1 MiB) |
|
|
55
|
+
|
|
56
|
+
## Request Handling
|
|
57
|
+
|
|
58
|
+
- 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.
|
|
59
|
+
- 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`.
|
|
60
|
+
- Thread messages accept `role` of `user`, `assistant` or `system`; `metadata` is stored with the entry and a token estimate is recorded.
|
|
61
|
+
- Bodies above `bodyLimit` return `413 PAYLOAD_TOO_LARGE`.
|
|
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.
|
|
54
66
|
|
|
55
67
|
## Endpoints
|
|
56
68
|
|
|
@@ -130,6 +142,51 @@ Deno.serve(app.fetch);
|
|
|
130
142
|
|
|
131
143
|
The adapter uses Hono's built-in `streamSSE` for Server-Sent Events — no raw response manipulation needed. Works across all runtimes.
|
|
132
144
|
|
|
145
|
+
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.
|
|
146
|
+
|
|
147
|
+
## WebSocket
|
|
148
|
+
|
|
149
|
+
WebSocket upgrades are runtime-specific in Hono, so pass the `upgradeWebSocket` helper of your runtime. The endpoint goes through the same middleware as the REST routes, including `auth`.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { serve } from '@hono/node-server';
|
|
153
|
+
import { createNodeWebSocket } from '@hono/node-ws';
|
|
154
|
+
|
|
155
|
+
const app = new Hono();
|
|
156
|
+
const { upgradeWebSocket, injectWebSocket } = createNodeWebSocket({ app });
|
|
157
|
+
|
|
158
|
+
app.route(
|
|
159
|
+
'/cogitator',
|
|
160
|
+
cogitatorApp({
|
|
161
|
+
cogitator,
|
|
162
|
+
agents: { chat: chatAgent },
|
|
163
|
+
enableWebSocket: true,
|
|
164
|
+
websocket: { path: '/ws', upgradeWebSocket, maxPayloadSize: 1024 * 1024 },
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const server = serve({ fetch: app.fetch, port: 3000 });
|
|
169
|
+
injectWebSocket(server);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
On Bun use `upgradeWebSocket` from `hono/bun`, on Deno from `hono/deno`, on Cloudflare Workers from `hono/cloudflare-workers`. Without `upgradeWebSocket` the endpoint answers `501 UNIMPLEMENTED`.
|
|
173
|
+
|
|
174
|
+
**Protocol:**
|
|
175
|
+
|
|
176
|
+
| Client sends | Payload |
|
|
177
|
+
| ------------ | ------------------------------------------------------------------------------ |
|
|
178
|
+
| `run` | `{ type: 'agent' \| 'workflow' \| 'swarm', name, input, context?, threadId? }` |
|
|
179
|
+
| `stop` | Cancels the current run |
|
|
180
|
+
| `ping` | Answered with `pong` (echoes `id`) |
|
|
181
|
+
|
|
182
|
+
| Server sends | Description |
|
|
183
|
+
| ------------ | ----------------------------------------------------------------------------------------- |
|
|
184
|
+
| `event` | `token`, `tool-call`, `tool-result`, `complete` (with the serialized result), `cancelled` |
|
|
185
|
+
| `error` | Invalid message, unknown resource, run already in progress, or a masked run failure |
|
|
186
|
+
| `pong` | Heartbeat reply |
|
|
187
|
+
|
|
188
|
+
Messages larger than `maxPayloadSize` are rejected and the socket is closed with code `1009`. Closing the socket aborts the active run. `handleWebSocketMessage` and `createClientState` are exported for custom WebSocket integrations.
|
|
189
|
+
|
|
133
190
|
## Individual Route Access
|
|
134
191
|
|
|
135
192
|
```typescript
|
|
@@ -137,7 +194,15 @@ import {
|
|
|
137
194
|
createAgentRoutes,
|
|
138
195
|
createThreadRoutes,
|
|
139
196
|
createToolRoutes,
|
|
197
|
+
createWorkflowRoutes,
|
|
198
|
+
createSwarmRoutes,
|
|
140
199
|
createHealthRoutes,
|
|
200
|
+
createSwaggerRoutes,
|
|
201
|
+
createWebSocketRoutes,
|
|
202
|
+
createContextMiddleware,
|
|
203
|
+
createAuthMiddleware,
|
|
204
|
+
createBodyLimitMiddleware,
|
|
205
|
+
errorHandler,
|
|
141
206
|
} from '@cogitator-ai/hono';
|
|
142
207
|
```
|
|
143
208
|
|
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,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAgB/D,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,CA4BrE"}
|
package/dist/app.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
2
|
import { createContextMiddleware } from './middleware/context.js';
|
|
3
3
|
import { createAuthMiddleware } from './middleware/auth.js';
|
|
4
|
+
import { createBodyLimitMiddleware } from './middleware/body-limit.js';
|
|
4
5
|
import { errorHandler } from './middleware/error-handler.js';
|
|
5
6
|
import { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
|
|
6
7
|
import { createSwaggerRoutes } from './swagger/index.js';
|
|
@@ -8,6 +9,7 @@ import { createWebSocketRoutes } from './websocket/handler.js';
|
|
|
8
9
|
export function cogitatorApp(opts) {
|
|
9
10
|
const app = new Hono();
|
|
10
11
|
app.use('*', createContextMiddleware(opts));
|
|
12
|
+
app.use('*', createBodyLimitMiddleware(opts.bodyLimit));
|
|
11
13
|
if (opts.auth) {
|
|
12
14
|
app.use('*', createAuthMiddleware(opts.auth));
|
|
13
15
|
}
|
|
@@ -21,7 +23,7 @@ export function cogitatorApp(opts) {
|
|
|
21
23
|
app.route('/', createSwaggerRoutes(opts.swagger));
|
|
22
24
|
}
|
|
23
25
|
if (opts.enableWebSocket) {
|
|
24
|
-
app.route('/', createWebSocketRoutes(opts.websocket
|
|
26
|
+
app.route('/', createWebSocketRoutes(opts.websocket));
|
|
25
27
|
}
|
|
26
28
|
app.onError(errorHandler);
|
|
27
29
|
return app;
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,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,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAW,CAAC;IAEhC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,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,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAW,CAAC;IAEhC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,yBAAyB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAExD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACrC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACpC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACrC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACnC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,oBAAoB,EAAE,CAAC,CAAC;IACvC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAEpC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE1B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
export { cogitatorApp } from './app.js';
|
|
2
|
-
export type { CogitatorAppOptions, CogitatorContext, HonoEnv, AuthContext, AuthFunction, 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 { CogitatorAppOptions, CogitatorContext, HonoEnv, AuthContext, AuthFunction, WebSocketConfig, AgentListResponse, AgentRunRequest, AgentRunResponse, ThreadResponse, AddMessageRequest, ToolListResponse, WorkflowListResponse, WorkflowRunRequest, WorkflowRunResponse, WorkflowStatusResponse, SwarmListResponse, SwarmRunRequest, SwarmRunResponse, BlackboardResponse, HealthResponse, ErrorResponse, SwaggerConfig, WebSocketMessage, WebSocketResponse, WebSocketRunPayload, WebSocketClientState, WebSocketLike, } from './types.js';
|
|
3
3
|
export { HonoStreamWriter } from './streaming/hono-stream-writer.js';
|
|
4
4
|
export { createContextMiddleware } from './middleware/context.js';
|
|
5
5
|
export { createAuthMiddleware } from './middleware/auth.js';
|
|
6
6
|
export { errorHandler } from './middleware/error-handler.js';
|
|
7
|
+
export { createBodyLimitMiddleware } from './middleware/body-limit.js';
|
|
7
8
|
export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
|
|
8
9
|
export { createSwaggerRoutes } from './swagger/index.js';
|
|
9
10
|
export { createWebSocketRoutes, handleWebSocketMessage, createClientState, } from './websocket/handler.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,mBAAmB,EACnB,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,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,mBAAmB,EACnB,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,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,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,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,EACL,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GACX,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export { HonoStreamWriter } from './streaming/hono-stream-writer.js';
|
|
|
3
3
|
export { createContextMiddleware } from './middleware/context.js';
|
|
4
4
|
export { createAuthMiddleware } from './middleware/auth.js';
|
|
5
5
|
export { errorHandler } from './middleware/error-handler.js';
|
|
6
|
+
export { createBodyLimitMiddleware } from './middleware/body-limit.js';
|
|
6
7
|
export { createHealthRoutes, createAgentRoutes, createThreadRoutes, createToolRoutes, createWorkflowRoutes, createSwarmRoutes, } from './routes/index.js';
|
|
7
8
|
export { createSwaggerRoutes } from './swagger/index.js';
|
|
8
9
|
export { createWebSocketRoutes, handleWebSocketMessage, createClientState, } from './websocket/handler.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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAiCxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAErE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,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,EACL,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GACX,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { HonoEnv } from '../types.js';
|
|
3
|
+
export declare const DEFAULT_BODY_LIMIT: number;
|
|
4
|
+
export declare function createBodyLimitMiddleware(maxSize?: number): MiddlewareHandler<HonoEnv>;
|
|
5
|
+
//# sourceMappingURL=body-limit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/body-limit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAE9C,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,MAA2B,GACnC,iBAAiB,CAAC,OAAO,CAAC,CAM5B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { bodyLimit } from 'hono/body-limit';
|
|
2
|
+
export const DEFAULT_BODY_LIMIT = 1024 * 1024;
|
|
3
|
+
export function createBodyLimitMiddleware(maxSize = DEFAULT_BODY_LIMIT) {
|
|
4
|
+
return bodyLimit({
|
|
5
|
+
maxSize,
|
|
6
|
+
onError: (c) => c.json({ error: { message: 'Payload too large', code: 'PAYLOAD_TOO_LARGE' } }, 413),
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=body-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-limit.js","sourceRoot":"","sources":["../../src/middleware/body-limit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,MAAM,UAAU,yBAAyB,CACvC,UAAkB,kBAAkB;IAEpC,OAAO,SAAS,CAAC;QACf,OAAO;QACP,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,GAAG,CAAC;KACtF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAGzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,OAAO,CAe9C,CAAC"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HTTPException } from 'hono/http-exception';
|
|
2
|
+
import { CogitatorError, ErrorCode } from '@cogitator-ai/types';
|
|
3
|
+
import { cogitatorErrorStatus } from '../utils/errors.js';
|
|
2
4
|
export const errorHandler = (err, c) => {
|
|
5
|
+
if (err instanceof HTTPException) {
|
|
6
|
+
return err.getResponse();
|
|
7
|
+
}
|
|
3
8
|
if (CogitatorError.isCogitatorError(err)) {
|
|
4
|
-
|
|
5
|
-
return c.json({ error: { message: err.message, code: err.code } }, statusCode);
|
|
9
|
+
return c.json({ error: { message: err.message, code: err.code } }, cogitatorErrorStatus(err));
|
|
6
10
|
}
|
|
7
11
|
console.error('[CogitatorHono] Unhandled error:', err);
|
|
8
12
|
return c.json({ error: { message: 'Internal server error', code: ErrorCode.INTERNAL_ERROR } }, 500);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/middleware/error-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,MAAM,YAAY,GAA0B,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;IAC5D,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;QACjC,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,cAAc,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,GAAG,CAAC,CAAC;IAEvD,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,EAC/E,GAAG,CACJ,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,aAAa,CAAC;AAchF,wBAAgB,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,CAwHjD"}
|
package/dist/routes/agents.js
CHANGED
|
@@ -2,15 +2,18 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import { streamSSE } from 'hono/streaming';
|
|
3
3
|
import { generateId } from '@cogitator-ai/server-shared';
|
|
4
4
|
import { HonoStreamWriter } from '../streaming/hono-stream-writer.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getOwn } from '../utils/lookup.js';
|
|
6
|
+
import { resolveError } from '../utils/errors.js';
|
|
7
|
+
import { createRequestAbortController, errorResponse, invalidInput, invalidJson, readJsonBody, requestAborted, } from '../utils/request.js';
|
|
8
|
+
import { parseAgentRunRequest } from '../utils/validation.js';
|
|
6
9
|
export function createAgentRoutes() {
|
|
7
10
|
const app = new Hono();
|
|
8
11
|
app.get('/agents', (c) => {
|
|
9
12
|
const ctx = c.get('cogitator');
|
|
10
13
|
const agentList = Object.entries(ctx.agents).map(([name, agent]) => ({
|
|
11
14
|
name,
|
|
12
|
-
description: agent.config.
|
|
13
|
-
tools: agent.config.tools?.map((t) => t.name)
|
|
15
|
+
description: agent.config.description,
|
|
16
|
+
tools: agent.config.tools?.map((t) => t.name) ?? [],
|
|
14
17
|
}));
|
|
15
18
|
const response = { agents: agentList };
|
|
16
19
|
return c.json(response);
|
|
@@ -18,25 +21,21 @@ export function createAgentRoutes() {
|
|
|
18
21
|
app.post('/agents/:name/run', async (c) => {
|
|
19
22
|
const ctx = c.get('cogitator');
|
|
20
23
|
const name = c.req.param('name');
|
|
21
|
-
const agent =
|
|
24
|
+
const agent = getOwn(ctx.agents, name);
|
|
22
25
|
if (!agent) {
|
|
23
26
|
return c.json({ error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' } }, 404);
|
|
24
27
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return c.
|
|
31
|
-
|
|
32
|
-
if (!body?.input) {
|
|
33
|
-
return c.json({ error: { message: 'Missing required field: input', code: 'INVALID_INPUT' } }, 400);
|
|
34
|
-
}
|
|
28
|
+
const body = await readJsonBody(c);
|
|
29
|
+
if (!body.ok)
|
|
30
|
+
return invalidJson(c);
|
|
31
|
+
const parsed = parseAgentRunRequest(body.value);
|
|
32
|
+
if (!parsed.ok)
|
|
33
|
+
return invalidInput(c, parsed.message);
|
|
34
|
+
const abortController = createRequestAbortController(c);
|
|
35
35
|
try {
|
|
36
36
|
const result = await ctx.runtime.run(agent, {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
threadId: body.threadId,
|
|
37
|
+
...parsed.value,
|
|
38
|
+
signal: abortController.signal,
|
|
40
39
|
});
|
|
41
40
|
const response = {
|
|
42
41
|
output: result.output,
|
|
@@ -51,57 +50,50 @@ export function createAgentRoutes() {
|
|
|
51
50
|
return c.json(response);
|
|
52
51
|
}
|
|
53
52
|
catch (error) {
|
|
54
|
-
if (
|
|
55
|
-
return c
|
|
56
|
-
|
|
57
|
-
console.error('[CogitatorHono] Agent run error:', error);
|
|
58
|
-
return c.json({ error: { message: 'Internal server error', code: 'INTERNAL' } }, 500);
|
|
53
|
+
if (abortController.signal.aborted)
|
|
54
|
+
return requestAborted(c);
|
|
55
|
+
return errorResponse(c, error, 'Agent run error');
|
|
59
56
|
}
|
|
60
57
|
});
|
|
61
58
|
app.post('/agents/:name/stream', async (c) => {
|
|
62
59
|
const ctx = c.get('cogitator');
|
|
63
60
|
const name = c.req.param('name');
|
|
64
|
-
const agent =
|
|
61
|
+
const agent = getOwn(ctx.agents, name);
|
|
65
62
|
if (!agent) {
|
|
66
63
|
return c.json({ error: { message: `Agent '${name}' not found`, code: 'NOT_FOUND' } }, 404);
|
|
67
64
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return c.
|
|
74
|
-
|
|
75
|
-
if (!body?.input) {
|
|
76
|
-
return c.json({ error: { message: 'Missing required field: input', code: 'INVALID_INPUT' } }, 400);
|
|
77
|
-
}
|
|
65
|
+
const body = await readJsonBody(c);
|
|
66
|
+
if (!body.ok)
|
|
67
|
+
return invalidJson(c);
|
|
68
|
+
const parsed = parseAgentRunRequest(body.value);
|
|
69
|
+
if (!parsed.ok)
|
|
70
|
+
return invalidInput(c, parsed.message);
|
|
71
|
+
const abortController = createRequestAbortController(c);
|
|
78
72
|
return streamSSE(c, async (stream) => {
|
|
79
73
|
const writer = new HonoStreamWriter(stream);
|
|
80
74
|
const messageId = generateId('msg');
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
const textId = generateId('txt');
|
|
76
|
+
stream.onAbort(() => {
|
|
77
|
+
writer.close();
|
|
78
|
+
abortController.abort();
|
|
79
|
+
});
|
|
84
80
|
try {
|
|
85
81
|
await writer.start(messageId);
|
|
86
|
-
textId = generateId('txt');
|
|
87
|
-
textStarted = true;
|
|
88
82
|
await writer.textStart(textId);
|
|
89
83
|
const result = await ctx.runtime.run(agent, {
|
|
90
|
-
|
|
91
|
-
context: body.context,
|
|
92
|
-
threadId: body.threadId,
|
|
84
|
+
...parsed.value,
|
|
93
85
|
stream: true,
|
|
86
|
+
signal: abortController.signal,
|
|
94
87
|
onToken: (token) => {
|
|
95
88
|
void writer.textDelta(textId, token);
|
|
96
89
|
},
|
|
97
90
|
onToolCall: (toolCall) => {
|
|
98
|
-
|
|
99
|
-
void writer.
|
|
100
|
-
void writer.toolCallEnd(
|
|
91
|
+
void writer.toolCallStart(toolCall.id, toolCall.name);
|
|
92
|
+
void writer.toolCallDelta(toolCall.id, JSON.stringify(toolCall.arguments));
|
|
93
|
+
void writer.toolCallEnd(toolCall.id);
|
|
101
94
|
},
|
|
102
95
|
onToolResult: (toolResult) => {
|
|
103
|
-
|
|
104
|
-
void writer.toolResult(resultId, toolResult.callId, toolResult.result);
|
|
96
|
+
void writer.toolResult(generateId('res'), toolResult.callId, toolResult.result);
|
|
105
97
|
},
|
|
106
98
|
});
|
|
107
99
|
await writer.textEnd(textId);
|
|
@@ -112,16 +104,11 @@ export function createAgentRoutes() {
|
|
|
112
104
|
});
|
|
113
105
|
}
|
|
114
106
|
catch (error) {
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
console.error('[CogitatorHono] Agent stream error:', error);
|
|
123
|
-
await writer.error('Internal server error', 'INTERNAL');
|
|
124
|
-
}
|
|
107
|
+
if (abortController.signal.aborted)
|
|
108
|
+
return;
|
|
109
|
+
await writer.textEnd(textId);
|
|
110
|
+
const { body: errorBody } = resolveError(error, 'Agent stream error');
|
|
111
|
+
await writer.error(errorBody.error.message, errorBody.error.code);
|
|
125
112
|
}
|
|
126
113
|
finally {
|
|
127
114
|
writer.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/routes/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,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,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"swarms.d.ts","sourceRoot":"","sources":["../../src/routes/swarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,OAAO,EAAyC,MAAM,aAAa,CAAC;AAelF,wBAAgB,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,CA+JjD"}
|
package/dist/routes/swarms.js
CHANGED
|
@@ -2,7 +2,11 @@ import { Hono } from 'hono';
|
|
|
2
2
|
import { streamSSE } from 'hono/streaming';
|
|
3
3
|
import { generateId } from '@cogitator-ai/server-shared';
|
|
4
4
|
import { HonoStreamWriter } from '../streaming/hono-stream-writer.js';
|
|
5
|
-
import {
|
|
5
|
+
import { getOwn } from '../utils/lookup.js';
|
|
6
|
+
import { isModuleNotFoundError, resolveError } from '../utils/errors.js';
|
|
7
|
+
import { createRequestAbortController, errorResponse, invalidInput, invalidJson, readJsonBody, requestAborted, } from '../utils/request.js';
|
|
8
|
+
import { serializeSwarmUsage, toSwarmRunResponse } from '../utils/results.js';
|
|
9
|
+
import { parseSwarmRunRequest } from '../utils/validation.js';
|
|
6
10
|
export function createSwarmRoutes() {
|
|
7
11
|
const app = new Hono();
|
|
8
12
|
app.get('/swarms', (c) => {
|
|
@@ -25,92 +29,67 @@ export function createSwarmRoutes() {
|
|
|
25
29
|
app.post('/swarms/:name/run', async (c) => {
|
|
26
30
|
const ctx = c.get('cogitator');
|
|
27
31
|
const name = c.req.param('name');
|
|
28
|
-
const swarmConfig =
|
|
32
|
+
const swarmConfig = getOwn(ctx.swarms, name);
|
|
29
33
|
if (!swarmConfig) {
|
|
30
34
|
return c.json({ error: { message: `Swarm '${name}' not found`, code: 'NOT_FOUND' } }, 404);
|
|
31
35
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return c.
|
|
38
|
-
|
|
39
|
-
if (!body?.input) {
|
|
40
|
-
return c.json({ error: { message: 'Missing required field: input', code: 'INVALID_INPUT' } }, 400);
|
|
41
|
-
}
|
|
36
|
+
const body = await readJsonBody(c);
|
|
37
|
+
if (!body.ok)
|
|
38
|
+
return invalidJson(c);
|
|
39
|
+
const parsed = parseSwarmRunRequest(body.value);
|
|
40
|
+
if (!parsed.ok)
|
|
41
|
+
return invalidInput(c, parsed.message);
|
|
42
|
+
const abortController = createRequestAbortController(c);
|
|
42
43
|
try {
|
|
43
44
|
const { Swarm } = await import('@cogitator-ai/swarms');
|
|
44
45
|
const swarm = new Swarm(ctx.runtime, swarmConfig);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
for (const [agentName, agentResult] of result.agentResults.entries()) {
|
|
53
|
-
agentResults[agentName] = {
|
|
54
|
-
output: agentResult.output,
|
|
55
|
-
usage: agentResult.usage,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
const resourceUsage = swarm.getResourceUsage();
|
|
59
|
-
const response = {
|
|
60
|
-
swarmId: swarm.id,
|
|
61
|
-
swarmName: swarm.name,
|
|
62
|
-
strategy: swarm.strategyType,
|
|
63
|
-
output: result.output,
|
|
64
|
-
agentResults,
|
|
65
|
-
usage: {
|
|
66
|
-
totalTokens: resourceUsage.totalTokens,
|
|
67
|
-
totalCost: resourceUsage.totalCost,
|
|
68
|
-
elapsedTime: resourceUsage.elapsedTime,
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
return c.json(response);
|
|
46
|
+
if (abortController.signal.aborted)
|
|
47
|
+
return requestAborted(c);
|
|
48
|
+
abortController.signal.addEventListener('abort', () => swarm.abort(), { once: true });
|
|
49
|
+
const result = await swarm.run(parsed.value);
|
|
50
|
+
if (abortController.signal.aborted)
|
|
51
|
+
return requestAborted(c);
|
|
52
|
+
return c.json(toSwarmRunResponse(swarm, result));
|
|
72
53
|
}
|
|
73
54
|
catch (error) {
|
|
74
|
-
if (
|
|
55
|
+
if (abortController.signal.aborted)
|
|
56
|
+
return requestAborted(c);
|
|
57
|
+
if (isModuleNotFoundError(error)) {
|
|
75
58
|
return c.json({ error: { message: 'Swarms package not installed', code: 'UNIMPLEMENTED' } }, 501);
|
|
76
59
|
}
|
|
77
|
-
|
|
78
|
-
return c.json({ error: { message: error.message, code: error.code } }, 500);
|
|
79
|
-
}
|
|
80
|
-
console.error('[CogitatorHono] Swarm run error:', error);
|
|
81
|
-
return c.json({ error: { message: 'Internal server error', code: 'INTERNAL' } }, 500);
|
|
60
|
+
return errorResponse(c, error, 'Swarm run error');
|
|
82
61
|
}
|
|
83
62
|
});
|
|
84
63
|
app.post('/swarms/:name/stream', async (c) => {
|
|
85
64
|
const ctx = c.get('cogitator');
|
|
86
65
|
const name = c.req.param('name');
|
|
87
|
-
const swarmConfig =
|
|
66
|
+
const swarmConfig = getOwn(ctx.swarms, name);
|
|
88
67
|
if (!swarmConfig) {
|
|
89
68
|
return c.json({ error: { message: `Swarm '${name}' not found`, code: 'NOT_FOUND' } }, 404);
|
|
90
69
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return c.
|
|
97
|
-
|
|
98
|
-
if (!body?.input) {
|
|
99
|
-
return c.json({ error: { message: 'Missing required field: input', code: 'INVALID_INPUT' } }, 400);
|
|
100
|
-
}
|
|
70
|
+
const body = await readJsonBody(c);
|
|
71
|
+
if (!body.ok)
|
|
72
|
+
return invalidJson(c);
|
|
73
|
+
const parsed = parseSwarmRunRequest(body.value);
|
|
74
|
+
if (!parsed.ok)
|
|
75
|
+
return invalidInput(c, parsed.message);
|
|
76
|
+
const abortController = createRequestAbortController(c);
|
|
101
77
|
return streamSSE(c, async (stream) => {
|
|
102
78
|
const writer = new HonoStreamWriter(stream);
|
|
103
79
|
const messageId = generateId('swarm');
|
|
104
|
-
stream.onAbort(() =>
|
|
80
|
+
stream.onAbort(() => {
|
|
81
|
+
writer.close();
|
|
82
|
+
abortController.abort();
|
|
83
|
+
});
|
|
105
84
|
try {
|
|
106
85
|
const { Swarm } = await import('@cogitator-ai/swarms');
|
|
107
86
|
const swarm = new Swarm(ctx.runtime, swarmConfig);
|
|
87
|
+
if (abortController.signal.aborted)
|
|
88
|
+
return;
|
|
89
|
+
abortController.signal.addEventListener('abort', () => swarm.abort(), { once: true });
|
|
108
90
|
await writer.start(messageId);
|
|
109
91
|
const result = await swarm.run({
|
|
110
|
-
|
|
111
|
-
context: body.context,
|
|
112
|
-
threadId: body.threadId,
|
|
113
|
-
timeout: body.timeout,
|
|
92
|
+
...parsed.value,
|
|
114
93
|
onAgentStart: (agentName) => {
|
|
115
94
|
void writer.swarmEvent('agent_start', { agentName, timestamp: Date.now() });
|
|
116
95
|
},
|
|
@@ -131,24 +110,24 @@ export function createSwarmRoutes() {
|
|
|
131
110
|
void writer.swarmEvent(event.type, event.data);
|
|
132
111
|
},
|
|
133
112
|
});
|
|
134
|
-
|
|
113
|
+
if (abortController.signal.aborted)
|
|
114
|
+
return;
|
|
135
115
|
await writer.swarmEvent('swarm_completed', {
|
|
136
116
|
swarmId: swarm.id,
|
|
137
117
|
output: result.output,
|
|
138
|
-
usage:
|
|
118
|
+
usage: serializeSwarmUsage(swarm.getResourceUsage()),
|
|
139
119
|
});
|
|
140
120
|
await writer.finish(messageId);
|
|
141
121
|
}
|
|
142
122
|
catch (error) {
|
|
143
|
-
if (
|
|
123
|
+
if (abortController.signal.aborted)
|
|
124
|
+
return;
|
|
125
|
+
if (isModuleNotFoundError(error)) {
|
|
144
126
|
await writer.error('Swarms package not installed', 'UNIMPLEMENTED');
|
|
145
127
|
}
|
|
146
|
-
else if (CogitatorError.isCogitatorError(error)) {
|
|
147
|
-
await writer.error(error.message, error.code);
|
|
148
|
-
}
|
|
149
128
|
else {
|
|
150
|
-
|
|
151
|
-
await writer.error(
|
|
129
|
+
const { body: errorBody } = resolveError(error, 'Swarm stream error');
|
|
130
|
+
await writer.error(errorBody.error.message, errorBody.error.code);
|
|
152
131
|
}
|
|
153
132
|
}
|
|
154
133
|
finally {
|
|
@@ -159,7 +138,7 @@ export function createSwarmRoutes() {
|
|
|
159
138
|
app.get('/swarms/:name/blackboard', (c) => {
|
|
160
139
|
const ctx = c.get('cogitator');
|
|
161
140
|
const name = c.req.param('name');
|
|
162
|
-
const swarmConfig =
|
|
141
|
+
const swarmConfig = getOwn(ctx.swarms, name);
|
|
163
142
|
if (!swarmConfig) {
|
|
164
143
|
return c.json({ error: { message: `Swarm '${name}' not found`, code: 'NOT_FOUND' } }, 404);
|
|
165
144
|
}
|
|
@@ -167,7 +146,7 @@ export function createSwarmRoutes() {
|
|
|
167
146
|
return c.json({ error: { message: 'Blackboard not enabled for this swarm', code: 'INVALID_INPUT' } }, 400);
|
|
168
147
|
}
|
|
169
148
|
const response = {
|
|
170
|
-
sections: swarmConfig.blackboard.sections
|
|
149
|
+
sections: swarmConfig.blackboard.sections ?? {},
|
|
171
150
|
};
|
|
172
151
|
return c.json(response);
|
|
173
152
|
});
|