import type { Command } from 'commander'; import { FleetAgentScaffoldError, scaffoldFleetAgent } from '../fleet/fleet-agent-scaffold.js'; export interface FleetAgentScaffoldCommandDeps { /** Test seam for the user-owned ~/.mosaic root. */ readonly fleetDataHome?: string; /** Resolves the active installed Mosaic root that owns the canonical runtime base. */ readonly mosaicHomeFor?: () => string; } interface NewAgentOptions { readonly harness?: string; readonly bundle?: string; readonly model?: string; } /** Registers the user-data seat scaffolder, distinct from roster-v2 CRUD. */ export function registerFleetAgentScaffoldCommand( fleetCommand: Command, deps: FleetAgentScaffoldCommandDeps = {}, ): void { const agent = fleetCommand .command('agent') .description('Manage user-owned fleet agent harness homes'); agent .command('new ') .description('Create an additive-or-refuse fleet agent harness home') .option('--harness ', 'Harness: claude or pi', 'claude') .option('--bundle ', 'Auth bundle selector', 'primary') .option('--model ', 'Optional harness-native model') .action(async (name: string, options: NewAgentOptions): Promise => { try { const result = await scaffoldFleetAgent({ name, harness: options.harness, bundle: options.bundle, model: options.model, ...(deps.fleetDataHome === undefined ? {} : { dataHome: deps.fleetDataHome }), ...(deps.mosaicHomeFor === undefined ? {} : { mosaicHome: deps.mosaicHomeFor() }), }); console.log( result.idempotent ? `Fleet agent "${name}" already matches the scaffold.` : `Created fleet agent "${name}" at ${result.agentDir}.`, ); if (!result.credentialTargetExists) { console.log( `Notice: credentials link is intentionally dangling until auth bundle "${result.profile['bundle']}" is enrolled: ${result.credentialTarget}`, ); } } catch (error: unknown) { process.exitCode = 1; const message = error instanceof Error ? error.message : String(error); const code = error instanceof FleetAgentScaffoldError ? error.code : 'scaffold-failed'; process.stderr.write(`mosaic fleet agent new failed (${code}): ${message}\n`); } }); }