@noorm/marie-cli 0.1.15 → 0.1.16
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/.marie_visual_verify_1771225696548/progress_bar_check.txt +1 -0
- package/SENTINEL.md +33 -0
- package/dist/domain/DomainEntity.js +7 -0
- package/dist/domain/DomainEntity.js.map +1 -0
- package/dist/extension.cjs +149 -147
- package/dist/extension.js +459 -0
- package/dist/extension.js.map +1 -0
- package/dist/infrastructure/BaseAdapter.js +3 -0
- package/dist/infrastructure/BaseAdapter.js.map +1 -0
- package/dist/monolith/cli/CliFileSystemPort.js +16 -8
- package/dist/monolith/cli/CliFileSystemPort.js.map +1 -1
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js +9 -6
- package/dist/monolith/cli/MarieToolDefinitionsCLI.js.map +1 -1
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js +1 -1
- package/dist/monolith/cli/services/JoyAutomationServiceCLI.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js +29 -10
- package/dist/monolith/infrastructure/ai/core/MarieEngine.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js +19 -13
- package/dist/monolith/infrastructure/ai/core/MarieToolProcessor.js.map +1 -1
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js +8 -8
- package/dist/monolith/infrastructure/ai/core/VscodeFileSystemPort.js.map +1 -1
- package/dist/monolith/infrastructure/config/ConfigService.js +2 -22
- package/dist/monolith/infrastructure/config/ConfigService.js.map +1 -1
- package/dist/monolith/infrastructure/joy/JoyTools.js +535 -0
- package/dist/monolith/infrastructure/joy/JoyTools.js.map +1 -0
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js +14 -13
- package/dist/monolith/infrastructure/tools/MarieToolDefinitions.js.map +1 -1
- package/dist/monolith/plumbing/analysis/TestService.js +2 -1
- package/dist/monolith/plumbing/analysis/TestService.js.map +1 -1
- package/dist/monolith/plumbing/filesystem/FileService.js +22 -10
- package/dist/monolith/plumbing/filesystem/FileService.js.map +1 -1
- package/dist/monolith/plumbing/utils/EnvironmentUtils.js +59 -0
- package/dist/monolith/plumbing/utils/EnvironmentUtils.js.map +1 -0
- package/dist/monolith/plumbing/utils/MutexUtils.js +86 -0
- package/dist/monolith/plumbing/utils/MutexUtils.js.map +1 -0
- package/dist/monolith/runtime/MarieRuntime.js +250 -136
- package/dist/monolith/runtime/MarieRuntime.js.map +1 -1
- package/dist/monolith/runtime/RuntimeAdapterBase.js +6 -0
- package/dist/monolith/runtime/RuntimeAdapterBase.js.map +1 -1
- package/dist/monolith/services/JoyAutomationService.js +1 -1
- package/dist/monolith/services/JoyAutomationService.js.map +1 -1
- package/dist/monolith/services/JoyService.js +1 -1
- package/dist/monolith/services/JoyService.js.map +1 -1
- package/dist/plumbing/BaseTool.js +7 -0
- package/dist/plumbing/BaseTool.js.map +1 -0
- package/dist/prompts.js +85 -0
- package/dist/prompts.js.map +1 -0
- package/dist/test_agent_stream_control_plane.js +170 -0
- package/dist/test_agent_stream_control_plane.js.map +1 -0
- package/dist/test_content_buffer_cap.js +67 -0
- package/dist/test_content_buffer_cap.js.map +1 -0
- package/dist/test_prefix_tree.js +120 -0
- package/dist/test_prefix_tree.js.map +1 -0
- package/dist/test_retry_utils.js +169 -0
- package/dist/test_retry_utils.js.map +1 -0
- package/dist/test_strategy_integration.js +114 -0
- package/dist/test_strategy_integration.js.map +1 -0
- package/dist/test_streaming_fragility.js +191 -0
- package/dist/test_streaming_fragility.js.map +1 -0
- package/dist/webview-ui/App.js +16 -0
- package/dist/webview-ui/App.js.map +1 -0
- package/dist/webview-ui/Providers.js +6 -0
- package/dist/webview-ui/Providers.js.map +1 -0
- package/dist/webview-ui/components/ApprovalPanel.js +8 -0
- package/dist/webview-ui/components/ApprovalPanel.js.map +1 -0
- package/dist/webview-ui/components/ChatPanel.js +19 -0
- package/dist/webview-ui/components/ChatPanel.js.map +1 -0
- package/dist/webview-ui/components/Composer.js +19 -0
- package/dist/webview-ui/components/Composer.js.map +1 -0
- package/dist/webview-ui/components/HeaderBar.js +5 -0
- package/dist/webview-ui/components/HeaderBar.js.map +1 -0
- package/dist/webview-ui/components/SessionList.js +14 -0
- package/dist/webview-ui/components/SessionList.js.map +1 -0
- package/dist/webview-ui/context/WebviewStateContext.js +146 -0
- package/dist/webview-ui/context/WebviewStateContext.js.map +1 -0
- package/dist/webview-ui/main.css +1 -0
- package/dist/webview-ui/main.js +108 -0
- package/dist/webview-ui/main.js.map +1 -0
- package/dist/webview-ui/types.js +2 -0
- package/dist/webview-ui/types.js.map +1 -0
- package/dist/webview-ui/vscode.js +4 -0
- package/dist/webview-ui/vscode.js.map +1 -0
- package/lint_output.txt +705 -0
- package/lint_output_v2.txt +711 -0
- package/marie-coder-0.1.16.vsix +0 -0
- package/package.json +3 -10
- package/JOY_ZONING.md +0 -200
- package/dist/monolith/tests/FileAppendVerifyTest.js +0 -28
- package/dist/monolith/tests/FileAppendVerifyTest.js.map +0 -1
- package/dist/monolith/tests/StreamingVerifyTest.js +0 -100
- package/dist/monolith/tests/StreamingVerifyTest.js.map +0 -1
- package/dist/monolith/tests/VisualProgressTest.js +0 -86
- package/dist/monolith/tests/VisualProgressTest.js.map +0 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { PrefixTree } from "./monolith/plumbing/utils/PrefixTree.js";
|
|
2
|
+
console.log("Starting PrefixTree Tests...\n");
|
|
3
|
+
// Test Suite 1: Basic Tag Detection
|
|
4
|
+
function testBasicDetection() {
|
|
5
|
+
console.log("Suite 1: Basic Tag Detection");
|
|
6
|
+
const tree = new PrefixTree(["<tool>", "</tool>", "<|start|>", "<|end|>"]);
|
|
7
|
+
// Test 1: Empty text
|
|
8
|
+
const result1 = tree.findEarliestTag("");
|
|
9
|
+
console.log(`Test: Empty text - ${result1 === null ? "PASS" : "FAIL"}`);
|
|
10
|
+
// Test 2: Single tag
|
|
11
|
+
const result2 = tree.findEarliestTag("Hello <tool> world");
|
|
12
|
+
console.log(`Test: Single tag - ${result2?.tag === "<tool>" && result2?.index === 6 ? "PASS" : "FAIL"}`);
|
|
13
|
+
// Test 3: Multiple tags (earliest wins)
|
|
14
|
+
const result3 = tree.findEarliestTag("Text </tool> more <tool> stuff");
|
|
15
|
+
console.log(`Test: Multiple tags (earliest) - ${result3?.tag === "</tool>" && result3?.index === 5 ? "PASS" : "FAIL"}`);
|
|
16
|
+
// Test 4: Overlapping tags
|
|
17
|
+
const result4 = tree.findEarliestTag("<<tool>>");
|
|
18
|
+
console.log(`Test: Overlapping tags - ${result4?.tag === "<tool>" && result4?.index === 1 ? "PASS" : "FAIL"}`);
|
|
19
|
+
// Test 5: No tags
|
|
20
|
+
const result5 = tree.findEarliestTag("Just plain text here");
|
|
21
|
+
console.log(`Test: No tags - ${result5 === null ? "PASS" : "FAIL"}`);
|
|
22
|
+
}
|
|
23
|
+
// Test Suite 2: Partial Tag Detection
|
|
24
|
+
function testPartialDetection() {
|
|
25
|
+
console.log("\nSuite 2: Partial Tag Detection");
|
|
26
|
+
const tree = new PrefixTree(["<tool>", "<|start|>", "<|end|>"]);
|
|
27
|
+
// Test 1: Complete partial at end
|
|
28
|
+
const result1 = tree.findLongestPartialAtEnd("Text <too");
|
|
29
|
+
console.log(`Test: Partial '<too' - ${result1 === 4 ? "PASS" : "FAIL (got " + result1 + ")"}`);
|
|
30
|
+
// Test 2: Longer partial
|
|
31
|
+
const result2 = tree.findLongestPartialAtEnd("Text <|star");
|
|
32
|
+
console.log(`Test: Partial '<|star' - ${result2 === 6 ? "PASS" : "FAIL (got " + result2 + ")"}`);
|
|
33
|
+
// Test 3: No partial
|
|
34
|
+
const result3 = tree.findLongestPartialAtEnd("No partial here");
|
|
35
|
+
console.log(`Test: No partial - ${result3 === 0 ? "PASS" : "FAIL"}`);
|
|
36
|
+
// Test 4: Complete tag (not a partial)
|
|
37
|
+
const result4 = tree.findLongestPartialAtEnd("Complete <tool>");
|
|
38
|
+
console.log(`Test: Complete tag (not partial) - ${result4 === 0 ? "PASS" : "FAIL"}`);
|
|
39
|
+
// Test 5: Single char partial
|
|
40
|
+
const result5 = tree.findLongestPartialAtEnd("End with <");
|
|
41
|
+
console.log(`Test: Single char partial '<' - ${result5 === 1 ? "PASS" : "FAIL (got " + result5 + ")"}`);
|
|
42
|
+
}
|
|
43
|
+
// Test Suite 3: Fuzzy Matching
|
|
44
|
+
function testFuzzyMatching() {
|
|
45
|
+
console.log("\nSuite 3: Fuzzy Matching");
|
|
46
|
+
const tree = new PrefixTree([
|
|
47
|
+
"<|tool_call_begin|>",
|
|
48
|
+
"<|tool_call_end|>",
|
|
49
|
+
"<tool>",
|
|
50
|
+
]);
|
|
51
|
+
// Test 1: Exact match (distance 0)
|
|
52
|
+
const result1 = tree.findSimilarTags("<tool>", 2);
|
|
53
|
+
console.log(`Test: Exact match - ${result1.includes("<tool>") && result1.length === 1 ? "PASS" : "FAIL"}`);
|
|
54
|
+
// Test 2: Distance 1 (one char off)
|
|
55
|
+
const result2 = tree.findSimilarTags("<tol>", 2);
|
|
56
|
+
console.log(`Test: Distance 1 - ${result2.includes("<tool>") ? "PASS" : "FAIL"}`);
|
|
57
|
+
// Test 3: Distance 2 (two chars off)
|
|
58
|
+
const result3 = tree.findSimilarTags("<|tool_call_begi|>", 2);
|
|
59
|
+
console.log(`Test: Distance 2 - ${result3.includes("<|tool_call_begin|>") ? "PASS" : "FAIL"}`);
|
|
60
|
+
// Test 4: Too far (distance > 2)
|
|
61
|
+
const result4 = tree.findSimilarTags("<toolz>", 1);
|
|
62
|
+
console.log(`Test: Distance > max - ${result4.length === 0 ? "PASS" : "FAIL"}`);
|
|
63
|
+
// Test 5: Multiple matches
|
|
64
|
+
const result5 = tree.findSimilarTags("<|tool_call_en|>", 2);
|
|
65
|
+
console.log(`Test: Multiple fuzzy matches - ${result5.length >= 1 ? "PASS" : "FAIL"}`);
|
|
66
|
+
}
|
|
67
|
+
// Test Suite 4: Performance with Large Tag Sets
|
|
68
|
+
function testPerformance() {
|
|
69
|
+
console.log("\nSuite 4: Performance");
|
|
70
|
+
// Create a large tag set
|
|
71
|
+
const tags = [];
|
|
72
|
+
for (let i = 0; i < 100; i++) {
|
|
73
|
+
tags.push(`<tag_${i}>`);
|
|
74
|
+
tags.push(`<|llama_tag_${i}|>`);
|
|
75
|
+
}
|
|
76
|
+
const tree = new PrefixTree(tags);
|
|
77
|
+
const text = "Some text content ".repeat(10) + "<tag_50>" + " more text".repeat(10);
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const result = tree.findEarliestTag(text);
|
|
80
|
+
const duration = Date.now() - startTime;
|
|
81
|
+
console.log(`Test: Large tag set (200 tags) - ${result?.tag === "<tag_50>" && duration < 50 ? "PASS" : "FAIL"} (${duration}ms)`);
|
|
82
|
+
// Test partial detection performance
|
|
83
|
+
const partialText = "x".repeat(1000) + "<tag_9";
|
|
84
|
+
const startTime2 = Date.now();
|
|
85
|
+
const partial = tree.findLongestPartialAtEnd(partialText);
|
|
86
|
+
const duration2 = Date.now() - startTime2;
|
|
87
|
+
console.log(`Test: Partial detection perf - ${partial === 7 && duration2 < 100 ? "PASS" : "FAIL"} (${duration2}ms)`);
|
|
88
|
+
}
|
|
89
|
+
// Test Suite 5: Edge Cases
|
|
90
|
+
function testEdgeCases() {
|
|
91
|
+
console.log("\nSuite 5: Edge Cases");
|
|
92
|
+
const tree = new PrefixTree(["<a>", "<ab>", "<abc>"]);
|
|
93
|
+
// Test 1: Nested overlapping tags
|
|
94
|
+
const result1 = tree.findEarliestTag("<a<ab>>");
|
|
95
|
+
console.log(`Test: Nested tags - ${result1?.tag === "<a>" && result1?.index === 0 ? "PASS" : "FAIL"}`);
|
|
96
|
+
// Test 2: Tag prefix of another
|
|
97
|
+
const result2 = tree.findEarliestTag("Text <abc> end");
|
|
98
|
+
console.log(`Test: Tag prefix - ${result2?.tag === "<a>" && result2?.index === 5 ? "PASS" : "FAIL"}`);
|
|
99
|
+
// Test 3: Special characters
|
|
100
|
+
const tree2 = new PrefixTree(["<|tag|>", "<tag\\n>"]);
|
|
101
|
+
const result3 = tree2.findEarliestTag("Start <|tag|> end");
|
|
102
|
+
console.log(`Test: Special chars - ${result3?.tag === "<|tag|>" ? "PASS" : "FAIL"}`);
|
|
103
|
+
// Test 4: Very long tag
|
|
104
|
+
const longTag = "<" + "x".repeat(100) + ">";
|
|
105
|
+
const tree3 = new PrefixTree([longTag]);
|
|
106
|
+
const result4 = tree3.findEarliestTag("Text " + longTag + " end");
|
|
107
|
+
console.log(`Test: Long tag (102 chars) - ${result4?.tag === longTag ? "PASS" : "FAIL"}`);
|
|
108
|
+
// Test 5: Unicode characters
|
|
109
|
+
const tree4 = new PrefixTree(["<🔧>", "<emoji>"]);
|
|
110
|
+
const result5 = tree4.findEarliestTag("Start <🔧> end");
|
|
111
|
+
console.log(`Test: Unicode - ${result5?.tag === "<🔧>" ? "PASS" : "FAIL"}`);
|
|
112
|
+
}
|
|
113
|
+
// Run all tests
|
|
114
|
+
testBasicDetection();
|
|
115
|
+
testPartialDetection();
|
|
116
|
+
testFuzzyMatching();
|
|
117
|
+
testPerformance();
|
|
118
|
+
testEdgeCases();
|
|
119
|
+
console.log("\nAll PrefixTree tests completed!");
|
|
120
|
+
//# sourceMappingURL=test_prefix_tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_prefix_tree.js","sourceRoot":"","sources":["../src/test_prefix_tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { withRetry, RetryConfig, } from "./monolith/plumbing/utils/RetryUtils.js";
|
|
2
|
+
console.log("Starting RetryUtils Tests...\n");
|
|
3
|
+
// Helper to simulate async operations
|
|
4
|
+
async function sleep(ms) {
|
|
5
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6
|
+
}
|
|
7
|
+
// Test Suite 1: Successful Execution
|
|
8
|
+
async function testSuccessfulExecution() {
|
|
9
|
+
console.log("Suite 1: Successful Execution");
|
|
10
|
+
// Test 1: No retry needed
|
|
11
|
+
let callCount = 0;
|
|
12
|
+
const config = new RetryConfig();
|
|
13
|
+
try {
|
|
14
|
+
const result = await withRetry(async () => {
|
|
15
|
+
callCount++;
|
|
16
|
+
return "success";
|
|
17
|
+
}, config, "Test1");
|
|
18
|
+
console.log(`Test: No retry needed - ${result === "success" && callCount === 1 ? "PASS" : "FAIL"}`);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.log(`Test: No retry needed - FAIL (threw error)`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Test Suite 2: Retryable Errors
|
|
25
|
+
async function testRetryableErrors() {
|
|
26
|
+
console.log("\nSuite 2: Retryable Errors");
|
|
27
|
+
// Test 1: Success on 2nd attempt
|
|
28
|
+
let attempt1 = 0;
|
|
29
|
+
const config1 = new RetryConfig();
|
|
30
|
+
try {
|
|
31
|
+
const result = await withRetry(async () => {
|
|
32
|
+
attempt1++;
|
|
33
|
+
if (attempt1 === 1) {
|
|
34
|
+
throw new Error("ETIMEDOUT: Connection timeout");
|
|
35
|
+
}
|
|
36
|
+
return "success";
|
|
37
|
+
}, config1, "Test2.1");
|
|
38
|
+
console.log(`Test: Success on 2nd attempt - ${result === "success" && attempt1 === 2 ? "PASS" : "FAIL (attempts: " + attempt1 + ")"}`);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
console.log(`Test: Success on 2nd attempt - FAIL (threw error)`);
|
|
42
|
+
}
|
|
43
|
+
// Test 2: Success on 3rd attempt
|
|
44
|
+
let attempt2 = 0;
|
|
45
|
+
const config2 = new RetryConfig();
|
|
46
|
+
try {
|
|
47
|
+
const result = await withRetry(async () => {
|
|
48
|
+
attempt2++;
|
|
49
|
+
if (attempt2 < 3) {
|
|
50
|
+
throw new Error("Rate limit exceeded");
|
|
51
|
+
}
|
|
52
|
+
return "success";
|
|
53
|
+
}, config2, "Test2.2");
|
|
54
|
+
console.log(`Test: Success on 3rd attempt - ${result === "success" && attempt2 === 3 ? "PASS" : "FAIL (attempts: " + attempt2 + ")"}`);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
console.log(`Test: Success on 3rd attempt - FAIL (threw error)`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Test Suite 3: Non-Retryable Errors
|
|
61
|
+
async function testNonRetryableErrors() {
|
|
62
|
+
console.log("\nSuite 3: Non-Retryable Errors");
|
|
63
|
+
// Test 1: Validation error (immediate failure)
|
|
64
|
+
let attempt1 = 0;
|
|
65
|
+
const config1 = new RetryConfig();
|
|
66
|
+
try {
|
|
67
|
+
await withRetry(async () => {
|
|
68
|
+
attempt1++;
|
|
69
|
+
throw new Error("Invalid input: missing required field");
|
|
70
|
+
}, config1, "Test3.1");
|
|
71
|
+
console.log(`Test: Non-retryable error - FAIL (should have thrown)`);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
console.log(`Test: Non-retryable error - ${attempt1 === 1 ? "PASS" : "FAIL (attempts: " + attempt1 + ")"}`);
|
|
75
|
+
}
|
|
76
|
+
// Test 2: Permission error
|
|
77
|
+
let attempt2 = 0;
|
|
78
|
+
const config2 = new RetryConfig();
|
|
79
|
+
try {
|
|
80
|
+
await withRetry(async () => {
|
|
81
|
+
attempt2++;
|
|
82
|
+
throw new Error("Permission denied");
|
|
83
|
+
}, config2, "Test3.2");
|
|
84
|
+
console.log(`Test: Permission error - FAIL (should have thrown)`);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.log(`Test: Permission error - ${attempt2 === 1 ? "PASS" : "FAIL (attempts: " + attempt2 + ")"}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Test Suite 4: Exhausted Retries
|
|
91
|
+
async function testExhaustedRetries() {
|
|
92
|
+
console.log("\nSuite 4: Exhausted Retries");
|
|
93
|
+
// Test 1: Max retries exceeded
|
|
94
|
+
let attempt = 0;
|
|
95
|
+
const config = new RetryConfig();
|
|
96
|
+
config.maxRetries = 3;
|
|
97
|
+
try {
|
|
98
|
+
await withRetry(async () => {
|
|
99
|
+
attempt++;
|
|
100
|
+
throw new Error("ETIMEDOUT: persistent timeout");
|
|
101
|
+
}, config, "Test4.1");
|
|
102
|
+
console.log(`Test: Max retries - FAIL (should have thrown)`);
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
// Should attempt 1 initial + 3 retries = 4 total
|
|
106
|
+
console.log(`Test: Max retries - ${attempt === 4 ? "PASS" : "FAIL (attempts: " + attempt + ", expected 4)"}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Test Suite 5: Exponential Backoff
|
|
110
|
+
async function testExponentialBackoff() {
|
|
111
|
+
console.log("\nSuite 5: Exponential Backoff");
|
|
112
|
+
const config = new RetryConfig();
|
|
113
|
+
config.baseDelayMs = 100;
|
|
114
|
+
config.maxDelayMs = 5000;
|
|
115
|
+
// Test 1: First retry delay
|
|
116
|
+
const delay1 = config.getBackoffDelay(0);
|
|
117
|
+
console.log(`Test: First retry delay - ${delay1 >= 100 && delay1 <= 200 ? "PASS" : "FAIL (got " + delay1 + "ms)"}`);
|
|
118
|
+
// Test 2: Second retry delay
|
|
119
|
+
const delay2 = config.getBackoffDelay(1);
|
|
120
|
+
console.log(`Test: Second retry delay - ${delay2 >= 200 && delay2 <= 350 ? "PASS" : "FAIL (got " + delay2 + "ms)"}`);
|
|
121
|
+
// Test 3: Max delay cap
|
|
122
|
+
const delay10 = config.getBackoffDelay(10);
|
|
123
|
+
console.log(`Test: Max delay cap - ${delay10 <= 5000 ? "PASS" : "FAIL (got " + delay10 + "ms)"}`);
|
|
124
|
+
// Test 4: Actual timing (2 retries)
|
|
125
|
+
let attempt = 0;
|
|
126
|
+
const startTime = Date.now();
|
|
127
|
+
try {
|
|
128
|
+
await withRetry(async () => {
|
|
129
|
+
attempt++;
|
|
130
|
+
if (attempt < 3) {
|
|
131
|
+
throw new Error("TIMEOUT: retry me");
|
|
132
|
+
}
|
|
133
|
+
return "success";
|
|
134
|
+
}, config, "Test5.4");
|
|
135
|
+
const duration = Date.now() - startTime;
|
|
136
|
+
// Should take ~100ms + ~200ms = ~300ms (with some variance for jitter)
|
|
137
|
+
console.log(`Test: Actual timing - ${duration >= 250 && duration <= 600 ? "PASS" : "FAIL (took " + duration + "ms)"}`);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
console.log(`Test: Actual timing - FAIL (threw error)`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Test Suite 6: Error Detection
|
|
144
|
+
function testErrorDetection() {
|
|
145
|
+
console.log("\nSuite 6: Error Detection");
|
|
146
|
+
const config = new RetryConfig();
|
|
147
|
+
// Test retryable errors
|
|
148
|
+
console.log(`Test: ETIMEDOUT - ${config.isRetryable("ETIMEDOUT: connection timeout") ? "PASS" : "FAIL"}`);
|
|
149
|
+
console.log(`Test: ECONNRESET - ${config.isRetryable("Error: ECONNRESET") ? "PASS" : "FAIL"}`);
|
|
150
|
+
console.log(`Test: Rate limit - ${config.isRetryable("Rate limit exceeded") ? "PASS" : "FAIL"}`);
|
|
151
|
+
console.log(`Test: Throttle - ${config.isRetryable("Request throttled") ? "PASS" : "FAIL"}`);
|
|
152
|
+
// Test non-retryable errors
|
|
153
|
+
console.log(`Test: Invalid input - ${!config.isRetryable("Invalid input") ? "PASS" : "FAIL"}`);
|
|
154
|
+
console.log(`Test: Permission - ${!config.isRetryable("Permission denied") ? "PASS" : "FAIL"}`);
|
|
155
|
+
}
|
|
156
|
+
// Run all tests
|
|
157
|
+
async function runAllTests() {
|
|
158
|
+
await testSuccessfulExecution();
|
|
159
|
+
await testRetryableErrors();
|
|
160
|
+
await testNonRetryableErrors();
|
|
161
|
+
await testExhaustedRetries();
|
|
162
|
+
await testExponentialBackoff();
|
|
163
|
+
testErrorDetection();
|
|
164
|
+
console.log("\nAll RetryUtils tests completed!");
|
|
165
|
+
}
|
|
166
|
+
runAllTests().catch((err) => {
|
|
167
|
+
console.error("Test error:", err);
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=test_retry_utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_retry_utils.js","sourceRoot":"","sources":["../src/test_retry_utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { MarieEngine } from "./monolith/infrastructure/ai/core/MarieEngine.js";
|
|
2
|
+
import { ToolRegistry } from "./monolith/infrastructure/tools/ToolRegistry.js";
|
|
3
|
+
import { MarieProgressTracker } from "./monolith/infrastructure/ai/core/MarieProgressTracker.js";
|
|
4
|
+
// --- MOCKS ---
|
|
5
|
+
class MockAIProvider {
|
|
6
|
+
async createMessage() {
|
|
7
|
+
return { role: "assistant", content: "Thought" };
|
|
8
|
+
}
|
|
9
|
+
callCount = 0;
|
|
10
|
+
async createMessageStream(params, onUpdate) {
|
|
11
|
+
this.callCount++;
|
|
12
|
+
if (this.callCount > 1) {
|
|
13
|
+
onUpdate({ type: "content_delta", text: "Done. " });
|
|
14
|
+
return { role: "assistant", content: "Done." };
|
|
15
|
+
}
|
|
16
|
+
onUpdate({ type: "content_delta", text: "I will create a file. " });
|
|
17
|
+
onUpdate({
|
|
18
|
+
type: "tool_call_delta",
|
|
19
|
+
index: 0,
|
|
20
|
+
id: "call_123",
|
|
21
|
+
name: "write_to_file"
|
|
22
|
+
});
|
|
23
|
+
onUpdate({
|
|
24
|
+
type: "tool_call_delta",
|
|
25
|
+
index: 0,
|
|
26
|
+
id: "call_123",
|
|
27
|
+
argumentsDelta: '{"path": "test.txt", "content": "hello"}'
|
|
28
|
+
});
|
|
29
|
+
onUpdate({ type: "usage", usage: { totalTokens: 100 } });
|
|
30
|
+
return {
|
|
31
|
+
role: "assistant",
|
|
32
|
+
content: "I will create a file.",
|
|
33
|
+
tool_uses: [{ id: "call_123", name: "write_to_file", input: { path: "test.txt", content: "hello" } }]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
estimateTokens() { return 0; }
|
|
37
|
+
async listModels() { return []; }
|
|
38
|
+
}
|
|
39
|
+
class MockFileSystemPort {
|
|
40
|
+
async readFile() { return ""; }
|
|
41
|
+
async writeFile(p, c) {
|
|
42
|
+
console.log(`[MockFS] Writing to ${p}: ${c}`);
|
|
43
|
+
}
|
|
44
|
+
async deleteFile() { }
|
|
45
|
+
async backupFile() { }
|
|
46
|
+
async restoreFile() { }
|
|
47
|
+
async rollbackAll() { }
|
|
48
|
+
clearBackups() { }
|
|
49
|
+
}
|
|
50
|
+
// --- TEST RUNNER ---
|
|
51
|
+
async function runStrategyTest() {
|
|
52
|
+
console.log("🚀 Starting Strategy Integration Test...");
|
|
53
|
+
const toolRegistry = new ToolRegistry();
|
|
54
|
+
toolRegistry.register({
|
|
55
|
+
name: "write_to_file",
|
|
56
|
+
description: "Write content",
|
|
57
|
+
input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } } },
|
|
58
|
+
execute: async (args) => {
|
|
59
|
+
console.log("[Tool] write_to_file executed");
|
|
60
|
+
return "Success";
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const run = {
|
|
64
|
+
runId: "test_run",
|
|
65
|
+
startedAt: Date.now(),
|
|
66
|
+
steps: 0,
|
|
67
|
+
tools: 0,
|
|
68
|
+
objectives: [
|
|
69
|
+
{ id: 'understand_request', label: 'Understand', status: 'in_progress' },
|
|
70
|
+
{ id: 'execute_plan', label: 'Execute', status: 'pending' },
|
|
71
|
+
{ id: 'deliver_result', label: 'Deliver', status: 'pending' }
|
|
72
|
+
],
|
|
73
|
+
activeObjectiveId: 'understand_request',
|
|
74
|
+
achieved: []
|
|
75
|
+
};
|
|
76
|
+
const events = [];
|
|
77
|
+
const tracker = new MarieProgressTracker({
|
|
78
|
+
onEvent: (e) => {
|
|
79
|
+
events.push(e);
|
|
80
|
+
console.log(`[Event Capture] Captured event: ${e.type}`);
|
|
81
|
+
if (e.type === 'progress_update') {
|
|
82
|
+
console.log(`[Tracker] Progress: ${e.activeObjectiveId} -> ${e.context}`);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
onStream: (c) => console.log(`[Stream] ${c}`)
|
|
86
|
+
}, run);
|
|
87
|
+
const provider = new MockAIProvider();
|
|
88
|
+
const fs = new MockFileSystemPort();
|
|
89
|
+
// We mock VscodeFileSystemPort by name to test environment detection in MarieEngine
|
|
90
|
+
Object.defineProperty(fs.constructor, 'name', { value: 'CliFileSystemPort' });
|
|
91
|
+
const engine = new MarieEngine(provider, toolRegistry, async () => true, // Auto-approve
|
|
92
|
+
undefined, fs);
|
|
93
|
+
console.log("\n--- Executing chatLoop ---");
|
|
94
|
+
await engine.chatLoop([{ role: "user", content: "create a file" }], tracker, async () => { });
|
|
95
|
+
// Wait for throttle timers in dispatcher
|
|
96
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
97
|
+
console.log("\n--- Verification ---");
|
|
98
|
+
console.log("Event types seen:", events.map(e => e.type).join(', '));
|
|
99
|
+
// 1. Verify environment detection
|
|
100
|
+
const state = engine.state;
|
|
101
|
+
console.log(`Test: Environment detected as CLI - ${state.environment === 'cli' ? 'PASS' : 'FAIL'}`);
|
|
102
|
+
// 2. Verify objective transition
|
|
103
|
+
const finalObjective = run.activeObjectiveId;
|
|
104
|
+
console.log(`Test: Objective transitioned to execute_plan - ${finalObjective === 'execute_plan' ? 'PASS' : 'FAIL'}`);
|
|
105
|
+
// 3. Verify event routing (content_delta should be in events)
|
|
106
|
+
const hasContentDelta = events.some(e => e.type === 'content_delta');
|
|
107
|
+
console.log(`Test: MarieEventDispatcher routed content_delta - ${hasContentDelta ? 'PASS' : 'FAIL'}`);
|
|
108
|
+
// 4. Verify tool delta routing
|
|
109
|
+
const hasToolDelta = events.some(e => e.type === 'tool_delta');
|
|
110
|
+
console.log(`Test: MarieEventDispatcher routed tool_delta - ${hasToolDelta ? 'PASS' : 'FAIL'}`);
|
|
111
|
+
console.log("\nStrategy Integration Test Completed!");
|
|
112
|
+
}
|
|
113
|
+
runStrategyTest().catch(console.error);
|
|
114
|
+
//# sourceMappingURL=test_strategy_integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_strategy_integration.js","sourceRoot":"","sources":["../src/test_strategy_integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { StreamTagDetector } from "./monolith/plumbing/utils/StreamTagDetector.js";
|
|
2
|
+
import { OpenRouterStreamParser } from "./monolith/infrastructure/ai/providers/OpenRouterStreamParser.js";
|
|
3
|
+
async function runTests() {
|
|
4
|
+
console.log("Starting Streaming Tests...\n");
|
|
5
|
+
// --- Suite 1: StreamTagDetector ---
|
|
6
|
+
console.log("Suite 1: StreamTagDetector (Component Level)");
|
|
7
|
+
const tests = [
|
|
8
|
+
{
|
|
9
|
+
name: "Normal Content (No Tags)",
|
|
10
|
+
chunks: ["Hello ", "world", "!"],
|
|
11
|
+
expectedTags: []
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "Complete Tag in One Chunk",
|
|
15
|
+
chunks: ["Hello <tool>"],
|
|
16
|
+
expectedTags: ["<tool>"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "Split Tag (<t + ool>)",
|
|
20
|
+
chunks: ["Hello <t", "ool>"],
|
|
21
|
+
expectedTags: ["<tool>"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "Llama 3 Split Tag",
|
|
25
|
+
chunks: ["Start <|tool_", "call_", "begin|> End"],
|
|
26
|
+
expectedTags: ["<|tool_call_begin|>"]
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
let passed = 0;
|
|
30
|
+
for (const test of tests) {
|
|
31
|
+
console.log(`Test: ${test.name}`);
|
|
32
|
+
const detector = new StreamTagDetector();
|
|
33
|
+
const detectedTags = [];
|
|
34
|
+
let outputText = "";
|
|
35
|
+
for (const chunk of test.chunks) {
|
|
36
|
+
const result = detector.process(chunk);
|
|
37
|
+
if (result.type === 'tag')
|
|
38
|
+
detectedTags.push(result.tag);
|
|
39
|
+
if (result.text)
|
|
40
|
+
outputText += result.text;
|
|
41
|
+
}
|
|
42
|
+
// Verification
|
|
43
|
+
const expected = test.expectedTags;
|
|
44
|
+
const actual = detectedTags;
|
|
45
|
+
let p = true;
|
|
46
|
+
if (expected.length !== actual.length)
|
|
47
|
+
p = false;
|
|
48
|
+
else {
|
|
49
|
+
for (let i = 0; i < expected.length; i++) {
|
|
50
|
+
if (expected[i] !== actual[i])
|
|
51
|
+
p = false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (p) {
|
|
55
|
+
console.log(" PASS");
|
|
56
|
+
passed++;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log(` FAIL. Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log(`Suite 1 Results: ${passed}/${tests.length} Passed\n`);
|
|
63
|
+
// --- Suite 2: OpenRouterStreamParser ---
|
|
64
|
+
console.log("Suite 2: OpenRouterStreamParser (Integration Level)");
|
|
65
|
+
// Test Llama 3 Tool Call Parsing
|
|
66
|
+
// Llama 3 format: <|tool_call_begin|> function_name <|tool_call_argument_begin|> {args} <|tool_call_end|>
|
|
67
|
+
const parserTests = [
|
|
68
|
+
{
|
|
69
|
+
name: "Llama 3 Full Tool Call",
|
|
70
|
+
chunks: [
|
|
71
|
+
"Some text ",
|
|
72
|
+
"<|tool_call_begin|> functions.weather_lookup <|tool_call_argument_begin|> ",
|
|
73
|
+
"{\"city\": \"Paris\"}",
|
|
74
|
+
" <|tool_call_end|>"
|
|
75
|
+
],
|
|
76
|
+
expectTool: "weather_lookup"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "Llama 3 Split Across Chunks",
|
|
80
|
+
chunks: [
|
|
81
|
+
"Text <|tool_call_", "begin|> functions.calculator ",
|
|
82
|
+
"<|tool_call_argument_", "begin|> {\"expression\": \"2+", "2\"} <|tool_call_end|>"
|
|
83
|
+
],
|
|
84
|
+
expectTool: "calculator"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: "Multiple Tags in One Chunk",
|
|
88
|
+
chunks: [
|
|
89
|
+
"<|tool_call_begin|> tool1 <|tool_call_argument_begin|> {} <|tool_call_end|><|tool_call_begin|> tool2 <|tool_call_argument_begin|> {} <|tool_call_end|>"
|
|
90
|
+
],
|
|
91
|
+
expectTool: "tool2" // The test loop picks the last one or we can check count
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "Messy Llama 3 (Plural & Missing Argument Tag)",
|
|
95
|
+
chunks: [
|
|
96
|
+
"<|tool_call_begin|> functions.test_tool <|tool_call_arguments_begin|> {\"key\": \"value\"} <|tool_call_end|>",
|
|
97
|
+
"<|tool_call_begin|> direct_tool {\"foo\": \"bar\"} <|tool_call_end|>"
|
|
98
|
+
],
|
|
99
|
+
expectTool: "direct_tool"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "Standard Content (No Tools)",
|
|
103
|
+
chunks: ["Just text"],
|
|
104
|
+
expectTool: null
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "Markdown JSON (No Tags) - REPRODUCTION",
|
|
108
|
+
chunks: [
|
|
109
|
+
"I will read the file.\n",
|
|
110
|
+
"```json\n",
|
|
111
|
+
"{\"name\": \"read_file\", \"input\": {\"path\": \"foo.ts\"}}\n",
|
|
112
|
+
"```"
|
|
113
|
+
],
|
|
114
|
+
expectTool: "read_file"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "Non-tool tags shouldn't be swallowed",
|
|
118
|
+
chunks: ["I have a plan:\n", "<Plan>\n", "1. Search\n", "2. Replace\n", "</Plan>\n", "Proceeding now."],
|
|
119
|
+
expectText: "I have a plan:\n<Plan>\n1. Search\n2. Replace\n</Plan>\nProceeding now."
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "Truncated buffer should flush as text",
|
|
123
|
+
chunks: ["Starting tool...\n", "<tool>\n", "{\"name\": \"incomplete\""],
|
|
124
|
+
expectText: "Starting tool...\n<tool>\n{\"name\": \"incomplete\""
|
|
125
|
+
}
|
|
126
|
+
];
|
|
127
|
+
passed = 0;
|
|
128
|
+
for (const test of parserTests) {
|
|
129
|
+
console.log(`Test: ${test.name}`);
|
|
130
|
+
const parser = new OpenRouterStreamParser();
|
|
131
|
+
let foundTools = [];
|
|
132
|
+
let emittedText = "";
|
|
133
|
+
let fullContent = "";
|
|
134
|
+
for (const chunk of test.chunks) {
|
|
135
|
+
fullContent += chunk;
|
|
136
|
+
const events = parser.processContent(chunk);
|
|
137
|
+
for (const event of events) {
|
|
138
|
+
if (event.type === 'tool_call_delta') {
|
|
139
|
+
if (event.name && !foundTools.includes(event.name)) {
|
|
140
|
+
foundTools.push(event.name);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (event.type === 'content_delta') {
|
|
144
|
+
emittedText += event.text;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Finalize parser
|
|
149
|
+
const finalEvents = parser.finalize(fullContent);
|
|
150
|
+
for (const event of finalEvents) {
|
|
151
|
+
if (event.type === 'tool_call_delta') {
|
|
152
|
+
if (event.name && !foundTools.includes(event.name)) {
|
|
153
|
+
foundTools.push(event.name);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (event.type === 'content_delta') {
|
|
157
|
+
emittedText += event.text;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (test.expectTool) {
|
|
161
|
+
if (foundTools.includes(test.expectTool)) {
|
|
162
|
+
console.log(` PASS: Detected tool '${test.expectTool}'`);
|
|
163
|
+
passed++;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
console.log(` FAIL: Expected '${test.expectTool}', found [${foundTools.join(', ')}]`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else if (test.expectText) {
|
|
170
|
+
if (emittedText.trim() === test.expectText.trim()) {
|
|
171
|
+
console.log(" PASS: Text emitted correctly");
|
|
172
|
+
passed++;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
console.log(` FAIL: Text mismatch.\n Expected: [${test.expectText.trim()}]\n Got: [${emittedText.trim()}]`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
if (foundTools.length === 0) {
|
|
180
|
+
console.log(" PASS: No tool detected");
|
|
181
|
+
passed++;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
console.log(` FAIL: Unexpected tool(s) found: [${foundTools.join(', ')}]`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
console.log(`Suite 2 Results: ${passed}/${parserTests.length} Passed\n`);
|
|
189
|
+
}
|
|
190
|
+
runTests();
|
|
191
|
+
//# sourceMappingURL=test_streaming_fragility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_streaming_fragility.js","sourceRoot":"","sources":["../src/test_streaming_fragility.ts"],"names":[],"mappings":"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"}
|