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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +30 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/config.d.ts +2189 -71
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +123 -3
  6. package/dist/config.js.map +1 -1
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +11 -23
  9. package/dist/context.js.map +1 -1
  10. package/dist/generated/graphql-schemas/__mj.d.ts +2143 -205
  11. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  12. package/dist/generated/graphql-schemas/__mj.js +24441 -14433
  13. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  14. package/dist/generic/FireAndForgetHeartbeat.d.ts +15 -1
  15. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  16. package/dist/generic/FireAndForgetHeartbeat.js +16 -2
  17. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  18. package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
  19. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
  20. package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
  21. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
  22. package/dist/generic/PushStatusResolver.d.ts +38 -0
  23. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  24. package/dist/generic/PushStatusResolver.js +84 -1
  25. package/dist/generic/PushStatusResolver.js.map +1 -1
  26. package/dist/generic/ResolverBase.d.ts +56 -4
  27. package/dist/generic/ResolverBase.d.ts.map +1 -1
  28. package/dist/generic/ResolverBase.js +191 -74
  29. package/dist/generic/ResolverBase.js.map +1 -1
  30. package/dist/generic/RunViewResolver.d.ts +4 -0
  31. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  32. package/dist/generic/RunViewResolver.js +33 -1
  33. package/dist/generic/RunViewResolver.js.map +1 -1
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +204 -50
  37. package/dist/index.js.map +1 -1
  38. package/dist/postgresqlCompat.d.ts +8 -0
  39. package/dist/postgresqlCompat.d.ts.map +1 -0
  40. package/dist/postgresqlCompat.js +19 -0
  41. package/dist/postgresqlCompat.js.map +1 -0
  42. package/dist/postgresqlPoolSettings.d.ts +108 -0
  43. package/dist/postgresqlPoolSettings.d.ts.map +1 -0
  44. package/dist/postgresqlPoolSettings.js +134 -0
  45. package/dist/postgresqlPoolSettings.js.map +1 -0
  46. package/dist/resolvers/AdhocQueryResolver.d.ts +23 -18
  47. package/dist/resolvers/AdhocQueryResolver.d.ts.map +1 -1
  48. package/dist/resolvers/AdhocQueryResolver.js +77 -167
  49. package/dist/resolvers/AdhocQueryResolver.js.map +1 -1
  50. package/dist/resolvers/AgentRunStatusPublisher.d.ts +55 -0
  51. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
  52. package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
  53. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
  54. package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
  55. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
  56. package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
  57. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
  58. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
  59. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
  60. package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
  61. package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
  62. package/dist/resolvers/EntityRecordNameResolver.d.ts +7 -23
  63. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  64. package/dist/resolvers/EntityRecordNameResolver.js +9 -47
  65. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  66. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  67. package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
  68. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  69. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  70. package/dist/resolvers/GetDataResolver.js +9 -0
  71. package/dist/resolvers/GetDataResolver.js.map +1 -1
  72. package/dist/resolvers/HumanHandoffResolver.d.ts +107 -0
  73. package/dist/resolvers/HumanHandoffResolver.d.ts.map +1 -0
  74. package/dist/resolvers/HumanHandoffResolver.js +324 -0
  75. package/dist/resolvers/HumanHandoffResolver.js.map +1 -0
  76. package/dist/resolvers/MeetingResolver.d.ts +69 -0
  77. package/dist/resolvers/MeetingResolver.d.ts.map +1 -0
  78. package/dist/resolvers/MeetingResolver.js +381 -0
  79. package/dist/resolvers/MeetingResolver.js.map +1 -0
  80. package/dist/resolvers/MergeRecordsResolver.d.ts +7 -0
  81. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  82. package/dist/resolvers/MergeRecordsResolver.js +16 -2
  83. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  84. package/dist/resolvers/RealtimeBridgeResolver.d.ts +34 -1
  85. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -1
  86. package/dist/resolvers/RealtimeBridgeResolver.js +202 -7
  87. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -1
  88. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +45 -89
  89. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  90. package/dist/resolvers/RealtimeClientSessionResolver.js +94 -240
  91. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  92. package/dist/resolvers/RunAIAgentResolver.d.ts +0 -16
  93. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  94. package/dist/resolvers/RunAIAgentResolver.js +23 -153
  95. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  96. package/dist/resolvers/RunDecisionResolver.d.ts +149 -0
  97. package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
  98. package/dist/resolvers/RunDecisionResolver.js +396 -0
  99. package/dist/resolvers/RunDecisionResolver.js.map +1 -0
  100. package/dist/resolvers/VectorizeEntityResolver.d.ts +1 -1
  101. package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
  102. package/dist/resolvers/VectorizeEntityResolver.js +14 -10
  103. package/dist/resolvers/VectorizeEntityResolver.js.map +1 -1
  104. package/dist/resolvers/adhocTimeout.d.ts +7 -0
  105. package/dist/resolvers/adhocTimeout.d.ts.map +1 -0
  106. package/dist/resolvers/adhocTimeout.js +12 -0
  107. package/dist/resolvers/adhocTimeout.js.map +1 -0
  108. package/dist/resolvers/meetings/index.d.ts +5 -0
  109. package/dist/resolvers/meetings/index.d.ts.map +1 -0
  110. package/dist/resolvers/meetings/index.js +5 -0
  111. package/dist/resolvers/meetings/index.js.map +1 -0
  112. package/dist/resolvers/meetings/meetingHelpers.d.ts +17 -0
  113. package/dist/resolvers/meetings/meetingHelpers.d.ts.map +1 -0
  114. package/dist/resolvers/meetings/meetingHelpers.js +212 -0
  115. package/dist/resolvers/meetings/meetingHelpers.js.map +1 -0
  116. package/dist/resolvers/meetings/meetingMutations.d.ts +12 -0
  117. package/dist/resolvers/meetings/meetingMutations.d.ts.map +1 -0
  118. package/dist/resolvers/meetings/meetingMutations.js +418 -0
  119. package/dist/resolvers/meetings/meetingMutations.js.map +1 -0
  120. package/dist/resolvers/meetings/meetingQueries.d.ts +7 -0
  121. package/dist/resolvers/meetings/meetingQueries.d.ts.map +1 -0
  122. package/dist/resolvers/meetings/meetingQueries.js +113 -0
  123. package/dist/resolvers/meetings/meetingQueries.js.map +1 -0
  124. package/dist/resolvers/meetings/meetingTypes.d.ts +89 -0
  125. package/dist/resolvers/meetings/meetingTypes.d.ts.map +1 -0
  126. package/dist/resolvers/meetings/meetingTypes.js +345 -0
  127. package/dist/resolvers/meetings/meetingTypes.js.map +1 -0
  128. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  129. package/dist/rest/ViewOperationsHandler.js +8 -5
  130. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  131. package/dist/services/TaskGraphActionRunner.d.ts +8 -0
  132. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  133. package/dist/services/TaskGraphActionRunner.js +27 -1
  134. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  135. package/dist/services/WorkQueueHostService.d.ts +36 -0
  136. package/dist/services/WorkQueueHostService.d.ts.map +1 -0
  137. package/dist/services/WorkQueueHostService.js +97 -0
  138. package/dist/services/WorkQueueHostService.js.map +1 -0
  139. package/dist/services/workQueueConfig.d.ts +103 -0
  140. package/dist/services/workQueueConfig.d.ts.map +1 -0
  141. package/dist/services/workQueueConfig.js +48 -0
  142. package/dist/services/workQueueConfig.js.map +1 -0
  143. package/dist/types.d.ts +5 -0
  144. package/dist/types.d.ts.map +1 -1
  145. package/dist/types.js.map +1 -1
  146. package/package.json +95 -92
  147. package/src/__tests__/AdhocQueryResolver.bugs.test.ts +14 -35
  148. package/src/__tests__/AdhocQueryResolver.pagination.test.ts +6 -2
  149. package/src/__tests__/AdhocQueryResolver.scopeGuard.test.ts +3 -3
  150. package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
  151. package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
  152. package/src/__tests__/EntityRecordNameResolver.fieldSecurity.test.ts +27 -72
  153. package/src/__tests__/HumanHandoffResolver.test.ts +233 -0
  154. package/src/__tests__/MeetingResolver.test.ts +374 -0
  155. package/src/__tests__/RealtimeBridgeResolver.test.ts +240 -2
  156. package/src/__tests__/RealtimeClientSessionResolver.test.ts +216 -2
  157. package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
  158. package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
  159. package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
  160. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +96 -0
  161. package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
  162. package/src/__tests__/ResolverBase.filterEscaping.test.ts +21 -2
  163. package/src/__tests__/ResolverBase.includeBinaryFields.test.ts +291 -0
  164. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +182 -12
  165. package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
  166. package/src/__tests__/RunDecisionResolver.test.ts +699 -0
  167. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +43 -0
  168. package/src/__tests__/VectorizeEntityResolver.test.ts +106 -0
  169. package/src/__tests__/WorkQueueHostService.test.ts +133 -0
  170. package/src/__tests__/adhocTimeoutClamp.test.ts +26 -0
  171. package/src/__tests__/conversationRunEvents.test.ts +399 -0
  172. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +283 -0
  173. package/src/__tests__/postgresqlPoolSettings.test.ts +131 -0
  174. package/src/__tests__/pushStatusFanOut.test.ts +206 -0
  175. package/src/__tests__/translateBracketsToPG.test.ts +20 -0
  176. package/src/auth/__tests__/backward-compatibility.test.ts +1 -0
  177. package/src/config.ts +130 -3
  178. package/src/context.ts +11 -24
  179. package/src/generated/graphql-schemas/__mj.ts +24183 -17182
  180. package/src/generic/FireAndForgetHeartbeat.ts +16 -2
  181. package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
  182. package/src/generic/PushStatusResolver.ts +97 -1
  183. package/src/generic/ResolverBase.ts +220 -76
  184. package/src/generic/RunViewResolver.ts +33 -2
  185. package/src/index.ts +228 -51
  186. package/src/postgresqlCompat.ts +21 -0
  187. package/src/postgresqlPoolSettings.ts +213 -0
  188. package/src/resolvers/AdhocQueryResolver.ts +88 -188
  189. package/src/resolvers/AgentRunStatusPublisher.ts +175 -0
  190. package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
  191. package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
  192. package/src/resolvers/EntityRecordNameResolver.ts +9 -51
  193. package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
  194. package/src/resolvers/GetDataResolver.ts +10 -0
  195. package/src/resolvers/HumanHandoffResolver.ts +304 -0
  196. package/src/resolvers/MeetingResolver.ts +438 -0
  197. package/src/resolvers/MergeRecordsResolver.ts +14 -2
  198. package/src/resolvers/RealtimeBridgeResolver.ts +227 -13
  199. package/src/resolvers/RealtimeClientSessionResolver.ts +99 -287
  200. package/src/resolvers/RunAIAgentResolver.ts +28 -174
  201. package/src/resolvers/RunDecisionResolver.ts +435 -0
  202. package/src/resolvers/VectorizeEntityResolver.ts +16 -11
  203. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
  204. package/src/resolvers/adhocTimeout.ts +12 -0
  205. package/src/resolvers/meetings/index.ts +4 -0
  206. package/src/resolvers/meetings/meetingHelpers.ts +307 -0
  207. package/src/resolvers/meetings/meetingMutations.ts +535 -0
  208. package/src/resolvers/meetings/meetingQueries.ts +172 -0
  209. package/src/resolvers/meetings/meetingTypes.ts +238 -0
  210. package/src/rest/ViewOperationsHandler.ts +8 -5
  211. package/src/services/TaskGraphActionRunner.ts +29 -1
  212. package/src/services/WorkQueueHostService.ts +129 -0
  213. package/src/services/workQueueConfig.ts +52 -0
  214. package/src/types.ts +5 -0
  215. package/dist/resolvers/adhoc-query-helpers.d.ts +0 -33
  216. package/dist/resolvers/adhoc-query-helpers.d.ts.map +0 -1
  217. package/dist/resolvers/adhoc-query-helpers.js +0 -50
  218. package/dist/resolvers/adhoc-query-helpers.js.map +0 -1
  219. package/src/__tests__/adhoc-query-helpers.test.ts +0 -50
  220. package/src/resolvers/adhoc-query-helpers.ts +0 -67
