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.
30 lines
1.4 KiB
TypeScript
30 lines
1.4 KiB
TypeScript
/**
|
|
* 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>; |