@treenity/mods 3.0.1 → 3.0.3
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/agent/client.ts +2 -0
- package/agent/guardian.ts +492 -0
- package/agent/seed.ts +74 -0
- package/agent/server.ts +4 -0
- package/agent/service.ts +644 -0
- package/agent/types.ts +184 -0
- package/agent/view.tsx +431 -0
- package/board/view.tsx +1 -1
- package/brahman/helpers.ts +7 -7
- package/brahman/service.ts +24 -24
- package/brahman/types.ts +21 -21
- package/brahman/views/action-cards.tsx +33 -23
- package/brahman/views/bot-view.tsx +3 -2
- package/brahman/views/chat-editor.tsx +119 -124
- package/brahman/views/menu-editor.tsx +75 -89
- package/brahman/views/page-layout.tsx +10 -8
- package/brahman/views/tstring-input.tsx +25 -15
- package/canary/service.ts +18 -18
- package/dist/board/view.js +1 -1
- package/dist/board/view.js.map +1 -1
- package/dist/brahman/helpers.d.ts +1 -1
- package/dist/brahman/helpers.d.ts.map +1 -1
- package/dist/brahman/helpers.js +6 -6
- package/dist/brahman/helpers.js.map +1 -1
- package/dist/brahman/service.js +24 -24
- package/dist/brahman/service.js.map +1 -1
- package/dist/brahman/types.d.ts +1 -1
- package/dist/brahman/types.d.ts.map +1 -1
- package/dist/brahman/types.js +21 -21
- package/dist/brahman/types.js.map +1 -1
- package/dist/brahman/views/action-cards.d.ts.map +1 -1
- package/dist/brahman/views/action-cards.js +7 -4
- package/dist/brahman/views/action-cards.js.map +1 -1
- package/dist/brahman/views/bot-view.d.ts.map +1 -1
- package/dist/brahman/views/bot-view.js +2 -1
- package/dist/brahman/views/bot-view.js.map +1 -1
- package/dist/brahman/views/chat-editor.d.ts.map +1 -1
- package/dist/brahman/views/chat-editor.js +27 -18
- package/dist/brahman/views/chat-editor.js.map +1 -1
- package/dist/brahman/views/menu-editor.d.ts.map +1 -1
- package/dist/brahman/views/menu-editor.js +12 -16
- package/dist/brahman/views/menu-editor.js.map +1 -1
- package/dist/brahman/views/page-layout.d.ts.map +1 -1
- package/dist/brahman/views/page-layout.js +1 -1
- package/dist/brahman/views/page-layout.js.map +1 -1
- package/dist/brahman/views/tstring-input.d.ts.map +1 -1
- package/dist/brahman/views/tstring-input.js +7 -3
- package/dist/brahman/views/tstring-input.js.map +1 -1
- package/dist/canary/service.js +18 -18
- package/dist/canary/service.js.map +1 -1
- package/dist/doc/fs-codec.js +1 -1
- package/dist/doc/fs-codec.js.map +1 -1
- package/dist/doc/renderers.d.ts.map +1 -1
- package/dist/doc/renderers.js +2 -1
- package/dist/doc/renderers.js.map +1 -1
- package/dist/doc/toolbar.d.ts.map +1 -1
- package/dist/doc/toolbar.js +5 -5
- package/dist/doc/toolbar.js.map +1 -1
- package/dist/launcher/types.js +2 -2
- package/dist/launcher/types.js.map +1 -1
- package/dist/launcher/view.js +2 -2
- package/dist/launcher/view.js.map +1 -1
- package/dist/mindmap/branch.d.ts +10 -0
- package/dist/mindmap/branch.d.ts.map +1 -1
- package/dist/mindmap/branch.js +42 -9
- package/dist/mindmap/branch.js.map +1 -1
- package/dist/mindmap/sidebar.d.ts.map +1 -1
- package/dist/mindmap/sidebar.js +4 -3
- package/dist/mindmap/sidebar.js.map +1 -1
- package/dist/mindmap/view.d.ts.map +1 -1
- package/dist/mindmap/view.js +35 -4
- package/dist/mindmap/view.js.map +1 -1
- package/dist/sensor-demo/service.js +6 -5
- package/dist/sensor-demo/service.js.map +1 -1
- package/dist/sensor-generator/action.js +1 -1
- package/dist/sensor-generator/action.js.map +1 -1
- package/dist/sim/service.js +41 -41
- package/dist/sim/service.js.map +1 -1
- package/dist/table/view.js.map +1 -1
- package/dist/todo/types.js +2 -2
- package/dist/todo/types.js.map +1 -1
- package/dist/todo/view.js +6 -4
- package/dist/todo/view.js.map +1 -1
- package/dist/whisper/inbox.js +3 -3
- package/dist/whisper/inbox.js.map +1 -1
- package/dist/whisper/route.d.ts +1 -1
- package/dist/whisper/route.d.ts.map +1 -1
- package/dist/whisper/route.js +13 -13
- package/dist/whisper/route.js.map +1 -1
- package/doc/CLAUDE.md +1 -1
- package/doc/fs-codec.ts +1 -1
- package/doc/renderers.tsx +4 -3
- package/doc/toolbar.tsx +12 -9
- package/launcher/types.ts +2 -2
- package/launcher/view.tsx +12 -8
- package/mcp/mcp-server.ts +393 -0
- package/mcp/server.ts +2 -0
- package/mcp/service.ts +18 -0
- package/mcp/types.ts +6 -0
- package/mindmap/branch.tsx +121 -22
- package/mindmap/mindmap.css +52 -0
- package/mindmap/sidebar.tsx +9 -6
- package/mindmap/view.tsx +40 -4
- package/package.json +30 -3
- package/sensor-demo/service.ts +6 -5
- package/sensor-generator/action.ts +1 -1
- package/sim/service.ts +41 -41
- package/table/view.tsx +7 -2
- package/todo/types.ts +2 -2
- package/todo/view.tsx +9 -10
- package/whisper/inbox.ts +3 -3
- package/whisper/route.ts +13 -13
- package/board/board.test.ts +0 -212
- package/brahman/brahman.test.ts +0 -855
- package/dist/mindmap/radial-tree.d.ts +0 -14
- package/dist/mindmap/radial-tree.d.ts.map +0 -1
- package/dist/mindmap/radial-tree.js +0 -184
- package/dist/mindmap/radial-tree.js.map +0 -1
- package/dist/mindmap/use-tree-data.d.ts +0 -14
- package/dist/mindmap/use-tree-data.d.ts.map +0 -1
- package/dist/mindmap/use-tree-data.js +0 -95
- package/dist/mindmap/use-tree-data.js.map +0 -1
- package/doc/fs-codec.test.ts +0 -119
- package/doc/markdown.test.ts +0 -152
- package/sim/sim.test.ts +0 -282
package/sim/sim.test.ts
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
// AgentSim tests — round engine, proximity, tools, quorum
|
|
2
|
-
|
|
3
|
-
import { createNode, getComponent, resolve } from '@treenity/core';
|
|
4
|
-
import type { ServiceHandle } from '@treenity/core/contexts/service';
|
|
5
|
-
import { createMemoryTree, type Tree } from '@treenity/core/tree';
|
|
6
|
-
import assert from 'node:assert/strict';
|
|
7
|
-
import { beforeEach, describe, it } from 'node:test';
|
|
8
|
-
import './service'; // registers handlers once (ESM cache)
|
|
9
|
-
|
|
10
|
-
let store: Tree;
|
|
11
|
-
|
|
12
|
-
function agent(path: string, name: string, icon: string, x: number, y: number, radius = 200) {
|
|
13
|
-
return createNode(path, 'sim.agent', {}, {
|
|
14
|
-
descriptive: { $type: 'sim.descriptive', name, icon, description: `${name} agent` },
|
|
15
|
-
ai: { $type: 'sim.ai', systemPrompt: `You are ${name}.` },
|
|
16
|
-
position: { $type: 'sim.position', x, y, radius },
|
|
17
|
-
memory: { $type: 'sim.memory', entries: [] },
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function world(path = '/w', running = false) {
|
|
22
|
-
return createNode(path, 'sim.world', {}, {
|
|
23
|
-
config: { $type: 'sim.config', width: 600, height: 400, roundDelay: 100, running },
|
|
24
|
-
round: { $type: 'sim.round', current: 0, phase: 'idle', log: [] },
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
store = createMemoryTree();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('sim.world registration', () => {
|
|
33
|
-
it('registers service handler', () => {
|
|
34
|
-
assert.ok(resolve('sim.world', 'service'));
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('registers start/stop actions', () => {
|
|
38
|
-
assert.ok(resolve('sim.world', 'action:start'));
|
|
39
|
-
assert.ok(resolve('sim.world', 'action:stop'));
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('start/stop actions', () => {
|
|
44
|
-
it('action:start sets running=true', async () => {
|
|
45
|
-
const w = world();
|
|
46
|
-
await store.set(w);
|
|
47
|
-
const handler = resolve('sim.world', 'action:start')!;
|
|
48
|
-
await handler({ node: w, store, signal: AbortSignal.timeout(5000) }, {});
|
|
49
|
-
// Handlers mutate ctx.node in-place; caller persists (executeAction or service loop)
|
|
50
|
-
await store.set(w);
|
|
51
|
-
const fresh = await store.get(w.$path);
|
|
52
|
-
assert.equal((getComponent(fresh!, 'config') as any).running, true);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('action:stop sets running=false', async () => {
|
|
56
|
-
const w = world('/w', true);
|
|
57
|
-
await store.set(w);
|
|
58
|
-
const handler = resolve('sim.world', 'action:stop')!;
|
|
59
|
-
await handler({ node: w, store, signal: AbortSignal.timeout(5000) }, {});
|
|
60
|
-
await store.set(w);
|
|
61
|
-
const fresh = await store.get(w.$path);
|
|
62
|
-
assert.equal((getComponent(fresh!, 'config') as any).running, false);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe('proximity', () => {
|
|
67
|
-
it('agents within radius are nearby', async () => {
|
|
68
|
-
await store.set(world('/w', true));
|
|
69
|
-
// Large radius covers entire map — stays nearby even after random moves
|
|
70
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100, 900));
|
|
71
|
-
await store.set(agent('/w/b', 'Bob', 'B', 200, 200, 900));
|
|
72
|
-
|
|
73
|
-
const svc = resolve('sim.world', 'service')!;
|
|
74
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
75
|
-
await new Promise((r) => setTimeout(r, 800));
|
|
76
|
-
await handle.stop();
|
|
77
|
-
|
|
78
|
-
const a = await store.get('/w/a');
|
|
79
|
-
const nearby = getComponent(a!, 'nearby') as any;
|
|
80
|
-
assert.ok(nearby);
|
|
81
|
-
assert.ok(nearby.agents.includes('Bob'));
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('agents outside radius are not nearby', async () => {
|
|
85
|
-
await store.set(world('/w', true));
|
|
86
|
-
await store.set(agent('/w/a', 'Alice', 'A', 0, 0, 50));
|
|
87
|
-
await store.set(agent('/w/b', 'Bob', 'B', 500, 500, 50)); // dist ~707 >> 50
|
|
88
|
-
|
|
89
|
-
const svc = resolve('sim.world', 'service')!;
|
|
90
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
91
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
92
|
-
await handle.stop();
|
|
93
|
-
|
|
94
|
-
const a = await store.get('/w/a');
|
|
95
|
-
const nearby = getComponent(a!, 'nearby') as any;
|
|
96
|
-
assert.ok(nearby);
|
|
97
|
-
assert.equal(nearby.agents.length, 0);
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
describe('round engine', () => {
|
|
102
|
-
it('advances round number after execution', async () => {
|
|
103
|
-
await store.set(world('/w', true));
|
|
104
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
105
|
-
|
|
106
|
-
const svc = resolve('sim.world', 'service')!;
|
|
107
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
108
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
109
|
-
await handle.stop();
|
|
110
|
-
|
|
111
|
-
const w = await store.get('/w');
|
|
112
|
-
const round = getComponent(w!, 'round') as any;
|
|
113
|
-
assert.ok(round.current >= 1, `expected round >= 1, got ${round.current}`);
|
|
114
|
-
assert.equal(round.phase, 'idle');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('does not run when running=false', async () => {
|
|
118
|
-
await store.set(world('/w', false));
|
|
119
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
120
|
-
|
|
121
|
-
const svc = resolve('sim.world', 'service')!;
|
|
122
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
123
|
-
await new Promise((r) => setTimeout(r, 400));
|
|
124
|
-
await handle.stop();
|
|
125
|
-
|
|
126
|
-
const w = await store.get('/w');
|
|
127
|
-
const round = getComponent(w!, 'round') as any;
|
|
128
|
-
assert.equal(round.current, 0);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('produces event log entries', async () => {
|
|
132
|
-
await store.set(world('/w', true));
|
|
133
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
134
|
-
await store.set(agent('/w/b', 'Bob', 'B', 200, 200));
|
|
135
|
-
|
|
136
|
-
const svc = resolve('sim.world', 'service')!;
|
|
137
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
138
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
139
|
-
await handle.stop();
|
|
140
|
-
|
|
141
|
-
const w = await store.get('/w');
|
|
142
|
-
const round = getComponent(w!, 'round') as any;
|
|
143
|
-
assert.ok(round.log.length > 0, 'expected at least 1 event in log');
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('log entries have required fields', async () => {
|
|
147
|
-
await store.set(world('/w', true));
|
|
148
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
149
|
-
|
|
150
|
-
const svc = resolve('sim.world', 'service')!;
|
|
151
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
152
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
153
|
-
await handle.stop();
|
|
154
|
-
|
|
155
|
-
const w = await store.get('/w');
|
|
156
|
-
const round = getComponent(w!, 'round') as any;
|
|
157
|
-
for (const entry of round.log) {
|
|
158
|
-
assert.ok(typeof entry.round === 'number');
|
|
159
|
-
assert.ok(typeof entry.agent === 'string');
|
|
160
|
-
assert.ok(typeof entry.action === 'string');
|
|
161
|
-
assert.ok(typeof entry.ts === 'number');
|
|
162
|
-
assert.ok(entry.data !== undefined);
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
describe('mock tools', () => {
|
|
168
|
-
it('move clamps to world bounds', async () => {
|
|
169
|
-
await store.set(world('/w', true));
|
|
170
|
-
// Place agent so random move could exceed bounds
|
|
171
|
-
await store.set(agent('/w/a', 'Alice', 'A', 599, 399));
|
|
172
|
-
|
|
173
|
-
const svc = resolve('sim.world', 'service')!;
|
|
174
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
175
|
-
// Run several rounds to get a move action
|
|
176
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
177
|
-
await handle.stop();
|
|
178
|
-
|
|
179
|
-
const a = await store.get('/w/a');
|
|
180
|
-
const pos = getComponent(a!, 'position') as any;
|
|
181
|
-
assert.ok(pos.x >= 0 && pos.x <= 600, `x=${pos.x} out of bounds`);
|
|
182
|
-
assert.ok(pos.y >= 0 && pos.y <= 400, `y=${pos.y} out of bounds`);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('remember adds to memory', async () => {
|
|
186
|
-
await store.set(world('/w', true));
|
|
187
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
188
|
-
|
|
189
|
-
const svc = resolve('sim.world', 'service')!;
|
|
190
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
191
|
-
// Run enough rounds for a remember action (mock: ~30% chance per round)
|
|
192
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
193
|
-
await handle.stop();
|
|
194
|
-
|
|
195
|
-
// Check if memory was modified (at least one remember should fire in ~10 rounds)
|
|
196
|
-
const a = await store.get('/w/a');
|
|
197
|
-
const mem = getComponent(a!, 'memory') as any;
|
|
198
|
-
// Can't guarantee remember fires, so just verify shape is intact
|
|
199
|
-
assert.ok(Array.isArray(mem.entries));
|
|
200
|
-
assert.ok(mem.entries.length <= 20, 'memory should be capped at 20');
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('speak sets heardBy for nearby agents', async () => {
|
|
204
|
-
await store.set(world('/w', true));
|
|
205
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100, 300));
|
|
206
|
-
await store.set(agent('/w/b', 'Bob', 'B', 150, 150, 300));
|
|
207
|
-
|
|
208
|
-
const svc = resolve('sim.world', 'service')!;
|
|
209
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
210
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
211
|
-
await handle.stop();
|
|
212
|
-
|
|
213
|
-
const w = await store.get('/w');
|
|
214
|
-
const round = getComponent(w!, 'round') as any;
|
|
215
|
-
const speakEvents = round.log.filter((e: any) => e.action === 'speak');
|
|
216
|
-
assert.ok(speakEvents.length > 0, 'should have at least one speak event');
|
|
217
|
-
for (const e of speakEvents) {
|
|
218
|
-
assert.ok(Array.isArray(e.heardBy), 'speak event should have heardBy');
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
describe('quorum (parallel execution)', () => {
|
|
224
|
-
it('all agents act in same round', async () => {
|
|
225
|
-
await store.set(world('/w', true));
|
|
226
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
227
|
-
await store.set(agent('/w/b', 'Bob', 'B', 200, 200));
|
|
228
|
-
await store.set(agent('/w/c', 'Eve', 'C', 300, 300));
|
|
229
|
-
|
|
230
|
-
const svc = resolve('sim.world', 'service')!;
|
|
231
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
232
|
-
// Run several rounds — remember actions don't produce log entries, need enough rounds
|
|
233
|
-
await new Promise((r) => setTimeout(r, 1500));
|
|
234
|
-
await handle.stop();
|
|
235
|
-
|
|
236
|
-
const w = await store.get('/w');
|
|
237
|
-
const round = getComponent(w!, 'round') as any;
|
|
238
|
-
assert.ok(round.log.length >= 1, 'should have at least 1 event across all rounds');
|
|
239
|
-
// Verify multiple agents produced events across rounds
|
|
240
|
-
const actors = new Set(round.log.map((e: any) => e.agent));
|
|
241
|
-
assert.ok(actors.size >= 2, `expected >= 2 actors, got ${actors.size}: ${[...actors]}`);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
describe('service lifecycle', () => {
|
|
246
|
-
it('stop halts the service', async () => {
|
|
247
|
-
await store.set(world('/w', true));
|
|
248
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100));
|
|
249
|
-
|
|
250
|
-
const svc = resolve('sim.world', 'service')!;
|
|
251
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
252
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
253
|
-
await handle.stop();
|
|
254
|
-
|
|
255
|
-
const w1 = await store.get('/w');
|
|
256
|
-
const round1 = (getComponent(w1!, 'round') as any).current;
|
|
257
|
-
|
|
258
|
-
// Wait more — should NOT advance
|
|
259
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
260
|
-
const w2 = await store.get('/w');
|
|
261
|
-
const round2 = (getComponent(w2!, 'round') as any).current;
|
|
262
|
-
assert.equal(round1, round2, 'round should not advance after stop');
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
describe('log trimming', () => {
|
|
267
|
-
it('log stays within 50 entries', async () => {
|
|
268
|
-
await store.set(world('/w', true));
|
|
269
|
-
await store.set(agent('/w/a', 'Alice', 'A', 100, 100, 300));
|
|
270
|
-
await store.set(agent('/w/b', 'Bob', 'B', 150, 150, 300));
|
|
271
|
-
|
|
272
|
-
const svc = resolve('sim.world', 'service')!;
|
|
273
|
-
const handle: ServiceHandle = await svc((await store.get('/w'))!, { store, subscribe: () => () => {} });
|
|
274
|
-
// Run many rounds
|
|
275
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
276
|
-
await handle.stop();
|
|
277
|
-
|
|
278
|
-
const w = await store.get('/w');
|
|
279
|
-
const round = getComponent(w!, 'round') as any;
|
|
280
|
-
assert.ok(round.log.length <= 50, `log has ${round.log.length} entries, expected <= 50`);
|
|
281
|
-
});
|
|
282
|
-
});
|