@memberjunction/task-graph 0.0.0 → 6.1.0-edge.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 (43) hide show
  1. package/LICENSE +7 -0
  2. package/dist/DispatcherConditionEvaluator.d.ts +10 -0
  3. package/dist/DispatcherConditionEvaluator.d.ts.map +1 -0
  4. package/dist/DispatcherConditionEvaluator.js +27 -0
  5. package/dist/DispatcherConditionEvaluator.js.map +1 -0
  6. package/dist/TaskClaimStore.d.ts +114 -0
  7. package/dist/TaskClaimStore.d.ts.map +1 -0
  8. package/dist/TaskClaimStore.js +218 -0
  9. package/dist/TaskClaimStore.js.map +1 -0
  10. package/dist/TaskGraphDispatcher.d.ts +186 -0
  11. package/dist/TaskGraphDispatcher.d.ts.map +1 -0
  12. package/dist/TaskGraphDispatcher.js +735 -0
  13. package/dist/TaskGraphDispatcher.js.map +1 -0
  14. package/dist/TaskGraphService.d.ts +138 -0
  15. package/dist/TaskGraphService.d.ts.map +1 -0
  16. package/dist/TaskGraphService.js +314 -0
  17. package/dist/TaskGraphService.js.map +1 -0
  18. package/dist/TaskGraphSubmitterImpl.d.ts +7 -0
  19. package/dist/TaskGraphSubmitterImpl.d.ts.map +1 -0
  20. package/dist/TaskGraphSubmitterImpl.js +52 -0
  21. package/dist/TaskGraphSubmitterImpl.js.map +1 -0
  22. package/dist/WorkflowSpecSync.d.ts +171 -0
  23. package/dist/WorkflowSpecSync.d.ts.map +1 -0
  24. package/dist/WorkflowSpecSync.js +393 -0
  25. package/dist/WorkflowSpecSync.js.map +1 -0
  26. package/dist/index.d.ts +18 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +18 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/operations/TaskGraphOperations.d.ts +39 -0
  31. package/dist/operations/TaskGraphOperations.d.ts.map +1 -0
  32. package/dist/operations/TaskGraphOperations.js +164 -0
  33. package/dist/operations/TaskGraphOperations.js.map +1 -0
  34. package/dist/operations/WorkflowOperations.d.ts +22 -0
  35. package/dist/operations/WorkflowOperations.d.ts.map +1 -0
  36. package/dist/operations/WorkflowOperations.js +99 -0
  37. package/dist/operations/WorkflowOperations.js.map +1 -0
  38. package/dist/types.d.ts +214 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +9 -0
  41. package/dist/types.js.map +1 -0
  42. package/package.json +33 -8
  43. package/README.md +0 -45
