@drej/core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ /** Base class for all drej workflow runtime errors. */
2
+ export declare class WorkflowError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ /** Thrown when a sandbox fails to create, boot, or reach `Running` state. */
6
+ export declare class SandboxError extends WorkflowError {
7
+ /** The sandbox ID, if one was assigned before the failure. */
8
+ readonly sandboxId?: string | undefined;
9
+ constructor(message: string,
10
+ /** The sandbox ID, if one was assigned before the failure. */
11
+ sandboxId?: string | undefined);
12
+ }
13
+ /**
14
+ * Thrown when execd inside a sandbox never becomes ready within the retry window.
15
+ * The sandbox is `Running` from the control plane's perspective, but the exec
16
+ * daemon is not accepting connections.
17
+ */
18
+ export declare class ExecConnectionError extends WorkflowError {
19
+ readonly sandboxId: string;
20
+ constructor(sandboxId: string);
21
+ }
22
+ /**
23
+ * Thrown when an `exec()` step exits with a non-zero exit code and the
24
+ * `strict` option is enabled. Carries the exit code and original command.
25
+ */
26
+ export declare class CommandError extends WorkflowError {
27
+ readonly exitCode: number;
28
+ readonly command: string;
29
+ readonly sandboxId: string;
30
+ constructor(exitCode: number, command: string, sandboxId: string);
31
+ }
@@ -0,0 +1,10 @@
1
+ export { LedgerEvent } from "./ledger";
2
+ export type { LedgerEntry, IStorageAdapter } from "./ledger";
3
+ export { LogLevel, ConsoleLogger, noopLogger } from "./logger";
4
+ export type { ILogger } from "./logger";
5
+ export { Workflow, WorkflowStatus } from "./workflow";
6
+ export type { WorkflowRunContext, WorkflowStep, WorkflowCheckpoint, WorkflowDeps, WorkflowHooks, } from "./workflow";
7
+ export { buildStep, resolveExecClient, shouldSnapshot, waitForSnapshot } from "./steps";
8
+ export type { StepDef, Predicate, WorkflowState, SnapshotConfig } from "./steps";
9
+ export { validateWorkflow } from "./validate";
10
+ export { WorkflowError, SandboxError, ExecConnectionError, CommandError } from "./errors";
@@ -0,0 +1,67 @@
1
+ /** Events emitted during workflow execution and stored in the ledger. */
2
+ export declare enum LedgerEvent {
3
+ /** Emitted once when a workflow run starts, before any steps execute. */
4
+ RunStarted = "run_started",
5
+ /** Emitted at the beginning of each step. */
6
+ StepStart = "step_start",
7
+ /** Emitted when a step finishes successfully. */
8
+ StepComplete = "step_complete",
9
+ /** Emitted when a step throws an unrecoverable error. */
10
+ StepFailed = "step_failed",
11
+ /** Emitted when a step's rollback handler completes during saga compensation. */
12
+ StepRolledBack = "step_rolled_back",
13
+ /** Emitted after all steps finish without error. */
14
+ WorkflowComplete = "workflow_complete",
15
+ /** Emitted after rollback completes following a step failure. */
16
+ WorkflowFailed = "workflow_failed",
17
+ /** Durable resumption point written after each successful step. */
18
+ Checkpoint = "checkpoint",
19
+ /** Streaming output chunk from `exec()` or `execCode()`. */
20
+ ExecEvent = "exec_event",
21
+ /** Emitted when a sandbox snapshot is captured mid-run. */
22
+ Snapshot = "snapshot"
23
+ }
24
+ /** A single event record written to the storage adapter during a workflow run. */
25
+ export interface LedgerEntry {
26
+ /** Unix timestamp in milliseconds. */
27
+ ts: number;
28
+ workflowName: string;
29
+ runId: string;
30
+ /** Zero-based index of the step that produced this event. `-1` for run-level events. */
31
+ stepIndex: number;
32
+ /** Parallel branch index, when this step is inside a `parallel()` block. */
33
+ branch?: number;
34
+ event: LedgerEvent;
35
+ /** Event-specific data (step output, snapshot ID, exec text, etc.). */
36
+ payload?: unknown;
37
+ /** Error message when `event` is `StepFailed` or `WorkflowFailed`. */
38
+ error?: string;
39
+ }
40
+ /**
41
+ * Persistence interface for workflow event storage.
42
+ *
43
+ * Implement this interface to plug in any storage backend. drej ships two
44
+ * official implementations: `@drej/sqlite` (local dev, zero infra) and
45
+ * `@drej/postgres` (production).
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * import { SQLiteAdapter } from "@drej/sqlite";
50
+ * const client = new DrejClient({ baseUrl, adapter: new SQLiteAdapter("./drej.db") });
51
+ * await client.connect();
52
+ * ```
53
+ */
54
+ export interface IStorageAdapter {
55
+ /** Run migrations / open connections. Must be called before first use. */
56
+ connect?(): Promise<void>;
57
+ /** Release connections and resources. Call on graceful shutdown. */
58
+ close?(): Promise<void>;
59
+ /** Persist a single ledger event. Called automatically during workflow execution. */
60
+ append(entry: LedgerEntry): Promise<void>;
61
+ /** Return all events for a specific run, in ascending timestamp order. */
62
+ readAll(workflowName: string, runId: string): Promise<LedgerEntry[]>;
63
+ /** Return the most recent checkpoint entry for a run, or `null` if none exists. */
64
+ lastCheckpoint(workflowName: string, runId: string): Promise<LedgerEntry | null>;
65
+ /** Return all run IDs recorded under a workflow name. */
66
+ listRuns(workflowName: string): Promise<string[]>;
67
+ }
@@ -0,0 +1,23 @@
1
+ export declare enum LogLevel {
2
+ Debug = 0,
3
+ Info = 1,
4
+ Warn = 2,
5
+ Error = 3,
6
+ Silent = 4
7
+ }
8
+ export interface ILogger {
9
+ debug(msg: string, meta?: Record<string, unknown>): void;
10
+ info(msg: string, meta?: Record<string, unknown>): void;
11
+ warn(msg: string, meta?: Record<string, unknown>): void;
12
+ error(msg: string, meta?: Record<string, unknown>): void;
13
+ }
14
+ export declare class ConsoleLogger implements ILogger {
15
+ private readonly minLevel;
16
+ constructor(minLevel?: LogLevel);
17
+ private log;
18
+ debug(msg: string, meta?: Record<string, unknown>): void;
19
+ info(msg: string, meta?: Record<string, unknown>): void;
20
+ warn(msg: string, meta?: Record<string, unknown>): void;
21
+ error(msg: string, meta?: Record<string, unknown>): void;
22
+ }
23
+ export declare const noopLogger: ILogger;
@@ -0,0 +1,100 @@
1
+ import { ControlClient, ExecClient } from "@drej/opensandbox";
2
+ import type { WorkflowStep } from "./workflow";
3
+ export type Predicate = {
4
+ op: "eq" | "neq";
5
+ field: string;
6
+ value: unknown;
7
+ } | {
8
+ op: "gt" | "lt" | "gte" | "lte";
9
+ field: string;
10
+ value: number;
11
+ } | {
12
+ op: "exists" | "not_exists";
13
+ field: string;
14
+ } | {
15
+ op: "and" | "or";
16
+ predicates: Predicate[];
17
+ };
18
+ export type StepDef = {
19
+ type: "create_sandbox";
20
+ image?: {
21
+ uri: string;
22
+ auth?: {
23
+ username: string;
24
+ password: string;
25
+ };
26
+ };
27
+ snapshotId?: string;
28
+ timeout?: number;
29
+ entrypoint?: string[];
30
+ env?: Record<string, string>;
31
+ metadata?: Record<string, string>;
32
+ resourceLimits?: {
33
+ cpu?: string;
34
+ memory?: string;
35
+ gpu?: string;
36
+ };
37
+ } | {
38
+ type: "exec_code";
39
+ code: string;
40
+ context?: {
41
+ id: string;
42
+ language: string;
43
+ };
44
+ } | {
45
+ type: "exec_command";
46
+ command: string;
47
+ cwd?: string;
48
+ envs?: Record<string, string>;
49
+ capture?: string;
50
+ strict?: boolean;
51
+ } | {
52
+ type: "delete_sandbox";
53
+ } | {
54
+ type: "write_file";
55
+ path: string;
56
+ content: string;
57
+ encoding?: "utf8" | "base64";
58
+ } | {
59
+ type: "read_file";
60
+ path: string;
61
+ as: string;
62
+ encoding?: "utf8" | "base64";
63
+ } | {
64
+ type: "snapshot";
65
+ } | {
66
+ type: "retry";
67
+ step: StepDef;
68
+ maxAttempts: number;
69
+ delayMs?: number;
70
+ backoff?: "fixed" | "exponential";
71
+ } | {
72
+ type: "conditional";
73
+ condition: Predicate;
74
+ then: StepDef[];
75
+ else?: StepDef[];
76
+ } | {
77
+ type: "loop";
78
+ over?: string;
79
+ items?: unknown[];
80
+ as: string;
81
+ steps: StepDef[];
82
+ concurrently?: boolean;
83
+ } | {
84
+ type: "parallel";
85
+ steps: StepDef[];
86
+ } | {
87
+ type: "sequence";
88
+ steps: StepDef[];
89
+ };
90
+ export type WorkflowState = Record<string, unknown> & {
91
+ sandboxId?: string;
92
+ };
93
+ export interface SnapshotConfig {
94
+ afterSteps?: number[];
95
+ everyNSteps?: number;
96
+ }
97
+ export declare function resolveExecClient(control: ControlClient, sandboxId: string, retries?: number, delayMs?: number): Promise<ExecClient>;
98
+ export declare function shouldSnapshot(config: SnapshotConfig, stepIndex: number): boolean;
99
+ export declare function waitForSnapshot(control: ControlClient, snapshotId: string, timeoutMs?: number): Promise<void>;
100
+ export declare function buildStep(def: StepDef): WorkflowStep;
@@ -0,0 +1,2 @@
1
+ import type { StepDef } from "./steps";
2
+ export declare function validateWorkflow(name: string, steps: StepDef[]): void;
@@ -0,0 +1,99 @@
1
+ import type { IStorageAdapter, LedgerEntry } from "./ledger";
2
+ import type { ControlClient, ExecClient } from "@drej/opensandbox";
3
+ import type { ILogger } from "./logger";
4
+ export interface WorkflowRunContext {
5
+ readonly workflowName: string;
6
+ readonly runId: string;
7
+ readonly stepIndex: number;
8
+ readonly control: ControlClient;
9
+ readonly resolveExec: (sandboxId: string) => Promise<ExecClient>;
10
+ emit(entry: LedgerEntry): Promise<void>;
11
+ }
12
+ export interface WorkflowStep {
13
+ readonly id: string;
14
+ run(input: unknown, ctx: WorkflowRunContext): Promise<unknown>;
15
+ rollback?(output: unknown, ctx: WorkflowRunContext): Promise<void>;
16
+ }
17
+ export interface WorkflowCheckpoint {
18
+ workflowName: string;
19
+ runId: string;
20
+ stepIndex: number;
21
+ completedSteps: Record<number, {
22
+ output: unknown;
23
+ completedAt: number;
24
+ }>;
25
+ timestamp: number;
26
+ }
27
+ export declare enum WorkflowStatus {
28
+ Idle = "idle",
29
+ Running = "running",
30
+ Completed = "completed",
31
+ Failed = "failed",
32
+ RolledBack = "rolled_back"
33
+ }
34
+ export interface WorkflowHooks {
35
+ onStepStart?(info: {
36
+ workflowName: string;
37
+ runId: string;
38
+ stepIndex: number;
39
+ stepId: string;
40
+ }): void | Promise<void>;
41
+ onStepComplete?(info: {
42
+ workflowName: string;
43
+ runId: string;
44
+ stepIndex: number;
45
+ stepId: string;
46
+ output: unknown;
47
+ }): void | Promise<void>;
48
+ onStepFailed?(info: {
49
+ workflowName: string;
50
+ runId: string;
51
+ stepIndex: number;
52
+ stepId: string;
53
+ error: Error;
54
+ }): void | Promise<void>;
55
+ onStepRolledBack?(info: {
56
+ workflowName: string;
57
+ runId: string;
58
+ stepIndex: number;
59
+ stepId: string;
60
+ }): void | Promise<void>;
61
+ onWorkflowComplete?(info: {
62
+ workflowName: string;
63
+ runId: string;
64
+ output: unknown;
65
+ }): void | Promise<void>;
66
+ onWorkflowFailed?(info: {
67
+ workflowName: string;
68
+ runId: string;
69
+ error: Error;
70
+ }): void | Promise<void>;
71
+ }
72
+ export interface WorkflowDeps {
73
+ control: ControlClient;
74
+ resolveExec: (sandboxId: string) => Promise<ExecClient>;
75
+ adapter: IStorageAdapter;
76
+ logger?: ILogger;
77
+ hooks?: WorkflowHooks;
78
+ }
79
+ export declare class Workflow {
80
+ private readonly steps;
81
+ private readonly deps;
82
+ readonly name: string;
83
+ readonly runId: string;
84
+ private _status;
85
+ private readonly completedSteps;
86
+ private readonly log;
87
+ get status(): WorkflowStatus;
88
+ constructor(name: string, runId: string, steps: WorkflowStep[], deps: WorkflowDeps);
89
+ private callHook;
90
+ run(input: unknown, startFromStep?: number): Promise<unknown>;
91
+ rollback(toStep?: number): Promise<void>;
92
+ snapshot(): WorkflowCheckpoint;
93
+ static resumeFromLedger(workflowName: string, runId: string, steps: WorkflowStep[], deps: WorkflowDeps): Promise<{
94
+ workflow: Workflow;
95
+ nextStep: number;
96
+ lastOutput: unknown;
97
+ }>;
98
+ private makeContext;
99
+ }
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@drej/core",
3
+ "version": "0.2.0",
4
+ "main": "./src/index.ts",
5
+ "types": "./dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "publishConfig": { "access": "public" },
10
+ "scripts": {
11
+ "build:types": "tsc --project tsconfig.build.json"
12
+ },
13
+ "dependencies": {
14
+ "@drej/opensandbox": "workspace:*"
15
+ },
16
+ "devDependencies": {
17
+ "bun-types": "latest",
18
+ "typescript": "latest"
19
+ }
20
+ }