@agentick/gateway 0.0.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/LICENSE +21 -0
- package/README.md +477 -0
- package/dist/agent-registry.d.ts +51 -0
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js +78 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/app-registry.d.ts +51 -0
- package/dist/app-registry.d.ts.map +1 -0
- package/dist/app-registry.js +78 -0
- package/dist/app-registry.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +37 -0
- package/dist/bin.js.map +1 -0
- package/dist/gateway.d.ts +165 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +1339 -0
- package/dist/gateway.js.map +1 -0
- package/dist/http-transport.d.ts +65 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +517 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +162 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +16 -0
- package/dist/protocol.js.map +1 -0
- package/dist/session-manager.d.ts +101 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +208 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/testing.d.ts +92 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +129 -0
- package/dist/testing.js.map +1 -0
- package/dist/transport-protocol.d.ts +162 -0
- package/dist/transport-protocol.d.ts.map +1 -0
- package/dist/transport-protocol.js +16 -0
- package/dist/transport-protocol.js.map +1 -0
- package/dist/transport.d.ts +115 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +56 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +314 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/types.js.map +1 -0
- package/dist/websocket-server.d.ts +87 -0
- package/dist/websocket-server.d.ts.map +1 -0
- package/dist/websocket-server.js +245 -0
- package/dist/websocket-server.js.map +1 -0
- package/dist/ws-transport.d.ts +17 -0
- package/dist/ws-transport.d.ts.map +1 -0
- package/dist/ws-transport.js +174 -0
- package/dist/ws-transport.js.map +1 -0
- package/package.json +51 -0
- package/src/__tests__/custom-methods.spec.ts +220 -0
- package/src/__tests__/gateway-methods.spec.ts +262 -0
- package/src/__tests__/gateway.spec.ts +404 -0
- package/src/__tests__/guards.spec.ts +235 -0
- package/src/__tests__/protocol.spec.ts +58 -0
- package/src/__tests__/session-manager.spec.ts +220 -0
- package/src/__tests__/ws-transport.spec.ts +246 -0
- package/src/app-registry.ts +103 -0
- package/src/bin.ts +38 -0
- package/src/gateway.ts +1712 -0
- package/src/http-transport.ts +623 -0
- package/src/index.ts +94 -0
- package/src/session-manager.ts +272 -0
- package/src/testing.ts +236 -0
- package/src/transport-protocol.ts +249 -0
- package/src/transport.ts +191 -0
- package/src/types.ts +392 -0
- package/src/websocket-server.ts +303 -0
- package/src/ws-transport.ts +205 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Agentick Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# @agentick/gateway
|
|
2
|
+
|
|
3
|
+
Unified gateway for multi-client, multi-app Agentick access.
|
|
4
|
+
|
|
5
|
+
Gateway can run as a **standalone daemon** or be **embedded** into existing web frameworks like Express or NestJS.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @agentick/gateway
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @agentick/gateway
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Standalone Mode
|
|
18
|
+
|
|
19
|
+
Run Gateway as its own process with built-in HTTP/SSE transport:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { createGateway } from "@agentick/gateway";
|
|
23
|
+
import { createApp, Model, System, Timeline } from "@agentick/core";
|
|
24
|
+
|
|
25
|
+
const ChatApp = () => (
|
|
26
|
+
<>
|
|
27
|
+
<Model model={gpt4} />
|
|
28
|
+
<System>You are a helpful assistant.</System>
|
|
29
|
+
<Timeline />
|
|
30
|
+
</>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const gateway = createGateway({
|
|
34
|
+
port: 3000,
|
|
35
|
+
host: "127.0.0.1",
|
|
36
|
+
apps: {
|
|
37
|
+
chat: createApp(<ChatApp />),
|
|
38
|
+
},
|
|
39
|
+
defaultApp: "chat",
|
|
40
|
+
auth: {
|
|
41
|
+
type: "token",
|
|
42
|
+
token: process.env.GATEWAY_TOKEN,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
await gateway.start();
|
|
47
|
+
console.log("Gateway running on http://127.0.0.1:3000");
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Embedded Mode
|
|
51
|
+
|
|
52
|
+
Embed Gateway into an existing Express app (or other framework):
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import express from "express";
|
|
56
|
+
import { Gateway } from "@agentick/gateway";
|
|
57
|
+
|
|
58
|
+
const app = express();
|
|
59
|
+
app.use(express.json());
|
|
60
|
+
|
|
61
|
+
const gateway = new Gateway({
|
|
62
|
+
embedded: true, // Skip starting internal HTTP server
|
|
63
|
+
apps: { assistant: agentickApp },
|
|
64
|
+
defaultApp: "assistant",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Handle requests yourself
|
|
68
|
+
app.use("/api", (req, res) => {
|
|
69
|
+
gateway.handleRequest(req, res);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
app.listen(3000);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
For Express, use `@agentick/express` which wraps this pattern:
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { createAgentickMiddleware } from "@agentick/express";
|
|
79
|
+
|
|
80
|
+
const middleware = createAgentickMiddleware({
|
|
81
|
+
apps: { assistant: agentickApp },
|
|
82
|
+
defaultApp: "assistant",
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
app.use("/api", middleware);
|
|
86
|
+
|
|
87
|
+
// Access gateway for lifecycle management
|
|
88
|
+
await middleware.gateway.close();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Configuration
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface GatewayConfig {
|
|
95
|
+
// Server (standalone mode only)
|
|
96
|
+
port?: number; // Default: 18789
|
|
97
|
+
host?: string; // Default: "127.0.0.1"
|
|
98
|
+
id?: string; // Auto-generated if not provided
|
|
99
|
+
|
|
100
|
+
// Apps
|
|
101
|
+
apps: Record<string, AgentickApp>;
|
|
102
|
+
defaultApp: string;
|
|
103
|
+
|
|
104
|
+
// Mode
|
|
105
|
+
embedded?: boolean; // Skip transport init, use handleRequest()
|
|
106
|
+
|
|
107
|
+
// Authentication
|
|
108
|
+
auth?: AuthConfig;
|
|
109
|
+
|
|
110
|
+
// Custom methods
|
|
111
|
+
methods?: MethodsConfig;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Authentication
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// No auth (development)
|
|
119
|
+
auth: { type: "none" }
|
|
120
|
+
|
|
121
|
+
// Static token
|
|
122
|
+
auth: {
|
|
123
|
+
type: "token",
|
|
124
|
+
token: process.env.API_TOKEN,
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// JWT
|
|
128
|
+
auth: {
|
|
129
|
+
type: "jwt",
|
|
130
|
+
secret: process.env.JWT_SECRET,
|
|
131
|
+
issuer: "my-app", // Optional
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Custom validation
|
|
135
|
+
auth: {
|
|
136
|
+
type: "custom",
|
|
137
|
+
validate: async (token) => {
|
|
138
|
+
const decoded = await verifyToken(token);
|
|
139
|
+
return decoded
|
|
140
|
+
? { valid: true, user: { id: decoded.sub } }
|
|
141
|
+
: { valid: false };
|
|
142
|
+
},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// With user hydration (works with any auth type)
|
|
146
|
+
auth: {
|
|
147
|
+
type: "custom",
|
|
148
|
+
validate: async (token) => {
|
|
149
|
+
const decoded = await verifyJWT(token);
|
|
150
|
+
return { valid: true, user: { id: decoded.sub } };
|
|
151
|
+
},
|
|
152
|
+
hydrateUser: async (authResult) => {
|
|
153
|
+
// Enrich with database data
|
|
154
|
+
const dbUser = await db.users.findById(authResult.user.id);
|
|
155
|
+
return {
|
|
156
|
+
id: dbUser.id,
|
|
157
|
+
tenantId: dbUser.tenantId,
|
|
158
|
+
roles: dbUser.roles,
|
|
159
|
+
email: dbUser.email,
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Custom Methods
|
|
166
|
+
|
|
167
|
+
Define RPC-style methods that clients can invoke. Methods run within Agentick's context system with full access to user info, channels, and tracing.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { createGateway, method } from "@agentick/gateway";
|
|
171
|
+
import { Context } from "@agentick/kernel";
|
|
172
|
+
import { z } from "zod";
|
|
173
|
+
|
|
174
|
+
const gateway = createGateway({
|
|
175
|
+
apps: { assistant: agentickApp },
|
|
176
|
+
defaultApp: "assistant",
|
|
177
|
+
|
|
178
|
+
methods: {
|
|
179
|
+
// Simple method - no schema needed
|
|
180
|
+
ping: async () => ({ pong: true, timestamp: Date.now() }),
|
|
181
|
+
|
|
182
|
+
// Namespaced methods
|
|
183
|
+
tasks: {
|
|
184
|
+
// With Zod schema - params are typed!
|
|
185
|
+
list: method({
|
|
186
|
+
schema: z.object({
|
|
187
|
+
sessionId: z.string(),
|
|
188
|
+
completed: z.boolean().optional(),
|
|
189
|
+
}),
|
|
190
|
+
handler: async (params) => {
|
|
191
|
+
const ctx = Context.get();
|
|
192
|
+
return todoService.list(params.sessionId, {
|
|
193
|
+
userId: ctx.user?.id,
|
|
194
|
+
completed: params.completed,
|
|
195
|
+
});
|
|
196
|
+
},
|
|
197
|
+
}),
|
|
198
|
+
|
|
199
|
+
create: method({
|
|
200
|
+
schema: z.object({
|
|
201
|
+
sessionId: z.string(),
|
|
202
|
+
title: z.string().min(1),
|
|
203
|
+
priority: z.enum(["low", "medium", "high"]).optional(),
|
|
204
|
+
}),
|
|
205
|
+
handler: async (params) => {
|
|
206
|
+
const ctx = Context.get();
|
|
207
|
+
const task = await todoService.create({
|
|
208
|
+
title: params.title,
|
|
209
|
+
priority: params.priority,
|
|
210
|
+
userId: ctx.user?.id,
|
|
211
|
+
});
|
|
212
|
+
// Emit event for devtools/subscribers
|
|
213
|
+
Context.emit("task:created", { taskId: task.id });
|
|
214
|
+
return task;
|
|
215
|
+
},
|
|
216
|
+
}),
|
|
217
|
+
|
|
218
|
+
// Deeply nested namespaces
|
|
219
|
+
admin: {
|
|
220
|
+
archive: method({
|
|
221
|
+
roles: ["admin"], // Checked before handler
|
|
222
|
+
handler: async () => todoService.archiveAll(),
|
|
223
|
+
}),
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
// Role-protected methods
|
|
228
|
+
admin: {
|
|
229
|
+
stats: method({
|
|
230
|
+
roles: ["admin"],
|
|
231
|
+
handler: async () => {
|
|
232
|
+
const ctx = Context.get();
|
|
233
|
+
return adminService.getStats(ctx.user?.tenantId);
|
|
234
|
+
},
|
|
235
|
+
}),
|
|
236
|
+
|
|
237
|
+
// Custom guard function
|
|
238
|
+
dangerousAction: method({
|
|
239
|
+
guard: async () => {
|
|
240
|
+
const ctx = Context.get();
|
|
241
|
+
return ctx.user?.roles?.includes("superadmin") ?? false;
|
|
242
|
+
},
|
|
243
|
+
handler: async (params) => {
|
|
244
|
+
// Only superadmins reach here
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Method Definition Styles
|
|
253
|
+
|
|
254
|
+
| Style | Example | Wrapper? |
|
|
255
|
+
| --------------- | ---------------------------------------------- | -------- |
|
|
256
|
+
| Simple function | `async (params) => result` | No |
|
|
257
|
+
| With schema | `method({ schema: z.object({...}), handler })` | Yes |
|
|
258
|
+
| With guards | `method({ roles: ["admin"], handler })` | Yes |
|
|
259
|
+
| Namespace | `{ tasks: { list, create } }` | No |
|
|
260
|
+
| Deep namespace | `{ tasks: { admin: { archive } } }` | No |
|
|
261
|
+
|
|
262
|
+
Methods are invoked using colon-separated paths: `tasks:list`, `tasks:admin:archive`, `admin:stats`.
|
|
263
|
+
|
|
264
|
+
### Guard Errors
|
|
265
|
+
|
|
266
|
+
Role and custom guards throw `GuardError` (from `@agentick/kernel`) on denial. The gateway returns HTTP 403 for guard denials:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { isGuardError } from "@agentick/kernel";
|
|
270
|
+
|
|
271
|
+
// In your error handling
|
|
272
|
+
if (isGuardError(error)) {
|
|
273
|
+
error.code; // "GUARD_DENIED"
|
|
274
|
+
error.guardType; // "role" or "custom"
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## HTTP Endpoints
|
|
279
|
+
|
|
280
|
+
Gateway exposes these HTTP endpoints:
|
|
281
|
+
|
|
282
|
+
| Method | Path | Description |
|
|
283
|
+
| ------ | --------- | ----------------------------- |
|
|
284
|
+
| GET | `/events` | SSE stream for session events |
|
|
285
|
+
| POST | `/send` | Send message to session |
|
|
286
|
+
| POST | `/invoke` | Invoke custom method |
|
|
287
|
+
|
|
288
|
+
### SSE Events Stream
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Connect to events stream
|
|
292
|
+
const events = new EventSource("/events?sessionId=main&token=xxx");
|
|
293
|
+
|
|
294
|
+
// Execution events
|
|
295
|
+
events.addEventListener("content_delta", (e) => {
|
|
296
|
+
console.log("Content:", JSON.parse(e.data).delta);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
events.addEventListener("tool_use", (e) => {
|
|
300
|
+
console.log("Tool:", JSON.parse(e.data).name);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
events.addEventListener("message_end", () => {
|
|
304
|
+
console.log("Response complete");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Connection events
|
|
308
|
+
events.addEventListener("connected", (e) => {
|
|
309
|
+
console.log("Connected:", JSON.parse(e.data));
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Send Message
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
curl -X POST http://localhost:3000/send \
|
|
317
|
+
-H "Content-Type: application/json" \
|
|
318
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
319
|
+
-d '{"sessionId": "main", "message": "Hello!"}'
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Invoke Method
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
curl -X POST http://localhost:3000/invoke \
|
|
326
|
+
-H "Content-Type: application/json" \
|
|
327
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
328
|
+
-d '{"method": "tasks:list", "params": {"sessionId": "main"}}'
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Lifecycle
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
const gateway = createGateway({ ... });
|
|
335
|
+
|
|
336
|
+
// Start (standalone mode)
|
|
337
|
+
await gateway.start();
|
|
338
|
+
|
|
339
|
+
// Events
|
|
340
|
+
gateway.on("session:created", ({ sessionId }) => { ... });
|
|
341
|
+
gateway.on("session:closed", ({ sessionId }) => { ... });
|
|
342
|
+
gateway.on("client:connected", ({ clientId }) => { ... });
|
|
343
|
+
gateway.on("client:disconnected", ({ clientId }) => { ... });
|
|
344
|
+
|
|
345
|
+
// Graceful shutdown
|
|
346
|
+
await gateway.close();
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Client SDK
|
|
350
|
+
|
|
351
|
+
Use `@agentick/client` to connect to Gateway:
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import { createClient } from "@agentick/client";
|
|
355
|
+
|
|
356
|
+
const client = createClient({
|
|
357
|
+
baseUrl: "http://localhost:3000",
|
|
358
|
+
token: process.env.GATEWAY_TOKEN,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Get session
|
|
362
|
+
const session = client.session("main");
|
|
363
|
+
|
|
364
|
+
// Send message and stream response
|
|
365
|
+
const handle = session.send("Hello!");
|
|
366
|
+
for await (const event of handle) {
|
|
367
|
+
if (event.type === "content_delta") {
|
|
368
|
+
process.stdout.write(event.delta);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Invoke custom method
|
|
373
|
+
const tasks = await session.invoke("tasks:list");
|
|
374
|
+
const newTask = await session.invoke("tasks:create", {
|
|
375
|
+
title: "Buy groceries",
|
|
376
|
+
priority: "high",
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Architecture
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
┌────────────────────────────────────────────────────────────┐
|
|
384
|
+
│ GATEWAY │
|
|
385
|
+
│ │
|
|
386
|
+
│ ┌───────────────────────────────────────────────────────┐ │
|
|
387
|
+
│ │ HTTP Transport │ │
|
|
388
|
+
│ │ (SSE events + REST endpoints) │ │
|
|
389
|
+
│ └───────────────────────┬───────────────────────────────┘ │
|
|
390
|
+
│ │ │
|
|
391
|
+
│ ┌───────────────┼───────────────┐ │
|
|
392
|
+
│ │ │ │ │
|
|
393
|
+
│ ▼ ▼ ▼ │
|
|
394
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
395
|
+
│ │ Web UI │ │ CLI │ │ Mobile │ │
|
|
396
|
+
│ │ Client │ │ Client │ │ Client │ │
|
|
397
|
+
│ └──────────┘ └──────────┘ └──────────┘ │
|
|
398
|
+
│ │
|
|
399
|
+
├─────────────────────────────────────────────────────────────┤
|
|
400
|
+
│ │
|
|
401
|
+
│ ┌─────────────────────────────────────────────────────┐ │
|
|
402
|
+
│ │ App Registry │ │
|
|
403
|
+
│ ├─────────────┬─────────────┬─────────────────────────┤ │
|
|
404
|
+
│ │ chat │ research │ coder │ │
|
|
405
|
+
│ │ (app) │ (app) │ (app) │ │
|
|
406
|
+
│ └──────┬──────┴──────┬──────┴───────────┬─────────────┘ │
|
|
407
|
+
│ │ │ │ │
|
|
408
|
+
│ ┌──────┴─────────────┴──────────────────┴──────┐ │
|
|
409
|
+
│ │ Session Manager │ │
|
|
410
|
+
│ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │
|
|
411
|
+
│ │ │sess1│ │sess2│ │sess3│ ... │ │
|
|
412
|
+
│ │ └─────┘ └─────┘ └─────┘ │ │
|
|
413
|
+
│ └──────────────────────────────────────────────┘ │
|
|
414
|
+
│ │
|
|
415
|
+
│ ┌─────────────────────────────────────────────────────┐ │
|
|
416
|
+
│ │ Custom Methods │ │
|
|
417
|
+
│ │ tasks:list, tasks:create, admin:stats, ... │ │
|
|
418
|
+
│ └─────────────────────────────────────────────────────┘ │
|
|
419
|
+
│ │
|
|
420
|
+
└─────────────────────────────────────────────────────────────┘
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Standalone vs Embedded
|
|
424
|
+
|
|
425
|
+
| Feature | Standalone | Embedded |
|
|
426
|
+
| ------------------ | ------------------------- | --------------------------------------- |
|
|
427
|
+
| Config | `port`, `host` | `embedded: true` |
|
|
428
|
+
| Start | `gateway.start()` | N/A |
|
|
429
|
+
| Request handling | Built-in HTTP server | `gateway.handleRequest(req, res)` |
|
|
430
|
+
| Use case | Dedicated gateway process | Integrate with Express/NestJS |
|
|
431
|
+
| Framework packages | Not needed | `@agentick/express`, `@agentick/nestjs` |
|
|
432
|
+
|
|
433
|
+
## Context Access
|
|
434
|
+
|
|
435
|
+
Custom methods run within Agentick's ALS (Async Local Storage) context:
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
import { Context } from "@agentick/kernel";
|
|
439
|
+
|
|
440
|
+
methods: {
|
|
441
|
+
"tasks:create": async (params) => {
|
|
442
|
+
const ctx = Context.get();
|
|
443
|
+
|
|
444
|
+
// User info (from auth)
|
|
445
|
+
console.log(ctx.user?.id);
|
|
446
|
+
console.log(ctx.user?.roles);
|
|
447
|
+
console.log(ctx.user?.tenantId);
|
|
448
|
+
|
|
449
|
+
// Request metadata
|
|
450
|
+
console.log(ctx.metadata?.sessionId);
|
|
451
|
+
console.log(ctx.metadata?.clientId);
|
|
452
|
+
|
|
453
|
+
// Distributed tracing
|
|
454
|
+
console.log(ctx.traceId);
|
|
455
|
+
|
|
456
|
+
// Channel access (if session has channels)
|
|
457
|
+
ctx.channels?.publish("notifications", { type: "task_created" });
|
|
458
|
+
|
|
459
|
+
// Emit events (for devtools/subscribers)
|
|
460
|
+
Context.emit("custom:task:created", { title: params.title });
|
|
461
|
+
|
|
462
|
+
return todoService.create(params);
|
|
463
|
+
},
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Related Packages
|
|
468
|
+
|
|
469
|
+
- [`@agentick/express`](../express) - Express middleware (thin adapter)
|
|
470
|
+
- [`@agentick/nestjs`](../nestjs) - NestJS module (thin adapter)
|
|
471
|
+
- [`@agentick/core`](../core) - JSX runtime for apps
|
|
472
|
+
- [`@agentick/client`](../client) - Client SDK
|
|
473
|
+
- [`@agentick/server`](../server) - SSE utilities
|
|
474
|
+
|
|
475
|
+
## License
|
|
476
|
+
|
|
477
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages available agents and their configurations.
|
|
5
|
+
*/
|
|
6
|
+
import type { App } from "@tentickle/core";
|
|
7
|
+
export interface AgentInfo {
|
|
8
|
+
id: string;
|
|
9
|
+
app: App;
|
|
10
|
+
name?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
isDefault: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class AgentRegistry {
|
|
15
|
+
private agents;
|
|
16
|
+
private defaultAgentId;
|
|
17
|
+
constructor(agents: Record<string, App>, defaultAgent: string);
|
|
18
|
+
/**
|
|
19
|
+
* Get an agent by ID
|
|
20
|
+
*/
|
|
21
|
+
get(id: string): AgentInfo | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Get the default agent
|
|
24
|
+
*/
|
|
25
|
+
getDefault(): AgentInfo;
|
|
26
|
+
/**
|
|
27
|
+
* Get the default agent ID
|
|
28
|
+
*/
|
|
29
|
+
get defaultId(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Check if an agent exists
|
|
32
|
+
*/
|
|
33
|
+
has(id: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get all agent IDs
|
|
36
|
+
*/
|
|
37
|
+
ids(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Get all agents
|
|
40
|
+
*/
|
|
41
|
+
all(): AgentInfo[];
|
|
42
|
+
/**
|
|
43
|
+
* Get agent count
|
|
44
|
+
*/
|
|
45
|
+
get size(): number;
|
|
46
|
+
/**
|
|
47
|
+
* Resolve an agent ID, falling back to default
|
|
48
|
+
*/
|
|
49
|
+
resolve(id?: string): AgentInfo;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=agent-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../src/agent-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,YAAY,EAAE,MAAM;IAkB7D;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAItC;;OAEG;IACH,UAAU,IAAI,SAAS;IAIvB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;OAEG;IACH,GAAG,IAAI,MAAM,EAAE;IAIf;;OAEG;IACH,GAAG,IAAI,SAAS,EAAE;IAIlB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS;CAYhC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages available agents and their configurations.
|
|
5
|
+
*/
|
|
6
|
+
export class AgentRegistry {
|
|
7
|
+
agents = new Map();
|
|
8
|
+
defaultAgentId;
|
|
9
|
+
constructor(agents, defaultAgent) {
|
|
10
|
+
if (!agents[defaultAgent]) {
|
|
11
|
+
throw new Error(`Default agent "${defaultAgent}" not found in agents: ${Object.keys(agents).join(", ")}`);
|
|
12
|
+
}
|
|
13
|
+
this.defaultAgentId = defaultAgent;
|
|
14
|
+
for (const [id, app] of Object.entries(agents)) {
|
|
15
|
+
this.agents.set(id, {
|
|
16
|
+
id,
|
|
17
|
+
app,
|
|
18
|
+
isDefault: id === defaultAgent,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get an agent by ID
|
|
24
|
+
*/
|
|
25
|
+
get(id) {
|
|
26
|
+
return this.agents.get(id);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the default agent
|
|
30
|
+
*/
|
|
31
|
+
getDefault() {
|
|
32
|
+
return this.agents.get(this.defaultAgentId);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the default agent ID
|
|
36
|
+
*/
|
|
37
|
+
get defaultId() {
|
|
38
|
+
return this.defaultAgentId;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Check if an agent exists
|
|
42
|
+
*/
|
|
43
|
+
has(id) {
|
|
44
|
+
return this.agents.has(id);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get all agent IDs
|
|
48
|
+
*/
|
|
49
|
+
ids() {
|
|
50
|
+
return Array.from(this.agents.keys());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get all agents
|
|
54
|
+
*/
|
|
55
|
+
all() {
|
|
56
|
+
return Array.from(this.agents.values());
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get agent count
|
|
60
|
+
*/
|
|
61
|
+
get size() {
|
|
62
|
+
return this.agents.size;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Resolve an agent ID, falling back to default
|
|
66
|
+
*/
|
|
67
|
+
resolve(id) {
|
|
68
|
+
if (!id) {
|
|
69
|
+
return this.getDefault();
|
|
70
|
+
}
|
|
71
|
+
const agent = this.agents.get(id);
|
|
72
|
+
if (!agent) {
|
|
73
|
+
throw new Error(`Unknown agent "${id}". Available: ${this.ids().join(", ")}`);
|
|
74
|
+
}
|
|
75
|
+
return agent;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=agent-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.js","sourceRoot":"","sources":["../src/agent-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH,MAAM,OAAO,aAAa;IAChB,MAAM,GAAG,IAAI,GAAG,EAAqB,CAAC;IACtC,cAAc,CAAS;IAE/B,YAAY,MAA2B,EAAE,YAAoB;QAC3D,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,kBAAkB,YAAY,0BAA0B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,YAAY,CAAC;QAEnC,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE;gBAClB,EAAE;gBACF,GAAG;gBACH,SAAS,EAAE,EAAE,KAAK,YAAY;aAC/B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,GAAG;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,GAAG;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,EAAW;QACjB,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,kBAAkB,EAAE,iBAAiB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Registry
|
|
3
|
+
*
|
|
4
|
+
* Manages available apps and their configurations.
|
|
5
|
+
*/
|
|
6
|
+
import type { App } from "@agentick/core";
|
|
7
|
+
export interface AppInfo {
|
|
8
|
+
id: string;
|
|
9
|
+
app: App;
|
|
10
|
+
name?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
isDefault: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class AppRegistry {
|
|
15
|
+
private apps;
|
|
16
|
+
private defaultAppId;
|
|
17
|
+
constructor(apps: Record<string, App>, defaultApp: string);
|
|
18
|
+
/**
|
|
19
|
+
* Get an app by ID
|
|
20
|
+
*/
|
|
21
|
+
get(id: string): AppInfo | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Get the default app
|
|
24
|
+
*/
|
|
25
|
+
getDefault(): AppInfo;
|
|
26
|
+
/**
|
|
27
|
+
* Get the default app ID
|
|
28
|
+
*/
|
|
29
|
+
get defaultId(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Check if an app exists
|
|
32
|
+
*/
|
|
33
|
+
has(id: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get all app IDs
|
|
36
|
+
*/
|
|
37
|
+
ids(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Get all apps
|
|
40
|
+
*/
|
|
41
|
+
all(): AppInfo[];
|
|
42
|
+
/**
|
|
43
|
+
* Get app count
|
|
44
|
+
*/
|
|
45
|
+
get size(): number;
|
|
46
|
+
/**
|
|
47
|
+
* Resolve an app ID, falling back to default
|
|
48
|
+
*/
|
|
49
|
+
resolve(id?: string): AppInfo;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=app-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-registry.d.ts","sourceRoot":"","sources":["../src/app-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAA8B;IAC1C,OAAO,CAAC,YAAY,CAAS;gBAEjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EAAE,MAAM;IAkBzD;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIpC;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;OAEG;IACH,GAAG,IAAI,MAAM,EAAE;IAIf;;OAEG;IACH,GAAG,IAAI,OAAO,EAAE;IAIhB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO;CAY9B"}
|