@positronic/core 0.0.1

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.
Files changed (53) hide show
  1. package/.swcrc +31 -0
  2. package/dist/src/adapters/types.js +16 -0
  3. package/dist/src/clients/types.js +1 -0
  4. package/dist/src/dsl/constants.js +15 -0
  5. package/dist/src/dsl/extensions.js +19 -0
  6. package/dist/src/dsl/json-patch.js +30 -0
  7. package/dist/src/dsl/types.js +1 -0
  8. package/dist/src/dsl/workflow-runner.js +93 -0
  9. package/dist/src/dsl/workflow.js +308 -0
  10. package/dist/src/file-stores/local-file-store.js +12 -0
  11. package/dist/src/file-stores/types.js +1 -0
  12. package/dist/src/index.js +10 -0
  13. package/dist/src/utils/temp-files.js +27 -0
  14. package/dist/types/adapters/types.d.ts +10 -0
  15. package/dist/types/adapters/types.d.ts.map +1 -0
  16. package/dist/types/clients/types.d.ts +10 -0
  17. package/dist/types/clients/types.d.ts.map +1 -0
  18. package/dist/types/dsl/constants.d.ts +16 -0
  19. package/dist/types/dsl/constants.d.ts.map +1 -0
  20. package/dist/types/dsl/extensions.d.ts +18 -0
  21. package/dist/types/dsl/extensions.d.ts.map +1 -0
  22. package/dist/types/dsl/json-patch.d.ts +11 -0
  23. package/dist/types/dsl/json-patch.d.ts.map +1 -0
  24. package/dist/types/dsl/types.d.ts +14 -0
  25. package/dist/types/dsl/types.d.ts.map +1 -0
  26. package/dist/types/dsl/workflow-runner.d.ts +28 -0
  27. package/dist/types/dsl/workflow-runner.d.ts.map +1 -0
  28. package/dist/types/dsl/workflow.d.ts +118 -0
  29. package/dist/types/dsl/workflow.d.ts.map +1 -0
  30. package/dist/types/file-stores/local-file-store.d.ts +7 -0
  31. package/dist/types/file-stores/local-file-store.d.ts.map +1 -0
  32. package/dist/types/file-stores/types.d.ts +4 -0
  33. package/dist/types/file-stores/types.d.ts.map +1 -0
  34. package/dist/types/index.d.ts +12 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/utils/temp-files.d.ts +12 -0
  37. package/dist/types/utils/temp-files.d.ts.map +1 -0
  38. package/package.json +21 -0
  39. package/src/adapters/types.ts +24 -0
  40. package/src/clients/types.ts +14 -0
  41. package/src/dsl/constants.ts +16 -0
  42. package/src/dsl/extensions.ts +58 -0
  43. package/src/dsl/json-patch.ts +27 -0
  44. package/src/dsl/types.ts +13 -0
  45. package/src/dsl/workflow-runner.test.ts +203 -0
  46. package/src/dsl/workflow-runner.ts +146 -0
  47. package/src/dsl/workflow.test.ts +1435 -0
  48. package/src/dsl/workflow.ts +554 -0
  49. package/src/file-stores/local-file-store.ts +11 -0
  50. package/src/file-stores/types.ts +3 -0
  51. package/src/index.ts +22 -0
  52. package/src/utils/temp-files.ts +46 -0
  53. package/tsconfig.json +10 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-patch.d.ts","sourceRoot":"","sources":["../../../src/dsl/json-patch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAE3C;;GAEG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,GAAG,SAAS,CAKzE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,GAAG,SAAS,EAAE,GAAG,KAAK,CAQlF"}
