ai-lens 0.8.47 → 0.8.49
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/.commithash +1 -1
- package/cli/status.js +39 -3
- package/client/sender.js +7 -1
- package/package.json +1 -1
package/.commithash
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
b5da117
|
package/cli/status.js
CHANGED
|
@@ -281,16 +281,51 @@ function checkCaptureRun(installedTools) {
|
|
|
281
281
|
}
|
|
282
282
|
} catch { /* best effort */ }
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
// GUI PATH test: on macOS, GUI apps (Cursor) get a minimal PATH from launchd,
|
|
285
|
+
// which often lacks paths added by .zshrc/.bashrc (e.g. nvm, miniforge, homebrew).
|
|
286
|
+
// Test the hook command with a stripped-down PATH to surface "env: node: No such file or directory".
|
|
287
|
+
let guiOk = true;
|
|
288
|
+
let guiDetail = '';
|
|
289
|
+
if (process.platform === 'darwin' && isCursor && shellOk) {
|
|
290
|
+
try {
|
|
291
|
+
const guiPath = '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin';
|
|
292
|
+
const guiEnv = { HOME: homedir(), PATH: guiPath, AI_LENS_PROJECTS: join(homedir(), '.ai-lens-status-check-nonexistent'), AI_LENS_STATUS_CHECK: '1' };
|
|
293
|
+
// Preserve AI_LENS_* config vars so capture.js can load config
|
|
294
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
295
|
+
if (k.startsWith('AI_LENS_') && !(k in guiEnv)) guiEnv[k] = v;
|
|
296
|
+
}
|
|
297
|
+
const guiResult = spawnSync('/bin/sh', ['-c', shellCommand], {
|
|
298
|
+
input: shellEvent,
|
|
299
|
+
encoding: 'utf-8',
|
|
300
|
+
timeout: 10_000,
|
|
301
|
+
env: guiEnv,
|
|
302
|
+
windowsHide: true,
|
|
303
|
+
});
|
|
304
|
+
if (guiResult.error) throw guiResult.error;
|
|
305
|
+
guiOk = guiResult.status === 0;
|
|
306
|
+
const stderr = (guiResult.stderr || '').trim();
|
|
307
|
+
guiDetail = guiOk ? 'exit 0' : `Exit code: ${guiResult.status}\nError: ${stderr || '(no stderr)'}`;
|
|
308
|
+
if (!guiOk && stderr.includes('No such file or directory')) {
|
|
309
|
+
guiDetail += '\nHint: node is not in the system PATH. GUI apps (Cursor) cannot find it.\n'
|
|
310
|
+
+ 'Fix: sudo ln -s $(which node) /usr/local/bin/node';
|
|
311
|
+
}
|
|
312
|
+
} catch (err) {
|
|
313
|
+
guiOk = false;
|
|
314
|
+
guiDetail = `Exit code: N/A\nError: ${err.message}`;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
toolResults.push({ name, ok: exitOk, cmd: testCmd, exitDetail, captureNote, shellOk, shellCmd: command, shellDetail, shellCaptureNote, guiOk, guiDetail });
|
|
285
319
|
}
|
|
286
320
|
|
|
287
|
-
const allOk = toolResults.every(r => r.ok && r.shellOk);
|
|
288
|
-
const failedTools = toolResults.filter(r => !r.ok || !r.shellOk).map(r => r.name);
|
|
321
|
+
const allOk = toolResults.every(r => r.ok && r.shellOk && r.guiOk);
|
|
322
|
+
const failedTools = toolResults.filter(r => !r.ok || !r.shellOk || !r.guiOk).map(r => r.name);
|
|
289
323
|
const summaryParts = toolResults.map(r => {
|
|
290
324
|
const directStatus = r.ok ? 'OK' : 'FAILED';
|
|
291
325
|
const shellStatus = r.shellOk ? 'OK' : 'FAILED';
|
|
292
326
|
const parts = [`${r.name}: ${directStatus}`];
|
|
293
327
|
if (!r.shellOk) parts[0] += `, shell: ${shellStatus}`;
|
|
328
|
+
if (!r.guiOk) parts[0] += ', GUI PATH: FAILED';
|
|
294
329
|
if (r.captureNote) parts[0] += ` (${r.captureNote})`;
|
|
295
330
|
return parts[0];
|
|
296
331
|
});
|
|
@@ -302,6 +337,7 @@ function checkCaptureRun(installedTools) {
|
|
|
302
337
|
if (r.captureNote) text += `\n Capture log: ${r.captureNote}`;
|
|
303
338
|
text += `\n Shell: ${r.shellCmd} < (test event)\n Shell result: ${r.shellDetail}`;
|
|
304
339
|
if (r.shellCaptureNote) text += `\n Shell capture log: ${r.shellCaptureNote}`;
|
|
340
|
+
if (r.guiDetail) text += `\n GUI PATH test: ${r.guiDetail}`;
|
|
305
341
|
return text;
|
|
306
342
|
}).join('\n\n');
|
|
307
343
|
|
package/client/sender.js
CHANGED
|
@@ -670,7 +670,13 @@ async function main() {
|
|
|
670
670
|
events.filter(e => !sentEventIds.has(e.event_id)).map(e => e.event_id).filter(Boolean)
|
|
671
671
|
);
|
|
672
672
|
partialRollback(sendingDir, acquiredPendingDir, unsentIds, eventFileMap);
|
|
673
|
-
|
|
673
|
+
// Node.js fetch wraps the real error in err.cause (e.g. DNS, TLS, ECONNREFUSED).
|
|
674
|
+
// Log both so sender.log shows the actual root cause, not just "fetch failed".
|
|
675
|
+
const cause = err.cause;
|
|
676
|
+
const errorDetail = cause
|
|
677
|
+
? { message: cause.message, code: cause.code, ...(cause.cause ? { inner: cause.cause.message, innerCode: cause.cause.code } : {}) }
|
|
678
|
+
: undefined;
|
|
679
|
+
log({ msg: 'failed', error: err.message, ...(errorDetail ? { cause: errorDetail } : {}), sent: sentEventIds.size, unsent: unsentIds.size, server: serverUrl });
|
|
674
680
|
if (err.message.includes('401')) {
|
|
675
681
|
log({ msg: 'auth-failed', error: 'Token invalid or revoked. Run: npx -y ai-lens init' });
|
|
676
682
|
}
|