@smithers-orchestrator/scheduler 0.16.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.
- package/LICENSE +21 -0
- package/package.json +190 -0
- package/src/ApprovalResolution.ts +7 -0
- package/src/CachePolicy.ts +8 -0
- package/src/ContinuationRequest.ts +3 -0
- package/src/ContinueAsNewTransition.ts +9 -0
- package/src/EngineDecision.ts +19 -0
- package/src/PlanNode.ts +32 -0
- package/src/RalphMeta.ts +7 -0
- package/src/RalphState.ts +4 -0
- package/src/RalphStateMap.ts +3 -0
- package/src/ReadonlyTaskStateMap.ts +3 -0
- package/src/RenderContext.ts +14 -0
- package/src/RetryPolicy.ts +6 -0
- package/src/RetryWaitMap.ts +1 -0
- package/src/RunResult.ts +15 -0
- package/src/ScheduleResult.ts +15 -0
- package/src/ScheduleSnapshot.ts +8 -0
- package/src/Scheduler.js +28 -0
- package/src/SchedulerLive.js +8 -0
- package/src/SmithersWorkflowOptions.ts +43 -0
- package/src/TaskFailure.ts +5 -0
- package/src/TaskOutput.ts +9 -0
- package/src/TaskRecord.ts +10 -0
- package/src/TaskState.ts +10 -0
- package/src/TaskStateMap.ts +3 -0
- package/src/TokenUsage.ts +9 -0
- package/src/WaitReason.ts +8 -0
- package/src/WorkflowSession.js +10 -0
- package/src/WorkflowSessionLive.js +6 -0
- package/src/WorkflowSessionOptions.ts +10 -0
- package/src/WorkflowSessionService.ts +52 -0
- package/src/buildPlanTree.js +273 -0
- package/src/buildStateKey.js +8 -0
- package/src/cloneTaskStateMap.js +10 -0
- package/src/computeRetryDelayMs.js +14 -0
- package/src/index.d.ts +437 -0
- package/src/index.js +53 -0
- package/src/isTerminalState.js +15 -0
- package/src/makeWorkflowSession.js +723 -0
- package/src/nowMs.js +6 -0
- package/src/parseStateKey.js +15 -0
- package/src/retryPolicyToSchedule.js +26 -0
- package/src/retryScheduleDelayMs.js +23 -0
- package/src/scheduleTasks.js +330 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 William Cory
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smithers-orchestrator/scheduler",
|
|
3
|
+
"version": "0.16.0",
|
|
4
|
+
"description": "Pure decision engine: session, scheduler, and task state management for Smithers workflows",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.d.ts",
|
|
10
|
+
"import": "./src/index.js",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./TaskState": {
|
|
14
|
+
"types": "./src/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./TaskStateMap": {
|
|
17
|
+
"types": "./src/index.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./ReadonlyTaskStateMap": {
|
|
20
|
+
"types": "./src/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./TaskRecord": {
|
|
23
|
+
"types": "./src/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./buildStateKey": {
|
|
26
|
+
"types": "./src/index.d.ts",
|
|
27
|
+
"import": "./src/buildStateKey.js",
|
|
28
|
+
"default": "./src/buildStateKey.js"
|
|
29
|
+
},
|
|
30
|
+
"./parseStateKey": {
|
|
31
|
+
"types": "./src/index.d.ts",
|
|
32
|
+
"import": "./src/parseStateKey.js",
|
|
33
|
+
"default": "./src/parseStateKey.js"
|
|
34
|
+
},
|
|
35
|
+
"./cloneTaskStateMap": {
|
|
36
|
+
"types": "./src/index.d.ts",
|
|
37
|
+
"import": "./src/cloneTaskStateMap.js",
|
|
38
|
+
"default": "./src/cloneTaskStateMap.js"
|
|
39
|
+
},
|
|
40
|
+
"./isTerminalState": {
|
|
41
|
+
"types": "./src/index.d.ts",
|
|
42
|
+
"import": "./src/isTerminalState.js",
|
|
43
|
+
"default": "./src/isTerminalState.js"
|
|
44
|
+
},
|
|
45
|
+
"./PlanNode": {
|
|
46
|
+
"types": "./src/index.d.ts"
|
|
47
|
+
},
|
|
48
|
+
"./ScheduleResult": {
|
|
49
|
+
"types": "./src/index.d.ts"
|
|
50
|
+
},
|
|
51
|
+
"./RalphMeta": {
|
|
52
|
+
"types": "./src/index.d.ts"
|
|
53
|
+
},
|
|
54
|
+
"./ContinuationRequest": {
|
|
55
|
+
"types": "./src/index.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"./RalphState": {
|
|
58
|
+
"types": "./src/index.d.ts"
|
|
59
|
+
},
|
|
60
|
+
"./RalphStateMap": {
|
|
61
|
+
"types": "./src/index.d.ts"
|
|
62
|
+
},
|
|
63
|
+
"./RetryWaitMap": {
|
|
64
|
+
"types": "./src/index.d.ts"
|
|
65
|
+
},
|
|
66
|
+
"./ScheduleSnapshot": {
|
|
67
|
+
"types": "./src/index.d.ts"
|
|
68
|
+
},
|
|
69
|
+
"./Scheduler": {
|
|
70
|
+
"types": "./src/index.d.ts",
|
|
71
|
+
"import": "./src/Scheduler.js",
|
|
72
|
+
"default": "./src/Scheduler.js"
|
|
73
|
+
},
|
|
74
|
+
"./SchedulerLive": {
|
|
75
|
+
"types": "./src/index.d.ts",
|
|
76
|
+
"import": "./src/SchedulerLive.js",
|
|
77
|
+
"default": "./src/SchedulerLive.js"
|
|
78
|
+
},
|
|
79
|
+
"./buildPlanTree": {
|
|
80
|
+
"types": "./src/index.d.ts",
|
|
81
|
+
"import": "./src/buildPlanTree.js",
|
|
82
|
+
"default": "./src/buildPlanTree.js"
|
|
83
|
+
},
|
|
84
|
+
"./scheduleTasks": {
|
|
85
|
+
"types": "./src/index.d.ts",
|
|
86
|
+
"import": "./src/scheduleTasks.js",
|
|
87
|
+
"default": "./src/scheduleTasks.js"
|
|
88
|
+
},
|
|
89
|
+
"./WorkflowSession": {
|
|
90
|
+
"types": "./src/index.d.ts",
|
|
91
|
+
"import": "./src/WorkflowSession.js",
|
|
92
|
+
"default": "./src/WorkflowSession.js"
|
|
93
|
+
},
|
|
94
|
+
"./WorkflowSessionService": {
|
|
95
|
+
"types": "./src/index.d.ts",
|
|
96
|
+
"import": "./src/WorkflowSessionService.js",
|
|
97
|
+
"default": "./src/WorkflowSessionService.js"
|
|
98
|
+
},
|
|
99
|
+
"./WorkflowSessionOptions": {
|
|
100
|
+
"types": "./src/index.d.ts"
|
|
101
|
+
},
|
|
102
|
+
"./makeWorkflowSession": {
|
|
103
|
+
"types": "./src/index.d.ts",
|
|
104
|
+
"import": "./src/makeWorkflowSession.js",
|
|
105
|
+
"default": "./src/makeWorkflowSession.js"
|
|
106
|
+
},
|
|
107
|
+
"./WorkflowSessionLive": {
|
|
108
|
+
"types": "./src/index.d.ts",
|
|
109
|
+
"import": "./src/WorkflowSessionLive.js",
|
|
110
|
+
"default": "./src/WorkflowSessionLive.js"
|
|
111
|
+
},
|
|
112
|
+
"./EngineDecision": {
|
|
113
|
+
"types": "./src/index.d.ts"
|
|
114
|
+
},
|
|
115
|
+
"./RenderContext": {
|
|
116
|
+
"types": "./src/index.d.ts"
|
|
117
|
+
},
|
|
118
|
+
"./WaitReason": {
|
|
119
|
+
"types": "./src/index.d.ts"
|
|
120
|
+
},
|
|
121
|
+
"./RunResult": {
|
|
122
|
+
"types": "./src/index.d.ts"
|
|
123
|
+
},
|
|
124
|
+
"./TaskOutput": {
|
|
125
|
+
"types": "./src/index.d.ts"
|
|
126
|
+
},
|
|
127
|
+
"./TaskFailure": {
|
|
128
|
+
"types": "./src/index.d.ts"
|
|
129
|
+
},
|
|
130
|
+
"./TokenUsage": {
|
|
131
|
+
"types": "./src/index.d.ts"
|
|
132
|
+
},
|
|
133
|
+
"./RetryPolicy": {
|
|
134
|
+
"types": "./src/index.d.ts"
|
|
135
|
+
},
|
|
136
|
+
"./CachePolicy": {
|
|
137
|
+
"types": "./src/index.d.ts"
|
|
138
|
+
},
|
|
139
|
+
"./SmithersWorkflowOptions": {
|
|
140
|
+
"types": "./src/index.d.ts"
|
|
141
|
+
},
|
|
142
|
+
"./ApprovalResolution": {
|
|
143
|
+
"types": "./src/index.d.ts"
|
|
144
|
+
},
|
|
145
|
+
"./ContinueAsNewTransition": {
|
|
146
|
+
"types": "./src/index.d.ts"
|
|
147
|
+
},
|
|
148
|
+
"./retryPolicyToSchedule": {
|
|
149
|
+
"types": "./src/index.d.ts",
|
|
150
|
+
"import": "./src/retryPolicyToSchedule.js",
|
|
151
|
+
"default": "./src/retryPolicyToSchedule.js"
|
|
152
|
+
},
|
|
153
|
+
"./retryScheduleDelayMs": {
|
|
154
|
+
"types": "./src/index.d.ts",
|
|
155
|
+
"import": "./src/retryScheduleDelayMs.js",
|
|
156
|
+
"default": "./src/retryScheduleDelayMs.js"
|
|
157
|
+
},
|
|
158
|
+
"./computeRetryDelayMs": {
|
|
159
|
+
"types": "./src/index.d.ts",
|
|
160
|
+
"import": "./src/computeRetryDelayMs.js",
|
|
161
|
+
"default": "./src/computeRetryDelayMs.js"
|
|
162
|
+
},
|
|
163
|
+
"./nowMs": {
|
|
164
|
+
"types": "./src/index.d.ts",
|
|
165
|
+
"import": "./src/nowMs.js",
|
|
166
|
+
"default": "./src/nowMs.js"
|
|
167
|
+
},
|
|
168
|
+
"./*": {
|
|
169
|
+
"types": "./src/index.d.ts",
|
|
170
|
+
"import": "./src/*.js",
|
|
171
|
+
"default": "./src/*.js"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"files": [
|
|
175
|
+
"src/"
|
|
176
|
+
],
|
|
177
|
+
"dependencies": {
|
|
178
|
+
"effect": "^3.21.0",
|
|
179
|
+
"@smithers-orchestrator/errors": "0.16.0",
|
|
180
|
+
"@smithers-orchestrator/graph": "0.16.0"
|
|
181
|
+
},
|
|
182
|
+
"devDependencies": {
|
|
183
|
+
"@types/bun": "latest",
|
|
184
|
+
"typescript": "~5.9.3"
|
|
185
|
+
},
|
|
186
|
+
"scripts": {
|
|
187
|
+
"build": "tsup --dts-only",
|
|
188
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ContinueAsNewTransition = {
|
|
2
|
+
readonly reason: "explicit" | "loop-threshold" | "driver";
|
|
3
|
+
readonly iteration?: number;
|
|
4
|
+
readonly statePayload?: unknown;
|
|
5
|
+
readonly stateJson?: string;
|
|
6
|
+
readonly newRunId?: string;
|
|
7
|
+
readonly carriedStateBytes?: number;
|
|
8
|
+
readonly ancestryDepth?: number;
|
|
9
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TaskDescriptor } from "@smithers-orchestrator/graph";
|
|
2
|
+
import type { ContinueAsNewTransition } from "./ContinueAsNewTransition.ts";
|
|
3
|
+
import type { RenderContext } from "./RenderContext.ts";
|
|
4
|
+
import type { RunResult } from "./RunResult.ts";
|
|
5
|
+
import type { WaitReason } from "./WaitReason.ts";
|
|
6
|
+
|
|
7
|
+
export type EngineDecision =
|
|
8
|
+
| { readonly _tag: "Execute"; readonly tasks: readonly TaskDescriptor[] }
|
|
9
|
+
| { readonly _tag: "ReRender"; readonly context: RenderContext }
|
|
10
|
+
| {
|
|
11
|
+
readonly _tag: "Wait";
|
|
12
|
+
readonly reason: WaitReason;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
readonly _tag: "ContinueAsNew";
|
|
16
|
+
readonly transition: ContinueAsNewTransition;
|
|
17
|
+
}
|
|
18
|
+
| { readonly _tag: "Finished"; readonly result: RunResult }
|
|
19
|
+
| { readonly _tag: "Failed"; readonly error: unknown };
|
package/src/PlanNode.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type PlanNode =
|
|
2
|
+
| { readonly kind: "task"; readonly nodeId: string }
|
|
3
|
+
| { readonly kind: "sequence"; readonly children: readonly PlanNode[] }
|
|
4
|
+
| { readonly kind: "parallel"; readonly children: readonly PlanNode[] }
|
|
5
|
+
| {
|
|
6
|
+
readonly kind: "ralph";
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly children: readonly PlanNode[];
|
|
9
|
+
readonly until: boolean;
|
|
10
|
+
readonly maxIterations: number;
|
|
11
|
+
readonly onMaxReached: "fail" | "return-last";
|
|
12
|
+
readonly continueAsNewEvery?: number;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
readonly kind: "continue-as-new";
|
|
16
|
+
readonly stateJson?: string;
|
|
17
|
+
}
|
|
18
|
+
| { readonly kind: "group"; readonly children: readonly PlanNode[] }
|
|
19
|
+
| {
|
|
20
|
+
readonly kind: "saga";
|
|
21
|
+
readonly id: string;
|
|
22
|
+
readonly actionChildren: readonly PlanNode[];
|
|
23
|
+
readonly compensationChildren: readonly PlanNode[];
|
|
24
|
+
readonly onFailure: "compensate" | "compensate-and-fail" | "fail";
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
readonly kind: "try-catch-finally";
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly tryChildren: readonly PlanNode[];
|
|
30
|
+
readonly catchChildren: readonly PlanNode[];
|
|
31
|
+
readonly finallyChildren: readonly PlanNode[];
|
|
32
|
+
};
|
package/src/RalphMeta.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { WorkflowGraph } from "@smithers-orchestrator/graph";
|
|
2
|
+
import type { TaskOutput } from "./TaskOutput.ts";
|
|
3
|
+
|
|
4
|
+
export type RenderContext = {
|
|
5
|
+
readonly runId: string;
|
|
6
|
+
readonly graph?: WorkflowGraph | null;
|
|
7
|
+
readonly iteration?: number;
|
|
8
|
+
readonly iterations?: Record<string, number> | ReadonlyMap<string, number>;
|
|
9
|
+
readonly input?: unknown;
|
|
10
|
+
readonly outputs?: Record<string, unknown[]> | ReadonlyMap<string, TaskOutput>;
|
|
11
|
+
readonly auth?: unknown;
|
|
12
|
+
readonly taskStates?: unknown;
|
|
13
|
+
readonly ralphIterations?: ReadonlyMap<string, number>;
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type RetryWaitMap = Map<string, number>;
|
package/src/RunResult.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type RunResult = {
|
|
2
|
+
readonly runId: string;
|
|
3
|
+
readonly status:
|
|
4
|
+
| "running"
|
|
5
|
+
| "finished"
|
|
6
|
+
| "failed"
|
|
7
|
+
| "cancelled"
|
|
8
|
+
| "continued"
|
|
9
|
+
| "waiting-approval"
|
|
10
|
+
| "waiting-event"
|
|
11
|
+
| "waiting-timer";
|
|
12
|
+
readonly output?: unknown;
|
|
13
|
+
readonly error?: unknown;
|
|
14
|
+
readonly nextRunId?: string;
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TaskDescriptor } from "@smithers-orchestrator/graph";
|
|
2
|
+
import type { ContinuationRequest } from "./ContinuationRequest.ts";
|
|
3
|
+
import type { RalphMeta } from "./RalphMeta.ts";
|
|
4
|
+
|
|
5
|
+
export type ScheduleResult = {
|
|
6
|
+
readonly runnable: readonly TaskDescriptor[];
|
|
7
|
+
readonly pendingExists: boolean;
|
|
8
|
+
readonly waitingApprovalExists: boolean;
|
|
9
|
+
readonly waitingEventExists: boolean;
|
|
10
|
+
readonly waitingTimerExists: boolean;
|
|
11
|
+
readonly readyRalphs: readonly RalphMeta[];
|
|
12
|
+
readonly continuation?: ContinuationRequest;
|
|
13
|
+
readonly nextRetryAtMs?: number;
|
|
14
|
+
readonly fatalError?: string;
|
|
15
|
+
};
|
package/src/Scheduler.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
/** @typedef {import("@smithers-orchestrator/graph").TaskDescriptor} TaskDescriptor */
|
|
3
|
+
/** @typedef {import("./TaskStateMap.ts").TaskStateMap} TaskStateMap */
|
|
4
|
+
/** @typedef {import("./PlanNode.ts").PlanNode} PlanNode */
|
|
5
|
+
/** @typedef {import("./RalphStateMap.ts").RalphStateMap} RalphStateMap */
|
|
6
|
+
/** @typedef {import("./RetryWaitMap.ts").RetryWaitMap} RetryWaitMap */
|
|
7
|
+
/** @typedef {import("./ScheduleResult.ts").ScheduleResult} ScheduleResult */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{
|
|
11
|
+
* readonly schedule: (
|
|
12
|
+
* plan: PlanNode | null,
|
|
13
|
+
* states: TaskStateMap,
|
|
14
|
+
* descriptors: Map<string, TaskDescriptor>,
|
|
15
|
+
* ralphState: RalphStateMap,
|
|
16
|
+
* retryWait: RetryWaitMap,
|
|
17
|
+
* nowMs: number,
|
|
18
|
+
* ) => import("effect").Effect.Effect<ScheduleResult>
|
|
19
|
+
* }} SchedulerService
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const SchedulerBase =
|
|
23
|
+
/** @type {Context.TagClass<Scheduler, "Scheduler", SchedulerService>} */ (
|
|
24
|
+
/** @type {unknown} */ (Context.Tag("Scheduler")())
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
export class Scheduler extends SchedulerBase {
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { Scheduler } from "./Scheduler.js";
|
|
3
|
+
import { scheduleTasks } from "./scheduleTasks.js";
|
|
4
|
+
|
|
5
|
+
/** @type {Layer.Layer<Scheduler, never, never>} */
|
|
6
|
+
export const SchedulerLive = Layer.succeed(Scheduler, {
|
|
7
|
+
schedule: (plan, states, descriptors, ralphState, retryWait, nowMs) => Effect.sync(() => scheduleTasks(plan, states, descriptors, ralphState, retryWait, nowMs)),
|
|
8
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type SmithersAlertSeverity = "info" | "warning" | "critical";
|
|
2
|
+
|
|
3
|
+
export type SmithersAlertLabels = Record<string, string>;
|
|
4
|
+
|
|
5
|
+
export type SmithersAlertReactionKind =
|
|
6
|
+
| "emit-only"
|
|
7
|
+
| "pause"
|
|
8
|
+
| "cancel"
|
|
9
|
+
| "open-approval"
|
|
10
|
+
| "deliver";
|
|
11
|
+
|
|
12
|
+
export type SmithersAlertReaction =
|
|
13
|
+
| { kind: "emit-only" }
|
|
14
|
+
| { kind: "pause" }
|
|
15
|
+
| { kind: "cancel" }
|
|
16
|
+
| { kind: "open-approval" }
|
|
17
|
+
| { kind: "deliver"; destination: string };
|
|
18
|
+
|
|
19
|
+
export type SmithersAlertReactionRef = string | SmithersAlertReaction;
|
|
20
|
+
|
|
21
|
+
export type SmithersAlertPolicyDefaults = {
|
|
22
|
+
owner?: string;
|
|
23
|
+
severity?: SmithersAlertSeverity;
|
|
24
|
+
runbook?: string;
|
|
25
|
+
labels?: SmithersAlertLabels;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type SmithersAlertPolicyRule = SmithersAlertPolicyDefaults & {
|
|
29
|
+
afterMs?: number;
|
|
30
|
+
reaction?: SmithersAlertReactionRef;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type SmithersAlertPolicy = {
|
|
34
|
+
defaults?: SmithersAlertPolicyDefaults;
|
|
35
|
+
rules?: Record<string, SmithersAlertPolicyRule>;
|
|
36
|
+
reactions?: Record<string, SmithersAlertReaction>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type SmithersWorkflowOptions = {
|
|
40
|
+
alertPolicy?: SmithersAlertPolicy;
|
|
41
|
+
cache?: boolean;
|
|
42
|
+
workflowHash?: string;
|
|
43
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TaskDescriptor } from "@smithers-orchestrator/graph";
|
|
2
|
+
import type { TaskState } from "./TaskState.ts";
|
|
3
|
+
|
|
4
|
+
export type TaskRecord = {
|
|
5
|
+
readonly descriptor: TaskDescriptor;
|
|
6
|
+
readonly state: TaskState;
|
|
7
|
+
readonly output?: unknown;
|
|
8
|
+
readonly error?: unknown;
|
|
9
|
+
readonly updatedAtMs: number;
|
|
10
|
+
};
|
package/src/TaskState.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type TokenUsage = {
|
|
2
|
+
readonly inputTokens?: number;
|
|
3
|
+
readonly outputTokens?: number;
|
|
4
|
+
readonly cacheReadTokens?: number;
|
|
5
|
+
readonly cacheWriteTokens?: number;
|
|
6
|
+
readonly reasoningTokens?: number;
|
|
7
|
+
readonly totalTokens?: number;
|
|
8
|
+
readonly [key: string]: unknown;
|
|
9
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type WaitReason =
|
|
2
|
+
| { readonly _tag: "Approval"; readonly nodeId: string }
|
|
3
|
+
| { readonly _tag: "Event"; readonly eventName: string }
|
|
4
|
+
| { readonly _tag: "Timer"; readonly resumeAtMs: number }
|
|
5
|
+
| { readonly _tag: "RetryBackoff"; readonly waitMs: number }
|
|
6
|
+
| { readonly _tag: "HotReload" }
|
|
7
|
+
| { readonly _tag: "OrphanRecovery"; readonly count: number }
|
|
8
|
+
| { readonly _tag: "ExternalTrigger" };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context } from "effect";
|
|
2
|
+
/** @typedef {import("./WorkflowSessionService.ts").WorkflowSessionService} WorkflowSessionService */
|
|
3
|
+
|
|
4
|
+
const WorkflowSessionBase =
|
|
5
|
+
/** @type {Context.TagClass<WorkflowSession, "WorkflowSession", WorkflowSessionService>} */ (
|
|
6
|
+
/** @type {unknown} */ (Context.Tag("WorkflowSession")())
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export class WorkflowSession extends WorkflowSessionBase {
|
|
10
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Layer } from "effect";
|
|
2
|
+
import { WorkflowSession } from "./WorkflowSession.js";
|
|
3
|
+
import { makeWorkflowSession } from "./makeWorkflowSession.js";
|
|
4
|
+
|
|
5
|
+
/** @type {Layer.Layer<WorkflowSession, never, never>} */
|
|
6
|
+
export const WorkflowSessionLive = Layer.sync(WorkflowSession, makeWorkflowSession);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type WorkflowSessionOptions = {
|
|
2
|
+
readonly runId?: string;
|
|
3
|
+
readonly nowMs?: () => number;
|
|
4
|
+
readonly requireStableFinish?: boolean;
|
|
5
|
+
readonly requireRerenderOnOutputChange?: boolean;
|
|
6
|
+
readonly initialRalphState?: ReadonlyMap<string, {
|
|
7
|
+
readonly iteration: number;
|
|
8
|
+
readonly done: boolean;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Effect } from "effect";
|
|
2
|
+
import type { WorkflowGraph } from "@smithers-orchestrator/graph";
|
|
3
|
+
import type { TaskStateMap } from "./TaskStateMap.ts";
|
|
4
|
+
import type { ApprovalResolution } from "./ApprovalResolution.ts";
|
|
5
|
+
import type { ScheduleSnapshot } from "./ScheduleSnapshot.ts";
|
|
6
|
+
import type { EngineDecision } from "./EngineDecision.ts";
|
|
7
|
+
import type { TaskFailure } from "./TaskFailure.ts";
|
|
8
|
+
import type { TaskOutput } from "./TaskOutput.ts";
|
|
9
|
+
|
|
10
|
+
export type WorkflowSessionService = {
|
|
11
|
+
readonly submitGraph: (graph: WorkflowGraph) => Effect.Effect<EngineDecision>;
|
|
12
|
+
readonly taskCompleted: (output: TaskOutput) => Effect.Effect<EngineDecision>;
|
|
13
|
+
readonly taskFailed: (failure: TaskFailure) => Effect.Effect<EngineDecision>;
|
|
14
|
+
readonly approvalResolved: (
|
|
15
|
+
nodeId: string,
|
|
16
|
+
resolution: ApprovalResolution,
|
|
17
|
+
) => Effect.Effect<EngineDecision>;
|
|
18
|
+
readonly approvalTimedOut: (nodeId: string) => Effect.Effect<EngineDecision>;
|
|
19
|
+
readonly eventReceived: (
|
|
20
|
+
eventName: string,
|
|
21
|
+
payload: unknown,
|
|
22
|
+
correlationId?: string | null,
|
|
23
|
+
) => Effect.Effect<EngineDecision>;
|
|
24
|
+
readonly signalReceived: (
|
|
25
|
+
signalName: string,
|
|
26
|
+
payload: unknown,
|
|
27
|
+
correlationId?: string | null,
|
|
28
|
+
) => Effect.Effect<EngineDecision>;
|
|
29
|
+
readonly timerFired: (
|
|
30
|
+
nodeId: string,
|
|
31
|
+
firedAtMs?: number,
|
|
32
|
+
) => Effect.Effect<EngineDecision>;
|
|
33
|
+
readonly hotReloaded: (graph: WorkflowGraph) => Effect.Effect<EngineDecision>;
|
|
34
|
+
readonly heartbeatTimedOut: (
|
|
35
|
+
nodeId: string,
|
|
36
|
+
iteration?: number,
|
|
37
|
+
details?: Record<string, unknown>,
|
|
38
|
+
) => Effect.Effect<EngineDecision>;
|
|
39
|
+
readonly cacheResolved: (
|
|
40
|
+
output: TaskOutput,
|
|
41
|
+
cached: boolean,
|
|
42
|
+
) => Effect.Effect<EngineDecision>;
|
|
43
|
+
readonly cacheMissed: (
|
|
44
|
+
nodeId: string,
|
|
45
|
+
iteration?: number,
|
|
46
|
+
) => Effect.Effect<EngineDecision>;
|
|
47
|
+
readonly recoverOrphanedTasks: () => Effect.Effect<EngineDecision>;
|
|
48
|
+
readonly cancelRequested: () => Effect.Effect<EngineDecision>;
|
|
49
|
+
readonly getTaskStates: () => Effect.Effect<TaskStateMap>;
|
|
50
|
+
readonly getSchedule: () => Effect.Effect<ScheduleSnapshot | null>;
|
|
51
|
+
readonly getCurrentGraph: () => Effect.Effect<WorkflowGraph | null>;
|
|
52
|
+
};
|