@mtkn/mega-agent 0.1.0 → 0.2.0
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 +624 -0
- package/dist/artifact/artifact.repository.d.ts +2 -1
- package/dist/artifact/artifact.repository.d.ts.map +1 -1
- package/dist/artifact/artifact.repository.js +1 -1
- package/dist/artifact/artifact.repository.js.map +1 -1
- package/dist/artifact/artifact.service.d.ts +3 -2
- package/dist/artifact/artifact.service.d.ts.map +1 -1
- package/dist/artifact/artifact.service.js.map +1 -1
- package/dist/artifact/artifact.types.d.ts +2 -1
- package/dist/artifact/artifact.types.d.ts.map +1 -1
- package/dist/artifact/artifact.types.js.map +1 -1
- package/dist/chat/chat-memory.integration.d.ts +3 -2
- package/dist/chat/chat-memory.integration.d.ts.map +1 -1
- package/dist/chat/chat-memory.integration.js.map +1 -1
- package/dist/chat/chat.repository.d.ts +2 -1
- package/dist/chat/chat.repository.d.ts.map +1 -1
- package/dist/chat/chat.repository.js +1 -1
- package/dist/chat/chat.repository.js.map +1 -1
- package/dist/chat/chat.service.d.ts +3 -2
- package/dist/chat/chat.service.d.ts.map +1 -1
- package/dist/chat/chat.service.js +108 -33
- package/dist/chat/chat.service.js.map +1 -1
- package/dist/chat/chat.types.d.ts +7 -5
- package/dist/chat/chat.types.d.ts.map +1 -1
- package/dist/chat/chat.types.js.map +1 -1
- package/dist/chat/prompts/system.prompts.d.ts.map +1 -1
- package/dist/chat/prompts/system.prompts.js +9 -6
- package/dist/chat/prompts/system.prompts.js.map +1 -1
- package/dist/incident/incident.correlator.d.ts +3 -2
- package/dist/incident/incident.correlator.d.ts.map +1 -1
- package/dist/incident/incident.correlator.js.map +1 -1
- package/dist/incident/incident.repository.d.ts +5 -4
- package/dist/incident/incident.repository.d.ts.map +1 -1
- package/dist/incident/incident.repository.js +6 -6
- package/dist/incident/incident.repository.js.map +1 -1
- package/dist/incident/incident.service.d.ts +3 -2
- package/dist/incident/incident.service.d.ts.map +1 -1
- package/dist/incident/incident.service.js.map +1 -1
- package/dist/incident/incident.types.d.ts +3 -2
- package/dist/incident/incident.types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/source.repository.d.ts +5 -4
- package/dist/mcp/source.repository.d.ts.map +1 -1
- package/dist/mcp/source.repository.js +3 -3
- package/dist/mcp/source.repository.js.map +1 -1
- package/dist/mcp/source.service.d.ts +3 -2
- package/dist/mcp/source.service.d.ts.map +1 -1
- package/dist/mcp/source.service.js.map +1 -1
- package/dist/memory/memory.repository.d.ts +3 -2
- package/dist/memory/memory.repository.d.ts.map +1 -1
- package/dist/memory/memory.repository.js +4 -4
- package/dist/memory/memory.repository.js.map +1 -1
- package/dist/memory/memory.service.d.ts +3 -2
- package/dist/memory/memory.service.d.ts.map +1 -1
- package/dist/memory/memory.service.js +2 -2
- package/dist/memory/memory.service.js.map +1 -1
- package/dist/memory/memory.types.d.ts +4 -3
- package/dist/memory/memory.types.d.ts.map +1 -1
- package/dist/memory/memory.types.js.map +1 -1
- package/dist/tools/tool-registry.d.ts +3 -2
- package/dist/tools/tool-registry.d.ts.map +1 -1
- package/dist/tools/tool-registry.js.map +1 -1
- package/dist/types/id.types.d.ts +7 -0
- package/dist/types/id.types.d.ts.map +1 -0
- package/dist/types/id.types.js +2 -0
- package/dist/types/id.types.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/workflow/workflow.repository.js.map +1 -1
- package/dist/workflow/workflow.service.d.ts.map +1 -1
- package/dist/workflow/workflow.service.js +7 -6
- package/dist/workflow/workflow.service.js.map +1 -1
- package/dist/workflow/workflow.types.d.ts +4 -2
- package/dist/workflow/workflow.types.d.ts.map +1 -1
- package/dist/workflow/workflow.types.js.map +1 -1
- package/package.json +1 -3
- package/prisma/schema.prisma +13 -5
- package/scripts/prisma-sync.mjs +216 -13
package/README.md
ADDED
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
# @mtkn/mega-agent
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@mtkn/mega-agent)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
AI-powered agent infrastructure for Express + Prisma backends. Drop-in chat API with tool calling, long-term memory, incident detection, workflow automation, and more.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Multi-provider LLM** — Anthropic, OpenAI, Gemini, or custom endpoints
|
|
11
|
+
- **Tool calling** with read/write approval workflow
|
|
12
|
+
- **Long-term memory** — embedding + Qdrant vector search (optional)
|
|
13
|
+
- **Chat API** with SSE streaming and 4 chat modes
|
|
14
|
+
- **Incident detection** — anomaly detection with severity levels
|
|
15
|
+
- **Workflow automation** — schedule, event, threshold, and manual triggers
|
|
16
|
+
- **Artifact storage** — reports, tables, charts, code, images, datasets
|
|
17
|
+
- **MCP support** — Model Context Protocol for external data sources
|
|
18
|
+
- **Prisma persistence** — 12 models, fully typed
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @mtkn/mega-agent
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { createMegaAgent } from '@mtkn/mega-agent';
|
|
28
|
+
|
|
29
|
+
const agent = await createMegaAgent({
|
|
30
|
+
prisma,
|
|
31
|
+
logger,
|
|
32
|
+
llm: {
|
|
33
|
+
providers: [
|
|
34
|
+
{ provider: 'anthropic', apiKey: 'sk-ant-...', defaultModel: 'claude-sonnet-4-20250514' },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
app.use('/api/chat', agent.createChatRouter(authMiddleware));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Requirements
|
|
43
|
+
|
|
44
|
+
| Requirement | Version |
|
|
45
|
+
|---|---|
|
|
46
|
+
| Node.js | >= 18.17 |
|
|
47
|
+
| TypeScript | 5.x |
|
|
48
|
+
| Express | 4.x |
|
|
49
|
+
| Prisma | 6.x |
|
|
50
|
+
| PostgreSQL | 14+ |
|
|
51
|
+
|
|
52
|
+
**Optional services (for memory system):**
|
|
53
|
+
|
|
54
|
+
| Service | Purpose |
|
|
55
|
+
|---|---|
|
|
56
|
+
| Qdrant | Vector database for semantic search |
|
|
57
|
+
| OpenAI API | Embedding model (`text-embedding-3-small`) |
|
|
58
|
+
| Redis + BullMQ | Job queue (for workflows) |
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install @mtkn/mega-agent
|
|
64
|
+
|
|
65
|
+
# Peer dependencies (should already be in your project)
|
|
66
|
+
npm install @prisma/client express
|
|
67
|
+
npm install -D prisma @types/express typescript
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Prisma Schema Setup
|
|
71
|
+
|
|
72
|
+
The package requires 16 enums and 12 models in your Prisma schema.
|
|
73
|
+
|
|
74
|
+
### Option A: Automatic Sync (Recommended)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
npx mega-agent-prisma-sync --target prisma/schema.prisma
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
On first run, the CLI interactively asks your preferred ID strategy:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
📋 mega-agent Prisma Schema Configuration
|
|
84
|
+
|
|
85
|
+
Primary key strategy for mega-agent models? (cuid/uuid/autoincrement) [cuid]:
|
|
86
|
+
User ID type in your app? (int/string) [int]:
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You can also pass flags directly (useful for CI/CD):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# UUID primary keys + String user IDs
|
|
93
|
+
npx mega-agent-prisma-sync --target prisma/schema.prisma --id-type uuid --user-id-type string
|
|
94
|
+
|
|
95
|
+
# Autoincrement (integer) primary keys
|
|
96
|
+
npx mega-agent-prisma-sync --target prisma/schema.prisma --id-type autoincrement
|
|
97
|
+
|
|
98
|
+
# Skip prompts, use previous config or defaults
|
|
99
|
+
npx mega-agent-prisma-sync --target prisma/schema.prisma --no-interactive
|
|
100
|
+
|
|
101
|
+
# Preview without writing
|
|
102
|
+
npx mega-agent-prisma-sync --target prisma/schema.prisma --id-type uuid --dry-run
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Available options:**
|
|
106
|
+
|
|
107
|
+
| Flag | Values | Default | Description |
|
|
108
|
+
|------|--------|---------|-------------|
|
|
109
|
+
| `--id-type` | `cuid`, `uuid`, `autoincrement` | `cuid` | Primary key strategy for all mega-agent models |
|
|
110
|
+
| `--user-id-type` | `int`, `string` | `int` | Type of the `userId` field (must match your User model's ID type) |
|
|
111
|
+
| `--no-interactive` | — | — | Skip prompts, use previous config or defaults |
|
|
112
|
+
| `--dry-run` | — | — | Print result without writing to file |
|
|
113
|
+
|
|
114
|
+
Your selection is saved in the marker comment. Re-running the sync command automatically detects and reuses the previous config.
|
|
115
|
+
|
|
116
|
+
### Option B: Manual Copy
|
|
117
|
+
|
|
118
|
+
Copy all enums and models from the reference schema:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# View the reference schema
|
|
122
|
+
cat node_modules/@mtkn/mega-agent/prisma/schema.prisma
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If your app uses UUID or autoincrement IDs, you'll need to manually adjust the `@id` defaults and `userId` field types.
|
|
126
|
+
|
|
127
|
+
### Add User Relations
|
|
128
|
+
|
|
129
|
+
Each AI model has a `userId` field. Add relations in your `User` model:
|
|
130
|
+
|
|
131
|
+
```prisma
|
|
132
|
+
model User {
|
|
133
|
+
// ... your existing fields ...
|
|
134
|
+
|
|
135
|
+
// AI Agent relations
|
|
136
|
+
aiMemories AiMemory[]
|
|
137
|
+
aiMemorySuggestions AiMemorySuggestion[]
|
|
138
|
+
aiChats AiChat[]
|
|
139
|
+
aiArtifacts AiArtifact[]
|
|
140
|
+
aiMcpSources AiMcpSource[]
|
|
141
|
+
aiWorkflows AiWorkflow[]
|
|
142
|
+
aiIncidents AiIncident[]
|
|
143
|
+
aiTimelineEvents AiTimelineEvent[]
|
|
144
|
+
aiReports AiReport[]
|
|
145
|
+
aiPreferences AiUserPreferences?
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
And add the reverse relation in each AI model:
|
|
150
|
+
|
|
151
|
+
```prisma
|
|
152
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Add Notification Model
|
|
156
|
+
|
|
157
|
+
The workflow service uses `prisma.notification.create()`. Your schema needs a Notification model. Adjust the `userId` type to match your User model:
|
|
158
|
+
|
|
159
|
+
```prisma
|
|
160
|
+
model Notification {
|
|
161
|
+
id Int @id @default(autoincrement())
|
|
162
|
+
userId Int @map("user_id") // Use String if your User.id is String
|
|
163
|
+
type String
|
|
164
|
+
title String
|
|
165
|
+
message String
|
|
166
|
+
isRead Boolean @default(false) @map("is_read")
|
|
167
|
+
createdAt DateTime @default(now()) @map("created_at")
|
|
168
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
169
|
+
@@map("notifications")
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Run Migration
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npx prisma migrate dev --name add_mega_agent_models
|
|
177
|
+
npx prisma generate
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Configuration
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
interface MegaAgentConfig {
|
|
184
|
+
/** Prisma client instance */
|
|
185
|
+
prisma: PrismaClient;
|
|
186
|
+
|
|
187
|
+
/** Logger with info/error/warn/debug methods */
|
|
188
|
+
logger: LoggerLike;
|
|
189
|
+
|
|
190
|
+
/** LLM provider configs (at least 1 required) */
|
|
191
|
+
llm: {
|
|
192
|
+
providers: Array<{
|
|
193
|
+
provider: 'anthropic' | 'openai' | 'gemini' | 'custom';
|
|
194
|
+
apiKey: string;
|
|
195
|
+
defaultModel?: string;
|
|
196
|
+
baseUrl?: string; // only for 'custom'
|
|
197
|
+
}>;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/** Memory system — omit to disable */
|
|
201
|
+
memory?: {
|
|
202
|
+
embedding: {
|
|
203
|
+
apiKey: string;
|
|
204
|
+
provider?: 'openai'; // default: 'openai'
|
|
205
|
+
defaultModel?: string; // default: 'text-embedding-3-small'
|
|
206
|
+
};
|
|
207
|
+
qdrant: {
|
|
208
|
+
host: string; // default: 'localhost'
|
|
209
|
+
port: number; // default: 6333
|
|
210
|
+
apiKey?: string;
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/** Agent identity (for system prompt customization) */
|
|
215
|
+
agent?: {
|
|
216
|
+
agentName?: string;
|
|
217
|
+
agentDescription?: string;
|
|
218
|
+
customPrompt?: string;
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Usage
|
|
224
|
+
|
|
225
|
+
### Basic Setup
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import type { Express } from 'express';
|
|
229
|
+
import { createMegaAgent } from '@mtkn/mega-agent';
|
|
230
|
+
import { prisma } from './lib/prisma-client.js';
|
|
231
|
+
import { logger } from './lib/logger.js';
|
|
232
|
+
import { authMiddleware } from './middleware/auth.js';
|
|
233
|
+
|
|
234
|
+
export async function initChatModule(app: Express): Promise<void> {
|
|
235
|
+
const providers = [];
|
|
236
|
+
|
|
237
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
238
|
+
providers.push({
|
|
239
|
+
provider: 'anthropic' as const,
|
|
240
|
+
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
241
|
+
defaultModel: process.env.ANTHROPIC_DEFAULT_MODEL || 'claude-sonnet-4-20250514',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (process.env.OPENAI_API_KEY) {
|
|
246
|
+
providers.push({
|
|
247
|
+
provider: 'openai' as const,
|
|
248
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
249
|
+
defaultModel: process.env.OPENAI_DEFAULT_MODEL || 'gpt-4o',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Memory config (optional — requires OpenAI key + Qdrant)
|
|
254
|
+
const memory = process.env.OPENAI_API_KEY
|
|
255
|
+
? {
|
|
256
|
+
embedding: {
|
|
257
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
258
|
+
provider: 'openai' as const,
|
|
259
|
+
defaultModel: process.env.EMBEDDING_MODEL || 'text-embedding-3-small',
|
|
260
|
+
},
|
|
261
|
+
qdrant: {
|
|
262
|
+
host: process.env.QDRANT_HOST || 'localhost',
|
|
263
|
+
port: parseInt(process.env.QDRANT_PORT || '6333', 10),
|
|
264
|
+
apiKey: process.env.QDRANT_API_KEY || undefined,
|
|
265
|
+
},
|
|
266
|
+
}
|
|
267
|
+
: undefined;
|
|
268
|
+
|
|
269
|
+
const agent = await createMegaAgent({
|
|
270
|
+
prisma,
|
|
271
|
+
logger,
|
|
272
|
+
llm: { providers },
|
|
273
|
+
memory,
|
|
274
|
+
agent: {
|
|
275
|
+
agentName: 'ProductionAssistant',
|
|
276
|
+
agentDescription: 'Manufacturing management AI assistant',
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Register domain-specific tools (see below)
|
|
281
|
+
registerMyTools();
|
|
282
|
+
|
|
283
|
+
// Mount chat routes
|
|
284
|
+
app.use('/api/chat', agent.createChatRouter(authMiddleware));
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Auth Middleware
|
|
289
|
+
|
|
290
|
+
The chat router requires an auth middleware that sets `req.user` with at least an `id` field:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
type AuthMiddleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
294
|
+
|
|
295
|
+
// Your middleware must set:
|
|
296
|
+
// req.user = { id: number | string, ... }
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
The `userId` type is flexible — it accepts both `number` and `string` to support different ID strategies (autoincrement integers, CUID strings, UUIDs, etc.).
|
|
300
|
+
|
|
301
|
+
### Registering Domain Tools
|
|
302
|
+
|
|
303
|
+
Tools give the AI agent access to your application's data and actions. The package comes with 2 built-in tools (`search_memory`, `create_memory`) when memory is enabled. Register your own domain tools after calling `createMegaAgent()`:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import { registerTools } from '@mtkn/mega-agent';
|
|
307
|
+
import type { ToolDefinition } from '@mtkn/mega-agent';
|
|
308
|
+
|
|
309
|
+
const tools: ToolDefinition[] = [
|
|
310
|
+
// Read tools — auto-executed, no user approval needed
|
|
311
|
+
{
|
|
312
|
+
name: 'list_products',
|
|
313
|
+
description: 'List products with optional status filter',
|
|
314
|
+
category: 'read',
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: 'object',
|
|
317
|
+
properties: {
|
|
318
|
+
status: { type: 'string', description: 'Filter by status', enum: ['ACTIVE', 'ARCHIVED'] },
|
|
319
|
+
limit: { type: 'number', description: 'Max results (default 20)' },
|
|
320
|
+
},
|
|
321
|
+
},
|
|
322
|
+
handler: async (args, userId) => {
|
|
323
|
+
return prisma.product.findMany({
|
|
324
|
+
where: args.status ? { status: args.status as string } : undefined,
|
|
325
|
+
take: (args.limit as number) || 20,
|
|
326
|
+
});
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
|
|
330
|
+
// Write tools — require user approval before execution
|
|
331
|
+
{
|
|
332
|
+
name: 'create_order',
|
|
333
|
+
description: 'Create a new order. Requires approval.',
|
|
334
|
+
category: 'write',
|
|
335
|
+
inputSchema: {
|
|
336
|
+
type: 'object',
|
|
337
|
+
properties: {
|
|
338
|
+
productId: { type: 'number', description: 'Product ID' },
|
|
339
|
+
quantity: { type: 'number', description: 'Order quantity' },
|
|
340
|
+
},
|
|
341
|
+
required: ['productId', 'quantity'],
|
|
342
|
+
},
|
|
343
|
+
handler: async (args, userId) => {
|
|
344
|
+
return prisma.order.create({
|
|
345
|
+
data: {
|
|
346
|
+
productId: args.productId as number,
|
|
347
|
+
quantity: args.quantity as number,
|
|
348
|
+
userId,
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
];
|
|
354
|
+
|
|
355
|
+
export function registerMyTools(): void {
|
|
356
|
+
registerTools(tools);
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Tool Categories:**
|
|
361
|
+
- `read` — Auto-executed by the agent, no approval needed
|
|
362
|
+
- `write` — Agent pauses and waits for user approval via `POST /:id/approve`
|
|
363
|
+
|
|
364
|
+
### Using Services Independently
|
|
365
|
+
|
|
366
|
+
You can use individual services without the full chat stack:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { initLLMService, LLMService } from '@mtkn/mega-agent';
|
|
370
|
+
import type { LLMProviderConfig } from '@mtkn/mega-agent';
|
|
371
|
+
|
|
372
|
+
// Initialize the LLM service once
|
|
373
|
+
const providers: LLMProviderConfig[] = [
|
|
374
|
+
{ provider: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY!, defaultModel: 'claude-sonnet-4-20250514' },
|
|
375
|
+
];
|
|
376
|
+
initLLMService({ config: providers, logger });
|
|
377
|
+
|
|
378
|
+
// Use it anywhere
|
|
379
|
+
const llm = new LLMService();
|
|
380
|
+
const response = await llm.complete({
|
|
381
|
+
messages: [
|
|
382
|
+
{ role: 'system', content: 'You are a risk analyst.' },
|
|
383
|
+
{ role: 'user', content: 'Analyze this production data...' },
|
|
384
|
+
],
|
|
385
|
+
temperature: 0.3,
|
|
386
|
+
});
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Other services (after `createMegaAgent()` has been called):
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import {
|
|
393
|
+
IncidentService, getIncidentServiceDeps,
|
|
394
|
+
WorkflowService, getWorkflowServiceDeps,
|
|
395
|
+
ArtifactService, getArtifactServiceDeps,
|
|
396
|
+
} from '@mtkn/mega-agent';
|
|
397
|
+
|
|
398
|
+
// Check if dependencies are initialized
|
|
399
|
+
if (getIncidentServiceDeps()) {
|
|
400
|
+
const incidents = new IncidentService();
|
|
401
|
+
// Use incident detection...
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (getWorkflowServiceDeps()) {
|
|
405
|
+
const workflows = new WorkflowService();
|
|
406
|
+
// Use workflow automation...
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## API Endpoints
|
|
411
|
+
|
|
412
|
+
The chat router creates the following endpoints:
|
|
413
|
+
|
|
414
|
+
| Method | Path | Description |
|
|
415
|
+
|--------|------|-------------|
|
|
416
|
+
| `POST` | `/` | Create a new chat session |
|
|
417
|
+
| `GET` | `/` | List user's chats (paginated) |
|
|
418
|
+
| `GET` | `/:id` | Get chat with full message history |
|
|
419
|
+
| `PATCH` | `/:id` | Update chat (title, mode, model, etc.) |
|
|
420
|
+
| `DELETE` | `/:id` | Delete chat and all messages |
|
|
421
|
+
| `POST` | `/:id/messages` | Send message (agent responds) |
|
|
422
|
+
| `POST` | `/:id/approve` | Approve a pending write tool call |
|
|
423
|
+
| `POST` | `/:id/reject` | Reject a pending write tool call |
|
|
424
|
+
|
|
425
|
+
### Send Message
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
POST /api/chat/:id/messages
|
|
429
|
+
Content-Type: application/json
|
|
430
|
+
|
|
431
|
+
{
|
|
432
|
+
"content": "Show me today's production stats",
|
|
433
|
+
"model": "claude-sonnet-4-20250514", // optional override
|
|
434
|
+
"stream": true // optional SSE streaming
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Response (non-streaming):**
|
|
439
|
+
|
|
440
|
+
```json
|
|
441
|
+
{
|
|
442
|
+
"success": true,
|
|
443
|
+
"data": {
|
|
444
|
+
"userMessage": { "id": "...", "role": "USER", "content": "..." },
|
|
445
|
+
"assistantMessage": { "id": "...", "role": "ASSISTANT", "content": "..." },
|
|
446
|
+
"memories": [],
|
|
447
|
+
"tokens": { "prompt": 1200, "completion": 350, "total": 1550 },
|
|
448
|
+
"latencyMs": 2340
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
**SSE Streaming:**
|
|
454
|
+
|
|
455
|
+
When `stream: true`, the response uses Server-Sent Events:
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
Content-Type: text/event-stream
|
|
459
|
+
|
|
460
|
+
data: {"type":"chunk","content":"Here are"}
|
|
461
|
+
data: {"type":"chunk","content":" today's stats..."}
|
|
462
|
+
data: {"type":"tool_call","name":"get_dashboard","args":{}}
|
|
463
|
+
data: {"type":"done","tokens":{"prompt":1200,"completion":350}}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## Chat Modes
|
|
467
|
+
|
|
468
|
+
Each chat session has a mode that shapes the agent's behavior:
|
|
469
|
+
|
|
470
|
+
| Mode | Description |
|
|
471
|
+
|------|-------------|
|
|
472
|
+
| `EXPLORE` | Analysis, insights, data exploration. Agent focuses on understanding and explaining. |
|
|
473
|
+
| `GENERATE` | Content creation. Agent produces structured output (reports, tables, code). |
|
|
474
|
+
| `EXECUTE` | Action-oriented. Agent actively uses tools to perform tasks. |
|
|
475
|
+
| `AUTOMATE` | Workflow setup. Agent helps create triggers, conditions, and automated actions. |
|
|
476
|
+
|
|
477
|
+
Set the mode when creating or updating a chat:
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
POST /api/chat
|
|
481
|
+
{ "mode": "EXECUTE", "title": "Production Management" }
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Tool Approval Flow
|
|
485
|
+
|
|
486
|
+
```
|
|
487
|
+
User sends message
|
|
488
|
+
│
|
|
489
|
+
▼
|
|
490
|
+
Agent processes with LLM
|
|
491
|
+
│
|
|
492
|
+
├── Uses read tool → auto-executes → continues
|
|
493
|
+
│
|
|
494
|
+
└── Uses write tool → pauses
|
|
495
|
+
│
|
|
496
|
+
▼
|
|
497
|
+
Returns pending tool call to client
|
|
498
|
+
│
|
|
499
|
+
├── POST /:id/approve → executes tool → agent continues
|
|
500
|
+
│
|
|
501
|
+
└── POST /:id/reject → agent informed → responds accordingly
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
## Prisma Models
|
|
505
|
+
|
|
506
|
+
The package uses 12 models and 16 enums:
|
|
507
|
+
|
|
508
|
+
| Model | Purpose |
|
|
509
|
+
|-------|---------|
|
|
510
|
+
| `AiMemory` | Long-term memory with vector embeddings |
|
|
511
|
+
| `AiMemorySuggestion` | AI-suggested memories for user review |
|
|
512
|
+
| `AiChat` | Chat sessions with mode and settings |
|
|
513
|
+
| `AiChatMessage` | Individual messages with token tracking |
|
|
514
|
+
| `AiArtifact` | Generated content (reports, charts, code, etc.) |
|
|
515
|
+
| `AiIncident` | Detected anomalies with severity and status |
|
|
516
|
+
| `AiMcpSource` | Model Context Protocol data sources |
|
|
517
|
+
| `AiWorkflow` | Automated workflows with triggers and actions |
|
|
518
|
+
| `AiWorkflowExecution` | Workflow execution history |
|
|
519
|
+
| `AiReport` | Generated reports (daily, weekly, monthly) |
|
|
520
|
+
| `AiTimelineEvent` | Event log for audit trail |
|
|
521
|
+
| `AiUserPreferences` | Per-user AI settings |
|
|
522
|
+
|
|
523
|
+
## Environment Variables
|
|
524
|
+
|
|
525
|
+
| Variable | Required | Description | Default |
|
|
526
|
+
|----------|----------|-------------|---------|
|
|
527
|
+
| `ANTHROPIC_API_KEY` | At least 1 LLM key | Anthropic API key | — |
|
|
528
|
+
| `ANTHROPIC_DEFAULT_MODEL` | No | Default Anthropic model | `claude-sonnet-4-20250514` |
|
|
529
|
+
| `OPENAI_API_KEY` | At least 1 LLM key | OpenAI API key | — |
|
|
530
|
+
| `OPENAI_DEFAULT_MODEL` | No | Default OpenAI model | `gpt-4o` |
|
|
531
|
+
| `EMBEDDING_MODEL` | No | OpenAI embedding model | `text-embedding-3-small` |
|
|
532
|
+
| `QDRANT_HOST` | No | Qdrant server host | `localhost` |
|
|
533
|
+
| `QDRANT_PORT` | No | Qdrant server port | `6333` |
|
|
534
|
+
| `QDRANT_API_KEY` | No | Qdrant auth key | — |
|
|
535
|
+
|
|
536
|
+
## MegaAgent Return Type
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
interface MegaAgent {
|
|
540
|
+
/** Access to service instances */
|
|
541
|
+
services: {
|
|
542
|
+
chat: ChatService;
|
|
543
|
+
llm: LLMService;
|
|
544
|
+
memory: MemoryService | null; // null if memory not configured
|
|
545
|
+
embedding: EmbeddingService | null;
|
|
546
|
+
qdrant: QdrantService | null;
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
/** Prompt settings */
|
|
550
|
+
promptOptions: {
|
|
551
|
+
agentName?: string;
|
|
552
|
+
agentDescription?: string;
|
|
553
|
+
customPrompt?: string;
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
/** Create Express router with all chat endpoints */
|
|
557
|
+
createChatRouter(authMiddleware: AuthMiddleware): Router;
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## Troubleshooting
|
|
562
|
+
|
|
563
|
+
### `Module '@prisma/client' has no exported member 'AiChat'`
|
|
564
|
+
|
|
565
|
+
Prisma client needs to be regenerated:
|
|
566
|
+
|
|
567
|
+
```bash
|
|
568
|
+
npx prisma generate
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
If using a monorepo with linked packages, ensure there's only one `@prisma/client` instance. Add a postinstall script to deduplicate:
|
|
572
|
+
|
|
573
|
+
```json
|
|
574
|
+
{
|
|
575
|
+
"scripts": {
|
|
576
|
+
"postinstall": "rm -rf node_modules/@mtkn/mega-agent/node_modules/@prisma node_modules/@mtkn/mega-agent/node_modules/.prisma 2>/dev/null || true"
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Memory system not starting
|
|
582
|
+
|
|
583
|
+
- Verify `OPENAI_API_KEY` is set and valid
|
|
584
|
+
- Check Qdrant is running: `curl http://localhost:6333/collections`
|
|
585
|
+
- Memory is optional — chat works without it
|
|
586
|
+
|
|
587
|
+
### Tools not being used by the agent
|
|
588
|
+
|
|
589
|
+
- Call `registerTools()` **after** `createMegaAgent()`
|
|
590
|
+
- Ensure `inputSchema` is valid JSON Schema (`type: 'object'` at root)
|
|
591
|
+
- Tool `handler` must return a `Promise`
|
|
592
|
+
- Check tool `description` — the LLM uses it to decide when to call the tool
|
|
593
|
+
|
|
594
|
+
### Agent not responding or timing out
|
|
595
|
+
|
|
596
|
+
- The agent loop has a max of 10 iterations per message
|
|
597
|
+
- Up to 20 context messages are sent to the LLM
|
|
598
|
+
- Check LLM API key validity and rate limits
|
|
599
|
+
|
|
600
|
+
## TypeScript Types
|
|
601
|
+
|
|
602
|
+
The package exports a `UserId` type for use in your application:
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
import type { UserId } from '@mtkn/mega-agent';
|
|
606
|
+
|
|
607
|
+
// UserId = string | number
|
|
608
|
+
// Matches both integer and string-based ID strategies
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
All service methods accept `UserId` for the `userId` parameter, so your app works regardless of whether your User model uses `Int @id @default(autoincrement())` or `String @id @default(cuid())`.
|
|
612
|
+
|
|
613
|
+
## Changelog
|
|
614
|
+
|
|
615
|
+
### v0.2.0
|
|
616
|
+
|
|
617
|
+
- **ID type selection** — `prisma-sync` CLI now supports `--id-type` (cuid/uuid/autoincrement) and `--user-id-type` (int/string) with interactive prompts
|
|
618
|
+
- **Flexible UserId** — All services accept `string | number` for userId, supporting any ID strategy
|
|
619
|
+
- **Removed `uuid` dependency** — Replaced with Node.js built-in `crypto.randomUUID()`
|
|
620
|
+
- **Bug fix** — Fixed hardcoded `userId: 1` in workflow action handlers
|
|
621
|
+
|
|
622
|
+
## License
|
|
623
|
+
|
|
624
|
+
MIT
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { AiArtifact } from '@prisma/client';
|
|
6
6
|
import type { CreateArtifactDto, UpdateArtifactDto, ArtifactListQuery, ArtifactServiceDependencies } from './artifact.types.js';
|
|
7
|
+
import type { UserId } from '../types/index.js';
|
|
7
8
|
export declare function initArtifactRepository(deps: ArtifactServiceDependencies): void;
|
|
8
9
|
export declare class ArtifactRepository {
|
|
9
10
|
private get prisma();
|
|
10
11
|
create(data: CreateArtifactDto): Promise<AiArtifact>;
|
|
11
12
|
findById(id: string): Promise<AiArtifact | null>;
|
|
12
|
-
findByUser(userId:
|
|
13
|
+
findByUser(userId: UserId, query?: ArtifactListQuery): Promise<AiArtifact[]>;
|
|
13
14
|
findByChat(chatId: string): Promise<AiArtifact[]>;
|
|
14
15
|
update(id: string, data: UpdateArtifactDto): Promise<AiArtifact>;
|
|
15
16
|
delete(id: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact.repository.d.ts","sourceRoot":"","sources":["../../src/artifact/artifact.repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"artifact.repository.d.ts","sourceRoot":"","sources":["../../src/artifact/artifact.repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAChI,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,2BAA2B,GAAG,IAAI,CAE9E;AAED,qBAAa,kBAAkB;IAC7B,OAAO,KAAK,MAAM,GAGjB;IAEK,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBpD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAIhD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAY5E,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAOjD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAahE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact.repository.js","sourceRoot":"","sources":["../../src/artifact/artifact.repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"artifact.repository.js","sourceRoot":"","sources":["../../src/artifact/artifact.repository.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,IAAI,KAAK,GAAuC,IAAI,CAAC;AAErD,MAAM,UAAU,sBAAsB,CAAC,IAAiC;IACtE,KAAK,GAAG,IAAI,CAAC;AACf,CAAC;AAED,MAAM,OAAO,kBAAkB;IAC7B,IAAY,MAAM;QAChB,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC,MAAM,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,IAAuB;QAClC,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YACnC,IAAI,EAAE;gBACJ,MAAM,EAAE,IAAI,CAAC,MAAa;gBAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAiB;gBAC/B,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBAC5C,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM;gBACvC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE;gBACrB,QAAQ,EAAE,IAAI,CAAC,QAAkB,IAAI,SAAS;aAC/C;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,KAAyB;QACxD,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;YACrC,KAAK,EAAE;gBACL,MAAM,EAAE,MAAa;gBACrB,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;aACzC;YACD,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;YAC9B,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE;YACxB,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC;SACzB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc;QAC7B,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;YACrC,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE;YAC/C,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;SAC/B,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAAuB;QAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;YACnC,KAAK,EAAE,EAAE,EAAE,EAAE;YACb,IAAI,EAAE;gBACJ,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACxC,GAAG,CAAC,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;gBACxE,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAiB,EAAE,CAAC;gBACtE,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrC,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAkB,EAAE,CAAC;aAC5D;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { AiArtifact } from '@prisma/client';
|
|
6
6
|
import type { CreateArtifactDto, UpdateArtifactDto, ArtifactListQuery, ArtifactServiceDependencies } from './artifact.types.js';
|
|
7
|
+
import type { UserId } from '../types/index.js';
|
|
7
8
|
export declare function initArtifactService(deps: ArtifactServiceDependencies): void;
|
|
8
9
|
export declare function getArtifactServiceDeps(): ArtifactServiceDependencies | null;
|
|
9
10
|
export declare class ArtifactService {
|
|
@@ -12,11 +13,11 @@ export declare class ArtifactService {
|
|
|
12
13
|
private get logger();
|
|
13
14
|
create(data: CreateArtifactDto): Promise<AiArtifact>;
|
|
14
15
|
getById(id: string): Promise<AiArtifact | null>;
|
|
15
|
-
listByUser(userId:
|
|
16
|
+
listByUser(userId: UserId, query?: ArtifactListQuery): Promise<AiArtifact[]>;
|
|
16
17
|
listByChat(chatId: string): Promise<AiArtifact[]>;
|
|
17
18
|
update(id: string, data: UpdateArtifactDto): Promise<AiArtifact>;
|
|
18
19
|
delete(id: string): Promise<void>;
|
|
19
|
-
createFromMessage(userId:
|
|
20
|
+
createFromMessage(userId: UserId, chatId: string, messageId: string, data: Partial<CreateArtifactDto>): Promise<AiArtifact>;
|
|
20
21
|
export(id: string, format: 'json' | 'csv' | 'md'): Promise<string>;
|
|
21
22
|
}
|
|
22
23
|
//# sourceMappingURL=artifact.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact.service.d.ts","sourceRoot":"","sources":["../../src/artifact/artifact.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"artifact.service.d.ts","sourceRoot":"","sources":["../../src/artifact/artifact.service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,2BAA2B,EAC5B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAIhD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,2BAA2B,GAAG,IAAI,CAG3E;AAED,wBAAgB,sBAAsB,IAAI,2BAA2B,GAAG,IAAI,CAE3E;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAqB;;IAQvC,OAAO,KAAK,MAAM,GAA4B;IAIxC,MAAM,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAMpD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI/C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAI5E,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAIjD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAIhE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjC,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC;IAahB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;CA6BzE"}
|