Files
orca/src/main/cursor/hook-script.ts
T
Brennan Benson f352e3e27d fix(cursor): emit Cursor-contract JSON from managed hooks
Merge rebased conflict repair after exact-head tests, typecheck, lint, format, and all required GitHub checks passed.
2026-08-27 00:25:31 -07:00

88 lines
3.5 KiB
TypeScript

import {
buildWindowsAgentHookPostCommand,
wrapPosixHookCommand,
wrapWindowsHookCommand
} from '../agent-hooks/installer-utils'
import {
buildPosixHookPayloadCapture,
buildPosixHookSpoolLines,
buildWindowsHookEnvironmentGuardLines,
buildWindowsHookStdinDrainEpilogue
} from '../agent-hooks/hook-stdin-contract'
import { getCursorHookResponse, type CursorEvent } from './hook-events'
const CURSOR_HOOK_RESPONSE_ENV = 'ORCA_CURSOR_HOOK_RESPONSE'
export function getPosixManagedCommand(scriptPath: string, eventName: CursorEvent): string {
const response = getCursorHookResponse(eventName)
return wrapPosixHookCommand(
scriptPath,
{ [CURSOR_HOOK_RESPONSE_ENV]: response },
{ fallbackStdout: response }
)
}
export function getManagedCommand(scriptPath: string, eventName: CursorEvent): string {
const response = getCursorHookResponse(eventName)
return process.platform === 'win32'
? wrapWindowsHookCommand(
scriptPath,
{ [CURSOR_HOOK_RESPONSE_ENV]: response },
{ fallbackStdout: response }
)
: getPosixManagedCommand(scriptPath, eventName)
}
export function getManagedScript(target: 'local' | 'posix' = 'local'): string {
if (target === 'local' && process.platform === 'win32') {
return [
'@echo off',
'setlocal',
// Why: Cursor permission hooks fail closed on empty/invalid stdout (#15462).
`if defined ${CURSOR_HOOK_RESPONSE_ENV} (echo %${CURSOR_HOOK_RESPONSE_ENV}%) else (echo {})`,
// Why: source current endpoint coordinates for PTYs surviving an Orca restart.
'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul',
...buildWindowsHookEnvironmentGuardLines(),
buildWindowsAgentHookPostCommand('cursor'),
'exit /b 0',
...buildWindowsHookStdinDrainEpilogue(),
''
].join('\r\n')
}
return [
'#!/bin/sh',
// Why: Cursor permission hooks fail closed on empty/invalid stdout (#15462).
`if [ -n "$${CURSOR_HOOK_RESPONSE_ENV}" ]; then`,
` printf '%s\\n' "$${CURSOR_HOOK_RESPONSE_ENV}"`,
'else',
' printf "{}\\n"',
'fi',
...buildPosixHookPayloadCapture(),
...buildPosixHookSpoolLines('cursor'),
// Why: refresh endpoint coordinates so surviving PTYs keep reporting.
'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then',
' . "$ORCA_AGENT_HOOK_ENDPOINT" 2>/dev/null || :',
'fi',
'if [ -z "$ORCA_AGENT_HOOK_PORT" ] || [ -z "$ORCA_AGENT_HOOK_TOKEN" ] || [ -z "$ORCA_PANE_KEY" ]; then',
' spool_hook_event',
' exit 0',
'fi',
// Why: post form fields because path-bearing worktree IDs are unsafe in hand-built JSON.
// Why: pipe payload to curl stdin to keep large output off the command line.
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/cursor" \\',
' --connect-timeout 0.5 --max-time 1.5 \\',
' -H "Content-Type: application/x-www-form-urlencoded" \\',
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
' --data-urlencode "paneKey=${ORCA_PANE_KEY}" \\',
' --data-urlencode "tabId=${ORCA_TAB_ID}" \\',
' --data-urlencode "launchToken=${ORCA_AGENT_LAUNCH_TOKEN}" \\',
' --data-urlencode "worktreeId=${ORCA_WORKTREE_ID}" \\',
' --data-urlencode "env=${ORCA_AGENT_HOOK_ENV}" \\',
' --data-urlencode "version=${ORCA_AGENT_HOOK_VERSION}" \\',
' --data-urlencode "payload@-" >/dev/null 2>&1 || spool_hook_event',
'exit 0',
''
].join('\n')
}