mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
perf(agent-hooks): drop the extra PowerShell per hook event for Gemini, dsh, Kiro, Droid and Command Code (#27717)
* perf(hooks): register direct .cmd hooks for Gemini, DSH, Kiro, Droid and Command Code on Windows On a cmd-safe profile path these agents now register the managed .cmd path itself instead of a `powershell.exe -EncodedCommand` launcher, so each hook event no longer pays a second PowerShell start-up on top of the runner's own shell. Profiles the bare path cannot carry (spaces, non-ASCII, UNC) keep the encoded launcher. Same pattern as Claude (#18875) and Muse (#26755). Refs #20913 * refactor(hooks): one Windows batch-hook helper and one payload-delivery table - Add wrapWindowsBatchHookCommand (bare .cmd path, encoded launcher otherwise) and use it for Muse, Gemini, DSH, Kiro, Droid and Command Code. - Fold the five agents into windows-hook-payload-delivery.test.ts as rows run under each vendor's shell, from a plain and a spaced profile, with a stale encoded registration seeded per row; drop the separate runner suite and its CI list entries. - Replace the Windows-only per-agent registration tests with ones that stub process.platform, so they run on every CI OS. - Fix stale launcher, helper and DSH comments. Refs #20913 --------- Co-authored-by: Orca Worker <orca-worker@localhost>
This commit is contained in:
@@ -20,8 +20,7 @@ vi.mock('os', async () => {
|
||||
|
||||
import { CommandCodeHookService } from './hook-service'
|
||||
|
||||
const WINDOWS_POWERSHELL_LAUNCHER =
|
||||
/^[A-Za-z]:\/[^"]*\/System32\/WindowsPowerShell\/v1\.0\/powershell\.exe -NoProfile -EncodedCommand \S+$/
|
||||
import { wrapWindowsBatchHookCommand } from '../agent-hooks/windows-direct-cmd-hook-command'
|
||||
|
||||
describe('CommandCodeHookService', () => {
|
||||
let homeDir: string
|
||||
@@ -52,7 +51,11 @@ describe('CommandCodeHookService', () => {
|
||||
expect(config.hooks.PostToolUse[0].matcher).toBe('.*')
|
||||
expect(config.hooks.Stop[0].matcher).toBeUndefined()
|
||||
expect(config.hooks.PreToolUse[0].hooks[0].command).toMatch(
|
||||
process.platform === 'win32' ? WINDOWS_POWERSHELL_LAUNCHER : /command-code-hook/
|
||||
process.platform === 'win32'
|
||||
? wrapWindowsBatchHookCommand(
|
||||
join(homeDir, '.orca', 'agent-hooks', 'command-code-hook.cmd')
|
||||
)
|
||||
: /command-code-hook/
|
||||
)
|
||||
if (process.platform !== 'win32') {
|
||||
expect(config.hooks.PreToolUse[0].hooks[0].command).toContain(join(homeDir, '.orca'))
|
||||
@@ -62,30 +65,24 @@ describe('CommandCodeHookService', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// Why: #6078 — a Windows user profile path with a space used to be written
|
||||
// verbatim as the hook command, so the agent split it at the space. The
|
||||
// managed command must use an encoded launcher so the path never appears raw
|
||||
// on the cmd.exe command line.
|
||||
it.skipIf(process.platform !== 'win32')(
|
||||
'wraps the managed hook command to survive spaces in the profile path (#6078)',
|
||||
() => {
|
||||
const spaceHome = join(tmpdir(), 'orca command-code home with spaces')
|
||||
mkdirSync(spaceHome, { recursive: true })
|
||||
homedirMock.mockReturnValue(spaceHome)
|
||||
try {
|
||||
expect(new CommandCodeHookService().install().state).toBe('installed')
|
||||
|
||||
const config = JSON.parse(
|
||||
readFileSync(join(spaceHome, '.commandcode', 'settings.json'), 'utf8')
|
||||
) as { hooks: Record<string, { hooks: { command: string }[] }[]> }
|
||||
|
||||
const command = config.hooks.PreToolUse[0].hooks[0].command
|
||||
expect(command).toMatch(WINDOWS_POWERSHELL_LAUNCHER)
|
||||
} finally {
|
||||
rmSync(spaceHome, { recursive: true, force: true })
|
||||
// Why: runs on every OS; windows-hook-payload-delivery.test.ts runs each form under Command Code's shell.
|
||||
it('registers the Windows batch hook command for every event', () => {
|
||||
const platform = vi.spyOn(process, 'platform', 'get').mockReturnValue('win32')
|
||||
try {
|
||||
expect(new CommandCodeHookService().install().state).toBe('installed')
|
||||
const command = wrapWindowsBatchHookCommand(
|
||||
join(homeDir, '.orca', 'agent-hooks', 'command-code-hook.cmd')
|
||||
)
|
||||
const config = JSON.parse(
|
||||
readFileSync(join(homeDir, '.commandcode', 'settings.json'), 'utf8')
|
||||
)
|
||||
for (const eventName of ['PreToolUse', 'PostToolUse', 'Stop']) {
|
||||
expect(config.hooks[eventName][0].hooks[0].command).toBe(command)
|
||||
}
|
||||
} finally {
|
||||
platform.mockRestore()
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it('installs a hook script that can recover the endpoint when Command Code strips token env', () => {
|
||||
new CommandCodeHookService().install()
|
||||
|
||||
@@ -9,11 +9,11 @@ import {
|
||||
readHooksJson,
|
||||
removeManagedCommands,
|
||||
wrapPosixHookCommand,
|
||||
wrapWindowsHookCommand,
|
||||
writeHooksJson,
|
||||
writeManagedScript,
|
||||
type HookDefinition
|
||||
} from '../agent-hooks/installer-utils'
|
||||
import { wrapWindowsBatchHookCommand } from '../agent-hooks/windows-direct-cmd-hook-command'
|
||||
import { refreshManagedScriptIfPresent } from '../agent-hooks/managed-hook-script-refresh'
|
||||
import {
|
||||
readHooksJsonRemote,
|
||||
@@ -48,7 +48,7 @@ function getManagedScriptPath(): string {
|
||||
|
||||
function getManagedCommand(scriptPath: string): string {
|
||||
return process.platform === 'win32'
|
||||
? wrapWindowsHookCommand(scriptPath)
|
||||
? wrapWindowsBatchHookCommand(scriptPath)
|
||||
: wrapPosixHookCommand(scriptPath)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user