@mandible-ai/mandible 0.2.0 → 0.3.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/README.md +169 -58
- 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/code-pipeline/with-providers.js +1 -2
- package/dist/examples/code-pipeline/with-providers.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/dist/src/cloud/client.d.ts +1 -1
- package/dist/src/cloud/client.d.ts.map +1 -1
- package/dist/src/cloud/client.js +1 -1
- package/dist/src/cloud/client.js.map +1 -1
- package/dist/src/cloud/index.d.ts +1 -3
- package/dist/src/cloud/index.d.ts.map +1 -1
- package/dist/src/cloud/index.js +0 -1
- package/dist/src/cloud/index.js.map +1 -1
- package/dist/src/cloud/types.d.ts +5 -9
- package/dist/src/cloud/types.d.ts.map +1 -1
- package/dist/src/core/types.d.ts +43 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +10 -0
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/dsl/index.d.ts +1 -0
- package/dist/src/dsl/index.d.ts.map +1 -1
- package/dist/src/dsl/index.js +1 -0
- package/dist/src/dsl/index.js.map +1 -1
- package/dist/src/dsl/mandible.d.ts +62 -0
- package/dist/src/dsl/mandible.d.ts.map +1 -0
- package/dist/src/dsl/mandible.js +140 -0
- package/dist/src/dsl/mandible.js.map +1 -0
- package/dist/src/environments/filesystem/adapter.d.ts.map +1 -1
- package/dist/src/environments/filesystem/adapter.js.map +1 -1
- package/dist/src/hosts/docker.d.ts +67 -0
- package/dist/src/hosts/docker.d.ts.map +1 -0
- package/dist/src/hosts/docker.js +135 -0
- package/dist/src/hosts/docker.js.map +1 -0
- package/dist/src/hosts/index.d.ts +5 -0
- package/dist/src/hosts/index.d.ts.map +1 -0
- package/dist/src/hosts/index.js +3 -0
- package/dist/src/hosts/index.js.map +1 -0
- package/dist/src/hosts/local.d.ts +41 -0
- package/dist/src/hosts/local.d.ts.map +1 -0
- package/dist/src/hosts/local.js +84 -0
- package/dist/src/hosts/local.js.map +1 -0
- package/dist/src/index.d.ts +8 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/providers/claude-code.d.ts.map +1 -1
- package/dist/src/providers/claude-code.js +3 -5
- package/dist/src/providers/claude-code.js.map +1 -1
- package/dist/src/providers/types.d.ts +0 -9
- package/dist/src/providers/types.d.ts.map +1 -1
- package/package.json +11 -6
- package/dist/examples/docker-pipeline/index.d.ts +0 -3
- package/dist/examples/docker-pipeline/index.d.ts.map +0 -1
- package/dist/examples/docker-pipeline/index.js +0 -235
- package/dist/examples/docker-pipeline/index.js.map +0 -1
- package/dist/examples/remote-pipeline/index.d.ts +0 -3
- package/dist/examples/remote-pipeline/index.d.ts.map +0 -1
- package/dist/examples/remote-pipeline/index.js +0 -154
- package/dist/examples/remote-pipeline/index.js.map +0 -1
- package/dist/src/environments/remote/adapter.d.ts +0 -61
- package/dist/src/environments/remote/adapter.d.ts.map +0 -1
- package/dist/src/environments/remote/adapter.js +0 -392
- package/dist/src/environments/remote/adapter.js.map +0 -1
- package/dist/src/environments/remote/index.d.ts +0 -5
- package/dist/src/environments/remote/index.d.ts.map +0 -1
- package/dist/src/environments/remote/index.js +0 -3
- package/dist/src/environments/remote/index.js.map +0 -1
- package/dist/src/environments/remote/protocol.d.ts +0 -124
- package/dist/src/environments/remote/protocol.d.ts.map +0 -1
- package/dist/src/environments/remote/protocol.js +0 -24
- package/dist/src/environments/remote/protocol.js.map +0 -1
- package/dist/src/providers/agent.d.ts +0 -23
- package/dist/src/providers/agent.d.ts.map +0 -1
- package/dist/src/providers/agent.js +0 -184
- package/dist/src/providers/agent.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,43 +27,110 @@ Stigmergy sidesteps all of that. The environment carries the state. Agents are s
|
|
|
27
27
|
## Quick start
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npm install mandible
|
|
30
|
+
npm install @mandible-ai/mandible
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
|
-
import {
|
|
34
|
+
import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
|
|
35
35
|
|
|
36
36
|
const env = new FilesystemEnvironment({ root: './.mandible/signals' });
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
.
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
38
|
+
const host = await mandible('code-review')
|
|
39
|
+
.environment(env)
|
|
40
|
+
.colony('shaper', c => c
|
|
41
|
+
.sense('task:ready', { unclaimed: true })
|
|
42
|
+
.do('shape-code', async (signal, ctx) => {
|
|
43
|
+
const result = await shapeCode(signal.payload);
|
|
44
|
+
await ctx.deposit('artifact:shaped', result, { causedBy: [signal.id] });
|
|
45
|
+
await ctx.withdraw(signal.id);
|
|
46
|
+
})
|
|
47
|
+
.concurrency(2)
|
|
48
|
+
.claim('lease', 30_000)
|
|
49
|
+
)
|
|
50
|
+
.colony('critic', c => c
|
|
51
|
+
.sense('artifact:shaped', { unclaimed: true })
|
|
52
|
+
.do('review-code', async (signal, ctx) => {
|
|
53
|
+
const review = await reviewCode(signal.payload);
|
|
54
|
+
await ctx.deposit('review:approved', review, { causedBy: [signal.id] });
|
|
55
|
+
await ctx.withdraw(signal.id);
|
|
56
|
+
})
|
|
57
|
+
.claim('exclusive')
|
|
58
|
+
)
|
|
59
|
+
.start();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
No colony references any other colony. They coordinate entirely through signals in the environment.
|
|
63
|
+
|
|
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)
|
|
48
69
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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',
|
|
55
102
|
}))
|
|
56
|
-
.
|
|
57
|
-
.
|
|
103
|
+
.colony('shaper', shaper)
|
|
104
|
+
.colony('critic', critic)
|
|
105
|
+
.colony('keeper', keeper)
|
|
106
|
+
.start();
|
|
58
107
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const criticRuntime = createRuntime(critic);
|
|
62
|
-
await shaperRuntime.start();
|
|
63
|
-
await criticRuntime.start();
|
|
108
|
+
console.log(host.metadata.projectId);
|
|
109
|
+
await host.stop();
|
|
64
110
|
```
|
|
65
111
|
|
|
66
|
-
|
|
112
|
+
#### Cloud (Edera microVMs)
|
|
113
|
+
|
|
114
|
+
For production workloads, run colonies in isolated Edera zones via [Mandible Cloud](https://mandible.dev):
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import { mandible, FilesystemEnvironment } from '@mandible-ai/mandible';
|
|
118
|
+
import { cloud } from '@mandible-ai/cloud';
|
|
119
|
+
|
|
120
|
+
const env = new FilesystemEnvironment({ root: './.mandible/signals' });
|
|
121
|
+
|
|
122
|
+
const host = await mandible('code-pipeline')
|
|
123
|
+
.environment(env)
|
|
124
|
+
.host(cloud({ apiKey: process.env.MANDIBLE_API_KEY!, project: 'code-review' }))
|
|
125
|
+
.colony('shaper', shaper)
|
|
126
|
+
.colony('critic', critic)
|
|
127
|
+
.colony('keeper', keeper)
|
|
128
|
+
.start();
|
|
129
|
+
|
|
130
|
+
await host.stop();
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Same colonies, same environment, different host.
|
|
67
134
|
|
|
68
135
|
### Run with the dashboard
|
|
69
136
|
|
|
@@ -134,14 +201,37 @@ sense → match rules → claim → execute action → deposit → (others sense
|
|
|
134
201
|
|
|
135
202
|
Other colonies sense those deposited signals and the cycle continues. Complex workflows emerge from simple local rules.
|
|
136
203
|
|
|
137
|
-
##
|
|
204
|
+
## Mandible DSL
|
|
205
|
+
|
|
206
|
+
The `mandible()` function is the top-level entry point for defining and starting multi-colony systems:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const host = await mandible('my-swarm')
|
|
210
|
+
.environment(env) // where colonies operate
|
|
211
|
+
.colony('name', c => c // define a colony inline
|
|
212
|
+
.sense('type:pattern', { unclaimed: true }) // what to watch for
|
|
213
|
+
.do('action-name', handler) // what to do
|
|
214
|
+
.concurrency(3) // max parallel agents
|
|
215
|
+
.claim('lease', 30_000) // claim strategy
|
|
216
|
+
)
|
|
217
|
+
.start(); // start everything
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`start()` delegates to the host — `local()` starts Node runtimes in the current process, `docker()` launches containers, `cloud()` launches Edera microVMs. Returns the host for lifecycle control (`host.stop()`, `host.dashboard()`).
|
|
221
|
+
|
|
222
|
+
### Colony builder
|
|
223
|
+
|
|
224
|
+
For lower-level control, use the `colony()` builder directly:
|
|
138
225
|
|
|
139
226
|
```typescript
|
|
140
227
|
colony('name')
|
|
141
228
|
.in(env) // which environment
|
|
142
229
|
.sense('type:pattern', { unclaimed: true }) // what to watch for
|
|
143
230
|
.when(signal => signal.payload.priority > 0) // optional guard
|
|
144
|
-
.do(
|
|
231
|
+
.do('shape', withClaudeCode({ // action provider
|
|
232
|
+
prompt: signal => `Implement: ${signal.payload.name}`,
|
|
233
|
+
allowedTools: ['Read', 'Write'],
|
|
234
|
+
}))
|
|
145
235
|
.concurrency(3) // max parallel agents
|
|
146
236
|
.claim('lease', 30_000) // claim strategy
|
|
147
237
|
.poll(2000) // sensor poll interval (ms)
|
|
@@ -204,7 +294,7 @@ Any shared substrate that supports observe/deposit/withdraw/claim/watch can be a
|
|
|
204
294
|
Signals are JSON files. Claims use atomic file operations. History lives in a `withdrawn/` directory.
|
|
205
295
|
|
|
206
296
|
```typescript
|
|
207
|
-
import { FilesystemEnvironment } from 'mandible';
|
|
297
|
+
import { FilesystemEnvironment } from '@mandible-ai/mandible';
|
|
208
298
|
|
|
209
299
|
const env = new FilesystemEnvironment({
|
|
210
300
|
root: './.mandible/signals',
|
|
@@ -217,7 +307,7 @@ const env = new FilesystemEnvironment({
|
|
|
217
307
|
Issues, pull requests, comments, and labels mapped as signals. Colonies can sense repository activity and deposit responses.
|
|
218
308
|
|
|
219
309
|
```typescript
|
|
220
|
-
import { GitHubEnvironment } from 'mandible';
|
|
310
|
+
import { GitHubEnvironment } from '@mandible-ai/mandible';
|
|
221
311
|
|
|
222
312
|
const env = new GitHubEnvironment({
|
|
223
313
|
owner: 'mandible-ai',
|
|
@@ -226,21 +316,6 @@ const env = new GitHubEnvironment({
|
|
|
226
316
|
});
|
|
227
317
|
```
|
|
228
318
|
|
|
229
|
-
### Remote (implemented)
|
|
230
|
-
|
|
231
|
-
WebSocket-based environment for distributed deployments. Multiple machines share a single signal namespace over the network.
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
import { RemoteEnvironment } from 'mandible';
|
|
235
|
-
|
|
236
|
-
const env = new RemoteEnvironment({
|
|
237
|
-
url: 'ws://coordinator:4041',
|
|
238
|
-
apiKey: process.env.MANDIBLE_API_KEY,
|
|
239
|
-
project: 'my-project',
|
|
240
|
-
name: 'distributed',
|
|
241
|
-
});
|
|
242
|
-
```
|
|
243
|
-
|
|
244
319
|
### Dolt (stubbed)
|
|
245
320
|
|
|
246
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.
|
|
@@ -264,6 +339,22 @@ interface Environment {
|
|
|
264
339
|
}
|
|
265
340
|
```
|
|
266
341
|
|
|
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`.
|
|
357
|
+
|
|
267
358
|
## Patterns
|
|
268
359
|
|
|
269
360
|
Reusable coordination patterns built on top of the core primitives.
|
|
@@ -273,7 +364,7 @@ Reusable coordination patterns built on top of the core primitives.
|
|
|
273
364
|
Cross-environment signal mirroring with attestation chains. Bridges watch for signals in one environment and mirror them to another, appending a signed attestation to preserve provenance across boundaries.
|
|
274
365
|
|
|
275
366
|
```typescript
|
|
276
|
-
import { createBridge } from 'mandible';
|
|
367
|
+
import { createBridge } from '@mandible-ai/mandible';
|
|
277
368
|
|
|
278
369
|
const bridge = createBridge({
|
|
279
370
|
name: 'local-to-github',
|
|
@@ -290,7 +381,7 @@ await bridge.start();
|
|
|
290
381
|
Trust monitoring colony that watches an environment for signals with invalid or missing provenance. When violations are detected, the sentinel deposits `trust:violation` report signals that other colonies can react to.
|
|
291
382
|
|
|
292
383
|
```typescript
|
|
293
|
-
import { createSentinel } from 'mandible';
|
|
384
|
+
import { createSentinel } from '@mandible-ai/mandible';
|
|
294
385
|
|
|
295
386
|
const sentinel = createSentinel({
|
|
296
387
|
name: 'trust-guard',
|
|
@@ -317,11 +408,14 @@ src/
|
|
|
317
408
|
attestation.ts Ed25519 signing & verification (@noble/ed25519)
|
|
318
409
|
dsl/
|
|
319
410
|
builder.ts Fluent colony definition DSL
|
|
411
|
+
mandible.ts mandible() — multi-colony orchestration + start
|
|
320
412
|
environments/
|
|
321
413
|
filesystem/ Filesystem adapter (JSON files + atomic claims)
|
|
322
414
|
github/ GitHub adapter (issues, PRs, comments, labels as signals)
|
|
323
|
-
remote/ Remote adapter (WebSocket-based distributed environments)
|
|
324
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
|
|
325
419
|
providers/
|
|
326
420
|
claude-code.ts withClaudeCode — Claude Code SDK (live)
|
|
327
421
|
structured-output.ts withStructuredOutput — multi-model
|
|
@@ -333,12 +427,17 @@ src/
|
|
|
333
427
|
|
|
334
428
|
tests/
|
|
335
429
|
core/ Signal, runtime, attestation tests
|
|
336
|
-
environments/ Filesystem, GitHub
|
|
430
|
+
environments/ Filesystem, GitHub adapter tests
|
|
431
|
+
dsl/ DSL and mandible() builder tests
|
|
337
432
|
providers/ Agent, structured output, bash provider tests
|
|
338
433
|
colonies/ Integration tests for colony workflows
|
|
339
434
|
|
|
340
435
|
examples/
|
|
341
|
-
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)
|
|
342
441
|
repo-maintenance/ Scout + Fixer repo maintenance demo
|
|
343
442
|
```
|
|
344
443
|
|
|
@@ -346,16 +445,26 @@ examples/
|
|
|
346
445
|
|
|
347
446
|
### Code pipeline
|
|
348
447
|
|
|
349
|
-
|
|
448
|
+
Three colonies coordinate through a shared filesystem environment:
|
|
350
449
|
|
|
351
|
-
- **Shaper** (concurrency: 2) — picks up `task:ready` signals, produces `
|
|
352
|
-
- **Critic** (concurrency: 2) — reviews shaped artifacts, deposits `review:approved` or `review:
|
|
353
|
-
- **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`
|
|
354
453
|
|
|
355
|
-
|
|
454
|
+
Colony definitions live in `colonies.ts` and are shared across all hosting modes:
|
|
356
455
|
|
|
357
456
|
```bash
|
|
358
|
-
|
|
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
|
|
359
468
|
```
|
|
360
469
|
|
|
361
470
|
### Repo maintenance
|
|
@@ -375,9 +484,11 @@ Both colonies are wired to real Claude agents via `withClaudeCode`. The dashboar
|
|
|
375
484
|
|
|
376
485
|
- [x] `mandible dev` CLI + live dashboard
|
|
377
486
|
- [x] `withClaudeCode` wired to Claude Code SDK
|
|
378
|
-
- [x] Test suite (
|
|
487
|
+
- [x] Test suite (378 tests, 95%+ coverage)
|
|
379
488
|
- [x] GitHub environment adapter
|
|
380
|
-
- [x]
|
|
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
|
|
381
492
|
- [ ] `create-mandible` starter template
|
|
382
493
|
- [ ] Dashboard GIF + landing page
|
|
383
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"}
|