ACP dispatch now spawns from the resolved registry's launch spec instead of a hardcoded per-name switch. acp-spawn.ts gains resolveLaunchSpec(resolved, installPath): launchCommand (config override / custom-ACP command) wins, else the kept resolveAcpSpawnArgs switch is the built-in fallback. acp-dispatch.ts spawns spec.binary/spec.args with env { ...process.env, ...spec.env }; dispatcher.ts loads the resolved def by task.agent and passes it through. Config-defined custom ACP providers dispatch with no new switch case. Built-in dispatch (opencode/goose/qwen) is byte-identical to pre-v2.3 — proven by a regression test (opencode->['acp'], goose->['acp'], qwen->['--acp'], binary=installPath ?? id, empty env -> plain process.env). Deliberate deviation from design's !installPath->null: the installPath ?? id fallback is preserved. setSessionMode/permission/streaming and the dispatcher poll/NOTIFY/running-guard untouched. 7 new acp-spawn.test.ts cases. No routes/UI (Phase 4+).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import type { ResolvedProviderDef } from './provider-config-registry.js';
|
|
|
|
/**
|
|
* Resolve ACP spawn argv per built-in provider (host-probe verified 2026-05-25).
|
|
* Source of truth for built-in default argv — resolveLaunchSpec wraps these; it
|
|
* does NOT replace them.
|
|
*/
|
|
export function resolveAcpSpawnArgs(agent: string): string[] | null {
|
|
switch (agent) {
|
|
case 'opencode':
|
|
case 'goose':
|
|
return ['acp'];
|
|
case 'qwen':
|
|
return ['--acp'];
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* v2.3 phase 3: resolve the launch spec for an ACP dispatch (design.md §5.1).
|
|
* Consults the resolved registry's launchCommand (config override or custom-ACP
|
|
* entry) first; otherwise falls back to the built-in default argv above.
|
|
*
|
|
* Byte-identical to pre-v2.3 for built-ins with no override: binary is
|
|
* `installPath ?? id` and args come from resolveAcpSpawnArgs — exactly the
|
|
* `binary = installPath ?? agent` + `resolveAcpSpawnArgs(agent)` the dispatcher
|
|
* used before. (Deliberate deviation from design §5.1's `!installPath → null`:
|
|
* the old path spawned the bare agent name when install_path was missing, so we
|
|
* preserve the `?? id` fallback rather than fail.)
|
|
*/
|
|
export function resolveLaunchSpec(
|
|
resolved: ResolvedProviderDef,
|
|
installPath: string | null,
|
|
): { binary: string; args: string[]; env?: Record<string, string> } | null {
|
|
if (resolved.launchCommand) {
|
|
return {
|
|
binary: resolved.launchCommand[0],
|
|
args: resolved.launchCommand.slice(1),
|
|
env: resolved.env,
|
|
};
|
|
}
|
|
const args = resolveAcpSpawnArgs(resolved.id);
|
|
if (!args) return null;
|
|
return { binary: installPath ?? resolved.id, args, env: resolved.env };
|
|
}
|
|
|
|
export function resolveAcpProbeBinaries(agent: string): string[] {
|
|
return [agent];
|
|
}
|