@memberjunction/server 6.2.0-edge.3 → 6.2.0-edge.5

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 (543) hide show
  1. package/README.md +20 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/BridgeHostInstance.d.ts +25 -0
  4. package/dist/agentSessions/BridgeHostInstance.d.ts.map +1 -0
  5. package/dist/agentSessions/BridgeHostInstance.js +30 -0
  6. package/dist/agentSessions/BridgeHostInstance.js.map +1 -0
  7. package/dist/agentSessions/HostInstance.d.ts +75 -11
  8. package/dist/agentSessions/HostInstance.d.ts.map +1 -1
  9. package/dist/agentSessions/HostInstance.js +99 -28
  10. package/dist/agentSessions/HostInstance.js.map +1 -1
  11. package/dist/agentSessions/ReturningVisitorRecap.d.ts.map +1 -1
  12. package/dist/agentSessions/ReturningVisitorRecap.js +7 -3
  13. package/dist/agentSessions/ReturningVisitorRecap.js.map +1 -1
  14. package/dist/agentSessions/SessionJanitor.d.ts +236 -27
  15. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  16. package/dist/agentSessions/SessionJanitor.js +682 -54
  17. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  18. package/dist/agentSessions/SessionManager.d.ts +48 -3
  19. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  20. package/dist/agentSessions/SessionManager.js +112 -9
  21. package/dist/agentSessions/SessionManager.js.map +1 -1
  22. package/dist/agentSessions/SessionRunIDVerifier.d.ts +63 -0
  23. package/dist/agentSessions/SessionRunIDVerifier.d.ts.map +1 -0
  24. package/dist/agentSessions/SessionRunIDVerifier.js +129 -0
  25. package/dist/agentSessions/SessionRunIDVerifier.js.map +1 -0
  26. package/dist/agentSessions/index.d.ts +2 -0
  27. package/dist/agentSessions/index.d.ts.map +1 -1
  28. package/dist/agentSessions/index.js +10 -3
  29. package/dist/agentSessions/index.js.map +1 -1
  30. package/dist/apiRoot.d.ts +32 -0
  31. package/dist/apiRoot.d.ts.map +1 -0
  32. package/dist/apiRoot.js +67 -0
  33. package/dist/apiRoot.js.map +1 -0
  34. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  35. package/dist/auth/AuthProviderCatalogRouter.js +25 -0
  36. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  37. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  38. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  39. package/dist/auth/LoginScreenEngine.js +57 -0
  40. package/dist/auth/LoginScreenEngine.js.map +1 -0
  41. package/dist/auth/actionAuthorization.d.ts +40 -0
  42. package/dist/auth/actionAuthorization.d.ts.map +1 -0
  43. package/dist/auth/actionAuthorization.js +94 -0
  44. package/dist/auth/actionAuthorization.js.map +1 -0
  45. package/dist/auth/index.d.ts +1 -0
  46. package/dist/auth/index.d.ts.map +1 -1
  47. package/dist/auth/index.js +4 -10
  48. package/dist/auth/index.js.map +1 -1
  49. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  50. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  51. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  52. package/dist/auth/magicLink/MagicLinkService.d.ts.map +1 -1
  53. package/dist/auth/magicLink/MagicLinkService.js +6 -3
  54. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  55. package/dist/auth/newUsers.d.ts +10 -0
  56. package/dist/auth/newUsers.d.ts.map +1 -1
  57. package/dist/auth/newUsers.js +80 -11
  58. package/dist/auth/newUsers.js.map +1 -1
  59. package/dist/config.d.ts +2514 -22
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +166 -4
  62. package/dist/config.js.map +1 -1
  63. package/dist/context.d.ts +8 -0
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +14 -11
  66. package/dist/context.js.map +1 -1
  67. package/dist/coreRoutes.d.ts +29 -0
  68. package/dist/coreRoutes.d.ts.map +1 -0
  69. package/dist/coreRoutes.js +142 -0
  70. package/dist/coreRoutes.js.map +1 -0
  71. package/dist/generated/graphql-schemas/__mj.d.ts +504 -3
  72. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  73. package/dist/generated/graphql-schemas/__mj.js +2456 -7
  74. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  75. package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
  76. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  77. package/dist/generic/CacheInvalidationResolver.js +59 -19
  78. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  79. package/dist/generic/OrphanedConversationDetailReconciler.js +3 -3
  80. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -1
  81. package/dist/generic/PushStatusResolver.js +1 -1
  82. package/dist/generic/PushStatusResolver.js.map +1 -1
  83. package/dist/generic/ResolverBase.d.ts +123 -48
  84. package/dist/generic/ResolverBase.d.ts.map +1 -1
  85. package/dist/generic/ResolverBase.js +293 -305
  86. package/dist/generic/ResolverBase.js.map +1 -1
  87. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  88. package/dist/generic/RunViewResolver.js +16 -0
  89. package/dist/generic/RunViewResolver.js.map +1 -1
  90. package/dist/globalCors.d.ts +33 -0
  91. package/dist/globalCors.d.ts.map +1 -0
  92. package/dist/globalCors.js +58 -0
  93. package/dist/globalCors.js.map +1 -0
  94. package/dist/index.d.ts +17 -0
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +219 -278
  97. package/dist/index.js.map +1 -1
  98. package/dist/isolatedProvider.d.ts +20 -0
  99. package/dist/isolatedProvider.d.ts.map +1 -0
  100. package/dist/isolatedProvider.js +22 -0
  101. package/dist/isolatedProvider.js.map +1 -0
  102. package/dist/multiTenancy/index.d.ts.map +1 -1
  103. package/dist/multiTenancy/index.js +22 -2
  104. package/dist/multiTenancy/index.js.map +1 -1
  105. package/dist/realtimeProxy/RealtimeProxyServer.d.ts +44 -4
  106. package/dist/realtimeProxy/RealtimeProxyServer.d.ts.map +1 -1
  107. package/dist/realtimeProxy/RealtimeProxyServer.js +121 -16
  108. package/dist/realtimeProxy/RealtimeProxyServer.js.map +1 -1
  109. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts +171 -0
  110. package/dist/realtimeProxy/RealtimeRelayTunnel.d.ts.map +1 -0
  111. package/dist/realtimeProxy/RealtimeRelayTunnel.js +532 -0
  112. package/dist/realtimeProxy/RealtimeRelayTunnel.js.map +1 -0
  113. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts +148 -0
  114. package/dist/realtimeSessions/RealtimeSessionEventService.d.ts.map +1 -0
  115. package/dist/realtimeSessions/RealtimeSessionEventService.js +191 -0
  116. package/dist/realtimeSessions/RealtimeSessionEventService.js.map +1 -0
  117. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts +66 -0
  118. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -0
  119. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +139 -0
  120. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -0
  121. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts +38 -0
  122. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -0
  123. package/dist/realtimeSessions/RealtimeVerifyRouter.js +99 -0
  124. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -0
  125. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  126. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  127. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  128. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  129. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts +61 -0
  130. package/dist/realtimeSessions/SessionVerificationPortsBase.d.ts.map +1 -0
  131. package/dist/realtimeSessions/SessionVerificationPortsBase.js +149 -0
  132. package/dist/realtimeSessions/SessionVerificationPortsBase.js.map +1 -0
  133. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts +57 -0
  134. package/dist/realtimeSessions/SlidingWindowRateLimiter.d.ts.map +1 -0
  135. package/dist/realtimeSessions/SlidingWindowRateLimiter.js +69 -0
  136. package/dist/realtimeSessions/SlidingWindowRateLimiter.js.map +1 -0
  137. package/dist/realtimeSessions/index.d.ts +19 -0
  138. package/dist/realtimeSessions/index.d.ts.map +1 -0
  139. package/dist/realtimeSessions/index.js +19 -0
  140. package/dist/realtimeSessions/index.js.map +1 -0
  141. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
  142. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  143. package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
  144. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  145. package/dist/realtimeSessions/sessionAccess.d.ts +92 -0
  146. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -0
  147. package/dist/realtimeSessions/sessionAccess.js +94 -0
  148. package/dist/realtimeSessions/sessionAccess.js.map +1 -0
  149. package/dist/realtimeSessions/sessionConfigStamps.d.ts +70 -0
  150. package/dist/realtimeSessions/sessionConfigStamps.d.ts.map +1 -0
  151. package/dist/realtimeSessions/sessionConfigStamps.js +93 -0
  152. package/dist/realtimeSessions/sessionConfigStamps.js.map +1 -0
  153. package/dist/realtimeSessions/subscriptionAuthorization.d.ts +65 -0
  154. package/dist/realtimeSessions/subscriptionAuthorization.d.ts.map +1 -0
  155. package/dist/realtimeSessions/subscriptionAuthorization.js +71 -0
  156. package/dist/realtimeSessions/subscriptionAuthorization.js.map +1 -0
  157. package/dist/realtimeSessions/verificationCore.d.ts +243 -0
  158. package/dist/realtimeSessions/verificationCore.d.ts.map +1 -0
  159. package/dist/realtimeSessions/verificationCore.js +356 -0
  160. package/dist/realtimeSessions/verificationCore.js.map +1 -0
  161. package/dist/realtimeSessions/verificationPages.d.ts +66 -0
  162. package/dist/realtimeSessions/verificationPages.d.ts.map +1 -0
  163. package/dist/realtimeSessions/verificationPages.js +110 -0
  164. package/dist/realtimeSessions/verificationPages.js.map +1 -0
  165. package/dist/realtimeSessions/verificationPolicy.d.ts +147 -0
  166. package/dist/realtimeSessions/verificationPolicy.d.ts.map +1 -0
  167. package/dist/realtimeSessions/verificationPolicy.js +249 -0
  168. package/dist/realtimeSessions/verificationPolicy.js.map +1 -0
  169. package/dist/realtimeSessions/verificationWorkflow.d.ts +263 -0
  170. package/dist/realtimeSessions/verificationWorkflow.d.ts.map +1 -0
  171. package/dist/realtimeSessions/verificationWorkflow.js +435 -0
  172. package/dist/realtimeSessions/verificationWorkflow.js.map +1 -0
  173. package/dist/realtimeWidget/widgetGuestElevation.d.ts +20 -2
  174. package/dist/realtimeWidget/widgetGuestElevation.d.ts.map +1 -1
  175. package/dist/realtimeWidget/widgetGuestElevation.js +31 -2
  176. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  177. package/dist/resolvers/ActionResolver.d.ts +31 -5
  178. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  179. package/dist/resolvers/ActionResolver.js +75 -14
  180. package/dist/resolvers/ActionResolver.js.map +1 -1
  181. package/dist/resolvers/AdhocQueryResolver.d.ts +14 -1
  182. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  183. package/dist/resolvers/AdhocQueryResolver.js +21 -5
  184. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  185. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  186. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  187. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  188. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  189. package/dist/resolvers/CacheStatsResolver.d.ts +27 -0
  190. package/dist/resolvers/CacheStatsResolver.d.ts.map +1 -1
  191. package/dist/resolvers/CacheStatsResolver.js +113 -2
  192. package/dist/resolvers/CacheStatsResolver.js.map +1 -1
  193. package/dist/resolvers/ClientToolRequestResolver.d.ts +4 -2
  194. package/dist/resolvers/ClientToolRequestResolver.d.ts.map +1 -1
  195. package/dist/resolvers/ClientToolRequestResolver.js +28 -10
  196. package/dist/resolvers/ClientToolRequestResolver.js.map +1 -1
  197. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  198. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  199. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  200. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  201. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  202. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  203. package/dist/resolvers/DatasetResolver.js +57 -8
  204. package/dist/resolvers/DatasetResolver.js.map +1 -1
  205. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  206. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  207. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  208. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  209. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +27 -1
  210. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  211. package/dist/resolvers/FetchEntityVectorsResolver.js +148 -2
  212. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  213. package/dist/resolvers/FileResolver.d.ts +82 -11
  214. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  215. package/dist/resolvers/FileResolver.js +279 -101
  216. package/dist/resolvers/FileResolver.js.map +1 -1
  217. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  218. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  219. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  220. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  221. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  222. package/dist/resolvers/GetDataResolver.js +6 -3
  223. package/dist/resolvers/GetDataResolver.js.map +1 -1
  224. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -1
  225. package/dist/resolvers/HumanHandoffResolver.js +7 -1
  226. package/dist/resolvers/HumanHandoffResolver.js.map +1 -1
  227. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  228. package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
  229. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  230. package/dist/resolvers/MCPResolver.d.ts.map +1 -1
  231. package/dist/resolvers/MCPResolver.js +9 -4
  232. package/dist/resolvers/MCPResolver.js.map +1 -1
  233. package/dist/resolvers/QueryResolver.d.ts +2 -0
  234. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  235. package/dist/resolvers/QueryResolver.js +13 -0
  236. package/dist/resolvers/QueryResolver.js.map +1 -1
  237. package/dist/resolvers/RealtimeBridgeResolver.d.ts +54 -2
  238. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  239. package/dist/resolvers/RealtimeBridgeResolver.js +155 -10
  240. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  241. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +157 -33
  242. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  243. package/dist/resolvers/RealtimeClientSessionResolver.js +404 -116
  244. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  245. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts +61 -0
  246. package/dist/resolvers/RealtimeSessionEventsResolver.d.ts.map +1 -0
  247. package/dist/resolvers/RealtimeSessionEventsResolver.js +130 -0
  248. package/dist/resolvers/RealtimeSessionEventsResolver.js.map +1 -0
  249. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts +85 -0
  250. package/dist/resolvers/RealtimeSessionVerificationResolver.d.ts.map +1 -0
  251. package/dist/resolvers/RealtimeSessionVerificationResolver.js +188 -0
  252. package/dist/resolvers/RealtimeSessionVerificationResolver.js.map +1 -0
  253. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +2 -0
  254. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  255. package/dist/resolvers/RemoteBrowserActionResolver.js +5 -1
  256. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  257. package/dist/resolvers/RunAIAgentResolver.d.ts +10 -0
  258. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  259. package/dist/resolvers/RunAIAgentResolver.js +100 -14
  260. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  261. package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
  262. package/dist/resolvers/RunTemplateResolver.js +12 -11
  263. package/dist/resolvers/RunTemplateResolver.js.map +1 -1
  264. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  265. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  266. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  267. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  268. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  269. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  270. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  271. package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
  272. package/dist/resolvers/SyncDataResolver.js +6 -2
  273. package/dist/resolvers/SyncDataResolver.js.map +1 -1
  274. package/dist/resolvers/SyncRolesUsersResolver.d.ts +2 -0
  275. package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
  276. package/dist/resolvers/SyncRolesUsersResolver.js +23 -6
  277. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  278. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  279. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  280. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  281. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  282. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  283. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  284. package/dist/resolvers/TestQuerySQLResolver.js +65 -13
  285. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  286. package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
  287. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  288. package/dist/resolvers/TransactionGroupResolver.js +102 -24
  289. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  290. package/dist/resolvers/UserAvatarResolver.d.ts +16 -0
  291. package/dist/resolvers/UserAvatarResolver.d.ts.map +1 -0
  292. package/dist/resolvers/UserAvatarResolver.js +124 -0
  293. package/dist/resolvers/UserAvatarResolver.js.map +1 -0
  294. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  295. package/dist/resolvers/UserResolver.js +2 -17
  296. package/dist/resolvers/UserResolver.js.map +1 -1
  297. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  298. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  299. package/dist/resolvers/agent-run-data-guard.js +72 -0
  300. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  301. package/dist/resolvers/agentVisionConsentAudit.d.ts +37 -0
  302. package/dist/resolvers/agentVisionConsentAudit.d.ts.map +1 -0
  303. package/dist/resolvers/agentVisionConsentAudit.js +63 -0
  304. package/dist/resolvers/agentVisionConsentAudit.js.map +1 -0
  305. package/dist/resolvers/avatarInputValidation.d.ts +40 -0
  306. package/dist/resolvers/avatarInputValidation.d.ts.map +1 -0
  307. package/dist/resolvers/avatarInputValidation.js +97 -0
  308. package/dist/resolvers/avatarInputValidation.js.map +1 -0
  309. package/dist/resolvers/currentUserRoles.d.ts +29 -0
  310. package/dist/resolvers/currentUserRoles.d.ts.map +1 -1
  311. package/dist/resolvers/currentUserRoles.js +30 -0
  312. package/dist/resolvers/currentUserRoles.js.map +1 -1
  313. package/dist/resolvers/meetings/meetingMutations.d.ts +6 -0
  314. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -1
  315. package/dist/resolvers/meetings/meetingMutations.js +21 -0
  316. package/dist/resolvers/meetings/meetingMutations.js.map +1 -1
  317. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  318. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  319. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  320. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  321. package/dist/rest/ViewOperationsHandler.d.ts +3 -1
  322. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  323. package/dist/rest/ViewOperationsHandler.js +21 -12
  324. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  325. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  326. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  327. package/dist/rest/setupRESTEndpoints.js +6 -0
  328. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  329. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  330. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  331. package/dist/serverExtensionReservedRoots.js +14 -17
  332. package/dist/serverExtensionReservedRoots.js.map +1 -1
  333. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  334. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  335. package/dist/services/MJStorageBlobStore.js +25 -19
  336. package/dist/services/MJStorageBlobStore.js.map +1 -1
  337. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  338. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  339. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  340. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  341. package/dist/services/TaskGraphActionRunner.js +27 -5
  342. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  343. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  344. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  345. package/dist/services/TaskGraphAgentRunner.js +157 -9
  346. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  347. package/dist/services/TaskGraphContinuationDeliverer.d.ts +57 -4
  348. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  349. package/dist/services/TaskGraphContinuationDeliverer.js +607 -18
  350. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  351. package/dist/sharedCache.d.ts +105 -0
  352. package/dist/sharedCache.d.ts.map +1 -0
  353. package/dist/sharedCache.js +279 -0
  354. package/dist/sharedCache.js.map +1 -0
  355. package/dist/types.d.ts +6 -0
  356. package/dist/types.d.ts.map +1 -1
  357. package/dist/types.js.map +1 -1
  358. package/package.json +99 -96
  359. package/src/__tests__/ActionResolver.authorization.test.ts +353 -0
  360. package/src/__tests__/AdhocQueryResolver.sqlAuthorizer.test.ts +104 -0
  361. package/src/__tests__/BridgeHostInstance.test.ts +232 -0
  362. package/src/__tests__/ClientToolRequestResolver.test.ts +116 -0
  363. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  364. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  365. package/src/__tests__/FetchEntityVectorsResolver.test.ts +433 -0
  366. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  367. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  368. package/src/__tests__/HostInstance.test.ts +84 -0
  369. package/src/__tests__/HumanHandoffResolver.test.ts +17 -0
  370. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  371. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  372. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  373. package/src/__tests__/MeetingResolver.test.ts +75 -1
  374. package/src/__tests__/RealtimeBridgeResolver.test.ts +415 -6
  375. package/src/__tests__/RealtimeClientSessionResolver.configTamper.test.ts +383 -0
  376. package/src/__tests__/RealtimeClientSessionResolver.test.ts +682 -58
  377. package/src/__tests__/RealtimeProxyServer.test.ts +16 -1
  378. package/src/__tests__/RealtimeRelay.test.ts +876 -0
  379. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  380. package/src/__tests__/RemoteBrowserActionResolver.goalRunLink.test.ts +129 -0
  381. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  382. package/src/__tests__/ResolverBase.aggregateScreen.test.ts +174 -0
  383. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  384. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  385. package/src/__tests__/ResolverBase.clientOldValues.test.ts +212 -6
  386. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  387. package/src/__tests__/ReturningVisitorRecap.test.ts +115 -0
  388. package/src/__tests__/RunAIAgentResolver.branch.test.ts +170 -0
  389. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +6 -4
  390. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
  391. package/src/__tests__/RunAIAgentResolver.stoppedPredecessor.test.ts +166 -0
  392. package/src/__tests__/RunTemplateResolver.test.ts +132 -0
  393. package/src/__tests__/RunViewResolver.cacheCheckForwarding.test.ts +63 -0
  394. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  395. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  396. package/src/__tests__/SessionJanitor.test.ts +1203 -21
  397. package/src/__tests__/SessionManager.test.ts +240 -17
  398. package/src/__tests__/SessionRunIDVerifier.test.ts +251 -0
  399. package/src/__tests__/SyncRolesUsersResolver.userRoles.test.ts +97 -0
  400. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  401. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  402. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +403 -22
  403. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  404. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  405. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  406. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  407. package/src/__tests__/UserAvatarResolver.test.ts +255 -0
  408. package/src/__tests__/UserResolver.currentUser.test.ts +16 -1
  409. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  410. package/src/__tests__/actionAuthorization.test.ts +130 -0
  411. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  412. package/src/__tests__/agentVisionConsentAudit.test.ts +118 -0
  413. package/src/__tests__/apiRootBoot.test.ts +202 -0
  414. package/src/__tests__/avatarInputValidation.test.ts +160 -0
  415. package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
  416. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  417. package/src/__tests__/globalCors.test.ts +217 -0
  418. package/src/__tests__/isolatedProviderTransactions.test.ts +169 -0
  419. package/src/__tests__/magicLinkService.consume.test.ts +6 -0
  420. package/src/__tests__/magicLinkService.provisionLog.test.ts +5 -0
  421. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  422. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  423. package/src/__tests__/multiTenancy.test.ts +1 -1
  424. package/src/__tests__/newUsers.template.test.ts +151 -0
  425. package/src/__tests__/newUsers.test.ts +74 -5
  426. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +17 -2
  427. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  428. package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
  429. package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
  430. package/src/__tests__/realtimeSessions/RealtimeSessionEventService.test.ts +201 -0
  431. package/src/__tests__/realtimeSessions/RealtimeSessionEventsResolver.test.ts +215 -0
  432. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationResolver.test.ts +102 -0
  433. package/src/__tests__/realtimeSessions/RealtimeSessionVerificationService.test.ts +349 -0
  434. package/src/__tests__/realtimeSessions/RealtimeVerifyRouter.test.ts +131 -0
  435. package/src/__tests__/realtimeSessions/SlidingWindowRateLimiter.test.ts +56 -0
  436. package/src/__tests__/realtimeSessions/helpers.ts +4 -0
  437. package/src/__tests__/realtimeSessions/sessionAccess.test.ts +129 -0
  438. package/src/__tests__/realtimeSessions/sessionConfigStamps.test.ts +124 -0
  439. package/src/__tests__/realtimeSessions/verificationCore.test.ts +355 -0
  440. package/src/__tests__/realtimeSessions/verificationPages.test.ts +84 -0
  441. package/src/__tests__/realtimeSessions/verificationPolicy.test.ts +226 -0
  442. package/src/__tests__/realtimeSessions/verificationWorkflow.test.ts +633 -0
  443. package/src/__tests__/resolverBase.fls.test.ts +87 -4
  444. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  445. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -96
  446. package/src/__tests__/sharedCache.test.ts +312 -0
  447. package/src/__tests__/widgetGuestElevation.test.ts +44 -0
  448. package/src/agentSessions/BridgeHostInstance.ts +32 -0
  449. package/src/agentSessions/HostInstance.ts +124 -28
  450. package/src/agentSessions/ReturningVisitorRecap.ts +7 -3
  451. package/src/agentSessions/SessionJanitor.ts +821 -59
  452. package/src/agentSessions/SessionManager.ts +138 -26
  453. package/src/agentSessions/SessionRunIDVerifier.ts +171 -0
  454. package/src/agentSessions/index.ts +10 -3
  455. package/src/apiRoot.ts +78 -0
  456. package/src/auth/AuthProviderCatalogRouter.ts +26 -0
  457. package/src/auth/LoginScreenEngine.ts +50 -0
  458. package/src/auth/actionAuthorization.ts +116 -0
  459. package/src/auth/index.ts +4 -8
  460. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  461. package/src/auth/magicLink/MagicLinkService.ts +6 -3
  462. package/src/auth/newUsers.ts +99 -11
  463. package/src/config.ts +171 -5
  464. package/src/context.ts +15 -10
  465. package/src/coreRoutes.ts +166 -0
  466. package/src/generated/graphql-schemas/__mj.ts +1815 -57
  467. package/src/generic/CacheInvalidationResolver.ts +73 -18
  468. package/src/generic/OrphanedConversationDetailReconciler.ts +3 -3
  469. package/src/generic/PushStatusResolver.ts +1 -1
  470. package/src/generic/ResolverBase.ts +335 -326
  471. package/src/generic/RunViewResolver.ts +21 -0
  472. package/src/globalCors.ts +71 -0
  473. package/src/index.ts +231 -300
  474. package/src/isolatedProvider.ts +22 -0
  475. package/src/multiTenancy/index.ts +24 -2
  476. package/src/realtimeProxy/RealtimeProxyServer.ts +148 -16
  477. package/src/realtimeProxy/RealtimeRelayTunnel.ts +645 -0
  478. package/src/realtimeSessions/README.md +179 -0
  479. package/src/realtimeSessions/RealtimeSessionEventService.ts +274 -0
  480. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +168 -0
  481. package/src/realtimeSessions/RealtimeVerifyRouter.ts +109 -0
  482. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  483. package/src/realtimeSessions/SessionVerificationPortsBase.ts +189 -0
  484. package/src/realtimeSessions/SlidingWindowRateLimiter.ts +92 -0
  485. package/src/realtimeSessions/index.ts +18 -0
  486. package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
  487. package/src/realtimeSessions/sessionAccess.ts +145 -0
  488. package/src/realtimeSessions/sessionConfigStamps.ts +123 -0
  489. package/src/realtimeSessions/subscriptionAuthorization.ts +116 -0
  490. package/src/realtimeSessions/verificationCore.ts +502 -0
  491. package/src/realtimeSessions/verificationPages.ts +149 -0
  492. package/src/realtimeSessions/verificationPolicy.ts +321 -0
  493. package/src/realtimeSessions/verificationWorkflow.ts +702 -0
  494. package/src/realtimeWidget/widgetGuestElevation.ts +34 -2
  495. package/src/resolvers/ActionResolver.ts +84 -21
  496. package/src/resolvers/AdhocQueryResolver.ts +24 -6
  497. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  498. package/src/resolvers/CacheStatsResolver.ts +89 -2
  499. package/src/resolvers/ClientToolRequestResolver.ts +25 -7
  500. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  501. package/src/resolvers/DatasetResolver.ts +70 -10
  502. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  503. package/src/resolvers/FetchEntityVectorsResolver.ts +179 -2
  504. package/src/resolvers/FileResolver.ts +321 -106
  505. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  506. package/src/resolvers/GetDataResolver.ts +6 -3
  507. package/src/resolvers/HumanHandoffResolver.ts +8 -0
  508. package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
  509. package/src/resolvers/MCPResolver.ts +8 -5
  510. package/src/resolvers/QueryResolver.ts +11 -0
  511. package/src/resolvers/RealtimeBridgeResolver.ts +163 -11
  512. package/src/resolvers/RealtimeClientSessionResolver.ts +511 -129
  513. package/src/resolvers/RealtimeSessionEventsResolver.ts +133 -0
  514. package/src/resolvers/RealtimeSessionVerificationResolver.ts +174 -0
  515. package/src/resolvers/RemoteBrowserActionResolver.ts +11 -1
  516. package/src/resolvers/RunAIAgentResolver.ts +116 -14
  517. package/src/resolvers/RunTemplateResolver.ts +13 -12
  518. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  519. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  520. package/src/resolvers/SyncDataResolver.ts +6 -2
  521. package/src/resolvers/SyncRolesUsersResolver.ts +24 -6
  522. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  523. package/src/resolvers/TestQuerySQLResolver.ts +68 -13
  524. package/src/resolvers/TransactionGroupResolver.ts +131 -27
  525. package/src/resolvers/UserAvatarResolver.ts +111 -0
  526. package/src/resolvers/UserResolver.ts +2 -16
  527. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  528. package/src/resolvers/agent-run-data-guard.ts +89 -0
  529. package/src/resolvers/agentVisionConsentAudit.ts +82 -0
  530. package/src/resolvers/avatarInputValidation.ts +123 -0
  531. package/src/resolvers/currentUserRoles.ts +32 -1
  532. package/src/resolvers/meetings/meetingMutations.ts +21 -0
  533. package/src/rest/RealtimeRecordingHandler.ts +464 -0
  534. package/src/rest/ViewOperationsHandler.ts +29 -13
  535. package/src/rest/setupRESTEndpoints.ts +6 -0
  536. package/src/serverExtensionReservedRoots.ts +14 -17
  537. package/src/services/MJStorageBlobStore.ts +31 -30
  538. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  539. package/src/services/TaskGraphActionRunner.ts +25 -5
  540. package/src/services/TaskGraphAgentRunner.ts +188 -11
  541. package/src/services/TaskGraphContinuationDeliverer.ts +713 -17
  542. package/src/sharedCache.ts +305 -0
  543. package/src/types.ts +7 -0
