/** * Shared spawn-and-attach helper. * * Two entry points compose `new` + a session verb: * * 1. `agent-relay new NAME CLI --attach [--mode …] [--ephemeral]` * — the explicit, flag-driven path. * 2. `agent-relay -n NAME CLI [args...]` — the bare `-n` shorthand, * hardcoded to `--mode passthrough --ephemeral`. * * Both call `runSpawnAndAttach()` here. There is one function that does * the work, and the only difference between the two entry points is * which `SpawnAndAttachOptions` they construct — so the shorthand and * the explicit form produce identical broker calls and teardown * behaviour by construction. * * This module lives in `src/cli/lib/` (not `src/cli/commands/`) because * it's a helper consumed by multiple commands (`new --attach` action) * and the bootstrap-layer alias dispatcher, not a verb registration in * its own right. */ import { type BrokerConnection } from './broker-connection.js'; import { type NewDependencies } from '../commands/new.js'; import { type DriveDependencies } from '../commands/drive.js'; import { type PassthroughDependencies } from '../commands/passthrough.js'; import { type ViewDependencies } from '../commands/view.js'; export type AttachMode = 'view' | 'drive' | 'passthrough'; /** Options the composition layer understands. */ export interface SpawnAndAttachOptions { name: string; cli: string; args?: string[]; mode?: AttachMode; ephemeral?: boolean; task?: string; channels?: string; cwd?: string; team?: string; model?: string; brokerUrl?: string; apiKey?: string; stateDir?: string; } /** Shared dependencies the composition needs. */ export interface SpawnAndAttachDependencies { /** For the spawn step. */ newDeps: NewDependencies; /** For `--mode drive` attach. */ driveDeps: DriveDependencies; /** For `--mode passthrough` attach. */ passthroughDeps: PassthroughDependencies; /** For `--mode view` attach. */ viewDeps: ViewDependencies; /** Issue a release on ephemeral teardown. Default delegates to `rm.releaseAgent`. */ releaseAgent: (connection: BrokerConnection, name: string, fetchFn: typeof globalThis.fetch) => Promise<{ ok: boolean; status: number; message?: string; }>; /** Signal registrar so the ephemeral teardown fires on SIGINT/SIGTERM. */ onSignal: (signal: NodeJS.Signals, handler: () => void | Promise) => void; log: (...args: unknown[]) => void; error: (...args: unknown[]) => void; } /** Bundle of child-module deps used by the production default factory. */ export interface AttachChildDependencies { newDeps: NewDependencies; driveDeps: DriveDependencies; passthroughDeps: PassthroughDependencies; viewDeps: ViewDependencies; } /** * Build the default child-module deps (`new` / `drive` / `passthrough` / * `view`) using the production defaults — global `fetch`, real * WebSocket, real signal registration, real stdin/stdout. Exported so * bootstrap-layer callers can wire production defaults without * re-encoding every detail. */ export declare function buildDefaultAttachChildDeps(): AttachChildDependencies; /** * Build the full `SpawnAndAttachDependencies` bundle from the child * deps. Exposed so callers that already have child deps (e.g. tests) * can opt into the default `releaseAgent` / `onSignal` wiring without * re-implementing it. */ export declare function buildSpawnAndAttachDeps(childDeps?: AttachChildDependencies): SpawnAndAttachDependencies; /** * Spawn an agent and immediately attach to it via the chosen session * verb. Single code path for both `new -n NAME CLI --attach …` and the * verbless `-n NAME CLI` alias. * * Returns the exit code the CLI should propagate. */ export declare function runSpawnAndAttach(options: SpawnAndAttachOptions, deps: SpawnAndAttachDependencies): Promise; /** * Tiny standalone entry point for the verbless `-n NAME CLI` shorthand * dispatcher in `bootstrap.ts`. Hands off to `runSpawnAndAttach` with * the shorthand's hardcoded preset (`--mode passthrough`, `--ephemeral`). */ export declare function runVerblessAliasDispatch(parsedArgs: { name: string; cli: string; args: string[]; }, childDeps?: AttachChildDependencies): Promise; /** * Pre-parse `argv.slice(2)` to detect the `-n NAME CLI [args...]` * shorthand. Returns the parsed shape when the arguments unambiguously * fit the shorthand, or `null` to let Commander parse normally. * * Recognised forms: * * agent-relay -n NAME CLI [args...] * agent-relay --name NAME CLI [args...] * agent-relay -nNAME CLI [args...] (joined short flag) * agent-relay --name=NAME CLI [args...] (equals form) * * Rejected (returns null — fall through to Commander): * - any of the registered subcommand names ('view', 'drive', etc.) * appears as the first non-flag token, even after `-n` * - `-h`/`--help`/`-V`/`--version` present * - `-n` without a CLI positional * * Exported for unit testing alongside the byte-equivalence test that * proves the shorthand parse matches what `new NAME CLI --attach --mode passthrough --ephemeral` * decomposes into at the action layer. */ export declare function parseVerblessAlias(args: string[], knownVerbs: ReadonlySet): { name: string; cli: string; args: string[]; } | null; //# sourceMappingURL=spawn-and-attach.d.ts.map