@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,146 @@
1
+ import { WORKFLOW_EVENTS } from './constants';
2
+ import { applyPatches } from './json-patch';
3
+ import type { Adapter } from "../adapters/types";
4
+ import type { FileStore } from "../file-stores/types";
5
+ import type { SerializedStep, Workflow } from './workflow';
6
+ import type { State } from './types';
7
+ import type { PromptClient } from '../clients/types';
8
+
9
+ interface Logger {
10
+ log(...args: any[]): void;
11
+ }
12
+
13
+ export class WorkflowRunner {
14
+ constructor(
15
+ private options: {
16
+ adapters: Adapter[],
17
+ fileStore: FileStore,
18
+ logger: Logger,
19
+ verbose: boolean,
20
+ client: PromptClient
21
+ }
22
+ ) {}
23
+
24
+ async run<
25
+ TOptions extends object = {},
26
+ TState extends State = {}
27
+ >(
28
+ workflow: Workflow<TOptions, TState>,
29
+ {
30
+ initialState = {} as TState,
31
+ options,
32
+ initialCompletedSteps,
33
+ workflowRunId,
34
+ endAfter
35
+ }: {
36
+ initialState?: TState,
37
+ options?: TOptions,
38
+ initialCompletedSteps?: SerializedStep[] | never,
39
+ workflowRunId?: string | never,
40
+ endAfter?: number
41
+ } = {}
42
+ ) {
43
+ const {
44
+ adapters,
45
+ logger: { log },
46
+ verbose,
47
+ fileStore,
48
+ client,
49
+ } = this.options;
50
+
51
+ let currentState = initialState ?? ({} as TState);
52
+ let stepNumber = 1;
53
+
54
+ // Apply any patches from completed steps
55
+ // to the initial state so that the workflow
56
+ // starts with a state that reflects all of the completed steps.
57
+ // Need to do this when a workflow is restarted with completed steps.
58
+ initialCompletedSteps?.forEach(step => {
59
+ if (step.patch) {
60
+ currentState = applyPatches(currentState, [step.patch]) as TState;
61
+ stepNumber++;
62
+ }
63
+ });
64
+
65
+ const workflowRun = workflowRunId && initialCompletedSteps
66
+ ? workflow.run({ initialState, initialCompletedSteps, workflowRunId, options, client, fileStore })
67
+ : workflow.run({ initialState, options, client, fileStore });
68
+
69
+ for await (const event of workflowRun) {
70
+ // Dispatch event to all adapters
71
+ await Promise.all(
72
+ adapters.map(adapter => adapter.dispatch(event))
73
+ );
74
+
75
+ // Update current state when steps complete
76
+ if (event.type === WORKFLOW_EVENTS.STEP_COMPLETE) {
77
+ if (event.patch) {
78
+ currentState = applyPatches(currentState, [event.patch]) as TState;
79
+ }
80
+
81
+ // Check if we should stop after this step
82
+ if (endAfter && stepNumber >= endAfter) {
83
+ // Log final state if verbose
84
+ if (verbose) {
85
+ log(`\nWorkflow stopped after step ${endAfter} as requested: \n\n ${JSON.stringify(
86
+ this.truncateDeep(structuredClone(currentState)), null, 2
87
+ )}`);
88
+ }
89
+ return;
90
+ }
91
+
92
+ stepNumber++;
93
+ }
94
+
95
+ // Log final state on workflow completion/error if verbose
96
+ if ((
97
+ event.type === WORKFLOW_EVENTS.COMPLETE ||
98
+ event.type === WORKFLOW_EVENTS.ERROR
99
+ ) && verbose) {
100
+ log(`\nWorkflow completed: \n\n ${JSON.stringify(
101
+ this.truncateDeep(structuredClone(currentState)), null, 2
102
+ )}`);
103
+ }
104
+ }
105
+ }
106
+
107
+ private truncateDeep(obj: any, maxLength: number = 100): any {
108
+ if (obj === null || obj === undefined) return obj;
109
+
110
+ if (typeof obj === 'string') {
111
+ return obj.length > maxLength ? obj.slice(0, maxLength) + '...' : obj;
112
+ }
113
+
114
+ if (Array.isArray(obj)) {
115
+ if (obj.length === 0) return obj;
116
+
117
+ let truncatedArray = [];
118
+ let currentLength = 2; // Account for [] brackets
119
+
120
+ for (let i = 0; i < obj.length; i++) {
121
+ const processedItem = this.truncateDeep(obj[i], maxLength);
122
+ const itemStr = JSON.stringify(processedItem);
123
+
124
+ if (currentLength + itemStr.length + (i > 0 ? 1 : 0) > maxLength) {
125
+ truncatedArray.push(`... (${obj.length})`);
126
+ break;
127
+ }
128
+
129
+ truncatedArray.push(processedItem);
130
+ currentLength += itemStr.length + (i > 0 ? 1 : 0); // Add 1 for comma
131
+ }
132
+
133
+ return truncatedArray;
134
+ }
135
+
136
+ if (typeof obj === 'object') {
137
+ const truncated: Record<string, any> = {};
138
+ for (const [key, value] of Object.entries(obj)) {
139
+ truncated[key] = this.truncateDeep(value, maxLength);
140
+ }
141
+ return truncated;
142
+ }
143
+
144
+ return obj;
145
+ }
146
+ }