@mandible-ai/mandible 0.3.0 → 0.3.2

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.
Files changed (30) hide show
  1. package/README.md +109 -44
  2. package/dist/examples/code-pipeline/colonies.d.ts +10 -0
  3. package/dist/examples/code-pipeline/colonies.d.ts.map +1 -0
  4. package/dist/examples/code-pipeline/colonies.js +112 -0
  5. package/dist/examples/code-pipeline/colonies.js.map +1 -0
  6. package/dist/examples/code-pipeline/docker.d.ts +3 -0
  7. package/dist/examples/code-pipeline/docker.d.ts.map +1 -0
  8. package/dist/examples/code-pipeline/docker.js +63 -0
  9. package/dist/examples/code-pipeline/docker.js.map +1 -0
  10. package/dist/examples/code-pipeline/index.js +44 -228
  11. package/dist/examples/code-pipeline/index.js.map +1 -1
  12. package/dist/examples/github-colony/mandible.config.d.ts +1 -10
  13. package/dist/examples/github-colony/mandible.config.d.ts.map +1 -1
  14. package/dist/examples/github-colony/mandible.config.js +16 -24
  15. package/dist/examples/github-colony/mandible.config.js.map +1 -1
  16. package/dist/examples/repo-maintenance/fixer.d.ts +11 -4
  17. package/dist/examples/repo-maintenance/fixer.d.ts.map +1 -1
  18. package/dist/examples/repo-maintenance/fixer.js +130 -123
  19. package/dist/examples/repo-maintenance/fixer.js.map +1 -1
  20. package/dist/examples/repo-maintenance/mandible.config.d.ts +1 -10
  21. package/dist/examples/repo-maintenance/mandible.config.d.ts.map +1 -1
  22. package/dist/examples/repo-maintenance/mandible.config.js +14 -14
  23. package/dist/examples/repo-maintenance/mandible.config.js.map +1 -1
  24. package/dist/examples/repo-maintenance/scout.d.ts +11 -4
  25. package/dist/examples/repo-maintenance/scout.d.ts.map +1 -1
  26. package/dist/examples/repo-maintenance/scout.js +102 -95
  27. package/dist/examples/repo-maintenance/scout.js.map +1 -1
  28. package/dist/examples/repo-maintenance/seed.js +19 -37
  29. package/dist/examples/repo-maintenance/seed.js.map +1 -1
  30. package/package.json +2 -7
package/README.md CHANGED
@@ -59,32 +59,78 @@ const host = await mandible('code-review')
59
59
  .start();
60
60
  ```
61
61
 
62
- No colony references any other colony. They coordinate entirely through signals in the environment. `start()` starts the runtimes and opens the live dashboard.
62
+ No colony references any other colony. They coordinate entirely through signals in the environment.
63
63
 
64
- ### Cloud deployment
64
+ ### Hosting models
65
+
66
+ The **environment** (where signals live) is orthogonal to the **host** (where colony code runs). Colony definitions stay the same across all hosts — only the `.host()` call changes.
67
+
68
+ #### Local (default)
69
+
70
+ Runs colonies as Node runtimes in the current process. This is the default when `.host()` is omitted:
71
+
72
+ ```typescript
73
+ import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
74
+
75
+ const env = new FilesystemEnvironment({ root: './.mandible/signals' });
76
+
77
+ const host = await mandible('code-pipeline')
78
+ .environment(env)
79
+ .colony('shaper', shaper)
80
+ .colony('critic', critic)
81
+ .colony('keeper', keeper)
82
+ .start();
83
+
84
+ await host.stop();
85
+ ```
86
+
87
+ #### Docker
88
+
89
+ Runs each colony as a Docker container via the Mandible Cloud API:
90
+
91
+ ```typescript
92
+ import { mandible, FilesystemEnvironment, docker } from '@mandible-ai/mandible';
93
+
94
+ const env = new FilesystemEnvironment({ root: './.mandible/signals' });
95
+
96
+ const host = await mandible('code-pipeline')
97
+ .environment(env)
98
+ .host(docker({
99
+ apiUrl: process.env.MANDIBLE_API_URL!,
100
+ apiKey: process.env.MANDIBLE_API_KEY!,
101
+ image: 'mandible-colony:latest',
102
+ }))
103
+ .colony('shaper', shaper)
104
+ .colony('critic', critic)
105
+ .colony('keeper', keeper)
106
+ .start();
107
+
108
+ console.log(host.metadata.projectId);
109
+ await host.stop();
110
+ ```
111
+
112
+ #### Cloud (Edera microVMs)
65
113
 
66
114
  For production workloads, run colonies in isolated Edera zones via [Mandible Cloud](https://mandible.dev):
67
115
 
68
116
  ```typescript
