refactor(engine): unify commands and orchestrators

Replace the CommandHost with a handler registry keyed by message type.
Message is a permissive base type the host extends; CommandResult is a
discriminated union on the type suffix. Commands and orchestrators are
the same async shape taking a RunContext with an AbortSignal; runCommand
emits :done/:cancel/:error.
This commit is contained in:
2026-08-10 18:40:35 +08:00
parent 81c115cb4d
commit 8bd186df54
6 changed files with 255 additions and 99 deletions
+30
View File
@@ -0,0 +1,30 @@
/**
* The run context and the unified command/orchestrator shape.
*
* A command and an orchestrator are the same thing: an async function taking a
* `RunContext`. A command returns a result and is awaited by the engine, which
* emits `:done`/`:cancel`/`:error`; an orchestrator returns `void` and is never
* awaited by a parent. Cancellation is an `AbortSignal` — a superseded command
* or disabled surface aborts it, `wait` rejects on abort, and the `:cancel`
* result is emitted. Errors are thrown: a command that throws emits `:error`.
*/
import type { Message } from './message.js';
/** The handle every handler runs against. */
export interface RunContext {
/** Cancellation: superseded, skipped, surface disabled. */
signal: AbortSignal;
/** Emit a message onto the queue. */
emit(msg: Message): void;
/** Await the next message matching `pred`. Rejects on abort. */
wait(pred: (m: Message) => boolean): Promise<Message>;
/** Enable/disable a trigger by `type#id`. */
enableTrigger(type: string, id?: string): void;
disableTrigger(type: string, id?: string): void;
}
/** A command: an async function taking the context plus its args. */
export type Command<Args, Result> = (ctx: RunContext & { args: Args }) => Promise<Result>;
/** An orchestrator: an async function that emits and awaits messages. */
export type Orchestrator = (ctx: RunContext) => Promise<void>;