mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 00:02:05 +00:00
* fix(agent-hooks): skip unavailable agent homes * refactor(agent-hooks): separate Pi and OMP home fix * test(agent-hooks): update merged protocol harnesses * fix(agent-hooks): avoid redundant reconciliation * fix(agent-hooks): harden reconciliation and detection * test(agent-hooks): cover settings reconciliation * fix(agent-hooks): hydrate PATH for paired clients
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
import { join } from 'node:path'
|
|
import {
|
|
AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD,
|
|
type AgentHookInstallManagedHooksParams
|
|
} from '../shared/agent-hook-relay'
|
|
import type { RelayDispatcher, RequestContext } from './dispatcher'
|
|
import type { AgentHookTarget } from '../shared/agent-hook-types'
|
|
import { isManagedAgentHookTarget } from '../shared/managed-agent-hook-targets'
|
|
|
|
export type ManagedHookInstallSummary = {
|
|
installers: number
|
|
errors: number
|
|
}
|
|
|
|
export type ManagedHookRuntime = {
|
|
installManagedHooks: (options?: {
|
|
signal?: AbortSignal
|
|
hostKeyFingerprint?: string
|
|
agents?: readonly AgentHookTarget[]
|
|
}) => Promise<ManagedHookInstallSummary>
|
|
}
|
|
|
|
const SHA256_HOST_KEY_PATTERN = /^SHA256:[A-Za-z\d+/]{43}$/
|
|
|
|
function readHostKeyFingerprint(params: unknown): string | undefined {
|
|
const fingerprint = (params as Partial<AgentHookInstallManagedHooksParams> | null)
|
|
?.hostKeyFingerprint
|
|
return typeof fingerprint === 'string' && SHA256_HOST_KEY_PATTERN.test(fingerprint)
|
|
? fingerprint
|
|
: undefined
|
|
}
|
|
|
|
function readAgents(params: unknown): AgentHookTarget[] {
|
|
const raw = (params as Partial<AgentHookInstallManagedHooksParams> | null)?.agents
|
|
if (raw === undefined) {
|
|
return []
|
|
}
|
|
if (!Array.isArray(raw) || !raw.every(isManagedAgentHookTarget)) {
|
|
throw new Error('invalid_managed_hook_agents')
|
|
}
|
|
return [...new Set(raw)]
|
|
}
|
|
|
|
let managedHookRuntime: ManagedHookRuntime | null = null
|
|
|
|
function loadManagedHookRuntime(): ManagedHookRuntime {
|
|
if (!managedHookRuntime) {
|
|
// Why: keep the sizeable installer implementation out of relay startup and
|
|
// its narrow TS project while still executing it in-process on the remote.
|
|
managedHookRuntime = require(join(__dirname, 'managed-hook-runtime.js')) as ManagedHookRuntime
|
|
}
|
|
return managedHookRuntime
|
|
}
|
|
|
|
export function registerManagedHookInstaller(
|
|
dispatcher: Pick<RelayDispatcher, 'onRequest'>,
|
|
loadRuntime: () => ManagedHookRuntime = loadManagedHookRuntime
|
|
): void {
|
|
dispatcher.onRequest(
|
|
AGENT_HOOK_INSTALL_MANAGED_HOOKS_METHOD,
|
|
async (params, context: RequestContext): Promise<ManagedHookInstallSummary> => {
|
|
context.signal?.throwIfAborted()
|
|
const hostKeyFingerprint = readHostKeyFingerprint(params)
|
|
const agents = readAgents(params)
|
|
return await loadRuntime().installManagedHooks({
|
|
signal: context.signal,
|
|
...(hostKeyFingerprint ? { hostKeyFingerprint } : {}),
|
|
agents
|
|
})
|
|
}
|
|
)
|
|
}
|