diff --git a/src/main/agent-hooks/installer-utils.test.ts b/src/main/agent-hooks/installer-utils.test.ts index 8e995fac07c..bb905f96ba8 100644 --- a/src/main/agent-hooks/installer-utils.test.ts +++ b/src/main/agent-hooks/installer-utils.test.ts @@ -12,7 +12,7 @@ import { tmpdir } from 'os' import { join } from 'path' import { createManagedCommandMatcher, - getManagedScriptPathForAgent, + getManagedScriptPath, writeHooksJson, type HooksConfig } from './installer-utils' @@ -148,15 +148,15 @@ describe('createManagedCommandMatcher', () => { }) }) -describe('createManagedCommandMatcher recognizes getManagedScriptPathForAgent paths', () => { +describe('createManagedCommandMatcher recognizes getManagedScriptPath paths', () => { it('matches a command built from the current path helper', () => { // Why: install-time removal of stale managed commands relies on the - // matcher recognizing any path produced by `getManagedScriptPathForAgent` + // matcher recognizing any path produced by `getManagedScriptPath` // (which routes through `AGENT_HOOKS_DIR_NAME`). If the directory name // ever changes, the matcher must stay in sync so a fresh install still // sweeps the newly-named entries cleanly. const userData = '/fake/userData' - const scriptPath = getManagedScriptPathForAgent(userData, 'claude-hook.sh') + const scriptPath = getManagedScriptPath(userData, 'claude-hook.sh') const matcher = createManagedCommandMatcher('claude-hook.sh') expect(matcher(`/bin/sh "${scriptPath}"`)).toBe(true) }) diff --git a/src/main/agent-hooks/installer-utils.ts b/src/main/agent-hooks/installer-utils.ts index 8720a4790ea..b1f7d453590 100644 --- a/src/main/agent-hooks/installer-utils.ts +++ b/src/main/agent-hooks/installer-utils.ts @@ -28,16 +28,11 @@ export function getAgentHooksDir(userDataPath: string): string { return join(userDataPath, AGENT_HOOKS_DIR_NAME) } -// Why: the endpoint file lives under userData so each Orca install (dev vs. -// packaged) has its own path and the two cannot clobber each other. Using a -// per-platform extension (`.env` on POSIX, `.cmd` on Windows) lets the hook -// scripts source the file with their platform-native syntax (`.` on POSIX, -// `call` on Windows); the OpenCode plugin's regex accepts both shapes so no -// platform detection is needed inside the plugin source either. -// Lives in installer-utils so both the hook server (which writes the file) -// and the managed-script generators (which source it from the script) share -// one source of truth for the filename convention. -export function getEndpointFileName(): string { +// Why: per-platform extension lets POSIX scripts source it with `.` and +// Windows scripts with `call`. The OpenCode plugin's regex accepts both +// `KEY=VALUE` and `set KEY=VALUE` lines so no platform branching is needed +// in the plugin. +function getEndpointFileName(): string { return process.platform === 'win32' ? 'endpoint.cmd' : 'endpoint.env' } @@ -51,7 +46,7 @@ export function getEndpointFilePath(userDataPath: string): string { // Why: single accessor for a managed-script path. Routes every agent's // hook-service through one helper so a rename of the dir or layout is a // one-line change here instead of four parallel edits. -export function getManagedScriptPathForAgent(userDataPath: string, scriptFileName: string): string { +export function getManagedScriptPath(userDataPath: string, scriptFileName: string): string { return join(getAgentHooksDir(userDataPath), scriptFileName) } diff --git a/src/main/agent-hooks/server.ts b/src/main/agent-hooks/server.ts index 5c95fa48dfc..2a69d5ec616 100644 --- a/src/main/agent-hooks/server.ts +++ b/src/main/agent-hooks/server.ts @@ -1054,9 +1054,8 @@ function normalizeHookPayload( } // Endpoint file path construction lives in installer-utils -// (getAgentHooksDir / getEndpointFilePath / getEndpointFileName) so the -// hook server (writer) and the managed-script generators (readers) share -// one source of truth for the directory + filename convention. +// (getAgentHooksDir / getEndpointFilePath) so the hook server and the +// install-time matcher share one source of truth for the directory name. // Why: every value in the endpoint file is sourced as shell. Reject any // value that contains shell/cmd metacharacters so a future field whose diff --git a/src/main/claude/hook-service.ts b/src/main/claude/hook-service.ts index 3b8d5d49099..7008f266aca 100644 --- a/src/main/claude/hook-service.ts +++ b/src/main/claude/hook-service.ts @@ -4,7 +4,7 @@ import { app } from 'electron' import type { AgentHookInstallState, AgentHookInstallStatus } from '../../shared/agent-hook-types' import { createManagedCommandMatcher, - getManagedScriptPathForAgent, + getManagedScriptPath as resolveManagedScriptPath, readHooksJson, removeManagedCommands, writeHooksJson, @@ -45,7 +45,7 @@ function getManagedScriptFileName(): string { } function getManagedScriptPath(): string { - return getManagedScriptPathForAgent(app.getPath('userData'), getManagedScriptFileName()) + return resolveManagedScriptPath(app.getPath('userData'), getManagedScriptFileName()) } function getManagedCommand(scriptPath: string): string { diff --git a/src/main/codex/hook-service.ts b/src/main/codex/hook-service.ts index 11cfe5b217b..3faf1d44f08 100644 --- a/src/main/codex/hook-service.ts +++ b/src/main/codex/hook-service.ts @@ -4,7 +4,7 @@ import { app } from 'electron' import type { AgentHookInstallState, AgentHookInstallStatus } from '../../shared/agent-hook-types' import { createManagedCommandMatcher, - getManagedScriptPathForAgent, + getManagedScriptPath as resolveManagedScriptPath, readHooksJson, removeManagedCommands, writeHooksJson, @@ -36,7 +36,7 @@ function getManagedScriptFileName(): string { } function getManagedScriptPath(): string { - return getManagedScriptPathForAgent(app.getPath('userData'), getManagedScriptFileName()) + return resolveManagedScriptPath(app.getPath('userData'), getManagedScriptFileName()) } function getManagedCommand(scriptPath: string): string { diff --git a/src/main/cursor/hook-service.ts b/src/main/cursor/hook-service.ts index fad3efda69e..a3e2546e7b4 100644 --- a/src/main/cursor/hook-service.ts +++ b/src/main/cursor/hook-service.ts @@ -4,7 +4,7 @@ import { app } from 'electron' import type { AgentHookInstallState, AgentHookInstallStatus } from '../../shared/agent-hook-types' import { createManagedCommandMatcher, - getManagedScriptPathForAgent, + getManagedScriptPath as resolveManagedScriptPath, readHooksJson, removeManagedCommands, writeHooksJson, @@ -48,7 +48,7 @@ function getManagedScriptFileName(): string { } function getManagedScriptPath(): string { - return getManagedScriptPathForAgent(app.getPath('userData'), getManagedScriptFileName()) + return resolveManagedScriptPath(app.getPath('userData'), getManagedScriptFileName()) } function getManagedCommand(scriptPath: string): string { diff --git a/src/main/gemini/hook-service.ts b/src/main/gemini/hook-service.ts index 9f852e213f9..fbce74fb060 100644 --- a/src/main/gemini/hook-service.ts +++ b/src/main/gemini/hook-service.ts @@ -4,7 +4,7 @@ import { app } from 'electron' import type { AgentHookInstallState, AgentHookInstallStatus } from '../../shared/agent-hook-types' import { createManagedCommandMatcher, - getManagedScriptPathForAgent, + getManagedScriptPath as resolveManagedScriptPath, readHooksJson, removeManagedCommands, writeHooksJson, @@ -34,7 +34,7 @@ function getManagedScriptFileName(): string { } function getManagedScriptPath(): string { - return getManagedScriptPathForAgent(app.getPath('userData'), getManagedScriptFileName()) + return resolveManagedScriptPath(app.getPath('userData'), getManagedScriptFileName()) } function getManagedCommand(scriptPath: string): string {