@@ -14,10 +14,19 @@ declare class AdhocQueryInput {
14
14
  /**
15
15
  * Resolver for executing ad-hoc (unsaved) SQL queries.
16
16
  *
17
+ * The query runs through the read-only provider's own ad-hoc path (`RunQuery` with `SQL`), the
18
+ * same one in-process callers use, so it behaves identically on every database platform: the SQL
19
+ * is validated and rendered there, paged in the database with a count, run under the caller's
20
+ * timeout, and on PostgreSQL inside a read-only transaction that is rolled back.
21
+ *
17
22
  * Security:
18
- * - SQL validated via SQLExpressionValidator (full_query context) — blocks mutations, dangerous operations
19
- * - Executes on read-only connection pool only (no fallback to read-write)
20
- * - Configurable timeout (default 30s)
23
+ * - SQL validated by the provider (SQLExpressionValidator, single read query) — blocks mutations
24
+ * - Authorizes the RENDERED SQL: every table reference must be an entity base view the caller
25
+ * reads unscoped (CanRead, no row-level filter, no denied fields). Entities with row/field
26
+ * policy for this user are refused — raw SQL cannot apply that policy, so those reads belong
27
+ * on RunView.
28
+ * - Read-only provider only (no fallback to read-write)
29
+ * - Configurable timeout (default 30s), enforced by the database
21
30
  * - Requires authenticated user (standard GraphQL auth, no @RequireSystemUser)
22
31
  * - Refuses scope-limited principals (see {@link IsScopeLimitedPrincipal}). Raw SQL bypasses
23
32
  * RunView, entity permissions and row-level security, so the RLS scope tokens that confine a
@@ -29,22 +38,18 @@ declare class AdhocQueryInput {
29
38
  export declare class AdhocQueryResolver extends ResolverBase {
30
39
  ExecuteAdhocQuery(input: AdhocQueryInput, context: AppContext): Promise<RunQueryResultType>;
31
40
  /**
32
- * Runs the page's data SQL, then — only when the page is FULL (so more rows may
33
- * exist) — a COUNT(*) for the true total. A short (or unpaged) page needs no
34
- * count: the exact total is `startRow + rowsReturned` (see {@link exactTotalFromPage}).
35
- *
36
- * The count is NON-FATAL: some queries page fine but cannot be counted — e.g.
37
- * duplicate column names are legal in a result set but rejected inside the COUNT
38
- * CTE wrap. A count failure must never sink the whole result, so we log it and
39
- * report a lower-bound total (`startRow + rowsReturned`) and let the data render.
40
- */
41
- private executeDataAndCount;
42
- /**
43
- * Executes one SQL statement on the read-only pool, racing it against the shared
44
- * wall-clock `deadline`. The timer is always cleared on completion so a settled
45
- * query never leaves a dangling timeout armed.
41
+ * SECURITY: authorizes the READ itself, against the SQL that will actually run. The provider
42
+ * validates that the SQL is a single read statement but places no restriction on WHAT is read.
43
+ * Rendering comes first because composition (`{{query:"..."}}`) and templates can introduce
44
+ * table references the raw input never named. Every table reference must be an entity base
45
+ * view the caller can read UNSCOPED — CanRead with no row-level filter and no denied fields —
46
+ * because raw SQL applies neither (see assertFullQueryUsesReadableEntityViews). The provider
47
+ * renders the same input the same way and only wraps it in server-built paging and a count,
48
+ * so the rendered SQL is the full set of reads. Returns the refusal message, or null.
46
49
  */
47
- private runSqlWithDeadline;
50
+ private authorizeRenderedSQL;
51
+ /** Maps the provider's result to the GraphQL shape, naming a timeout plainly. */
52
+ private toResultType;
48
53
  private buildErrorResult;
49
54
  }
