feat: in-app Orchestrator (Phase 2) — multi-agent conductor
Brings the deterministic Han-flow conductor into BooCode: launch any read-only flow from BooChat or BooCoder, watch each agent stream live in a Paseo-style run pane, get an evidence-disciplined report — on local Qwen, persisted and resumable. Read-only enforced hard via qwen --approval-mode plan (orchestrator tasks fail closed if qwen is unavailable; never fall to write-capable native). Backend (apps/coder): re-homed conductor defs, flow_runs/flow_steps schema, flow-runner + dispatcher onTaskTerminal hook, restart-resume, runs routes (launch/list/get/cancel), user-channel WS. Contracts: two flow_run_* frames. Web: orchestrator pane kind + OrchestratorPane, Workflow button + slash flows (BooChat/BooCoder parity), FlowLauncherDialog, "New Orchestrator" in the + and split menus, runs history + export. Plan: openspec/changes/orchestrator. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
69
apps/coder/src/conductor/flows/index.ts
Normal file
69
apps/coder/src/conductor/flows/index.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/** Flow registry. Han skills as Spine configs + the bespoke code-review pipeline. */
|
||||
import type { Flow, Spine } from '../types.js';
|
||||
import { buildSpineFlow } from '../spine.js';
|
||||
|
||||
import { research } from './research.js';
|
||||
import { investigate } from './investigate.js';
|
||||
import { architecturalAnalysis } from './architectural-analysis.js';
|
||||
import { securityReview } from './security-review.js';
|
||||
import {
|
||||
gapAnalysis,
|
||||
projectDiscovery,
|
||||
projectDocumentation,
|
||||
testPlanning,
|
||||
dataReview,
|
||||
devopsReview,
|
||||
issueTriage,
|
||||
} from './discovery.js';
|
||||
import {
|
||||
planFeature,
|
||||
planImplementation,
|
||||
planPhasedBuild,
|
||||
planWorkItems,
|
||||
iterativePlanReview,
|
||||
} from './planning.js';
|
||||
import { adr, codingStandard, runbook, tdd, stakeholderSummary } from './authoring.js';
|
||||
import { codeReview } from './code-review.js';
|
||||
|
||||
const spines: Spine[] = [
|
||||
// analysis / research
|
||||
research,
|
||||
investigate,
|
||||
architecturalAnalysis,
|
||||
securityReview,
|
||||
gapAnalysis,
|
||||
dataReview,
|
||||
devopsReview,
|
||||
issueTriage,
|
||||
// discovery / docs / tests
|
||||
projectDiscovery,
|
||||
projectDocumentation,
|
||||
testPlanning,
|
||||
// planning (best-effort one-pass)
|
||||
planFeature,
|
||||
planImplementation,
|
||||
planPhasedBuild,
|
||||
planWorkItems,
|
||||
iterativePlanReview,
|
||||
// authoring / reporting (best-effort one-pass)
|
||||
adr,
|
||||
codingStandard,
|
||||
runbook,
|
||||
tdd,
|
||||
stakeholderSummary,
|
||||
];
|
||||
|
||||
const bespoke: Flow[] = [codeReview];
|
||||
|
||||
const ALL: Flow[] = [...spines.map(buildSpineFlow), ...bespoke];
|
||||
|
||||
export const FLOWS: Record<string, Flow> = Object.fromEntries(ALL.map((f) => [f.name, f]));
|
||||
export const FLOW_NAMES: string[] = ALL.map((f) => f.name);
|
||||
|
||||
export function describeFlows(): string {
|
||||
return ALL.map((f) => ` ${f.name.padEnd(24)} ${f.description}`).join('\n');
|
||||
}
|
||||
|
||||
export function getFlow(name: string): Flow | undefined {
|
||||
return FLOWS[name];
|
||||
}
|
||||
Reference in New Issue
Block a user