69
- import { mandible } from '@mandible-ai/mandible';
70
- import { CloudEnvironment } from '@mandible-ai/cloud';
117
+ import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
118
+ import { cloud } from '@mandible-ai/cloud';
71
119
 
72
- const env = new CloudEnvironment({
73
- apiKey: process.env.MANDIBLE_API_KEY,
74
- project: 'code-review',
75
- });
120
+ const env = new FilesystemEnvironment({ root: './.mandible/signals' });
76
121
 
77
- const host = await mandible('code-review')
122
+ const host = await mandible('code-pipeline')
78
123
  .environment(env)
79
- .colony('shaper', c => c.sense('task:ready').do('shape', shapeHandler))
80
- .colony('critic', c => c.sense('artifact:shaped').do('review', reviewHandler))
124
+ .host(cloud({ apiKey: process.env.MANDIBLE_API_KEY!, project: 'code-review' }))
125
+ .colony('shaper', shaper)
126
+ .colony('critic', critic)
127
+ .colony('keeper', keeper)
81
128
  .start();
82
129
 
83
- // Later:
84
130
  await host.stop();
85
131
  ```
86
132
 
87
- Same DSL, different host. The host decides how colonies run.
133
+ Same colonies, same environment, different host.
88
134
 
89
135
  ### Run with the dashboard
90
136
 
@@ -160,7 +206,7 @@ Other colonies sense those deposited signals and the cycle continues. Complex wo
160
206
  The `mandible()` function is the top-level entry point for defining and starting multi-colony systems:
161
207
 
162
208
  ```typescript
163
- const host = await mandible('pipeline-name')
209
+ const host = await mandible('my-swarm')
164
210
  .environment(env) // where colonies operate
