@bolloon/bolloon-agent 0.2.9 → 0.2.11
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 +467 -467
- package/bin/bolloon-cli.cjs +183 -183
- package/bin/bolloon.cjs +0 -0
- package/bin/bolloon.js +157 -0
- package/dist/agents/agent-manifest-protocol.js +0 -52
- package/dist/agents/constraint-layer.js +19 -19
- package/dist/agents/pi-sdk.js +287 -1213
- package/dist/agents/shell-guard.js +2 -2
- package/dist/agents/workflow-pivot-loop.js +2 -81
- package/dist/bollharness/src/scripts/deploy-guard.js +8 -8
- package/dist/bollharness-integration/context-router-judgment.js +4 -4
- package/dist/bollharness-integration/context-router.js +292 -292
- package/dist/bollharness-integration/gate-state-machine.js +13 -26
- package/dist/bollharness-integration/integration.js +0 -71
- package/dist/bollharness-integration/llm-judgment-engine.js +134 -134
- package/dist/bollharness-integration/skill-adapter.js +127 -52
- package/dist/bootstrap/context-collector.js +3 -6
- package/dist/bootstrap/lifecycle-hooks.js +1 -15
- package/dist/cli-entry.js +35 -39
- package/dist/constraint-runtime/src/_archive_helper.js +9 -0
- package/dist/constraint-runtime/src/agent/coordinator.js +48 -0
- package/dist/constraint-runtime/src/agent/index.js +1 -0
- package/dist/constraint-runtime/src/assistant/index.js +12 -0
- package/dist/constraint-runtime/src/bootstrap/index.js +12 -0
- package/dist/constraint-runtime/src/bootstrap_graph.js +13 -0
- package/dist/constraint-runtime/src/bridge/index.js +12 -0
- package/dist/constraint-runtime/src/buddy/index.js +12 -0
- package/dist/constraint-runtime/src/cli/index.js +12 -0
- package/dist/constraint-runtime/src/command_graph.js +10 -0
- package/dist/constraint-runtime/src/commands.js +60 -0
- package/dist/constraint-runtime/src/components/index.js +12 -0
- package/dist/constraint-runtime/src/constants/index.js +12 -0
- package/dist/constraint-runtime/src/constraint/budget.js +22 -0
- package/dist/constraint-runtime/src/constraint/index.js +2 -0
- package/dist/constraint-runtime/src/constraint/permission.js +20 -0
- package/dist/constraint-runtime/src/context.js +30 -0
- package/dist/constraint-runtime/src/coordinator/index.js +12 -0
- package/dist/constraint-runtime/src/cost_hook.js +4 -0
- package/dist/constraint-runtime/src/cost_tracker.js +8 -0
- package/dist/constraint-runtime/src/deferred_init.js +10 -0
- package/dist/constraint-runtime/src/direct_modes.js +6 -0
- package/dist/constraint-runtime/src/dynamic-tool-loader.js +85 -0
- package/dist/constraint-runtime/src/entrypoints/index.js +12 -0
- package/dist/constraint-runtime/src/execution_registry.js +44 -0
- package/dist/constraint-runtime/src/history.js +9 -0
- package/dist/constraint-runtime/src/hooks/index.js +12 -0
- package/dist/constraint-runtime/src/index.js +26 -0
- package/dist/constraint-runtime/src/ink.js +4 -0
- package/dist/constraint-runtime/src/keybindings/index.js +12 -0
- package/dist/constraint-runtime/src/memdir/index.js +12 -0
- package/dist/constraint-runtime/src/migrations/index.js +12 -0
- package/dist/constraint-runtime/src/models.js +1 -0
- package/dist/constraint-runtime/src/moreright/index.js +12 -0
- package/dist/constraint-runtime/src/native_ts/index.js +12 -0
- package/dist/constraint-runtime/src/output_styles/index.js +12 -0
- package/dist/constraint-runtime/src/parity_audit.js +12 -0
- package/dist/constraint-runtime/src/plugins/index.js +12 -0
- package/dist/constraint-runtime/src/port_manifest.js +11 -0
- package/dist/constraint-runtime/src/prefetch.js +9 -0
- package/dist/constraint-runtime/src/query.js +1 -0
- package/dist/constraint-runtime/src/remote/index.js +12 -0
- package/dist/constraint-runtime/src/remote_runtime.js +9 -0
- package/dist/constraint-runtime/src/runtime/index.js +1 -0
- package/dist/constraint-runtime/src/runtime/session.js +35 -0
- package/dist/constraint-runtime/src/schemas/index.js +12 -0
- package/dist/constraint-runtime/src/screens/index.js +12 -0
- package/dist/constraint-runtime/src/server/index.js +12 -0
- package/dist/constraint-runtime/src/services/index.js +12 -0
- package/dist/constraint-runtime/src/session_store.js +22 -0
- package/dist/constraint-runtime/src/setup.js +30 -0
- package/dist/constraint-runtime/src/skills/index.js +1 -0
- package/dist/constraint-runtime/src/skills/skill-registry.js +28 -0
- package/dist/constraint-runtime/src/state/index.js +12 -0
- package/dist/constraint-runtime/src/system_init.js +20 -0
- package/dist/constraint-runtime/src/thinking/engine.js +42 -0
- package/dist/constraint-runtime/src/thinking/index.js +1 -0
- package/dist/constraint-runtime/src/tool_pool.js +8 -0
- package/dist/constraint-runtime/src/tools/OpenCLI/execAdapter.js +7 -0
- package/dist/constraint-runtime/src/tools/OpenCLI/listAdapters.js +7 -0
- package/dist/constraint-runtime/src/tools/OpenCLI/runCommand.js +7 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/confirmTransaction.js +6 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/createTransaction.js +8 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/executeTransaction.js +6 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/getBalance.js +6 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/getPendingTransactions.js +6 -0
- package/dist/constraint-runtime/src/tools/SafeSDK/proposeTransaction.js +6 -0
- package/dist/constraint-runtime/src/tools.js +80 -0
- package/dist/constraint-runtime/src/transcript.js +19 -0
- package/dist/constraint-runtime/src/types/index.js +12 -0
- package/dist/constraint-runtime/src/upstream_proxy/index.js +12 -0
- package/dist/constraint-runtime/src/utils/index.js +12 -0
- package/dist/constraint-runtime/src/vim/index.js +12 -0
- package/dist/constraint-runtime/src/voice/index.js +12 -0
- package/dist/constraint-runtime/tests/agent.test.js +16 -0
- package/dist/constraint-runtime/tests/constraint.test.js +41 -0
- package/dist/constraint-runtime/tests/skill.test.js +19 -0
- package/dist/constraint-runtime/tests/thinking.test.js +22 -0
- package/dist/context-compaction/auto-compact.js +7 -7
- package/dist/electron-preload.js +1 -18
- package/dist/electron-preload.js.map +1 -1
- package/dist/electron.js +168 -3
- package/dist/electron.js.map +1 -1
- package/dist/index.js +116 -136
- package/dist/llm/config-store.js +8 -24
- package/dist/llm/llm-judgment-client.js +102 -102
- package/dist/llm/pi-ai.js +85 -126
- package/dist/llm/system-prompt/layers/channel/local.md +14 -14
- package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -18
- package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -19
- package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -89
- package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -21
- package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -15
- package/dist/llm/system-prompt/layers/core/identity.md +37 -37
- package/dist/llm/system-prompt/layers/core/knowledge.md +17 -17
- package/dist/llm/system-prompt/layers/core/memory_system.md +12 -12
- package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -28
- package/dist/llm/system-prompt/layers/core/refusal.md +37 -37
- package/dist/llm/system-prompt/layers/core/tone.md +31 -31
- package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -13
- package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -41
- package/dist/llm/system-prompt/layers/role/architect.md +20 -20
- package/dist/llm/system-prompt/layers/role/expert.md +19 -19
- package/dist/llm/system-prompt/layers/role/implementer.md +15 -15
- package/dist/llm/system-prompt/layers/role/security.md +15 -15
- package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -72
- package/dist/llm/system-prompt/layers/tool/bash.md +25 -25
- package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -171
- package/dist/llm/system-prompt/layers/tool/image_search.md +70 -70
- package/dist/llm/system-prompt/layers/tool/manifest.md +89 -89
- package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -53
- package/dist/llm/system-prompt/layers/tool/web_search.md +83 -83
- package/dist/llm/tool-manifest/ask_user_input.js +1 -1
- package/dist/llm/tool-manifest/bash.js +3 -3
- package/dist/llm/tool-manifest/create_file.js +4 -4
- package/dist/llm/tool-manifest/fetch_sports_data.js +3 -3
- package/dist/llm/tool-manifest/image_search.js +2 -2
- package/dist/llm/tool-manifest/mcp.js +2 -2
- package/dist/llm/tool-manifest/message_compose.js +3 -3
- package/dist/llm/tool-manifest/places.js +2 -2
- package/dist/llm/tool-manifest/present_files.js +1 -1
- package/dist/llm/tool-manifest/recipe.js +2 -2
- package/dist/llm/tool-manifest/str_replace.js +5 -5
- package/dist/llm/tool-manifest/view.js +3 -3
- package/dist/llm/tool-manifest/weather.js +4 -4
- package/dist/llm/tool-manifest/web.js +4 -4
- package/dist/pi-ecosystem-colony/index.js +365 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +51 -51
- package/dist/pi-ecosystem-judgment/distill-prompt.js +42 -42
- package/dist/pi-ecosystem-judgment/distillation.js +14 -14
- package/dist/pi-ecosystem-judgment/monitor-gate.js +28 -28
- package/dist/pi-ecosystem-judgment/value-injection.js +102 -102
- package/dist/security/context-router-tool.js +15 -15
- package/dist/security/tool-gate.js +0 -11
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +101 -0
- package/dist/social/ant-colony/PheromoneEngine.js +227 -0
- package/dist/social/ant-colony/index.js +6 -0
- package/dist/social/ant-colony/types.js +24 -0
- package/dist/test/ai-judgment-test.js +80 -0
- package/dist/test/bollharness-integration.test.js +318 -0
- package/dist/test/channel-agent-multi-dialogue.js +205 -0
- package/dist/test/channel-heartbeat-agent-test.js +201 -0
- package/dist/test/constraint-layer.test.js +164 -0
- package/dist/test/diap-identity-test.js +172 -0
- package/dist/test/diap-quick-test.js +62 -0
- package/dist/test/global-shared-context.test.js +315 -0
- package/dist/test/harness-judgment-injection.test.js +246 -0
- package/dist/test/harness-workflow-integrator-test.js +228 -0
- package/dist/test/human-value-store.test.js +243 -0
- package/dist/test/hybrid-integration-test.js +118 -0
- package/dist/test/hybrid-messenger-verify.js +55 -0
- package/dist/test/iroh-bistream-debug.js +38 -0
- package/dist/test/iroh-communication.test.js +66 -0
- package/dist/test/iroh-debug-test.js +57 -0
- package/dist/test/iroh-diap-test.js +71 -0
- package/dist/test/iroh-direct-connect.js +55 -0
- package/dist/test/iroh-e2e-fixed.js +89 -0
- package/dist/test/iroh-e2e-same-process.js +63 -0
- package/dist/test/iroh-e2e.js +66 -0
- package/dist/test/iroh-final-e2e.js +72 -0
- package/dist/test/iroh-relay-test.js +37 -0
- package/dist/test/iroh-simple-test.js +41 -0
- package/dist/test/iroh-transport-verify.js +54 -0
- package/dist/test/iroh-transport.test.js +37 -0
- package/dist/test/iroh-two-nodes.js +70 -0
- package/dist/test/iroh-verify.js +44 -0
- package/dist/test/judgment-decision.test.js +219 -0
- package/dist/test/llm-judgment-integration.test.js +220 -0
- package/dist/test/p2p-agent-complex-dialogue.js +385 -0
- package/dist/test/p2p-agent-dialogue.js +341 -0
- package/dist/test/p2p-agent-full-bidirectional.js +510 -0
- package/dist/test/p2p-agent-harness-flow.js +437 -0
- package/dist/test/p2p-agent-harness-single.js +143 -0
- package/dist/test/p2p-ai-dialogue-test.js +318 -0
- package/dist/test/p2p-cid-connect-test.js +195 -0
- package/dist/test/p2p-connect-receiver.js +69 -0
- package/dist/test/p2p-doc-transfer.js +110 -0
- package/dist/test/p2p-identity-page-test.js +77 -0
- package/dist/test/p2p-iroh-test.js +171 -0
- package/dist/test/p2p-minimal-test.js +241 -0
- package/dist/test/p2p-node-1.js +148 -0
- package/dist/test/p2p-node-2.js +148 -0
- package/dist/test/p2p-server.js +281 -0
- package/dist/test/p2p-two-nodes-test.js +438 -0
- package/dist/test/pi-sdk.test.js +44 -0
- package/dist/test/set-persona.js +40 -0
- package/dist/test/simple.test.js +9 -0
- package/dist/test/storage-integration.test.js +150 -0
- package/dist/test/subagent-manager.test.js +276 -0
- package/dist/test/test-gate-flow.test.js +81 -0
- package/dist/test/workflow-engine.test.js +87 -0
- package/dist/test/workflow-pivot-loop.test.js +246 -0
- package/dist/web/api-config.html +520 -520
- package/dist/web/client.js +2917 -3791
- package/dist/web/components/p2p/index.js +234 -276
- package/dist/web/components/wallet-viem.mjs +118 -118
- package/dist/web/index.html +374 -373
- package/dist/web/manifest.json +20 -20
- package/dist/web/server.js +23 -775
- package/dist/web/style.css +4737 -4737
- package/dist/web/ui/message-renderer.js +373 -451
- package/dist/web/ui/step-timeline.js +255 -351
- package/package.json +160 -160
- package/scripts/build-cli.js +215 -215
- package/scripts/build-web.ts +125 -125
- package/scripts/postinstall.js +152 -152
- package/bin/bolloon-daemon.sh +0 -207
- package/bin/ipfs +0 -0
- package/dist/agents/chat-segmenter.js +0 -298
- package/dist/agents/judgment-protocol.js +0 -479
- package/dist/agents/parse-tool-call.js +0 -304
- package/dist/agents/peer-manifest-loader.js +0 -210
- package/dist/agents/react-loop.js +0 -120
- package/dist/agents/session-store.js +0 -171
- package/dist/agents/tool-registry.js +0 -136
- package/dist/bootstrap/chat-archiver.js +0 -276
- package/dist/bootstrap/memory-compressor.js +0 -170
- package/dist/bootstrap/persona-loader.js +0 -94
- package/dist/electron/config.js +0 -16
- package/dist/electron/config.js.map +0 -1
- package/dist/electron/dialogs.js +0 -71
- package/dist/electron/dialogs.js.map +0 -1
- package/dist/electron/first-run.js +0 -129
- package/dist/electron/first-run.js.map +0 -1
- package/dist/electron/ipc.js +0 -16
- package/dist/electron/ipc.js.map +0 -1
- package/dist/electron/logger.js +0 -77
- package/dist/electron/logger.js.map +0 -1
- package/dist/electron/main.js +0 -60
- package/dist/electron/main.js.map +0 -1
- package/dist/electron/menu.js +0 -140
- package/dist/electron/menu.js.map +0 -1
- package/dist/electron/paths.js +0 -33
- package/dist/electron/paths.js.map +0 -1
- package/dist/electron/server.js +0 -74
- package/dist/electron/server.js.map +0 -1
- package/dist/electron/tray.js +0 -73
- package/dist/electron/tray.js.map +0 -1
- package/dist/electron/window.js +0 -69
- package/dist/electron/window.js.map +0 -1
- package/dist/network/local-inbox-bus.js +0 -73
- package/dist/network/p2p-outbox.js +0 -161
- package/dist/network/peer-fs.js +0 -420
- package/dist/network/peer-resource-bridge.js +0 -216
- package/dist/web/components/p2p/P2PModal.js +0 -188
- package/dist/web/components/p2p/p2p-modal.js +0 -664
- package/dist/web/components/p2p/p2p-tools.js +0 -248
- package/dist/web/input-validator.js +0 -103
- package/dist/web/util/safe-name.js +0 -32
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { SubAgentManager, resetSubAgentManager } from '../agents/subagent-manager.js';
|
|
5
|
+
const TEST_STORAGE_PATH = path.join('/tmp', '.bolloon-test', 'agents');
|
|
6
|
+
describe('SubAgentManager', () => {
|
|
7
|
+
let manager;
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
resetSubAgentManager();
|
|
10
|
+
manager = new SubAgentManager({ storagePath: TEST_STORAGE_PATH });
|
|
11
|
+
try {
|
|
12
|
+
await fs.rm(TEST_STORAGE_PATH, { recursive: true, force: true });
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
});
|
|
16
|
+
describe('Agent Registration', () => {
|
|
17
|
+
it('should register a new agent', async () => {
|
|
18
|
+
await manager.initialize();
|
|
19
|
+
const agent = await manager.registerAgent({
|
|
20
|
+
name: 'TestAgent',
|
|
21
|
+
capabilities: ['coding', 'debugging'],
|
|
22
|
+
parentAgentId: 'parent-001'
|
|
23
|
+
});
|
|
24
|
+
expect(agent.id).toBeDefined();
|
|
25
|
+
expect(agent.name).toBe('TestAgent');
|
|
26
|
+
expect(agent.capabilities).toEqual(['coding', 'debugging']);
|
|
27
|
+
expect(agent.status).toBe('active');
|
|
28
|
+
expect(agent.parentAgentId).toBe('parent-001');
|
|
29
|
+
});
|
|
30
|
+
it('should update agent status', async () => {
|
|
31
|
+
await manager.initialize();
|
|
32
|
+
const agent = await manager.registerAgent({
|
|
33
|
+
name: 'TestAgent',
|
|
34
|
+
capabilities: ['coding']
|
|
35
|
+
});
|
|
36
|
+
await manager.updateAgentStatus(agent.id, 'busy');
|
|
37
|
+
const updated = await manager.getAgent(agent.id);
|
|
38
|
+
expect(updated?.status).toBe('busy');
|
|
39
|
+
});
|
|
40
|
+
it('should update agent info', async () => {
|
|
41
|
+
await manager.initialize();
|
|
42
|
+
const agent = await manager.registerAgent({
|
|
43
|
+
name: 'TestAgent',
|
|
44
|
+
capabilities: ['coding']
|
|
45
|
+
});
|
|
46
|
+
await manager.updateAgent(agent.id, {
|
|
47
|
+
did: 'did:key:test123',
|
|
48
|
+
walletAddress: '0x123...'
|
|
49
|
+
});
|
|
50
|
+
const updated = await manager.getAgent(agent.id);
|
|
51
|
+
expect(updated?.did).toBe('did:key:test123');
|
|
52
|
+
expect(updated?.walletAddress).toBe('0x123...');
|
|
53
|
+
});
|
|
54
|
+
it('should get all agents', async () => {
|
|
55
|
+
await manager.initialize();
|
|
56
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
57
|
+
await manager.registerAgent({ name: 'Agent2', capabilities: ['writing'] });
|
|
58
|
+
const agents = await manager.getAllAgents();
|
|
59
|
+
expect(agents).toHaveLength(2);
|
|
60
|
+
});
|
|
61
|
+
it('should get active agents only', async () => {
|
|
62
|
+
await manager.initialize();
|
|
63
|
+
const agent1 = await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
64
|
+
await manager.registerAgent({ name: 'Agent2', capabilities: ['writing'] });
|
|
65
|
+
await manager.updateAgentStatus(agent1.id, 'terminated');
|
|
66
|
+
const activeAgents = await manager.getActiveAgents();
|
|
67
|
+
expect(activeAgents).toHaveLength(1);
|
|
68
|
+
expect(activeAgents[0].name).toBe('Agent2');
|
|
69
|
+
});
|
|
70
|
+
it('should find agents by capability', async () => {
|
|
71
|
+
await manager.initialize();
|
|
72
|
+
await manager.registerAgent({ name: 'Coder', capabilities: ['coding', 'debugging'] });
|
|
73
|
+
await manager.registerAgent({ name: 'Writer', capabilities: ['writing', 'editing'] });
|
|
74
|
+
await manager.registerAgent({ name: 'FullStack', capabilities: ['coding', 'writing'] });
|
|
75
|
+
const coders = await manager.getAgentsByCapability('coding');
|
|
76
|
+
expect(coders).toHaveLength(2);
|
|
77
|
+
});
|
|
78
|
+
it('should find agent by DID', async () => {
|
|
79
|
+
await manager.initialize();
|
|
80
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'], did: 'did:key:abc' });
|
|
81
|
+
const agent = await manager.getAgentByDid('did:key:abc');
|
|
82
|
+
expect(agent?.name).toBe('Agent1');
|
|
83
|
+
});
|
|
84
|
+
it('should unregister agent', async () => {
|
|
85
|
+
await manager.initialize();
|
|
86
|
+
const agent = await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
87
|
+
await manager.unregisterAgent(agent.id);
|
|
88
|
+
const deleted = await manager.getAgent(agent.id);
|
|
89
|
+
expect(deleted).toBeUndefined();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
describe('Task Management', () => {
|
|
93
|
+
it('should create a task', async () => {
|
|
94
|
+
await manager.initialize();
|
|
95
|
+
const task = await manager.createTask('delegate', 'Fix bug', 'Fix the login bug in the authentication module', 'parent-001', 'agent-001', 'high', 'Bug ID: #1234');
|
|
96
|
+
expect(task.id).toBeDefined();
|
|
97
|
+
expect(task.title).toBe('Fix bug');
|
|
98
|
+
expect(task.type).toBe('delegate');
|
|
99
|
+
expect(task.priority).toBe('high');
|
|
100
|
+
expect(task.status).toBe('assigned');
|
|
101
|
+
});
|
|
102
|
+
it('should create pending task without assignee', async () => {
|
|
103
|
+
await manager.initialize();
|
|
104
|
+
const task = await manager.createTask('consult', 'Code review', 'Review the new API implementation', 'parent-001');
|
|
105
|
+
expect(task.status).toBe('pending');
|
|
106
|
+
expect(task.toAgentId).toBeUndefined();
|
|
107
|
+
});
|
|
108
|
+
it('should assign task to agent', async () => {
|
|
109
|
+
await manager.initialize();
|
|
110
|
+
const agent = await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
111
|
+
const task = await manager.createTask('delegate', 'Task', 'Description', 'parent-001');
|
|
112
|
+
await manager.assignTask(task.id, agent.id);
|
|
113
|
+
const updated = await manager.getTask(task.id);
|
|
114
|
+
expect(updated?.assignedAgentId).toBe(agent.id);
|
|
115
|
+
expect(updated?.status).toBe('assigned');
|
|
116
|
+
});
|
|
117
|
+
it('should update task status', async () => {
|
|
118
|
+
await manager.initialize();
|
|
119
|
+
const task = await manager.createTask('delegate', 'Task', 'Description', 'parent-001');
|
|
120
|
+
await manager.updateTaskStatus(task.id, 'completed', 'Task result', undefined);
|
|
121
|
+
const updated = await manager.getTask(task.id);
|
|
122
|
+
expect(updated?.status).toBe('completed');
|
|
123
|
+
expect(updated?.result).toBe('Task result');
|
|
124
|
+
expect(updated?.completedAt).toBeDefined();
|
|
125
|
+
});
|
|
126
|
+
it('should get tasks for agent', async () => {
|
|
127
|
+
await manager.initialize();
|
|
128
|
+
const agent = await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
129
|
+
await manager.createTask('delegate', 'Task1', 'Desc1', 'parent-001', agent.id);
|
|
130
|
+
await manager.createTask('delegate', 'Task2', 'Desc2', 'parent-001', agent.id);
|
|
131
|
+
const tasks = await manager.getTasksForAgent(agent.id);
|
|
132
|
+
expect(tasks).toHaveLength(2);
|
|
133
|
+
});
|
|
134
|
+
it('should get pending tasks', async () => {
|
|
135
|
+
await manager.initialize();
|
|
136
|
+
await manager.createTask('delegate', 'Task1', 'Desc1', 'parent-001');
|
|
137
|
+
await manager.createTask('delegate', 'Task2', 'Desc2', 'parent-001');
|
|
138
|
+
await manager.createTask('delegate', 'Task3', 'Desc3', 'parent-001', 'agent-001');
|
|
139
|
+
const pending = await manager.getPendingTasks();
|
|
140
|
+
expect(pending).toHaveLength(2);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
describe('Task Delegation', () => {
|
|
144
|
+
it('should find best agent for task', async () => {
|
|
145
|
+
await manager.initialize();
|
|
146
|
+
await manager.registerAgent({ name: 'Coder', capabilities: ['coding'] });
|
|
147
|
+
await manager.registerAgent({ name: 'Writer', capabilities: ['writing'] });
|
|
148
|
+
await manager.registerAgent({ name: 'FullStack', capabilities: ['coding', 'writing'] });
|
|
149
|
+
const agent = await manager.findBestAgentForTask(['coding']);
|
|
150
|
+
expect(agent).toBeDefined();
|
|
151
|
+
expect(agent?.capabilities).toContain('coding');
|
|
152
|
+
});
|
|
153
|
+
it('should delegate task to best available agent', async () => {
|
|
154
|
+
await manager.initialize();
|
|
155
|
+
await manager.registerAgent({ name: 'Coder', capabilities: ['coding'] });
|
|
156
|
+
const { task, agent } = await manager.delegateTask('parent-001', 'Implement the new feature', ['coding']);
|
|
157
|
+
expect(task.status).toBe('assigned');
|
|
158
|
+
expect(agent).toBeDefined();
|
|
159
|
+
expect(agent?.name).toBe('Coder');
|
|
160
|
+
});
|
|
161
|
+
it('should create pending task if no agent available', async () => {
|
|
162
|
+
await manager.initialize();
|
|
163
|
+
const { task, agent } = await manager.delegateTask('parent-001', 'Implement the new feature', ['quantum-computing']);
|
|
164
|
+
expect(task.status).toBe('pending');
|
|
165
|
+
expect(agent).toBeUndefined();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
describe('Inter-Agent Messaging', () => {
|
|
169
|
+
it('should send message between agents', async () => {
|
|
170
|
+
await manager.initialize();
|
|
171
|
+
await manager.registerAgent({ name: 'Sender', capabilities: ['coding'] });
|
|
172
|
+
await manager.registerAgent({ name: 'Receiver', capabilities: ['coding'] });
|
|
173
|
+
const message = await manager.sendMessage('sender-id', 'receiver-id', 'Hello, can you help with this task?', 'query');
|
|
174
|
+
expect(message.id).toBeDefined();
|
|
175
|
+
expect(message.content).toBe('Hello, can you help with this task?');
|
|
176
|
+
expect(message.type).toBe('query');
|
|
177
|
+
});
|
|
178
|
+
it('should get messages for agent', async () => {
|
|
179
|
+
await manager.initialize();
|
|
180
|
+
await manager.registerAgent({ name: 'Sender', capabilities: ['coding'] });
|
|
181
|
+
await manager.registerAgent({ name: 'Receiver', capabilities: ['coding'] });
|
|
182
|
+
await manager.sendMessage('sender-id', 'receiver-id', 'Message 1');
|
|
183
|
+
await manager.sendMessage('sender-id', 'receiver-id', 'Message 2');
|
|
184
|
+
const messages = await manager.getMessagesForAgent('receiver-id');
|
|
185
|
+
expect(messages).toHaveLength(2);
|
|
186
|
+
});
|
|
187
|
+
it('should receive messages via listener', async () => {
|
|
188
|
+
await manager.initialize();
|
|
189
|
+
await manager.registerAgent({ name: 'Sender', capabilities: ['coding'] });
|
|
190
|
+
await manager.registerAgent({ name: 'Receiver', capabilities: ['coding'] });
|
|
191
|
+
let receivedMessage = null;
|
|
192
|
+
const unsubscribe = manager.onMessage('receiver-id', (msg) => {
|
|
193
|
+
receivedMessage = msg;
|
|
194
|
+
});
|
|
195
|
+
await manager.sendMessage('sender-id', 'receiver-id', 'Test message');
|
|
196
|
+
expect(receivedMessage).toBeDefined();
|
|
197
|
+
expect(receivedMessage.content).toBe('Test message');
|
|
198
|
+
unsubscribe();
|
|
199
|
+
});
|
|
200
|
+
it('should broadcast message to all agents', async () => {
|
|
201
|
+
await manager.initialize();
|
|
202
|
+
const agent1 = await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
203
|
+
const agent2 = await manager.registerAgent({ name: 'Agent2', capabilities: ['coding'] });
|
|
204
|
+
const agent3 = await manager.registerAgent({ name: 'Agent3', capabilities: ['coding'] });
|
|
205
|
+
await manager.broadcastMessage('parent-id', 'System-wide notification');
|
|
206
|
+
const msgs1 = await manager.getMessagesForAgent(agent1.id);
|
|
207
|
+
const msgs2 = await manager.getMessagesForAgent(agent2.id);
|
|
208
|
+
const msgs3 = await manager.getMessagesForAgent(agent3.id);
|
|
209
|
+
expect(msgs1).toHaveLength(1);
|
|
210
|
+
expect(msgs2).toHaveLength(1);
|
|
211
|
+
expect(msgs3).toHaveLength(1);
|
|
212
|
+
});
|
|
213
|
+
it('should consult another agent', async () => {
|
|
214
|
+
await manager.initialize();
|
|
215
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
216
|
+
await manager.registerAgent({ name: 'Agent2', capabilities: ['coding'] });
|
|
217
|
+
const message = await manager.consultAgent('agent1-id', 'agent2-id', 'What is the best approach for this?');
|
|
218
|
+
expect(message.type).toBe('query');
|
|
219
|
+
expect(message.toAgentId).toBe('agent2-id');
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
describe('Task Listeners', () => {
|
|
223
|
+
it('should notify task listeners on status change', async () => {
|
|
224
|
+
await manager.initialize();
|
|
225
|
+
const task = await manager.createTask('delegate', 'Task', 'Desc', 'parent-001');
|
|
226
|
+
let updatedTask;
|
|
227
|
+
manager.onTask((t) => {
|
|
228
|
+
updatedTask = t;
|
|
229
|
+
});
|
|
230
|
+
await manager.updateTaskStatus(task.id, 'completed', 'Done');
|
|
231
|
+
expect(updatedTask).toBeDefined();
|
|
232
|
+
expect(updatedTask?.status).toBe('completed');
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
describe('Statistics', () => {
|
|
236
|
+
it('should return agent statistics', async () => {
|
|
237
|
+
await manager.initialize();
|
|
238
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
239
|
+
await manager.registerAgent({ name: 'Agent2', capabilities: ['writing'] });
|
|
240
|
+
await manager.createTask('delegate', 'Task1', 'Desc', 'parent-001');
|
|
241
|
+
await manager.createTask('delegate', 'Task2', 'Desc', 'parent-001', 'agent-001');
|
|
242
|
+
const stats = await manager.getAgentStatistics();
|
|
243
|
+
expect(stats.total).toBe(2);
|
|
244
|
+
expect(stats.pendingTasks).toBe(1);
|
|
245
|
+
expect(stats.activeTasks).toBe(1);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
describe('Persistence', () => {
|
|
249
|
+
it('should persist and reload agents', async () => {
|
|
250
|
+
await manager.initialize();
|
|
251
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
252
|
+
const newManager = new SubAgentManager({ storagePath: TEST_STORAGE_PATH });
|
|
253
|
+
await newManager.initialize();
|
|
254
|
+
const agents = await newManager.getAllAgents();
|
|
255
|
+
expect(agents).toHaveLength(1);
|
|
256
|
+
expect(agents[0].name).toBe('Agent1');
|
|
257
|
+
});
|
|
258
|
+
it('should persist and reload tasks', async () => {
|
|
259
|
+
await manager.initialize();
|
|
260
|
+
await manager.createTask('delegate', 'Task1', 'Desc', 'parent-001');
|
|
261
|
+
const newManager = new SubAgentManager({ storagePath: TEST_STORAGE_PATH });
|
|
262
|
+
await newManager.initialize();
|
|
263
|
+
const tasks = await newManager.getPendingTasks();
|
|
264
|
+
expect(tasks).toHaveLength(1);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
describe('Destroy', () => {
|
|
268
|
+
it('should clean up all data on destroy', async () => {
|
|
269
|
+
await manager.initialize();
|
|
270
|
+
await manager.registerAgent({ name: 'Agent1', capabilities: ['coding'] });
|
|
271
|
+
await manager.destroy();
|
|
272
|
+
const agents = await manager.getAllAgents();
|
|
273
|
+
expect(agents).toHaveLength(0);
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { GateStateMachine } from '../bollharness-integration/gate-state-machine.js';
|
|
3
|
+
import { initializeGateHooks, listGateHooks, clearGateHooks } from '../bollharness-integration/gate-transition-hooks.js';
|
|
4
|
+
import { generateJudgmentInjection, getCoreJudgmentsForSession, getJudgmentsForPath } from '../bollharness-integration/context-router-judgment.js';
|
|
5
|
+
import { getCombinedJudgments } from '../pi-ecosystem-judgment/index.js';
|
|
6
|
+
describe('Gate State Machine', () => {
|
|
7
|
+
it('should initialize at gate 0', () => {
|
|
8
|
+
const gsm = new GateStateMachine();
|
|
9
|
+
expect(gsm.getCurrentGate()).toBe(0);
|
|
10
|
+
});
|
|
11
|
+
it('should have correct gate pack', () => {
|
|
12
|
+
const gsm = new GateStateMachine();
|
|
13
|
+
const pack = gsm.getGatePack();
|
|
14
|
+
expect(pack.current_gate).toBe(0);
|
|
15
|
+
expect(pack.required_artifact).toBeTruthy();
|
|
16
|
+
expect(pack.required_next_skill).toBe('arch');
|
|
17
|
+
});
|
|
18
|
+
it('should transition to gate 1', async () => {
|
|
19
|
+
const gsm = new GateStateMachine();
|
|
20
|
+
const result = await gsm.transition();
|
|
21
|
+
expect(result.from).toBe(0);
|
|
22
|
+
expect(result.to).toBe(1);
|
|
23
|
+
expect(result.blockers).toHaveLength(0);
|
|
24
|
+
expect(gsm.getCurrentGate()).toBe(1);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('Gate Transition Hooks', () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
clearGateHooks();
|
|
30
|
+
});
|
|
31
|
+
it('should initialize without hooks', () => {
|
|
32
|
+
initializeGateHooks();
|
|
33
|
+
const hooks = listGateHooks();
|
|
34
|
+
expect(hooks).toBeDefined();
|
|
35
|
+
});
|
|
36
|
+
it('should load hooks from settings', () => {
|
|
37
|
+
initializeGateHooks();
|
|
38
|
+
const hooks = listGateHooks();
|
|
39
|
+
console.log('Loaded hooks:', hooks.length);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('Judgment System', () => {
|
|
43
|
+
it('should load judgments from YAML files', async () => {
|
|
44
|
+
const judgments = await getCombinedJudgments();
|
|
45
|
+
console.log('Total judgments loaded:', judgments.length);
|
|
46
|
+
judgments.forEach(j => {
|
|
47
|
+
console.log(` - ${j.id}: ${j.content ? j.content.substring(0, 30) : 'N/A'}... (${j.type}, conf: ${j.confidence})`);
|
|
48
|
+
});
|
|
49
|
+
expect(Array.isArray(judgments)).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
it('should generate core judgments for gate 0', async () => {
|
|
52
|
+
const injection = await getCoreJudgmentsForSession(0.9);
|
|
53
|
+
console.log('Core judgments length:', injection.length);
|
|
54
|
+
if (injection.length > 0) {
|
|
55
|
+
console.log('Core judgments sample:', injection.substring(0, 300));
|
|
56
|
+
}
|
|
57
|
+
expect(typeof injection).toBe('string');
|
|
58
|
+
});
|
|
59
|
+
it('should generate judgment injection for gate 0', async () => {
|
|
60
|
+
const injection = await generateJudgmentInjection('src/agents/', 0);
|
|
61
|
+
console.log('Gate 0 injection length:', injection.length);
|
|
62
|
+
if (injection.length > 0) {
|
|
63
|
+
console.log('Gate 0 injection:', injection.substring(0, 300));
|
|
64
|
+
}
|
|
65
|
+
expect(typeof injection).toBe('string');
|
|
66
|
+
});
|
|
67
|
+
it('should generate judgment injection for gate 3', async () => {
|
|
68
|
+
const injection = await generateJudgmentInjection('src/agents/', 3);
|
|
69
|
+
console.log('Gate 3 injection length:', injection.length);
|
|
70
|
+
if (injection.length > 0) {
|
|
71
|
+
console.log('Gate 3 injection:', injection.substring(0, 300));
|
|
72
|
+
}
|
|
73
|
+
expect(typeof injection).toBe('string');
|
|
74
|
+
});
|
|
75
|
+
it('should get judgments for path', async () => {
|
|
76
|
+
const result = await getJudgmentsForPath('src/agents/');
|
|
77
|
+
console.log('Path judgments - count:', result.judgments.length, 'confidence:', result.confidence);
|
|
78
|
+
expect(result.fragments).toBeDefined();
|
|
79
|
+
expect(Array.isArray(result.judgments)).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WorkflowEngine Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
5
|
+
import { WorkflowEngine } from '../agents/workflow-engine.js';
|
|
6
|
+
import { ConstraintLayer } from '../agents/constraint-layer.js';
|
|
7
|
+
// Mock dependencies
|
|
8
|
+
vi.mock('../documents/reader.js', () => ({
|
|
9
|
+
documentReader: {
|
|
10
|
+
read: vi.fn().mockResolvedValue({
|
|
11
|
+
text: 'test content',
|
|
12
|
+
metadata: { filename: 'test.txt', size: 12, type: '.txt' }
|
|
13
|
+
}),
|
|
14
|
+
chunk: vi.fn().mockReturnValue(['test content'])
|
|
15
|
+
}
|
|
16
|
+
}));
|
|
17
|
+
vi.mock('../llm/minimax.js', () => ({
|
|
18
|
+
getMinimax: vi.fn().mockReturnValue({
|
|
19
|
+
summarize: vi.fn().mockResolvedValue({ summary: 'test summary', qualityScore: 0.8 }),
|
|
20
|
+
improveContent: vi.fn().mockResolvedValue('improved content')
|
|
21
|
+
})
|
|
22
|
+
}));
|
|
23
|
+
vi.mock('../network/p2p.js', () => ({
|
|
24
|
+
p2pNetwork: {
|
|
25
|
+
getPeers: vi.fn().mockReturnValue(['peer1', 'peer2']),
|
|
26
|
+
sendMessage: vi.fn().mockResolvedValue(undefined),
|
|
27
|
+
broadcast: vi.fn().mockResolvedValue(undefined)
|
|
28
|
+
}
|
|
29
|
+
}));
|
|
30
|
+
describe('WorkflowEngine', () => {
|
|
31
|
+
let engine;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
engine = new WorkflowEngine();
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
});
|
|
36
|
+
describe('executeStep', () => {
|
|
37
|
+
it('should execute read step successfully', async () => {
|
|
38
|
+
const step = {
|
|
39
|
+
id: 'read',
|
|
40
|
+
type: 'read',
|
|
41
|
+
config: { path: 'test.txt' },
|
|
42
|
+
retry: { max: 0, current: 0, backoffMs: 0 },
|
|
43
|
+
onFail: 'abort'
|
|
44
|
+
};
|
|
45
|
+
const context = { peers: [], logs: [] };
|
|
46
|
+
const result = await engine.executeStep(step, context);
|
|
47
|
+
expect(result.status).toBe('success');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('executeWorkflow', () => {
|
|
51
|
+
it('should execute multiple steps in order', async () => {
|
|
52
|
+
const steps = [
|
|
53
|
+
{
|
|
54
|
+
id: 'read',
|
|
55
|
+
type: 'read',
|
|
56
|
+
config: { path: 'test.txt' },
|
|
57
|
+
retry: { max: 0, current: 0, backoffMs: 0 },
|
|
58
|
+
onFail: 'abort'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'chunk',
|
|
62
|
+
type: 'chunk',
|
|
63
|
+
config: { maxChunkSize: 1000 },
|
|
64
|
+
retry: { max: 0, current: 0, backoffMs: 0 },
|
|
65
|
+
onFail: 'abort'
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
const workflow = await engine.executeWorkflow(steps);
|
|
69
|
+
expect(workflow.status).toBe('completed');
|
|
70
|
+
expect(workflow.results.size).toBe(2);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
describe('getConstraintLayer', () => {
|
|
74
|
+
it('should return the constraint layer instance', () => {
|
|
75
|
+
const layer = engine.getConstraintLayer();
|
|
76
|
+
expect(layer).toBeDefined();
|
|
77
|
+
expect(layer instanceof ConstraintLayer).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('setConstraintLayer', () => {
|
|
81
|
+
it('should allow setting a custom constraint layer', () => {
|
|
82
|
+
const customLayer = new ConstraintLayer();
|
|
83
|
+
engine.setConstraintLayer(customLayer);
|
|
84
|
+
expect(engine.getConstraintLayer()).toBe(customLayer);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|