@zibby/core 0.1.11 → 0.1.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/core",
3
- "version": "0.1.11",
3
+ "version": "0.1.15",
4
4
  "description": "Core test automation engine with multi-agent and multi-MCP support",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -23,10 +23,15 @@ export class CursorAgentStrategy extends AgentStrategy {
23
23
 
24
24
  canHandle(_context) {
25
25
  const paths = [
26
- 'agent',
27
- '/usr/local/bin/agent',
26
+ // Try absolute paths first (most reliable)
27
+ join(homedir(), '.local', 'bin', 'cursor-agent'),
28
+ join(homedir(), '.cursor', 'bin', 'cursor-agent'),
28
29
  '/usr/local/bin/cursor-agent',
29
- '/Applications/Cursor.app/Contents/Resources/app/bin/cursor'
30
+ '/usr/local/bin/agent',
31
+ '/Applications/Cursor.app/Contents/Resources/app/bin/cursor',
32
+ // Try PATH last (may have symlink issues)
33
+ 'agent',
34
+ 'cursor-agent'
30
35
  ];
31
36
 
32
37
  for (const path of paths) {
@@ -81,10 +86,15 @@ export class CursorAgentStrategy extends AgentStrategy {
81
86
  this._setupMcpConfig(sessionPath, workspace, config);
82
87
 
83
88
  const possibleBins = [
84
- 'agent',
85
- '/usr/local/bin/agent',
89
+ // Try absolute paths first (most reliable)
90
+ join(homedir(), '.local', 'bin', 'cursor-agent'),
91
+ join(homedir(), '.cursor', 'bin', 'cursor-agent'),
86
92
  '/usr/local/bin/cursor-agent',
87
- '/Applications/Cursor.app/Contents/Resources/app/bin/cursor'
93
+ '/usr/local/bin/agent',
94
+ '/Applications/Cursor.app/Contents/Resources/app/bin/cursor',
95
+ // Try PATH last (may have symlink issues)
96
+ 'agent',
97
+ 'cursor-agent'
88
98
  ];
89
99
 
90
100
  let cursorBin = null;
@@ -113,11 +123,14 @@ export class CursorAgentStrategy extends AgentStrategy {
113
123
 
114
124
  if (!cursorBin) {
115
125
  throw new Error(
116
- 'Cursor Agent CLI not found or not working.\n\n' +
117
- 'Install it with:\n' +
118
- ' npm install -g @cursor/agent\n\n' +
119
- 'Or set CURSOR_API_KEY and ensure "agent" is in your PATH.\n' +
120
- 'Test with: agent --version'
126
+ `Cursor Agent CLI not found or not working.\n\n` +
127
+ `Checked paths:\n` +
128
+ `${possibleBins.map(p => ` - ${p}`).join('\n')}\n\n` +
129
+ `Install cursor-agent:\n` +
130
+ ` curl https://cursor.com/install -fsS | bash\n\n` +
131
+ `Then add to PATH:\n` +
132
+ ` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc\n\n` +
133
+ `Test with: agent --version`
121
134
  );
122
135
  }
123
136
 
@@ -138,28 +151,19 @@ export class CursorAgentStrategy extends AgentStrategy {
138
151
  writeFileSync(promptFile, prompt, 'utf-8');
139
152
  logger.debug(`📝 [Agent] Prompt written to ${promptFile} (${prompt.length} chars)`);
140
153
 
141
- let args;
142
- if (cursorBin === 'agent') {
143
- args = [
144
- 'chat',
145
- '--print',
146
- '--force',
147
- '--approve-mcps',
148
- '--output-format', 'stream-json',
149
- '--stream-partial-output',
150
- '--model', model || 'auto',
151
- ];
152
- if (process.env.CURSOR_API_KEY) {
153
- args.push('--api-key', process.env.CURSOR_API_KEY);
154
- }
155
- args.push(`@${promptFile}`);
156
- } else {
157
- args = ['agent', '--print', '--force', '--trust', '--approve-mcps'];
158
- if (process.env.CURSOR_API_KEY) {
159
- args.push('--api-key', process.env.CURSOR_API_KEY);
160
- }
161
- args.push('--model', model || 'auto', `@${promptFile}`);
154
+ // All cursor-agent binaries use the same command structure (no subcommand needed)
155
+ const args = [
156
+ '--print',
157
+ '--force',
158
+ '--approve-mcps',
159
+ '--output-format', 'stream-json',
160
+ '--stream-partial-output',
161
+ '--model', model || 'auto',
162
+ ];
163
+ if (process.env.CURSOR_API_KEY) {
164
+ args.push('--api-key', process.env.CURSOR_API_KEY);
162
165
  }
166
+ args.push(`@${promptFile}`);
163
167
 
164
168
  const fullCmd = [cursorBin, ...args].join(' ');
165
169
  logger.debug(`[Agent] Executing: ${fullCmd.slice(0, 200)}`);
@@ -322,6 +326,7 @@ export class CursorAgentStrategy extends AgentStrategy {
322
326
  let lastOutputTime = Date.now();
323
327
  let lineCount = 0;
324
328
  let killed = false;
329
+ let processStarted = false;
325
330
 
326
331
  const proc = spawn(bin, args, {
327
332
  cwd,
@@ -331,6 +336,52 @@ export class CursorAgentStrategy extends AgentStrategy {
331
336
 
332
337
  logger.debug(`[Agent] PID: ${proc.pid}`);
333
338
 
339
+ const startupTimer = setTimeout(() => {
340
+ if (!processStarted && lineCount === 0) {
341
+ killed = true;
342
+ const binaryPath = bin.replace(/^"(.*)"$/, '$1');
343
+ const binaryExists = existsSync(binaryPath);
344
+
345
+ logger.error(`❌ [Agent] Process failed to start within 5 seconds.`);
346
+ logger.error(` Binary: ${bin}`);
347
+ logger.error(` File exists: ${binaryExists ? 'Yes (but not working - may be corrupted)' : 'No'}`);
348
+ logger.error(` PATH includes ~/.local/bin: ${process.env.PATH.includes('.local/bin') ? 'Yes' : 'No'}`);
349
+
350
+ if (binaryExists) {
351
+ logger.error(`\n ⚠️ Binary exists but won't start. Try reinstalling:`);
352
+ logger.error(` rm -f "${binaryPath}"`);
353
+ logger.error(` curl https://cursor.com/install -fsS | bash`);
354
+ logger.error(` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc`);
355
+ } else {
356
+ logger.error(`\n Install cursor-agent:`);
357
+ logger.error(` curl https://cursor.com/install -fsS | bash`);
358
+ logger.error(` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc`);
359
+ }
360
+
361
+ proc.kill('SIGTERM');
362
+ setTimeout(() => { if (!proc.killed) proc.kill('SIGKILL'); }, 2000);
363
+ reject(new Error(
364
+ `Cursor Agent failed to start. Binary '${binaryPath}' ${binaryExists ? 'exists but is not working (corrupted?)' : 'not found'}.\n\n` +
365
+ `${binaryExists
366
+ ? '⚠️ The binary file exists but failed to start. It may be corrupted or incomplete.\n\n' +
367
+ 'Try reinstalling cursor-agent:\n' +
368
+ ` rm -f "${binaryPath}"\n` +
369
+ ' curl https://cursor.com/install -fsS | bash\n\n' +
370
+ 'Ensure ~/.local/bin is in your PATH:\n' +
371
+ ' echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.zshrc\n' +
372
+ ' source ~/.zshrc\n\n' +
373
+ 'Test with: agent --version'
374
+ : 'Install cursor-agent:\n' +
375
+ ' curl https://cursor.com/install -fsS | bash\n\n' +
376
+ 'Add ~/.local/bin to your PATH:\n' +
377
+ ' echo \'export PATH="$HOME/.local/bin:$PATH"\' >> ~/.zshrc\n' +
378
+ ' source ~/.zshrc\n\n' +
379
+ 'Test with: agent --version'
380
+ }`
381
+ ));
382
+ }
383
+ }, 5000);
384
+
334
385
  if (stdinPrompt) {
335
386
  proc.stdin.write(stdinPrompt);
336
387
  proc.stdin.end();
@@ -434,6 +485,11 @@ export class CursorAgentStrategy extends AgentStrategy {
434
485
  stdout += chunk;
435
486
  lastOutputTime = Date.now();
436
487
 
488
+ if (!processStarted) {
489
+ processStarted = true;
490
+ clearTimeout(startupTimer);
491
+ }
492
+
437
493
  const displayText = streamParser.processChunk(chunk);
438
494
  if (displayText) {
439
495
  process.stdout.write(displayText);
@@ -448,6 +504,11 @@ export class CursorAgentStrategy extends AgentStrategy {
448
504
  stderr += chunk;
449
505
  lastOutputTime = Date.now();
450
506
 
507
+ if (!processStarted) {
508
+ processStarted = true;
509
+ clearTimeout(startupTimer);
510
+ }
511
+
451
512
  const lines = chunk.split('\n').filter(l => l.trim());
452
513
  for (const line of lines) {
453
514
  logger.warn(`⚠️ [Agent stderr] ${line}`);
@@ -456,6 +517,7 @@ export class CursorAgentStrategy extends AgentStrategy {
456
517
 
457
518
  proc.on('close', (code, signal) => {
458
519
  clearTimeout(timer);
520
+ clearTimeout(startupTimer);
459
521
  clearInterval(heartbeat);
460
522
  streamParser.flush();
461
523
  const elapsed = Math.round((Date.now() - startTime) / 1000);
@@ -489,8 +551,14 @@ export class CursorAgentStrategy extends AgentStrategy {
489
551
 
490
552
  proc.on('error', (err) => {
491
553
  clearTimeout(timer);
554
+ clearTimeout(startupTimer);
492
555
  clearInterval(heartbeat);
493
- reject(new Error(`Cursor Agent spawn error: ${err.message}`));
556
+ reject(new Error(
557
+ `Cursor Agent spawn error: ${err.message}\n` +
558
+ `Binary: ${bin}\n` +
559
+ `This usually means the binary is not in PATH. Try:\n` +
560
+ ` echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc`
561
+ ));
494
562
  });
495
563
  });
496
564
  }
@@ -47,13 +47,12 @@ export class BrowserTestAutomationAgent extends WorkflowAgent {
47
47
  BrowserTestResultHandler.saveTitle(result, cwd);
48
48
  await BrowserTestResultHandler.saveExecutionData(result);
49
49
 
50
- if (process.env.ZIBBY_MEMORY) {
51
- try {
52
- const { memoryEndRun, memorySyncPush } = await import('@zibby/memory');
53
- const sessionId = result.state.sessionPath?.split('/').pop();
54
- memoryEndRun(cwd, { sessionId, passed: result.success !== false });
55
- memorySyncPush(cwd);
56
- } catch { /* @zibby/memory not available */ }
57
- }
50
+ // Memory end-run hook (if @zibby/memory is installed)
51
+ try {
52
+ const { memoryEndRun, memorySyncPush } = await import('@zibby/memory');
53
+ const sessionId = result.state.sessionPath?.split('/').pop();
54
+ memoryEndRun(cwd, { sessionId, passed: result.success !== false });
55
+ memorySyncPush(cwd);
56
+ } catch { /* @zibby/memory not available */ }
58
57
  }
59
58
  }
@@ -14,7 +14,7 @@ import { formatAssertionChecklist } from './utils.mjs';
14
14
 
15
15
  export const executeLiveNode = {
16
16
  name: 'execute_live',
17
- skills: [SKILLS.BROWSER, ...(process.env.ZIBBY_MEMORY ? [SKILLS.MEMORY] : [])],
17
+ skills: [SKILLS.BROWSER, SKILLS.MEMORY],
18
18
  timeout: 600000,
19
19
 
20
20
  prompt: (state) => {