/** * WorkflowContextLite — v3 checkpoint engine backed by NAPI-RS. * * Unlike the v1 WorkflowContext (which throws SuspendExecution and relies on * server redispatch), this context talks directly to the embedded Rust engine. * * Each durable step: * 1. Check in-memory checkpoint map (O(1) lookup) * 2. If memoized → return instantly * 3. If not → call engine via FFI, execute activity in-process, checkpoint result * * No network. No suspension. No redispatch. Just function calls. */ import type { NativeEngine, CheckpointInfo } from '@memoflowio/memoflow-engine'; import type { ActivityOptions, ActivityMethodsOf, ApprovalOptions, LlmStepMeta } from '../types.js'; import { NonDeterminismError } from './step-key.js'; import { type ApprovalDecision } from './approval.js'; import type { ImplicitStepHost } from './runtime-context.js'; import { type HttpEffectRecord, type ImplicitStepsConfig } from './http-effect.js'; export declare function safeTimeout(fn: () => void, ms: number): void; export { NonDeterminismError }; export { approvalSignalName, isApprovalSignal, approvalNameFromSignal, InvalidApprovalPayloadError } from './approval.js'; export type { ApprovalDecision } from './approval.js'; export declare class SignalTimeoutError extends Error { readonly signalName: string; constructor(signalName: string, message?: string); } export declare class SuspendExecution { readonly commands: any[]; constructor(commands: any[]); } export declare class WorkflowContextLite implements ImplicitStepHost { readonly workflowId: string; readonly runId: string; readonly taskQueue: string; private engine; private stepSeq; private stepKeys; /** Occurrence tracker for implicit HTTP steps (P6.1). See WorkflowContext. */ private httpStepKeys; /** Implicit-steps config (P6.1). Defaults make bare fetch durable. */ readonly implicitConfig: ImplicitStepsConfig; private checkpoints; private signalResolvers; /** * step.llm (P3.1) — lite-parity decision: plumbing `meta` through * crates/engine's SQLite checkpoint schema and the NAPI boundary is * disproportionate to this feature (engine-node has no concept of * observability metadata and CheckpointInfo is a fixed native struct). * Meta capture here is TS-side only: kept in-memory per step_seq for the * lifetime of this context, exposed via `getLlmMeta()` for the embedded * dashboard to read directly from the running worker. It does NOT survive * a process restart the way the Postgres-server-backed `meta` column * does — acceptable because it's pure observability, not execution * semantics (Design Law 1 unaffected either way). */ private llmMeta; constructor(workflowId: string, runId: string, taskQueue: string, engine: NativeEngine, checkpoints: CheckpointInfo[], implicitConfig?: Partial); assertImplicitEffectAllowed(): void; /** * Execute a durable activity. If checkpointed, returns memoized result. * Otherwise: checkpoint "started" → execute in-process → checkpoint "completed" → return. */ activity(activityType: string, args: any[], options?: ActivityOptions): Promise; /** * Typed sugar over `activity()` for LLM/AI calls (P3.1 step.llm). Same * step identity semantics as `activity()` — see the server-backed * `WorkflowContext.llm()` for the full rationale. */ llm(activityType: string, args: any[], options?: ActivityOptions): Promise; /** * Read back the LLM meta recorded for a given step (P3.1), if any. Used * by the embedded dashboard to render the per-step LLM panel — see the * lite-parity note on the `llmMeta` field above. */ getLlmMeta(stepSeq: number): LlmStepMeta | undefined; /** All recorded LLM meta for this context, keyed by step_seq. */ getAllLlmMeta(): ReadonlyMap; /** * Durable sleep — timer managed by the Rust engine. */ sleep(duration: string): Promise; /** * Wait for an external signal. */ waitForSignal(signalName: string, options?: { timeout?: string; }): Promise; /** * Human-in-the-loop approval (P3.3) — sugar over `waitForSignal` with a * typed `{ approved, by, comment }` payload. Same signal-name convention * (`approval:{name}`) and validation/error semantics as the server-backed * `WorkflowContext.approval()` — see there for the full rationale. Lite * preserves unassigned approval behavior without a server round-trip, but * rejects options whose security semantics require server-backed IAM. */ approval(name: string, options?: ApprovalOptions): Promise; /** * Deliver a signal to this workflow context (called by the Worker when a signal arrives). */ deliverSignal(signalName: string, payload: any): void; /** * Record a side-effect (non-deterministic value, computed once). */ sideEffect(fn: () => T): Promise; /** See WorkflowContext.nextHttpStepKey. Consumes seq + occurrence index. */ nextHttpStepKey(source: string): { stepSeq: number; stepKey: string; }; /** See WorkflowContext.lookupHttpEffect. */ lookupHttpEffect(stepSeq: number, stepKey: string, method: string, url: string): HttpEffectRecord | undefined; /** * See WorkflowContext.recordHttpEffect. Lite writes the checkpoint through * the embedded engine immediately (and awaits it) — the interceptor awaits * this before delivering the Response, so the checkpoint is durable before * user code sees the result (Design Law 2). `meta` is kept TS-side for the * embedded dashboard, same lite-parity decision as step.llm (see `llmMeta`). */ recordHttpEffect(stepSeq: number, stepKey: string, record: HttpEffectRecord, meta?: Record): Promise; /** * ImplicitStepHost (P6.1): lite runs the workflow straight to completion and * awaits the fetch naturally (no collect-then-suspend drain loop), so there * is nothing to gate on the counter — this is a no-op that satisfies the * interface. */ markHttpInFlight(_delta: number): void; /** See WorkflowContext.idempotencyKey (N2: step key is required; implicit * calls get an interceptor-injected key automatically). */ idempotencyKey(stepKey: string): string; /** See WorkflowContext.raw — non-durable escape-hatch fetch. */ get raw(): { fetch: typeof fetch; }; /** * Create a type-safe proxy for calling activities. */ proxyActivities(activityClass: new (...args: any[]) => T, options?: ActivityOptions): ActivityMethodsOf; get currentStep(): number; isStepCompleted(stepSeq: number): boolean; /** * Execute an activity function directly in-process. * Looks up the activity in the registry, creates an instance, and calls it. */ private executeActivity; }