import { z } from 'zod'; import { i as AnnotationActor } from './interface-DMzwv0lD.js'; import { b as SuspendedStateSchema, P as ProgressUpdate, L as LogLevel, S as StageResult, a as SuspendedResult, C as CompletionCheckResult, c as StageMode } from './types-ByGg__Kd.js'; /** * Stage interface and context definitions * * Stages are the building blocks of workflows. Each stage: * - Has strongly-typed input, output, and config schemas (Zod) * - Can be sync or async-batch * - Has access to AI helper, storage, and logging via context * - Can suspend workflow for long-running batch operations */ /** * Single-attribute form options. * * The `actor` field accepts an `AnnotationActor` ({ kind?, id?, version? }). * `payload` is a separate blob slot for non-queryable rich data. * `idempotencyKey` opts the annotation into the unique constraint on * `(workflowRunId, key, idempotencyKey)` so retries are deduped. */ interface AnnotateOpts { actor?: AnnotationActor; payload?: Record; idempotencyKey?: string; /** * If true, the engine writes an `annotation:created` outbox event in * the same transaction as the annotation row. Useful for plugins or * external systems (audit pipelines, SIEM, live dashboards) that * want push notifications on provenance writes. Off by default. */ emitEvent?: boolean; } /** * Batch form — multiple attributes share one envelope (actor / payload / * idempotencyKey / emitEvent). Each attribute becomes one row in * WorkflowAnnotation; if `emitEvent` is set, each row also emits its * own `annotation:created` outbox event. */ interface AnnotateBatch { attributes: Record; actor?: AnnotationActor; payload?: Record; idempotencyKey?: string; emitEvent?: boolean; } /** * Stability level for a well-known annotation key, attached at definition * time and surfaced to IDEs through the conventions module. * * Policy: once a key is `stable`, it is immutable. Renames and value-type * changes must ship as new keys; the old key gets a `@deprecated` JSDoc * tag. No env-var stability opt-in (we deliberately do not copy * OpenTelemetry's `OTEL_SEMCONV_STABILITY_OPT_IN`). */ type Stability = "stable" | "experimental" | "deprecated"; /** * Typed annotation key. The phantom `_valueType` parameter lets * `ctx.annotate(key, value)` enforce that `value` matches `T` at compile * time when the key was defined with `typedKey(...)`. The marker is * never set at runtime — only the `key` string is. */ interface TypedKey { readonly key: string; readonly stability: Stability; readonly description?: string; /** Phantom — never populated. Used only for `T` inference. */ readonly _valueType?: T; } /** * Overloaded callable supporting three forms: * * - **Typed key**: `ctx.annotate(Decision.outcome, "low")` — value type * is inferred from the TypedKey, giving compile-time linkage between * well-known keys and their expected value shapes. * - **String key**: `ctx.annotate("custom.namespace.key", value)` — * escape hatch for org-defined conventions. * - **Batch**: `ctx.annotate({ attributes: {...}, actor?, ... })` — * emit several related attributes sharing one envelope. * * All three return `void` from the caller's perspective; writes are * buffered on the context and flushed inside the stage-completion * transaction. `undefined` values are dropped (OTel pattern: callers can * write `ctx.annotate("x.id", maybeId)` without guarding). */ interface AnnotateFn { (key: TypedKey, value: T, opts?: AnnotateOpts): void; (key: string, value: unknown, opts?: AnnotateOpts): void; (args: AnnotateBatch): void; } interface StageContext> { workflowRunId: string; stageId: string; stageNumber: number; stageName: string; /** Database record ID for this stage execution (for logging to persistence) */ stageRecordId?: string; input: TInput; config: TConfig; resumeState?: z.infer; onProgress: (update: ProgressUpdate) => void; onLog: (level: LogLevel, message: string, meta?: Record) => void; log: (level: LogLevel, message: string, meta?: Record) => void; annotate: AnnotateFn; storage: StageStorage; workflowContext: Partial; } interface StageStorage { save(key: string, data: T): Promise; load(key: string): Promise; exists(key: string): Promise; delete(key: string): Promise; getStageKey(stageId: string, suffix?: string): string; } /** * Context passed to checkCompletion for async-batch stages. * Includes identification info so stages don't need to store it in metadata. */ interface CheckCompletionContext { workflowRunId: string; stageId: string; /** Database record ID for this stage execution (for logging to persistence) */ stageRecordId?: string; config: TConfig; onLog: (level: LogLevel, message: string, meta?: Record) => void; log: (level: LogLevel, message: string, meta?: Record) => void; annotate: AnnotateFn; storage: StageStorage; } interface Stage, TId extends string = string> { id: TId; name: string; description?: string; /** * Optional: List of stage IDs that this stage depends on. * The workflow builder will validate that all dependencies are present * in the workflow before this stage is executed. * * Example: dependencies: ["data-extraction", "guidelines"] */ dependencies?: string[]; inputSchema: TInput; outputSchema: TOutput; configSchema: TConfig; execute: (context: StageContext, z.infer, TWorkflowContext>) => Promise> | SuspendedResult>; checkCompletion?: (suspendedState: z.infer, context: CheckCompletionContext>) => Promise>>; mode?: StageMode; estimateCost?: (input: z.infer, config: z.infer) => number; } export type { CheckCompletionContext as C, Stability as S, TypedKey as T, Stage as a, StageContext as b };