50
55
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"AdhocQueryResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/AdhocQueryResolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD;;;GAGG;AACH,cACM,eAAe;IAEjB,GAAG,EAAE,MAAM,CAAC;IAGZ,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBACa,kBAAmB,SAAQ,YAAY;IAE1C,iBAAiB,CACkB,KAAK,EAAE,eAAe,EACpD,OAAO,EAAE,UAAU,GAC3B,OAAO,CAAC,kBAAkB,CAAC;IAgI9B;;;;;;;;;OASG;YACW,mBAAmB;IA6BjC;;;;OAIG;YACW,kBAAkB;IAwBhC,OAAO,CAAC,gBAAgB;CAc3B"}
1
+ {"version":3,"file":"AdhocQueryResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/AdhocQueryResolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;;GAGG;AACH,cACM,eAAe;IAEjB,GAAG,EAAE,MAAM,CAAC;IAGZ,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,OAAO,CAAC,EAAE,MAAM,CAAC;IAGjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,kBAAmB,SAAQ,YAAY;IAE1C,iBAAiB,CACkB,KAAK,EAAE,eAAe,EACpD,OAAO,EAAE,UAAU,GAC3B,OAAO,CAAC,kBAAkB,CAAC;IAoC9B;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAW5B,iFAAiF;IACjF,OAAO,CAAC,YAAY;IA6BpB,OAAO,CAAC,gBAAgB;CAc3B"}
@@ -12,14 +12,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  };
13
13
  import { Arg, Ctx, Query, Resolver, Field, Int, InputType } from 'type-graphql';
