@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.
- package/README.md +109 -44
- package/dist/examples/code-pipeline/colonies.d.ts +10 -0
- package/dist/examples/code-pipeline/colonies.d.ts.map +1 -0
- package/dist/examples/code-pipeline/colonies.js +112 -0
- package/dist/examples/code-pipeline/colonies.js.map +1 -0
- package/dist/examples/code-pipeline/docker.d.ts +3 -0
- package/dist/examples/code-pipeline/docker.d.ts.map +1 -0
- package/dist/examples/code-pipeline/docker.js +63 -0
- package/dist/examples/code-pipeline/docker.js.map +1 -0
- package/dist/examples/code-pipeline/index.js +44 -228
- package/dist/examples/code-pipeline/index.js.map +1 -1
- package/dist/examples/github-colony/mandible.config.d.ts +1 -10
- package/dist/examples/github-colony/mandible.config.d.ts.map +1 -1
- package/dist/examples/github-colony/mandible.config.js +16 -24
- package/dist/examples/github-colony/mandible.config.js.map +1 -1
- package/dist/examples/repo-maintenance/fixer.d.ts +11 -4
- package/dist/examples/repo-maintenance/fixer.d.ts.map +1 -1
- package/dist/examples/repo-maintenance/fixer.js +130 -123
- package/dist/examples/repo-maintenance/fixer.js.map +1 -1
- package/dist/examples/repo-maintenance/mandible.config.d.ts +1 -10
- package/dist/examples/repo-maintenance/mandible.config.d.ts.map +1 -1
- package/dist/examples/repo-maintenance/mandible.config.js +14 -14
- package/dist/examples/repo-maintenance/mandible.config.js.map +1 -1
- package/dist/examples/repo-maintenance/scout.d.ts +11 -4
- package/dist/examples/repo-maintenance/scout.d.ts.map +1 -1
- package/dist/examples/repo-maintenance/scout.js +102 -95
- package/dist/examples/repo-maintenance/scout.js.map +1 -1
- package/dist/examples/repo-maintenance/seed.js +19 -37
- package/dist/examples/repo-maintenance/seed.js.map +1 -1
- 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.
|
|
62
|
+
No colony references any other colony. They coordinate entirely through signals in the environment.
|
|
63
63
|
|
|
64
|
-
###
|
|
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 {
|
|
117
|
+
import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
|
|
118
|
+
import { cloud } from '@mandible-ai/cloud';
|
|
71
119
|
|
|
72
|
-
const env = new
|
|
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-
|
|
122
|
+
const host = await mandible('code-pipeline')
|
|
78
123
|
.environment(env)
|
|
79
|
-
.
|
|
80
|
-
.colony('
|
|
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
|
|
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('
|
|
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(
|
|
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.
|
|
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
|
-
|
|
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
|
|
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/
|
|
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
|
-
|
|
448
|
+
Three colonies coordinate through a shared filesystem environment:
|
|
394
449
|
|
|
395
|
-
- **Shaper** (concurrency: 2) — picks up `task:ready` signals, produces `
|
|
396
|
-
- **Critic** (concurrency: 2) — reviews shaped artifacts, deposits `review:approved` or `review:
|
|
397
|
-
- **Keeper** (concurrency: 1) —
|
|
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
|
-
|
|
454
|
+
Colony definitions live in `colonies.ts` and are shared across all hosting modes:
|
|
400
455
|
|
|
401
456
|
```bash
|
|
402
|
-
|
|
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]
|
|
425
|
-
- [x] `
|
|
426
|
-
- [ ] `@mandible-ai/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 @@
|
|
|
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"}
|