@@ -12,12 +12,16 @@
12
12
  *
13
13
  * @module @memberjunction/server
14
14
  */
15
- import { LogError, LogStatus, type IMetadataProvider, type UserInfo } from '@memberjunction/core';
15
+ import { LogError, LogStatus, RunView, type IMetadataProvider, type UserInfo } from '@memberjunction/core';
16
+ import { UUIDsEqual } from '@memberjunction/global';
17
+ import { UserCache } from '@memberjunction/generic-database-provider';
16
18
  import { MJAIAgentRunEntity, MJConversationDetailEntity } from '@memberjunction/core-entities';
17
19
  import { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
18
20
  import { AgentRunner } from '@memberjunction/ai-agents';
19
21
  import { ChatMessageRole } from '@memberjunction/ai';
22
+ import type { PubSubEngine } from 'type-graphql';
20
23
  import type { ProviderFactory, TaskContinuationDeliverer, TaskContinuationParams } from '@memberjunction/task-graph';
24
+ import { PublishStatusUpdate } from '../generic/PushStatusResolver.js';
21
25
 
22
26
  /** How many per-task lines a posted summary shows before collapsing the rest into a count. */
23
27
  const MAX_LISTED_TASKS = 20;
@@ -43,10 +47,12 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
43
47
  constructor(
44
48
  private readonly providerFactory: ProviderFactory,
45
49
  private readonly contextUser: UserInfo,
50
+ private readonly pubSub?: PubSubEngine,
46
51
  ) {}
47
52
 
48
53
  /**
49
- * Posts the roll-up as an AI-role message in the graph's conversation.
54
+ * Posts the roll-up as an AI-role message in the graph's conversation, on the fork of the
55
+ * message that started the graph (Main when that message is in Main).
50
56
  *
51
57
  * Never throws. The dispatcher calls this inside the compare-and-swap that marks a completion
52
58
  * delivered; an error escaping would either abort that guard or leave the graph looking
@@ -62,8 +68,8 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
62
68
  }
63
69
 
64
70
  const provider = await this.providerFactory.CreateProvider();
65
- const conversationID = await this.resolveConversationID(params.ConversationDetailID, provider);
66
- if (!conversationID) {
71
+ const origin = await this.resolveOrigin(params.ConversationDetailID, provider);
72
+ if (!origin) {
67
73
  LogError(
68
74
  `[TaskGraphContinuationDeliverer] Conversation detail ${params.ConversationDetailID} could not be loaded — ` +
69
75
  `"${params.WorkflowName}" has nowhere to post its outcome.`
@@ -71,20 +77,62 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
71
77
  return;
72
78
  }
73
79
 
74
- const detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', this.contextUser);
80
+ const actingUser = this.resolveActingUser(origin.OwnerUserID);
81
+ const enrichedParams = await this.enrichTasksWithOutputs(params, provider);
82
+ const renderedOutcome = this.renderMessage(enrichedParams);
83
+
84
+ if (origin.IsLatest) {
85
+ // No intervening messages were sent while the workflow ran: update the originating
86
+ // message in-place so the single conversation turn holds the progress card, step
87
+ // artifacts, and final outcome together.
88
+ origin.OriginDetail.Status = 'Complete';
89
+ origin.OriginDetail.Message = renderedOutcome;
90
+ if (!(await origin.OriginDetail.Save())) {
91
+ LogError(
92
+ `[TaskGraphContinuationDeliverer] Could not update in-place outcome of "${params.WorkflowName}": ` +
93
+ `${origin.OriginDetail.LatestResult?.CompleteMessage ?? 'unknown error'}`
94
+ );
95
+ return;
96
+ }
97
+ this.publishCompletion(
98
+ origin.OwnerUserID,
99
+ params.ConversationDetailID,
100
+ params.ConversationDetailID,
101
+ origin.ConversationID,
102
+ params.SubmittedByAgentRunID ?? 'task-graph',
103
+ true,
104
+ );
105
+ return;
106
+ }
107
+
108
+ const detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', actingUser);
75
109
  detail.NewRecord();
76
- detail.ConversationID = conversationID;
110
+ detail.ConversationID = origin.ConversationID;
111
+ detail.BranchID = origin.BranchID;
112
+ detail.ParentID = params.ConversationDetailID;
77
113
  detail.Role = 'AI';
78
114
  detail.Status = 'Complete';
79
115
  detail.HiddenToUser = false;
80
- detail.Message = this.renderMessage(params);
116
+ detail.Message = renderedOutcome;
81
117
 
82
118
  if (!(await detail.Save())) {
83
119
  LogError(
84
120
  `[TaskGraphContinuationDeliverer] Could not post the outcome of "${params.WorkflowName}": ` +
85
121
  `${detail.LatestResult?.CompleteMessage ?? 'unknown error'}`
86
122
  );
123
+ return;
87
124
  }
125
+
126
+ await this.markOriginDetailCompleted(origin.OriginDetail, params.WorkflowName);
127
+
128
+ this.publishCompletion(
129
+ origin.OwnerUserID,
130
+ detail.ID || params.ConversationDetailID,
131
+ params.ConversationDetailID,
132
+ origin.ConversationID,
133
+ params.SubmittedByAgentRunID ?? 'task-graph',
134
+ true,
135
+ );
88
136
  } catch (e) {
89
137
  LogError(`[TaskGraphContinuationDeliverer] Posting the outcome of "${params.WorkflowName}" threw`, undefined, e);
90
138
  }
@@ -118,22 +166,160 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
118
166
  return;
119
167
  }
120
168
 
169
+ // When a sub-agent (e.g., Workflow Planner) submitted the workflow on behalf of a parent
170
+ // conversation agent (e.g., Sage), walk up `ParentRunID` so the root conversation agent
171
+ // synthesizes the final response to the user.
172
+ let targetRun = priorRun;
173
+ const initialRunId = (priorRun.ID || params.SubmittedByAgentRunID).toLowerCase();
174
+ const visitedRunIDs = new Set<string>([initialRunId]);
175
+ while (targetRun.ParentRunID && !visitedRunIDs.has(targetRun.ParentRunID.toLowerCase()) && visitedRunIDs.size < 10) {
176
+ visitedRunIDs.add(targetRun.ParentRunID.toLowerCase());
177
+ const parentRun = await provider.GetEntityObject<MJAIAgentRunEntity>('MJ: AI Agent Runs', this.contextUser);
178
+ if (await parentRun.Load(targetRun.ParentRunID)) {
179
+ targetRun = parentRun;
180
+ } else {
181
+ break;
182
+ }
183
+ }
184
+
121
185
  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.`);
186
+ if (!(await agent.Load(targetRun.AgentID))) {
187
+ LogError(`[TaskGraphContinuationDeliverer] Agent ${targetRun.AgentID} could not be loaded — posting "${params.WorkflowName}" instead.`);
124
188
  await this.PostMessage(params);
125
189
  return;
126
190
  }
127
191
 
128
- await new AgentRunner().RunAgent({
192
+ // Run on the fork of the message that started the graph, as PostMessage posts into it:
193
+ // RunAgent derives the conversation from the detail, but not the fork.
194
+ const runUserId = targetRun.UserID || priorRun.UserID;
195
+ const origin = params.ConversationDetailID
196
+ ? await this.resolveOrigin(params.ConversationDetailID, provider, runUserId)
197
+ : null;
198
+ const ownerUserId = runUserId || origin?.OwnerUserID || this.contextUser.ID;
199
+ const actingUser = this.resolveActingUser(ownerUserId);
200
+
201
+ // Adaptive delivery:
202
+ // - When the originating workflow message is still the latest message in the conversation
203
+ // (origin.IsLatest === true), update it in-place so the single turn carries the workflow
204
+ // progress card, step artifacts, and synthesized narrative together.
205
+ // - When intervening messages were sent while the workflow ran (origin.IsLatest === false),
206
+ // create a bottom continuation message linked via ParentID = params.ConversationDetailID
207
+ // and update the originating message's stale "I'll follow up..." copy.
208
+ let replyDetail: MJConversationDetailEntity | null = null;
209
+ let replySaved = false;
210
+ if (origin?.ConversationID) {
211
+ if (origin.IsLatest) {
212
+ replyDetail = origin.OriginDetail;
213
+ replySaved = true;
214
+ } else {
215
+ replyDetail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', actingUser);
216
+ replyDetail.NewRecord();
217
+ replyDetail.ConversationID = origin.ConversationID;
218
+ replyDetail.BranchID = origin.BranchID;
219
+ replyDetail.ParentID = params.ConversationDetailID;
220
+ replyDetail.Role = 'AI';
221
+ replyDetail.Status = 'In-Progress';
222
+ replyDetail.HiddenToUser = false;
223
+ replyDetail.AgentID = agent.ID;
224
+ replyDetail.Message = `⏳ Synthesizing results from **${params.WorkflowName}**...`;
225
+ replySaved = await replyDetail.Save();
226
+ }
227
+ }
228
+
229
+ const targetDetailId = origin?.IsLatest
230
+ ? (params.ConversationDetailID ?? replyDetail?.ID ?? undefined)
231
+ : ((replyDetail && replySaved && replyDetail.ID)
232
+ ? replyDetail.ID
233
+ : (params.ConversationDetailID ?? undefined));
234
+
235
+ const enrichedParams = await this.enrichTasksWithOutputs(params, provider);
236
+ const renderedContinuationMessage = this.renderMessage(enrichedParams);
237
+
238
+ const runner = new AgentRunner(provider);
239
+ const result = await runner.RunAgent({
129
240
  agent,
130
- conversationMessages: [{ role: ChatMessageRole.user, content: this.renderMessage(params) }],
131
- contextUser: this.contextUser,
132
- conversationDetailId: params.ConversationDetailID ?? undefined,
241
+ provider,
242
+ conversationMessages: [{
243
+ role: ChatMessageRole.user,
244
+ content:
245
+ `${renderedContinuationMessage}\n\n` +
246
+ `Please synthesize ALL workflow steps above into a clear, direct, comprehensive final response for the user (covering every completed step's findings, SQL queries, data tables, strategic analysis, and report summaries, and briefly explaining any conditional steps that were skipped because their prerequisite condition was not met).`,
247
+ }],
248
+ // Prevent the continuation synthesis turn from auto-hydrating an unrelated artifact
249
+ // or prior scratch payload into payload, while still recording LastRunID lineage.
250
+ inputArtifacts: [],
251
+ payload: {},
252
+ lastRunId: targetRun.ID,
253
+ contextUser: actingUser,
254
+ conversationId: origin?.ConversationID ?? undefined,
255
+ conversationDetailId: targetDetailId,
256
+ ConversationBranchID: origin?.BranchID ?? undefined,
133
257
  // The load-bearing value: without it the next graph this run submits restarts the
134
258
  // chain at zero and the cap never fires.
135
259
  continuationDepth: params.ReinvokeDepth + 1,
136
260
  });
261
+
262
+ if (replyDetail && replySaved) {
263
+ const succeeded = result?.success !== false;
264
+ replyDetail.Status = succeeded ? 'Complete' : 'Error';
265
+ replyDetail.Message = result?.agentRun?.Message || renderedContinuationMessage;
266
+ if (result?.responseForm) {
267
+ replyDetail.ResponseForm = JSON.stringify(result.responseForm);
268
+ }
269
+ if (result?.actionableCommands && result.actionableCommands.length > 0) {
270
+ replyDetail.ActionableCommands = JSON.stringify(result.actionableCommands);
271
+ }
272
+ if (result?.automaticCommands && result.automaticCommands.length > 0) {
273
+ replyDetail.AutomaticCommands = JSON.stringify(result.automaticCommands);
274
+ }
275
+ await replyDetail.Save();
276
+
277
+ if (!origin?.IsLatest && origin?.OriginDetail) {
278
+ await this.markOriginDetailCompleted(origin.OriginDetail, params.WorkflowName);
279
+ }
280
+
281
+ const artifactTargetDetailId = targetDetailId ?? replyDetail.ID;
282
+ const hasNonEmptyPayload =
283
+ result?.payload != null &&
284
+ (typeof result.payload !== 'object' ||
285
+ Array.isArray(result.payload) ||
286
+ Object.keys(result.payload as Record<string, unknown>).length > 0);
287
+ if (
288
+ succeeded &&
289
+ hasNonEmptyPayload &&
290
+ artifactTargetDetailId &&
291
+ result.artifactDirective?.behavior !== 'suppress' &&
292
+ typeof runner.ProcessAgentArtifacts === 'function'
293
+ ) {
294
+ try {
295
+ await runner.ProcessAgentArtifacts(result, artifactTargetDetailId, undefined, actingUser, provider);
296
+ } catch (artifactErr) {
297
+ LogError(
298
+ `[TaskGraphContinuationDeliverer] Artifact creation for "${params.WorkflowName}" failed (non-fatal)`,
299
+ undefined,
300
+ artifactErr,
301
+ );
302
+ }
303
+ }
304
+ }
305
+
306
+ if (origin) {
307
+ // When updating the originating message in-place (origin.IsLatest === true),
308
+ // keep the completion event pointed at the primary orchestrating run (targetRun.ID)
309
+ // so the message's gear icon opens the full workflow-orchestrating run rather than
310
+ // the 2-step post-workflow synthesis run.
311
+ const completionRunId = origin.IsLatest
312
+ ? (targetRun.ID || result?.agentRun?.ID || params.SubmittedByAgentRunID)
313
+ : (result?.agentRun?.ID ?? params.SubmittedByAgentRunID);
314
+ this.publishCompletion(
315
+ ownerUserId,
316
+ targetDetailId ?? params.ConversationDetailID ?? '',
317
+ params.ConversationDetailID,
318
+ origin.ConversationID,
319
+ completionRunId,
320
+ result?.success !== false,
321
+ );
322
+ }
137
323
  } catch (e) {
138
324
  // FALL BACK, don't just log (C3). Both load-failure paths above already post instead of
139
325
  // reinvoking, on the principle that a completed workflow's outcome must reach the user
@@ -149,10 +335,519 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
149
335
  }
150
336
  }
151
337
 
152
- /** The conversation a detail belongs to. */
153
- private async resolveConversationID(conversationDetailID: string, provider: IMetadataProvider): Promise<string | null> {
154
- const detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', this.contextUser);
155
- return (await detail.Load(conversationDetailID)) ? detail.ConversationID : null;
338
+ /**
339
+ * Broadcasts a completion event on `PUSH_STATUS_UPDATES_TOPIC` so open conversation tabs
340
+ * immediately reload both the originating workflow message and the newly posted continuation reply.
341
+ */
342
+ private publishCompletion(
343
+ ownerUserId: string,
344
+ replyDetailId: string,
345
+ originDetailId: string | null,
346
+ conversationId: string,
347
+ agentRunId: string,
348
+ success: boolean,
349
+ ): void {
350
+ if (!this.pubSub || !ownerUserId) return;
351
+ try {
352
+ if (originDetailId && originDetailId !== replyDetailId) {
353
+ PublishStatusUpdate(this.pubSub, {
354
+ sessionId: '*',
355
+ ownerUserId,
356
+ message: JSON.stringify({
357
+ resolver: 'RunAIAgentResolver',
358
+ type: 'StreamingContent',
359
+ status: 'ok',
360
+ data: {
361
+ type: 'complete',
362
+ conversationDetailId: originDetailId,
363
+ conversationId,
364
+ agentRunId,
365
+ success,
366
+ timestamp: new Date(),
367
+ },
368
+ }),
369
+ });
370
+ }
371
+ if (replyDetailId) {
372
+ PublishStatusUpdate(this.pubSub, {
373
+ sessionId: '*',
374
+ ownerUserId,
375
+ message: JSON.stringify({
376
+ resolver: 'RunAIAgentResolver',
377
+ type: 'StreamingContent',
378
+ status: 'ok',
379
+ data: {
380
+ type: 'complete',
381
+ conversationDetailId: replyDetailId,
382
+ originConversationDetailId: originDetailId,
383
+ conversationId,
384
+ agentRunId,
385
+ success,
386
+ timestamp: new Date(),
387
+ },
388
+ }),
389
+ });
390
+ }
391
+ } catch (err) {
392
+ LogError(`[TaskGraphContinuationDeliverer] Failed to publish completion notification (ignored)`, undefined, err);
393
+ }
394
+ }
395
+
396
+ /**
397
+ * The conversation, fork (null is Main), owner user, loaded entity, and whether the originating
398
+ * detail is still the latest visible message in the conversation; null when it cannot be loaded.
399
+ */
400
+ private async resolveOrigin(
401
+ conversationDetailID: string,
402
+ provider: IMetadataProvider,
403
+ fallbackOwnerUserId?: string | null,
404
+ ): Promise<{
405
+ ConversationID: string;
406
+ BranchID: string | null;
407
+ OwnerUserID: string;
408
+ OriginDetail: MJConversationDetailEntity;
409
+ IsLatest: boolean;
410
+ } | null> {
411
+ const initialUser = this.resolveActingUser(fallbackOwnerUserId);
412
+ let detail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', initialUser);
413
+ if (!(await detail.Load(conversationDetailID))) {
414
+ return null;
415
+ }
416
+ let ownerUserId = fallbackOwnerUserId || detail.UserID || null;
417
+ if (!ownerUserId && detail.ConversationID) {
418
+ ownerUserId = await this.lookupConversationOwnerId(detail.ConversationID, provider);
419
+ }
420
+ const resolvedOwnerUserId = ownerUserId || this.contextUser.ID;
421
+ const actingUser = this.resolveActingUser(resolvedOwnerUserId);
422
+ // `MJConversationDetailEntityExtended.Save()` refuses writes when the entity's context user
423
+ // is not the conversation owner (`this.contextUser` is the server system user). Re-bind
424
+ // `OriginDetail` to `actingUser` whenever `ownerUserId` was discovered after loading `detail`.
425
+ if (!UUIDsEqual(actingUser.ID, initialUser.ID)) {
426
+ const writableDetail = await provider.GetEntityObject<MJConversationDetailEntity>('MJ: Conversation Details', actingUser);
427
+ if (await writableDetail.Load(conversationDetailID)) {
428
+ detail = writableDetail;
429
+ }
430
+ }
431
+ const branchId = detail.BranchID ?? null;
432
+ const isLatest = detail.ConversationID
433
+ ? await this.isLatestConversationMessage(detail.ConversationID, branchId, conversationDetailID, provider)
434
+ : false;
435
+ return {
436
+ ConversationID: detail.ConversationID,
437
+ BranchID: branchId,
438
+ OwnerUserID: resolvedOwnerUserId,
439
+ OriginDetail: detail,
440
+ IsLatest: isLatest,
441
+ };
442
+ }
443
+
444
+ /**
445
+ * Returns `true` when `originDetailId` is the newest visible message on its conversation branch,
446
+ * meaning no intervening messages were posted while the workflow ran in the background.
447
+ */
448
+ private async isLatestConversationMessage(
449
+ conversationId: string,
450
+ branchId: string | null,
451
+ originDetailId: string,
452
+ provider: IMetadataProvider,
453
+ ): Promise<boolean> {
454
+ try {
455
+ const safeConvId = conversationId.replace(/'/g, "''");
456
+ const branchPredicate = branchId
457
+ ? `BranchID='${branchId.replace(/'/g, "''")}'`
458
+ : `BranchID IS NULL`;
459
+ const rv = RunView.FromMetadataProvider(provider);
460
+ const res = await rv.RunView<{ ID: string }>(
461
+ {
462
+ EntityName: 'MJ: Conversation Details',
463
+ ExtraFilter: `ConversationID='${safeConvId}' AND ${branchPredicate} AND (HiddenToUser = 0 OR HiddenToUser IS NULL)`,
464
+ Fields: ['ID'],
465
+ OrderBy: '__mj_CreatedAt DESC',
466
+ MaxRows: 1,
467
+ ResultType: 'simple',
468
+ BypassCache: true,
469
+ },
470
+ this.contextUser,
471
+ );
472
+ if (res.Success && res.Results && res.Results.length > 0 && res.Results[0].ID) {
473
+ return UUIDsEqual(res.Results[0].ID, originDetailId);
474
+ }
475
+ } catch {
476
+ // Fall back to false when RunView is unavailable.
477
+ }
478
+ return false;
479
+ }
480
+
481
+ /**
482
+ * Replaces the originating message's stale "I'll follow up when it finishes" copy with a clean
483
+ * completion note when the workflow outcome was delivered in a separate bottom continuation message.
484
+ */
485
+ private async markOriginDetailCompleted(
486
+ originDetail: MJConversationDetailEntity,
487
+ workflowName: string,
488
+ ): Promise<void> {
489
+ try {
490
+ const currentMsg = originDetail.Message || '';
491
+ const completionNote = `*(✅ **${workflowName}** completed — synthesized results posted below.)*`;
492
+ if (!currentMsg.includes(completionNote)) {
493
+ const cleaned = currentMsg
494
+ .replace(/\s*I['’]ll follow up when it finishes\.?/gi, '')
495
+ .trim();
496
+ originDetail.Message = cleaned
497
+ ? `${cleaned}\n\n${completionNote}`
498
+ : completionNote;
499
+ originDetail.Status = 'Complete';
500
+ await originDetail.Save();
501
+ }
502
+ } catch {
503
+ // Non-fatal if origin detail note update fails.
504
+ }
505
+ }
506
+
507
+ /**
508
+ * Looks up the conversation owner's `UserID` from `MJ: Conversations` when the originating
509
+ * `MJ: Conversation Details` row is an AI message (`detail.UserID === null`).
510
+ */
511
+ private async lookupConversationOwnerId(
512
+ conversationId: string,
513
+ provider: IMetadataProvider,
514
+ ): Promise<string | null> {
515
+ try {
516
+ const safeId = conversationId.replace(/'/g, "''");
517
+ const rv = RunView.FromMetadataProvider(provider);
518
+ const res = await rv.RunView<{ ID: string; UserID: string }>(
519
+ {
520
+ EntityName: 'MJ: Conversations',
521
+ ExtraFilter: `ID='${safeId}'`,
522
+ Fields: ['ID', 'UserID'],
523
+ ResultType: 'simple',
524
+ },
525
+ this.contextUser,
526
+ );
527
+ if (res.Success && res.Results && res.Results.length > 0 && res.Results[0].UserID) {
528
+ return res.Results[0].UserID;
529
+ }
530
+ } catch {
531
+ // Fall back to contextUser when provider is a lightweight test harness without RunView.
532
+ }
533
+ return null;
534
+ }
535
+
536
+ /**
537
+ * Resolves the conversation owner's `UserInfo` from `UserCache` so `MJConversationDetailEntityExtended`
538
+ * ownership checks and artifact ownership succeed. Falls back to `this.contextUser` when not cached.
539
+ */
540
+ private resolveActingUser(ownerUserId: string | null | undefined): UserInfo {
541
+ if (!ownerUserId) {
542
+ return this.contextUser;
543
+ }
544
+ try {
545
+ const users = UserCache.Instance?.Users ?? UserCache.Users ?? [];
546
+ const matched = users.find((u) => UUIDsEqual(u.ID, ownerUserId));
547
+ if (matched) {
548
+ return matched;
549
+ }
550
+ } catch {
551
+ // Fall back to contextUser when UserCache is not initialized.
552
+ }
553
+ return this.contextUser;
554
+ }
555
+
556
+ /**
557
+ * Loads child task `OutputPayload` rows for `params.ParentTaskID`, strips upstream payload keys
558
+ * inherited unchanged via `TaskGraphDispatcher.applyStepOutputMapping`, and replaces generic
559
+ * `"output available (N chars)"` summaries with readable output excerpts so both `PostMessage`
560
+ * and `Reinvoke` carry each step's own concrete results into the conversation.
561
+ */
562
+ private async enrichTasksWithOutputs(
563
+ params: TaskContinuationParams,
564
+ provider: IMetadataProvider,
565
+ ): Promise<TaskContinuationParams> {
566
+ if (!params.ParentTaskID || params.Tasks.length === 0) {
567
+ return params;
568
+ }
569
+ try {
570
+ const safeParentId = params.ParentTaskID.replace(/'/g, "''");
571
+ const rv = RunView.FromMetadataProvider(provider);
572
+ const res = await rv.RunView<{ ID: string; Name: string; OutputPayload: string | null }>(
573
+ {
574
+ EntityName: 'MJ: Tasks',
575
+ ExtraFilter: `ParentID='${safeParentId}'`,
576
+ Fields: ['ID', 'Name', 'OutputPayload'],
577
+ ResultType: 'simple',
578
+ BypassCache: true,
579
+ },
580
+ this.contextUser,
581
+ );
582
+ const outputById = new Map<string, string>();
583
+ const nameById = new Map<string, string>();
584
+ for (const row of res.Results ?? []) {
585
+ if (row.ID) {
586
+ const lower = row.ID.toLowerCase();
587
+ if (row.Name) {
588
+ nameById.set(lower, row.Name);
589
+ }
590
+ if (row.OutputPayload) {
591
+ outputById.set(lower, row.OutputPayload);
592
+ }
593
+ }
594
+ }
595
+ for (const t of params.Tasks) {
596
+ if (t.TaskID && t.Name && !nameById.has(t.TaskID.toLowerCase())) {
597
+ nameById.set(t.TaskID.toLowerCase(), t.Name);
598
+ }
599
+ }
600
+
601
+ const skippedReasonById = await this.resolveSkippedTaskReasons(params, rv, nameById);
602
+ if (outputById.size === 0 && skippedReasonById.size === 0) {
603
+ return params;
604
+ }
605
+ const seenUpstreamKeyValues = new Map<string, string>();
606
+ return {
607
+ ...params,
608
+ Tasks: params.Tasks.map((task) => {
609
+ const lowerId = task.TaskID.toLowerCase();
610
+ if (task.Status === 'Skipped' && !task.Summary) {
611
+ const skipReason = skippedReasonById.get(lowerId);
612
+ if (skipReason) {
613
+ return { ...task, Summary: skipReason };
614
+ }
615
+ }
616
+ const rawOutput = outputById.get(lowerId);
617
+ if (!rawOutput) {
618
+ return task;
619
+ }
620
+ const deltaOutput = this.stripInheritedUpstreamKeys(rawOutput, seenUpstreamKeyValues);
621
+ const isPlaceholderSummary = !task.Summary || task.Summary.startsWith('output available (');
622
+ if (!isPlaceholderSummary) {
623
+ return task;
624
+ }
625
+ const excerpt = this.extractOutputExcerpt(deltaOutput);
626
+ return excerpt ? { ...task, Summary: excerpt } : task;
627
+ }),
628
+ };
629
+ } catch {
630
+ return params;
631
+ }
632
+ }
633
+
634
+ /**
635
+ * Resolves a human-readable explanation for each `Skipped` task in `params.Tasks` by inspecting
636
+ * its `MJ: Task Dependencies` (`Condition` and upstream prerequisite status).
637
+ */
638
+ private async resolveSkippedTaskReasons(
639
+ params: TaskContinuationParams,
640
+ rv: RunView,
641
+ nameById: Map<string, string>,
642
+ ): Promise<Map<string, string>> {
643
+ const reasons = new Map<string, string>();
644
+ const skippedTasks = params.Tasks.filter((t) => t.Status === 'Skipped' && Boolean(t.TaskID));
645
+ if (skippedTasks.length === 0) {
646
+ return reasons;
647
+ }
648
+ try {
649
+ const quotedIds = skippedTasks
650
+ .map((t) => `'${t.TaskID.replace(/'/g, "''")}'`)
651
+ .join(',');
652
+ const depRes = await rv.RunView<{
653
+ TaskID: string;
654
+ DependsOnTaskID: string;
655
+ Condition: string | null;
656
+ }>(
657
+ {
658
+ EntityName: 'MJ: Task Dependencies',
659
+ ExtraFilter: `TaskID IN (${quotedIds})`,
660
+ Fields: ['TaskID', 'DependsOnTaskID', 'Condition'],
661
+ ResultType: 'simple',
662
+ BypassCache: true,
663
+ },
664
+ this.contextUser,
665
+ );
666
+ const statusById = new Map<string, string>();
667
+ for (const t of params.Tasks) {
668
+ if (t.TaskID) {
669
+ statusById.set(t.TaskID.toLowerCase(), t.Status);
670
+ }
671
+ }
672
+ const depsByTask = new Map<string, Array<{ DependsOnTaskID: string; Condition: string | null }>>();
673
+ for (const dep of depRes.Results ?? []) {
674
+ if (!dep.TaskID) continue;
675
+ const key = dep.TaskID.toLowerCase();
676
+ const list = depsByTask.get(key) ?? [];
677
+ list.push(dep);
678
+ depsByTask.set(key, list);
679
+ }
680
+ for (const skipped of skippedTasks) {
681
+ const lower = skipped.TaskID.toLowerCase();
682
+ const deps = depsByTask.get(lower) ?? [];
683
+ const parts: string[] = [];
684
+ for (const dep of deps) {
685
+ const prereqKey = dep.DependsOnTaskID?.toLowerCase() ?? '';
686
+ const prereqName = nameById.get(prereqKey);
687
+ const prereqStatus = statusById.get(prereqKey);
688
+ if (dep.Condition && dep.Condition.trim()) {
689
+ parts.push(
690
+ prereqName
691
+ ? `branch condition \`${dep.Condition.trim()}\` on "${prereqName}" evaluated to false`
692
+ : `branch condition \`${dep.Condition.trim()}\` evaluated to false`,
693
+ );
694
+ } else if (prereqStatus === 'Skipped' || prereqStatus === 'Failed') {
695
+ parts.push(
696
+ prereqName
697
+ ? `prerequisite "${prereqName}" was ${prereqStatus}`
698
+ : `prerequisite task was ${prereqStatus}`,
699
+ );
700
+ }
701
+ }
702
+ reasons.set(
703
+ lower,
704
+ parts.length > 0
705
+ ? parts.join('; ')
706
+ : 'prerequisite branch condition evaluated to false',
707
+ );
708
+ }
709
+ } catch {
710
+ // Optional dependency lookup; return empty map on failure.
711
+ }
712
+ return reasons;
713
+ }
714
+
715
+ /**
716
+ * Removes top-level JSON keys from `rawOutput` whose serialized value is identical to an
717
+ * earlier step's output in the same workflow (`TaskGraphDispatcher.applyStepOutputMapping`
718
+ * merges `{ ...payload, ...output }`), while recording this step's keys for downstream steps.
719
+ */
720
+ private stripInheritedUpstreamKeys(
721
+ rawOutput: string,
722
+ seenUpstreamKeyValues: Map<string, string>,
723
+ ): string {
724
+ try {
725
+ const parsed = JSON.parse(rawOutput.trim()) as Record<string, unknown>;
726
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
727
+ const delta: Record<string, unknown> = {};
728
+ for (const [key, value] of Object.entries(parsed)) {
729
+ const serializedVal = JSON.stringify(value);
730
+ if (seenUpstreamKeyValues.get(key) !== serializedVal) {
731
+ delta[key] = value;
732
+ }
733
+ seenUpstreamKeyValues.set(key, serializedVal);
734
+ }
735
+ if (Object.keys(delta).length > 0) {
736
+ return JSON.stringify(delta);
737
+ }
738
+ }
739
+ } catch {
740
+ // Non-JSON output; return as-is.
741
+ }
742
+ return rawOutput;
743
+ }
744
+
745
+ /**
746
+ * Extracts a human-readable excerpt from a task's serialized `OutputPayload` (up to 2,500 chars).
747
+ */
748
+ private extractOutputExcerpt(rawOutput: string): string {
749
+ const maxChars = 2500;
750
+ const trimmed = rawOutput.trim();
751
+ if (!trimmed) {
752
+ return '';
753
+ }
754
+ try {
755
+ const parsed = JSON.parse(trimmed) as Record<string, unknown>;
756
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
757
+ const sections: string[] = [];
758
+ const titleText = parsed.title ?? parsed.queryName ?? parsed.savedQueryName;
759
+ if (typeof titleText === 'string' && titleText.trim()) {
760
+ sections.push(`Title: ${titleText.trim()}`);
761
+ }
762
+ if (typeof parsed.message === 'string' && parsed.message.trim()) {
763
+ sections.push(parsed.message.trim());
764
+ }
765
+ const summaryText = parsed.summary ?? parsed.description ?? parsed.interpretation;
766
+ if (typeof summaryText === 'string' && summaryText.trim()) {
767
+ sections.push(summaryText.trim());
768
+ }
769
+ if (typeof parsed.explanation === 'string' && parsed.explanation.trim()) {
770
+ sections.push(`Explanation: ${parsed.explanation.trim()}`);
771
+ }
772
+ if (typeof parsed.analysis === 'string' && parsed.analysis.trim()) {
773
+ sections.push(`Analysis: ${parsed.analysis.trim()}`);
774
+ }
775
+ const sqlText = parsed.request ?? parsed.sql;
776
+ if (typeof sqlText === 'string' && sqlText.trim()) {
777
+ sections.push(`SQL / Request:\n\`\`\`sql\n${sqlText.trim()}\n\`\`\``);
778
+ }
779
+ if (typeof parsed.plan === 'string' && parsed.plan.trim()) {
780
+ sections.push(parsed.plan.trim());
781
+ }
782
+
783
+ // Nested synthesis object (e.g., Research Agent / Query Strategist)
784
+ const synthesis = (typeof parsed.synthesis === 'object' && parsed.synthesis !== null && !Array.isArray(parsed.synthesis))
785
+ ? (parsed.synthesis as Record<string, unknown>)
786
+ : undefined;
787
+ if (synthesis) {
788
+ if (typeof synthesis.executiveSummary === 'string' && synthesis.executiveSummary.trim()) {
789
+ sections.push(`Executive Summary: ${synthesis.executiveSummary.trim()}`);
790
+ }
791
+ if (Array.isArray(synthesis.keyFindings) && synthesis.keyFindings.length > 0) {
792
+ sections.push(`Key Findings: ${JSON.stringify(synthesis.keyFindings.slice(0, 10))}`);
793
+ }
794
+ if (Array.isArray(synthesis.recommendations) && synthesis.recommendations.length > 0) {
795
+ sections.push(`Recommendations: ${JSON.stringify(synthesis.recommendations.slice(0, 10))}`);
796
+ }
797
+ }
798
+
799
+ // Nested report object (e.g., Research Report Writer)
800
+ const report = (typeof parsed.report === 'object' && parsed.report !== null && !Array.isArray(parsed.report))
801
+ ? (parsed.report as Record<string, unknown>)
802
+ : undefined;
803
+ if (report) {
804
+ if (typeof report.name === 'string' && report.name.trim()) {
805
+ sections.push(`Report Title: ${report.name.trim()}`);
806
+ }
807
+ if (typeof report.description === 'string' && report.description.trim()) {
808
+ sections.push(`Report Summary: ${report.description.trim()}`);
809
+ }
810
+ if (typeof report.html === 'string' && report.html.trim()) {
811
+ const plainReportText = report.html
812
+ .replace(/<style[\s\S]*?<\/style>/gi, ' ')
813
+ .replace(/<script[\s\S]*?<\/script>/gi, ' ')
814
+ .replace(/<[^>]+>/g, ' ')
815
+ .replace(/\s+/g, ' ')
816
+ .trim();
817
+ if (plainReportText) {
818
+ sections.push(`Report Excerpt: ${plainReportText.slice(0, 1000)}`);
819
+ }
820
+ }
821
+ }
822
+
823
+ // Action output fields (Result / result / output / value)
824
+ const actionOutput = parsed.Result ?? parsed.result ?? parsed.output ?? parsed.value;
825
+ if (actionOutput !== undefined && actionOutput !== null) {
826
+ const formattedActionOutput = typeof actionOutput === 'string'
827
+ ? actionOutput.trim()
828
+ : JSON.stringify(actionOutput);
829
+ if (formattedActionOutput) {
830
+ sections.push(`Result: ${formattedActionOutput}`);
831
+ }
832
+ }
833
+
834
+ if (Array.isArray(parsed.rows) && parsed.rows.length > 0) {
835
+ sections.push(`Sample Rows (${parsed.rows.length} total): ${JSON.stringify(parsed.rows.slice(0, 10))}`);
836
+ }
837
+
838
+ if (parsed.decisions !== undefined && parsed.decisions !== null && sections.length === 0) {
839
+ sections.push(`Decisions: ${JSON.stringify(parsed.decisions)}`);
840
+ }
841
+
842
+ if (sections.length > 0) {
843
+ const combined = sections.join('\n\n');
844
+ return combined.length > maxChars ? `${combined.slice(0, maxChars)}…` : combined;
845
+ }
846
+ }
847
+ } catch {
848
+ // Fall through to raw string truncation when OutputPayload is not JSON.
849
+ }
850
+ return trimmed.length > maxChars ? `${trimmed.slice(0, maxChars)}…` : trimmed;
156
851
  }
157
852
 
158
853
  /**
@@ -185,6 +880,7 @@ export class TaskGraphContinuationDeliverer implements TaskContinuationDeliverer
185
880
  case 'Complete': return '✅';
186
881
  case 'Failed': return '❌';
187
882
  case 'Cancelled': return '⊘';
883
+ case 'Skipped': return '⏭️';
188
884
  default: return '•';
189
885
  }
190
886
  }