MCPcopy Create free account
hub / github.com/TraderAlice/OpenAlice / runHeadlessTask

Function runHeadlessTask

src/workspaces/headless-task.ts:149–270  ·  view source on GitHub ↗
(args: HeadlessTaskArgs)

Source from the content-addressed store, hash-verified

147}
148
149export async function runHeadlessTask(args: HeadlessTaskArgs): Promise<HeadlessTaskResult> {
150 const { command, cwd, env, timeoutMs, logger } = args;
151 const [argv0] = command;
152 if (!argv0) throw new Error('headless: empty command');
153
154 const start = Date.now();
155 let exitCode: number | null = null;
156 let signal: NodeJS.Signals | null = null;
157 let killed = false;
158 let agentSessionId: string | null = null;
159 const outSink = makeTailSink(OUTPUT_TAIL_BYTES);
160 const errSink = makeTailSink(OUTPUT_TAIL_BYTES);
161 const scanner = args.extractSessionId
162 ? makeSessionIdScanner(args.extractSessionId, (id) => {
163 agentSessionId = id;
164 logger.info('headless.session_id_captured', { agentSessionId: id });
165 args.onSessionId?.(id);
166 })
167 : null;
168 // win32: resolve the bare CLI name against PATH × PATHEXT. Native-exe agents
169 // (claude.exe, codex.exe) resolve to a direct path and run headless fine. But
170 // npm-shim agents (opencode, pi → a `.cmd`) would have to run through cmd.exe,
171 // and the headless PROMPT is the trailing arg — routing it through cmd.exe
172 // re-parses shell metacharacters (CVE-2024-27980 territory), a real injection
173 // surface. So shim agents stay headless-unsupported on Windows; we fail with a
174 // clear, recorded reason instead of a silent ENOENT. (Interactive launch of
175 // the same agents works — see win-command.ts / persistent-session.ts.)
176 const resolved = resolveLaunchCommand(command, { env });
177 if (resolved.viaShell) {
178 logger.error('headless.win32_shim_unsupported', { command: argv0 });
179 return {
180 command,
181 cwd,
182 exitCode: -1,
183 signal: null,
184 killed: false,
185 durationMs: Date.now() - start,
186 stdoutTail: '',
187 stderrTail:
188 `win32: "${argv0}" is an npm .cmd shim; headless dispatch is unsupported ` +
189 `on Windows (routing the task prompt through cmd.exe is a shell-injection ` +
190 `surface). Native-exe agents (claude, codex) run headless; run shim agents ` +
191 `(opencode, pi) interactively instead.`,
192 agentSessionId: null,
193 };
194 }
195 const [spawnFile, ...spawnArgs] = resolved.argv;
196 if (!spawnFile) throw new Error('headless: empty command after resolution');
197 const outFile = args.stdoutFile ? await openLogStream(args.stdoutFile, logger, 'stdout') : null;
198 const errFile = args.stderrFile ? await openLogStream(args.stderrFile, logger, 'stderr') : null;
199 const child = spawn(spawnFile, spawnArgs, {
200 cwd,
201 env: env as NodeJS.ProcessEnv,
202 stdio: ['ignore', 'pipe', 'pipe'],
203 });
204 child.stdout?.on('data', (d: Buffer) => {
205 outSink.push(d);
206 scanner?.push(d);

Callers 2

runHeadlessTaskMethodFunction · 0.85

Calls 8

makeTailSinkFunction · 0.85
makeSessionIdScannerFunction · 0.85
resolveLaunchCommandFunction · 0.85
openLogStreamFunction · 0.85
infoMethod · 0.80
fromMethod · 0.80
errorMethod · 0.65
pushMethod · 0.65

Tested by

no test coverage detected