@noorm/marie-cli 0.1.15 → 0.1.17
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/cli-new/components/App.js +3 -1
- package/dist/cli-new/components/App.js.map +1 -1
- package/dist/cli-new/components/Banner.js +5 -5
- package/dist/cli-new/components/Banner.js.map +1 -1
- package/dist/cli-new/hooks/useUpdateCheck.js +17 -0
- package/dist/cli-new/hooks/useUpdateCheck.js.map +1 -0
- package/dist/domain/DomainEntity.js +7 -0
- package/dist/domain/DomainEntity.js.map +1 -0
- package/dist/extension.cjs +164 -154
- package/dist/extension.js +473 -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/MarieSentinelService.js +23 -3
- package/dist/monolith/plumbing/analysis/MarieSentinelService.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/monolith/services/UpdateService.js +61 -0
- package/dist/monolith/services/UpdateService.js.map +1 -0
- package/dist/plumbing/BaseTool.js +7 -0
- package/dist/plumbing/BaseTool.js.map +1 -0
- package/dist/prompts.js +90 -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,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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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Providers } from "./Providers.js";
|
|
3
|
+
import { ApprovalPanel } from "./components/ApprovalPanel.js";
|
|
4
|
+
import { ChatPanel } from "./components/ChatPanel.js";
|
|
5
|
+
import { Composer } from "./components/Composer.js";
|
|
6
|
+
import { HeaderBar } from "./components/HeaderBar.js";
|
|
7
|
+
import { SessionList } from "./components/SessionList.js";
|
|
8
|
+
import { useWebviewState } from "./context/WebviewStateContext.js";
|
|
9
|
+
function AppContent() {
|
|
10
|
+
const { state, actions } = useWebviewState();
|
|
11
|
+
return (_jsxs("div", { className: "layout", children: [_jsx(SessionList, { sessions: state.sessions, currentSessionId: state.currentSessionId, onLoad: actions.loadSession, onCreate: actions.createSession, onRefresh: actions.refreshSessions }), _jsxs("main", { className: "right", children: [_jsx(HeaderBar, { config: state.config, isLoading: state.isLoading, onAutonomyMode: actions.setAutonomyMode, onClear: actions.clearSession, onStop: actions.stopGeneration, onSettings: actions.openSettings }), _jsx(ChatPanel, { messages: state.messages, streamingBuffer: state.streamingBuffer }), _jsx(ApprovalPanel, { pendingApproval: state.pendingApproval, onApprove: actions.approveTool }), _jsx(Composer, { isLoading: state.isLoading, onSend: actions.sendMessage, onModels: actions.getModels })] })] }));
|
|
12
|
+
}
|
|
13
|
+
export default function App() {
|
|
14
|
+
return (_jsx(Providers, { children: _jsx(AppContent, {}) }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=App.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"App.js","sourceRoot":"","sources":["../../src/webview-ui/App.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAA;AAElE,SAAS,UAAU;IACf,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,eAAe,EAAE,CAAA;IAE5C,OAAO,CACH,eAAK,SAAS,EAAC,QAAQ,aACnB,KAAC,WAAW,IACR,QAAQ,EAAE,KAAK,CAAC,QAAQ,EACxB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EACxC,MAAM,EAAE,OAAO,CAAC,WAAW,EAC3B,QAAQ,EAAE,OAAO,CAAC,aAAa,EAC/B,SAAS,EAAE,OAAO,CAAC,eAAe,GACpC,EAEF,gBAAM,SAAS,EAAC,OAAO,aACnB,KAAC,SAAS,IACN,MAAM,EAAE,KAAK,CAAC,MAAM,EACpB,SAAS,EAAE,KAAK,CAAC,SAAS,EAC1B,cAAc,EAAE,OAAO,CAAC,eAAe,EACvC,OAAO,EAAE,OAAO,CAAC,YAAY,EAC7B,MAAM,EAAE,OAAO,CAAC,cAAc,EAC9B,UAAU,EAAE,OAAO,CAAC,YAAY,GAClC,EAEF,KAAC,SAAS,IAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,GAAI,EAE/E,KAAC,aAAa,IAAC,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,SAAS,EAAE,OAAO,CAAC,WAAW,GAAI,EAEzF,KAAC,QAAQ,IAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,GAAI,IAC/F,IACL,CACT,CAAA;AACL,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,GAAG;IACvB,OAAO,CACH,KAAC,SAAS,cACN,KAAC,UAAU,KAAG,GACN,CACf,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { WebviewStateProvider } from "./context/WebviewStateContext.js";
|
|
3
|
+
export function Providers({ children }) {
|
|
4
|
+
return _jsx(WebviewStateProvider, { children: children });
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=Providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Providers.js","sourceRoot":"","sources":["../../src/webview-ui/Providers.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AAEvE,MAAM,UAAU,SAAS,CAAC,EAAE,QAAQ,EAA2B;IAC3D,OAAO,KAAC,oBAAoB,cAAE,QAAQ,GAAwB,CAAA;AAClE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function ApprovalPanel({ pendingApproval, onApprove, }) {
|
|
3
|
+
if (!pendingApproval) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
return (_jsxs("div", { className: "approval", children: [_jsx("strong", { children: "Approval required" }), _jsxs("div", { children: ["Tool: ", _jsx("code", { children: pendingApproval.toolName })] }), _jsx("pre", { children: JSON.stringify(pendingApproval.toolInput, null, 2) }), _jsxs("div", { className: "row", children: [_jsx("button", { onClick: () => onApprove(true), children: "Approve" }), _jsx("button", { onClick: () => onApprove(false), children: "Deny" })] })] }));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=ApprovalPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalPanel.js","sourceRoot":"","sources":["../../../src/webview-ui/components/ApprovalPanel.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,aAAa,CAAC,EAC1B,eAAe,EACf,SAAS,GAIZ;IACG,IAAI,CAAC,eAAe,EAAE,CAAC;QACnB,OAAO,IAAI,CAAA;IACf,CAAC;IAED,OAAO,CACH,eAAK,SAAS,EAAC,UAAU,aACrB,iDAAkC,EAClC,oCACU,yBAAO,eAAe,CAAC,QAAQ,GAAQ,IAC3C,EACN,wBAAM,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAO,EAC/D,eAAK,SAAS,EAAC,KAAK,aAChB,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,wBAAkB,EACxD,iBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,qBAAe,IACpD,IACJ,CACT,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
function roleLabel(role) {
|
|
4
|
+
if (role === "assistant")
|
|
5
|
+
return "Marie";
|
|
6
|
+
if (role === "user")
|
|
7
|
+
return "You";
|
|
8
|
+
return "System";
|
|
9
|
+
}
|
|
10
|
+
export function ChatPanel({ messages, streamingBuffer, }) {
|
|
11
|
+
const chatRef = useRef(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (chatRef.current) {
|
|
14
|
+
chatRef.current.scrollTop = chatRef.current.scrollHeight;
|
|
15
|
+
}
|
|
16
|
+
}, [messages, streamingBuffer]);
|
|
17
|
+
return (_jsxs("section", { className: "chat", ref: chatRef, children: [messages.map((message) => (_jsxs("div", { className: `msg ${message.role}`, children: [_jsx("div", { className: "role", children: roleLabel(message.role) }), _jsx("pre", { children: message.content })] }, message.id))), streamingBuffer && (_jsxs("div", { className: "msg assistant stream", children: [_jsx("div", { className: "role", children: "Marie" }), _jsx("pre", { children: streamingBuffer })] }))] }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ChatPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatPanel.js","sourceRoot":"","sources":["../../../src/webview-ui/components/ChatPanel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAGzC,SAAS,SAAS,CAAC,IAAuB;IACtC,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,OAAO,CAAA;IACxC,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAA;IACjC,OAAO,QAAQ,CAAA;AACnB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EACtB,QAAQ,EACR,eAAe,GAIlB;IACG,MAAM,OAAO,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAA;IAEnD,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAA;QAC5D,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAA;IAE/B,OAAO,CACH,mBAAS,SAAS,EAAC,MAAM,EAAC,GAAG,EAAE,OAAO,aACjC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvB,eAAK,SAAS,EAAE,OAAO,OAAO,CAAC,IAAI,EAAE,aACjC,cAAK,SAAS,EAAC,MAAM,YAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,GAAO,EACrD,wBAAM,OAAO,CAAC,OAAO,GAAO,KAFY,OAAO,CAAC,EAAE,CAGhD,CACT,CAAC,EACD,eAAe,IAAI,CAChB,eAAK,SAAS,EAAC,sBAAsB,aACjC,cAAK,SAAS,EAAC,MAAM,sBAAY,EACjC,wBAAM,eAAe,GAAO,IAC1B,CACT,IACK,CACb,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
export function Composer({ isLoading, onSend, onModels, }) {
|
|
4
|
+
const [input, setInput] = useState("");
|
|
5
|
+
const submit = () => {
|
|
6
|
+
const text = input.trim();
|
|
7
|
+
if (!text)
|
|
8
|
+
return;
|
|
9
|
+
setInput("");
|
|
10
|
+
onSend(text);
|
|
11
|
+
};
|
|
12
|
+
return (_jsxs("footer", { className: "composer", children: [_jsx("textarea", { value: input, onChange: (e) => setInput(e.target.value), onKeyDown: (e) => {
|
|
13
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
submit();
|
|
16
|
+
}
|
|
17
|
+
}, placeholder: "Ask Marie\u2026" }), _jsxs("div", { className: "stack", children: [_jsx("button", { onClick: submit, disabled: isLoading, children: "Send" }), _jsx("button", { onClick: onModels, className: "secondary", children: "Models" })] })] }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=Composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Composer.js","sourceRoot":"","sources":["../../../src/webview-ui/components/Composer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,MAAM,UAAU,QAAQ,CAAC,EACrB,SAAS,EACT,MAAM,EACN,QAAQ,GAKX;IACG,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtC,MAAM,MAAM,GAAG,GAAG,EAAE;QAChB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,QAAQ,CAAC,EAAE,CAAC,CAAA;QACZ,MAAM,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC,CAAA;IAED,OAAO,CACH,kBAAQ,SAAS,EAAC,UAAU,aACxB,mBACI,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;oBACb,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;wBACnC,CAAC,CAAC,cAAc,EAAE,CAAA;wBAClB,MAAM,EAAE,CAAA;oBACZ,CAAC;gBACL,CAAC,EACD,WAAW,EAAC,iBAAY,GAC1B,EACF,eAAK,SAAS,EAAC,OAAO,aAClB,iBAAQ,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,qBAEnC,EACT,iBAAQ,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAC,WAAW,uBAEvC,IACP,IACD,CACZ,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function HeaderBar({ config, isLoading, onAutonomyMode, onClear, onStop, onSettings, }) {
|
|
3
|
+
return (_jsxs("header", { className: "top", children: [_jsxs("div", { children: [_jsxs("div", { children: [_jsx("strong", { children: "Marie" }), " \u00B7 ", config.provider, " \u00B7 ", config.model] }), _jsxs("div", { className: "muted", children: ["Spirit Pressure: ", config.autonomyMode === 'ascension' ? 'ASCENDANT' : config.autonomyMode, isLoading ? " · Running…" : ""] })] }), _jsxs("div", { className: "row", children: [_jsxs("select", { value: config.autonomyMode, onChange: (e) => onAutonomyMode(e.target.value), children: [_jsx("option", { value: "balanced", children: "balanced" }), _jsx("option", { value: "high", children: "high" }), _jsx("option", { value: "ascension", children: "ascension" })] }), _jsx("button", { onClick: onClear, className: "secondary", children: "Clear" }), _jsx("button", { onClick: onStop, className: "secondary", children: "Stop" }), _jsx("button", { onClick: onSettings, className: "secondary", children: "Settings" })] })] }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=HeaderBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HeaderBar.js","sourceRoot":"","sources":["../../../src/webview-ui/components/HeaderBar.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,SAAS,CAAC,EACtB,MAAM,EACN,SAAS,EACT,cAAc,EACd,OAAO,EACP,MAAM,EACN,UAAU,GAQb;IACG,OAAO,CACH,kBAAQ,SAAS,EAAC,KAAK,aACnB,0BACI,0BACI,qCAAsB,cAAI,MAAM,CAAC,QAAQ,cAAK,MAAM,CAAC,KAAK,IACxD,EACN,eAAK,SAAS,EAAC,OAAO,kCAAmB,MAAM,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAO,IACrJ,EACN,eAAK,SAAS,EAAC,KAAK,aAChB,kBAAQ,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,aAC/E,iBAAQ,KAAK,EAAC,UAAU,yBAAkB,EAC1C,iBAAQ,KAAK,EAAC,MAAM,qBAAc,EAClC,iBAAQ,KAAK,EAAC,WAAW,0BAAmB,IACvC,EACT,iBAAQ,OAAO,EAAE,OAAO,EAAE,SAAS,EAAC,WAAW,sBAEtC,EACT,iBAAQ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAC,WAAW,qBAErC,EACT,iBAAQ,OAAO,EAAE,UAAU,EAAE,SAAS,EAAC,WAAW,yBAEzC,IACP,IACD,CACZ,CAAA;AACL,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
function formatSessionDate(timestamp) {
|
|
3
|
+
try {
|
|
4
|
+
return new Date(timestamp).toLocaleDateString();
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return "";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function SessionList({ sessions, currentSessionId, onLoad, onCreate, onRefresh, }) {
|
|
11
|
+
const sorted = [...sessions].sort((a, b) => Number(b.isPinned) - Number(a.isPinned) || b.lastModified - a.lastModified);
|
|
12
|
+
return (_jsxs("aside", { className: "left stack", children: [_jsxs("div", { className: "row", children: [_jsx("button", { onClick: onCreate, children: "New" }), _jsx("button", { onClick: onRefresh, className: "secondary", children: "Refresh" })] }), _jsx("div", { className: "muted", children: "Sessions" }), _jsxs("div", { className: "stack", children: [sorted.length === 0 && _jsx("div", { className: "muted", children: "No sessions" }), sorted.map((session) => (_jsxs("button", { onClick: () => onLoad(session.id), className: `session ${session.id === currentSessionId ? "active" : ""}`, children: [_jsxs("span", { children: [session.isPinned ? "📌 " : "", session.title || "New Session"] }), _jsx("span", { className: "muted", children: formatSessionDate(session.lastModified) })] }, session.id)))] })] }));
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=SessionList.js.map
|