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

Function runHeadlessTaskMethod

src/workspaces/service.ts:488–534  ·  view source on GitHub ↗
(
    ws: WorkspaceMeta,
    adapter: CliAdapter,
    prompt: string,
    timeoutMs: number,
    // Dispatch-path extras: a taskId keys the on-disk task log; onSessionId
    // fires when the adapter's stdout scanner captures the agent's own session
    // id (recorded WHILE running, so the panel can offer "open as session").
    opts: { taskId?: string; onSessionId?: (id: string) => void } = {},
  )

Source from the content-addressed store, hash-verified

486 };
487
488 const runHeadlessTaskMethod = async (
489 ws: WorkspaceMeta,
490 adapter: CliAdapter,
491 prompt: string,
492 timeoutMs: number,
493 // Dispatch-path extras: a taskId keys the on-disk task log; onSessionId
494 // fires when the adapter's stdout scanner captures the agent's own session
495 // id (recorded WHILE running, so the panel can offer "open as session").
496 opts: { taskId?: string; onSessionId?: (id: string) => void } = {},
497 ): Promise<HeadlessTaskResult> => {
498 if (!adapter.capabilities.headless || !adapter.composeHeadlessCommand) {
499 throw new Error(`adapter "${adapter.id}" has no headless mode`);
500 }
501 await ensureAgentCredentialReady({
502 meta: ws,
503 agentId: adapter.id,
504 adapter,
505 logger: launcherLogger,
506 });
507 // Reuse a fresh interactive spawn's env/cwd (identical MCP injection),
508 // then swap the interactive command for the one-shot headless argv. Inject
509 // AQ_RUN_ID = this run's taskId so the agent's inbox pushes self-link to the
510 // run server-side (via the `alice` shim header / opencode's MCP header) —
511 // headless-only, agent never sees it. The taskId is the registry key the
512 // route resolves issueId/agent from.
513 const { cwd, env } = composeSpawnInputs(
514 ws,
515 adapter,
516 undefined,
517 undefined,
518 opts.taskId ? { AQ_RUN_ID: opts.taskId } : undefined,
519 );
520 const command = adapter.composeHeadlessCommand(config.command, { cwd, env }, prompt);
521 const logPaths = opts.taskId ? headlessLogPaths(headlessLogsDir, opts.taskId) : null;
522 return runHeadlessTask({
523 command,
524 cwd,
525 env,
526 timeoutMs,
527 logger: launcherLogger.child({ scope: 'headless', wsId: ws.id, agent: adapter.id }),
528 ...(logPaths ? { stdoutFile: logPaths.stdout, stderrFile: logPaths.stderr } : {}),
529 ...(adapter.extractHeadlessSessionId
530 ? { extractSessionId: adapter.extractHeadlessSessionId.bind(adapter) }
531 : {}),
532 ...(opts.onSessionId ? { onSessionId: opts.onSessionId } : {}),
533 });
534 };
535
536 /**
537 * ASYNC dispatch: record the task, spawn it in the background, return the

Callers 1

Calls 6

composeSpawnInputsFunction · 0.85
headlessLogPathsFunction · 0.85
runHeadlessTaskFunction · 0.85
childMethod · 0.80

Tested by

no test coverage detected