@memberjunction/task-graph 6.1.0-edge.1 → 6.1.0-edge.3
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 +180 -4
- package/README.md +214 -0
- package/dist/TaskClaimStore.d.ts +387 -4
- package/dist/TaskClaimStore.d.ts.map +1 -1
- package/dist/TaskClaimStore.js +605 -20
- package/dist/TaskClaimStore.js.map +1 -1
- package/dist/TaskGraphDispatcher.d.ts +668 -5
- package/dist/TaskGraphDispatcher.d.ts.map +1 -1
- package/dist/TaskGraphDispatcher.js +2942 -127
- package/dist/TaskGraphDispatcher.js.map +1 -1
- package/dist/TaskGraphService.d.ts +364 -5
- package/dist/TaskGraphService.d.ts.map +1 -1
- package/dist/TaskGraphService.js +1039 -43
- package/dist/TaskGraphService.js.map +1 -1
- package/dist/TaskGraphSubmitterImpl.d.ts.map +1 -1
- package/dist/TaskGraphSubmitterImpl.js +5 -0
- package/dist/TaskGraphSubmitterImpl.js.map +1 -1
- package/dist/TaskLoopExecutor.d.ts +62 -0
- package/dist/TaskLoopExecutor.d.ts.map +1 -0
- package/dist/TaskLoopExecutor.js +248 -0
- package/dist/TaskLoopExecutor.js.map +1 -0
- package/dist/WorkflowSpecSync.d.ts +28 -2
- package/dist/WorkflowSpecSync.d.ts.map +1 -1
- package/dist/WorkflowSpecSync.js +83 -2
- package/dist/WorkflowSpecSync.js.map +1 -1
- package/dist/condition-gate.d.ts +128 -0
- package/dist/condition-gate.d.ts.map +1 -0
- package/dist/condition-gate.js +257 -0
- package/dist/condition-gate.js.map +1 -0
- package/dist/debug-state.d.ts +102 -0
- package/dist/debug-state.d.ts.map +1 -0
- package/dist/debug-state.js +135 -0
- package/dist/debug-state.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/TaskGraphDebugOperations.d.ts +99 -0
- package/dist/operations/TaskGraphDebugOperations.d.ts.map +1 -0
- package/dist/operations/TaskGraphDebugOperations.js +310 -0
- package/dist/operations/TaskGraphDebugOperations.js.map +1 -0
- package/dist/operations/TaskGraphOperations.d.ts +20 -2
- package/dist/operations/TaskGraphOperations.d.ts.map +1 -1
- package/dist/operations/TaskGraphOperations.js +51 -8
- package/dist/operations/TaskGraphOperations.js.map +1 -1
- package/dist/operations/WorkflowDraftOperation.d.ts +37 -0
- package/dist/operations/WorkflowDraftOperation.d.ts.map +1 -0
- package/dist/operations/WorkflowDraftOperation.js +141 -0
- package/dist/operations/WorkflowDraftOperation.js.map +1 -0
- package/dist/settlement-rescue.d.ts +85 -0
- package/dist/settlement-rescue.d.ts.map +1 -0
- package/dist/settlement-rescue.js +119 -0
- package/dist/settlement-rescue.js.map +1 -0
- package/dist/task-graph-kick.d.ts +3 -0
- package/dist/task-graph-kick.d.ts.map +1 -0
- package/dist/task-graph-kick.js +17 -0
- package/dist/task-graph-kick.js.map +1 -0
- package/dist/task-predicates.d.ts +77 -0
- package/dist/task-predicates.d.ts.map +1 -0
- package/dist/task-predicates.js +75 -0
- package/dist/task-predicates.js.map +1 -0
- package/dist/types.d.ts +224 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +12 -8
|
@@ -16,7 +16,20 @@
|
|
|
16
16
|
* @module @memberjunction/task-graph
|
|
17
17
|
*/
|
|
18
18
|
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
19
|
-
import { type
|
|
19
|
+
import { type MJTaskEntity_ITaskStepConfiguration } from '@memberjunction/core-entities';
|
|
20
|
+
import { type TaskGraphInvocationEnvelope, type TaskGraphSpec, type TaskGraphSpecNode, type ForEachOperation, type WhileOperation } from '@memberjunction/ai-core-plus';
|
|
21
|
+
import { type EdgeOverrideVerdict, type StepTarget, type TaskGraphDebugState } from './debug-state.js';
|
|
22
|
+
/**
|
|
23
|
+
* Normalizes a caller-supplied reinvoke depth to a safe cap seed.
|
|
24
|
+
*
|
|
25
|
+
* The runaway-loop cap is a signed comparison over a persisted-verbatim seed, and the remote Submit
|
|
26
|
+
* operation is the one seam where the seed is caller-supplied rather than computed by the engine —
|
|
27
|
+
* a negative value would BUY hops (`-1000` turns a 5-hop cap into 1005). Clamped rather than
|
|
28
|
+
* refused so a stale client sending zero-adjacent noise keeps working, and no accepted value can
|
|
29
|
+
* ever weaken the cap. Exported pure because a boundary rule that cannot be tested directly is a
|
|
30
|
+
* boundary nobody will notice moving.
|
|
31
|
+
*/
|
|
32
|
+
export declare function ClampReinvokeDepth(value: unknown): number | undefined;
|
|
20
33
|
/** Context a submission carries beyond the graph itself. */
|
|
21
34
|
export type TaskGraphSubmitContext = {
|
|
22
35
|
/** Environment the tasks belong to. */
|
|
@@ -34,6 +47,16 @@ export type TaskGraphSubmitContext = {
|
|
|
34
47
|
* re-invoked by a finished graph carries its parent's depth + 1.
|
|
35
48
|
*/
|
|
36
49
|
ReinvokeDepth?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The invocation's runtime parameters, for the flow dialect's `data`/`context` roots (R3-3).
|
|
52
|
+
* Persisted on the parent because the instance evaluating a condition is routinely not the
|
|
53
|
+
* process that accepted the graph.
|
|
54
|
+
*/
|
|
55
|
+
Invocation?: TaskGraphInvocationEnvelope;
|
|
56
|
+
/** Seed `$.debug` on the parent at insert. See `TaskGraphStartDebug`. */
|
|
57
|
+
Debug?: {
|
|
58
|
+
paused?: boolean;
|
|
59
|
+
};
|
|
37
60
|
};
|
|
38
61
|
/**
|
|
39
62
|
* What the parent Task row remembers about the graph beyond its tasks.
|
|
@@ -45,6 +68,16 @@ export type TaskGraphSubmitContext = {
|
|
|
45
68
|
export type TaskGraphParentMetadata = {
|
|
46
69
|
continuation: 'message' | 'reinvoke' | 'none';
|
|
47
70
|
reinvokeDepth: number;
|
|
71
|
+
/**
|
|
72
|
+
* How a failure propagates in this graph — persisted because the dispatcher that settles a graph
|
|
73
|
+
* is routinely not the process that accepted it, and the spec is gone by then.
|
|
74
|
+
*
|
|
75
|
+
* `'block'` (the default) makes a failed step terminal for its dependents. `'edges'` releases
|
|
76
|
+
* them along their drawn paths, which is what lets a workflow author a RECOVERY route. Compiled
|
|
77
|
+
* flows are `'edges'`; without persisting it, every recovery path a flow author draws is dead
|
|
78
|
+
* machinery — the edges exist and nothing ever follows them.
|
|
79
|
+
*/
|
|
80
|
+
failureSemantics?: 'block' | 'edges';
|
|
48
81
|
submittedByAgentRunID: string | null;
|
|
49
82
|
/**
|
|
50
83
|
* Who the graph belongs to.
|
|
@@ -64,6 +97,36 @@ export type TaskGraphParentMetadata = {
|
|
|
64
97
|
* racing the same completion produce one winner rather than two notifications.
|
|
65
98
|
*/
|
|
66
99
|
continuationDeliveredAt?: string;
|
|
100
|
+
/**
|
|
101
|
+
* HOW it was delivered — written by the same compare-and-swap that sets the timestamp.
|
|
102
|
+
*
|
|
103
|
+
* `'expired'` means the settlement was found after its delivery window, so the run and its cost
|
|
104
|
+
* were corrected but nothing was announced: posting a week-old "your workflow finished" into a
|
|
105
|
+
* live conversation, or starting a fresh billed turn for it, is worse than staying quiet. The
|
|
106
|
+
* distinction has to survive in the row, or an expired settlement is indistinguishable from a
|
|
107
|
+
* delivered one the moment anybody looks afterwards.
|
|
108
|
+
*/
|
|
109
|
+
continuationDeliveredAs?: 'delivered' | 'expired' | 'cancelled';
|
|
110
|
+
/**
|
|
111
|
+
* Set, once and durably, when a step declares the workflow finished before its remaining steps.
|
|
112
|
+
*
|
|
113
|
+
* Read by `loadGraphState` so every instance's claim filter knows the remaining steps are about
|
|
114
|
+
* to be skipped. Without it the decision lives only in the deciding instance's memory, and a
|
|
115
|
+
* concurrent poll — including that same instance's, since task execution is not awaited — can
|
|
116
|
+
* claim and start a step the early finish is in the middle of skipping.
|
|
117
|
+
*/
|
|
118
|
+
earlyFinishedAt?: string;
|
|
119
|
+
/**
|
|
120
|
+
* The invocation's `data` and `context`, as the flow dialect's roots of the same names (R3-3).
|
|
121
|
+
*
|
|
122
|
+
* Absent for a graph submitted without them, in which case those roots resolve to the same
|
|
123
|
+
* empty-but-readable value any absent data does — a condition on them reads false rather than
|
|
124
|
+
* throwing, exactly as the walker's would on a missing key.
|
|
125
|
+
*/
|
|
126
|
+
invocation?: {
|
|
127
|
+
data?: unknown;
|
|
128
|
+
context?: unknown;
|
|
129
|
+
};
|
|
67
130
|
};
|
|
68
131
|
/**
|
|
69
132
|
* Continuation chains are bounded separately from graph nesting.
|
|
@@ -87,6 +150,33 @@ export declare const MAX_REINVOKE_DEPTH = 5;
|
|
|
87
150
|
* graph wanted" is still to tell the user their work finished.
|
|
88
151
|
*/
|
|
89
152
|
export declare function ParseTaskGraphParentMetadata(raw: string | null | undefined): TaskGraphParentMetadata;
|
|
153
|
+
/**
|
|
154
|
+
* The JSON bag `persistParent` writes. Exported so start-paused is testable without a database —
|
|
155
|
+
* Pause-after-submit races the first dispatcher poll, so this bag is the only place `paused: true`
|
|
156
|
+
* is guaranteed to land before anyone claims.
|
|
157
|
+
*/
|
|
158
|
+
export declare function BuildTaskGraphParentInputPayload(args: {
|
|
159
|
+
continuation: TaskGraphParentMetadata['continuation'];
|
|
160
|
+
reinvokeDepth: number;
|
|
161
|
+
failureSemantics: NonNullable<TaskGraphParentMetadata['failureSemantics']>;
|
|
162
|
+
submittedByAgentRunID: string | null;
|
|
163
|
+
submittedByUserID: string | null;
|
|
164
|
+
invocation?: {
|
|
165
|
+
data?: unknown;
|
|
166
|
+
context?: unknown;
|
|
167
|
+
} | null;
|
|
168
|
+
startPaused?: boolean;
|
|
169
|
+
}): Record<string, unknown>;
|
|
170
|
+
/** What a cancellation actually managed to do. */
|
|
171
|
+
export type TaskGraphCancelResult = {
|
|
172
|
+
/** False when anything the caller asked to stop is still running. */
|
|
173
|
+
Success: boolean;
|
|
174
|
+
/** True only when every non-terminal task in the graph — and its descendants — is Cancelled. */
|
|
175
|
+
Cancelled: boolean;
|
|
176
|
+
/** Named so the caller can say which parts of the workflow are still going. */
|
|
177
|
+
UncancelledTaskNames: string[];
|
|
178
|
+
ErrorMessage?: string;
|
|
179
|
+
};
|
|
90
180
|
/** True when a continuation chain has gone as far as it may. */
|
|
91
181
|
export declare function IsReinvokeCapReached(meta: TaskGraphParentMetadata): boolean;
|
|
92
182
|
export type TaskGraphSubmitResult = {
|
|
@@ -97,7 +187,70 @@ export type TaskGraphSubmitResult = {
|
|
|
97
187
|
TaskIDMap?: Map<string, string>;
|
|
98
188
|
ErrorMessage?: string;
|
|
99
189
|
};
|
|
190
|
+
/** Name of the task type used for agent-orchestrated graphs. */
|
|
191
|
+
export declare const TASK_TYPE_NAME = "AI Workflow";
|
|
192
|
+
/**
|
|
193
|
+
* Reports the node kinds this dispatcher cannot execute, or `null` when the graph is fully runnable.
|
|
194
|
+
*
|
|
195
|
+
* **Why this is a submit-time check and not a validation rule.** `ValidateTaskGraphSpec` is a pure
|
|
196
|
+
* function over the spec: it answers "is this a well-formed graph?", and its answer has to be the
|
|
197
|
+
* same in a browser, a CLI and a server. "Can it run *here*?" is a different question whose answer
|
|
198
|
+
* changes as runners are added, so it belongs to the runtime that owns the runners.
|
|
199
|
+
*
|
|
200
|
+
* **Why refuse rather than persist-and-stall.** Before this existed, `persistTasks` keyed off which
|
|
201
|
+
* configuration field happened to be populated and fell through to "Human task assigned to the
|
|
202
|
+
* submitter" for everything else — so a loop step silently became an approval request nobody asked
|
|
203
|
+
* for and nothing would ever complete. A graph that hangs forever while *looking* like it is waiting
|
|
204
|
+
* on a person is the most expensive failure available here. Refusing at the door instead names the
|
|
205
|
+
* offending step while the workflow is still the author's to edit.
|
|
206
|
+
*/
|
|
207
|
+
/**
|
|
208
|
+
* Projects a spec node onto the `Task.Configuration` bag.
|
|
209
|
+
*
|
|
210
|
+
* Everything the row cannot hold in a column of its own: the kind-specific settings, the payload
|
|
211
|
+
* mappings, and the execution policy. Returning `null` for an empty result keeps `Configuration`
|
|
212
|
+
* NULL rather than `"{}"`, so "this step has no settings" reads the same in the database as it does
|
|
213
|
+
* in the spec.
|
|
214
|
+
*
|
|
215
|
+
* **The mappings are the point.** They are how a step's result reaches the payload, and every
|
|
216
|
+
* branch condition downstream reads the payload — so a step persisted without them produces a
|
|
217
|
+
* workflow whose conditions all evaluate against nothing. Undefined is falsy, so that failure looks
|
|
218
|
+
* exactly like a branch legitimately not being taken.
|
|
219
|
+
*/
|
|
220
|
+
export declare function BuildStepConfiguration(node: TaskGraphSpecNode): MJTaskEntity_ITaskStepConfiguration | null;
|
|
221
|
+
/**
|
|
222
|
+
* The loop definition on a node, whichever loop kind it is.
|
|
223
|
+
*
|
|
224
|
+
* ForEach and While differ in how they decide to iterate, not in what they repeat, so everything
|
|
225
|
+
* downstream of that decision — body resolution, name collection, persistence — treats them alike.
|
|
226
|
+
*/
|
|
227
|
+
export declare function LoopOperationOf(node: TaskGraphSpecNode): ForEachOperation | WhileOperation | null;
|
|
228
|
+
export declare function FindUnrunnableKinds(spec: TaskGraphSpec): string | null;
|
|
229
|
+
/**
|
|
230
|
+
* Reports human steps assigned to someone other than the submitter, or `null` when there are none.
|
|
231
|
+
*
|
|
232
|
+
* Cross-user assignment needs an authorization model (#3524) — deciding that A may put work in B's
|
|
233
|
+
* inbox is a permissions question, not a graph question. Until it lands, a workflow can only ask the
|
|
234
|
+
* person who started it.
|
|
235
|
+
*
|
|
236
|
+
* **Why refuse rather than reassign.** Persist wrote `task.UserID = submitter` unconditionally, so
|
|
237
|
+
* an authored `assignToUserID` was overwritten in silence. Every layer above accepts the field —
|
|
238
|
+
* the flow compiler reads it into the spec, the validator passes it, the spec type declares it — so
|
|
239
|
+
* silence here is indistinguishable from support: the graph submits, a step appears in the WRONG
|
|
240
|
+
* person's inbox, the named person is never told, and the author has no reason to suspect any of it.
|
|
241
|
+
* Refusing while the graph is still the author's to edit is the only point at which saying so costs
|
|
242
|
+
* nothing.
|
|
243
|
+
*/
|
|
244
|
+
export declare function FindCrossUserAssignments(spec: TaskGraphSpec, submitterUserID: string): string | null;
|
|
100
245
|
export declare class TaskGraphService {
|
|
246
|
+
/**
|
|
247
|
+
* Guarded single-statement writes, shared with the dispatcher.
|
|
248
|
+
*
|
|
249
|
+
* The instance id is descriptive only — this service never CLAIMS anything, it only issues
|
|
250
|
+
* guarded transitions whose predicates are about the row's own status rather than about who
|
|
251
|
+
* holds it.
|
|
252
|
+
*/
|
|
253
|
+
private readonly claims;
|
|
101
254
|
/**
|
|
102
255
|
* Validates and persists a task graph, returning as soon as it is durable.
|
|
103
256
|
*
|
|
@@ -108,13 +261,57 @@ export declare class TaskGraphService {
|
|
|
108
261
|
*/
|
|
109
262
|
Submit(spec: TaskGraphSpec, context: TaskGraphSubmitContext): Promise<TaskGraphSubmitResult>;
|
|
110
263
|
/**
|
|
111
|
-
* Cancels a graph
|
|
264
|
+
* Cancels a graph, everything in it that has not already settled, and everything it started.
|
|
112
265
|
*
|
|
113
266
|
* Cancels children first: a parent marked `Cancelled` while children are still `Pending` would
|
|
114
267
|
* leave the dispatcher free to pick those children up, which is the opposite of what the caller
|
|
115
268
|
* asked for.
|
|
269
|
+
*
|
|
270
|
+
* **The verdict is the outcome, not the attempt** (R2-9). This returned `true` unconditionally
|
|
271
|
+
* while logging each child that failed to cancel — so one failed save left that child `Pending`,
|
|
272
|
+
* told the caller cancellation had succeeded, and let the dispatcher run the child afterwards.
|
|
273
|
+
* The graph could then settle `Complete` and ANNOUNCE ITS COMPLETION into the conversation of a
|
|
274
|
+
* workflow the user had cancelled. A partial cancel now says so and names what survived; the
|
|
275
|
+
* graph stays active, so retrying is meaningful rather than cosmetic.
|
|
116
276
|
*/
|
|
117
|
-
Cancel(parentTaskID: string, context: TaskGraphSubmitContext): Promise<
|
|
277
|
+
Cancel(parentTaskID: string, context: TaskGraphSubmitContext): Promise<TaskGraphCancelResult>;
|
|
278
|
+
/**
|
|
279
|
+
* `Cancel`, carrying the recursion state the public entry point does not expose.
|
|
280
|
+
*
|
|
281
|
+
* **The depth cap was dead code** (R3-10): `Cancel` passed a literal 0, and the recursion
|
|
282
|
+
* re-entered through `this.Cancel`, which restarted at 0 — so the check could never fire and
|
|
283
|
+
* the "bounded by the reinvoke depth cap" promise was false. A hand-edited `AgentRunID` cycle
|
|
284
|
+
* recursed to stack overflow mid-cancel.
|
|
285
|
+
*
|
|
286
|
+
* The visited set is cheap armour on top: the cap bounds how DEEP a legitimate chain goes, and
|
|
287
|
+
* a cycle is not deep, it is circular. Arithmetic alone would eventually stop it; a visited set
|
|
288
|
+
* stops it immediately and covers linkage shapes the arithmetic does not anticipate.
|
|
289
|
+
*/
|
|
290
|
+
private cancelWithDepth;
|
|
291
|
+
/**
|
|
292
|
+
* Cancels the graphs that this graph's own steps submitted, one level at a time.
|
|
293
|
+
*
|
|
294
|
+
* The linkage is `child task → AgentRunID → the graphs that run submitted`, which is exactly how
|
|
295
|
+
* the continuation chain finds its way back up; walking it downward is the same relation read the
|
|
296
|
+
* other way. Depth-capped by the same constant that caps reinvocation, so a self-referencing
|
|
297
|
+
* workflow cannot make cancellation recurse further than it could have spawned.
|
|
298
|
+
*
|
|
299
|
+
* @returns names of tasks in descendant graphs that could not be cancelled
|
|
300
|
+
*/
|
|
301
|
+
private cancelNestedGraphs;
|
|
302
|
+
/**
|
|
303
|
+
* Closes the still-open requests raised for a set of tasks.
|
|
304
|
+
*
|
|
305
|
+
* `Canceled` rather than `Expired`: nobody ran out of time, the ask was withdrawn — and the two
|
|
306
|
+
* mean different things downstream, since the dispatcher treats an expired human step as a
|
|
307
|
+
* FAILURE a give-up edge can route around, which would be a lie about a graph somebody stopped
|
|
308
|
+
* on purpose.
|
|
309
|
+
*
|
|
310
|
+
* Failures here are logged and never propagated: the graph is already cancelled, and refusing to
|
|
311
|
+
* finish that because an inbox row would not close would leave the graph in a worse state than
|
|
312
|
+
* the debris it is trying to avoid.
|
|
313
|
+
*/
|
|
314
|
+
private cancelOpenRequests;
|
|
118
315
|
/**
|
|
119
316
|
* Returns a failed task to `Pending` so the dispatcher can run it again.
|
|
120
317
|
*
|
|
@@ -122,15 +319,177 @@ export declare class TaskGraphService {
|
|
|
122
319
|
* leaving them blocked would make the retry pointless, as the graph still could not progress
|
|
123
320
|
* past this node.
|
|
124
321
|
*/
|
|
125
|
-
Retry(taskID: string, context: TaskGraphSubmitContext): Promise<boolean>;
|
|
322
|
+
Retry(taskID: string, context: TaskGraphSubmitContext, inputPayload?: unknown): Promise<boolean>;
|
|
323
|
+
/**
|
|
324
|
+
* Store for the guarded JSON_MODIFY writes. The instance identity and TTL are claim-protocol
|
|
325
|
+
* concerns this class never exercises — the debug writes are instance-free.
|
|
326
|
+
*/
|
|
327
|
+
private readonly debugWrites;
|
|
328
|
+
/** Result shape shared by the control verbs: what happened, and the state that now holds. */
|
|
329
|
+
private controlResult;
|
|
330
|
+
/**
|
|
331
|
+
* Loads a graph parent and proves it IS a workflow graph before any debug write.
|
|
332
|
+
*
|
|
333
|
+
* Read with `BypassCache` for the same reason the dispatcher reads rows that way: the debug bag
|
|
334
|
+
* is written by direct `JSON_MODIFY` statements that fire no cache invalidation, so a cached
|
|
335
|
+
* read here could merge new state over a stale copy and silently resurrect a cleared flag.
|
|
336
|
+
*/
|
|
337
|
+
private loadWorkflowParent;
|
|
338
|
+
/**
|
|
339
|
+
* Writes the debug-bag fields a verb OWNS, and reports the state that results.
|
|
340
|
+
*
|
|
341
|
+
* Field-scoped on purpose — see {@link TaskClaimStore.TryWriteDebugFields}. A verb declares the
|
|
342
|
+
* paths it is responsible for; everything else in the bag is left exactly as the database has
|
|
343
|
+
* it, so a concurrent step-consume, breakpoint edit, or override cannot be undone by a verb that
|
|
344
|
+
* was not talking about them.
|
|
345
|
+
*
|
|
346
|
+
* The returned state is this instance's best view (read + the fields just written) and is
|
|
347
|
+
* advisory — the same posture the console takes toward frames.
|
|
348
|
+
*/
|
|
349
|
+
private writeDebugFields;
|
|
350
|
+
/**
|
|
351
|
+
* Pauses a graph: nothing new is claimed until it is resumed. In-flight steps finish naturally
|
|
352
|
+
* and their completions land — a pause gates claiming and never touches a live claim, which is
|
|
353
|
+
* why there is no "what happens to the claim" question to answer.
|
|
354
|
+
*/
|
|
355
|
+
PauseGraph(parentTaskID: string, context: TaskGraphSubmitContext, pausedByUserID?: string | null): Promise<{
|
|
356
|
+
Success: boolean;
|
|
357
|
+
Debug?: TaskGraphDebugState;
|
|
358
|
+
ErrorMessage?: string;
|
|
359
|
+
}>;
|
|
360
|
+
/** Resumes a paused graph. Breakpoints and edge overrides survive — only the pause clears. */
|
|
361
|
+
ResumeGraph(parentTaskID: string, context: TaskGraphSubmitContext): Promise<{
|
|
362
|
+
Success: boolean;
|
|
363
|
+
Debug?: TaskGraphDebugState;
|
|
364
|
+
ErrorMessage?: string;
|
|
365
|
+
}>;
|
|
366
|
+
/**
|
|
367
|
+
* Arms a one-shot step allowance on a paused graph: `'one'` releases the next eligible task,
|
|
368
|
+
* `'wave'` releases the current frontier, a task ID releases exactly that task. The dispatcher
|
|
369
|
+
* consumes the allowance CAS-style, so two instances stepping the same graph release work once.
|
|
370
|
+
*/
|
|
371
|
+
StepGraph(parentTaskID: string, target: StepTarget, context: TaskGraphSubmitContext): Promise<{
|
|
372
|
+
Success: boolean;
|
|
373
|
+
Debug?: TaskGraphDebugState;
|
|
374
|
+
ErrorMessage?: string;
|
|
375
|
+
}>;
|
|
376
|
+
/**
|
|
377
|
+
* Replaces the graph's breakpoint set. Every ID must name a child of this graph — a breakpoint
|
|
378
|
+
* on a task in some other graph would gate nothing and silently lie to the person who set it.
|
|
379
|
+
*/
|
|
380
|
+
SetBreakpoints(parentTaskID: string, taskIDs: string[], context: TaskGraphSubmitContext): Promise<{
|
|
381
|
+
Success: boolean;
|
|
382
|
+
Debug?: TaskGraphDebugState;
|
|
383
|
+
ErrorMessage?: string;
|
|
384
|
+
}>;
|
|
385
|
+
/**
|
|
386
|
+
* Overrides one edge's condition verdict — the operator's answer for a path the engine cannot
|
|
387
|
+
* decide (a held graph) or decided wrongly (a broken guard). `'false'` reads as "branch not
|
|
388
|
+
* taken" and cascades skips; `'true'` opens the gate; `null` removes the override.
|
|
389
|
+
*/
|
|
390
|
+
SetEdgeOverride(parentTaskID: string, edgeID: string, verdict: EdgeOverrideVerdict | null, context: TaskGraphSubmitContext): Promise<{
|
|
391
|
+
Success: boolean;
|
|
392
|
+
Debug?: TaskGraphDebugState;
|
|
393
|
+
ErrorMessage?: string;
|
|
394
|
+
}>;
|
|
395
|
+
/**
|
|
396
|
+
* Declares a Pending step not-taken. Downstream dependents proceed — `Skipped` satisfies a
|
|
397
|
+
* prerequisite — and any open human request for the step is withdrawn so nobody keeps seeing an
|
|
398
|
+
* ask for work the operator decided against.
|
|
399
|
+
*/
|
|
400
|
+
SkipTask(taskID: string, context: TaskGraphSubmitContext): Promise<{
|
|
401
|
+
Success: boolean;
|
|
402
|
+
ErrorMessage?: string;
|
|
403
|
+
}>;
|
|
404
|
+
/**
|
|
405
|
+
* Marks a step Complete with an operator-supplied output.
|
|
406
|
+
*
|
|
407
|
+
* Human steps are refused here on purpose: they already have a first-class completion path
|
|
408
|
+
* (`TaskGraph.CompleteTask`) with the assignee/elevation check, and this verb must not become
|
|
409
|
+
* the door that bypasses it.
|
|
410
|
+
*/
|
|
411
|
+
ForceCompleteTask(taskID: string, outputPayload: unknown, context: TaskGraphSubmitContext): Promise<{
|
|
412
|
+
Success: boolean;
|
|
413
|
+
ErrorMessage?: string;
|
|
414
|
+
}>;
|
|
415
|
+
/**
|
|
416
|
+
* Replaces a Pending step's input — the "edit the brief before stepping" move at a breakpoint.
|
|
417
|
+
* Applies to this run only; the step must not have started.
|
|
418
|
+
*
|
|
419
|
+
* **A guarded statement, not load-check-save.** The in-memory `Status === 'Pending'` check plus
|
|
420
|
+
* `task.Save()` is an unconditional full-row UPDATE: a task claimed in the window between the
|
|
421
|
+
* load and the save has its claim columns reverted to the pre-claim snapshot *while its body
|
|
422
|
+
* runs*, and a second instance then claims it again — the step executes twice. See
|
|
423
|
+
* {@link TaskClaimStore.TryUpdateInputPayload}, which makes the check and the write one atomic
|
|
424
|
+
* operation whose rowcount is the answer.
|
|
425
|
+
*/
|
|
426
|
+
UpdateTaskInput(taskID: string, inputPayload: unknown, context: TaskGraphSubmitContext): Promise<{
|
|
427
|
+
Success: boolean;
|
|
428
|
+
ErrorMessage?: string;
|
|
429
|
+
}>;
|
|
126
430
|
/** Maps every referenced agent name to its ID, or reports all unresolvable names at once. */
|
|
127
431
|
private resolveAgents;
|
|
128
|
-
/**
|
|
432
|
+
/**
|
|
433
|
+
* Maps every referenced action name to its ID, or reports all unresolvable names at once.
|
|
434
|
+
*
|
|
435
|
+
* Deliberately a mirror of {@link resolveAgents} rather than a generalization of it: the two
|
|
436
|
+
* read different entities and produce different error prose, and the shared shape is three
|
|
437
|
+
* lines. Collapsing them would trade a readable failure message for a parameterized lookup.
|
|
438
|
+
*/
|
|
439
|
+
/**
|
|
440
|
+
* Maps every referenced prompt name to its ID.
|
|
441
|
+
*
|
|
442
|
+
* A prompt is addressed by name in the spec and stored as a foreign key on the row, exactly like
|
|
443
|
+
* agents and actions — a name in JSON cannot be joined, checked, or survive a rename.
|
|
444
|
+
*/
|
|
445
|
+
private resolvePrompts;
|
|
446
|
+
private resolveActions;
|
|
447
|
+
/**
|
|
448
|
+
* Finds or creates the task type used for orchestrated graphs — exactly one of it, ever.
|
|
449
|
+
*
|
|
450
|
+
* **This resolves the engine's discriminator, not a label** (R2-7). Round 1 scoped every sweep
|
|
451
|
+
* arm and both payload-writing guards to this type, so a second row sharing the name lets
|
|
452
|
+
* different processes bind different IDs — and a graph stamped with the other one is invisible
|
|
453
|
+
* to the sweep, never claimed, never settled, its submitting run `Paused` forever, with no
|
|
454
|
+
* error anywhere.
|
|
455
|
+
*
|
|
456
|
+
* Race-safe by INSERT-then-reselect rather than by checking harder. Two concurrent first-ever
|
|
457
|
+
* submissions both read "not there" and both insert; the unique index added in this round makes
|
|
458
|
+
* the loser's insert fail, and the loser then re-reads and finds the winner's row. Checking
|
|
459
|
+
* first is what created the window, so the fix cannot be a better check.
|
|
460
|
+
*/
|
|
129
461
|
private ensureTaskType;
|
|
462
|
+
/**
|
|
463
|
+
* The `AI Workflow` task type's ID, resolved deterministically.
|
|
464
|
+
*
|
|
465
|
+
* `ORDER BY` is not decoration: two rows sharing the name come back in whatever order the engine
|
|
466
|
+
* chooses, so an unordered `MaxRows: 1` lets two processes bind different IDs from the same
|
|
467
|
+
* data. The index this round adds makes duplicates impossible going forward; the ordering makes
|
|
468
|
+
* the resolution deterministic on a database that still has some, and the warning makes the
|
|
469
|
+
* situation visible rather than merely survivable.
|
|
470
|
+
*/
|
|
471
|
+
private findTaskTypeID;
|
|
130
472
|
/** Writes the parent task that represents the graph as a whole. */
|
|
131
473
|
private persistParent;
|
|
132
474
|
/** Writes each child task, returning the tempId -> real ID mapping edges will need. */
|
|
133
475
|
private persistChildren;
|
|
476
|
+
/**
|
|
477
|
+
* Reports the node kinds this dispatcher cannot yet execute, or `null` when the graph is
|
|
478
|
+
* entirely runnable.
|
|
479
|
+
*
|
|
480
|
+
* **Why this is a submit-time check and not a validation rule.** `ValidateTaskGraphSpec` is a
|
|
481
|
+
* pure function over the spec: it answers "is this a well-formed graph?", and its answer must be
|
|
482
|
+
* the same in a browser, a CLI and a server. "Can it run *here*?" is a different question whose
|
|
483
|
+
* answer changes as runners are added, so it belongs to the runtime that owns the runners.
|
|
484
|
+
*
|
|
485
|
+
* **Why refuse rather than persist-and-stall.** `Prompt`, `ForEach`, `While` and `External`
|
|
486
|
+
* are legitimate parts of the spec, but the `Task` row has nowhere to carry a node's `kind` or
|
|
487
|
+
* its typed `configuration` — so a persisted one could not be dispatched even if a runner
|
|
488
|
+
* existed. Refusing at the door tells the author which step is the problem while the graph is
|
|
489
|
+
* still theirs to edit. The alternative is a graph that submits successfully and then never
|
|
490
|
+
* finishes, which costs an operator an afternoon to diagnose.
|
|
491
|
+
*/
|
|
492
|
+
private findUnrunnableKinds;
|
|
134
493
|
/** Writes the dependency edges, translating tempIds to persisted IDs. */
|
|
135
494
|
private persistDependencies;
|
|
136
495
|
private loadChildren;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskGraphService.d.ts","sourceRoot":"","sources":["../src/TaskGraphService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACH,iBAAiB,
|
|
1
|
+
{"version":3,"file":"TaskGraphService.d.ts","sourceRoot":"","sources":["../src/TaskGraphService.ts"],"names":[],"mappings":"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"}
|