@agentick/express 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 +329 -0
- package/dist/__tests__/message-flow.integration.spec.d.ts +8 -0
- package/dist/__tests__/message-flow.integration.spec.d.ts.map +1 -0
- package/dist/__tests__/message-flow.integration.spec.jsx +175 -0
- package/dist/__tests__/message-flow.integration.spec.jsx.map +1 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +114 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +10 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +367 -0
- package/dist/router.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +41 -0
- package/src/index.ts +157 -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,329 @@
|
|
|
1
|
+
# @agentick/express
|
|
2
|
+
|
|
3
|
+
Express middleware for Agentick Gateway.
|
|
4
|
+
|
|
5
|
+
This is a **thin adapter** (~50 lines) that delegates all business logic to `@agentick/gateway`. Use this when you want to integrate Agentick into an existing Express application.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @agentick/express
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @agentick/express
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import express from "express";
|
|
19
|
+
import { createAgentickMiddleware } from "@agentick/express";
|
|
20
|
+
import { createApp, Model, System, Timeline } from "@agentick/core";
|
|
21
|
+
|
|
22
|
+
const app = express();
|
|
23
|
+
app.use(express.json());
|
|
24
|
+
|
|
25
|
+
// Define your agent
|
|
26
|
+
const AssistantAgent = () => (
|
|
27
|
+
<>
|
|
28
|
+
<Model model={gpt4} />
|
|
29
|
+
<System>You are a helpful assistant.</System>
|
|
30
|
+
<Timeline />
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const agentickApp = createApp(<AssistantAgent />);
|
|
35
|
+
|
|
36
|
+
// Create middleware
|
|
37
|
+
const agentick = createAgentickMiddleware({
|
|
38
|
+
apps: { assistant: agentickApp },
|
|
39
|
+
defaultApp: "assistant",
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Mount at /api
|
|
43
|
+
app.use("/api", agentick);
|
|
44
|
+
|
|
45
|
+
// Start server
|
|
46
|
+
const server = app.listen(3000);
|
|
47
|
+
|
|
48
|
+
// Graceful shutdown - access gateway via .gateway property
|
|
49
|
+
process.on("SIGTERM", async () => {
|
|
50
|
+
await agentick.gateway.close();
|
|
51
|
+
server.close();
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
### createAgentickMiddleware(config, options?)
|
|
58
|
+
|
|
59
|
+
Creates an Express Router that delegates to an embedded Gateway.
|
|
60
|
+
|
|
61
|
+
Returns a `AgentickRouter` - an Express Router with an attached `.gateway` property for lifecycle management.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { createAgentickMiddleware, method } from "@agentick/express";
|
|
65
|
+
import { z } from "zod";
|
|
66
|
+
|
|
67
|
+
const middleware = createAgentickMiddleware({
|
|
68
|
+
// Required: Register your apps
|
|
69
|
+
apps: {
|
|
70
|
+
assistant: agentickApp,
|
|
71
|
+
researcher: researchApp,
|
|
72
|
+
},
|
|
73
|
+
defaultApp: "assistant",
|
|
74
|
+
|
|
75
|
+
// Optional: Authentication
|
|
76
|
+
auth: {
|
|
77
|
+
type: "custom",
|
|
78
|
+
validate: async (token) => {
|
|
79
|
+
const user = await verifyToken(token);
|
|
80
|
+
return user ? { valid: true, user } : { valid: false };
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
// Optional: Custom methods
|
|
85
|
+
methods: {
|
|
86
|
+
tasks: {
|
|
87
|
+
list: method({
|
|
88
|
+
schema: z.object({ sessionId: z.string() }),
|
|
89
|
+
handler: async (params) => todoService.list(params.sessionId),
|
|
90
|
+
}),
|
|
91
|
+
create: method({
|
|
92
|
+
schema: z.object({
|
|
93
|
+
sessionId: z.string(),
|
|
94
|
+
title: z.string().min(1),
|
|
95
|
+
}),
|
|
96
|
+
handler: async (params) => todoService.create(params),
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
health: async () => ({
|
|
100
|
+
status: "ok",
|
|
101
|
+
timestamp: new Date().toISOString(),
|
|
102
|
+
}),
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### AgentickRouter
|
|
108
|
+
|
|
109
|
+
The middleware returns a `AgentickRouter` which extends Express Router with:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
interface AgentickRouter extends Router {
|
|
113
|
+
/** The underlying Gateway instance for lifecycle management */
|
|
114
|
+
gateway: Gateway;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use `.gateway` for:
|
|
119
|
+
|
|
120
|
+
- Graceful shutdown: `await middleware.gateway.close()`
|
|
121
|
+
- Event subscriptions: `middleware.gateway.on('session:created', ...)`
|
|
122
|
+
- Direct method invocation (advanced)
|
|
123
|
+
|
|
124
|
+
### Options
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
interface AgentickMiddlewareOptions {
|
|
128
|
+
/**
|
|
129
|
+
* Extract token from Express request.
|
|
130
|
+
* By default, extracts from Authorization header.
|
|
131
|
+
*/
|
|
132
|
+
getToken?: (req: Request) => string | undefined;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Endpoints
|
|
137
|
+
|
|
138
|
+
The middleware exposes these HTTP endpoints:
|
|
139
|
+
|
|
140
|
+
| Method | Path | Description |
|
|
141
|
+
| ------ | --------- | ----------------------------- |
|
|
142
|
+
| GET | `/events` | SSE stream for session events |
|
|
143
|
+
| POST | `/send` | Send message to session |
|
|
144
|
+
| POST | `/invoke` | Invoke custom method |
|
|
145
|
+
|
|
146
|
+
### SSE Events Stream
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// Client connects to events stream
|
|
150
|
+
const events = new EventSource("/api/events?sessionId=main&token=xxx");
|
|
151
|
+
|
|
152
|
+
events.addEventListener("content_delta", (e) => {
|
|
153
|
+
const data = JSON.parse(e.data);
|
|
154
|
+
console.log("Content:", data.delta);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
events.addEventListener("tool_use", (e) => {
|
|
158
|
+
const data = JSON.parse(e.data);
|
|
159
|
+
console.log("Tool call:", data.name);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
events.addEventListener("message_end", () => {
|
|
163
|
+
console.log("Response complete");
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Send Message
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
const response = await fetch("/api/send", {
|
|
171
|
+
method: "POST",
|
|
172
|
+
headers: {
|
|
173
|
+
"Content-Type": "application/json",
|
|
174
|
+
Authorization: `Bearer ${token}`,
|
|
175
|
+
},
|
|
176
|
+
body: JSON.stringify({
|
|
177
|
+
sessionId: "main",
|
|
178
|
+
message: "Hello!",
|
|
179
|
+
}),
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Invoke Custom Method
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const response = await fetch("/api/invoke", {
|
|
187
|
+
method: "POST",
|
|
188
|
+
headers: {
|
|
189
|
+
"Content-Type": "application/json",
|
|
190
|
+
Authorization: `Bearer ${token}`,
|
|
191
|
+
},
|
|
192
|
+
body: JSON.stringify({
|
|
193
|
+
method: "tasks:list",
|
|
194
|
+
params: { sessionId: "main" },
|
|
195
|
+
}),
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Custom Methods
|
|
200
|
+
|
|
201
|
+
Define methods using the `method()` helper for schema validation and guards:
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { method } from "@agentick/express";
|
|
205
|
+
import { z } from "zod";
|
|
206
|
+
import { Context } from "@agentick/kernel";
|
|
207
|
+
|
|
208
|
+
const middleware = createAgentickMiddleware({
|
|
209
|
+
apps: { assistant: agentickApp },
|
|
210
|
+
defaultApp: "assistant",
|
|
211
|
+
methods: {
|
|
212
|
+
// Simple method - no schema
|
|
213
|
+
ping: async () => ({ pong: true }),
|
|
214
|
+
|
|
215
|
+
// With Zod schema - params are typed!
|
|
216
|
+
tasks: {
|
|
217
|
+
create: method({
|
|
218
|
+
schema: z.object({
|
|
219
|
+
title: z.string().min(1),
|
|
220
|
+
priority: z.enum(["low", "medium", "high"]).optional(),
|
|
221
|
+
}),
|
|
222
|
+
handler: async (params) => {
|
|
223
|
+
// Access Agentick context
|
|
224
|
+
const ctx = Context.get();
|
|
225
|
+
return todoService.create({
|
|
226
|
+
title: params.title,
|
|
227
|
+
priority: params.priority,
|
|
228
|
+
userId: ctx.user?.id,
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
232
|
+
|
|
233
|
+
// With role guards
|
|
234
|
+
admin: {
|
|
235
|
+
delete: method({
|
|
236
|
+
roles: ["admin"],
|
|
237
|
+
schema: z.object({ id: z.number() }),
|
|
238
|
+
handler: async (params) => todoService.delete(params.id),
|
|
239
|
+
}),
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## Authentication
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// Token auth
|
|
250
|
+
auth: {
|
|
251
|
+
type: "token",
|
|
252
|
+
token: process.env.API_TOKEN,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// JWT auth
|
|
256
|
+
auth: {
|
|
257
|
+
type: "jwt",
|
|
258
|
+
secret: process.env.JWT_SECRET,
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Custom auth with user hydration
|
|
262
|
+
auth: {
|
|
263
|
+
type: "custom",
|
|
264
|
+
validate: async (token) => {
|
|
265
|
+
const decoded = await verifyJWT(token);
|
|
266
|
+
return { valid: true, user: { id: decoded.sub } };
|
|
267
|
+
},
|
|
268
|
+
hydrateUser: async (authResult) => {
|
|
269
|
+
const dbUser = await db.users.findById(authResult.user.id);
|
|
270
|
+
return {
|
|
271
|
+
id: dbUser.id,
|
|
272
|
+
tenantId: dbUser.tenantId,
|
|
273
|
+
roles: dbUser.roles,
|
|
274
|
+
};
|
|
275
|
+
},
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Graceful Shutdown
|
|
280
|
+
|
|
281
|
+
The middleware exposes the underlying Gateway for lifecycle management:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
const agentick = createAgentickMiddleware({ ... });
|
|
285
|
+
app.use("/api", agentick);
|
|
286
|
+
|
|
287
|
+
const server = app.listen(3000);
|
|
288
|
+
|
|
289
|
+
const shutdown = async (signal: string) => {
|
|
290
|
+
console.log(`${signal} received, shutting down...`);
|
|
291
|
+
|
|
292
|
+
// Close gateway first (cleanly disconnects all sessions)
|
|
293
|
+
await agentick.gateway.close();
|
|
294
|
+
|
|
295
|
+
// Then close HTTP server
|
|
296
|
+
server.close(() => {
|
|
297
|
+
console.log("Server closed");
|
|
298
|
+
process.exit(0);
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
process.once("SIGTERM", () => shutdown("SIGTERM"));
|
|
303
|
+
process.once("SIGINT", () => shutdown("SIGINT"));
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Re-exports
|
|
307
|
+
|
|
308
|
+
For convenience, the package re-exports common types from `@agentick/gateway`:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
export {
|
|
312
|
+
Gateway,
|
|
313
|
+
method,
|
|
314
|
+
type GatewayConfig,
|
|
315
|
+
type MethodDefinition,
|
|
316
|
+
type AuthConfig,
|
|
317
|
+
} from "@agentick/gateway";
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Related Packages
|
|
321
|
+
|
|
322
|
+
- [`@agentick/gateway`](../gateway) - Core gateway (used internally)
|
|
323
|
+
- [`@agentick/core`](../core) - JSX runtime for agents
|
|
324
|
+
- [`@agentick/client`](../client) - Browser/Node client SDK
|
|
325
|
+
- [`@agentick/server`](../server) - SSE utilities
|
|
326
|
+
|
|
327
|
+
## License
|
|
328
|
+
|
|
329
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-flow.integration.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/message-flow.integration.spec.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express Handler Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* These tests verify the handler creates sessions correctly
|
|
5
|
+
* and routes requests to the appropriate endpoints.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
8
|
+
import express, {} from "express";
|
|
9
|
+
import { createTentickleHandler } from "../router";
|
|
10
|
+
import { createApp, Model, System, Timeline } from "@tentickle/core";
|
|
11
|
+
// Helper to create a mock model
|
|
12
|
+
function createMockModel() {
|
|
13
|
+
return {
|
|
14
|
+
metadata: {
|
|
15
|
+
id: "test-model",
|
|
16
|
+
provider: "test",
|
|
17
|
+
model: "test",
|
|
18
|
+
capabilities: ["streaming", "tools"],
|
|
19
|
+
},
|
|
20
|
+
generate: vi.fn().mockResolvedValue({
|
|
21
|
+
message: { role: "assistant", content: [{ type: "text", text: "Test response" }] },
|
|
22
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
23
|
+
stopReason: "stop",
|
|
24
|
+
}),
|
|
25
|
+
stream: vi.fn().mockImplementation(async function* () {
|
|
26
|
+
yield { type: "content_delta", delta: "Test ", role: "assistant" };
|
|
27
|
+
yield { type: "content_delta", delta: "response", role: "assistant" };
|
|
28
|
+
yield {
|
|
29
|
+
type: "result",
|
|
30
|
+
message: { role: "assistant", content: [{ type: "text", text: "Test response" }] },
|
|
31
|
+
usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },
|
|
32
|
+
stopReason: "stop",
|
|
33
|
+
};
|
|
34
|
+
}),
|
|
35
|
+
fromEngineState: vi.fn().mockImplementation(async (input) => {
|
|
36
|
+
return {
|
|
37
|
+
messages: [
|
|
38
|
+
...(input.system || []).map((e) => e.message),
|
|
39
|
+
...input.timeline.filter((e) => e.kind === "message").map((e) => e.message),
|
|
40
|
+
],
|
|
41
|
+
tools: input.tools || [],
|
|
42
|
+
};
|
|
43
|
+
}),
|
|
44
|
+
toEngineState: vi.fn().mockImplementation(async (output) => ({
|
|
45
|
+
message: output.message,
|
|
46
|
+
toolCalls: [],
|
|
47
|
+
stopReason: { reason: "stop", description: "Completed", recoverable: false },
|
|
48
|
+
usage: output.usage,
|
|
49
|
+
})),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
describe("Express Handler Setup", () => {
|
|
53
|
+
let expressApp;
|
|
54
|
+
let tentickleApp;
|
|
55
|
+
let mockModel;
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
mockModel = createMockModel();
|
|
58
|
+
const Agent = () => {
|
|
59
|
+
return (<>
|
|
60
|
+
<Model model={mockModel}/>
|
|
61
|
+
<System>You are a test assistant</System>
|
|
62
|
+
<Timeline />
|
|
63
|
+
</>);
|
|
64
|
+
};
|
|
65
|
+
tentickleApp = createApp(Agent, { maxTicks: 1 });
|
|
66
|
+
expressApp = express();
|
|
67
|
+
expressApp.use(express.json());
|
|
68
|
+
});
|
|
69
|
+
describe("createTentickleHandler", () => {
|
|
70
|
+
it("should create a valid express router", () => {
|
|
71
|
+
const handler = createTentickleHandler(tentickleApp);
|
|
72
|
+
expect(handler).toBeDefined();
|
|
73
|
+
expect(typeof handler).toBe("function");
|
|
74
|
+
});
|
|
75
|
+
it("should accept custom options", () => {
|
|
76
|
+
const handler = createTentickleHandler(tentickleApp, {
|
|
77
|
+
authenticate: (req) => ({ userId: req.headers["x-user-id"] }),
|
|
78
|
+
});
|
|
79
|
+
expect(handler).toBeDefined();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe("Session management", () => {
|
|
83
|
+
it("should create session on demand", () => {
|
|
84
|
+
// App should be able to create sessions
|
|
85
|
+
const session = tentickleApp.session("test-session");
|
|
86
|
+
expect(session).toBeDefined();
|
|
87
|
+
expect(session.id).toBe("test-session");
|
|
88
|
+
});
|
|
89
|
+
it("should reuse existing session with same ID", () => {
|
|
90
|
+
const session1 = tentickleApp.session("reuse-session");
|
|
91
|
+
const session2 = tentickleApp.session("reuse-session");
|
|
92
|
+
// Should be the same session instance
|
|
93
|
+
expect(session1).toBe(session2);
|
|
94
|
+
});
|
|
95
|
+
it("should create different sessions for different IDs", () => {
|
|
96
|
+
const session1 = tentickleApp.session("session-a");
|
|
97
|
+
const session2 = tentickleApp.session("session-b");
|
|
98
|
+
expect(session1.id).not.toBe(session2.id);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe("Message handling via session", () => {
|
|
102
|
+
it("should handle send with message", async () => {
|
|
103
|
+
const session = tentickleApp.session("send-test");
|
|
104
|
+
const handle = session.send({
|
|
105
|
+
message: {
|
|
106
|
+
role: "user",
|
|
107
|
+
content: [{ type: "text", text: "Hello" }],
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
// Collect events to verify execution happened
|
|
111
|
+
const events = [];
|
|
112
|
+
for await (const event of handle) {
|
|
113
|
+
events.push(event);
|
|
114
|
+
}
|
|
115
|
+
// Should have received events
|
|
116
|
+
expect(events.length).toBeGreaterThan(0);
|
|
117
|
+
// Should have execution_start
|
|
118
|
+
const hasExecutionStart = events.some((e) => e.type === "execution_start");
|
|
119
|
+
expect(hasExecutionStart).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it("should pass user message to model", async () => {
|
|
122
|
+
const session = tentickleApp.session("model-test");
|
|
123
|
+
await session.send({
|
|
124
|
+
message: {
|
|
125
|
+
role: "user",
|
|
126
|
+
content: [{ type: "text", text: "Test message" }],
|
|
127
|
+
},
|
|
128
|
+
}).result;
|
|
129
|
+
// Model's fromEngineState should have been called
|
|
130
|
+
expect(mockModel.fromEngineState).toHaveBeenCalled();
|
|
131
|
+
// Check that user message was in the input
|
|
132
|
+
const calls = mockModel.fromEngineState.mock.calls;
|
|
133
|
+
const lastCall = calls[calls.length - 1];
|
|
134
|
+
const input = lastCall[0];
|
|
135
|
+
const userEntries = input.timeline.filter((e) => e.message?.role === "user");
|
|
136
|
+
expect(userEntries.length).toBeGreaterThanOrEqual(1);
|
|
137
|
+
});
|
|
138
|
+
it("should stream events from execution", async () => {
|
|
139
|
+
const session = tentickleApp.session("stream-test");
|
|
140
|
+
const handle = session.send({
|
|
141
|
+
message: {
|
|
142
|
+
role: "user",
|
|
143
|
+
content: [{ type: "text", text: "Stream test" }],
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
const events = [];
|
|
147
|
+
for await (const event of handle) {
|
|
148
|
+
events.push(event);
|
|
149
|
+
}
|
|
150
|
+
// Should have received events
|
|
151
|
+
expect(events.length).toBeGreaterThan(0);
|
|
152
|
+
// Should have common event types
|
|
153
|
+
const eventTypes = events.map((e) => e.type);
|
|
154
|
+
expect(eventTypes).toContain("execution_start");
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe("Handler with Custom Options", () => {
|
|
159
|
+
it("should accept authentication handler", async () => {
|
|
160
|
+
const mockModel = createMockModel();
|
|
161
|
+
const Agent = () => (<>
|
|
162
|
+
<Model model={mockModel}/>
|
|
163
|
+
<System>Test</System>
|
|
164
|
+
<Timeline />
|
|
165
|
+
</>);
|
|
166
|
+
const app = createApp(Agent, { maxTicks: 1 });
|
|
167
|
+
const authHandler = vi.fn().mockReturnValue({ userId: "user-123" });
|
|
168
|
+
const handler = createTentickleHandler(app, {
|
|
169
|
+
authenticate: authHandler,
|
|
170
|
+
});
|
|
171
|
+
// The handler should be created successfully
|
|
172
|
+
expect(handler).toBeDefined();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
//# sourceMappingURL=message-flow.integration.spec.jsx.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-flow.integration.spec.jsx","sourceRoot":"","sources":["../../src/__tests__/message-flow.integration.spec.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agentick/express - Express adapter for Agentick Gateway
|
|
3
|
+
*
|
|
4
|
+
* Provides an Express middleware that delegates to Gateway.
|
|
5
|
+
* This is a thin adapter - all business logic lives in @agentick/gateway.
|
|
6
|
+
*
|
|
7
|
+
* @example Quick start
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import express from "express";
|
|
10
|
+
* import { createAgentickMiddleware } from "@agentick/express";
|
|
11
|
+
* import { createApp } from "@agentick/core";
|
|
12
|
+
*
|
|
13
|
+
* const app = express();
|
|
14
|
+
* app.use(express.json());
|
|
15
|
+
*
|
|
16
|
+
* const agentickApp = createApp(<MyAgent />);
|
|
17
|
+
*
|
|
18
|
+
* app.use("/api", createAgentickMiddleware({
|
|
19
|
+
* apps: { assistant: agentickApp },
|
|
20
|
+
* defaultApp: "assistant",
|
|
21
|
+
* }));
|
|
22
|
+
*
|
|
23
|
+
* const server = app.listen(3000);
|
|
24
|
+
*
|
|
25
|
+
* // Cleanup on shutdown
|
|
26
|
+
* process.on("SIGTERM", () => server.close());
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example With custom methods and auth
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { createAgentickMiddleware, method } from "@agentick/express";
|
|
32
|
+
* import { z } from "zod";
|
|
33
|
+
*
|
|
34
|
+
* app.use("/api", createAgentickMiddleware({
|
|
35
|
+
* apps: { assistant: agentickApp },
|
|
36
|
+
* defaultApp: "assistant",
|
|
37
|
+
* auth: {
|
|
38
|
+
* type: "custom",
|
|
39
|
+
* validate: async (token) => {
|
|
40
|
+
* const user = await verifyToken(token);
|
|
41
|
+
* return user ? { valid: true, user } : { valid: false };
|
|
42
|
+
* },
|
|
43
|
+
* },
|
|
44
|
+
* methods: {
|
|
45
|
+
* tasks: {
|
|
46
|
+
* list: method({
|
|
47
|
+
* schema: z.object({ sessionId: z.string() }),
|
|
48
|
+
* handler: async (params) => todoService.list(params.sessionId),
|
|
49
|
+
* }),
|
|
50
|
+
* },
|
|
51
|
+
* },
|
|
52
|
+
* }));
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @module @agentick/express
|
|
56
|
+
*/
|
|
57
|
+
import { Router } from "express";
|
|
58
|
+
import type { Request } from "express";
|
|
59
|
+
import { Gateway, type GatewayConfig } from "@agentick/gateway";
|
|
60
|
+
/**
|
|
61
|
+
* Options for the Express middleware.
|
|
62
|
+
*/
|
|
63
|
+
export interface AgentickMiddlewareOptions {
|
|
64
|
+
/**
|
|
65
|
+
* Extract token from Express request.
|
|
66
|
+
* By default, extracts from Authorization header.
|
|
67
|
+
*/
|
|
68
|
+
getToken?: (req: Request) => string | undefined;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Gateway config type for Express middleware.
|
|
72
|
+
* Excludes standalone-mode-only options.
|
|
73
|
+
*/
|
|
74
|
+
export type AgentickExpressConfig = Omit<GatewayConfig, "port" | "host" | "transport" | "httpPort">;
|
|
75
|
+
/**
|
|
76
|
+
* Express Router with attached Gateway instance for lifecycle management.
|
|
77
|
+
*/
|
|
78
|
+
export interface AgentickRouter extends Router {
|
|
79
|
+
/** The underlying Gateway instance for lifecycle management */
|
|
80
|
+
gateway: Gateway;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create Express middleware that delegates to Gateway.
|
|
84
|
+
*
|
|
85
|
+
* @param gatewayConfig - Gateway configuration (apps, methods, auth, etc.)
|
|
86
|
+
* @param options - Optional Express-specific options
|
|
87
|
+
* @returns Express Router middleware with attached gateway
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const middleware = createAgentickMiddleware({
|
|
92
|
+
* apps: { assistant: myApp },
|
|
93
|
+
* defaultApp: "assistant",
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* app.use("/api", middleware);
|
|
97
|
+
*
|
|
98
|
+
* // Access gateway for lifecycle management
|
|
99
|
+
* process.on("SIGTERM", () => middleware.gateway.close());
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function createAgentickMiddleware(gatewayConfig: AgentickExpressConfig, options?: AgentickMiddlewareOptions): AgentickRouter;
|
|
103
|
+
/**
|
|
104
|
+
* Get the Gateway instance from middleware for advanced use.
|
|
105
|
+
* Useful for lifecycle management, events, etc.
|
|
106
|
+
*/
|
|
107
|
+
export declare function createAgentickGateway(gatewayConfig: AgentickExpressConfig): Gateway;
|
|
108
|
+
export { Gateway, method, type GatewayConfig, type MethodDefinition, type AuthConfig, } from "@agentick/gateway";
|
|
109
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAA0B,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC;AAEpG;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,MAAM;IAC5C,+DAA+D;IAC/D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,qBAAqB,EACpC,OAAO,GAAE,yBAA8B,GACtC,cAAc,CA2BhB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,qBAAqB,GAAG,OAAO,CAKnF;AAGD,OAAO,EACL,OAAO,EACP,MAAM,EACN,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC"}
|