@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 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,8 @@
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
+ export {};
8
+ //# sourceMappingURL=message-flow.integration.spec.d.ts.map
@@ -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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"}
@@ -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"}