14
14
  import { LogError } from '@memberjunction/core';
15
- import { SQLExpressionValidator } from '@memberjunction/global';
16
15
  import { RenderPipeline } from '@memberjunction/generic-database-provider';
17
- import { GetReadOnlyDataSource, GetReadOnlyProvider } from '../util.js';
16
+ import { configInfo } from '../config.js';
17
+ import { GetReadOnlyProvider } from '../util.js';
18
18
  import { ResolverBase } from '../generic/ResolverBase.js';
19
19
  import { IsScopeLimitedPrincipal } from '../auth/scopeLimitedPrincipal.js';
20
20
  import { RunQueryResultType } from './QueryResolver.js';
21
- import { ExactTotalFromPage, ResolveAdhocTotalRowCount } from './adhoc-query-helpers.js';
22
- import sql from 'mssql';
21
+ import { ClampAdhocTimeoutSeconds } from './adhocTimeout.js';
23
22
  /**
24
23
  * Input type for executing ad-hoc SQL queries directly.
25
24
  * The SQL is validated server-side to ensure it's a safe SELECT/WITH statement.
@@ -48,10 +47,19 @@ AdhocQueryInput = __decorate([
48
47
  /**
49
48
  * Resolver for executing ad-hoc (unsaved) SQL queries.
50
49
  *
50
+ * The query runs through the read-only provider's own ad-hoc path (`RunQuery` with `SQL`), the
51
+ * same one in-process callers use, so it behaves identically on every database platform: the SQL
52
+ * is validated and rendered there, paged in the database with a count, run under the caller's
53
+ * timeout, and on PostgreSQL inside a read-only transaction that is rolled back.
54
+ *
51
55
  * Security:
52
- * - SQL validated via SQLExpressionValidator (full_query context) — blocks mutations, dangerous operations
53
- * - Executes on read-only connection pool only (no fallback to read-write)
54
- * - Configurable timeout (default 30s)
56
+ * - SQL validated by the provider (SQLExpressionValidator, single read query) — blocks mutations
57
+ * - Authorizes the RENDERED SQL: every table reference must be an entity base view the caller
58
+ * reads unscoped (CanRead, no row-level filter, no denied fields). Entities with row/field
59
+ * policy for this user are refused — raw SQL cannot apply that policy, so those reads belong
60
+ * on RunView.
61
+ * - Read-only provider only (no fallback to read-write)
62
+ * - Configurable timeout (default 30s), enforced by the database
55
63
  * - Requires authenticated user (standard GraphQL auth, no @RequireSystemUser)
56
64
  * - Refuses scope-limited principals (see {@link IsScopeLimitedPrincipal}). Raw SQL bypasses
57
65
  * RunView, entity permissions and row-level security, so the RLS scope tokens that confine a
@@ -63,180 +71,82 @@ AdhocQueryInput = __decorate([
63
71
  let AdhocQueryResolver = class AdhocQueryResolver extends ResolverBase {
64
72
  async ExecuteAdhocQuery(input, context) {
65
73
  const startTime = Date.now();
74
+ // SECURITY: refuse principals whose read authority is narrower than their role grant.
75
+ // Ad-hoc SQL does not go through RunView, entity permissions or row-level security, so the
76
+ // RLS scope tokens that confine a magic-link session are never substituted. There is no
77
+ // filter to narrow, so the only correct answer for such a principal is no.
78
+ if (IsScopeLimitedPrincipal(context.userPayload?.userRecord)) {
79
+ return this.buildErrorResult('Ad-hoc SQL execution is not permitted for scope-limited sessions.');
80
+ }
81
+ const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: false });
82
+ if (!provider) {
83
+ return this.buildErrorResult('No read-only data source available for ad-hoc query execution');
84
+ }
85
+ const contextUser = context.userPayload?.userRecord;
86
+ const refusal = this.authorizeRenderedSQL(input.SQL, provider.PlatformKey, context, contextUser);
87
+ if (refusal) {
88
+ return this.buildErrorResult(refusal, Date.now() - startTime);
89
+ }
90
+ const timeoutSeconds = ClampAdhocTimeoutSeconds(input.TimeoutSeconds, configInfo.databaseSettings.requestTimeout);
91
+ // A negative offset must not reach paging, where it would turn paging off.
92
+ const startRow = Math.max(0, Number.isInteger(input.StartRow) ? input.StartRow : 0);
66
93
  try {
67
- // 1. SECURITY: refuse principals whose read authority is narrower than their role
68
- // grant. This resolver runs a raw SELECT on the read-only pool — it does NOT go
69
- // through RunView, entity permissions or row-level security, so the RLS scope tokens
70
- // that confine a magic-link session are never substituted here. There is no filter
71
- // to narrow, so the only correct answer for such a principal is no. Checked before
72
- // the SQL is even validated: authorization gates the work, it does not race it.
73
- if (IsScopeLimitedPrincipal(context.userPayload?.userRecord)) {
74
- return this.buildErrorResult('Ad-hoc SQL execution is not permitted for scope-limited sessions.');
75
- }
76
- // 2. Security: validate SQL using SQLExpressionValidator
77
- const validator = SQLExpressionValidator.Instance;
78
- const validation = validator.validateFullQuery(input.SQL);
79
- if (!validation.valid) {
80
- return this.buildErrorResult(validation.error || 'SQL validation failed');
81
- }
82
- // 3. Get READ-ONLY data source (no fallback to read-write)
83
- let readOnlyDS;
84
- try {
85
- readOnlyDS = GetReadOnlyDataSource(context.dataSources, { allowFallbackToReadWrite: false });
86
- }
87
- catch {
88
- return this.buildErrorResult('No read-only data source available for ad-hoc query execution');
89
- }
90
- // 4. Resolve platform from the read-only provider for the render pipeline.
91
- let platform = 'sqlserver';
92
- try {
93
- const provider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: false });
94
- if (provider?.PlatformKey)
95
- platform = provider.PlatformKey;
96
- }
97
- catch {
98
- // Provider not configured — keep the default platform.
99
- }
100
- const contextUser = context.userPayload?.userRecord;
101
- // 5. Route the SQL through RenderPipeline so composition tokens
102
- // resolve, comments and templates are processed, and the row cap
103
- // is applied at the database (via TOP / LIMIT / OFFSET-FETCH).
104
- //
105
- // Page whenever a positive MaxRows is requested — INCLUDING the first
106
- // page (StartRow 0). This yields OFFSET/FETCH data SQL *and* a
107
- // COUNT(*) query so the response reports the true total row count
108
- // rather than just the returned page size. It mirrors the saved-query
109
- // path (GenericDatabaseProvider.InternalRunQuery → WrapWithPaging).
110
- // (Previously paging was gated on StartRow > 0, so page 1 fell back to
111
- // a TOP-N cap with TotalRowCount = page size — hiding the pager.)
112
- // Clamp StartRow to a non-negative integer. A negative offset must not slip
113
- // past the paging gate (which would then run the query with no row cap at all).
114
- const startRow = Math.max(0, Number.isInteger(input.StartRow) ? input.StartRow : 0);
115
- const maxRows = input.MaxRows;
116
- const usePaging = maxRows != null && Number.isInteger(maxRows) && maxRows > 0;
117
- let dataSQL;
118
- let countSQL = null;
119
- try {
120
- const rendered = RenderPipeline.Run(input.SQL, {
121
- Platform: platform,
122
- ContextUser: contextUser,
123
- ...(usePaging ? { Paging: { StartRow: startRow, MaxRows: maxRows } } : {}),
124
- });
125
- dataSQL = rendered.FinalSQL;
126
- countSQL = rendered.PagingResult?.CountSQL ?? null;
127
- }
128
- catch (renderErr) {
129
- const renderMsg = renderErr instanceof Error ? renderErr.message : String(renderErr);
130
- return this.buildErrorResult(`Ad-hoc query rendering failed: ${renderMsg}`);
131
- }
132
- // 6. Execute the page (and, only when a full page needs it, the count) under
133
- // a shared wall-clock deadline derived from the request's timeout budget.
134
- const deadline = startTime + (input.TimeoutSeconds ?? 30) * 1000;
135
- const { recordset, totalRowCount } = await this.executeDataAndCount(readOnlyDS, dataSQL, countSQL, startRow, usePaging ? maxRows : null, deadline);
136
- const executionTimeMs = Date.now() - startTime;
137
- // 7. Return as RunQueryResultType
138
- return {
139
- QueryID: '',
140
- QueryName: 'Ad-Hoc Query',
141
- Success: true,
142
- Results: JSON.stringify(recordset),
143
- RowCount: recordset.length,
144
- TotalRowCount: totalRowCount,
145
- PageNumber: usePaging ? Math.floor(startRow / maxRows) + 1 : undefined,
146
- PageSize: usePaging ? maxRows : undefined,
147
- ExecutionTime: executionTimeMs,
148
- ErrorMessage: ''
149
- };
94
+ const result = await provider.RunQuery({
95
+ SQL: input.SQL,
96
+ MaxRows: input.MaxRows,
97
+ StartRow: startRow,
98
+ TimeoutSeconds: timeoutSeconds,
99
+ }, contextUser);
100
+ return this.toResultType(result, startRow, input.MaxRows, timeoutSeconds, Date.now() - startTime);
150
101
  }
151
102
  catch (err) {
152
- const executionTimeMs = Date.now() - startTime;
153
103
  const errorMessage = err instanceof Error ? err.message : String(err);
154
- // Handle timeout
155
- if (errorMessage.includes('timeout') || errorMessage.includes('Timeout')) {
156
- return {
157
- QueryID: '',
158
- QueryName: 'Ad-Hoc Query',
159
- Success: false,
160
- Results: '[]',
161
- RowCount: 0,
162
- TotalRowCount: 0,
163
- PageNumber: undefined,
164
- PageSize: undefined,
165
- ExecutionTime: executionTimeMs,
166
- ErrorMessage: `Query execution exceeded ${input.TimeoutSeconds ?? 30} second timeout`
167
- };
168
- }
169
104
  LogError(`Ad-hoc query execution failed: ${errorMessage}`);
170
- return {
171
- QueryID: '',
172
- QueryName: 'Ad-Hoc Query',
173
- Success: false,
174
- Results: '[]',
175
- RowCount: 0,
176
- TotalRowCount: 0,
177
- PageNumber: undefined,
178
- PageSize: undefined,
179
- ExecutionTime: executionTimeMs,
180
- ErrorMessage: `Query execution failed: ${errorMessage}`
181
- };
105
+ return this.buildErrorResult(`Query execution failed: ${errorMessage}`, Date.now() - startTime);
182
106
  }
183
107
  }
184
108
  /**
185
- * Runs the page's data SQL, then — only when the page is FULL (so more rows may
186
- * exist) — a COUNT(*) for the true total. A short (or unpaged) page needs no
187
- * count: the exact total is `startRow + rowsReturned` (see {@link exactTotalFromPage}).
188
- *
189
- * The count is NON-FATAL: some queries page fine but cannot be counted — e.g.
190
- * duplicate column names are legal in a result set but rejected inside the COUNT
191
- * CTE wrap. A count failure must never sink the whole result, so we log it and
192
- * report a lower-bound total (`startRow + rowsReturned`) and let the data render.
109
+ * SECURITY: authorizes the READ itself, against the SQL that will actually run. The provider
110
+ * validates that the SQL is a single read statement but places no restriction on WHAT is read.
111
+ * Rendering comes first because composition (`{{query:"..."}}`) and templates can introduce
112
+ * table references the raw input never named. Every table reference must be an entity base
113
+ * view the caller can read UNSCOPED — CanRead with no row-level filter and no denied fields —
114
+ * because raw SQL applies neither (see assertFullQueryUsesReadableEntityViews). The provider
115
+ * renders the same input the same way and only wraps it in server-built paging and a count,
116
+ * so the rendered SQL is the full set of reads. Returns the refusal message, or null.
193
117
  */
