import type { Schema } from "../extensions/schema/index.js"; import type { Agent } from "../agent/types.js"; import type { Tool } from "../tool/types.js"; import type { ScheduleIntegrationRequirementConfig } from "../schedule/types.js"; import type { BlobRef, BlobStorage } from "./blob/types.js"; import type { SourceIntegrationPolicyManifest } from "../integrations/source-policy.js"; import type { WorkflowProjectionState } from "./runtime-state.js"; import type { DurableTimedWaitKind } from "./timed-wait-state.js"; export type { ApprovalDecision, ApprovalStatus, BackoffStrategy, LoopExecutionContext, NodeState, NodeStatus, ParallelStrategy, PendingApproval, RetryConfig, RunFilter, WaitType, WorkflowError, WorkflowNodeType, WorkflowQueueItem, WorkflowStatus, } from "./schemas/index.js"; import type { LoopExecutionContext, NodeState, ParallelStrategy, PendingApproval, RetryConfig, WaitType, WorkflowError, WorkflowStatus } from "./schemas/index.js"; /** * Workflow context containing JSON-representable input and node outputs. * * A run that suspends is persisted as JSON, so anything a step writes here has * to survive `JSON.stringify` unchanged. A `Date`, `Map`, or class instance * does not: it is readable in memory and comes back as something else after a * resume, which makes the type a later step sees depend on whether the run * happened to pause. `serializeWorkflowContext` enforces this at the * persistence boundary. */ export interface WorkflowContext { input: unknown; env?: Record; _tenant?: CapturedTenantContext; [nodeId: string]: unknown; } /** * Checkpoint - defined locally to use WorkflowContext interface * (Zod inference doesn't handle index signatures with required properties well) */ export interface Checkpoint { id: string; nodeId: string; timestamp: Date; context: WorkflowContext; nodeStates: Record; /** @internal Framework-only public projection ownership sidecar. */ _workflowProjection?: WorkflowProjectionState; /** @internal Validated root snapshot for resuming a descendant checkpoint. */ _resumeEnvelope?: CheckpointResumeEnvelope; } /** @internal Serializable identity of one admitted workflow graph node. */ export interface WorkflowGraphIdentityNode { readonly id: string; readonly type: WorkflowNodeConfig["type"]; readonly dependsOn: readonly string[] | null; readonly composite: WorkflowGraphCompositeIdentity | null; } /** @internal Serializable identity of statically visible composite descendants. */ export type WorkflowGraphCompositeIdentity = { readonly kind: "parallel"; readonly strategy: ParallelStrategy | null; readonly nodes: readonly WorkflowGraphIdentityNode[]; } | { readonly kind: "branch"; readonly then: readonly WorkflowGraphIdentityNode[]; readonly else: readonly WorkflowGraphIdentityNode[] | null; } | { readonly kind: "loop"; readonly dynamic: boolean; readonly nodes: readonly WorkflowGraphIdentityNode[] | null; } | { readonly kind: "map"; readonly processorKind: "node" | "workflow"; readonly processorId: string; readonly processorVersion: string | null; readonly dynamic: boolean; readonly nodes: readonly WorkflowGraphIdentityNode[] | null; } | { readonly kind: "subWorkflow"; readonly workflowId: string; readonly workflowVersion: string | null; readonly dynamic: boolean; readonly nodes: readonly WorkflowGraphIdentityNode[] | null; }; export type WorkflowGraphIdentity = readonly WorkflowGraphIdentityNode[]; /** @internal Durable root graph admission captured before any admitted node runs. */ export interface WorkflowGraphAdmission { readonly stepsEvaluationContext: WorkflowContext; readonly stepsEvaluationProjection: WorkflowProjectionState; readonly graphIdentity: WorkflowGraphIdentity; readonly workflowVersion: string | null; } /** @internal Durable root snapshot synthesized by the owning composite stack. */ export interface CheckpointResumeEnvelope { readonly schemaVersion: 2; /** Root composite/node that owns this resumable transaction. */ readonly ownerNodeId: string; readonly context: WorkflowContext; readonly nodeStates: Record; readonly workflowProjection: WorkflowProjectionState; /** Original root graph-admission snapshot; never derived from post-node context. */ readonly graphAdmission: WorkflowGraphAdmission; } /** * Blob resolver interface */ export interface BlobResolver { getText(ref: BlobRef): Promise; getBytes(ref: BlobRef): Promise; getStream(ref: BlobRef): Promise; stat(ref: BlobRef): Promise; delete(ref: BlobRef): Promise; } /** * Step builder context */ export interface StepBuilderContext { input: TInput; context: WorkflowContext; blobStorage?: BlobStorage; blob?: BlobResolver; } /** * Base node configuration (shared by all node types) */ export interface BaseNodeConfig { /** * Human-readable purpose for this node, surfaced through workflow metadata so * a run view can label the step with something an operator understands rather * than its id. */ description?: string; checkpoint?: boolean; retry?: RetryConfig; timeout?: string | number; skip?: (context: WorkflowContext) => boolean | Promise; } /** * Step node configuration */ export interface StepNodeConfig extends BaseNodeConfig { type: "step"; agent?: string | Agent; tool?: string | Tool; input?: string | Record | ((context: WorkflowContext) => unknown); } /** * Parallel node configuration */ export interface ParallelNodeConfig extends BaseNodeConfig { type: "parallel"; nodes: WorkflowNode[]; strategy?: ParallelStrategy; } /** * Branch node configuration */ export interface BranchNodeConfig extends BaseNodeConfig { type: "branch"; condition: (context: WorkflowContext) => boolean | Promise; then: WorkflowNode[]; else?: WorkflowNode[]; } /** * Wait node configuration */ export interface WaitNodeConfig extends BaseNodeConfig { type: "wait"; waitType: WaitType; message?: string; payload?: unknown | ((context: WorkflowContext) => unknown); /** * Explicit identities allowed to decide the approval. When omitted, the * authenticated host boundary is responsible for supplying the caller's * canonical identity to the approval API. */ approvers?: string[]; eventName?: string; /** * Shape a human's structured answer must satisfy. Validated when the decision * is submitted, so a non-conformant answer is refused rather than persisted. * Held in the registered definition rather than the run record -- a schema is * not serializable. */ responseSchema?: Schema; } /** * Durable record of a run parked on a `waitForEvent` or `delay` node. * * A parked event wait is the event-side counterpart of a pending approval: it * is what a later `publishEvent` is matched against, and what the timeout * reconciler finds when the declared timeout elapses. Without a persisted * record, a parked run is indistinguishable from a stalled one. */ export interface PendingEventWait { id: string; runId: string; nodeId: string; /** Event name that releases this wait. A delay carries the reserved internal name. */ eventName: string; /** Whether the node was declared with `delay()` or `waitForEvent()`. */ waitKind: DurableTimedWaitKind; requestedAt: Date; /** Deadline derived from the node's declared `timeout`, when it declared one. */ expiresAt?: Date; status: "pending" | "delivered" | "expired" | "cancelled"; } /** * Sub-workflow node configuration */ export interface SubWorkflowNodeConfig extends BaseNodeConfig { type: "subWorkflow"; workflow: string | WorkflowDefinition; input?: unknown | ((context: WorkflowContext) => unknown); output?: (result: unknown) => unknown; } /** * Map node configuration */ export interface MapNodeConfig extends BaseNodeConfig { type: "map"; items: unknown[] | ((context: WorkflowContext) => unknown[] | Promise); processor: WorkflowNode | WorkflowDefinition; concurrency?: number; } /** * Loop node configuration */ export interface LoopNodeConfig extends BaseNodeConfig { type: "loop"; while: (context: WorkflowContext, loop: LoopExecutionContext) => boolean | Promise; steps: WorkflowNode[] | ((context: WorkflowContext, loop: LoopExecutionContext) => WorkflowNode[]); maxIterations: number; onMaxIterations?: (context: WorkflowContext, loop: LoopExecutionContext) => Record | Promise>; onComplete?: (context: WorkflowContext, loop: LoopExecutionContext) => Record | Promise>; iterationTimeout?: string | number; delay?: number | string; } /** * Union of all workflow node configurations */ export type WorkflowNodeConfig = StepNodeConfig | ParallelNodeConfig | MapNodeConfig | BranchNodeConfig | WaitNodeConfig | SubWorkflowNodeConfig | LoopNodeConfig; /** * Workflow node */ export interface WorkflowNode { id: string; config: WorkflowNodeConfig; dependsOn?: string[]; } /** * Workflow definition */ export interface WorkflowDefinition { id: string; description?: string; /** Required for a persisted run to be safely resumed after its initial start admission. */ version?: string; inputSchema?: Schema; outputSchema?: Schema; /** Explicit integration scopes and resources required by scheduled runs. */ integrationRequirements?: ScheduleIntegrationRequirementConfig[]; retry?: RetryConfig; timeout?: string | number; introspect?: boolean; steps: WorkflowNode[] | ((context: StepBuilderContext) => WorkflowNode[]); onError?: (error: Error, context: WorkflowContext) => void | Promise; onComplete?: (result: TOutput, context: WorkflowContext) => void | Promise; } /** * Workflow instance */ export interface Workflow { definition: WorkflowDefinition; id: string; version?: string; } /** * Captured tenant context for multi-tenant workflow execution. * Allows tools and framework utilities to access the current tenant * without explicit parameter passing. */ export interface CapturedTenantContext { /** Project slug identifying the tenant */ projectSlug: string; /** OAuth token for API access */ token: string; /** Optional project ID (UUID) */ projectId?: string; /** Whether running in production mode */ productionMode: boolean; /** Release ID for production deployments */ releaseId?: string | null; /** Branch name or ID for preview mode */ branch?: string | null; /** Environment name associated with this tenant context */ environmentName?: string | null; } /** * Workflow run state */ export interface WorkflowRun { id: string; workflowId: string; /** Immutable definition version; persisted recovery requires a non-null exact match. */ version?: string; status: WorkflowStatus; input: TInput; output?: TOutput; nodeStates: Record; /** * Nodes the run is occupied with right now: the top-level batch it is * executing while `running`, the node it is parked on while `waiting` (which * can be a child of a composite), and empty once it completes. A failed run * keeps the nodes in its terminal batch that failed or were still running. A * cancelled run keeps the last recorded value, so both terminal states still * name where execution stopped. */ currentNodes: string[]; context: WorkflowContext; checkpoints: Checkpoint[]; pendingApprovals: PendingApproval[]; error?: WorkflowError; createdAt: Date; startedAt?: Date; /** Last heartbeat timestamp for liveness detection in distributed workers */ heartbeatAt?: Date; completedAt?: Date; /** Exact source-owned integration restriction captured when this run was created. */ readonly sourceIntegrationPolicy: SourceIntegrationPolicyManifest; /** Worker ID for distributed execution */ workerId?: string; /** Captured tenant context for multi-tenant job execution */ _tenant?: CapturedTenantContext; /** * @internal W3C `traceparent` of the most recent execution's `workflow.run` * span. A run that parks and resumes traces once per execution; the next * execution links back to this so the executions stay joined. */ _traceContext?: string; /** @internal Immutable durable provenance model version. */ _runtimeStateVersion?: number; /** @internal Framework-only public projection ownership sidecar. */ _workflowProjection?: WorkflowProjectionState; } /** Whether a value is a non-empty approval identity without surrounding whitespace. */ export declare function isCanonicalApprovalIdentity(value: unknown): value is string; /** Validate and snapshot an optional explicit approval allowlist. */ export declare function captureApprovalApprovers(value: unknown, label?: string): string[] | undefined; /** * Maximum retry attempts accepted by executable workflow nodes. * * This matches the loop iteration ceiling and prevents configurations that can * consume effectively unbounded worker time or overflow exponential backoff * arithmetic before the configured maximum delay is applied. */ export declare const MAX_WORKFLOW_RETRY_ATTEMPTS = 100; /** * Parse duration string to milliseconds */ export declare function parseDuration(duration: string | number): number; /** * Parse a duration with a boundary-specific label for actionable errors. * * @internal */ export declare function parseDurationWithLabel(duration: string | number, label: string): number; /** * Parse a duration that represents a timeout or interval and therefore cannot * use zero to mean "disabled". * * @internal */ export declare function parsePositiveDurationWithLabel(duration: string | number, label: string): number; /** * Validate retry configuration */ export declare function validateRetryConfig(config: RetryConfig, label?: string): void; /** * Generate a unique workflow ID */ export declare function generateId(prefix?: string): string; //# sourceMappingURL=types.d.ts.map