feat(worker): in-box process-group marker + kill helpers for agent turns
This commit is contained in:
@@ -391,6 +391,42 @@ export const ensureUserContainer = async (args: {
|
||||
return name;
|
||||
};
|
||||
|
||||
const shellQuote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`;
|
||||
|
||||
// Wraps a CLI argv so the process runs as a new session/process-group leader whose
|
||||
// bash parent carries the marker in its argv (matchable by `pgrep -f`). We do NOT
|
||||
// `exec` (bash must survive so the marker stays visible); stdout/stderr fds are
|
||||
// inherited by the CLI so streaming still works.
|
||||
export const buildMarkedCommand = (
|
||||
marker: string,
|
||||
command: string[],
|
||||
): string[] => {
|
||||
const script = `# ${marker}\nexec 0</dev/null\n${command.map(shellQuote).join(' ')}`;
|
||||
return ['setsid', 'bash', '-lc', script];
|
||||
};
|
||||
|
||||
// Kills every process group whose bash parent matches the marker, TERM then KILL.
|
||||
// The negative pid (`-"$pid"`) targets the whole process group, so the CLI and any
|
||||
// children it spawned die together.
|
||||
export const buildKillScript = (marker: string): string =>
|
||||
[
|
||||
`pids=$(pgrep -f ${shellQuote(marker)} || true)`,
|
||||
`for pid in $pids; do kill -TERM -"$pid" 2>/dev/null || true; done`,
|
||||
`sleep 2`,
|
||||
`for pid in $pids; do kill -KILL -"$pid" 2>/dev/null || true; done`,
|
||||
].join('\n');
|
||||
|
||||
export const killBoxProcessesByMarker = async (args: {
|
||||
containerName: string;
|
||||
marker: string;
|
||||
}): Promise<void> => {
|
||||
await execa(
|
||||
containerRuntime(),
|
||||
['exec', args.containerName, 'bash', '-lc', buildKillScript(args.marker)],
|
||||
{ reject: false, stdin: 'ignore' },
|
||||
);
|
||||
};
|
||||
|
||||
export const streamExecInContainer = async (args: {
|
||||
containerName: string;
|
||||
command: string[];
|
||||
|
||||
Reference in New Issue
Block a user