@@ -0,0 +1,14 @@
1
+ export type JsonPrimitive = string | number | boolean | null;
2
+ export type JsonArray = JsonValue[];
3
+ export type JsonObject = {
4
+ [Key in string]?: JsonValue;
5
+ };
6
+ export type JsonValue = JsonPrimitive | JsonArray | JsonObject;
7
+ export type State = JsonObject;
8
+ export type JsonPatch = {
9
+ op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';
10
+ path: string;
11
+ value?: JsonValue;
12
+ from?: string;
13
+ }[];
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/dsl/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;AACpC,MAAM,MAAM,UAAU,GAAG;KAAG,GAAG,IAAI,MAAM,CAAC,CAAC,EAAE,SAAS;CAAE,CAAC;AACzD,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;AAE/D,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC;AAE/B,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { Adapter } from "../adapters/types";
2
+ import type { FileStore } from "../file-stores/types";
3
+ import type { SerializedStep, Workflow } from './workflow';
4
+ import type { State } from './types';
5
+ import type { PromptClient } from '../clients/types';
6
+ interface Logger {
7
+ log(...args: any[]): void;
8
+ }
9
+ export declare class WorkflowRunner {
10
+ private options;
11
+ constructor(options: {
12
+ adapters: Adapter[];
13
+ fileStore: FileStore;
14
+ logger: Logger;
15
+ verbose: boolean;
16
+ client: PromptClient;
17
+ });
18
+ run<TOptions extends object = {}, TState extends State = {}>(workflow: Workflow<TOptions, TState>, { initialState, options, initialCompletedSteps, workflowRunId, endAfter }?: {
19
+ initialState?: TState;
20
+ options?: TOptions;
21
+ initialCompletedSteps?: SerializedStep[] | never;
22
+ workflowRunId?: string | never;
23
+ endAfter?: number;
24
+ }): Promise<void>;
25
+ private truncateDeep;
26
+ }
27
+ export {};
28
+ //# sourceMappingURL=workflow-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-runner.d.ts","sourceRoot":"","sources":["../../../src/dsl/workflow-runner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,UAAU,MAAM;IACd,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;CAC3B;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE;QACf,QAAQ,EAAE,OAAO,EAAE,CAAC;QACpB,SAAS,EAAE,SAAS,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,YAAY,CAAA;KACrB;IAGG,GAAG,CACP,QAAQ,SAAS,MAAM,GAAG,EAAE,EAC5B,MAAM,SAAS,KAAK,GAAG,EAAE,EAEzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,EACpC,EACE,YAA2B,EAC3B,OAAO,EACP,qBAAqB,EACrB,aAAa,EACb,QAAQ,EACT,GAAE;QACD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,OAAO,CAAC,EAAE,QAAQ,CAAC;QACnB,qBAAqB,CAAC,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;QACjD,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;QAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;KACb;IAkER,OAAO,CAAC,YAAY;CAuCrB"}
@@ -0,0 +1,118 @@
1
+ import { z } from "zod";
2
+ import type { PromptClient } from "../clients/types";
3
+ import type { State, JsonPatch } from "./types";
4
+ import { STATUS, WORKFLOW_EVENTS } from './constants';
5
+ import type { FileStore } from "../file-stores/types";
6
+ export type SerializedError = {
7
+ name: string;
8
+ message: string;
9
+ stack?: string;
10
+ };
11
+ interface BaseEvent<TOptions extends object = {}> {
12
+ type: typeof WORKFLOW_EVENTS[keyof typeof WORKFLOW_EVENTS];
13
+ options: TOptions;
14
+ workflowRunId: string;
15
+ }
16
+ interface WorkflowBaseEvent<TOptions extends object = {}> extends BaseEvent<TOptions> {
17
+ workflowTitle: string;
18
+ workflowDescription?: string;
19
+ }
20
+ export interface WorkflowStartEvent<TOptions extends object = {}> extends WorkflowBaseEvent<TOptions> {
21
+ type: typeof WORKFLOW_EVENTS.START | typeof WORKFLOW_EVENTS.RESTART;
22
+ initialState: State;
23
+ status: typeof STATUS.RUNNING;
24
+ }
25
+ export interface WorkflowCompleteEvent<TOptions extends object = {}> extends WorkflowBaseEvent<TOptions> {
26
+ type: typeof WORKFLOW_EVENTS.COMPLETE;
27
+ status: typeof STATUS.COMPLETE;
28
+ }
29
+ export interface WorkflowErrorEvent<TOptions extends object = {}> extends WorkflowBaseEvent<TOptions> {
30
+ type: typeof WORKFLOW_EVENTS.ERROR;
31
+ status: typeof STATUS.ERROR;
32
+ error: SerializedError;
33
+ }
34
+ export interface StepStatusEvent<TOptions extends object = {}> extends BaseEvent<TOptions> {
35
+ type: typeof WORKFLOW_EVENTS.STEP_STATUS;
36
+ steps: SerializedStep[];
37
+ }
38
+ export interface StepStartedEvent<TOptions extends object = {}> extends BaseEvent<TOptions> {
39
+ type: typeof WORKFLOW_EVENTS.STEP_START;
40
+ status: typeof STATUS.RUNNING;
41
+ stepTitle: string;
42
+ stepId: string;
43
+ }
44
+ export interface StepCompletedEvent<TOptions extends object = {}> extends BaseEvent<TOptions> {
45
+ type: typeof WORKFLOW_EVENTS.STEP_COMPLETE;
46
+ status: typeof STATUS.RUNNING;
47
+ stepTitle: string;
48
+ stepId: string;
49
+ patch: JsonPatch;
50
+ }
51
+ export type WorkflowEvent<TOptions extends object = {}> = WorkflowStartEvent<TOptions> | WorkflowCompleteEvent<TOptions> | WorkflowErrorEvent<TOptions> | StepStatusEvent<TOptions> | StepStartedEvent<TOptions> | StepCompletedEvent<TOptions>;
52
+ export interface SerializedStep {
53
+ title: string;
54
+ status: typeof STATUS[keyof typeof STATUS];
55
+ id: string;
56
+ patch?: JsonPatch;
57
+ }
58
+ interface BaseRunParams<TOptions extends object = {}> {
59
+ fileStore: FileStore;
60
+ client: PromptClient;
61
+ options?: TOptions;
62
+ }
63
+ export interface InitialRunParams<TOptions extends object = {}> extends BaseRunParams<TOptions> {
64
+ initialState?: State;
65
+ initialCompletedSteps?: never;
66
+ workflowRunId?: never;
67
+ }
68
+ export interface RerunParams<TOptions extends object = {}> extends BaseRunParams<TOptions> {
69
+ initialState: State;
70
+ initialCompletedSteps: SerializedStep[];
71
+ workflowRunId: string;
72
+ }
73
+ export declare class Workflow<TOptions extends object = {}, TState extends State = {}> {
74
+ readonly title: string;
75
+ private description?;
76
+ private blocks;
77
+ type: 'workflow';
78
+ constructor(title: string, description?: string | undefined);
79
+ step<TNewState extends State>(title: string, action: (params: {
80
+ state: TState;
81
+ options: TOptions;
82
+ client: PromptClient;
83
+ fileStore: FileStore;
84
+ }) => TNewState | Promise<TNewState>): Workflow<TOptions, TNewState>;
85
+ workflow<TInnerState extends State, TNewState extends State>(title: string, innerWorkflow: Workflow<TOptions, TInnerState>, action: (params: {
86
+ state: TState;
87
+ workflowState: TInnerState;
88
+ }) => TNewState, initialState?: State | ((state: TState) => State)): Workflow<TOptions, TNewState>;
89
+ prompt<TResponseKey extends string & {
90
+ readonly brand?: unique symbol;
91
+ }, TSchema extends z.ZodObject<any>, TNewState extends State = TState & {
92
+ [K in TResponseKey]: z.infer<TSchema>;
93
+ }>(title: string, config: {
94
+ template: (state: TState) => string;
95
+ responseModel: {
96
+ schema: TSchema;
97
+ name: TResponseKey & (string extends TResponseKey ? never : unknown);
98
+ };
99
+ client?: PromptClient;
100
+ }, reduce?: (params: {
101
+ state: TState;
102
+ response: z.infer<TSchema>;
103
+ options: TOptions;
104
+ prompt: string;
105
+ }) => TNewState | Promise<TNewState>): Workflow<TOptions, TNewState>;
106
+ run(params: InitialRunParams<TOptions>): AsyncGenerator<WorkflowEvent<TOptions>>;
107
+ run(params: RerunParams<TOptions>): AsyncGenerator<WorkflowEvent<TOptions>>;
108
+ private withBlocks;
109
+ private nextWorkflow;
110
+ }
111
+ export declare function disableWorkflowNameUniqueness(): void;
112
+ export declare function enableWorkflowNameUniqueness(): void;
113
+ export declare function workflow<TOptions extends object = {}, TState extends State = {}>(workflowConfig: string | {
114
+ title: string;
115
+ description?: string;
116
+ }): Workflow<TOptions, TState>;
117
+ export {};
118
+ //# sourceMappingURL=workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../../src/dsl/workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { FileStore } from './types';
2
+ export declare class LocalFileStore implements FileStore {
3
+ private baseDir;
4
+ constructor(baseDir: string);
5
+ readFile(path: string): Promise<string>;
6
+ }
7
+ //# sourceMappingURL=local-file-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-file-store.d.ts","sourceRoot":"","sources":["../../../src/file-stores/local-file-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,cAAe,YAAW,SAAS;IAClC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI9C"}
@@ -0,0 +1,4 @@
1
+ export interface FileStore {
2
+ readFile(path: string): Promise<string>;
3
+ }
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/file-stores/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzC"}
@@ -0,0 +1,12 @@
1
+ export { Workflow, workflow } from "./dsl/workflow";
2
+ export { WorkflowRunner } from "./dsl/workflow-runner";
3
+ export { createExtension } from "./dsl/extensions";
4
+ export { STATUS, WORKFLOW_EVENTS } from "./dsl/constants";
5
+ export { Adapter } from "./adapters/types";
6
+ export type { WorkflowEvent, SerializedStep, InitialRunParams, RerunParams, WorkflowStartEvent, WorkflowCompleteEvent, WorkflowErrorEvent, StepStatusEvent, StepStartedEvent, StepCompletedEvent } from "./dsl/workflow";
7
+ export type { PromptClient, ResponseModel } from "./clients/types";
8
+ export type { State } from "./dsl/types";
9
+ export type { FileStore } from "./file-stores/types";
10
+ export { createPatch, applyPatches } from "./dsl/json-patch";
11
+ export { LocalFileStore } from "./file-stores/local-file-store";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,YAAY,EACV,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Writes content to a temporary file and opens it in cursor
3
+ */
4
+ export declare function writeAndOpenTemp(content: string, prefix: string, extension?: string): Promise<string>;
5
+ /**
6
+ * Writes both prompt and response to temp files and opens them in cursor
7
+ */
8
+ export declare function writePromptAndResponse(prompt: string, response: unknown, prefix?: string): Promise<{
9
+ promptPath: string;
10
+ responsePath: string;
11
+ }>;
12
+ //# sourceMappingURL=temp-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../../src/utils/temp-files.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAc,GACxB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,EACjB,MAAM,GAAE,MAAgB,GACvB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CASvD"}
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@positronic/core",
3
+ "version": "0.0.1",
4
+ "description": "A DSL for AI Workflows",
5
+ "type": "module",
6
+ "main": "dist/src/index.js",
7
+ "types": "dist/types/index.d.ts",
8
+ "scripts": {
9
+ "tsc": "tsc --project tsconfig.json",
10
+ "build": "npm run tsc && swc src -d dist",
11
+ "clean": "rm -rf tsconfig.tsbuildinfo dist"
12
+ },
13
+ "dependencies": {
14
+ "fast-json-patch": "^3.1.1",
15
+ "uuid": "^11.0.5",
16
+ "zod": "^3.24.1"
17
+ },
18
+ "devDependencies": {
19
+ "@types/uuid": "^10.0.0"
20
+ }
21
+ }
@@ -0,0 +1,24 @@
1
+ import { WORKFLOW_EVENTS } from '../dsl/constants';
2
+ import type { WorkflowEvent } from '../dsl/workflow';
3
+
4
+ export abstract class Adapter<Options extends object = any> {
5
+ async started?(event: WorkflowEvent<Options>): Promise<void>;
6
+ async updated?(event: WorkflowEvent<Options>): Promise<void>;
7
+ async completed?(event: WorkflowEvent<Options>): Promise<void>;
8
+ async error?(event: WorkflowEvent<Options>): Promise<void>;
9
+ async restarted?(event: WorkflowEvent<Options>): Promise<void>;
10
+
11
+ async dispatch(event: WorkflowEvent<Options>) {
12
+ if (event.type === WORKFLOW_EVENTS.START && this.started) {
13
+ await this.started(event);
14
+ } else if (event.type === WORKFLOW_EVENTS.STEP_COMPLETE && this.updated) {
15
+ await this.updated(event);
16
+ } else if (event.type === WORKFLOW_EVENTS.COMPLETE && this.completed) {
17
+ await this.completed(event);
18
+ } else if (event.type === WORKFLOW_EVENTS.ERROR && this.error) {
19
+ await this.error(event);
20
+ } else if (event.type === WORKFLOW_EVENTS.RESTART && this.restarted) {
21
+ await this.restarted(event);
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ import { z } from 'zod';
2
+
3
+ export type ResponseModel<T extends z.AnyZodObject> = {
4
+ schema: T;
5
+ name: string;
6
+ description?: string;
7
+ }
8
+
9
+ export interface PromptClient {
10
+ execute<T extends z.AnyZodObject>(
11
+ prompt: string,
12
+ responseModel: ResponseModel<T>,
13
+ ): Promise<z.infer<T>>;
14
+ }
@@ -0,0 +1,16 @@
1
+ export const WORKFLOW_EVENTS = {
2
+ START: 'workflow:start',
3
+ RESTART: 'workflow:restart',
4
+ STEP_START: 'step:start',
5
+ STEP_COMPLETE: 'step:complete',
6
+ STEP_STATUS: 'step:status',
7
+ ERROR: 'workflow:error',
8
+ COMPLETE: 'workflow:complete',
9
+ } as const;
10
+
11
+ export const STATUS = {
12
+ PENDING: 'pending',
13
+ RUNNING: 'running',
14
+ COMPLETE: 'complete',
15
+ ERROR: 'error',
16
+ } as const;
@@ -0,0 +1,58 @@
1
+ import { Workflow } from "./workflow";
2
+ import type { State } from "./types";
3
+
4
+ type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
5
+
6
+ type ExtensionMethods<
7
+ TExtension extends Record<string, any>,
8
+ TOptions extends object,
9
+ TState extends State
10
+ > = TExtension extends ((...args: any[]) => any)
11
+ ? TExtension extends ((
12
+ this: any,
13
+ title: string,
14
+ config: infer TConfig
15
+ ) => Workflow<any, infer TReturnState>)
16
+ ? (
17
+ title: string,
18
+ config: TConfig extends ((ctx: any) => any)
19
+ ? { [P in keyof TConfig]: TConfig[P] extends Function ? ((ctx: TState) => any) : TConfig[P] }
20
+ : TConfig
21
+ ) => Workflow<TOptions, Expand<TState & TReturnState>>
22
+ : never
23
+ : {
24
+ [K in keyof TExtension]: TExtension[K] extends (
25
+ this: any,
26
+ title: string,
27
+ config: infer TConfig
28
+ ) => Workflow<any, infer TReturnState>
29
+ ? (
30
+ title: string,
31
+ config: TConfig extends ((ctx: any) => any)
32
+ ? { [P in keyof TConfig]: TConfig[P] extends Function ? ((ctx: TState) => any) : TConfig[P] }
33
+ : TConfig
34
+ ) => Workflow<TOptions, Expand<TState & TReturnState>>
35
+ : never;
36
+ };
37
+
38
+ export function createExtension<
39
+ TExtensionKey extends string,
40
+ TExtension extends Record<string, any>
41
+ >(key: TExtensionKey, extension: TExtension) {
42
+ return {
43
+ install() {
44
+ Object.defineProperty(Workflow.prototype, key, {
45
+ get() {
46
+ const boundMethods: Record<string, Function> = {};
47
+ for (const [methodKey, fn] of Object.entries(extension)) {
48
+ boundMethods[methodKey] = fn.bind(this);
49
+ }
50
+ return boundMethods;
51
+ }
52
+ });
53
+ },
54
+ augment<TOptions extends object, TState extends State>(): ExtensionMethods<TExtension, TOptions, TState> {
55
+ return {} as ExtensionMethods<TExtension, TOptions, TState>;
56
+ }
57
+ };
58
+ }
@@ -0,0 +1,27 @@
1
+ import pkg from 'fast-json-patch';
2
+ const { compare, applyPatch } = pkg;
3
+ import { JsonPatch, State } from './types';
4
+
5
+ /**
6
+ * Creates a JSON Patch that describes the changes needed to transform prevState into nextState.
7
+ */
8
+ export function createPatch(prevState: State, nextState: State): JsonPatch {
9
+ // Filter out non-standard operations and ensure type safety
10
+ return compare(prevState, nextState).filter(op =>
11
+ ['add', 'remove', 'replace', 'move', 'copy', 'test'].includes(op.op)
12
+ ) as JsonPatch;
13
+ }
14
+
15
+ /**
16
+ * Applies one or more JSON Patches to a state object and returns the resulting state.
17
+ * If multiple patches are provided, they are applied in sequence.
18
+ */
19
+ export function applyPatches(state: State, patches: JsonPatch | JsonPatch[]): State {
20
+ const patchArray = Array.isArray(patches[0]) ? patches as JsonPatch[] : [patches as JsonPatch];
21
+
22
+ // Apply patches in sequence, creating a new state object each time
23
+ return patchArray.reduce((currentState, patch) => {
24
+ const { newDocument } = applyPatch(currentState, patch as any[], true, false);
25
+ return newDocument;
26
+ }, { ...state });
27
+ }
@@ -0,0 +1,13 @@
1
+ export type JsonPrimitive = string | number | boolean | null;
2
+ export type JsonArray = JsonValue[];
3
+ export type JsonObject = { [Key in string]?: JsonValue };
4
+ export type JsonValue = JsonPrimitive | JsonArray | JsonObject;
5
+
6
+ export type State = JsonObject;
7
+
8
+ export type JsonPatch = {
9
+ op: 'add' | 'remove' | 'replace' | 'move' | 'copy' | 'test';
10
+ path: string;
11
+ value?: JsonValue;
12
+ from?: string;
13
+ }[];
@@ -0,0 +1,203 @@
1
+ import { WorkflowRunner } from './workflow-runner';
2
+ import { workflow } from './workflow';
3
+ import { WORKFLOW_EVENTS, STATUS } from './constants';
4
+ import type { FileStore } from '../file-stores/types';
5
+
6
+ class TestFileStore implements FileStore {
7
+ async readFile(path: string) {
8
+ return Promise.resolve('');
9
+ }
10
+ }
11
+
12
+ describe('WorkflowRunner', () => {
13
+ const mockClient = {
14
+ execute: jest.fn()
15
+ };
16
+
17
+ const mockLogger = {
18
+ log: jest.fn()
19
+ };
20
+
21
+ const mockAdapter = {
22
+ dispatch: jest.fn()
23
+ };
24
+
25
+ const fileStore = new TestFileStore();
26
+
27
+ beforeEach(() => {
28
+ jest.clearAllMocks();
29
+ });
30
+
31
+ it('should run a workflow and dispatch events to adapters', async () => {
32
+ const runner = new WorkflowRunner({
33
+ adapters: [mockAdapter],
34
+ fileStore,
35
+ logger: mockLogger,
36
+ verbose: false,
37
+ client: mockClient
38
+ });
39
+
40
+ const testWorkflow = workflow('Test Workflow')
41
+ .step('First Step', () => ({ value: 42 }))
42
+ .step('Async Step', async ({ state}) => {
43
+ await new Promise(resolve => setTimeout(resolve, 10));
44
+ return { ...state, asyncValue: 'completed' };
45
+ })
46
+ .step('Final Step', ({ state }) => ({
47
+ ...state,
48
+ finalValue: state.value * 2
49
+ }));
50
+
51
+ await runner.run(testWorkflow);
52
+
53
+ // Verify adapter received all events in correct order
54
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
55
+ expect.objectContaining({
56
+ type: WORKFLOW_EVENTS.START,
57
+ workflowTitle: 'Test Workflow'
58
+ })
59
+ );
60
+
61
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
62
+ expect.objectContaining({
63
+ type: WORKFLOW_EVENTS.STEP_COMPLETE,
64
+ stepTitle: 'First Step'
65
+ })
66
+ );
67
+
68
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
69
+ expect.objectContaining({
70
+ type: WORKFLOW_EVENTS.STEP_COMPLETE,
71
+ stepTitle: 'Async Step'
72
+ })
73
+ );
74
+
75
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
76
+ expect.objectContaining({
77
+ type: WORKFLOW_EVENTS.STEP_COMPLETE,
78
+ stepTitle: 'Final Step'
79
+ })
80
+ );
81
+
82
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
83
+ expect.objectContaining({
84
+ type: WORKFLOW_EVENTS.COMPLETE,
85
+ status: STATUS.COMPLETE
86
+ })
87
+ );
88
+
89
+ // Verify the order of events
90
+ const stepCompletions = mockAdapter.dispatch.mock.calls
91
+ .filter(call => call[0].type === WORKFLOW_EVENTS.STEP_COMPLETE)
92
+ .map(call => call[0].stepTitle);
93
+
94
+ expect(stepCompletions).toEqual([
95
+ 'First Step',
96
+ 'Async Step',
97
+ 'Final Step'
98
+ ]);
99
+ });
100
+
101
+ it('should log final state when verbose is true', async () => {
102
+ const runner = new WorkflowRunner({
103
+ adapters: [],
104
+ fileStore,
105
+ logger: mockLogger,
106
+ verbose: true,
107
+ client: mockClient
108
+ });
109
+
110
+ const testWorkflow = workflow('Test Workflow')
111
+ .step('Test Step', () => ({ value: 42 }));
112
+
113
+ await runner.run(testWorkflow);
114
+
115
+ expect(mockLogger.log).toHaveBeenCalledWith(
116
+ expect.stringContaining('Workflow completed:')
117
+ );
118
+ expect(mockLogger.log).toHaveBeenCalledWith(
119
+ expect.stringContaining('"value": 42')
120
+ );
121
+ });
122
+
123
+ it('should handle workflow errors', async () => {
124
+ const runner = new WorkflowRunner({
125
+ adapters: [mockAdapter],
126
+ fileStore,
127
+ logger: mockLogger,
128
+ verbose: true,
129
+ client: mockClient
130
+ });
131
+
132
+ const errorWorkflow = workflow('Error Workflow')
133
+ .step('Error Step', () => {
134
+ throw new Error('Test error');
135
+ });
136
+
137
+ try {
138
+ await runner.run(errorWorkflow);
139
+ } catch (error) {
140
+ // Expected error
141
+ }
142
+
143
+ // Verify error event was dispatched
144
+ expect(mockAdapter.dispatch).toHaveBeenCalledWith(
145
+ expect.objectContaining({
146
+ type: WORKFLOW_EVENTS.ERROR,
147
+ error: expect.objectContaining({
148
+ message: 'Test error'
149
+ })
150
+ })
151
+ );
152
+ });
153
+
154
+ it('should truncate long values in verbose output', async () => {
155
+ const runner = new WorkflowRunner({
156
+ adapters: [],
157
+ fileStore,
158
+ logger: mockLogger,
159
+ verbose: true,
160
+ client: mockClient
161
+ });
162
+
163
+ const longString = 'a'.repeat(1000); // Make string much longer
164
+ const testWorkflow = workflow('Test Workflow')
165
+ .step('Test Step', () => ({
166
+ longString,
167
+ nested: { longString }
168
+ }));
169
+
170
+ await runner.run(testWorkflow);
171
+
172
+ const logCall = mockLogger.log.mock.calls.find(call =>
173
+ call[0].includes('Workflow completed:')
174
+ );
175
+
176
+ expect(logCall[0]).toContain('...');
177
+ expect(logCall[0].length).toBeLessThan(longString.length);
178
+ });
179
+
180
+ it('should maintain state between steps', async () => {
181
+ const runner = new WorkflowRunner({
182
+ adapters: [],
183
+ fileStore,
184
+ logger: mockLogger,
185
+ verbose: true,
186
+ client: mockClient
187
+ });
188
+
189
+ const testWorkflow = workflow('Test Workflow')
190
+ .step('First Step', () => ({ count: 1 }))
191
+ .step('Second Step', ({ state }) => ({
192
+ count: state.count + 1
193
+ }));
194
+
195
+ await runner.run(testWorkflow);
196
+
197
+ const finalLog = mockLogger.log.mock.calls.find(call =>
198
+ call[0].includes('Workflow completed:')
199
+ );
200
+
201
+ expect(finalLog[0]).toContain('"count": 2');
202
+ });
203
+ });