Refactor monolithic heartbeat service, AgentConfigForm, and CLI heartbeat-run into a proper adapter registry pattern. Each adapter type (process, claude-local, codex-local, http) gets its own module with server-side execution logic, CLI invocation, and UI config form. Significantly reduces file sizes and enables adding new adapters without touching core code. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
78 lines
1.8 KiB
TypeScript
78 lines
1.8 KiB
TypeScript
import type { AdapterExecutionContext, AdapterExecutionResult } from "../types.js";
|
|
import {
|
|
asString,
|
|
asNumber,
|
|
asStringArray,
|
|
parseObject,
|
|
buildPaperclipEnv,
|
|
redactEnvForLogs,
|
|
runChildProcess,
|
|
} from "../utils.js";
|
|
|
|
export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExecutionResult> {
|
|
const { runId, agent, config, onLog, onMeta } = ctx;
|
|
const command = asString(config.command, "");
|
|
if (!command) throw new Error("Process adapter missing command");
|
|
|
|
const args = asStringArray(config.args);
|
|
const cwd = asString(config.cwd, process.cwd());
|
|
const envConfig = parseObject(config.env);
|
|
const env: Record<string, string> = { ...buildPaperclipEnv(agent) };
|
|
for (const [k, v] of Object.entries(envConfig)) {
|
|
if (typeof v === "string") env[k] = v;
|
|
}
|
|
|
|
const timeoutSec = asNumber(config.timeoutSec, 900);
|
|
const graceSec = asNumber(config.graceSec, 15);
|
|
|
|
if (onMeta) {
|
|
await onMeta({
|
|
adapterType: "process",
|
|
command,
|
|
cwd,
|
|
commandArgs: args,
|
|
env: redactEnvForLogs(env),
|
|
});
|
|
}
|
|
|
|
const proc = await runChildProcess(runId, command, args, {
|
|
cwd,
|
|
env,
|
|
timeoutSec,
|
|
graceSec,
|
|
onLog,
|
|
});
|
|
|
|
if (proc.timedOut) {
|
|
return {
|
|
exitCode: proc.exitCode,
|
|
signal: proc.signal,
|
|
timedOut: true,
|
|
errorMessage: `Timed out after ${timeoutSec}s`,
|
|
};
|
|
}
|
|
|
|
if ((proc.exitCode ?? 0) !== 0) {
|
|
return {
|
|
exitCode: proc.exitCode,
|
|
signal: proc.signal,
|
|
timedOut: false,
|
|
errorMessage: `Process exited with code ${proc.exitCode ?? -1}`,
|
|
resultJson: {
|
|
stdout: proc.stdout,
|
|
stderr: proc.stderr,
|
|
},
|
|
};
|
|
}
|
|
|
|
return {
|
|
exitCode: proc.exitCode,
|
|
signal: proc.signal,
|
|
timedOut: false,
|
|
resultJson: {
|
|
stdout: proc.stdout,
|
|
stderr: proc.stderr,
|
|
},
|
|
};
|
|
}
|