@@ -0,0 +1,39 @@
1
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ import { TaskGraphSubmitOperation, TaskGraphCancelOperation, TaskGraphRetryTaskOperation, TaskGraphGetStatusOperation, type TaskGraphSubmitInput, type TaskGraphSubmitOutput, type TaskGraphControlInput, type TaskGraphControlOutput, type TaskGraphRetryInput, type TaskGraphStatusOutput } from '@memberjunction/core-entities';
3
+ /**
4
+ * `TaskGraph.Submit` — validate and durably persist a graph, returning immediately.
5
+ *
6
+ * Returning before execution is the point: the caller is freed the moment the work is safe, and the
7
+ * dispatcher owns it from there. That is what lets an agent submit a graph over MCP without holding
8
+ * anything open.
9
+ */
10
+ export declare class TaskGraphSubmitServerOperation extends TaskGraphSubmitOperation {
11
+ protected InternalExecute(input: TaskGraphSubmitInput, provider: IMetadataProvider, user: UserInfo): Promise<TaskGraphSubmitOutput>;
12
+ }
13
+ /** `TaskGraph.Cancel` — cancel a graph and every task in it that has not already settled. */
14
+ export declare class TaskGraphCancelServerOperation extends TaskGraphCancelOperation {
15
+ protected InternalExecute(input: TaskGraphControlInput, provider: IMetadataProvider, user: UserInfo): Promise<TaskGraphControlOutput>;
16
+ }
17
+ /**
18
+ * `TaskGraph.RetryTask` — return a failed task to `Pending` and unblock its dependents.
19
+ *
20
+ * Unblocking is not optional: retrying a task while its dependents remain `Blocked` leaves the graph
21
+ * exactly as stuck as before, because nothing downstream ever becomes eligible again.
22
+ */
23
+ export declare class TaskGraphRetryTaskServerOperation extends TaskGraphRetryTaskOperation {
24
+ protected InternalExecute(input: TaskGraphRetryInput, provider: IMetadataProvider, user: UserInfo): Promise<TaskGraphControlOutput>;
25
+ }
26
+ /**
27
+ * `TaskGraph.GetStatus` — snapshot a graph's progress without waiting for anything.
28
+ *
29
+ * This is the observation half of making execution durable. Once nobody holds a request open, a
30
+ * caller — a client re-attaching after reload, an agent checking work it submitted, an external MCP
31
+ * caller — needs a way to ask "where is it?". The rollup uses the same pure algorithm the dispatcher
32
+ * uses, so the reported status cannot disagree with the engine's own view.
33
+ */
34
+ export declare class TaskGraphGetStatusServerOperation extends TaskGraphGetStatusOperation {
35
+ protected InternalExecute(input: TaskGraphControlInput, provider: IMetadataProvider, user: UserInfo): Promise<TaskGraphStatusOutput>;
36
+ }
37
+ /** Prevents tree-shaking of the registered operation classes. */
38
+ export declare function LoadTaskGraphOperations(): void;
39
+ //# sourceMappingURL=TaskGraphOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskGraphOperations.d.ts","sourceRoot":"","sources":["../../src/operations/TaskGraphOperations.ts"],"names":[],"mappings":"AAqBA,OAAO,EAA0B,iBAAiB,EAAW,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAEH,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC7B,MAAM,+BAA+B,CAAC;AAsCvC;;;;;;GAMG;AACH,qBACa,8BAA+B,SAAQ,wBAAwB;cACxD,eAAe,CAC3B,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,qBAAqB,CAAC;CAepC;AAED,6FAA6F;AAC7F,qBACa,8BAA+B,SAAQ,wBAAwB;cACxD,eAAe,CAC3B,KAAK,EAAE,qBAAqB,EAC5B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,sBAAsB,CAAC;CAYrC;AAED;;;;;GAKG;AACH,qBACa,iCAAkC,SAAQ,2BAA2B;cAC9D,eAAe,CAC3B,KAAK,EAAE,mBAAmB,EAC1B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,sBAAsB,CAAC;CAUrC;AAED;;;;;;;GAOG;AACH,qBACa,iCAAkC,SAAQ,2BAA2B;cAC9D,eAAe,CAC3B,KAAK,EAAE,qBAAqB,EAC5B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,qBAAqB,CAAC;CAkCpC;AAED,iEAAiE;AACjE,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C"}
@@ -0,0 +1,164 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview Remote Operation implementations for the task-graph control plane.
9
+ *
10
+ * **Why these exist rather than bespoke GraphQL mutations.** Remote Operations are MJ's *typed
11
+ * control plane* — one call site reachable from MCP (external agents), from an Action wrapper
12
+ * (internal agents), and from the UI. Phase 2 originally shipped `SubmitTaskGraph` /
13
+ * `CancelTaskGraph` / `RetryTask` as GraphQL mutations, which fixed the durability problem but left
14
+ * the reachability one exactly where it was: callable from the Explorer client and nothing else.
15
+ *
16
+ * That was inconsistent with the closest analogous substrate — Record Set Processing exposes
17
+ * `Run` / `Pause` / `Resume` / `Cancel` / `Get Run Status` entirely as Remote Operations — and it
18
+ * undercut the program's own goal of letting agents *set up* workflows rather than only navigate to
19
+ * them. These operations replace those mutations.
20
+ *
21
+ * Each row is `GenerationType=Manual`, so CodeGen emits a typed base into `@memberjunction/core-entities`
22
+ * and these subclasses supply the body. All logic stays in `TaskGraphService`; these are thin
23
+ * adapters, and the last registration wins by import order per the ClassFactory contract.
24
+ *
25
+ * @module @memberjunction/task-graph
26
+ */
27
+ import { RegisterClass } from '@memberjunction/global';
28
+ import { BaseRemotableOperation, RunView } from '@memberjunction/core';
29
+ import { TaskGraphSubmitOperation, TaskGraphCancelOperation, TaskGraphRetryTaskOperation, TaskGraphGetStatusOperation, } from '@memberjunction/core-entities';
30
+ import { ComputeParentRollup } from '@memberjunction/ai-core-plus';
31
+ import { TaskGraphService } from '../TaskGraphService.js';
32
+ /**
33
+ * Builds the service context from the operation's provider + user.
34
+ *
35
+ * `environmentID` is empty on the cancel/retry paths and that is not a placeholder: the graph
36
+ * already exists, so nothing is created that would need one, and `TaskGraphService` reads the field
37
+ * only while persisting a new graph.
38
+ */
39
+ function submitContext(provider, user, environmentID, conversationDetailID) {
40
+ return {
41
+ EnvironmentID: environmentID,
42
+ ConversationDetailID: conversationDetailID ?? null,
43
+ ContextUser: user,
44
+ Provider: provider,
45
+ };
46
+ }
47
+ /**
48
+ * `TaskGraph.Submit` — validate and durably persist a graph, returning immediately.
49
+ *
50
+ * Returning before execution is the point: the caller is freed the moment the work is safe, and the
51
+ * dispatcher owns it from there. That is what lets an agent submit a graph over MCP without holding
52
+ * anything open.
53
+ */
54
+ let TaskGraphSubmitServerOperation = class TaskGraphSubmitServerOperation extends TaskGraphSubmitOperation {
55
+ async InternalExecute(input, provider, user) {
56
+ if (!input?.spec)
57
+ throw new Error('spec is required');
58
+ if (!input?.environmentID)
59
+ throw new Error('environmentID is required');
60
+ const spec = input.spec;
61
+ const result = await new TaskGraphService().Submit(spec, submitContext(provider, user, input.environmentID, input.conversationDetailID));
62
+ return {
63
+ success: result.Success,
64
+ parentTaskID: result.ParentTaskID,
65
+ errorMessage: result.ErrorMessage,
66
+ };
67
+ }
68
+ };
69
+ TaskGraphSubmitServerOperation = __decorate([
70
+ RegisterClass(BaseRemotableOperation, 'TaskGraph.Submit')
71
+ ], TaskGraphSubmitServerOperation);
72
+ export { TaskGraphSubmitServerOperation };
73
+ /** `TaskGraph.Cancel` — cancel a graph and every task in it that has not already settled. */
74
+ let TaskGraphCancelServerOperation = class TaskGraphCancelServerOperation extends TaskGraphCancelOperation {
75
+ async InternalExecute(input, provider, user) {
76
+ if (!input?.parentTaskID)
77
+ throw new Error('parentTaskID is required');
78
+ // EnvironmentID is unused on the cancel path — the graph already exists, so nothing new is
79
+ // created that would need one.
80
+ const ok = await new TaskGraphService().Cancel(input.parentTaskID, submitContext(provider, user, ''));
81
+ if (!ok)
82
+ return { success: false, errorMessage: 'Cancel failed; see the server log for detail.' };
83
+ const parent = await provider.GetEntityObject('MJ: Tasks', user);
84
+ const loaded = await parent.Load(input.parentTaskID);
85
+ return { success: true, status: loaded ? parent.Status : undefined };
86
+ }
87
+ };
88
+ TaskGraphCancelServerOperation = __decorate([
89
+ RegisterClass(BaseRemotableOperation, 'TaskGraph.Cancel')
90
+ ], TaskGraphCancelServerOperation);
91
+ export { TaskGraphCancelServerOperation };
92
+ /**
93
+ * `TaskGraph.RetryTask` — return a failed task to `Pending` and unblock its dependents.
94
+ *
95
+ * Unblocking is not optional: retrying a task while its dependents remain `Blocked` leaves the graph
96
+ * exactly as stuck as before, because nothing downstream ever becomes eligible again.
97
+ */
98
+ let TaskGraphRetryTaskServerOperation = class TaskGraphRetryTaskServerOperation extends TaskGraphRetryTaskOperation {
99
+ async InternalExecute(input, provider, user) {
100
+ if (!input?.taskID)
101
+ throw new Error('taskID is required');
102
+ const ok = await new TaskGraphService().Retry(input.taskID, submitContext(provider, user, ''));
103
+ if (!ok)
104
+ return { success: false, errorMessage: 'Retry failed; the task may not be in a Failed state.' };
105
+ const task = await provider.GetEntityObject('MJ: Tasks', user);
106
+ const loaded = await task.Load(input.taskID);
107
+ return { success: true, status: loaded ? task.Status : undefined };
108
+ }
109
+ };
110
+ TaskGraphRetryTaskServerOperation = __decorate([
111
+ RegisterClass(BaseRemotableOperation, 'TaskGraph.RetryTask')
112
+ ], TaskGraphRetryTaskServerOperation);
113
+ export { TaskGraphRetryTaskServerOperation };
114
+ /**
115
+ * `TaskGraph.GetStatus` — snapshot a graph's progress without waiting for anything.
116
+ *
117
+ * This is the observation half of making execution durable. Once nobody holds a request open, a
118
+ * caller — a client re-attaching after reload, an agent checking work it submitted, an external MCP
119
+ * caller — needs a way to ask "where is it?". The rollup uses the same pure algorithm the dispatcher
120
+ * uses, so the reported status cannot disagree with the engine's own view.
121
+ */
122
+ let TaskGraphGetStatusServerOperation = class TaskGraphGetStatusServerOperation extends TaskGraphGetStatusOperation {
123
+ async InternalExecute(input, provider, user) {
124
+ if (!input?.parentTaskID)
125
+ throw new Error('parentTaskID is required');
126
+ // Read-only snapshot, so `simple` + a narrow field list — no reason to pay for entity
127
+ // objects here. Scoped to the operation's own provider rather than the global default.
128
+ const children = await RunView.FromMetadataProvider(provider).RunView({
129
+ EntityName: 'MJ: Tasks',
130
+ ExtraFilter: `ParentID='${input.parentTaskID}'`,
131
+ Fields: ['ID', 'Name', 'Status', 'AgentRunID', 'ErrorMessage'],
132
+ ResultType: 'simple',
133
+ }, user);
134
+ if (!children.Success) {
135
+ return { success: false, errorMessage: children.ErrorMessage ?? 'Could not load the graph.' };
136
+ }
137
+ const rows = children.Results ?? [];
138
+ const rollup = ComputeParentRollup(rows.map((r) => ({ id: r.ID, status: r.Status })));
139
+ return {
140
+ success: true,
141
+ status: rollup.status,
142
+ percentComplete: rollup.percentComplete,
143
+ tasks: rows.map((r) => ({
144
+ taskID: r.ID,
145
+ name: r.Name,
146
+ status: r.Status,
147
+ agentRunID: r.AgentRunID ?? undefined,
148
+ errorMessage: r.ErrorMessage ?? undefined,
149
+ })),
150
+ };
151
+ }
152
+ };
153
+ TaskGraphGetStatusServerOperation = __decorate([
154
+ RegisterClass(BaseRemotableOperation, 'TaskGraph.GetStatus')
155
+ ], TaskGraphGetStatusServerOperation);
156
+ export { TaskGraphGetStatusServerOperation };
157
+ /** Prevents tree-shaking of the registered operation classes. */
158
+ export function LoadTaskGraphOperations() {
159
+ void TaskGraphSubmitServerOperation;
160
+ void TaskGraphCancelServerOperation;
161
+ void TaskGraphRetryTaskServerOperation;
162
+ void TaskGraphGetStatusServerOperation;
163
+ }
164
+ //# sourceMappingURL=TaskGraphOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskGraphOperations.js","sourceRoot":"","sources":["../../src/operations/TaskGraphOperations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
2
+ import { WorkflowSaveOperation, WorkflowValidateOperation, type WorkflowSaveInput, type WorkflowSaveOutput, type WorkflowValidateOutput } from '@memberjunction/core-entities';
3
+ import { ValidateWorkflowSpec } from '@memberjunction/ai-core-plus';
4
+ /** `Workflow.Save` — validate a workflow and reconcile every substrate it owns. */
5
+ export declare class WorkflowSaveServerOperation extends WorkflowSaveOperation {
6
+ protected InternalExecute(input: WorkflowSaveInput, provider: IMetadataProvider, user: UserInfo): Promise<WorkflowSaveOutput>;
7
+ }
8
+ /**
9
+ * `Workflow.Validate` — check a workflow without saving it.
10
+ *
11
+ * Writes nothing, which is the point: an agent drafting a workflow can iterate until it is right
12
+ * before anything reaches the scheduler. Reports every failure at once rather than the first, so a
13
+ * fix takes one round-trip rather than several.
14
+ */
15
+ export declare class WorkflowValidateServerOperation extends WorkflowValidateOperation {
16
+ protected InternalExecute(input: WorkflowSaveInput, _provider: IMetadataProvider, _user: UserInfo): Promise<WorkflowValidateOutput>;
17
+ }
18
+ /** Renders validation failures for a caller that wants one string. */
19
+ export declare function FormatWorkflowErrors(errors: ReturnType<typeof ValidateWorkflowSpec>['Errors']): string;
20
+ /** Prevents tree-shaking of the registered operation classes. */
21
+ export declare function LoadWorkflowOperations(): void;
22
+ //# sourceMappingURL=WorkflowOperations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowOperations.d.ts","sourceRoot":"","sources":["../../src/operations/WorkflowOperations.ts"],"names":[],"mappings":"AAiBA,OAAO,EAA0B,iBAAiB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACH,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEH,oBAAoB,EAEvB,MAAM,8BAA8B,CAAC;AAmBtC,mFAAmF;AACnF,qBACa,2BAA4B,SAAQ,qBAAqB;cAClD,eAAe,CAC3B,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,kBAAkB,CAAC;CAmBjC;AAED;;;;;;GAMG;AACH,qBACa,+BAAgC,SAAQ,yBAAyB;cAC1D,eAAe,CAC3B,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,iBAAiB,EAC5B,KAAK,EAAE,QAAQ,GAChB,OAAO,CAAC,sBAAsB,CAAC;CAWrC;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM,CAEtG;AAED,iEAAiE;AACjE,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C"}
@@ -0,0 +1,99 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview Remote Operations for authoring workflows.
9
+ *
10
+ * **This is the hole the program set out to close.** Agents could already *navigate* to a workflow;
11
+ * they could not *set one up*. Today `Create Scheduled Job` cannot even set `Configuration`, so an
12
+ * agent asked to "run this every Monday" had nothing to call. These two operations make authoring a
13
+ * workflow — steps and triggers together — a single typed call reachable from MCP (external agents),
14
+ * an Action wrapper (internal agents), and the editor.
15
+ *
16
+ * **Two operations, not one, because drafting and committing are different acts.** `Validate` lets an
17
+ * agent iterate on a draft without writing anything — the draft-then-confirm shape dry-run and Plan
18
+ * Mode already established. `Save` commits. Both run the identical validator, so a workflow that
19
+ * validates cannot then be rejected on save for a different reason.
20
+ *
21
+ * @module @memberjunction/task-graph
22
+ */
23
+ import { RegisterClass, MJGlobal } from '@memberjunction/global';
24
+ import { BaseRemotableOperation } from '@memberjunction/core';
25
+ import { WorkflowSaveOperation, WorkflowValidateOperation, } from '@memberjunction/core-entities';
26
+ import { FormatWorkflowValidationErrors, ValidateWorkflowSpec, } from '@memberjunction/ai-core-plus';
27
+ import { WorkflowSpecSync } from '../WorkflowSpecSync.js';
28
+ /**
29
+ * Resolves the host's agent writer, or null.
30
+ *
31
+ * Looked up through the ClassFactory rather than imported so this package does not depend on the
32
+ * agent-manager. Null is a legitimate configuration (a worker, a test) and produces an honest
33
+ * failure rather than a half-saved workflow.
34
+ */
35
+ function resolveAgentWriter() {
36
+ return MJGlobal.Instance.ClassFactory.CreateInstance(
37
+ // The base class is declared in the agent-manager; resolving by key alone keeps this package
38
+ // free of that import while still finding whatever the host registered.
39
+ Object, 'WorkflowAgentWriter');
40
+ }
41
+ /** `Workflow.Save` — validate a workflow and reconcile every substrate it owns. */
42
+ let WorkflowSaveServerOperation = class WorkflowSaveServerOperation extends WorkflowSaveOperation {
43
+ async InternalExecute(input, provider, user) {
44
+ if (!input?.spec)
45
+ throw new Error('spec is required');
46
+ const spec = input.spec;
47
+ const result = await new WorkflowSpecSync(resolveAgentWriter()).Persist(spec, {
48
+ ContextUser: user,
49
+ Provider: provider,
50
+ });
51
+ return {
52
+ success: result.Success,
53
+ agentID: result.AgentID,
54
+ scheduledJobIDs: result.ScheduledJobIDs,
55
+ // Surfaced, not swallowed: a user who asked for "run this when an invoice changes" and
56
+ // got a workflow that never fires has no way to discover why from the UI alone.
57
+ unreconciled: result.Unreconciled.length ? result.Unreconciled : undefined,
58
+ errorMessage: result.ErrorMessage,
59
+ };
60
+ }
61
+ };
62
+ WorkflowSaveServerOperation = __decorate([
63
+ RegisterClass(BaseRemotableOperation, 'Workflow.Save')
64
+ ], WorkflowSaveServerOperation);
65
+ export { WorkflowSaveServerOperation };
66
+ /**
67
+ * `Workflow.Validate` — check a workflow without saving it.
68
+ *
69
+ * Writes nothing, which is the point: an agent drafting a workflow can iterate until it is right
70
+ * before anything reaches the scheduler. Reports every failure at once rather than the first, so a
71
+ * fix takes one round-trip rather than several.
72
+ */
73
+ let WorkflowValidateServerOperation = class WorkflowValidateServerOperation extends WorkflowValidateOperation {
74
+ async InternalExecute(input, _provider, _user) {
75
+ if (!input?.spec)
76
+ throw new Error('spec is required');
77
+ const validation = ValidateWorkflowSpec(input.spec);
78
+ return {
79
+ valid: validation.Valid,
80
+ errors: validation.Errors.length
81
+ ? validation.Errors.map((e) => ({ code: e.Code, message: e.Message, triggerIndex: e.TriggerIndex }))
82
+ : undefined,
83
+ };
84
+ }
85
+ };
86
+ WorkflowValidateServerOperation = __decorate([
87
+ RegisterClass(BaseRemotableOperation, 'Workflow.Validate')
88
+ ], WorkflowValidateServerOperation);
89
+ export { WorkflowValidateServerOperation };
90
+ /** Renders validation failures for a caller that wants one string. */
91
+ export function FormatWorkflowErrors(errors) {
92
+ return FormatWorkflowValidationErrors(errors);
93
+ }
94
+ /** Prevents tree-shaking of the registered operation classes. */
95
+ export function LoadWorkflowOperations() {
96
+ void WorkflowSaveServerOperation;
97
+ void WorkflowValidateServerOperation;
98
+ }
99
+ //# sourceMappingURL=WorkflowOperations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkflowOperations.js","sourceRoot":"","sources":["../../src/operations/WorkflowOperations.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAA+B,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EACH,qBAAqB,EACrB,yBAAyB,GAI5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACH,8BAA8B,EAC9B,oBAAoB,GAEvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAA4B,MAAM,qBAAqB,CAAC;AAEjF;;;;;;GAMG;AACH,SAAS,kBAAkB;IACvB,OAAO,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,cAAc;IAChD,6FAA6F;IAC7F,wEAAwE;IACxE,MAAkD,EAClD,qBAAqB,CACxB,CAAC;AACN,CAAC;AAED,mFAAmF;AAE5E,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,qBAAqB;IACxD,KAAK,CAAC,eAAe,CAC3B,KAAwB,EACxB,QAA2B,EAC3B,IAAc;QAEd,IAAI,CAAC,KAAK,EAAE,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEtD,MAAM,IAAI,GAAiB,KAAK,CAAC,IAAI,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE;YAC1E,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;QAEH,OAAO;YACH,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,uFAAuF;YACvF,gFAAgF;YAChF,YAAY,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;YAC1E,YAAY,EAAE,MAAM,CAAC,YAAY;SACpC,CAAC;IACN,CAAC;CACJ,CAAA;AAxBY,2BAA2B;IADvC,aAAa,CAAC,sBAAsB,EAAE,eAAe,CAAC;GAC1C,2BAA2B,CAwBvC;;AAED;;;;;;GAMG;AAEI,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,yBAAyB;IAChE,KAAK,CAAC,eAAe,CAC3B,KAAwB,EACxB,SAA4B,EAC5B,KAAe;QAEf,IAAI,CAAC,KAAK,EAAE,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAEtD,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAoB,CAAC,CAAC;QACpE,OAAO;YACH,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,MAAM;gBAC5B,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;gBACpG,CAAC,CAAC,SAAS;SAClB,CAAC;IACN,CAAC;CACJ,CAAA;AAhBY,+BAA+B;IAD3C,aAAa,CAAC,sBAAsB,EAAE,mBAAmB,CAAC;GAC9C,+BAA+B,CAgB3C;;AAED,sEAAsE;AACtE,MAAM,UAAU,oBAAoB,CAAC,MAAyD;IAC1F,OAAO,8BAA8B,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,sBAAsB;IAClC,KAAK,2BAA2B,CAAC;IACjC,KAAK,+BAA+B,CAAC;AACzC,CAAC"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * @fileoverview Contracts for task-graph submission and durable execution.
3
+ * @module @memberjunction/task-graph
4
+ */
5
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
6
+ /**
7
+ * Mints a fresh metadata/data provider.
8
+ *
9
+ * The dispatcher runs outside any HTTP request and executes tasks concurrently, so it must never
10
+ * share one provider — and therefore one transaction scope — across parallel work. Rather than
11
+ * import MJServer (which would invert the dependency: MJServer depends on this package, not the
12
+ * reverse), the host supplies a factory. MJServer's implementation wraps the same
13
+ * `createPerRequestProviders` machinery that already mints a provider per request over the shared
14
+ * connection pool, which is proven cheap at request scale.
15
+ *
16
+ * Contract: every call returns a provider safe to use on its own transaction scope. Callers are
17
+ * responsible for nothing beyond using it — pooling and lifetime are the host's concern.
18
+ */
19
+ export type ProviderFactory = {
20
+ CreateProvider(): Promise<IMetadataProvider>;
21
+ };
22
+ /**
23
+ * Runs one agent for one task node.
24
+ *
25
+ * Abstracted rather than taking `AgentRunner` directly so the dispatcher can be unit-tested without
26
+ * standing up the agent framework, and so a host with a different execution strategy (a queue, a
27
+ * remote worker) can supply its own.
28
+ */
29
+ export type TaskAgentRunner = {
30
+ RunAgentForTask(params: TaskAgentRunParams): Promise<TaskAgentRunResult>;
31
+ };
32
+ /** What happened to a task or a graph, as a closed set a consumer can branch on. */
33
+ export type TaskGraphFrameKind =
34
+ /** A task was claimed by an instance and is about to run. */
35
+ 'TaskStarted'
36
+ /** A task finished successfully. */
37
+ | 'TaskCompleted'
38
+ /** A task failed. `ErrorMessage` says why. */
39
+ | 'TaskFailed'
40
+ /** A task was blocked because a prerequisite failed or became unreachable. */
41
+ | 'TaskBlocked'
42
+ /** A human task became actionable and is waiting on its assignee. */
43
+ | 'TaskAwaitingHuman'
44
+ /** Every node has reached a terminal state; `Status` is the graph's rolled-up outcome. */
45
+ | 'GraphSettled';
46
+ /**
47
+ * One thing that happened, addressed by the graph it happened in.
48
+ *
49
+ * **Addressed by `ParentTaskID`, deliberately not by session.** A durable graph outlives the tab
50
+ * that submitted it — it may be started by a schedule with no session at all, and a user who
51
+ * refreshes mid-run should still see the rest. Keying on the graph means "watch this workflow run"
52
+ * works for anyone permitted to read it, whenever they arrive.
53
+ *
54
+ * Frames are **semantic, not cache invalidations**: a consumer renders "step 3 of 7 running" from
55
+ * the frame itself rather than re-reading rows and diffing them to guess what changed.
56
+ */
57
+ export type TaskGraphFrame = {
58
+ Kind: TaskGraphFrameKind;
59
+ /** The graph this happened in — the subscription key. */
60
+ ParentTaskID: string;
61
+ /**
62
+ * Who the graph belongs to, from the parent's durable metadata.
63
+ *
64
+ * Carried on the frame rather than looked up by the consumer because a consumer's delivery
65
+ * filter runs per frame and synchronously — a database round trip there would make watching a
66
+ * run cost more than running it. Absent means the graph predates ownership being recorded, and
67
+ * a consumer that authorizes on it should fail closed rather than broadcast.
68
+ */
69
+ OwnerUserID?: string | null;
70
+ /** The node it happened to. Absent on `GraphSettled`, which is about the graph itself. */
71
+ TaskID?: string;
72
+ /** Node name, so a consumer can label the frame without loading the row. */
73
+ TaskName?: string;
74
+ /** The task's (or, for `GraphSettled`, the graph's) status after the event. */
75
+ Status?: string;
76
+ /** Failure detail on `TaskFailed`. */
77
+ ErrorMessage?: string;
78
+ /** For a human task, who it is waiting on. */
79
+ AssignedUserID?: string;
80
+ /** How many nodes have reached a terminal state, and out of how many. */
81
+ CompletedCount?: number;
82
+ TotalCount?: number;
83
+ };
84
+ /**
85
+ * Receives dispatcher lifecycle frames.
86
+ *
87
+ * Optional, and a host that supplies none loses nothing but visibility — the dispatcher's behavior
88
+ * is identical either way. Abstracted for the same reason execution and continuation are: publishing
89
+ * to subscribers is a transport concern, and this package must not acquire a dependency on the
90
+ * transport layer to gain observability.
91
+ *
92
+ * Implementations MUST NOT throw and MUST NOT block: a frame is an announcement about work, never a
93
+ * step of it, so a broken observer must not be able to stall or fail a graph.
94
+ */
95
+ export type TaskGraphObserver = {
96
+ OnFrame(frame: TaskGraphFrame): void;
97
+ };
98
+ /** Everything an executor needs to run a single task node. */
99
+ export type TaskAgentRunParams = {
100
+ /** The task row being executed. */
101
+ TaskID: string;
102
+ /** Agent assigned to the task. */
103
+ AgentID: string;
104
+ /** Parsed `Task.InputPayload`, if any. */
105
+ InputPayload: unknown;
106
+ /** Parsed `OutputPayload` of each completed dependency, keyed by that task's ID. */
107
+ DependencyOutputs: Map<string, unknown>;
108
+ /** Provider minted for this task alone — never shared with a sibling. */
109
+ Provider: IMetadataProvider;
110
+ /** User the work runs as. */
111
+ ContextUser: UserInfo;
112
+ };
113
+ /** Outcome of running one task node. */
114
+ export type TaskAgentRunResult = {
115
+ Success: boolean;
116
+ /** Structured output to persist to `Task.OutputPayload`. */
117
+ Output?: unknown;
118
+ /** Failure detail to persist to `Task.ErrorMessage`. */
119
+ ErrorMessage?: string;
120
+ /** The `MJ: AI Agent Runs` row that executed this task, for `Task.AgentRunID`. */
121
+ AgentRunID?: string;
122
+ };
123
+ /**
124
+ * Delivers a finished graph's outcome, per its `continuation` mode.
125
+ *
126
+ * Abstracted for the same reason agent execution is: the dispatcher knows *when* a graph has
127
+ * settled and *what* it produced, but posting into a conversation and starting a fresh agent turn
128
+ * are host concerns. Injecting them keeps this package free of both the conversation layer and the
129
+ * agent framework — a dependency on the latter would be circular, since agents submit graphs.
130
+ *
131
+ * A host that implements neither still gets correct behavior: the dispatcher logs the outcome and
132
+ * marks it delivered, so a graph never silently repeats its completion.
133
+ */
134
+ export type TaskContinuationDeliverer = {
135
+ /** Posts the results into the conversation the graph answers. */
136
+ PostMessage(params: TaskContinuationParams): Promise<void>;
137
+ /**
138
+ * Starts the submitting agent a fresh turn carrying the outcome.
139
+ *
140
+ * Optional: a host with no agent framework loaded (a worker, a test) legitimately cannot do
141
+ * this, and the dispatcher degrades to `PostMessage` rather than dropping the completion.
142
+ */
143
+ Reinvoke?(params: TaskContinuationParams): Promise<void>;
144
+ };
145
+ /** Everything a continuation needs to say what happened. */
146
+ export type TaskContinuationParams = {
147
+ ParentTaskID: string;
148
+ WorkflowName: string;
149
+ /** Conversation the graph answers, when it came from a conversational channel. */
150
+ ConversationDetailID: string | null;
151
+ /** The agent run that emitted the graph — the target of a `reinvoke`. */
152
+ SubmittedByAgentRunID: string | null;
153
+ /** How many continuation hops preceded this one, so a re-submitted graph can carry depth + 1. */
154
+ ReinvokeDepth: number;
155
+ /**
156
+ * Per-task outcome. Deliberately carries a `summary` and an `outputRef`, not inline payloads —
157
+ * a ten-task graph's full outputs would swamp the continuation turn's context window, and the
158
+ * agent can pull what it actually needs by task ID.
159
+ */
160
+ Tasks: Array<{
161
+ TaskID: string;
162
+ Name: string;
163
+ Status: string;
164
+ Summary?: string;
165
+ ErrorMessage?: string;
166
+ }>;
167
+ /** One-line human-readable roll-up. */
168
+ Summary: string;
169
+ };
170
+ /** Tuning knobs for the durable dispatcher. */
171
+ export type TaskGraphDispatcherConfig = {
172
+ /**
173
+ * Identifies this dispatcher instance in `Task.ClaimedBy`. Must be stable for the process
174
+ * lifetime and distinct per instance — it is what lets reconciliation tell "my orphaned work"
175
+ * from "another instance's live work".
176
+ */
177
+ InstanceID: string;
178
+ /**
179
+ * How long a claim is honored before reconciliation may reclaim the task.
180
+ *
181
+ * Generous by default: the cost of a too-short TTL is a *duplicate execution* (a healthy but
182
+ * slow task gets reclaimed while still running), whereas the cost of a too-long TTL is merely
183
+ * delayed recovery after a crash. Long-running tasks extend it by heartbeat, so the TTL only
184
+ * has to exceed the heartbeat interval by a comfortable margin.
185
+ */
186
+ ClaimTTLSeconds: number;
187
+ /** How often an in-flight task extends its own claim. Must be well below `ClaimTTLSeconds`. */
188
+ HeartbeatIntervalSeconds: number;
189
+ /** Maximum tasks executed concurrently by this instance. */
190
+ MaxConcurrentTasks: number;
191
+ /**
192
+ * How often to look for claimable work.
193
+ *
194
+ * Five seconds is the right production default — a graph's steps are agent runs measured in
195
+ * seconds to minutes, so polling faster buys latency nobody perceives and costs a query per
196
+ * instance per tick. It is configurable rather than fixed because the correct value genuinely
197
+ * differs by host: a test harness driving a graph to completion should not wait five seconds per
198
+ * node, and a deployment running many short tasks may want tighter latency.
199
+ */
200
+ PollIntervalSeconds: number;
201
+ /** How often the reconciliation sweep runs. */
202
+ ReconciliationIntervalSeconds: number;
203
+ };
204
+ /** Defaults chosen so a heartbeat has several chances to land before a claim lapses. */
205
+ export declare const DEFAULT_DISPATCHER_CONFIG: Omit<TaskGraphDispatcherConfig, 'InstanceID'>;
206
+ /** Why a reconciliation sweep touched a task — logged loudly, never silently corrected. */
207
+ export type ReconciliationAction = 'ExpiredClaimReleased' | 'OrphanedInProgressReleased' | 'StaleClaimCleared';
208
+ /** One normalization the sweep performed. */
209
+ export type ReconciliationEvent = {
210
+ TaskID: string;
211
+ Action: ReconciliationAction;
212
+ Detail: string;
213
+ };
214
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /** Defaults chosen so a heartbeat has several chances to land before a claim lapses. */
2
+ export const DEFAULT_DISPATCHER_CONFIG = {
3
+ ClaimTTLSeconds: 300,
4
+ HeartbeatIntervalSeconds: 60,
5
+ MaxConcurrentTasks: 5,
6
+ PollIntervalSeconds: 5,
7
+ ReconciliationIntervalSeconds: 120,
8
+ };
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA2NA,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GAAkD;IACpF,eAAe,EAAE,GAAG;IACpB,wBAAwB,EAAE,EAAE;IAC5B,kBAAkB,EAAE,CAAC;IACrB,mBAAmB,EAAE,CAAC;IACtB,6BAA6B,EAAE,GAAG;CACrC,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,35 @@
1
1
  {
2
2
  "name": "@memberjunction/task-graph",
3
- "version": "0.0.0",
4
- "description": "OIDC trusted publishing setup package for @memberjunction/task-graph",
5
- "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
9
- ]
10
- }
3
+ "type": "module",
4
+ "version": "6.1.0-edge.1",
5
+ "description": "MemberJunction: Task Graph - producer-agnostic submission and durable execution of dependency-ordered task graphs",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "/dist"
10
+ ],
11
+ "author": "MemberJunction.com",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "@memberjunction/ai-agents": "6.1.0-edge.1",
15
+ "@memberjunction/ai-core-plus": "6.1.0-edge.1",
16
+ "@memberjunction/core": "6.1.0-edge.1",
17
+ "@memberjunction/core-entities": "6.1.0-edge.1",
18
+ "@memberjunction/global": "6.1.0-edge.1",
19
+ "@memberjunction/notifications": "6.1.0-edge.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "24.10.11",
23
+ "typescript": "^5.9.3",
24
+ "vitest": "^3.2.4"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/MemberJunction/MJ"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc && tsc-alias -f",
32
+ "watch": "tsc --watch",
33
+ "test": "vitest run"
34
+ }
35
+ }