165
211
  .colony('name', c => c // define a colony inline
166
212
  .sense('type:pattern', { unclaimed: true }) // what to watch for
@@ -182,7 +228,10 @@ colony('name')
182
228
  .in(env) // which environment
183
229
  .sense('type:pattern', { unclaimed: true }) // what to watch for
184
230
  .when(signal => signal.payload.priority > 0) // optional guard
185
- .do(withClaudeCode({ allowedTools: ['Read', 'Write'] })) // action provider
231
+ .do('shape', withClaudeCode({ // action provider
232
+ prompt: signal => `Implement: ${signal.payload.name}`,
233
+ allowedTools: ['Read', 'Write'],
234
+ }))
186
235
  .concurrency(3) // max parallel agents
187
236
  .claim('lease', 30_000) // claim strategy
188
237
  .poll(2000) // sensor poll interval (ms)
@@ -267,21 +316,6 @@ const env = new GitHubEnvironment({
267
316
  });
268
317
  ```
269
318
 
270
- ### Remote (implemented)
271
-
272
- WebSocket-based environment for distributed deployments. Multiple machines share a single signal namespace over the network.
273
-
274
- ```typescript
275
- import { RemoteEnvironment } from '@mandible-ai/mandible';
276
-
277
- const env = new RemoteEnvironment({
278
- url: 'ws://coordinator:4041',
279
- apiKey: process.env.MANDIBLE_API_KEY,
280
- project: 'my-project',
281
- name: 'distributed',
282
- });
283
- ```
284
-
285
319
  ### Dolt (stubbed)
286
320
 
287
321
  [Dolt](https://www.dolthub.com/) is a SQL database with Git-like versioning. Signals become rows, branching enables parallel work, and `dolt_history` provides queryable time travel for the full signal history.
@@ -305,7 +339,21 @@ interface Environment {
305
339
  }
306
340
  ```
307
341
 
308
- Hosts are orthogonal to Environments. The environment is where signals live; the host is where colony code runs. Call `host.start(colonies)` to start and `host.stop()` to shut down. `host.dashboard()` opens the live observability UI.
342
+ Hosts are orthogonal to Environments. To run colonies somewhere other than the local process, implement the `Host` interface:
343
+
344
+ ```typescript
345
+ interface Host {
346
+ name: string;
347
+ start(colonies: ColonyDefinition[]): Promise<void>;
348
+ stop(): Promise<void>;
349
+ dashboard(options?: DashboardOptions): Promise<void>;
350
+ metadata: HostMetadata;
351
+ colonies: Array<{ name: string; state: string }>;
352
+ environments: Environment[];
353
+ }
354
+ ```
355
+
356
+ Built-in hosts: `local()` (in-process), `docker()` (containers). Cloud hosts live in `@mandible-ai/cloud`.
309
357
 
310
358
  ## Patterns
311
359
 
@@ -360,12 +408,14 @@ src/
360
408
  attestation.ts Ed25519 signing & verification (@noble/ed25519)
361
409
  dsl/
362
410
  builder.ts Fluent colony definition DSL
363
- pipeline.ts mandible() — multi-colony orchestration + deploy
411
+ mandible.ts mandible() — multi-colony orchestration + start
364
412
  environments/
365
413
  filesystem/ Filesystem adapter (JSON files + atomic claims)
366
414
  github/ GitHub adapter (issues, PRs, comments, labels as signals)
367
- remote/ Remote adapter (WebSocket-based distributed environments)
368
415
  dolt/ Dolt adapter (stub)
416
+ hosts/
417
+ local.ts LocalHost — runs colonies in current process
418
+ docker.ts DockerHost — runs colonies as Docker containers
369
419
  providers/
370
420
  claude-code.ts withClaudeCode — Claude Code SDK (live)
371
421
  structured-output.ts withStructuredOutput — multi-model
@@ -377,12 +427,17 @@ src/
377
427
 
378
428
  tests/
379
429
  core/ Signal, runtime, attestation tests
380
- environments/ Filesystem, GitHub, remote adapter tests
430
+ environments/ Filesystem, GitHub adapter tests
431
+ dsl/ DSL and mandible() builder tests
381
432
  providers/ Agent, structured output, bash provider tests
382
433
  colonies/ Integration tests for colony workflows
383
434
 
384
435
  examples/
385
- code-pipeline/ Shaper → Critic → Keeper pipeline demo
436
+ code-pipeline/
437
+ colonies.ts Shared colony definitions (shaper, critic, keeper)
438
+ index.ts Local host — runs in current process
439
+ docker.ts Docker host — runs as containers
440
+ with-providers.ts Real LLM providers (Claude Code, Anthropic, Bash)
386
441
  repo-maintenance/ Scout + Fixer repo maintenance demo
387
442
  ```
388
443
 
@@ -390,16 +445,26 @@ examples/
390
445
 
391
446
  ### Code pipeline
392
447
 
393
- The included demo seeds 5 coding tasks into a filesystem environment. Three colonies self-organize to process them:
448
+ Three colonies coordinate through a shared filesystem environment:
394
449
 
395
- - **Shaper** (concurrency: 2) — picks up `task:ready` signals, produces `task:shaped` signals
396
- - **Critic** (concurrency: 2) — reviews shaped artifacts, deposits `review:approved` or `review:rejected`
397
- - **Keeper** (concurrency: 1) — commits approved work, deposits `task:complete`
450
+ - **Shaper** (concurrency: 2) — picks up `task:ready` signals, produces `artifact:shaped`
451
+ - **Critic** (concurrency: 2) — reviews shaped artifacts, deposits `review:approved` or `review:changes-needed`
452
+ - **Keeper** (concurrency: 1) — merges approved work, deposits `artifact:merged`
398
453
 
399
- No orchestrator. No message broker. No routing logic. The colonies discover work through the environment and coordinate through signals.
454
+ Colony definitions live in `colonies.ts` and are shared across all hosting modes:
400
455
 
401
456
  ```bash
402
- npm run demo
457
+ # Local host (default)
458
+ npx tsx examples/code-pipeline/index.ts
459
+
460
+ # Docker host
461
+ export MANDIBLE_API_URL=http://localhost:9091
462
+ export MANDIBLE_API_KEY=your-key
463
+ npx tsx examples/code-pipeline/docker.ts
464
+
465
+ # With real LLM providers
466
+ export ANTHROPIC_API_KEY=sk-ant-...
467
+ npx tsx examples/code-pipeline/with-providers.ts
403
468
  ```
404
469
 
405
470
  ### Repo maintenance
@@ -421,9 +486,9 @@ Both colonies are wired to real Claude agents via `withClaudeCode`. The dashboar
421
486
  - [x] `withClaudeCode` wired to Claude Code SDK
422
487
  - [x] Test suite (378 tests, 95%+ coverage)
423
488
  - [x] GitHub environment adapter
424
- - [x] Remote environment adapter
425
- - [x] `mandible()` DSL with environment-based deployment
426
- - [ ] `@mandible-ai/cloud` — deploy to Edera zones via Mandible Cloud
489
+ - [x] `mandible()` DSL with Host/Environment separation
490
+ - [x] `local()` and `docker()` host implementations
491
+ - [ ] `@mandible-ai/cloud` — run colonies in Edera microVMs via Mandible Cloud
427
492
  - [ ] `create-mandible` starter template
428
493
  - [ ] Dashboard GIF + landing page
429
494
  - [ ] Dolt full implementation
@@ -0,0 +1,10 @@
1
+ import type { ColonyBuilder } from '../../src/dsl/builder.js';
2
+ export declare function shaper(c: ColonyBuilder): ColonyBuilder<Record<string, unknown>>;
3
+ export declare function critic(c: ColonyBuilder): ColonyBuilder<Record<string, unknown>>;
4
+ export declare function keeper(c: ColonyBuilder): ColonyBuilder<Record<string, unknown>>;
5
+ export declare const SEED_TASKS: {
6
+ name: string;
7
+ priority: string;
8
+ description: string;
9
+ }[];
10
+ //# sourceMappingURL=colonies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colonies.d.ts","sourceRoot":"","sources":["../../../examples/code-pipeline/colonies.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAiC9D,wBAAgB,MAAM,CAAC,CAAC,EAAE,aAAa,0CAgBtC;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,aAAa,0CA+BtC;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,aAAa,0CAiBtC;AAED,eAAO,MAAM,UAAU;;;;GAMtB,CAAC"}
@@ -0,0 +1,112 @@
1
+ // ============================================================
2
+ // Shared Colony Definitions — Shaper / Critic / Keeper
3
+ // ============================================================
4
+ // These colonies are reusable across any host (local, docker,
5
+ // cloud). They define *what* happens, not *where* it runs.
6
+ //
7
+ // Each colony only knows about signal types — no colony
8
+ // references any other colony. Coordination emerges from
9
+ // the shared signal environment.
10
+ // ============================================================
11
+ function sleep(ms) {
12
+ return new Promise(resolve => setTimeout(resolve, ms));
13
+ }
14
+ async function simulateShaping(task) {
15
+ await sleep(500 + Math.random() * 1500);
16
+ return {
17
+ code: `function ${task.name}() { return true; }`,
18
+ linesChanged: Math.floor(Math.random() * 100) + 10,
19
+ task: task.name,
20
+ };
21
+ }
22
+ async function simulateReview(artifact) {
23
+ await sleep(300 + Math.random() * 1000);
24
+ const approved = Math.random() > 0.2;
25
+ return {
26
+ approved,
27
+ feedback: approved
28
+ ? `Code for "${artifact.task}" looks good.`
29
+ : `Code for "${artifact.task}" needs error handling.`,
30
+ };
31
+ }
32
+ async function simulateMerge(artifact) {
33
+ await sleep(200 + Math.random() * 500);
34
+ return { merged: true, task: artifact.task, commitHash: Math.random().toString(36).slice(2, 10) };
35
+ }
36
+ // Colony configurators — passed to mandible().colony(name, configure)
37
+ export function shaper(c) {
38
+ return c
39
+ .sense('task:ready', { unclaimed: true, minConcentration: 0.1 })
40
+ .do('shape-code', async (signal, ctx) => {
41
+ ctx.log(`Shaping: ${signal.payload.name}`);
42
+ const artifact = await simulateShaping(signal.payload);
43
+ await ctx.deposit('artifact:shaped', artifact, {
44
+ causedBy: [signal.id],
45
+ tags: ['needs-review'],
46
+ });
47
+ await ctx.withdraw(signal.id);
48
+ ctx.log(`Shaped "${signal.payload.name}" (${artifact.linesChanged} lines)`);
49
+ })
50
+ .concurrency(2)
51
+ .claim('lease', 30_000)
52
+ .poll(1000);
53
+ }
54
+ export function critic(c) {
55
+ return c
56
+ .sense('artifact:shaped', { unclaimed: true, minConcentration: 0.1 })
57
+ .do('review-code', async (signal, ctx) => {
58
+ ctx.log(`Reviewing: ${signal.payload.task}`);
59
+ const review = await simulateReview(signal.payload);
60
+ if (review.approved) {
61
+ await ctx.deposit('review:approved', {
62
+ artifact: signal.payload,
63
+ feedback: review.feedback,
64
+ }, {
65
+ causedBy: [signal.id],
66
+ tags: ['ready-to-merge'],
67
+ });
68
+ ctx.log(`Approved: ${review.feedback}`);
69
+ }
70
+ else {
71
+ await ctx.deposit('review:changes-needed', {
72
+ artifact: signal.payload,
73
+ feedback: review.feedback,
74
+ }, {
75
+ causedBy: [signal.id],
76
+ tags: ['needs-rework'],
77
+ ttl: 60_000,
78
+ });
79
+ ctx.log(`Changes needed: ${review.feedback}`);
80
+ }
81
+ await ctx.withdraw(signal.id);
82
+ })
83
+ .concurrency(2)
84
+ .claim('lease', 30_000)
85
+ .poll(1000);
86
+ }
87
+ export function keeper(c) {
88
+ return c
89
+ .sense('review:approved', { unclaimed: true, minConcentration: 0.1 })
90
+ .do('merge-artifact', async (signal, ctx) => {
91
+ const artifact = signal.payload.artifact ?? {};
92
+ ctx.log(`Merging: ${artifact.task}`);
93
+ const result = await simulateMerge(artifact);
94
+ await ctx.deposit('artifact:merged', result, {
95
+ causedBy: [signal.id],
96
+ tags: ['complete'],
97
+ });
98
+ await ctx.withdraw(signal.id);
99
+ ctx.log(`Merged -> commit ${result.commitHash}`);
100
+ })
101
+ .concurrency(1)
102
+ .claim('exclusive')
103
+ .poll(1000);
104
+ }
105
+ export const SEED_TASKS = [
106
+ { name: 'auth-middleware', priority: 'high', description: 'Add JWT authentication' },
107
+ { name: 'rate-limiter', priority: 'medium', description: 'API rate limiting' },
108
+ { name: 'health-check', priority: 'low', description: 'Add /health endpoint' },
109
+ { name: 'error-handler', priority: 'high', description: 'Global error handling' },
110
+ { name: 'request-logger', priority: 'medium', description: 'Structured logging' },
111
+ ];
112
+ //# sourceMappingURL=colonies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colonies.js","sourceRoot":"","sources":["../../../examples/code-pipeline/colonies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env tsx
2
+ export {};
3
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../examples/code-pipeline/docker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env tsx
2
+ // ============================================================
3
+ // Code Pipeline — Docker Host
4
+ // ============================================================
5
+ // Same colonies as index.ts, but running as Docker containers
6
+ // via the Mandible Cloud API. The colony definitions are
7
+ // identical — only the host changes.
8
+ //
9
+ // Prerequisites:
10
+ // - Mandible Cloud API running (local or remote)
11
+ // - MANDIBLE_API_URL and MANDIBLE_API_KEY set
12
+ //
13
+ // To run:
14
+ // export MANDIBLE_API_URL=http://localhost:9091
15
+ // export MANDIBLE_API_KEY=your-api-key
16
+ // npx tsx examples/code-pipeline/docker.ts
17
+ // ============================================================
18
+ import { mandible, FilesystemEnvironment, docker } from '../../src/index.js';
19
+ import { shaper, critic, keeper, SEED_TASKS } from './colonies.js';
20
+ const apiUrl = process.env.MANDIBLE_API_URL;
21
+ const apiKey = process.env.MANDIBLE_API_KEY;
22
+ if (!apiUrl || !apiKey) {
23
+ console.error('Set MANDIBLE_API_URL and MANDIBLE_API_KEY');
24
+ process.exit(1);
25
+ }
26
+ const env = new FilesystemEnvironment({ root: '/tmp/mandible-demo', name: 'code-pipeline' });
27
+ // Same colonies, different host
28
+ const host = await mandible('code-pipeline')
29
+ .environment(env)
30
+ .host(docker({
31
+ apiUrl,
32
+ apiKey,
33
+ image: 'mandible-colony:latest',
34
+ }))
35
+ .colony('shaper', shaper)
36
+ .colony('critic', critic)
37
+ .colony('keeper', keeper)
38
+ .start();
39
+ const meta = host.metadata;
40
+ console.log(`Started ${host.colonies.length} colonies on ${host.name} host`);
41
+ console.log(`Project: ${meta.projectId}`);
42
+ console.log(`Signal server: ${meta.signalServerUrl}\n`);
43
+ // Seed tasks
44
+ for (const task of SEED_TASKS) {
45
+ await env.deposit({
46
+ type: 'task:ready',
47
+ payload: task,
48
+ meta: { deposited_by: 'seed', tags: [task.priority] },
49
+ });
50
+ console.log(` seeded: task:ready "${task.name}"`);
51
+ }
52
+ console.log('\nColonies running in Docker containers.');
53
+ console.log('Press Ctrl+C to stop.\n');
54
+ // Keep alive until interrupted
55
+ process.on('SIGINT', async () => {
56
+ console.log('\nStopping...');
57
+ await host.stop();
58
+ console.log('Stopped.');
59
+ process.exit(0);
60
+ });
61
+ // Block forever
62
+ await new Promise(() => { });
63
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../examples/code-pipeline/docker.ts"],"names":[],"mappings":";AACA,+DAA+D;AAC/D,8BAA8B;AAC9B,+DAA+D;AAC/D,8DAA8D;AAC9D,yDAAyD;AACzD,qCAAqC;AACrC,EAAE;AACF,iBAAiB;AACjB,mDAAmD;AACnD,gDAAgD;AAChD,EAAE;AACF,UAAU;AACV,kDAAkD;AAClD,yCAAyC;AACzC,6CAA6C;AAC7C,+DAA+D;AAE/D,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,EAA2B,MAAM,oBAAoB,CAAC;AACtG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEnE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE5C,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,GAAG,GAAG,IAAI,qBAAqB,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAE7F,gCAAgC;AAChC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC;KACzC,WAAW,CAAC,GAAG,CAAC;KAChB,IAAI,CAAC,MAAM,CAAC;IACX,MAAM;IACN,MAAM;IACN,KAAK,EAAE,wBAAwB;CAChC,CAAC,CAAC;KACF,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;KACxB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;KACxB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;KACxB,KAAK,EAAE,CAAC;AAEX,MAAM,IAAI,GAAG,IAAI,CAAC,QAA8B,CAAC;AACjD,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,MAAM,gBAAgB,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;AAC7E,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AAC1C,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,eAAe,IAAI,CAAC,CAAC;AAExD,aAAa;AACb,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;IAC9B,MAAM,GAAG,CAAC,OAAO,CAAC;QAChB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;KACtD,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;AACxD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEvC,+BAA+B;AAC/B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC9B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAClB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,gBAAgB;AAChB,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC"}