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:
@@ -7,6 +7,7 @@ import type {
|
||||
ErrorReason,
|
||||
HtmlArtifactState,
|
||||
MarkdownArtifactState,
|
||||
OrchestratorState,
|
||||
Project,
|
||||
Session,
|
||||
} from '@/api/types';
|
||||
@@ -184,6 +185,52 @@ export interface GitDiffRefreshEvent {
|
||||
type: 'git_diff_refresh';
|
||||
}
|
||||
|
||||
// Orchestrator: emitted client-side to open an orchestrator pane.
|
||||
// useWorkspacePanes subscribes and inserts the pane (or focuses an existing one).
|
||||
// placement carries the surface context: 'new' (+ menu) or 'split' (split-pane
|
||||
// menu). addOrchestratorPane appends in both cases; the hint is available for
|
||||
// future positional differentiation.
|
||||
export interface OpenOrchestratorPaneEvent {
|
||||
type: 'open_orchestrator_pane';
|
||||
state: OrchestratorState;
|
||||
placement?: 'new' | 'split';
|
||||
}
|
||||
|
||||
// Orchestrator: emitted by the Workflow button on ChatInput (or "New Orchestrator"
|
||||
// menu items) to request the flow launcher dialog. Carries the current pane's
|
||||
// project and the placement context ('new' from the + menu, 'split' from the
|
||||
// split-pane menu) so the resulting open_orchestrator_pane can be placed correctly.
|
||||
export interface OpenFlowLauncherEvent {
|
||||
type: 'open_flow_launcher';
|
||||
project_id: string;
|
||||
placement?: 'new' | 'split';
|
||||
}
|
||||
|
||||
// Orchestrator: run-level frames forwarded from the coder user channel by
|
||||
// useCoderUserEvents. OrchestratorPane subscribes to update its roster/report.
|
||||
export interface FlowRunStartedEvent {
|
||||
type: 'flow_run_started';
|
||||
run_id: string;
|
||||
flow_name: string;
|
||||
band: 'small' | 'medium' | 'large';
|
||||
steps: Array<{
|
||||
step_id: string;
|
||||
agent: string;
|
||||
kind: 'agent' | 'code';
|
||||
chat_id: string;
|
||||
label: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface FlowRunStepUpdatedEvent {
|
||||
type: 'flow_run_step_updated';
|
||||
run_id: string;
|
||||
step_id: string;
|
||||
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'cancelled';
|
||||
run_status?: 'running' | 'completed' | 'failed' | 'cancelled';
|
||||
report?: string;
|
||||
}
|
||||
|
||||
export type SessionEvent =
|
||||
| SessionRenamedEvent
|
||||
| ProjectCreatedEvent
|
||||
@@ -211,7 +258,11 @@ export type SessionEvent =
|
||||
| ProjectUpdatedEvent
|
||||
| ChatStatusEvent
|
||||
| RefetchMessagesEvent
|
||||
| GitDiffRefreshEvent;
|
||||
| GitDiffRefreshEvent
|
||||
| OpenOrchestratorPaneEvent
|
||||
| FlowRunStartedEvent
|
||||
| FlowRunStepUpdatedEvent
|
||||
| OpenFlowLauncherEvent;
|
||||
type Listener = (event: SessionEvent) => void;
|
||||
|
||||
const listeners = new Set<Listener>();
|
||||
|
||||
Reference in New Issue
Block a user