Files
orca/src/main/cursor/hook-script.ts
T
5ce9d58b2d fix(agent-hooks): force C numeric locale on POSIX curl timeouts (#19600)
* fix(agent-hooks): force C numeric locale on POSIX curl timeouts

curl parses --connect-timeout/--max-time with locale-sensitive strtod, so comma-decimal locales reject 0.5 and every hook silently falls into the restart spool.

Fixes #19578

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(agent-hooks): neutralize LC_ALL before setting LC_NUMERIC=C on POSIX curl

Signed-off-by: siddiqui irshad <mohdirshad1306@gmail.com>

* style(agent-hooks): format scoped curl commands

* test(hooks): expect scoped curl locale in Muse install script

---------

Signed-off-by: siddiqui irshad <mohdirshad1306@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Neil <neil@stably.ai>
2026-10-24 02:17:08 -07:00

102 lines
4.2 KiB
TypeScript

import {
buildWindowsAgentHookPostCommand,
wrapPosixHookCommand,
buildWindowsHookPowerShellCommand,
wrapWindowsPowerShellEncodedCommand
} from '../agent-hooks/installer-utils'
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
import {
buildPosixHookPayloadCapture,
buildPosixHookSpoolLines,
buildWindowsHookEnvironmentGuardLines,
buildWindowsHookStdinDrainEpilogue
} from '../agent-hooks/hook-stdin-contract'
import {
buildPosixGrokReplayGuardLines,
buildWindowsGrokReplayGuardLines
} from '../agent-hooks/grok-replay-guard'
import { quoteStartupArg } from '../../shared/tui-agent-startup-shell'
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 {
if (process.platform !== 'win32') {
// Cursor uses the login shell; wrap the POSIX guard in sh with portable quoting.
return `/bin/sh -c ${quoteStartupArg(getPosixManagedCommand(scriptPath, eventName), 'posix')}`
}
const response = getCursorHookResponse(eventName)
const command = buildWindowsHookPowerShellCommand(
scriptPath,
{ [CURSOR_HOOK_RESPONSE_ENV]: response },
{ fallbackStdout: response }
)
// PowerShell 5.1 defaults to the ANSI code page when translating hook stdin.
return wrapWindowsPowerShellEncodedCommand(
`[Console]::InputEncoding = New-Object System.Text.UTF8Encoding; $OutputEncoding = [Console]::InputEncoding; ${command}`
)
}
export function getManagedScript(target: 'local' | 'posix' = 'local'): string {
if (target === 'local' && process.platform === 'win32') {
return [
'@echo off',
'setlocal',
// Cursor permission hooks reject empty or invalid stdout (#15462).
`if defined ${CURSOR_HOOK_RESPONSE_ENV} (echo %${CURSOR_HOOK_RESPONSE_ENV}%) else (echo {})`,
// Refresh endpoints for PTYs that survived an Orca restart.
'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul',
...buildWindowsHookEnvironmentGuardLines(),
...buildWindowsGrokReplayGuardLines(),
buildWindowsAgentHookPostCommand('cursor'),
'exit /b 0',
...buildWindowsHookStdinDrainEpilogue(),
''
].join('\r\n')
}
return [
'#!/bin/sh',
// Cursor permission hooks reject empty or invalid stdout (#15462).
`if [ -n "$${CURSOR_HOOK_RESPONSE_ENV}" ]; then`,
` printf '%s\\n' "$${CURSOR_HOOK_RESPONSE_ENV}"`,
'else',
' printf "{}\\n"',
'fi',
...buildPosixHookPayloadCapture(),
...buildPosixGrokReplayGuardLines(),
...buildPosixHookSpoolLines('cursor'),
// Refresh endpoints for PTYs that survived an Orca restart.
'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',
// Form encoding handles path-bearing IDs; stdin keeps large payloads off the command line.
`printf '%s' "$payload" | ${posixCurlCommand()} -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')
}