@litmers/cursorflow-orchestrator 0.1.15 โ 0.1.18
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/CHANGELOG.md +7 -1
- package/README.md +1 -0
- package/commands/cursorflow-run.md +2 -0
- package/commands/cursorflow-triggers.md +250 -0
- package/dist/cli/clean.js +1 -1
- package/dist/cli/clean.js.map +1 -1
- package/dist/cli/init.js +13 -8
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/logs.js +24 -15
- package/dist/cli/logs.js.map +1 -1
- package/dist/cli/monitor.js +12 -3
- package/dist/cli/monitor.js.map +1 -1
- package/dist/cli/prepare.js +36 -13
- package/dist/cli/prepare.js.map +1 -1
- package/dist/cli/resume.js.map +1 -1
- package/dist/core/orchestrator.js +10 -6
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/reviewer.d.ts +6 -4
- package/dist/core/reviewer.js +7 -5
- package/dist/core/reviewer.js.map +1 -1
- package/dist/core/runner.d.ts +8 -0
- package/dist/core/runner.js +166 -14
- package/dist/core/runner.js.map +1 -1
- package/dist/utils/config.js +13 -4
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/doctor.js +28 -1
- package/dist/utils/doctor.js.map +1 -1
- package/dist/utils/enhanced-logger.d.ts +2 -2
- package/dist/utils/enhanced-logger.js +102 -34
- package/dist/utils/enhanced-logger.js.map +1 -1
- package/dist/utils/repro-thinking-logs.d.ts +1 -0
- package/dist/utils/repro-thinking-logs.js +80 -0
- package/dist/utils/repro-thinking-logs.js.map +1 -0
- package/dist/utils/types.d.ts +12 -0
- package/dist/utils/webhook.js +3 -0
- package/dist/utils/webhook.js.map +1 -1
- package/package.json +4 -2
- package/scripts/ai-security-check.js +3 -0
- package/scripts/local-security-gate.sh +9 -1
- package/scripts/verify-and-fix.sh +37 -0
- package/src/cli/clean.ts +1 -1
- package/src/cli/init.ts +12 -9
- package/src/cli/logs.ts +25 -15
- package/src/cli/monitor.ts +13 -4
- package/src/cli/prepare.ts +36 -15
- package/src/cli/resume.ts +1 -1
- package/src/core/orchestrator.ts +10 -6
- package/src/core/reviewer.ts +14 -9
- package/src/core/runner.ts +173 -15
- package/src/utils/config.ts +12 -5
- package/src/utils/doctor.ts +31 -1
- package/src/utils/enhanced-logger.ts +105 -40
- package/src/utils/repro-thinking-logs.ts +54 -0
- package/src/utils/types.ts +12 -0
- package/src/utils/webhook.ts +3 -0
- package/scripts/simple-logging-test.sh +0 -97
- package/scripts/test-real-cursor-lifecycle.sh +0 -289
- package/scripts/test-real-logging.sh +0 -289
- package/scripts/test-streaming-multi-task.sh +0 -247
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import * as fs from 'fs';
|
|
15
15
|
import * as path from 'path';
|
|
16
|
-
import {
|
|
16
|
+
import { Transform, TransformCallback } from 'stream';
|
|
17
17
|
import { EnhancedLogConfig } from './types';
|
|
18
18
|
|
|
19
19
|
// Re-export for backwards compatibility
|
|
@@ -163,6 +163,23 @@ export class StreamingMessageParser {
|
|
|
163
163
|
},
|
|
164
164
|
});
|
|
165
165
|
break;
|
|
166
|
+
|
|
167
|
+
case 'thinking':
|
|
168
|
+
// Thinking message (Claude 3.7+ etc.)
|
|
169
|
+
if (json.subtype === 'delta' && json.text) {
|
|
170
|
+
// Check if this is a new message or continuation
|
|
171
|
+
if (this.currentRole !== 'thinking') {
|
|
172
|
+
// Flush previous message if any
|
|
173
|
+
this.flush();
|
|
174
|
+
this.currentRole = 'thinking';
|
|
175
|
+
this.messageStartTime = json.timestamp_ms || Date.now();
|
|
176
|
+
}
|
|
177
|
+
this.currentMessage += json.text;
|
|
178
|
+
} else if (json.subtype === 'completed') {
|
|
179
|
+
// Thinking completed - flush immediately
|
|
180
|
+
this.flush();
|
|
181
|
+
}
|
|
182
|
+
break;
|
|
166
183
|
}
|
|
167
184
|
}
|
|
168
185
|
|
|
@@ -191,7 +208,7 @@ export class StreamingMessageParser {
|
|
|
191
208
|
}
|
|
192
209
|
|
|
193
210
|
export interface ParsedMessage {
|
|
194
|
-
type: 'system' | 'user' | 'assistant' | 'tool' | 'tool_result' | 'result';
|
|
211
|
+
type: 'system' | 'user' | 'assistant' | 'tool' | 'tool_result' | 'result' | 'thinking';
|
|
195
212
|
role: string;
|
|
196
213
|
content: string;
|
|
197
214
|
timestamp: number;
|
|
@@ -505,6 +522,21 @@ export class EnhancedLogManager {
|
|
|
505
522
|
formatted = `[${ts}] ๐ RESL: ${msg.metadata?.toolName || 'Tool'}${toolResultLines}\n`;
|
|
506
523
|
break;
|
|
507
524
|
|
|
525
|
+
case 'thinking':
|
|
526
|
+
// Format thinking block
|
|
527
|
+
const thinkLabel = `[ ๐ค THINKING ] `;
|
|
528
|
+
const thinkWidth = 80;
|
|
529
|
+
const thinkTop = `โโ${thinkLabel}${'โ'.repeat(Math.max(0, thinkWidth - thinkLabel.length - 2))}`;
|
|
530
|
+
const thinkBottom = `โโ${'โ'.repeat(thinkWidth - 2)}`;
|
|
531
|
+
|
|
532
|
+
const thinkLines = msg.content.trim().split('\n');
|
|
533
|
+
formatted = `[${ts}] ${thinkTop}\n`;
|
|
534
|
+
for (const line of thinkLines) {
|
|
535
|
+
formatted += `[${ts}] โ ${line}\n`;
|
|
536
|
+
}
|
|
537
|
+
formatted += `[${ts}] ${thinkBottom}\n`;
|
|
538
|
+
break;
|
|
539
|
+
|
|
508
540
|
default:
|
|
509
541
|
formatted = `[${ts}] ${msg.content}\n`;
|
|
510
542
|
}
|
|
@@ -669,20 +701,71 @@ export class EnhancedLogManager {
|
|
|
669
701
|
this.cleanTransform.write(data);
|
|
670
702
|
}
|
|
671
703
|
|
|
672
|
-
//
|
|
673
|
-
this.
|
|
704
|
+
// Process lines for readable log and JSON entries
|
|
705
|
+
this.lineBuffer += text;
|
|
706
|
+
const lines = this.lineBuffer.split('\n');
|
|
707
|
+
this.lineBuffer = lines.pop() || '';
|
|
674
708
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
709
|
+
for (const line of lines) {
|
|
710
|
+
const cleanLine = stripAnsi(line).trim();
|
|
711
|
+
if (!cleanLine) continue;
|
|
712
|
+
|
|
713
|
+
// Handle streaming JSON messages (for boxes, etc. in readable log)
|
|
714
|
+
if (cleanLine.startsWith('{')) {
|
|
715
|
+
if (this.streamingParser) {
|
|
716
|
+
this.streamingParser.parseLine(cleanLine);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Special handling for terminal.jsonl entries for AI messages
|
|
720
|
+
if (this.config.writeJsonLog) {
|
|
721
|
+
try {
|
|
722
|
+
const json = JSON.parse(cleanLine);
|
|
723
|
+
let displayMsg = cleanLine;
|
|
724
|
+
let metadata = { ...json };
|
|
725
|
+
|
|
726
|
+
// Extract cleaner text for significant AI message types
|
|
727
|
+
if (json.type === 'thinking' && json.text) {
|
|
728
|
+
displayMsg = json.text;
|
|
729
|
+
} else if (json.type === 'assistant' && json.message?.content) {
|
|
730
|
+
displayMsg = json.message.content
|
|
731
|
+
.filter((c: any) => c.type === 'text')
|
|
732
|
+
.map((c: any) => c.text)
|
|
733
|
+
.join('');
|
|
734
|
+
} else if (json.type === 'user' && json.message?.content) {
|
|
735
|
+
displayMsg = json.message.content
|
|
736
|
+
.filter((c: any) => c.type === 'text')
|
|
737
|
+
.map((c: any) => c.text)
|
|
738
|
+
.join('');
|
|
739
|
+
} else if (json.type === 'tool_call' && json.subtype === 'started') {
|
|
740
|
+
const toolName = Object.keys(json.tool_call)[0] || 'unknown';
|
|
741
|
+
const args = json.tool_call[toolName]?.args || {};
|
|
742
|
+
displayMsg = `๐ง CALL: ${toolName}(${JSON.stringify(args)})`;
|
|
743
|
+
} else if (json.type === 'tool_call' && json.subtype === 'completed') {
|
|
744
|
+
const toolName = Object.keys(json.tool_call)[0] || 'unknown';
|
|
745
|
+
displayMsg = `๐ RESL: ${toolName}`;
|
|
746
|
+
} else if (json.type === 'result') {
|
|
747
|
+
displayMsg = json.result || 'Task completed';
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
this.writeJsonEntry({
|
|
751
|
+
timestamp: new Date().toISOString(),
|
|
752
|
+
level: 'stdout',
|
|
753
|
+
lane: this.session.laneName,
|
|
754
|
+
task: this.session.taskName,
|
|
755
|
+
message: displayMsg.substring(0, 2000), // Larger limit for AI text
|
|
756
|
+
metadata,
|
|
757
|
+
});
|
|
758
|
+
continue; // Already logged this JSON line
|
|
759
|
+
} catch {
|
|
760
|
+
// Not valid JSON or error, fall through to regular logging
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Also include significant info/status lines in readable log (compact)
|
|
766
|
+
if (this.readableLogFd !== null) {
|
|
680
767
|
// Look for log lines: [ISO_DATE] [LEVEL] ...
|
|
681
|
-
if (cleanLine &&
|
|
682
|
-
!cleanLine.startsWith('{') &&
|
|
683
|
-
!this.isNoiseLog(cleanLine) &&
|
|
684
|
-
/\[\d{4}-\d{2}-\d{2}T/.test(cleanLine)) {
|
|
685
|
-
|
|
768
|
+
if (!this.isNoiseLog(cleanLine) && /\[\d{4}-\d{2}-\d{2}T/.test(cleanLine)) {
|
|
686
769
|
try {
|
|
687
770
|
// Check if it has a level marker
|
|
688
771
|
if (/\[(INFO|WARN|ERROR|SUCCESS|DEBUG)\]/.test(cleanLine)) {
|
|
@@ -698,44 +781,26 @@ export class EnhancedLogManager {
|
|
|
698
781
|
} catch {}
|
|
699
782
|
}
|
|
700
783
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
if (this.config.writeJsonLog) {
|
|
705
|
-
const cleanText = stripAnsi(text).trim();
|
|
706
|
-
if (cleanText && !this.isNoiseLog(cleanText)) {
|
|
784
|
+
|
|
785
|
+
// Write regular non-JSON lines to terminal.jsonl
|
|
786
|
+
if (this.config.writeJsonLog && !this.isNoiseLog(cleanLine)) {
|
|
707
787
|
this.writeJsonEntry({
|
|
708
788
|
timestamp: new Date().toISOString(),
|
|
709
789
|
level: 'stdout',
|
|
710
790
|
lane: this.session.laneName,
|
|
711
791
|
task: this.session.taskName,
|
|
712
|
-
message:
|
|
713
|
-
raw: this.config.keepRawLogs ? undefined :
|
|
792
|
+
message: cleanLine.substring(0, 1000),
|
|
793
|
+
raw: this.config.keepRawLogs ? undefined : line.substring(0, 1000),
|
|
714
794
|
});
|
|
715
795
|
}
|
|
716
796
|
}
|
|
717
797
|
}
|
|
718
798
|
|
|
719
799
|
/**
|
|
720
|
-
* Parse streaming JSON data for readable log
|
|
800
|
+
* Parse streaming JSON data for readable log - legacy, integrated into writeStdout
|
|
721
801
|
*/
|
|
722
802
|
private parseStreamingData(text: string): void {
|
|
723
|
-
if
|
|
724
|
-
|
|
725
|
-
// Buffer incomplete lines
|
|
726
|
-
this.lineBuffer += text;
|
|
727
|
-
const lines = this.lineBuffer.split('\n');
|
|
728
|
-
|
|
729
|
-
// Keep the last incomplete line in buffer
|
|
730
|
-
this.lineBuffer = lines.pop() || '';
|
|
731
|
-
|
|
732
|
-
// Parse complete lines
|
|
733
|
-
for (const line of lines) {
|
|
734
|
-
const trimmed = line.trim();
|
|
735
|
-
if (trimmed.startsWith('{')) {
|
|
736
|
-
this.streamingParser.parseLine(trimmed);
|
|
737
|
-
}
|
|
738
|
-
}
|
|
803
|
+
// Legacy method, no longer used but kept for internal references if any
|
|
739
804
|
}
|
|
740
805
|
|
|
741
806
|
/**
|
|
@@ -873,7 +938,7 @@ export class EnhancedLogManager {
|
|
|
873
938
|
|
|
874
939
|
// Skip common progress/spinner patterns
|
|
875
940
|
const noisePatterns = [
|
|
876
|
-
/^[\s
|
|
941
|
+
/^[\sโโโโโโโโดโฌโค]+$/, // Box drawing only (removed duplicate โ)
|
|
877
942
|
/^[.\s]+$/, // Dots only
|
|
878
943
|
/^[=>\s-]+$/, // Progress bar characters
|
|
879
944
|
/^\d+%$/, // Percentage only
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { createLogManager } from './enhanced-logger';
|
|
4
|
+
|
|
5
|
+
async function testThinkingLogs() {
|
|
6
|
+
const testDir = path.join(process.cwd(), '_test_thinking_logs');
|
|
7
|
+
if (fs.existsSync(testDir)) {
|
|
8
|
+
fs.rmSync(testDir, { recursive: true });
|
|
9
|
+
}
|
|
10
|
+
fs.mkdirSync(testDir, { recursive: true });
|
|
11
|
+
|
|
12
|
+
console.log('--- Initializing Log Manager ---');
|
|
13
|
+
const manager = createLogManager(testDir, 'test-lane-thinking', {
|
|
14
|
+
writeJsonLog: true,
|
|
15
|
+
keepRawLogs: true
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
manager.setTask('repro-thinking-task', 'sonnet-4.5-thinking');
|
|
19
|
+
|
|
20
|
+
const logLines = [
|
|
21
|
+
'{"type":"tool_call","subtype":"started","call_id":"0_tool_54a8fcc9-6981-4f59-aeb6-3ab6d37b2","tool_call":{"readToolCall":{"args":{"path":"/home/eugene/workbench/workbench-os-eungjin/_cursorflow/worktrees/cursorflow/run-mjfxp57i/agent_output.txt"}}}}',
|
|
22
|
+
'{"type":"thinking","subtype":"delta","text":"**Defining Installation Strategy**\\n\\nI\'ve considered the `package.json` file as the central point for installation in automated environments. Thinking now about how that impacts the user\'s ultimate goal, given this is how the process begins in these environments.\\n\\n\\n"}',
|
|
23
|
+
'{"type":"thinking","subtype":"delta","text":"**Clarifying Execution Context**\\n\\nI\'m focused on the user\'s explicit command: `pnpm add @convex-dev/agent ai @ai-sdk/google zod`. My inability to directly execute this is a key constraint. I\'m exploring ways to inform the user about this. I\'ve considered that, without the tools required to run the original command, any attempt to run a command like `grep` or `date` is pointless and will fail.\\n\\n\\n"}',
|
|
24
|
+
'{"type":"tool_call","subtype":"started","call_id":"0_tool_d8f826c8-9d8f-4cab-9ff8-1c47d1ac1","tool_call":{"shellToolCall":{"args":{"command":"date"}}}}'
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
console.log('\n--- Feeding Log Lines to Manager ---');
|
|
28
|
+
for (const line of logLines) {
|
|
29
|
+
console.log('Processing:', line.substring(0, 100) + '...');
|
|
30
|
+
manager.writeStdout(line + '\n');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
manager.close();
|
|
34
|
+
|
|
35
|
+
console.log('\n--- Verifying terminal-readable.log ---');
|
|
36
|
+
const readableLog = fs.readFileSync(path.join(testDir, 'terminal-readable.log'), 'utf8');
|
|
37
|
+
console.log(readableLog);
|
|
38
|
+
|
|
39
|
+
console.log('\n--- Verifying terminal.jsonl (last 3 entries) ---');
|
|
40
|
+
const jsonlLog = fs.readFileSync(path.join(testDir, 'terminal.jsonl'), 'utf8');
|
|
41
|
+
const lines = jsonlLog.trim().split('\n');
|
|
42
|
+
for (const line of lines.slice(-3)) {
|
|
43
|
+
const parsed = JSON.parse(line);
|
|
44
|
+
console.log(JSON.stringify({
|
|
45
|
+
level: parsed.level,
|
|
46
|
+
message: parsed.message.substring(0, 50) + '...',
|
|
47
|
+
hasMetadata: !!parsed.metadata,
|
|
48
|
+
metadataType: parsed.metadata?.type
|
|
49
|
+
}, null, 2));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
testThinkingLogs().catch(console.error);
|
|
54
|
+
|
package/src/utils/types.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface CursorFlowConfig {
|
|
|
18
18
|
lockfileReadOnly: boolean;
|
|
19
19
|
enableReview: boolean;
|
|
20
20
|
reviewModel: string;
|
|
21
|
+
reviewAllTasks?: boolean;
|
|
21
22
|
maxReviewIterations: number;
|
|
22
23
|
defaultLaneConfig: LaneConfig;
|
|
23
24
|
logLevel: string;
|
|
@@ -189,6 +190,10 @@ export interface Task {
|
|
|
189
190
|
model?: string;
|
|
190
191
|
/** Acceptance criteria for the AI reviewer to validate */
|
|
191
192
|
acceptanceCriteria?: string[];
|
|
193
|
+
/** Task-level dependencies (format: "lane:task") */
|
|
194
|
+
dependsOn?: string[];
|
|
195
|
+
/** Task execution timeout in milliseconds. Overrides lane-level timeout. */
|
|
196
|
+
timeout?: number;
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
export interface RunnerConfig {
|
|
@@ -200,9 +205,11 @@ export interface RunnerConfig {
|
|
|
200
205
|
baseBranch?: string;
|
|
201
206
|
model?: string;
|
|
202
207
|
dependencyPolicy: DependencyPolicy;
|
|
208
|
+
enableReview?: boolean;
|
|
203
209
|
/** Output format for cursor-agent (default: 'stream-json') */
|
|
204
210
|
agentOutputFormat?: 'stream-json' | 'json' | 'plain';
|
|
205
211
|
reviewModel?: string;
|
|
212
|
+
reviewAllTasks?: boolean;
|
|
206
213
|
maxReviewIterations?: number;
|
|
207
214
|
acceptanceCriteria?: string[];
|
|
208
215
|
/** Task execution timeout in milliseconds. Default: 600000 (10 minutes) */
|
|
@@ -263,6 +270,7 @@ export interface ReviewResult {
|
|
|
263
270
|
export interface TaskResult {
|
|
264
271
|
taskName: string;
|
|
265
272
|
taskBranch: string;
|
|
273
|
+
acceptanceCriteria?: string[];
|
|
266
274
|
[key: string]: any;
|
|
267
275
|
}
|
|
268
276
|
|
|
@@ -281,6 +289,10 @@ export interface LaneState {
|
|
|
281
289
|
tasksFile?: string; // Original tasks file path
|
|
282
290
|
dependsOn?: string[];
|
|
283
291
|
pid?: number;
|
|
292
|
+
/** List of completed task names in this lane */
|
|
293
|
+
completedTasks?: string[];
|
|
294
|
+
/** Task-level dependencies currently being waited for (format: "lane:task") */
|
|
295
|
+
waitingFor?: string[];
|
|
284
296
|
}
|
|
285
297
|
|
|
286
298
|
export interface ConversationEntry {
|
package/src/utils/webhook.ts
CHANGED
|
@@ -56,6 +56,9 @@ async function sendWebhook(config: WebhookConfig, event: CursorFlowEvent) {
|
|
|
56
56
|
const controller = new AbortController();
|
|
57
57
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
58
58
|
|
|
59
|
+
// SECURITY NOTE: Intentionally sending event data to configured webhook URLs.
|
|
60
|
+
// This is the expected behavior - users explicitly configure webhook endpoints
|
|
61
|
+
// to receive CursorFlow events. The data is JSON-serialized event metadata.
|
|
59
62
|
const response = await fetch(config.url, {
|
|
60
63
|
method: 'POST',
|
|
61
64
|
headers,
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
#
|
|
3
|
-
# Simple Real Logging Test
|
|
4
|
-
# This test runs cursor-agent directly and verifies log capture
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
set -e
|
|
8
|
-
|
|
9
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
|
-
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
11
|
-
|
|
12
|
-
echo "๐งช Simple Cursor-Agent Logging Test"
|
|
13
|
-
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
14
|
-
|
|
15
|
-
# Check cursor-agent
|
|
16
|
-
if ! command -v cursor-agent &> /dev/null; then
|
|
17
|
-
echo "โ cursor-agent not found"
|
|
18
|
-
exit 1
|
|
19
|
-
fi
|
|
20
|
-
|
|
21
|
-
cd "$PROJECT_ROOT"
|
|
22
|
-
|
|
23
|
-
# Build
|
|
24
|
-
echo "Building..."
|
|
25
|
-
npm run build > /dev/null 2>&1
|
|
26
|
-
|
|
27
|
-
# Setup test dir
|
|
28
|
-
TEST_DIR="$PROJECT_ROOT/_test-logs"
|
|
29
|
-
rm -rf "$TEST_DIR"
|
|
30
|
-
mkdir -p "$TEST_DIR"
|
|
31
|
-
|
|
32
|
-
# Create a very simple task
|
|
33
|
-
cat > "$TEST_DIR/task.json" << 'EOF'
|
|
34
|
-
{
|
|
35
|
-
"baseBranch": "main",
|
|
36
|
-
"branchPrefix": "test/log-",
|
|
37
|
-
"timeout": 30000,
|
|
38
|
-
"tasks": [
|
|
39
|
-
{
|
|
40
|
-
"name": "echo-test",
|
|
41
|
-
"prompt": "Say 'test complete' and nothing else.",
|
|
42
|
-
"model": "sonnet-4.5"
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
EOF
|
|
47
|
-
|
|
48
|
-
# Run with node directly
|
|
49
|
-
echo ""
|
|
50
|
-
echo "Running cursor-agent via runner..."
|
|
51
|
-
echo ""
|
|
52
|
-
|
|
53
|
-
LANE_DIR="$TEST_DIR/lane"
|
|
54
|
-
mkdir -p "$LANE_DIR"
|
|
55
|
-
|
|
56
|
-
# Run runner.js directly
|
|
57
|
-
timeout 60 node dist/core/runner.js "$TEST_DIR/task.json" \
|
|
58
|
-
--run-dir "$LANE_DIR" \
|
|
59
|
-
--executor cursor-agent \
|
|
60
|
-
--start-index 0 || true
|
|
61
|
-
|
|
62
|
-
echo ""
|
|
63
|
-
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
64
|
-
echo "๐ Log Files Created:"
|
|
65
|
-
echo ""
|
|
66
|
-
|
|
67
|
-
ls -la "$LANE_DIR"/*.log "$LANE_DIR"/*.jsonl 2>/dev/null || echo "No log files found"
|
|
68
|
-
|
|
69
|
-
echo ""
|
|
70
|
-
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
71
|
-
echo "๐ terminal.log content:"
|
|
72
|
-
echo ""
|
|
73
|
-
|
|
74
|
-
if [ -f "$LANE_DIR/terminal.log" ]; then
|
|
75
|
-
head -50 "$LANE_DIR/terminal.log"
|
|
76
|
-
else
|
|
77
|
-
echo "No terminal.log"
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
echo ""
|
|
81
|
-
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
82
|
-
echo "๐ terminal.jsonl (first 3 entries):"
|
|
83
|
-
echo ""
|
|
84
|
-
|
|
85
|
-
if [ -f "$LANE_DIR/terminal.jsonl" ]; then
|
|
86
|
-
head -3 "$LANE_DIR/terminal.jsonl"
|
|
87
|
-
else
|
|
88
|
-
echo "No terminal.jsonl"
|
|
89
|
-
fi
|
|
90
|
-
|
|
91
|
-
# Cleanup git branches
|
|
92
|
-
git branch -D test/log-* 2>/dev/null || true
|
|
93
|
-
git worktree remove _cursorflow/worktrees/test/log-* --force 2>/dev/null || true
|
|
94
|
-
|
|
95
|
-
echo ""
|
|
96
|
-
echo "โ
Test finished"
|
|
97
|
-
|