MAESTRO: fix(cursor): use bun runtime and fix hooks directory detection
Cherry-picked source changes from PR #721. Fixes two Cursor standalone setup bugs: 1. findCursorHooksDir() now checks for hooks.json (unified CLI mode) in addition to legacy common.sh/common.ps1 scripts 2. installCursorHooks() now uses bun instead of node for hook commands since worker-service.cjs depends on bun:sqlite 3. Added findBunPath() to detect bun executable across platforms Build artifacts skipped (pre-existing dompurify viewer dep issue). Source-only cherry-pick, TypeScript compilation clean for modified file. Co-Authored-By: polux0 <aleksaprosperitylabs@gmail.com> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -128,7 +128,7 @@ export async function updateCursorContextForProject(projectName: string, port: n
|
||||
/**
|
||||
* Find cursor-hooks directory
|
||||
* Searches in order: marketplace install, source repo
|
||||
* Checks for both bash (common.sh) and PowerShell (common.ps1) scripts
|
||||
* Checks for hooks.json (unified CLI mode) or legacy shell scripts
|
||||
*/
|
||||
export function findCursorHooksDir(): string | null {
|
||||
const possiblePaths = [
|
||||
@@ -141,8 +141,10 @@ export function findCursorHooksDir(): string | null {
|
||||
];
|
||||
|
||||
for (const p of possiblePaths) {
|
||||
// Check for either bash or PowerShell common script
|
||||
if (existsSync(path.join(p, 'common.sh')) || existsSync(path.join(p, 'common.ps1'))) {
|
||||
// Check for hooks.json (unified CLI mode) or legacy shell scripts
|
||||
if (existsSync(path.join(p, 'hooks.json')) ||
|
||||
existsSync(path.join(p, 'common.sh')) ||
|
||||
existsSync(path.join(p, 'common.ps1'))) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -193,6 +195,37 @@ export function findWorkerServicePath(): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Bun executable path
|
||||
* Required because worker-service.cjs uses bun:sqlite which is Bun-specific
|
||||
* Searches common installation locations across platforms
|
||||
*/
|
||||
export function findBunPath(): string {
|
||||
const possiblePaths = [
|
||||
// Standard user install location (most common)
|
||||
path.join(homedir(), '.bun', 'bin', 'bun'),
|
||||
// Global install locations
|
||||
'/usr/local/bin/bun',
|
||||
'/usr/bin/bun',
|
||||
// Windows locations
|
||||
...(process.platform === 'win32' ? [
|
||||
path.join(homedir(), '.bun', 'bin', 'bun.exe'),
|
||||
path.join(process.env.LOCALAPPDATA || '', 'bun', 'bun.exe'),
|
||||
] : []),
|
||||
];
|
||||
|
||||
for (const p of possiblePaths) {
|
||||
if (p && existsSync(p)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to 'bun' and hope it's in PATH
|
||||
// This allows the installation to proceed even if we can't find bun
|
||||
// The user will get a clear error when the hook runs if bun isn't available
|
||||
return 'bun';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the target directory for Cursor hooks based on install target
|
||||
*/
|
||||
@@ -312,15 +345,21 @@ export async function installCursorHooks(_sourceDir: string, target: CursorInsta
|
||||
// Generate hooks.json with unified CLI commands
|
||||
const hooksJsonPath = path.join(targetDir, 'hooks.json');
|
||||
|
||||
// Find bun executable - required because worker-service.cjs uses bun:sqlite
|
||||
const bunPath = findBunPath();
|
||||
const escapedBunPath = bunPath.replace(/\\/g, '\\\\');
|
||||
|
||||
// Use the absolute path to worker-service.cjs
|
||||
// Escape backslashes for JSON on Windows
|
||||
const escapedWorkerPath = workerServicePath.replace(/\\/g, '\\\\');
|
||||
|
||||
// Helper to create hook command using unified CLI
|
||||
// Helper to create hook command using unified CLI with bun runtime
|
||||
const makeHookCommand = (command: string) => {
|
||||
return `node "${escapedWorkerPath}" hook cursor ${command}`;
|
||||
return `"${escapedBunPath}" "${escapedWorkerPath}" hook cursor ${command}`;
|
||||
};
|
||||
|
||||
console.log(` Using Bun runtime: ${bunPath}`);
|
||||
|
||||
const hooksJson: CursorHooksJson = {
|
||||
version: 1,
|
||||
hooks: {
|
||||
@@ -356,7 +395,7 @@ export async function installCursorHooks(_sourceDir: string, target: CursorInsta
|
||||
Installation complete!
|
||||
|
||||
Hooks installed to: ${targetDir}/hooks.json
|
||||
Using unified CLI: node worker-service.cjs hook cursor <command>
|
||||
Using unified CLI: bun worker-service.cjs hook cursor <command>
|
||||
|
||||
Next steps:
|
||||
1. Start claude-mem worker: claude-mem start
|
||||
@@ -532,7 +571,7 @@ export function checkCursorHooksStatus(): number {
|
||||
const firstCommand = hooksContent?.hooks?.beforeSubmitPrompt?.[0]?.command || '';
|
||||
|
||||
if (firstCommand.includes('worker-service.cjs') && firstCommand.includes('hook cursor')) {
|
||||
console.log(` Mode: Unified CLI (node worker-service.cjs)`);
|
||||
console.log(` Mode: Unified CLI (bun worker-service.cjs)`);
|
||||
} else {
|
||||
// Detect legacy shell scripts
|
||||
const bashScripts = ['session-init.sh', 'context-inject.sh', 'save-observation.sh'];
|
||||
|
||||
Reference in New Issue
Block a user