@memberjunction/server 6.1.0-edge.0 → 6.1.0-edge.2

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 (175) hide show
  1. package/dist/auth/exampleNewUserSubClass.js +1 -1
  2. package/dist/auth/exampleNewUserSubClass.js.map +1 -1
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +9 -5
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/magicLink/MagicLinkService.js +1 -1
  7. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  8. package/dist/auth/newUsers.js +1 -1
  9. package/dist/auth/newUsers.js.map +1 -1
  10. package/dist/context.js +2 -2
  11. package/dist/context.js.map +1 -1
  12. package/dist/generated/generated.d.ts +208 -646
  13. package/dist/generated/generated.d.ts.map +1 -1
  14. package/dist/generated/generated.js +1123 -3773
  15. package/dist/generated/generated.js.map +1 -1
  16. package/dist/generic/ResolverBase.d.ts +19 -3
  17. package/dist/generic/ResolverBase.d.ts.map +1 -1
  18. package/dist/generic/ResolverBase.js +51 -17
  19. package/dist/generic/ResolverBase.js.map +1 -1
  20. package/dist/index.d.ts +6 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +100 -42
  23. package/dist/index.js.map +1 -1
  24. package/dist/logging/secretRedactor.d.ts +9 -0
  25. package/dist/logging/secretRedactor.d.ts.map +1 -1
  26. package/dist/logging/secretRedactor.js +39 -0
  27. package/dist/logging/secretRedactor.js.map +1 -1
  28. package/dist/middleware/BaseServerMiddleware.d.ts +5 -0
  29. package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
  30. package/dist/middleware/BaseServerMiddleware.js +5 -0
  31. package/dist/middleware/BaseServerMiddleware.js.map +1 -1
  32. package/dist/realtimeWidget/WidgetSessionService.js +1 -1
  33. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  34. package/dist/realtimeWidget/widgetGuestElevation.js +1 -1
  35. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  36. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  37. package/dist/resolvers/ActionResolver.js +12 -0
  38. package/dist/resolvers/ActionResolver.js.map +1 -1
  39. package/dist/resolvers/ComponentRegistryResolver.js +1 -1
  40. package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
  41. package/dist/resolvers/EntityPermissionResolver.js +1 -1
  42. package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
  43. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +9 -0
  44. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  45. package/dist/resolvers/IntegrationDiscoveryResolver.js +3 -1
  46. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  47. package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
  48. package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
  49. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
  50. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  51. package/dist/resolvers/RealtimeClientSessionResolver.js +5 -0
  52. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  53. package/dist/resolvers/SearchEntitiesResolver.js +1 -1
  54. package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
  55. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  56. package/dist/resolvers/SqlLoggingConfigResolver.js +1 -1
  57. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  58. package/dist/resolvers/SyncRolesUsersResolver.js +2 -2
  59. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  60. package/dist/resolvers/TaskGraphFrameResolver.d.ts +85 -0
  61. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -0
  62. package/dist/resolvers/TaskGraphFrameResolver.js +163 -0
  63. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -0
  64. package/dist/resolvers/UserFavoriteResolver.js +1 -1
  65. package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
  66. package/dist/rest/OAuthCallbackHandler.js +1 -1
  67. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  68. package/dist/rest/RESTEndpointHandler.d.ts +0 -4
  69. package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
  70. package/dist/rest/RESTEndpointHandler.js +1 -15
  71. package/dist/rest/RESTEndpointHandler.js.map +1 -1
  72. package/dist/rest/SignatureWebhookHandler.js +1 -1
  73. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  74. package/dist/services/DurableEntityActionTaskSubmitter.d.ts +26 -0
  75. package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -0
  76. package/dist/services/DurableEntityActionTaskSubmitter.js +55 -0
  77. package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -0
  78. package/dist/services/ScheduledJobsService.js +1 -1
  79. package/dist/services/ScheduledJobsService.js.map +1 -1
  80. package/dist/services/StartTaskGraphDispatcher.d.ts +33 -0
  81. package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -0
  82. package/dist/services/StartTaskGraphDispatcher.js +46 -0
  83. package/dist/services/StartTaskGraphDispatcher.js.map +1 -0
  84. package/dist/services/TaskGraphActionRunner.d.ts +34 -0
  85. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -0
  86. package/dist/services/TaskGraphActionRunner.js +95 -0
  87. package/dist/services/TaskGraphActionRunner.js.map +1 -0
  88. package/dist/services/TaskGraphAgentRunner.d.ts +28 -0
  89. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -0
  90. package/dist/services/TaskGraphAgentRunner.js +104 -0
  91. package/dist/services/TaskGraphAgentRunner.js.map +1 -0
  92. package/dist/services/TaskGraphContinuationDeliverer.d.ts +70 -0
  93. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -0
  94. package/dist/services/TaskGraphContinuationDeliverer.js +162 -0
  95. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -0
  96. package/dist/services/TaskGraphPromptRunner.d.ts +31 -0
  97. package/dist/services/TaskGraphPromptRunner.d.ts.map +1 -0
  98. package/dist/services/TaskGraphPromptRunner.js +134 -0
  99. package/dist/services/TaskGraphPromptRunner.js.map +1 -0
  100. package/dist/services/TaskGraphProviderFactory.d.ts +39 -0
  101. package/dist/services/TaskGraphProviderFactory.d.ts.map +1 -0
  102. package/dist/services/TaskGraphProviderFactory.js +28 -0
  103. package/dist/services/TaskGraphProviderFactory.js.map +1 -0
  104. package/dist/telephony/RingCentralTelephonyService.js +1 -1
  105. package/dist/telephony/RingCentralTelephonyService.js.map +1 -1
  106. package/dist/telephony/TwilioTelephonyRouter.js +1 -1
  107. package/dist/telephony/TwilioTelephonyRouter.js.map +1 -1
  108. package/dist/telephony/VonageTelephonyRouter.js +1 -1
  109. package/dist/telephony/VonageTelephonyRouter.js.map +1 -1
  110. package/package.json +92 -89
  111. package/src/__tests__/RealtimeClientSessionResolver.test.ts +1 -1
  112. package/src/__tests__/ResolverBase.frozenRecordMapping.test.ts +133 -0
  113. package/src/__tests__/ResolverBase.transportMapping.test.ts +289 -0
  114. package/src/__tests__/SessionManager.test.ts +1 -1
  115. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +249 -0
  116. package/src/__tests__/TaskGraphFrameResolver.test.ts +136 -0
  117. package/src/__tests__/WidgetSessionService.test.ts +1 -1
  118. package/src/__tests__/databaseAbstraction.test.ts +1 -1
  119. package/src/__tests__/magicLinkService.provisionLog.test.ts +1 -1
  120. package/src/__tests__/resolverBase.rls.test.ts +3 -0
  121. package/src/__tests__/secretRedactor.failOpen.test.ts +135 -0
  122. package/src/__tests__/widgetGuestElevation.test.ts +1 -1
  123. package/src/auth/exampleNewUserSubClass.ts +1 -1
  124. package/src/auth/index.ts +10 -6
  125. package/src/auth/magicLink/MagicLinkService.ts +1 -1
  126. package/src/auth/newUsers.ts +1 -1
  127. package/src/context.ts +2 -2
  128. package/src/generated/generated.ts +955 -2735
  129. package/src/generic/ResolverBase.ts +52 -17
  130. package/src/index.ts +108 -43
  131. package/src/logging/secretRedactor.ts +43 -0
  132. package/src/middleware/BaseServerMiddleware.ts +5 -0
  133. package/src/realtimeWidget/WidgetSessionService.ts +1 -1
  134. package/src/realtimeWidget/widgetGuestElevation.ts +1 -1
  135. package/src/resolvers/ActionResolver.ts +13 -0
  136. package/src/resolvers/ComponentRegistryResolver.ts +1 -1
  137. package/src/resolvers/EntityPermissionResolver.ts +1 -1
  138. package/src/resolvers/IntegrationDiscoveryResolver.ts +12 -2
  139. package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
  140. package/src/resolvers/RealtimeClientSessionResolver.ts +13 -0
  141. package/src/resolvers/SearchEntitiesResolver.ts +1 -1
  142. package/src/resolvers/SqlLoggingConfigResolver.ts +1 -2
  143. package/src/resolvers/SyncRolesUsersResolver.ts +2 -2
  144. package/src/resolvers/TaskGraphFrameResolver.ts +160 -0
  145. package/src/resolvers/UserFavoriteResolver.ts +1 -1
  146. package/src/rest/OAuthCallbackHandler.ts +1 -1
  147. package/src/rest/RESTEndpointHandler.ts +1 -15
  148. package/src/rest/SignatureWebhookHandler.ts +1 -1
  149. package/src/services/DurableEntityActionTaskSubmitter.ts +78 -0
  150. package/src/services/ScheduledJobsService.ts +1 -1
  151. package/src/services/StartTaskGraphDispatcher.ts +78 -0
  152. package/src/services/TaskGraphActionRunner.ts +99 -0
  153. package/src/services/TaskGraphAgentRunner.ts +115 -0
  154. package/src/services/TaskGraphContinuationDeliverer.ts +181 -0
  155. package/src/services/TaskGraphPromptRunner.ts +144 -0
  156. package/src/services/TaskGraphProviderFactory.ts +53 -0
  157. package/src/telephony/RingCentralTelephonyService.ts +1 -1
  158. package/src/telephony/TwilioTelephonyRouter.ts +1 -1
  159. package/src/telephony/VonageTelephonyRouter.ts +1 -1
  160. package/dist/resolvers/ReportResolver.d.ts +0 -24
  161. package/dist/resolvers/ReportResolver.d.ts.map +0 -1
  162. package/dist/resolvers/ReportResolver.js +0 -198
  163. package/dist/resolvers/ReportResolver.js.map +0 -1
  164. package/dist/resolvers/TaskResolver.d.ts +0 -31
  165. package/dist/resolvers/TaskResolver.d.ts.map +0 -1
  166. package/dist/resolvers/TaskResolver.js +0 -157
  167. package/dist/resolvers/TaskResolver.js.map +0 -1
  168. package/dist/services/TaskOrchestrator.d.ts +0 -130
  169. package/dist/services/TaskOrchestrator.d.ts.map +0 -1
  170. package/dist/services/TaskOrchestrator.js +0 -692
  171. package/dist/services/TaskOrchestrator.js.map +0 -1
  172. package/src/resolvers/ReportResolver.ts +0 -165
  173. package/src/resolvers/TaskResolver.ts +0 -148
  174. package/src/resolvers/__tests__/ReportResolver.test.ts +0 -279
  175. package/src/services/TaskOrchestrator.ts +0 -873
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @fileoverview MJServer's implementation of the task-graph `TaskContinuationDeliverer` seam.
3
+ *
4
+ * **The dispatcher shipped with nowhere to deliver.** `StartTaskGraphDispatcher` constructed it
5
+ * without a deliverer at all, so a graph that finished logged its outcome, marked itself delivered,
6
+ * and said nothing to the conversation that asked for it. Durable execution nobody hears about is
7
+ * half a promise — the same shape as Phase 2's dispatcher that ran nothing.
8
+ *
9
+ * Posting into a conversation is a host concern by design: the task-graph package must not depend on
10
+ * the conversation layer, and cannot depend on the agent framework at all without a cycle (agents
11
+ * submit graphs). This adapter is where those dependencies are allowed to live.
12
+ *
13
+ * @module @memberjunction/server
14
+ */
15
+ import { LogError, LogStatus, type IMetadataProvider, type UserInfo } from '@memberjunction/core';
16
+ import { MJAIAgentRunEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';
17
+ import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
18
+ import { AgentRunner } from '@memberjunction/ai-agents';
19
+ import { ChatMessageRole } from '@memberjunction/ai';
20
+ import type { ProviderFactory, TaskContinuationDeliverer, TaskContinuationParams } from '@memberjunction/task-graph';
21
+
22
+ /** How many per-task lines a posted summary shows before collapsing the rest into a count. */
23
+ const MAX_LISTED_TASKS = 20;
24
+
25
+ /**
26
+ * Delivers a finished graph's outcome — as a conversation message, or by starting the submitting
27
+ * agent a fresh turn.
28
+ *
29
+ * **The chain is bounded, and that is what took a schema change to make true.** A graph may declare
30
+ * `continuation: 'reinvoke'`, and the agent it restarts can emit another graph, which can reinvoke
31
+ * again. The guard for that (`MAX_REINVOKE_DEPTH`) shipped in Phase 3, but the number it compared
32
+ * was permanently zero: `TaskGraphService.Submit` reads `ReinvokeDepth` from its caller, and a
33
+ * reinvoked agent had no way to know it *was* a continuation. `AIAgentRun.ContinuationDepth` closes
34
+ * that loop — this stamps depth + 1 on the run it starts, `BaseAgent` passes it into any graph that
35
+ * run submits, and the cap finally compares against something real.
36
+ */
37
+ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer {
38
+ /**
39
+ * @param providerFactory mints a fresh provider per delivery, for the same reason the dispatcher
40
+ * does: deliveries run outside any request and concurrently with task execution, so
41
+ * sharing one provider would share one transaction scope across unrelated work.
42
+ */
43
+ constructor(
44
+ private readonly providerFactory: ProviderFactory,
45
+ private readonly contextUser: UserInfo,
46
+ ) {}
47
+
48
+ /**
49
+ * Posts the roll-up as an AI-role message in the graph's conversation.
50
+ *
51
+ * Never throws. The dispatcher calls this inside the compare-and-swap that marks a completion
52
+ * delivered; an error escaping would either abort that guard or leave the graph looking
53
+ * undelivered and re-notifying on every later sweep.
54
+ */
55
+ public async PostMessage(params: TaskContinuationParams): Promise<void> {
56
+ try {
57
+ if (!params.ConversationDetailID) {
58
+ // A graph submitted headlessly — a schedule, an entity-change trigger, an API call —
59
+ // has no conversation to answer. Not an error; most workflows are in this shape.
60
+ LogStatus(`[TaskGraphContinuationDeliverer] "${params.WorkflowName}" finished with no conversation to post to.`);
61
+ return;
62
+ }
63
+
64
+ const provider = await this.providerFactory.CreateProvider();
65
+ const conversationID = await this.resolveConversationID(params.ConversationDetailID, provider);
66
+ if (!conversationID) {
67
+ LogError(
68
+ `[TaskGraphContinuationDeliverer] Conversation detail ${params.ConversationDetailID} could not be loaded — ` +
69
+ `"${params.WorkflowName}" has nowhere to post its outcome.`
70
+ );
71
+ return;
72
+ }
73
+
74
+ const detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', this.contextUser);
75
+ detail.NewRecord();
76
+ detail.ConversationID = conversationID;
77
+ detail.Role = 'AI';
78
+ detail.Status = 'Complete';
79
+ detail.HiddenToUser = false;
80
+ detail.Message = this.renderMessage(params);
81
+
82
+ if (!(await detail.Save())) {
83
+ LogError(
84
+ `[TaskGraphContinuationDeliverer] Could not post the outcome of "${params.WorkflowName}": ` +
85
+ `${detail.LatestResult?.CompleteMessage ?? 'unknown error'}`
86
+ );
87
+ }
88
+ } catch (e) {
89
+ LogError(`[TaskGraphContinuationDeliverer] Posting the outcome of "${params.WorkflowName}" threw`, undefined, e);
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Starts the submitting agent a fresh turn carrying the graph's outcome.
95
+ *
96
+ * Never throws, for the same reason `PostMessage` does not: the dispatcher calls this inside the
97
+ * compare-and-swap that marks a completion delivered.
98
+ *
99
+ * The new run records `ReinvokeDepth + 1` so the chain is bounded. The dispatcher has already
100
+ * refused to call this when the cap is reached — it degrades to `PostMessage` — so arriving here
101
+ * means there is budget left, and stamping the depth is what keeps that true for the next hop.
102
+ */
103
+ public async Reinvoke(params: TaskContinuationParams): Promise<void> {
104
+ try {
105
+ if (!params.SubmittedByAgentRunID) {
106
+ // Nothing to restart. A graph with no submitting run came from a schedule or a
107
+ // trigger, where "continue the conversation" has no meaning.
108
+ LogStatus(`[TaskGraphContinuationDeliverer] "${params.WorkflowName}" asked to reinvoke but records no submitting agent run — posting instead.`);
109
+ await this.PostMessage(params);
110
+ return;
111
+ }
112
+
113
+ const provider = await this.providerFactory.CreateProvider();
114
+ const priorRun = await provider.GetEntityObject<MJAIAgentRunEntity>('MJ: AI Agent Runs', this.contextUser);
115
+ if (!(await priorRun.Load(params.SubmittedByAgentRunID))) {
116
+ LogError(`[TaskGraphContinuationDeliverer] Submitting run ${params.SubmittedByAgentRunID} could not be loaded — posting "${params.WorkflowName}" instead.`);
117
+ await this.PostMessage(params);
118
+ return;
119
+ }
120
+
121
+ const agent = await provider.GetEntityObject<MJAIAgentEntityExtended>('MJ: AI Agents', this.contextUser);
122
+ if (!(await agent.Load(priorRun.AgentID))) {
123
+ LogError(`[TaskGraphContinuationDeliverer] Agent ${priorRun.AgentID} could not be loaded — posting "${params.WorkflowName}" instead.`);
124
+ await this.PostMessage(params);
125
+ return;
126
+ }
127
+
128
+ await new AgentRunner().RunAgent({
129
+ agent,
130
+ conversationMessages: [{ role: ChatMessageRole.user, content: this.renderMessage(params) }],
131
+ contextUser: this.contextUser,
132
+ conversationDetailId: params.ConversationDetailID ?? undefined,
133
+ // The load-bearing value: without it the next graph this run submits restarts the
134
+ // chain at zero and the cap never fires.
135
+ continuationDepth: params.ReinvokeDepth + 1,
136
+ });
137
+ } catch (e) {
138
+ LogError(`[TaskGraphContinuationDeliverer] Reinvoking for "${params.WorkflowName}" threw`, undefined, e);
139
+ }
140
+ }
141
+
142
+ /** The conversation a detail belongs to. */
143
+ private async resolveConversationID(conversationDetailID: string, provider: IMetadataProvider): Promise<string | null> {
144
+ const detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', this.contextUser);
145
+ return (await detail.Load(conversationDetailID)) ? detail.ConversationID : null;
146
+ }
147
+
148
+ /**
149
+ * Renders the outcome as Markdown.
150
+ *
151
+ * Per-task lines rather than one aggregate status: a graph where nine of ten steps succeeded is a
152
+ * materially different message from one that failed outright, and the roll-up alone cannot say
153
+ * which step went wrong. Long graphs truncate so a fifty-step workflow does not bury the
154
+ * conversation — the task rows remain the complete record.
155
+ */
156
+ private renderMessage(params: TaskContinuationParams): string {
157
+ const lines = [`**${params.WorkflowName}** finished.`, '', params.Summary];
158
+
159
+ if (params.Tasks.length > 0) {
160
+ lines.push('');
161
+ for (const task of params.Tasks.slice(0, MAX_LISTED_TASKS)) {
162
+ const detail = task.ErrorMessage ?? task.Summary;
163
+ lines.push(`- ${this.statusIcon(task.Status)} **${task.Name}** — ${task.Status}${detail ? `: ${detail}` : ''}`);
164
+ }
165
+ if (params.Tasks.length > MAX_LISTED_TASKS) {
166
+ lines.push(`- …and ${params.Tasks.length - MAX_LISTED_TASKS} more`);
167
+ }
168
+ }
169
+
170
+ return lines.join('\n');
171
+ }
172
+
173
+ private statusIcon(status: string): string {
174
+ switch (status) {
175
+ case 'Complete': return '✅';
176
+ case 'Failed': return '❌';
177
+ case 'Cancelled': return '⊘';
178
+ default: return '•';
179
+ }
180
+ }
181
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @fileoverview MJServer's implementation of the task-graph `TaskPromptRunner` seam.
3
+ *
4
+ * The third sibling of {@link TaskGraphAgentRunner} and {@link TaskGraphActionRunner}, and here for
5
+ * the same reason: the dispatcher knows *when* a prompt-assigned node should run and nothing about
6
+ * how a prompt executes. The AI engine depends on the entity layer the dispatcher also builds on, so
7
+ * importing it into `@memberjunction/task-graph` would make every consumer of durable execution load
8
+ * the prompt engine too.
9
+ *
10
+ * **Why prompt nodes matter enough to have their own runner.** The `User Onboarding Flow Agent`
11
+ * ships with six of them. Until this existed, every one of its steps was refused at submission and
12
+ * the agent could not run at all — the refusal was correct (a persisted step nothing can execute
13
+ * waits forever) but it made a shipped workflow unusable rather than merely unfinished.
14
+ *
15
+ * @module @memberjunction/server
16
+ */
17
+ import { AIPromptRunner } from '@memberjunction/ai-prompts';
18
+ import { AIEngine } from '@memberjunction/aiengine';
19
+ import { AIPromptParams } from '@memberjunction/ai-core-plus';
20
+ import { LogError } from '@memberjunction/core';
21
+ import { UUIDsEqual } from '@memberjunction/global';
22
+ import type { TaskPromptRunner, TaskPromptRunParams, TaskPromptRunResult } from '@memberjunction/task-graph';
23
+
24
+ /** The placeholder a workflow prompt uses to receive the payload (plan §5.7). */
25
+ const CURRENT_PAYLOAD_PLACEHOLDER = '_CURRENT_PAYLOAD';
26
+
27
+ export class TaskGraphPromptRunner implements TaskPromptRunner {
28
+ public async RunPromptForTask(params: TaskPromptRunParams): Promise<TaskPromptRunResult> {
29
+ try {
30
+ await AIEngine.Instance.Config(false, params.ContextUser);
31
+ const prompt = AIEngine.Instance.Prompts.find((p) => UUIDsEqual(p.ID, params.PromptID));
32
+ if (!prompt) {
33
+ return { Success: false, ErrorMessage: `Prompt ${params.PromptID} is not in the engine's metadata.` };
34
+ }
35
+
36
+ const promptParams = new AIPromptParams();
37
+ promptParams.prompt = prompt;
38
+ promptParams.contextUser = params.ContextUser;
39
+ promptParams.data = this.buildData(params);
40
+
41
+ const result = await new AIPromptRunner().ExecutePrompt(promptParams);
42
+ if (!result?.success) {
43
+ return {
44
+ Success: false,
45
+ ErrorMessage: result?.errorMessage ?? 'The prompt did not return a result.',
46
+ PromptRunID: result?.promptRun?.ID,
47
+ };
48
+ }
49
+
50
+ const parsed = this.parseResponse(result.result);
51
+ return {
52
+ Success: true,
53
+ Output: parsed.payload,
54
+ PromptRunID: result.promptRun?.ID,
55
+ ChatMessage: parsed.chatMessage,
56
+ };
57
+ } catch (e) {
58
+ const message = e instanceof Error ? e.message : String(e);
59
+ LogError(`[TaskGraphPromptRunner] Task ${params.TaskID} failed: ${message}`);
60
+ return { Success: false, ErrorMessage: message };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * What the prompt's template can see.
66
+ *
67
+ * The payload arrives under a **placeholder name** rather than being spread across the top level,
68
+ * so a workflow author writes `{{ _CURRENT_PAYLOAD }}` and gets the whole thing — and a payload
69
+ * key can never collide with a template parameter and silently win.
70
+ *
71
+ * `flowContext` carries what the step knows about its own position: what its prerequisites
72
+ * produced. Without it a prompt is reasoning about the payload alone and cannot refer to the step
73
+ * immediately before it.
74
+ */
75
+ private buildData(params: TaskPromptRunParams): Record<string, unknown> {
76
+ const payload = params.InputPayload && typeof params.InputPayload === 'object'
77
+ ? params.InputPayload as Record<string, unknown>
78
+ : {};
79
+
80
+ const dependencyOutputs: Record<string, unknown> = {};
81
+ for (const [taskID, output] of params.DependencyOutputs) dependencyOutputs[taskID] = output;
82
+
83
+ return {
84
+ ...(params.TemplateParameters ?? {}),
85
+ // JSON, not the object. A template writes `{{ _CURRENT_PAYLOAD }}` and expects to SEE
86
+ // the payload; handing the renderer an object yields "[object Object]", and the model
87
+ // then answers about a value it was never shown. That failure is invisible from the
88
+ // outside — the prompt run succeeds, the response is well-formed, and it is about
89
+ // nothing. It is what kept the Content Pipeline reviewer rejecting a draft it could not
90
+ // read, on every iteration, forever.
91
+ [CURRENT_PAYLOAD_PLACEHOLDER]: JSON.stringify(payload, null, 2),
92
+ flowContext: JSON.stringify({ dependencyOutputs }, null, 2),
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Reads the model's response as a payload update, and notices when it wants to stop.
98
+ *
99
+ * **A prompt is the only node kind that can end the workflow early**, because it is the only one
100
+ * doing open-ended reasoning: it can conclude the remaining steps are unnecessary. That is
101
+ * expressed as a Chat-shaped response, and the dispatcher honours it by skipping what remains and
102
+ * settling the parent Complete — rather than treating an early finish as an abandoned graph.
103
+ *
104
+ * Non-JSON is not an error. A prompt that answers in prose has still answered; it simply carries
105
+ * no structured update, so it becomes a message rather than a payload merge.
106
+ */
107
+ private parseResponse(raw: unknown): { payload?: Record<string, unknown>; chatMessage?: string } {
108
+ if (raw == null) return {};
109
+
110
+ if (typeof raw === 'object') {
111
+ return this.interpret(raw as Record<string, unknown>);
112
+ }
113
+
114
+ if (typeof raw === 'string') {
115
+ const text = raw.trim();
116
+ const fenced = text.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '');
117
+ try {
118
+ const parsed: unknown = JSON.parse(fenced);
119
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
120
+ return this.interpret(parsed as Record<string, unknown>);
121
+ }
122
+ } catch {
123
+ // Prose, not JSON — see above.
124
+ }
125
+ return { chatMessage: text };
126
+ }
127
+
128
+ return {};
129
+ }
130
+
131
+ /** Separates "here is an update" from "we are done, tell them this". */
132
+ private interpret(obj: Record<string, unknown>): { payload?: Record<string, unknown>; chatMessage?: string } {
133
+ const nextStep = obj['nextStep'] as { type?: string } | undefined;
134
+ const wantsChat = nextStep?.type === 'Chat' || obj['taskComplete'] === true;
135
+ const message = typeof obj['message'] === 'string' ? obj['message'] : undefined;
136
+
137
+ if (wantsChat && message) {
138
+ // The payload still merges: a prompt that both concluded and produced data should not
139
+ // lose the data because it also had something to say.
140
+ return { payload: obj, chatMessage: message };
141
+ }
142
+ return { payload: obj };
143
+ }
144
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview MJServer's implementation of the task-graph `ProviderFactory` seam.
3
+ *
4
+ * The durable dispatcher runs outside any HTTP request and executes tasks concurrently, so it must
5
+ * never share one provider — and therefore one transaction scope and one set of entity instances —
6
+ * across parallel work. It needs a way to mint providers on demand.
7
+ *
8
+ * Rather than have `@memberjunction/task-graph` import MJServer to get at that machinery (which
9
+ * would invert the dependency: MJServer depends on task-graph, not the reverse), the package
10
+ * declares a `ProviderFactory` interface and the host supplies an implementation. This is that
11
+ * implementation.
12
+ *
13
+ * It mints exactly what the per-request path already mints — a fresh provider over the **shared
14
+ * connection pool**, with metadata reuse — which is proven cheap at request scale and is why the
15
+ * plan chose this mechanism rather than inventing a dispatcher-specific one. The pool remains the
16
+ * real concurrency governor; the dispatcher's own `MaxConcurrentTasks` sits below it.
17
+ *
18
+ * @module @memberjunction/server
19
+ */
20
+ import { DatabaseProviderBase, IMetadataProvider } from '@memberjunction/core';
21
+ import type { ProviderFactory } from '@memberjunction/task-graph';
22
+ import { SQLServerDataProvider, SQLServerProviderConfigData } from '@memberjunction/sqlserver-dataprovider';
23
+ import sql from 'mssql';
24
+ import { mj_core_schema } from '../config.js';
25
+
26
+ /**
27
+ * Creates providers for the dispatcher, one per task execution.
28
+ *
29
+ * SQL Server path only for now, matching where the dispatcher is hosted. The PostgreSQL branch of
30
+ * `createPerRequestProviders` is deliberately not duplicated here — when PG hosting is needed, the
31
+ * right move is to lift the shared branch out of `context.ts` rather than fork it a second time.
32
+ */
33
+ export class TaskGraphProviderFactory implements ProviderFactory {
34
+ constructor(private readonly pool: sql.ConnectionPool) {}
35
+
36
+ public async CreateProvider(): Promise<IMetadataProvider> {
37
+ // `loadIfNeeded = false` (the trailing false) reuses already-loaded metadata rather than
38
+ // re-reading it per provider — the difference between "cheap enough to do per task" and
39
+ // "prohibitively expensive".
40
+ const config = new SQLServerProviderConfigData(this.pool, mj_core_schema, 0, undefined, undefined, false);
41
+ const provider = new SQLServerDataProvider();
42
+ await provider.Config(config);
43
+ return provider as unknown as IMetadataProvider;
44
+ }
45
+ }
46
+
47
+ /** Convenience for hosts that already hold a pool. */
48
+ export function CreateTaskGraphProviderFactory(pool: sql.ConnectionPool): ProviderFactory {
49
+ return new TaskGraphProviderFactory(pool);
50
+ }
51
+
52
+ /** Re-exported for hosts that need the concrete type. */
53
+ export type { DatabaseProviderBase };
@@ -19,7 +19,7 @@
19
19
 
20
20
  import { RunView, UserInfo, IMetadataProvider, Metadata, LogError, LogStatus } from '@memberjunction/core';
21
21
  import type { MJAIBridgeAgentIdentityEntity, MJAIBridgeProviderEntity } from '@memberjunction/core-entities';
22
- import { UserCache } from '@memberjunction/sqlserver-dataprovider';
22
+ import { UserCache } from '@memberjunction/generic-database-provider';
23
23
  import { AIBridgeEngine } from '@memberjunction/ai-bridge-server';
24
24
  import { CreateBridgeRealtimeSession } from '@memberjunction/ai-agents';
25
25
  import {
@@ -20,7 +20,7 @@ import { Router, urlencoded, type Request, type Response } from 'express';
20
20
  import { WebSocketServer, type WebSocket } from 'ws';
21
21
  import { RegisterMediaUpgradeRoute } from './media-upgrade-router.js';
22
22
  import { LogError, LogStatus, UserInfo, IMetadataProvider, Metadata } from '@memberjunction/core';
23
- import { UserCache } from '@memberjunction/sqlserver-dataprovider';
23
+ import { UserCache } from '@memberjunction/generic-database-provider';
24
24
  import {
25
25
  verifyTwilioSignature,
26
26
  resolveInboundCall,
@@ -26,7 +26,7 @@ import { WebSocketServer, type WebSocket } from 'ws';
26
26
  import type { IncomingMessage } from 'node:http';
27
27
  import { RegisterMediaUpgradeRoute } from './media-upgrade-router.js';
28
28
  import { LogError, LogStatus, UserInfo, IMetadataProvider, Metadata } from '@memberjunction/core';
29
- import { UserCache } from '@memberjunction/sqlserver-dataprovider';
29
+ import { UserCache } from '@memberjunction/generic-database-provider';
30
30
  import {
31
31
  verifyVonageSignature,
32
32
  verifyVonageJwt,
@@ -1,24 +0,0 @@
1
- import { AppContext } from '../types.js';
2
- import { ResolverBase } from '../generic/ResolverBase.js';
3
- export declare class RunReportResultType {
4
- ReportID: string;
5
- Success: boolean;
6
- Results: string;
7
- RowCount: number;
8
- ExecutionTime: number;
9
- ErrorMessage: string;
10
- }
11
- export declare class CreateReportResultType {
12
- ReportID: string;
13
- ReportName: string;
14
- Success: boolean;
15
- ErrorMessage: string;
16
- }
17
- export declare class ReportResolverExtended extends ResolverBase {
18
- GetReportData(ReportID: string, context: AppContext): Promise<RunReportResultType>;
19
- /**
20
- * This mutation will create a new report from a conversation detail ID
21
- */
22
- CreateReportFromConversationDetailID(ConversationDetailID: string, { dataSource, userPayload, providers }: AppContext): Promise<CreateReportResultType>;
23
- }
24
- //# sourceMappingURL=ReportResolver.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ReportResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/ReportResolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAMzC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,qBACa,mBAAmB;IAE9B,QAAQ,EAAE,MAAM,CAAC;IAGjB,OAAO,EAAE,OAAO,CAAC;IAGjB,OAAO,EAAE,MAAM,CAAC;IAGhB,QAAQ,EAAE,MAAM,CAAC;IAGjB,aAAa,EAAE,MAAM,CAAC;IAGtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBACa,sBAAsB;IAEjC,QAAQ,EAAE,MAAM,CAAC;IAGjB,UAAU,EAAE,MAAM,CAAC;IAGnB,OAAO,EAAE,OAAO,CAAC;IAGjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBACa,sBAAuB,SAAQ,YAAY;IAEhD,aAAa,CAAgC,QAAQ,EAAE,MAAM,EAAS,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAkB9H;;OAEG;IAEG,oCAAoC,CACG,oBAAoB,EAAE,MAAM,EAChE,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,UAAU,GACxD,OAAO,CAAC,sBAAsB,CAAC;CA0FnC"}
@@ -1,198 +0,0 @@
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
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- import { RunReport } from '@memberjunction/core';
14
- import { Arg, Ctx, Field, Mutation, ObjectType, Query, Resolver } from 'type-graphql';
15
- import { DataContext } from '@memberjunction/data-context';
16
- import { z } from 'zod';
17
- import mssql from 'mssql';
18
- import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
19
- import { ResolverBase } from '../generic/ResolverBase.js';
20
- let RunReportResultType = class RunReportResultType {
21
- };
22
- __decorate([
23
- Field(),
24
- __metadata("design:type", String)
25
- ], RunReportResultType.prototype, "ReportID", void 0);
26
- __decorate([
27
- Field(),
28
- __metadata("design:type", Boolean)
29
- ], RunReportResultType.prototype, "Success", void 0);
30
- __decorate([
31
- Field(),
32
- __metadata("design:type", String)
33
- ], RunReportResultType.prototype, "Results", void 0);
34
- __decorate([
35
- Field(),
36
- __metadata("design:type", Number)
37
- ], RunReportResultType.prototype, "RowCount", void 0);
38
- __decorate([
39
- Field(),
40
- __metadata("design:type", Number)
41
- ], RunReportResultType.prototype, "ExecutionTime", void 0);
42
- __decorate([
43
- Field(),
44
- __metadata("design:type", String)
45
- ], RunReportResultType.prototype, "ErrorMessage", void 0);
46
- RunReportResultType = __decorate([
47
- ObjectType()
48
- ], RunReportResultType);
49
- export { RunReportResultType };
50
- let CreateReportResultType = class CreateReportResultType {
51
- };
52
- __decorate([
53
- Field(),
54
- __metadata("design:type", String)
55
- ], CreateReportResultType.prototype, "ReportID", void 0);
56
- __decorate([
57
- Field(),
58
- __metadata("design:type", String)
59
- ], CreateReportResultType.prototype, "ReportName", void 0);
60
- __decorate([
61
- Field(),
62
- __metadata("design:type", Boolean)
63
- ], CreateReportResultType.prototype, "Success", void 0);
64
- __decorate([
65
- Field(),
66
- __metadata("design:type", String)
67
- ], CreateReportResultType.prototype, "ErrorMessage", void 0);
68
- CreateReportResultType = __decorate([
69
- ObjectType()
70
- ], CreateReportResultType);
71
- export { CreateReportResultType };
72
- let ReportResolverExtended = class ReportResolverExtended extends ResolverBase {
73
- async GetReportData(ReportID, context) {
74
- // Check API key scope authorization for report run
75
- await this.CheckAPIKeyScopeAuthorization('report:run', ReportID, context.userPayload);
76
- const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true });
77
- const rp = new RunReport(provider);
78
- const result = await rp.RunReport({ ReportID: ReportID });
79
- return {
80
- ReportID: ReportID,
81
- Success: result.Success,
82
- Results: JSON.stringify(result.Results),
83
- RowCount: result.RowCount,
84
- ExecutionTime: result.ExecutionTime,
85
- ErrorMessage: result.ErrorMessage,
86
- };
87
- }
88
- /**
89
- * This mutation will create a new report from a conversation detail ID
90
- */
91
- async CreateReportFromConversationDetailID(ConversationDetailID, { dataSource, userPayload, providers }) {
92
- // Check API key scope authorization for report creation (uses entity:create for Reports entity)
93
- await this.CheckAPIKeyScopeAuthorization('entity:create', 'Reports', userPayload);
94
- try {
95
- const md = GetReadWriteProvider(providers);
96
- // Resolve via the stamped payload user (GetUserFromPayload), NOT a fresh UserCache
97
- // lookup by email. UserCache.Users returns the shared, unstamped instance — re-fetching
98
- // by email here would silently drop any per-request API-key row-filter binding
99
- // (APIKeyRowFilters / APIKeyActingContext) already stamped onto userPayload.userRecord,
100
- // so a filtered key's report-creation work would run unfiltered. GetUserFromPayload
101
- // prefers userPayload.userRecord and only falls back to a UserCache email lookup when
102
- // no payload user is present (e.g. non-request-scoped callers), matching every other
103
- // resolver's contextUser resolution.
104
- const u = this.GetUserFromPayload(userPayload);
105
- if (!u)
106
- throw new Error('Unable to find user');
107
- const cde = md.Entities.find((e) => e.Name === 'MJ: Conversation Details');
108
- if (!cde)
109
- throw new Error('Unable to find Conversation Details Entity metadata');
110
- const cd = md.Entities.find((e) => e.Name === 'MJ: Conversations');
111
- if (!cd)
112
- throw new Error('Unable to find Conversations Entity metadata');
113
- const sql = `SELECT
114
- cd.Message, cd.ConversationID, c.DataContextID
115
- FROM
116
- ${cde.SchemaName}.${cde.BaseView} cd
117
- INNER JOIN
118
- ${cd.SchemaName}.${cd.BaseView} c
119
- ON
120
- cd.ConversationID = c.ID
121
- WHERE
122
- cd.ID=@ConversationDetailID`;
123
- const request = new mssql.Request(dataSource);
124
- request.input('ConversationDetailID', mssql.UniqueIdentifier, ConversationDetailID);
125
- const result = await request.query(sql);
126
- if (!result || !result.recordset || result.recordset.length === 0)
127
- throw new Error('Unable to retrieve converation details');
128
- const skipData = JSON.parse(result.recordset[0].Message);
129
- const report = await md.GetEntityObject('MJ: Reports', u);
130
- report.NewRecord();
131
- // support the legacy report title as old conversation details had a reportTitle property
132
- // but the new SkipData object has a title property, so favor the title property
133
- const title = skipData.title ? skipData.title : skipData.reportTitle ? skipData.reportTitle : 'Untitled Report';
134
- report.Name = title;
135
- report.Description = skipData.userExplanation ? skipData.userExplanation : '';
136
- report.ConversationID = result.recordset[0].ConversationID;
137
- report.ConversationDetailID = ConversationDetailID;
138
- const dc = new DataContext();
139
- await dc.LoadMetadata(result.recordset[0].DataContextID, u);
140
- const newDataContext = await DataContext.Clone(dc, false, u);
141
- if (!newDataContext)
142
- throw new Error('Error cloning data context');
143
- report.DataContextID = newDataContext.ID;
144
- // next, strip out the messags from the SkipData object to put them into our Report Configuration as we dont need to store that information as we have a
145
- // link back to the conversation and conversation detail, skipData can be modified as it is a copy of the data doesn't affect the original source
146
- skipData.messages = [];
147
- report.Configuration = JSON.stringify(skipData);
148
- report.SharingScope = 'None';
149
- report.UserID = u.ID;
150
- if (await report.Save()) {
151
- return {
152
- ReportID: report.ID,
153
- ReportName: report.Name,
154
- Success: true,
155
- ErrorMessage: '',
156
- };
157
- }
158
- else {
159
- return {
160
- ReportID: '',
161
- ReportName: '',
162
- Success: false,
163
- ErrorMessage: 'Unable to save new report',
164
- };
165
- }
166
- }
167
- catch (ex) {
168
- const err = z.object({ message: z.string() }).safeParse(ex);
169
- return {
170
- ReportID: '',
171
- ReportName: '',
172
- Success: false,
173
- ErrorMessage: 'Unable to create new report: ' + err.success ? err.data.message : String(ex),
174
- };
175
- }
176
- }
177
- };
178
- __decorate([
179
- Query(() => RunReportResultType),
180
- __param(0, Arg('ReportID', () => String)),
181
- __param(1, Ctx()),
182
- __metadata("design:type", Function),
183
- __metadata("design:paramtypes", [String, Object]),
184
- __metadata("design:returntype", Promise)
185
- ], ReportResolverExtended.prototype, "GetReportData", null);
186
- __decorate([
187
- Mutation(() => CreateReportResultType),
188
- __param(0, Arg('ConversationDetailID', () => String)),
189
- __param(1, Ctx()),
190
- __metadata("design:type", Function),
191
- __metadata("design:paramtypes", [String, Object]),
192
- __metadata("design:returntype", Promise)
193
- ], ReportResolverExtended.prototype, "CreateReportFromConversationDetailID", null);
194
- ReportResolverExtended = __decorate([
195
- Resolver(RunReportResultType)
196
- ], ReportResolverExtended);
197
- export { ReportResolverExtended };
198
- //# sourceMappingURL=ReportResolver.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ReportResolver.js","sourceRoot":"","sources":["../../src/resolvers/ReportResolver.ts"],"names":[],"mappings":"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"}