mirror of
https://github.com/stablyai/orca.git
synced 2026-10-26 08:02:44 +00:00
The four agent hook services, the main hooks module, and the two relay modules each carried a file-level `eslint-disable max-lines` and ran 365-628 counted lines against a 300-line budget. AGENTS.md calls for splitting rather than suppressing, and config/max-lines-baseline.txt is a shrink-only ratchet, so this removes all seven suppressions and prunes their entries (341 -> 334). Pure move, no behavior change. Each hook service splits into its managed script source, its config/bundle serialization, and its remote-install path, keeping the per-agent integrations independent: copilot, amp, antigravity and hermes each retain their own getManagedScript rather than sharing one, because each emits a different script body for a different agent. Merging them by name would have been a behavior change, not a refactor. For antigravity the suppression's stated rationale -- that local install, Windows wrapper generation, status cleanup, and SSH remote install must share one event list and managed-command matcher so stale-hook cleanup cannot drift by platform -- is now enforced structurally instead: both install paths call buildInstalledConfig + createAntigravityManagedCommandMatcher over the single ANTIGRAVITY_EVENTS catalog, with the graph a strict DAG. Also registers the six new antigravity/ and copilot/ modules in config/tsconfig.cli.json. That project uses a curated `include` list rather than a glob, so an unlisted module fails `tsc -p config/tsconfig.tc.cli.json` with TS6307 even though the entire unit suite passes. Verified: oxlint clean, ratchet passes, typecheck clean, full unit suite green (remaining failures are pre-existing load flakes in untouched files, green when re-run serially), no new runtime import cycles, and no lint suppression added.
74 lines
2.4 KiB
TypeScript
74 lines
2.4 KiB
TypeScript
import {
|
|
wrapPosixHookCommand,
|
|
wrapWindowsHookCommand,
|
|
type HookDefinition
|
|
} from '../agent-hooks/installer-utils'
|
|
|
|
// Why: Copilot's user-level hook files can use VS Code-compatible PascalCase
|
|
// names, which match the event vocabulary already normalized by Orca's hook
|
|
// server and avoid wrapper-side event remapping.
|
|
export const COPILOT_EVENTS = [
|
|
'SessionStart',
|
|
'SessionEnd',
|
|
'UserPromptSubmit',
|
|
'PreToolUse',
|
|
'PostToolUse',
|
|
'PostToolUseFailure',
|
|
// Why: GitHub's current reference documents subagentStart with only the
|
|
// camelCase payload shape. The wrapper passes the event name separately, so
|
|
// Orca can normalize it without depending on a PascalCase payload.
|
|
'subagentStart',
|
|
'SubagentStop',
|
|
'PreCompact',
|
|
'Stop',
|
|
'ErrorOccurred',
|
|
'PermissionRequest',
|
|
'Notification'
|
|
] as const
|
|
|
|
export function getManagedCommand(scriptPath: string, eventName: string): string {
|
|
if (process.platform !== 'win32') {
|
|
return wrapPosixHookCommand(scriptPath, { ORCA_COPILOT_HOOK_EVENT: eventName })
|
|
}
|
|
return wrapWindowsHookCommand(scriptPath, { ORCA_COPILOT_HOOK_EVENT: eventName })
|
|
}
|
|
|
|
export function getManagedHookDefinition(command: string): HookDefinition {
|
|
return process.platform === 'win32'
|
|
? { type: 'command', powershell: command, timeoutSec: 5 }
|
|
: { type: 'command', bash: command, timeoutSec: 5 }
|
|
}
|
|
|
|
export function definitionHasCurrentCommand(definition: HookDefinition, command: string): boolean {
|
|
return (
|
|
definition.command === command ||
|
|
definition.bash === command ||
|
|
definition.powershell === command ||
|
|
(Array.isArray(definition.hooks) && definition.hooks.some((hook) => hook.command === command))
|
|
)
|
|
}
|
|
|
|
export function definitionHasStaleManagedCommand(
|
|
definition: HookDefinition,
|
|
currentCommand: string | null,
|
|
isManagedCommand: (command: string | undefined) => boolean
|
|
): boolean {
|
|
const commands = [definition.command, definition.bash, definition.powershell]
|
|
if (commands.some((command) => isManagedCommand(command) && command !== currentCommand)) {
|
|
return true
|
|
}
|
|
return (
|
|
Array.isArray(definition.hooks) &&
|
|
definition.hooks.some(
|
|
(hook) => isManagedCommand(hook.command) && hook.command !== currentCommand
|
|
)
|
|
)
|
|
}
|
|
|
|
export function definitionsChanged(before: HookDefinition[], after: HookDefinition[]): boolean {
|
|
return (
|
|
before.length !== after.length ||
|
|
after.some((definition, index) => definition !== before[index])
|
|
)
|
|
}
|