194
- async executeDataAndCount(ds, dataSQL, countSQL, startRow, maxRows, deadline) {
195
- const dataResult = await this.runSqlWithDeadline(ds, dataSQL, deadline);
196
- const recordset = (dataResult.recordset ?? []);
197
- // Total already known from the page alone (unpaged, or a short page)? Skip the count.
198
- const exact = ExactTotalFromPage(startRow, recordset.length, maxRows);
199
- if (exact != null || !countSQL) {
200
- return { recordset, totalRowCount: exact ?? recordset.length };
201
- }
202
- // Full page — a COUNT(*) is required to know the true total.
203
- const lowerBound = startRow + recordset.length;
118
+ authorizeRenderedSQL(sqlText, platform, context, contextUser) {
204
119
  try {
205
- const countResult = await this.runSqlWithDeadline(ds, countSQL, deadline);
206
- return { recordset, totalRowCount: ResolveAdhocTotalRowCount(countResult.recordset, lowerBound) };
120
+ const rendered = RenderPipeline.Run(sqlText, { Platform: platform, ContextUser: contextUser, RequireReadStatement: true });
121
+ const mdProvider = GetReadOnlyProvider(context.providers, { allowFallbackToReadWrite: true }) ?? undefined;
122
+ this.assertFullQueryUsesReadableEntityViews(rendered.Trace.AfterTemplates, mdProvider, contextUser, 'ad-hoc SQL');
123
+ return null;
207
124
  }
208
- catch (countErr) {
209
- const msg = countErr instanceof Error ? countErr.message : String(countErr);
210
- LogError(`Ad-hoc query row-count failed; reporting a lower-bound total (${lowerBound}). ${msg}`);
211
- return { recordset, totalRowCount: lowerBound };
125
+ catch (err) {
126
+ return err instanceof Error ? err.message : String(err);
212
127
  }
213
128
  }
214
- /**
215
- * Executes one SQL statement on the read-only pool, racing it against the shared
216
- * wall-clock `deadline`. The timer is always cleared on completion so a settled
217
- * query never leaves a dangling timeout armed.
218
- */
219
- async runSqlWithDeadline(ds, sqlText, deadline) {
220
- const remaining = deadline - Date.now();
221
- if (remaining <= 0) {
222
- throw new Error('Query timeout exceeded');
223
- }
224
- let timer;
225
- try {
226
- return await Promise.race([
227
- new sql.Request(ds).query(sqlText),
228
- new Promise((_, reject) => {
229
- timer = setTimeout(() => reject(new Error('Query timeout exceeded')), remaining);
230
- }),
231
- ]);
232
- }
233
- finally {
234
- if (timer) {
235
- clearTimeout(timer);
236
- }
129
+ /** Maps the provider's result to the GraphQL shape, naming a timeout plainly. */
130
+ toResultType(result, startRow, maxRows, timeoutSeconds, executionTimeMs) {
131
+ if (!result.Success) {
132
+ const message = result.ErrorMessage ?? 'Ad-hoc query failed';
133
+ return this.buildErrorResult(/timeout/i.test(message) ? `Query execution exceeded ${timeoutSeconds} second timeout` : message, executionTimeMs);
237
134
  }
135
+ const paged = maxRows != null && Number.isInteger(maxRows) && maxRows > 0;
136
+ return {
137
+ QueryID: '',
138
+ QueryName: 'Ad-Hoc Query',
139
+ Success: true,
140
+ Results: JSON.stringify(result.Results),
141
+ RowCount: result.RowCount,
142
+ TotalRowCount: result.TotalRowCount,
143
+ PageNumber: paged ? Math.floor(startRow / maxRows) + 1 : undefined,
144
+ PageSize: paged ? maxRows : undefined,
145
+ ExecutionTime: executionTimeMs,
146
+ ErrorMessage: ''
147
+ };
238
148
  }
239
- buildErrorResult(errorMessage) {
149
+ buildErrorResult(errorMessage, executionTimeMs = 0) {
240
150
  return {
241
151
  QueryID: '',
242
152
  QueryName: 'Ad-Hoc Query',
@@ -246,7 +156,7 @@ let AdhocQueryResolver = class AdhocQueryResolver extends ResolverBase {
246
156
  TotalRowCount: 0,
247
157
  PageNumber: undefined,
248
158
  PageSize: undefined,
249
- ExecutionTime: 0,
159
+ ExecutionTime: executionTimeMs,
250
160
  ErrorMessage: errorMessage
251
161
  };
252
162
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AdhocQueryResolver.js","sourceRoot":"","sources":["../../src/resolvers/AdhocQueryResolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AdhocQueryResolver.js","sourceRoot":"","sources":["../../src/resolvers/AdhocQueryResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Publishes one agent run's live status on the caller's session.
3
+ *
4
+ * `RunAIAgentResolver` uses this for every status it sends. A host whose
5
+ * `AgentTurnHandler` answers with an In-Progress reply uses the same publisher,
6
+ * on that caller's session, so the chat follows the turn: significant-step
7
+ * progress, streamed text, the partial result, and the completion. When the
8
+ * turn throws instead of returning a result, call `PublishFailure` with the
9
+ * reply row's id and the error.
10
+ */
11
+ import type { PubSubEngine } from 'type-graphql';
12
+ import type { AgentExecutionProgressCallback, AgentExecutionStreamingCallback, ExecuteAgentResult } from '@memberjunction/ai-core-plus';
13
+ import type { UserPayload } from '../types.js';
14
+ /** The run fields the published messages read. Entities and test fakes both satisfy this. */
15
+ interface StatusRun {
16
+ ID?: string;
17
+ ConversationDetailID?: string;
18
+ ErrorMessage?: string;
19
+ Steps?: Array<{
20
+ StepName?: string;
21
+ }>;
22
+ GetAll?: () => unknown;
23
+ }
24
+ export declare class AgentRunStatusPublisher {
25
+ private readonly pubSub;
26
+ private readonly userPayload;
27
+ private readonly sessionId;
28
+ private run;
29
+ /**
30
+ * @param sessionId Session stamped on the message body. Defaults to the payload's session.
31
+ * The push itself is always addressed to `userPayload.sessionId`, matching the resolver.
32
+ */
33
+ constructor(pubSub: PubSubEngine, userPayload: UserPayload, sessionId?: string);
34
+ /** Latest run observed from a progress event, including steps that are not published. */
35
+ get AgentRun(): StatusRun | null;
36
+ /** AgentRunner's progress callback. Noise steps are kept for {@link AgentRun} and not published. */
37
+ get OnProgress(): AgentExecutionProgressCallback;
38
+ /** AgentRunner's streaming callback. Publishes nothing until a progress event has carried the run. */
39
+ get OnStreaming(): AgentExecutionStreamingCallback;
40
+ /**
41
+ * The partial result, then the completion. `conversationDetailId` is the reply row the
42
+ * chat should update. When omitted, the completion uses the run's own detail id.
43
+ */
44
+ PublishFinal(result: ExecuteAgentResult, conversationDetailId?: string, resultJson?: string): void;
45
+ /**
46
+ * Completion for a failure that has no run. The fire-and-forget path uses this when
47
+ * `executeAIAgent` rejects. A host uses it the same way: when the turn throws
48
+ * instead of returning a result, call `PublishFailure` with the reply row's id
49
+ * and the error. That completion is what tells the chat the reply finished.
50
+ */
51
+ PublishFailure(conversationDetailId: string | undefined, errorMessage: string): void;
52
+ private publish;
53
+ }
54
+ export {};
55
+ //# sourceMappingURL=AgentRunStatusPublisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentRunStatusPublisher.d.ts","sourceRoot":"","sources":["../../src/resolvers/AgentRunStatusPublisher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EACR,8BAA8B,EAC9B,+BAA+B,EAC/B,kBAAkB,EACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,6FAA6F;AAC7F,UAAU,SAAS;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC;CAC1B;AAED,qBAAa,uBAAuB;IAQ5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAT9B,OAAO,CAAC,GAAG,CAA0B;IAErC;;;OAGG;gBAEkB,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,WAAW,EACxB,SAAS,GAAE,MAA8B;IAG9D,yFAAyF;IACzF,IAAW,QAAQ,IAAI,SAAS,GAAG,IAAI,CAEtC;IAED,oGAAoG;IACpG,IAAW,UAAU,IAAI,8BAA8B,CAgCtD;IAED,sGAAsG;IACtG,IAAW,WAAW,IAAI,+BAA+B,CAsBxD;IAED;;;OAGG;IACI,YAAY,CAAC,MAAM,EAAE,kBAAkB,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IA+BzG;;;;;OAKG;IACI,cAAc,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAa3F,OAAO,CAAC,OAAO;CAYlB"}
@@ -0,0 +1,141 @@
1
+ import { PublishStatusUpdate } from '../generic/PushStatusResolver.js';
2
+ const SIGNIFICANT_STEPS = ['prompt_execution', 'action_execution', 'subagent_execution', 'decision_processing'];
3
+ export class AgentRunStatusPublisher {
4
+ /**
5
+ * @param sessionId Session stamped on the message body. Defaults to the payload's session.
6
+ * The push itself is always addressed to `userPayload.sessionId`, matching the resolver.
7
+ */
8
+ constructor(pubSub, userPayload, sessionId = userPayload.sessionId) {
9
+ this.pubSub = pubSub;
10
+ this.userPayload = userPayload;
11
+ this.sessionId = sessionId;
12
+ this.run = null;
13
+ }
14
+ /** Latest run observed from a progress event, including steps that are not published. */
15
+ get AgentRun() {
16
+ return this.run;
17
+ }
18
+ /** AgentRunner's progress callback. Noise steps are kept for {@link AgentRun} and not published. */
19
+ get OnProgress() {
20
+ return (progress) => {
21
+ const fromEvent = progress.metadata?.agentRun;
22
+ if (fromEvent) {
23
+ this.run = fromEvent;
24
+ }
25
+ if (!SIGNIFICANT_STEPS.includes(progress.step)) {
26
+ return;
27
+ }
28
+ const agentRun = fromEvent || this.run;
29
+ if (!agentRun?.ID) {
30
+ // A host that streams before the first progress event otherwise sees nothing and no reason.
31
+ console.error('❌ No agent run available for progress callback');
32
+ return;
33
+ }
34
+ this.publish('ExecutionProgress', {
35
+ sessionId: this.sessionId,
36
+ agentRunId: agentRun.ID,
37
+ type: 'progress',
38
+ agentRun: agentRun.GetAll ? agentRun.GetAll() : agentRun,
39
+ progress: {
40
+ currentStep: progress.step,
41
+ percentage: progress.percentage,
42
+ message: progress.message,
43
+ agentName: progress.metadata?.agentName,
44
+ agentType: progress.metadata?.agentType,
45
+ stepCount: progress.metadata?.stepCount,
46
+ hierarchicalStep: progress.metadata?.hierarchicalStep,
47
+ },
48
+ timestamp: new Date(),
49
+ });
50
+ };
51
+ }
52
+ /** AgentRunner's streaming callback. Publishes nothing until a progress event has carried the run. */
53
+ get OnStreaming() {
54
+ return (chunk) => {
55
+ const agentRun = this.run;
56
+ if (!agentRun?.ID) {
57
+ console.error('❌ No agent run available for streaming callback');
58
+ return;
59
+ }
60
+ this.publish('StreamingContent', {
61
+ sessionId: this.sessionId,
62
+ agentRunId: agentRun.ID,
63
+ type: 'streaming',
64
+ agentRun: agentRun.GetAll ? agentRun.GetAll() : agentRun,
65
+ streaming: {
66
+ content: chunk.content,
67
+ isPartial: !chunk.isComplete,
68
+ stepName: chunk.stepType,
69
+ agentName: chunk.modelName,
70
+ kind: chunk.kind,
71
+ },
72
+ timestamp: new Date(),
73
+ });
74
+ };
75
+ }
76
+ /**
77
+ * The partial result, then the completion. `conversationDetailId` is the reply row the
78
+ * chat should update. When omitted, the completion uses the run's own detail id.
79
+ */
80
+ PublishFinal(result, conversationDetailId, resultJson) {
81
+ const agentRun = result.agentRun;
82
+ if (agentRun?.ID) {
83
+ let lastStep = 'Completed';
84
+ const steps = agentRun.Steps;
85
+ if (steps && steps.length > 0) {
86
+ lastStep = steps[steps.length - 1]?.StepName || 'Completed';
87
+ }
88
+ this.publish('StreamingContent', {
89
+ sessionId: this.sessionId,
90
+ agentRunId: agentRun.ID,
91
+ type: 'partial_result',
92
+ partialResult: {
93
+ currentStep: lastStep,
94
+ partialOutput: result.payload || undefined,
95
+ },
96
+ timestamp: new Date(),
97
+ });
98
+ }
99
+ this.publish('StreamingContent', {
100
+ sessionId: this.sessionId,
101
+ agentRunId: agentRun?.ID || 'unknown',
102
+ type: 'complete',
103
+ timestamp: new Date(),
104
+ conversationDetailId: conversationDetailId || agentRun?.ConversationDetailID,
105
+ success: result.success,
106
+ errorMessage: agentRun?.ErrorMessage || undefined,
107
+ result: resultJson || undefined,
108
+ });
109
+ }
110
+ /**
111
+ * Completion for a failure that has no run. The fire-and-forget path uses this when
112
+ * `executeAIAgent` rejects. A host uses it the same way: when the turn throws
113
+ * instead of returning a result, call `PublishFailure` with the reply row's id
114
+ * and the error. That completion is what tells the chat the reply finished.
115
+ */
116
+ PublishFailure(conversationDetailId, errorMessage) {
117
+ this.publish('StreamingContent', {
118
+ sessionId: this.sessionId,
119
+ agentRunId: 'unknown',
120
+ type: 'complete',
121
+ timestamp: new Date(),
122
+ conversationDetailId,
123
+ success: false,
124
+ errorMessage,
125
+ result: JSON.stringify({ success: false, errorMessage }),
126
+ });
127
+ }
128
+ publish(type, data) {
129
+ PublishStatusUpdate(this.pubSub, {
130
+ sessionId: this.userPayload.sessionId,
131
+ ownerUserId: this.userPayload?.userRecord?.ID ?? '',
132
+ message: JSON.stringify({
133
+ resolver: 'RunAIAgentResolver',
134
+ type,
135
+ status: 'ok',
136
+ data,
137
+ }),
138
+ });
139
+ }
140
+ }
141
+ //# sourceMappingURL=AgentRunStatusPublisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentRunStatusPublisher.js","sourceRoot":"","sources":["../../src/resolvers/AgentRunStatusPublisher.ts"],"names":[],"mappings":"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"}