/** * orchestration-dispatch.ts — Heuristic auto / single / swarm / crew dispatch * * Decides how to fan out a fresh agent spawn: * - `single` → spawn one agent (current behavior, default for most prompts) * - `swarm` → spawn N agents with the same prompt in parallel (live strategy) * - `crew` → spawn 3 role-specialized agents (planner, executor, reviewer) and * join their results into one group * - `auto` → run `analyzePrompt` + `heuristicPickMode` to pick a concrete mode * * Heuristic signals (cheap, keyword-based — not LLM-driven, no extra latency): * - planner keyword (e.g. "plan", "design") → crew * - parallel keyword (e.g. "compare", "benchmark") → swarm * - review keyword (e.g. "review", "audit") → crew * - refactor + (test or multiple-files) → crew * - implement + multiple-files → crew * - long prompt (> 800 chars) with implementation key → crew * - otherwise → single * * Note: multiple file paths alone do NOT trigger crew — they require an * accompanying implementation signal. Read-only prompts that mention * multiple files (e.g. "explore ./src/a.ts and ./src/b.ts") resolve to single. * * The dispatcher is pure (no I/O, no side effects) so it's cheap to unit-test * and safe to call inline from the Agent tool's execute path. */ import type { OrchestrationMode } from "./agent-registry.js"; import type { SubagentType } from "./types.js"; export type OrchestrationKind = "single" | "swarm" | "crew"; export interface SwarmAgentPlan { /** Short (3-5 word) description shown in the UI. */ description: string; /** Prompt for this swarm member. */ prompt: string; } export type CrewRole = "planner" | "executor" | "reviewer"; export interface CrewRolePlan { role: CrewRole; description: string; prompt: string; } export type OrchestrationDecision = { kind: "single"; } | { kind: "swarm"; agents: SwarmAgentPlan[]; joinMode: "swarm"; } | { kind: "crew"; roles: CrewRolePlan[]; joinMode: "group"; }; export interface PromptAnalysis { /** Prompt length in characters. */ length: number; /** Number of "step" or numbered list items detected (rough). */ estimatedSteps: number; /** Detected file paths (rough absolute or relative path match). */ hasMultipleFiles: boolean; /** True if prompt mentions reviewing/auditing/validating. */ hasReviewKeyword: boolean; /** True if prompt mentions parallel/compare/benchmark. */ hasParallelKeyword: boolean; /** True if prompt mentions planning/designing/architecting. */ hasPlanKeyword: boolean; /** True if prompt mentions implementing/building/writing. */ hasImplementKeyword: boolean; /** True if prompt mentions refactoring/restructuring. */ hasRefactorKeyword: boolean; /** True if prompt mentions testing/test suite. */ hasTestKeyword: boolean; } /** * Score a prompt for orchestration signals. Pure / side-effect free. */ export declare function analyzePrompt(prompt: string): PromptAnalysis; /** * Pick a concrete dispatch kind from a prompt analysis. * * Order of precedence (most specific signal wins): * 1. planner / review → crew (always) * 2. refactor + (test or multiple-files) → crew * 3. implement + multiple-files → crew (implementation across files) * 4. long + multi-step implementation → crew * 5. parallel keyword → swarm * 6. otherwise → single * * Note: `hasMultipleFiles` alone does NOT trigger crew — it requires an * accompanying implementation signal. Read-only prompts that mention * multiple files (e.g. "explore ./src/a.ts and ./src/b.ts") correctly * resolve to single. */ export declare function heuristicPickMode(a: PromptAnalysis): OrchestrationKind; /** * Build a swarm plan: N copies of the same prompt with distinct descriptions. * Defaults to 2 parallel members; capped at 5 to avoid runaway fan-out. */ export declare function buildSwarmPlan(prompt: string, description: string, n?: number): SwarmAgentPlan[]; /** * Build a 3-role crew plan from a single user prompt. * * - planner → reads the request, drafts an implementation plan + files to touch * - executor → implements the plan end-to-end * - reviewer → audits the executor's output against the original request * * The user prompt is passed verbatim to the executor; the planner and reviewer * get role-specific framing that quotes the user request. */ export declare function buildCrewPlan(prompt: string, description: string, _subagentType: SubagentType): CrewRolePlan[]; export interface ResolveOpts { mode: OrchestrationMode; prompt: string; description: string; subagentType: SubagentType; /** When true, the orchestrator will run agents in the background. */ runInBackground: boolean; /** Optional override for the swarm member count. */ swarmSize?: number; } /** * Resolve the orchestrator mode for a fresh agent spawn. * Pure / synchronous — no I/O, no manager calls. The caller is responsible for * materializing the decision into actual `manager.spawn(...)` calls. */ export declare function resolveOrchestrationMode(opts: ResolveOpts): OrchestrationDecision;