@bolloon/bolloon-agent 0.2.8 → 0.2.10
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 -157
- package/scripts/build-cli.js +216 -0
- package/scripts/build-web.ts +125 -0
- package/scripts/postinstall.js +153 -0
- 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,219 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { evaluateDecision, submitDecisionResponse, queryInternalAgents, getPendingDecisions, getDecisionRequest, getDecisionStats, setConfidenceThreshold, setDefaultDecisionLevel, } from '../pi-ecosystem-judgment/decision.js';
|
|
3
|
+
import * as judgmentModule from '../pi-ecosystem-judgment/index.js';
|
|
4
|
+
vi.mock('../pi-ecosystem-colony/index.js', () => ({
|
|
5
|
+
listAnts: vi.fn().mockReturnValue([
|
|
6
|
+
{ id: 'ant-1', name: 'BuilderAnt', signal: 'ACTIVE', capabilities: ['coding'] },
|
|
7
|
+
{ id: 'ant-2', name: 'ReviewerAnt', signal: 'ACTIVE', capabilities: ['review'] },
|
|
8
|
+
{ id: 'ant-3', name: 'TesterAnt', signal: 'ACTIVE', capabilities: ['testing'] },
|
|
9
|
+
]),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock('../pi-ecosystem-subagents/index.js', () => ({
|
|
12
|
+
listSubagents: vi.fn().mockReturnValue([
|
|
13
|
+
{ id: 'sub-1', name: 'CodeSubagent', status: 'running', capabilities: ['coding'] },
|
|
14
|
+
{ id: 'sub-2', name: 'DocSubagent', status: 'running', capabilities: ['writing'] },
|
|
15
|
+
]),
|
|
16
|
+
}));
|
|
17
|
+
describe('Decision System - Internal vs External Judgment Communication', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
setConfidenceThreshold(0.7);
|
|
20
|
+
setDefaultDecisionLevel('autonomous');
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
describe('Decision Level Determination', () => {
|
|
24
|
+
it('should be autonomous when confidence >= threshold', async () => {
|
|
25
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.9);
|
|
26
|
+
const request = await evaluateDecision('Use const instead of var', 'typescript', 'agent-001', 0.7);
|
|
27
|
+
expect(request.level).toBe('autonomous');
|
|
28
|
+
expect(request.targets).toEqual([]);
|
|
29
|
+
expect(request.status).toBe('pending');
|
|
30
|
+
});
|
|
31
|
+
it('should consult_internal when confidence >= threshold * 0.7 but < threshold', async () => {
|
|
32
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.5);
|
|
33
|
+
const request = await evaluateDecision('Refactor this function', 'refactor', 'agent-001', 0.7);
|
|
34
|
+
expect(request.level).toBe('consult_internal');
|
|
35
|
+
expect(request.targets).toContain('colony_ant');
|
|
36
|
+
expect(request.targets).toContain('subagent');
|
|
37
|
+
expect(request.targets).not.toContain('p2p_agent');
|
|
38
|
+
expect(request.targets).not.toContain('human');
|
|
39
|
+
});
|
|
40
|
+
it('should consult_external when confidence >= threshold * 0.4 but < threshold * 0.7', async () => {
|
|
41
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.35);
|
|
42
|
+
const request = await evaluateDecision('Cross-system migration strategy', 'migration', 'agent-001', 0.7);
|
|
43
|
+
expect(request.level).toBe('consult_external');
|
|
44
|
+
expect(request.targets).toContain('p2p_agent');
|
|
45
|
+
expect(request.targets).toContain('colony_ant');
|
|
46
|
+
expect(request.targets).toContain('subagent');
|
|
47
|
+
});
|
|
48
|
+
it('should require_human when confidence < threshold * 0.4', async () => {
|
|
49
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.2);
|
|
50
|
+
const request = await evaluateDecision('Strategic pivot decision', 'strategy', 'agent-001', 0.7);
|
|
51
|
+
expect(request.level).toBe('require_human');
|
|
52
|
+
expect(request.targets).toEqual(['human']);
|
|
53
|
+
});
|
|
54
|
+
it('should default to confidence 0.5 when no judgments exist', async () => {
|
|
55
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.5);
|
|
56
|
+
const request = await evaluateDecision('No prior judgment context', 'unknown', 'agent-001', 0.7);
|
|
57
|
+
expect(request.confidence).toBe(0.5);
|
|
58
|
+
expect(request.level).toBe('consult_internal');
|
|
59
|
+
expect(request.targets).toContain('colony_ant');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe('Internal Consultation (colony_ant, subagent)', () => {
|
|
63
|
+
it('should query up to 3 colony ants for consult_internal', async () => {
|
|
64
|
+
const request = await evaluateDecision('Which approach is better: A or B?', 'decision', 'agent-001', 0.7);
|
|
65
|
+
request.level = 'consult_internal';
|
|
66
|
+
request.targets = ['colony_ant', 'subagent'];
|
|
67
|
+
const results = await queryInternalAgents(request);
|
|
68
|
+
expect(results.length).toBeGreaterThan(0);
|
|
69
|
+
expect(results.some(r => r.target === 'colony_ant')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
it('should query up to 2 subagents for consult_internal', async () => {
|
|
72
|
+
const request = await evaluateDecision('Code review decision', 'review', 'agent-001', 0.7);
|
|
73
|
+
request.level = 'consult_internal';
|
|
74
|
+
request.targets = ['colony_ant', 'subagent'];
|
|
75
|
+
const results = await queryInternalAgents(request);
|
|
76
|
+
expect(results.some(r => r.target === 'subagent')).toBe(true);
|
|
77
|
+
});
|
|
78
|
+
it('should include consultation results in request', async () => {
|
|
79
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.5);
|
|
80
|
+
const request = await evaluateDecision('Implementation strategy', 'strategy', 'agent-001', 0.7);
|
|
81
|
+
expect(request.targets.length).toBeGreaterThan(0);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('External Consultation (p2p_agent)', () => {
|
|
85
|
+
it('should include p2p_agent in consult_external targets', async () => {
|
|
86
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.35);
|
|
87
|
+
const request = await evaluateDecision('Peer system integration decision', 'integration', 'agent-001', 0.7);
|
|
88
|
+
expect(request.level).toBe('consult_external');
|
|
89
|
+
expect(request.targets).toContain('p2p_agent');
|
|
90
|
+
});
|
|
91
|
+
it('should support external peer-to-peer consultation', async () => {
|
|
92
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.35);
|
|
93
|
+
const request = await evaluateDecision('Protocol version negotiation', 'protocol', 'agent-001', 0.7);
|
|
94
|
+
expect(request.targets).toContain('p2p_agent');
|
|
95
|
+
expect(request.targets).toContain('colony_ant');
|
|
96
|
+
expect(request.targets).toContain('subagent');
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe('Decision Response Flow', () => {
|
|
100
|
+
it('should update status to authorized on positive response', async () => {
|
|
101
|
+
const request = await evaluateDecision('Proceed with deployment', 'deploy', 'agent-001', 0.7);
|
|
102
|
+
const response = await submitDecisionResponse(request.id, {
|
|
103
|
+
authorized: true,
|
|
104
|
+
content: 'Approved',
|
|
105
|
+
by: 'human',
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
});
|
|
108
|
+
expect(response?.status).toBe('authorized');
|
|
109
|
+
expect(response?.respondedAt).toBeDefined();
|
|
110
|
+
});
|
|
111
|
+
it('should update status to rejected on negative response', async () => {
|
|
112
|
+
const request = await evaluateDecision('Skip tests for faster delivery', 'testing', 'agent-001', 0.7);
|
|
113
|
+
const response = await submitDecisionResponse(request.id, {
|
|
114
|
+
authorized: false,
|
|
115
|
+
content: 'No, tests are required',
|
|
116
|
+
by: 'human',
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
});
|
|
119
|
+
expect(response?.status).toBe('rejected');
|
|
120
|
+
});
|
|
121
|
+
it('should support delegation to other targets', async () => {
|
|
122
|
+
const request = await evaluateDecision('Architecture decision', 'architecture', 'agent-001', 0.7);
|
|
123
|
+
const response = await submitDecisionResponse(request.id, {
|
|
124
|
+
authorized: true,
|
|
125
|
+
content: 'Delegating to senior architect',
|
|
126
|
+
delegate: 'colony_ant',
|
|
127
|
+
by: 'human',
|
|
128
|
+
timestamp: new Date().toISOString(),
|
|
129
|
+
});
|
|
130
|
+
expect(response?.response?.delegate).toBe('colony_ant');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('Decision State Tracking', () => {
|
|
134
|
+
it('should track pending decisions', async () => {
|
|
135
|
+
await evaluateDecision('Decision 1', 'context', 'agent-001', 0.7);
|
|
136
|
+
await evaluateDecision('Decision 2', 'context', 'agent-001', 0.7);
|
|
137
|
+
const pending = getPendingDecisions();
|
|
138
|
+
expect(pending.length).toBeGreaterThanOrEqual(2);
|
|
139
|
+
});
|
|
140
|
+
it('should retrieve decision by ID', async () => {
|
|
141
|
+
const created = await evaluateDecision('Test Decision', 'context', 'agent-001', 0.7);
|
|
142
|
+
const retrieved = getDecisionRequest(created.id);
|
|
143
|
+
expect(retrieved).toBeDefined();
|
|
144
|
+
expect(retrieved?.description).toBe('Test Decision');
|
|
145
|
+
});
|
|
146
|
+
it('should calculate decision statistics', async () => {
|
|
147
|
+
await evaluateDecision('Decision A', 'context', 'agent-001', 0.7);
|
|
148
|
+
await evaluateDecision('Decision B', 'context', 'agent-001', 0.7);
|
|
149
|
+
const stats = getDecisionStats();
|
|
150
|
+
expect(stats.total).toBeGreaterThanOrEqual(2);
|
|
151
|
+
expect(stats.pending).toBeGreaterThanOrEqual(2);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe('Threshold Sensitivity', () => {
|
|
155
|
+
it('should escalate to require_human with very high threshold', async () => {
|
|
156
|
+
setConfidenceThreshold(0.9);
|
|
157
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.3);
|
|
158
|
+
const request = await evaluateDecision('Conservative decision', 'context', 'agent-001');
|
|
159
|
+
expect(request.level).toBe('require_human');
|
|
160
|
+
expect(request.targets).toEqual(['human']);
|
|
161
|
+
});
|
|
162
|
+
it('should be autonomous with low threshold', async () => {
|
|
163
|
+
setConfidenceThreshold(0.3);
|
|
164
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(0.5);
|
|
165
|
+
const request = await evaluateDecision('Aggressive decision', 'context', 'agent-001');
|
|
166
|
+
expect(request.level).toBe('autonomous');
|
|
167
|
+
expect(request.targets).toEqual([]);
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('Cross-Cutting Concerns', () => {
|
|
171
|
+
it('should create unique decision IDs', async () => {
|
|
172
|
+
const request1 = await evaluateDecision('Decision 1', 'c', 'a', 0.7);
|
|
173
|
+
const request2 = await evaluateDecision('Decision 2', 'c', 'a', 0.7);
|
|
174
|
+
expect(request1.id).not.toBe(request2.id);
|
|
175
|
+
});
|
|
176
|
+
it('should include agent ID in request', async () => {
|
|
177
|
+
const request = await evaluateDecision('Test', 'c', 'my-agent-123', 0.7);
|
|
178
|
+
expect(request.agentId).toBe('my-agent-123');
|
|
179
|
+
});
|
|
180
|
+
it('should record creation timestamp', async () => {
|
|
181
|
+
const before = new Date().toISOString();
|
|
182
|
+
const request = await evaluateDecision('Test', 'c', 'a', 0.7);
|
|
183
|
+
const after = new Date().toISOString();
|
|
184
|
+
expect(request.createdAt).toBeDefined();
|
|
185
|
+
expect(request.createdAt >= before).toBe(true);
|
|
186
|
+
expect(request.createdAt <= after).toBe(true);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe('Decision Level Boundary Conditions', () => {
|
|
191
|
+
beforeEach(() => {
|
|
192
|
+
setConfidenceThreshold(0.7);
|
|
193
|
+
});
|
|
194
|
+
it.each([
|
|
195
|
+
{ confidence: 0.9, expectedLevel: 'autonomous' },
|
|
196
|
+
{ confidence: 0.5, expectedLevel: 'consult_internal' },
|
|
197
|
+
{ confidence: 0.35, expectedLevel: 'consult_external' },
|
|
198
|
+
{ confidence: 0.2, expectedLevel: 'require_human' },
|
|
199
|
+
])('confidence $confidence should map to $expectedLevel', async ({ confidence, expectedLevel }) => {
|
|
200
|
+
vi.spyOn(judgmentModule, 'calculateConfidence').mockReturnValueOnce(confidence);
|
|
201
|
+
const request = await evaluateDecision('Boundary test', 'boundary', 'agent-001', 0.7);
|
|
202
|
+
expect(request.level).toBe(expectedLevel);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
describe('Consultation Target Matrix', () => {
|
|
206
|
+
beforeEach(() => {
|
|
207
|
+
setConfidenceThreshold(0.7);
|
|
208
|
+
});
|
|
209
|
+
const matrix = [
|
|
210
|
+
{ level: 'autonomous', expectedTargets: [] },
|
|
211
|
+
{ level: 'consult_internal', expectedTargets: ['colony_ant', 'subagent'] },
|
|
212
|
+
{ level: 'consult_external', expectedTargets: ['colony_ant', 'subagent', 'p2p_agent'] },
|
|
213
|
+
{ level: 'require_human', expectedTargets: ['human'] },
|
|
214
|
+
];
|
|
215
|
+
it.each(matrix)('level $level should have targets $expectedTargets', ({ level, expectedTargets }) => {
|
|
216
|
+
expect(level).toBeDefined();
|
|
217
|
+
expect(expectedTargets).toBeDefined();
|
|
218
|
+
});
|
|
219
|
+
});
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-as-Judge 集成测试
|
|
3
|
+
*
|
|
4
|
+
* 测试内容:
|
|
5
|
+
* 1. LLMJudgmentClient 的 LLM 调用
|
|
6
|
+
* 2. Prompt 变体 (concise/standard/deep) 的选择
|
|
7
|
+
* 3. Skill Prompt 配置化
|
|
8
|
+
* 4. ChannelJudgmentEngine 的 LLM 集成
|
|
9
|
+
*
|
|
10
|
+
* 运行: npx tsx src/test/llm-judgment-integration.test.ts
|
|
11
|
+
*/
|
|
12
|
+
import { config } from 'dotenv';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { createLLMJudgmentClient, JUDGMENT_PROMPTS } from '../llm/llm-judgment-client.js';
|
|
16
|
+
import { createChannelJudgmentEngine } from '../bollharness-integration/channel-judgment-engine.js';
|
|
17
|
+
import { createLLMJudgmentEngine, SKILL_PROMPTS } from '../bollharness-integration/llm-judgment-engine.js';
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
config();
|
|
20
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = path.dirname(__filename);
|
|
22
|
+
// 测试用例
|
|
23
|
+
const TEST_CASES = [
|
|
24
|
+
{
|
|
25
|
+
input: '我们需要设计一个用户认证系统,包含登录、注册和OAuth社交登录。',
|
|
26
|
+
description: '架构设计问题',
|
|
27
|
+
expected: { approach: 'design', complexity: 'complex' }
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
input: '帮我 review 一下这段代码有没有安全问题',
|
|
31
|
+
description: '代码审查问题',
|
|
32
|
+
expected: { approach: 'analyze', skills: ['guardian-fixer'] }
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
input: '如何实现JWT token的刷新机制?',
|
|
36
|
+
description: '实现问题',
|
|
37
|
+
expected: { approach: 'implement' }
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
input: '这个任务比较复杂,帮我分解一下',
|
|
41
|
+
description: '任务分解问题',
|
|
42
|
+
expected: { approach: 'coordinate', skills: ['task-arch'] }
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
// 测试 Prompt 变体
|
|
46
|
+
async function testPromptVariants() {
|
|
47
|
+
console.log('\n━━━ Prompt 变体测试 ━━━\n');
|
|
48
|
+
const client = await createLLMJudgmentClient({ useLLM: true });
|
|
49
|
+
for (const promptName of ['default', 'architecture', 'code', 'security']) {
|
|
50
|
+
const config = JUDGMENT_PROMPTS[promptName];
|
|
51
|
+
console.log(`[${promptName}]`);
|
|
52
|
+
console.log(` System prompt 长度: ${config.systemPrompt.length} 字符`);
|
|
53
|
+
console.log(` Output format: ${config.outputFormat}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 测试 LLMJudgmentClient
|
|
57
|
+
async function testLLMJudgmentClient() {
|
|
58
|
+
console.log('\n━━━ LLMJudgmentClient 测试 ━━━\n');
|
|
59
|
+
const client = await createLLMJudgmentClient({ useLLM: false }); // 快速模式
|
|
60
|
+
for (const tc of TEST_CASES) {
|
|
61
|
+
console.log(`测试: ${tc.description}`);
|
|
62
|
+
console.log(`输入: "${tc.input.substring(0, 40)}..."`);
|
|
63
|
+
const result = await client.judge(tc.input, {
|
|
64
|
+
senderName: 'TestUser',
|
|
65
|
+
history: ['之前的对话']
|
|
66
|
+
});
|
|
67
|
+
console.log(` Approach: ${result.decision.approach}`);
|
|
68
|
+
console.log(` Complexity: ${result.assessment.complexity}`);
|
|
69
|
+
console.log(` Skills: ${result.routing.skills.join(', ')}`);
|
|
70
|
+
console.log();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// 测试 Skill Prompts 配置
|
|
74
|
+
function testSkillPromptsConfig() {
|
|
75
|
+
console.log('\n━━━ Skill Prompts 配置化测试 ━━━\n');
|
|
76
|
+
const skillNames = Object.keys(SKILL_PROMPTS);
|
|
77
|
+
console.log(`已配置的 Skills: ${skillNames.join(', ')}\n`);
|
|
78
|
+
for (const [name, skill] of Object.entries(SKILL_PROMPTS)) {
|
|
79
|
+
console.log(`[${name}]`);
|
|
80
|
+
console.log(` 名称: ${skill.name}`);
|
|
81
|
+
console.log(` 描述: ${skill.description}`);
|
|
82
|
+
console.log(` System prompt 长度: ${skill.systemPrompt.length} 字符`);
|
|
83
|
+
console.log(` Output format: ${skill.outputFormat}`);
|
|
84
|
+
console.log();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// 测试 YAML 配置加载
|
|
88
|
+
async function testYAMLConfig() {
|
|
89
|
+
console.log('\n━━━ YAML 配置文件测试 ━━━\n');
|
|
90
|
+
const yamlPath = path.join(__dirname, '../bollharness-integration/judgment-prompts.yaml');
|
|
91
|
+
try {
|
|
92
|
+
const content = fs.readFileSync(yamlPath, 'utf-8');
|
|
93
|
+
console.log(`✓ YAML 配置文件存在`);
|
|
94
|
+
console.log(` 路径: ${yamlPath}`);
|
|
95
|
+
console.log(` 大小: ${content.length} 字节`);
|
|
96
|
+
// 简单解析检查
|
|
97
|
+
const hasPromptVariants = content.includes('prompt_variants');
|
|
98
|
+
const hasSkills = content.includes('skills:');
|
|
99
|
+
const hasOutputFormats = content.includes('output_formats');
|
|
100
|
+
console.log(` 包含 Prompt 变体: ${hasPromptVariants ? '✓' : '✗'}`);
|
|
101
|
+
console.log(` 包含 Skills 配置: ${hasSkills ? '✓' : '✗'}`);
|
|
102
|
+
console.log(` 包含输出格式: ${hasOutputFormats ? '✓' : '✗'}`);
|
|
103
|
+
// 解析行数统计
|
|
104
|
+
const lines = content.split('\n').filter(l => l.trim() && !l.trim().startsWith('#'));
|
|
105
|
+
console.log(` 非注释行数: ${lines.length}`);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error(`✗ YAML 配置文件读取失败:`, err);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// 测试 ChannelJudgmentEngine
|
|
112
|
+
async function testChannelJudgmentEngine() {
|
|
113
|
+
console.log('\n━━━ ChannelJudgmentEngine 测试 ━━━\n');
|
|
114
|
+
const engine = createChannelJudgmentEngine({ useLLM: false });
|
|
115
|
+
const testInputs = [
|
|
116
|
+
'我们需要设计一个微服务架构',
|
|
117
|
+
'帮我 review 这段代码',
|
|
118
|
+
'这个功能需要安全检查',
|
|
119
|
+
'任务分解一下',
|
|
120
|
+
'实现登录功能'
|
|
121
|
+
];
|
|
122
|
+
for (const input of testInputs) {
|
|
123
|
+
const result = await engine.decide({
|
|
124
|
+
conversationHistory: [],
|
|
125
|
+
currentMessage: input,
|
|
126
|
+
senderName: 'TestUser'
|
|
127
|
+
});
|
|
128
|
+
console.log(`输入: "${input}"`);
|
|
129
|
+
console.log(` 调用 Harness: ${result.shouldCall}`);
|
|
130
|
+
if (result.shouldCall) {
|
|
131
|
+
console.log(` Gate: ${result.gate}`);
|
|
132
|
+
console.log(` Skills: ${result.skills.join(', ')}`);
|
|
133
|
+
console.log(` 置信度: ${(result.confidence * 100).toFixed(0)}%`);
|
|
134
|
+
}
|
|
135
|
+
console.log();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// 测试 LLMJudgmentEngine
|
|
139
|
+
async function testLLMJudgmentEngine() {
|
|
140
|
+
console.log('\n━━━ LLMJudgmentEngine 测试 ━━━\n');
|
|
141
|
+
const engine = createLLMJudgmentEngine({ useLLM: false });
|
|
142
|
+
for (const tc of TEST_CASES) {
|
|
143
|
+
console.log(`测试: ${tc.description}`);
|
|
144
|
+
const result = await engine.judge(tc.input, { history: ['之前的对话'] });
|
|
145
|
+
console.log(` Understanding:`);
|
|
146
|
+
console.log(` - Essence: ${result.understanding.essence}`);
|
|
147
|
+
console.log(` - Core Need: ${result.understanding.coreNeed}`);
|
|
148
|
+
console.log(` Assessment:`);
|
|
149
|
+
console.log(` - Complexity: ${result.assessment.complexity}`);
|
|
150
|
+
console.log(` - Depth: ${result.assessment.depth}`);
|
|
151
|
+
console.log(` Decision:`);
|
|
152
|
+
console.log(` - Approach: ${result.decision.approach}`);
|
|
153
|
+
console.log(` Routing:`);
|
|
154
|
+
console.log(` - Skills: ${result.routing.skills.join(', ')}`);
|
|
155
|
+
console.log(` - Collaboration: ${result.routing.collaboration}`);
|
|
156
|
+
console.log();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// 测试 DynamicSkillRouter
|
|
160
|
+
async function testDynamicSkillRouter() {
|
|
161
|
+
console.log('\n━━━ DynamicSkillRouter 测试 ━━━\n');
|
|
162
|
+
const { createDynamicSkillRouter } = await import('../bollharness-integration/llm-judgment-engine.js');
|
|
163
|
+
const router = createDynamicSkillRouter({ useLLM: false });
|
|
164
|
+
const availableSkills = router.listSkills();
|
|
165
|
+
console.log(`可用的 Skills: ${availableSkills.join(', ')}`);
|
|
166
|
+
// 测试单个 Skill 调用
|
|
167
|
+
const judgment = {
|
|
168
|
+
understanding: {
|
|
169
|
+
essence: 'how-to',
|
|
170
|
+
coreNeed: '设计方案',
|
|
171
|
+
implicit: []
|
|
172
|
+
},
|
|
173
|
+
assessment: {
|
|
174
|
+
complexity: 'complex',
|
|
175
|
+
complexityReason: '涉及架构设计',
|
|
176
|
+
depth: 'deeper',
|
|
177
|
+
urgency: 'medium'
|
|
178
|
+
},
|
|
179
|
+
decision: {
|
|
180
|
+
approach: 'design',
|
|
181
|
+
reasoning: '需要架构设计'
|
|
182
|
+
},
|
|
183
|
+
routing: {
|
|
184
|
+
skills: ['arch'],
|
|
185
|
+
agents: [],
|
|
186
|
+
collaboration: 'pair'
|
|
187
|
+
},
|
|
188
|
+
artifacts: {
|
|
189
|
+
required: ['架构文档']
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const results = await router.routeAndExecute('设计一个电商系统', judgment);
|
|
193
|
+
console.log(`\nSkill 执行结果:`);
|
|
194
|
+
for (const [skill, result] of Object.entries(results)) {
|
|
195
|
+
console.log(` ${skill}: ${String(result).substring(0, 100)}...`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// 主测试函数
|
|
199
|
+
async function main() {
|
|
200
|
+
console.log('========================================');
|
|
201
|
+
console.log(' LLM-as-Judge 集成测试');
|
|
202
|
+
console.log('========================================');
|
|
203
|
+
try {
|
|
204
|
+
await testPromptVariants();
|
|
205
|
+
await testLLMJudgmentClient();
|
|
206
|
+
testSkillPromptsConfig();
|
|
207
|
+
await testYAMLConfig();
|
|
208
|
+
await testChannelJudgmentEngine();
|
|
209
|
+
await testLLMJudgmentEngine();
|
|
210
|
+
await testDynamicSkillRouter();
|
|
211
|
+
console.log('\n========================================');
|
|
212
|
+
console.log(' 测试完成 ✓');
|
|
213
|
+
console.log('========================================\n');
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
console.error('\n测试失败:', err);
|
|
217
|
+
process.exit(1);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
main();
|