genesis-ai-cli 7.4.5
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/.env.example +78 -0
- package/README.md +282 -0
- package/dist/src/active-inference/actions.d.ts +75 -0
- package/dist/src/active-inference/actions.js +250 -0
- package/dist/src/active-inference/autonomous-loop.d.ts +103 -0
- package/dist/src/active-inference/autonomous-loop.js +289 -0
- package/dist/src/active-inference/core.d.ts +85 -0
- package/dist/src/active-inference/core.js +555 -0
- package/dist/src/active-inference/demo-autonomous-loop.d.ts +8 -0
- package/dist/src/active-inference/demo-autonomous-loop.js +338 -0
- package/dist/src/active-inference/demo-value-integration.d.ts +8 -0
- package/dist/src/active-inference/demo-value-integration.js +174 -0
- package/dist/src/active-inference/index.d.ts +32 -0
- package/dist/src/active-inference/index.js +88 -0
- package/dist/src/active-inference/integration.d.ts +114 -0
- package/dist/src/active-inference/integration.js +698 -0
- package/dist/src/active-inference/memory-integration.d.ts +51 -0
- package/dist/src/active-inference/memory-integration.js +232 -0
- package/dist/src/active-inference/observations.d.ts +67 -0
- package/dist/src/active-inference/observations.js +147 -0
- package/dist/src/active-inference/test-active-inference.d.ts +8 -0
- package/dist/src/active-inference/test-active-inference.js +320 -0
- package/dist/src/active-inference/test-value-integration.d.ts +6 -0
- package/dist/src/active-inference/test-value-integration.js +168 -0
- package/dist/src/active-inference/types.d.ts +150 -0
- package/dist/src/active-inference/types.js +59 -0
- package/dist/src/active-inference/value-integration.d.ts +164 -0
- package/dist/src/active-inference/value-integration.js +459 -0
- package/dist/src/agents/base-agent.d.ts +53 -0
- package/dist/src/agents/base-agent.js +178 -0
- package/dist/src/agents/builder.d.ts +67 -0
- package/dist/src/agents/builder.js +537 -0
- package/dist/src/agents/critic.d.ts +35 -0
- package/dist/src/agents/critic.js +322 -0
- package/dist/src/agents/ethicist.d.ts +54 -0
- package/dist/src/agents/ethicist.js +393 -0
- package/dist/src/agents/explorer.d.ts +26 -0
- package/dist/src/agents/explorer.js +216 -0
- package/dist/src/agents/feeling.d.ts +41 -0
- package/dist/src/agents/feeling.js +320 -0
- package/dist/src/agents/index.d.ts +111 -0
- package/dist/src/agents/index.js +222 -0
- package/dist/src/agents/memory.d.ts +69 -0
- package/dist/src/agents/memory.js +404 -0
- package/dist/src/agents/message-bus.d.ts +88 -0
- package/dist/src/agents/message-bus.js +267 -0
- package/dist/src/agents/narrator.d.ts +90 -0
- package/dist/src/agents/narrator.js +473 -0
- package/dist/src/agents/planner.d.ts +38 -0
- package/dist/src/agents/planner.js +341 -0
- package/dist/src/agents/predictor.d.ts +73 -0
- package/dist/src/agents/predictor.js +506 -0
- package/dist/src/agents/sensor.d.ts +88 -0
- package/dist/src/agents/sensor.js +377 -0
- package/dist/src/agents/test-agents.d.ts +6 -0
- package/dist/src/agents/test-agents.js +73 -0
- package/dist/src/agents/types.d.ts +194 -0
- package/dist/src/agents/types.js +7 -0
- package/dist/src/brain/index.d.ts +185 -0
- package/dist/src/brain/index.js +843 -0
- package/dist/src/brain/trace.d.ts +91 -0
- package/dist/src/brain/trace.js +327 -0
- package/dist/src/brain/types.d.ts +165 -0
- package/dist/src/brain/types.js +51 -0
- package/dist/src/cli/chat.d.ts +237 -0
- package/dist/src/cli/chat.js +1959 -0
- package/dist/src/cli/dispatcher.d.ts +182 -0
- package/dist/src/cli/dispatcher.js +718 -0
- package/dist/src/cli/human-loop.d.ts +170 -0
- package/dist/src/cli/human-loop.js +543 -0
- package/dist/src/cli/index.d.ts +12 -0
- package/dist/src/cli/index.js +28 -0
- package/dist/src/cli/interactive.d.ts +141 -0
- package/dist/src/cli/interactive.js +757 -0
- package/dist/src/cli/ui.d.ts +205 -0
- package/dist/src/cli/ui.js +632 -0
- package/dist/src/consciousness/attention-schema.d.ts +154 -0
- package/dist/src/consciousness/attention-schema.js +432 -0
- package/dist/src/consciousness/global-workspace.d.ts +149 -0
- package/dist/src/consciousness/global-workspace.js +422 -0
- package/dist/src/consciousness/index.d.ts +186 -0
- package/dist/src/consciousness/index.js +476 -0
- package/dist/src/consciousness/phi-calculator.d.ts +119 -0
- package/dist/src/consciousness/phi-calculator.js +445 -0
- package/dist/src/consciousness/phi-decisions.d.ts +169 -0
- package/dist/src/consciousness/phi-decisions.js +383 -0
- package/dist/src/consciousness/phi-monitor.d.ts +153 -0
- package/dist/src/consciousness/phi-monitor.js +465 -0
- package/dist/src/consciousness/types.d.ts +260 -0
- package/dist/src/consciousness/types.js +44 -0
- package/dist/src/daemon/dream-mode.d.ts +115 -0
- package/dist/src/daemon/dream-mode.js +470 -0
- package/dist/src/daemon/index.d.ts +162 -0
- package/dist/src/daemon/index.js +542 -0
- package/dist/src/daemon/maintenance.d.ts +139 -0
- package/dist/src/daemon/maintenance.js +549 -0
- package/dist/src/daemon/process.d.ts +82 -0
- package/dist/src/daemon/process.js +442 -0
- package/dist/src/daemon/scheduler.d.ts +90 -0
- package/dist/src/daemon/scheduler.js +494 -0
- package/dist/src/daemon/types.d.ts +213 -0
- package/dist/src/daemon/types.js +50 -0
- package/dist/src/epistemic/index.d.ts +74 -0
- package/dist/src/epistemic/index.js +225 -0
- package/dist/src/grounding/epistemic-stack.d.ts +100 -0
- package/dist/src/grounding/epistemic-stack.js +408 -0
- package/dist/src/grounding/feedback.d.ts +98 -0
- package/dist/src/grounding/feedback.js +276 -0
- package/dist/src/grounding/index.d.ts +123 -0
- package/dist/src/grounding/index.js +224 -0
- package/dist/src/grounding/verifier.d.ts +149 -0
- package/dist/src/grounding/verifier.js +484 -0
- package/dist/src/healing/detector.d.ts +110 -0
- package/dist/src/healing/detector.js +436 -0
- package/dist/src/healing/fixer.d.ts +138 -0
- package/dist/src/healing/fixer.js +572 -0
- package/dist/src/healing/index.d.ts +23 -0
- package/dist/src/healing/index.js +43 -0
- package/dist/src/hooks/index.d.ts +135 -0
- package/dist/src/hooks/index.js +317 -0
- package/dist/src/index.d.ts +23 -0
- package/dist/src/index.js +1266 -0
- package/dist/src/kernel/index.d.ts +155 -0
- package/dist/src/kernel/index.js +795 -0
- package/dist/src/kernel/invariants.d.ts +153 -0
- package/dist/src/kernel/invariants.js +355 -0
- package/dist/src/kernel/test-kernel.d.ts +6 -0
- package/dist/src/kernel/test-kernel.js +108 -0
- package/dist/src/kernel/test-real-mcp.d.ts +10 -0
- package/dist/src/kernel/test-real-mcp.js +295 -0
- package/dist/src/llm/index.d.ts +146 -0
- package/dist/src/llm/index.js +428 -0
- package/dist/src/llm/router.d.ts +136 -0
- package/dist/src/llm/router.js +510 -0
- package/dist/src/mcp/index.d.ts +85 -0
- package/dist/src/mcp/index.js +657 -0
- package/dist/src/mcp/resilient.d.ts +139 -0
- package/dist/src/mcp/resilient.js +417 -0
- package/dist/src/memory/cache.d.ts +118 -0
- package/dist/src/memory/cache.js +356 -0
- package/dist/src/memory/cognitive-workspace.d.ts +231 -0
- package/dist/src/memory/cognitive-workspace.js +521 -0
- package/dist/src/memory/consolidation.d.ts +99 -0
- package/dist/src/memory/consolidation.js +443 -0
- package/dist/src/memory/episodic.d.ts +114 -0
- package/dist/src/memory/episodic.js +394 -0
- package/dist/src/memory/forgetting.d.ts +134 -0
- package/dist/src/memory/forgetting.js +324 -0
- package/dist/src/memory/index.d.ts +211 -0
- package/dist/src/memory/index.js +367 -0
- package/dist/src/memory/indexer.d.ts +123 -0
- package/dist/src/memory/indexer.js +479 -0
- package/dist/src/memory/procedural.d.ts +136 -0
- package/dist/src/memory/procedural.js +479 -0
- package/dist/src/memory/semantic.d.ts +132 -0
- package/dist/src/memory/semantic.js +497 -0
- package/dist/src/memory/types.d.ts +193 -0
- package/dist/src/memory/types.js +15 -0
- package/dist/src/orchestrator.d.ts +65 -0
- package/dist/src/orchestrator.js +317 -0
- package/dist/src/persistence/index.d.ts +257 -0
- package/dist/src/persistence/index.js +763 -0
- package/dist/src/pipeline/executor.d.ts +51 -0
- package/dist/src/pipeline/executor.js +695 -0
- package/dist/src/pipeline/index.d.ts +7 -0
- package/dist/src/pipeline/index.js +11 -0
- package/dist/src/self-production.d.ts +67 -0
- package/dist/src/self-production.js +205 -0
- package/dist/src/subagents/executor.d.ts +58 -0
- package/dist/src/subagents/executor.js +283 -0
- package/dist/src/subagents/index.d.ts +37 -0
- package/dist/src/subagents/index.js +53 -0
- package/dist/src/subagents/registry.d.ts +23 -0
- package/dist/src/subagents/registry.js +167 -0
- package/dist/src/subagents/types.d.ts +79 -0
- package/dist/src/subagents/types.js +14 -0
- package/dist/src/tools/bash.d.ts +139 -0
- package/dist/src/tools/bash.js +583 -0
- package/dist/src/tools/edit.d.ts +125 -0
- package/dist/src/tools/edit.js +424 -0
- package/dist/src/tools/git.d.ts +179 -0
- package/dist/src/tools/git.js +504 -0
- package/dist/src/tools/index.d.ts +21 -0
- package/dist/src/tools/index.js +163 -0
- package/dist/src/types.d.ts +145 -0
- package/dist/src/types.js +7 -0
- package/dist/src/world-model/decoder.d.ts +163 -0
- package/dist/src/world-model/decoder.js +517 -0
- package/dist/src/world-model/digital-twin.d.ts +219 -0
- package/dist/src/world-model/digital-twin.js +695 -0
- package/dist/src/world-model/encoder.d.ts +141 -0
- package/dist/src/world-model/encoder.js +564 -0
- package/dist/src/world-model/index.d.ts +221 -0
- package/dist/src/world-model/index.js +772 -0
- package/dist/src/world-model/predictor.d.ts +161 -0
- package/dist/src/world-model/predictor.js +681 -0
- package/dist/src/world-model/test-value-jepa.d.ts +8 -0
- package/dist/src/world-model/test-value-jepa.js +430 -0
- package/dist/src/world-model/types.d.ts +341 -0
- package/dist/src/world-model/types.js +69 -0
- package/dist/src/world-model/value-jepa.d.ts +247 -0
- package/dist/src/world-model/value-jepa.js +622 -0
- package/dist/test/brain.test.d.ts +11 -0
- package/dist/test/brain.test.js +358 -0
- package/dist/test/cli/dispatcher.test.d.ts +4 -0
- package/dist/test/cli/dispatcher.test.js +332 -0
- package/dist/test/cli/human-loop.test.d.ts +4 -0
- package/dist/test/cli/human-loop.test.js +270 -0
- package/dist/test/grounding/feedback.test.d.ts +4 -0
- package/dist/test/grounding/feedback.test.js +462 -0
- package/dist/test/grounding/verifier.test.d.ts +4 -0
- package/dist/test/grounding/verifier.test.js +442 -0
- package/dist/test/grounding.test.d.ts +6 -0
- package/dist/test/grounding.test.js +246 -0
- package/dist/test/healing/detector.test.d.ts +4 -0
- package/dist/test/healing/detector.test.js +266 -0
- package/dist/test/healing/fixer.test.d.ts +4 -0
- package/dist/test/healing/fixer.test.js +369 -0
- package/dist/test/integration.test.d.ts +5 -0
- package/dist/test/integration.test.js +290 -0
- package/dist/test/tools/bash.test.d.ts +4 -0
- package/dist/test/tools/bash.test.js +348 -0
- package/dist/test/tools/edit.test.d.ts +4 -0
- package/dist/test/tools/edit.test.js +350 -0
- package/dist/test/tools/git.test.d.ts +4 -0
- package/dist/test/tools/git.test.js +350 -0
- package/package.json +60 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for Genesis Tool Dispatcher
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const node_test_1 = require("node:test");
|
|
10
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
11
|
+
const dispatcher_js_1 = require("../../src/cli/dispatcher.js");
|
|
12
|
+
(0, node_test_1.describe)('ToolDispatcher', () => {
|
|
13
|
+
(0, node_test_1.beforeEach)(() => {
|
|
14
|
+
(0, dispatcher_js_1.resetDispatcher)();
|
|
15
|
+
});
|
|
16
|
+
// ==========================================================================
|
|
17
|
+
// Parsing Tests
|
|
18
|
+
// ==========================================================================
|
|
19
|
+
(0, node_test_1.describe)('Parsing', () => {
|
|
20
|
+
(0, node_test_1.it)('should parse OpenAI-style tool calls', () => {
|
|
21
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
22
|
+
const llmCalls = [
|
|
23
|
+
{
|
|
24
|
+
id: 'call_1',
|
|
25
|
+
type: 'function',
|
|
26
|
+
function: {
|
|
27
|
+
name: 'bash',
|
|
28
|
+
arguments: '{"command": "ls -la"}',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'call_2',
|
|
33
|
+
type: 'function',
|
|
34
|
+
function: {
|
|
35
|
+
name: 'edit',
|
|
36
|
+
arguments: '{"file_path": "test.ts", "old_string": "foo", "new_string": "bar"}',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
const calls = dispatcher.parseToolCalls(llmCalls);
|
|
41
|
+
node_assert_1.default.strictEqual(calls.length, 2);
|
|
42
|
+
node_assert_1.default.strictEqual(calls[0].name, 'bash');
|
|
43
|
+
node_assert_1.default.strictEqual(calls[0].params.command, 'ls -la');
|
|
44
|
+
node_assert_1.default.strictEqual(calls[1].name, 'edit');
|
|
45
|
+
node_assert_1.default.strictEqual(calls[1].params.file_path, 'test.ts');
|
|
46
|
+
});
|
|
47
|
+
(0, node_test_1.it)('should parse XML-style tool calls', () => {
|
|
48
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
49
|
+
const text = `
|
|
50
|
+
Let me run a command for you.
|
|
51
|
+
<tool_use name="bash">
|
|
52
|
+
<param name="command">echo "hello"</param>
|
|
53
|
+
</tool_use>
|
|
54
|
+
`;
|
|
55
|
+
const calls = dispatcher.parseToolCalls(text);
|
|
56
|
+
node_assert_1.default.strictEqual(calls.length, 1);
|
|
57
|
+
node_assert_1.default.strictEqual(calls[0].name, 'bash');
|
|
58
|
+
node_assert_1.default.strictEqual(calls[0].params.command, 'echo "hello"');
|
|
59
|
+
});
|
|
60
|
+
(0, node_test_1.it)('should parse invoke-style tool calls', () => {
|
|
61
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
62
|
+
const text = `
|
|
63
|
+
<invoke name="git_status">
|
|
64
|
+
<param name="cwd">/tmp</param>
|
|
65
|
+
</invoke>
|
|
66
|
+
`;
|
|
67
|
+
const calls = dispatcher.parseToolCalls(text);
|
|
68
|
+
node_assert_1.default.strictEqual(calls.length, 1);
|
|
69
|
+
node_assert_1.default.strictEqual(calls[0].name, 'git_status');
|
|
70
|
+
node_assert_1.default.strictEqual(calls[0].params.cwd, '/tmp');
|
|
71
|
+
});
|
|
72
|
+
(0, node_test_1.it)('should parse JSON-style tool calls', () => {
|
|
73
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
74
|
+
const text = `
|
|
75
|
+
I'll run this tool:
|
|
76
|
+
{"tool": "bash", "params": {"command": "pwd"}}
|
|
77
|
+
`;
|
|
78
|
+
const calls = dispatcher.parseToolCalls(text);
|
|
79
|
+
node_assert_1.default.strictEqual(calls.length, 1);
|
|
80
|
+
node_assert_1.default.strictEqual(calls[0].name, 'bash');
|
|
81
|
+
node_assert_1.default.strictEqual(calls[0].params.command, 'pwd');
|
|
82
|
+
});
|
|
83
|
+
(0, node_test_1.it)('should handle multiple tool calls in one response', () => {
|
|
84
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
85
|
+
const text = `
|
|
86
|
+
<tool_use name="bash">
|
|
87
|
+
<param name="command">ls</param>
|
|
88
|
+
</tool_use>
|
|
89
|
+
<tool_use name="bash">
|
|
90
|
+
<param name="command">pwd</param>
|
|
91
|
+
</tool_use>
|
|
92
|
+
`;
|
|
93
|
+
const calls = dispatcher.parseToolCalls(text);
|
|
94
|
+
node_assert_1.default.strictEqual(calls.length, 2);
|
|
95
|
+
});
|
|
96
|
+
(0, node_test_1.it)('should handle empty response', () => {
|
|
97
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
98
|
+
const calls = dispatcher.parseToolCalls('Just a plain response with no tools.');
|
|
99
|
+
node_assert_1.default.strictEqual(calls.length, 0);
|
|
100
|
+
});
|
|
101
|
+
(0, node_test_1.it)('should handle malformed tool calls gracefully', () => {
|
|
102
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
103
|
+
const text = `
|
|
104
|
+
<tool_use name="bash">
|
|
105
|
+
invalid xml content without params
|
|
106
|
+
</tool_use>
|
|
107
|
+
`;
|
|
108
|
+
// Should not throw
|
|
109
|
+
const calls = dispatcher.parseToolCalls(text);
|
|
110
|
+
node_assert_1.default.ok(Array.isArray(calls));
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
// ==========================================================================
|
|
114
|
+
// Routing Tests
|
|
115
|
+
// ==========================================================================
|
|
116
|
+
(0, node_test_1.describe)('Routing', () => {
|
|
117
|
+
(0, node_test_1.it)('should route local tools correctly', () => {
|
|
118
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
119
|
+
const calls = dispatcher.parseToolCalls([
|
|
120
|
+
{
|
|
121
|
+
id: 'call_1',
|
|
122
|
+
type: 'function',
|
|
123
|
+
function: { name: 'bash', arguments: '{}' },
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'call_2',
|
|
127
|
+
type: 'function',
|
|
128
|
+
function: { name: 'edit', arguments: '{}' },
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'call_3',
|
|
132
|
+
type: 'function',
|
|
133
|
+
function: { name: 'git_status', arguments: '{}' },
|
|
134
|
+
},
|
|
135
|
+
]);
|
|
136
|
+
node_assert_1.default.strictEqual(calls[0].source, 'local');
|
|
137
|
+
node_assert_1.default.strictEqual(calls[1].source, 'local');
|
|
138
|
+
node_assert_1.default.strictEqual(calls[2].source, 'local');
|
|
139
|
+
});
|
|
140
|
+
(0, node_test_1.it)('should route MCP tools correctly', () => {
|
|
141
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
142
|
+
const calls = dispatcher.parseToolCalls([
|
|
143
|
+
{
|
|
144
|
+
id: 'call_1',
|
|
145
|
+
type: 'function',
|
|
146
|
+
function: { name: 'search_arxiv', arguments: '{}' },
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 'call_2',
|
|
150
|
+
type: 'function',
|
|
151
|
+
function: { name: 'wolfram_query', arguments: '{}' },
|
|
152
|
+
},
|
|
153
|
+
]);
|
|
154
|
+
node_assert_1.default.strictEqual(calls[0].source, 'mcp');
|
|
155
|
+
node_assert_1.default.strictEqual(calls[0].mcpServer, 'arxiv');
|
|
156
|
+
node_assert_1.default.strictEqual(calls[1].source, 'mcp');
|
|
157
|
+
node_assert_1.default.strictEqual(calls[1].mcpServer, 'wolfram');
|
|
158
|
+
});
|
|
159
|
+
(0, node_test_1.it)('should default unknown tools to local', () => {
|
|
160
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
161
|
+
const calls = dispatcher.parseToolCalls([
|
|
162
|
+
{
|
|
163
|
+
id: 'call_1',
|
|
164
|
+
type: 'function',
|
|
165
|
+
function: { name: 'unknown_tool', arguments: '{}' },
|
|
166
|
+
},
|
|
167
|
+
]);
|
|
168
|
+
node_assert_1.default.strictEqual(calls[0].source, 'local');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
// ==========================================================================
|
|
172
|
+
// Execution Tests
|
|
173
|
+
// ==========================================================================
|
|
174
|
+
(0, node_test_1.describe)('Execution', () => {
|
|
175
|
+
(0, node_test_1.it)('should execute local tools successfully', async () => {
|
|
176
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
177
|
+
const calls = [
|
|
178
|
+
{
|
|
179
|
+
id: 'call_1',
|
|
180
|
+
name: 'bash',
|
|
181
|
+
params: { command: 'echo "test"' },
|
|
182
|
+
source: 'local',
|
|
183
|
+
},
|
|
184
|
+
];
|
|
185
|
+
const result = await dispatcher.dispatch(calls);
|
|
186
|
+
node_assert_1.default.ok(result.results.length > 0);
|
|
187
|
+
node_assert_1.default.strictEqual(result.results[0].name, 'bash');
|
|
188
|
+
// May or may not succeed depending on sandbox
|
|
189
|
+
});
|
|
190
|
+
(0, node_test_1.it)('should handle failed validation', async () => {
|
|
191
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
192
|
+
const calls = [
|
|
193
|
+
{
|
|
194
|
+
id: 'call_1',
|
|
195
|
+
name: 'edit',
|
|
196
|
+
params: {}, // Missing required params
|
|
197
|
+
source: 'local',
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
const result = await dispatcher.dispatch(calls);
|
|
201
|
+
node_assert_1.default.strictEqual(result.results[0].success, false);
|
|
202
|
+
node_assert_1.default.ok(result.results[0].error);
|
|
203
|
+
});
|
|
204
|
+
(0, node_test_1.it)('should handle unknown tools gracefully', async () => {
|
|
205
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
206
|
+
const calls = [
|
|
207
|
+
{
|
|
208
|
+
id: 'call_1',
|
|
209
|
+
name: 'nonexistent_tool',
|
|
210
|
+
params: {},
|
|
211
|
+
source: 'local',
|
|
212
|
+
},
|
|
213
|
+
];
|
|
214
|
+
const result = await dispatcher.dispatch(calls);
|
|
215
|
+
node_assert_1.default.strictEqual(result.results[0].success, false);
|
|
216
|
+
node_assert_1.default.ok(result.results[0].error?.includes('Unknown tool'));
|
|
217
|
+
});
|
|
218
|
+
(0, node_test_1.it)('should track execution duration', async () => {
|
|
219
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
220
|
+
const calls = [
|
|
221
|
+
{
|
|
222
|
+
id: 'call_1',
|
|
223
|
+
name: 'bash',
|
|
224
|
+
params: { command: 'echo "test"' },
|
|
225
|
+
source: 'local',
|
|
226
|
+
},
|
|
227
|
+
];
|
|
228
|
+
const result = await dispatcher.dispatch(calls);
|
|
229
|
+
node_assert_1.default.ok(result.totalDuration >= 0);
|
|
230
|
+
node_assert_1.default.ok(result.results[0].duration >= 0);
|
|
231
|
+
});
|
|
232
|
+
(0, node_test_1.it)('should support parallel execution', async () => {
|
|
233
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)({ maxParallel: 3 });
|
|
234
|
+
const calls = [
|
|
235
|
+
{ id: 'call_1', name: 'bash', params: { command: 'echo 1' }, source: 'local' },
|
|
236
|
+
{ id: 'call_2', name: 'bash', params: { command: 'echo 2' }, source: 'local' },
|
|
237
|
+
{ id: 'call_3', name: 'bash', params: { command: 'echo 3' }, source: 'local' },
|
|
238
|
+
];
|
|
239
|
+
const result = await dispatcher.dispatch(calls);
|
|
240
|
+
node_assert_1.default.strictEqual(result.results.length, 3);
|
|
241
|
+
node_assert_1.default.ok(result.parallelExecutions >= 1);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
// ==========================================================================
|
|
245
|
+
// History Tests
|
|
246
|
+
// ==========================================================================
|
|
247
|
+
(0, node_test_1.describe)('History', () => {
|
|
248
|
+
(0, node_test_1.it)('should track execution history', async () => {
|
|
249
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
250
|
+
await dispatcher.dispatch([
|
|
251
|
+
{ id: 'call_1', name: 'bash', params: { command: 'echo 1' }, source: 'local' },
|
|
252
|
+
]);
|
|
253
|
+
await dispatcher.dispatch([
|
|
254
|
+
{ id: 'call_2', name: 'bash', params: { command: 'echo 2' }, source: 'local' },
|
|
255
|
+
]);
|
|
256
|
+
const history = dispatcher.getHistory();
|
|
257
|
+
node_assert_1.default.strictEqual(history.length, 2);
|
|
258
|
+
});
|
|
259
|
+
(0, node_test_1.it)('should clear history', async () => {
|
|
260
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
261
|
+
await dispatcher.dispatch([
|
|
262
|
+
{ id: 'call_1', name: 'bash', params: { command: 'echo 1' }, source: 'local' },
|
|
263
|
+
]);
|
|
264
|
+
dispatcher.clearHistory();
|
|
265
|
+
node_assert_1.default.strictEqual(dispatcher.getHistory().length, 0);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
// ==========================================================================
|
|
269
|
+
// Formatting Tests
|
|
270
|
+
// ==========================================================================
|
|
271
|
+
(0, node_test_1.describe)('Formatting', () => {
|
|
272
|
+
(0, node_test_1.it)('should format results for LLM context', async () => {
|
|
273
|
+
const dispatcher = (0, dispatcher_js_1.getDispatcher)();
|
|
274
|
+
const result = await dispatcher.dispatch([
|
|
275
|
+
{ id: 'call_1', name: 'bash', params: { command: 'echo "hello"' }, source: 'local' },
|
|
276
|
+
]);
|
|
277
|
+
const formatted = dispatcher.formatResultsForLLM(result.results);
|
|
278
|
+
node_assert_1.default.ok(formatted.includes('<tool_results>'));
|
|
279
|
+
node_assert_1.default.ok(formatted.includes('</tool_results>'));
|
|
280
|
+
node_assert_1.default.ok(formatted.includes('name="bash"'));
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
// ==========================================================================
|
|
284
|
+
// Tool Listing Tests
|
|
285
|
+
// ==========================================================================
|
|
286
|
+
(0, node_test_1.describe)('Tool Listing', () => {
|
|
287
|
+
(0, node_test_1.it)('should list available tools', () => {
|
|
288
|
+
const tools = (0, dispatcher_js_1.listAllTools)();
|
|
289
|
+
node_assert_1.default.ok(tools.local.includes('bash'));
|
|
290
|
+
node_assert_1.default.ok(tools.local.includes('edit'));
|
|
291
|
+
node_assert_1.default.ok(Object.keys(tools.mcp).includes('arxiv'));
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
// ==========================================================================
|
|
295
|
+
// Convenience Functions
|
|
296
|
+
// ==========================================================================
|
|
297
|
+
(0, node_test_1.describe)('Convenience Functions', () => {
|
|
298
|
+
(0, node_test_1.it)('dispatchTools should work with string input', async () => {
|
|
299
|
+
const text = `
|
|
300
|
+
<tool_use name="bash">
|
|
301
|
+
<param name="command">echo test</param>
|
|
302
|
+
</tool_use>
|
|
303
|
+
`;
|
|
304
|
+
const result = await (0, dispatcher_js_1.dispatchTools)(text);
|
|
305
|
+
node_assert_1.default.ok(result.results.length > 0);
|
|
306
|
+
});
|
|
307
|
+
(0, node_test_1.it)('executeTool should work', async () => {
|
|
308
|
+
const result = await (0, dispatcher_js_1.executeTool)('bash', { command: 'echo "hello"' });
|
|
309
|
+
node_assert_1.default.strictEqual(result.name, 'bash');
|
|
310
|
+
// Success depends on sandbox config
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
// ==========================================================================
|
|
314
|
+
// Progress Callback Tests
|
|
315
|
+
// ==========================================================================
|
|
316
|
+
(0, node_test_1.describe)('Progress Callback', () => {
|
|
317
|
+
(0, node_test_1.it)('should call progress callback', async () => {
|
|
318
|
+
const progressCalls = [];
|
|
319
|
+
const dispatcher = new dispatcher_js_1.ToolDispatcher({
|
|
320
|
+
onProgress: (status) => {
|
|
321
|
+
progressCalls.push(status.phase);
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
await dispatcher.dispatch([
|
|
325
|
+
{ id: 'call_1', name: 'bash', params: { command: 'echo 1' }, source: 'local' },
|
|
326
|
+
]);
|
|
327
|
+
node_assert_1.default.ok(progressCalls.includes('validating'));
|
|
328
|
+
node_assert_1.default.ok(progressCalls.includes('executing'));
|
|
329
|
+
node_assert_1.default.ok(progressCalls.includes('complete'));
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
});
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tests for Genesis Human-in-the-Loop Module
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
const node_test_1 = require("node:test");
|
|
10
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
11
|
+
const human_loop_js_1 = require("../../src/cli/human-loop.js");
|
|
12
|
+
const index_js_1 = require("../../src/tools/index.js");
|
|
13
|
+
(0, node_test_1.describe)('HumanLoop', () => {
|
|
14
|
+
(0, node_test_1.beforeEach)(() => {
|
|
15
|
+
(0, human_loop_js_1.resetHumanLoop)();
|
|
16
|
+
});
|
|
17
|
+
// ==========================================================================
|
|
18
|
+
// Configuration Tests
|
|
19
|
+
// ==========================================================================
|
|
20
|
+
(0, node_test_1.describe)('Configuration', () => {
|
|
21
|
+
(0, node_test_1.it)('should use default configuration', () => {
|
|
22
|
+
const hl = new human_loop_js_1.HumanLoop();
|
|
23
|
+
node_assert_1.default.ok(hl);
|
|
24
|
+
});
|
|
25
|
+
(0, node_test_1.it)('should accept custom configuration', () => {
|
|
26
|
+
const hl = new human_loop_js_1.HumanLoop({
|
|
27
|
+
defaultTimeout: 5000,
|
|
28
|
+
allowSkip: false,
|
|
29
|
+
useColors: false,
|
|
30
|
+
});
|
|
31
|
+
node_assert_1.default.ok(hl);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
// ==========================================================================
|
|
35
|
+
// Question Types
|
|
36
|
+
// ==========================================================================
|
|
37
|
+
(0, node_test_1.describe)('Question Types', () => {
|
|
38
|
+
(0, node_test_1.it)('should support confirm type', () => {
|
|
39
|
+
const question = {
|
|
40
|
+
type: 'confirm',
|
|
41
|
+
text: 'Do you want to proceed?',
|
|
42
|
+
default: true,
|
|
43
|
+
};
|
|
44
|
+
node_assert_1.default.strictEqual(question.type, 'confirm');
|
|
45
|
+
node_assert_1.default.strictEqual(question.default, true);
|
|
46
|
+
});
|
|
47
|
+
(0, node_test_1.it)('should support choice type with options', () => {
|
|
48
|
+
const options = [
|
|
49
|
+
{ value: 'a', label: 'Option A', description: 'First option' },
|
|
50
|
+
{ value: 'b', label: 'Option B', recommended: true },
|
|
51
|
+
{ value: 'c', label: 'Option C' },
|
|
52
|
+
];
|
|
53
|
+
const question = {
|
|
54
|
+
type: 'choice',
|
|
55
|
+
text: 'Choose one:',
|
|
56
|
+
options,
|
|
57
|
+
};
|
|
58
|
+
node_assert_1.default.strictEqual(question.options?.length, 3);
|
|
59
|
+
node_assert_1.default.ok(question.options?.[1].recommended);
|
|
60
|
+
});
|
|
61
|
+
(0, node_test_1.it)('should support multiChoice type', () => {
|
|
62
|
+
const question = {
|
|
63
|
+
type: 'multiChoice',
|
|
64
|
+
text: 'Select all that apply:',
|
|
65
|
+
options: [
|
|
66
|
+
{ value: '1', label: 'One' },
|
|
67
|
+
{ value: '2', label: 'Two' },
|
|
68
|
+
{ value: '3', label: 'Three' },
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
node_assert_1.default.strictEqual(question.type, 'multiChoice');
|
|
72
|
+
});
|
|
73
|
+
(0, node_test_1.it)('should support text type', () => {
|
|
74
|
+
const question = {
|
|
75
|
+
type: 'text',
|
|
76
|
+
text: 'Enter your name:',
|
|
77
|
+
default: 'Anonymous',
|
|
78
|
+
};
|
|
79
|
+
node_assert_1.default.strictEqual(question.type, 'text');
|
|
80
|
+
node_assert_1.default.strictEqual(question.default, 'Anonymous');
|
|
81
|
+
});
|
|
82
|
+
(0, node_test_1.it)('should support context', () => {
|
|
83
|
+
const question = {
|
|
84
|
+
type: 'confirm',
|
|
85
|
+
text: 'Proceed?',
|
|
86
|
+
context: 'This will delete 10 files.',
|
|
87
|
+
};
|
|
88
|
+
node_assert_1.default.strictEqual(question.context, 'This will delete 10 files.');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// ==========================================================================
|
|
92
|
+
// History & Stats
|
|
93
|
+
// ==========================================================================
|
|
94
|
+
(0, node_test_1.describe)('History & Stats', () => {
|
|
95
|
+
(0, node_test_1.it)('should track empty history initially', () => {
|
|
96
|
+
const hl = new human_loop_js_1.HumanLoop();
|
|
97
|
+
const history = hl.getHistory();
|
|
98
|
+
node_assert_1.default.strictEqual(history.length, 0);
|
|
99
|
+
});
|
|
100
|
+
(0, node_test_1.it)('should clear history', () => {
|
|
101
|
+
const hl = new human_loop_js_1.HumanLoop();
|
|
102
|
+
hl.clearHistory();
|
|
103
|
+
const history = hl.getHistory();
|
|
104
|
+
node_assert_1.default.strictEqual(history.length, 0);
|
|
105
|
+
});
|
|
106
|
+
(0, node_test_1.it)('should return stats', () => {
|
|
107
|
+
const hl = new human_loop_js_1.HumanLoop();
|
|
108
|
+
const stats = hl.stats();
|
|
109
|
+
node_assert_1.default.strictEqual(stats.totalQuestions, 0);
|
|
110
|
+
node_assert_1.default.strictEqual(stats.responded, 0);
|
|
111
|
+
node_assert_1.default.strictEqual(stats.timedOut, 0);
|
|
112
|
+
node_assert_1.default.strictEqual(stats.cancelled, 0);
|
|
113
|
+
node_assert_1.default.strictEqual(stats.avgResponseTime, 0);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// ==========================================================================
|
|
117
|
+
// Singleton Tests
|
|
118
|
+
// ==========================================================================
|
|
119
|
+
(0, node_test_1.describe)('Singleton', () => {
|
|
120
|
+
(0, node_test_1.it)('should return same instance', () => {
|
|
121
|
+
const hl1 = (0, human_loop_js_1.getHumanLoop)();
|
|
122
|
+
const hl2 = (0, human_loop_js_1.getHumanLoop)();
|
|
123
|
+
node_assert_1.default.strictEqual(hl1, hl2);
|
|
124
|
+
});
|
|
125
|
+
(0, node_test_1.it)('should reset singleton', () => {
|
|
126
|
+
const hl1 = (0, human_loop_js_1.getHumanLoop)();
|
|
127
|
+
(0, human_loop_js_1.resetHumanLoop)();
|
|
128
|
+
const hl2 = (0, human_loop_js_1.getHumanLoop)();
|
|
129
|
+
node_assert_1.default.notStrictEqual(hl1, hl2);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
// ==========================================================================
|
|
133
|
+
// Tool Registration
|
|
134
|
+
// ==========================================================================
|
|
135
|
+
(0, node_test_1.describe)('Tool Registration', () => {
|
|
136
|
+
(0, node_test_1.it)('should register ask_user tool', () => {
|
|
137
|
+
const tool = index_js_1.toolRegistry.get('ask_user');
|
|
138
|
+
node_assert_1.default.ok(tool);
|
|
139
|
+
node_assert_1.default.strictEqual(tool.name, 'ask_user');
|
|
140
|
+
node_assert_1.default.ok(tool.description.includes('Ask the user'));
|
|
141
|
+
});
|
|
142
|
+
(0, node_test_1.it)('should register confirm tool', () => {
|
|
143
|
+
const tool = index_js_1.toolRegistry.get('confirm');
|
|
144
|
+
node_assert_1.default.ok(tool);
|
|
145
|
+
node_assert_1.default.strictEqual(tool.name, 'confirm');
|
|
146
|
+
});
|
|
147
|
+
(0, node_test_1.it)('ask_user should validate params', () => {
|
|
148
|
+
const tool = index_js_1.toolRegistry.get('ask_user');
|
|
149
|
+
// Missing text
|
|
150
|
+
const invalid = tool?.validate?.({});
|
|
151
|
+
node_assert_1.default.strictEqual(invalid?.valid, false);
|
|
152
|
+
// Valid
|
|
153
|
+
const valid = tool?.validate?.({ text: 'Question?' });
|
|
154
|
+
node_assert_1.default.strictEqual(valid?.valid, true);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
// ==========================================================================
|
|
158
|
+
// Question Option Tests
|
|
159
|
+
// ==========================================================================
|
|
160
|
+
(0, node_test_1.describe)('Question Options', () => {
|
|
161
|
+
(0, node_test_1.it)('should support recommended option', () => {
|
|
162
|
+
const options = [
|
|
163
|
+
{ value: 'safe', label: 'Safe approach', recommended: true },
|
|
164
|
+
{ value: 'fast', label: 'Fast approach' },
|
|
165
|
+
];
|
|
166
|
+
const recommended = options.find(o => o.recommended);
|
|
167
|
+
node_assert_1.default.ok(recommended);
|
|
168
|
+
node_assert_1.default.strictEqual(recommended.value, 'safe');
|
|
169
|
+
});
|
|
170
|
+
(0, node_test_1.it)('should support option descriptions', () => {
|
|
171
|
+
const options = [
|
|
172
|
+
{ value: 'a', label: 'A', description: 'This is option A' },
|
|
173
|
+
{ value: 'b', label: 'B', description: 'This is option B' },
|
|
174
|
+
];
|
|
175
|
+
node_assert_1.default.strictEqual(options[0].description, 'This is option A');
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
// ==========================================================================
|
|
179
|
+
// Answer Structure Tests
|
|
180
|
+
// ==========================================================================
|
|
181
|
+
(0, node_test_1.describe)('Answer Structure', () => {
|
|
182
|
+
(0, node_test_1.it)('should have correct answer structure', () => {
|
|
183
|
+
// Simulated answer
|
|
184
|
+
const answer = {
|
|
185
|
+
question: {
|
|
186
|
+
type: 'confirm',
|
|
187
|
+
text: 'Test?',
|
|
188
|
+
},
|
|
189
|
+
value: true,
|
|
190
|
+
responded: true,
|
|
191
|
+
responseTime: 1500,
|
|
192
|
+
};
|
|
193
|
+
node_assert_1.default.strictEqual(answer.value, true);
|
|
194
|
+
node_assert_1.default.strictEqual(answer.responded, true);
|
|
195
|
+
node_assert_1.default.ok(answer.responseTime >= 0);
|
|
196
|
+
});
|
|
197
|
+
(0, node_test_1.it)('should track timeout', () => {
|
|
198
|
+
const answer = {
|
|
199
|
+
question: { type: 'confirm', text: 'Test?' },
|
|
200
|
+
value: false,
|
|
201
|
+
responded: false,
|
|
202
|
+
timedOut: true,
|
|
203
|
+
responseTime: 5000,
|
|
204
|
+
};
|
|
205
|
+
node_assert_1.default.strictEqual(answer.timedOut, true);
|
|
206
|
+
node_assert_1.default.strictEqual(answer.responded, false);
|
|
207
|
+
});
|
|
208
|
+
(0, node_test_1.it)('should track cancellation', () => {
|
|
209
|
+
const answer = {
|
|
210
|
+
question: { type: 'choice', text: 'Choose?' },
|
|
211
|
+
value: '',
|
|
212
|
+
responded: true,
|
|
213
|
+
cancelled: true,
|
|
214
|
+
responseTime: 500,
|
|
215
|
+
};
|
|
216
|
+
node_assert_1.default.strictEqual(answer.cancelled, true);
|
|
217
|
+
node_assert_1.default.strictEqual(answer.value, '');
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
// ==========================================================================
|
|
221
|
+
// Integration Tests (mocked)
|
|
222
|
+
// ==========================================================================
|
|
223
|
+
(0, node_test_1.describe)('Integration', () => {
|
|
224
|
+
(0, node_test_1.it)('should support callback on response', () => {
|
|
225
|
+
let callbackCalled = false;
|
|
226
|
+
const hl = new human_loop_js_1.HumanLoop({
|
|
227
|
+
onResponse: (answer) => {
|
|
228
|
+
callbackCalled = true;
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
// We can't actually test interactive input here,
|
|
232
|
+
// but we can verify the callback is set up correctly
|
|
233
|
+
node_assert_1.default.ok(hl);
|
|
234
|
+
});
|
|
235
|
+
(0, node_test_1.it)('should close cleanly', () => {
|
|
236
|
+
const hl = new human_loop_js_1.HumanLoop();
|
|
237
|
+
hl.close();
|
|
238
|
+
// Should not throw
|
|
239
|
+
node_assert_1.default.ok(true);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
// ==========================================================================
|
|
243
|
+
// Destructive Operation Tests
|
|
244
|
+
// ==========================================================================
|
|
245
|
+
(0, node_test_1.describe)('Destructive Operations', () => {
|
|
246
|
+
(0, node_test_1.it)('should format destructive warning', () => {
|
|
247
|
+
// This tests the structure of destructive confirmations
|
|
248
|
+
const operation = 'Delete all files';
|
|
249
|
+
const details = '10 files will be permanently removed';
|
|
250
|
+
// Just verify the strings are valid
|
|
251
|
+
node_assert_1.default.ok(operation.length > 0);
|
|
252
|
+
node_assert_1.default.ok(details.length > 0);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
// ==========================================================================
|
|
256
|
+
// Approach Selection Tests
|
|
257
|
+
// ==========================================================================
|
|
258
|
+
(0, node_test_1.describe)('Approach Selection', () => {
|
|
259
|
+
(0, node_test_1.it)('should format approach options', () => {
|
|
260
|
+
const task = 'Implement authentication';
|
|
261
|
+
const approaches = [
|
|
262
|
+
{ name: 'JWT', description: 'Token-based auth', recommended: true },
|
|
263
|
+
{ name: 'Session', description: 'Server-side sessions' },
|
|
264
|
+
{ name: 'OAuth', description: 'Third-party providers' },
|
|
265
|
+
];
|
|
266
|
+
node_assert_1.default.strictEqual(approaches.length, 3);
|
|
267
|
+
node_assert_1.default.ok(approaches.find(a => a.recommended));
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
});
|