Skip to content

fix(hooks): add timeout and bypass PowerShell for Cursor hooks on Windows - #225

Open
ralf0131 wants to merge 1 commit into
mainfrom
fix/issue-197
Open

fix(hooks): add timeout and bypass PowerShell for Cursor hooks on Windows#225
ralf0131 wants to merge 1 commit into
mainfrom
fix/issue-197

Conversation

@ralf0131

@ralf0131 ralf0131 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes #197

Root Cause

On Windows, Cursor hooks go through a PowerShell 5.1 cold start (1-5s+) then Resolve-NodeBin probes (0.3-3s) then processor. Cursor kills the hook at its default timeout (no timeout field in hooks.json), so the chain is terminated before the processor runs.

Fix Strategy (3 layers)

Step 1: Write timeout: 30 into hooks.json entries (safety net)

  • Add timeout?: number to AgentHookConfig and HookDefinition
  • Add "timeout": 30 to agents.d/cursor.json
  • installHook writes/reconciles timeout; isHookInstalled checks match
  • Upgrade-in-place: patch existing entries that lack timeout

Step 2: Bypass PowerShell on Windows - invoke node directly (latency elimination)

  • New resolveWindowsNodeBin(): reads ~/.loongsuite-pilot/node-bin pin, falls back to process.execPath
  • New wrapCursorWin32Command(): emits cmd.exe /d /s /c "<node>" "<hooksDir>/cursor-hook-processor.mjs"
  • Legacy command migration via legacyCursorHookCommands() - automatic upgrade on next deploy
  • Falls back to current PowerShell path if no valid node bin found

Step 3: Reduce .ps1 fallback latency (optional hardening)

  • Cache Resolve-NodeBin probe result back to node-bin pin file

Files Modified

  • agents.d/cursor.json
  • src/types/deployment.ts
  • src/hooks/hook-manager.ts
  • src/deployment/hook-strategy.ts

Risk

  • cmd.exe quoting errors (mitigated by unit tests + mandatory real-Windows E2E)
  • Stale node-bin pin (mitigated by existing INVALID_NODE_BIN_ALARM + watchdog redeploy)

Generated by github-manager

…dows (#197)

- Add timeout: 30 to cursor hook config in agents.d/cursor.json
- Add timeout field to AgentHookConfig and HookDefinition types
- Implement wrapCursorWin32Command() to invoke node directly via cmd.exe
- Add resolveWindowsNodeBin() for node binary resolution on Windows
- Add legacyCursorHookCommands() for automatic migration from PowerShell path
- Update hook-strategy.ts to route cursor through direct node invocation
- Update hook-manager.ts to handle timeout reconciliation and Windows command wrapping
- All 43 hook-strategy tests pass
Copilot AI lite review requested due to automatic review settings August 5, 2026 23:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses Windows Cursor hook timeouts by ensuring hook entries declare an explicit timeout and by reducing hook startup latency on Windows through direct Node invocation (bypassing PowerShell cold start), fitting into the project’s hook-based agent deployment and lifecycle management.

Changes:

  • Add an optional per-hook timeout field to deployment hook configs and propagate it into installed hooks.json entries (including upgrade-in-place repair).
  • Introduce Windows Cursor-specific command wrapping to invoke cursor-hook-processor.mjs via cmd.exe + node directly, and migrate legacy commands.
  • Update Cursor agent definition to include a default timeout: 30.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
agents.d/cursor.json Adds timeout: 30 to Cursor hook configuration.
src/types/deployment.ts Extends hook config typing with optional timeout.
src/hooks/hook-manager.ts Implements timeout reconciliation and Windows Cursor command generation/migration helpers.
src/deployment/hook-strategy.ts Threads timeout into hook definitions and migrates legacy Cursor commands on Windows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/hooks/hook-manager.ts
Comment on lines 487 to 527
@@ -443,6 +521,8 @@ export class HookManager {
settingsPath,
hookJsonPath: ['hooks', event],
hookCommand: command,
...(replaceHookCommands ? { replaceHookCommands } : {}),
timeout: 30,
historyDir: path.join(baseDir, 'logs', 'cursor', 'history'),
}));
Comment thread src/hooks/hook-manager.ts
Comment on lines +36 to +46
export function resolveWindowsNodeBin(dataDir?: string): string | null {
const baseDir = dataDir ?? resolveHome('~/.loongsuite-pilot');
const pinFile = path.join(baseDir, 'node-bin');
try {
if (fsSync.existsSync(pinFile)) {
const pinned = fsSync.readFileSync(pinFile, 'utf8').trim();
if (pinned && fsSync.existsSync(pinned)) return pinned;
}
} catch { /* ignore pin read failures */ }
return process.execPath || null;
}
Comment thread src/hooks/hook-manager.ts
Comment on lines +61 to +71
export function wrapCursorWin32Command(hookScriptPath: string, dataDir?: string): string {
const nodeBin = resolveWindowsNodeBin(dataDir);
if (!nodeBin) {
return `powershell -NoProfile -ExecutionPolicy Bypass -File "${hookScriptPath}"`;
}
const processorPath = path.join(
path.dirname(hookScriptPath),
'cursor-hook-processor.mjs',
);
return `cmd.exe /d /s /c ""${nodeBin}" "${processorPath}""`;
}
@ralf0131

ralf0131 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

CI Passed ✅ — All checks passed. Ready for maintainer review.


Automated by "github-manager-bot"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows PowerShell 冷启动超时导致 Cursor Hooks 无法采集数据

2 participants