@memberjunction/server 6.2.0-edge.4 → 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 (287) hide show
  1. package/README.md +20 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/agentSessions/SessionJanitor.d.ts +91 -30
  4. package/dist/agentSessions/SessionJanitor.d.ts.map +1 -1
  5. package/dist/agentSessions/SessionJanitor.js +311 -81
  6. package/dist/agentSessions/SessionJanitor.js.map +1 -1
  7. package/dist/agentSessions/SessionManager.d.ts +5 -1
  8. package/dist/agentSessions/SessionManager.d.ts.map +1 -1
  9. package/dist/agentSessions/SessionManager.js +13 -1
  10. package/dist/agentSessions/SessionManager.js.map +1 -1
  11. package/dist/apiRoot.d.ts +32 -0
  12. package/dist/apiRoot.d.ts.map +1 -0
  13. package/dist/apiRoot.js +67 -0
  14. package/dist/apiRoot.js.map +1 -0
  15. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -1
  16. package/dist/auth/AuthProviderCatalogRouter.js +25 -0
  17. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -1
  18. package/dist/auth/LoginScreenEngine.d.ts +22 -0
  19. package/dist/auth/LoginScreenEngine.d.ts.map +1 -0
  20. package/dist/auth/LoginScreenEngine.js +57 -0
  21. package/dist/auth/LoginScreenEngine.js.map +1 -0
  22. package/dist/auth/index.d.ts +1 -0
  23. package/dist/auth/index.d.ts.map +1 -1
  24. package/dist/auth/index.js +1 -0
  25. package/dist/auth/index.js.map +1 -1
  26. package/dist/auth/magicLink/MagicLinkRouter.d.ts.map +1 -1
  27. package/dist/auth/magicLink/MagicLinkRouter.js +3 -2
  28. package/dist/auth/magicLink/MagicLinkRouter.js.map +1 -1
  29. package/dist/config.d.ts +136 -22
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/config.js +43 -4
  32. package/dist/config.js.map +1 -1
  33. package/dist/coreRoutes.d.ts +29 -0
  34. package/dist/coreRoutes.d.ts.map +1 -0
  35. package/dist/coreRoutes.js +142 -0
  36. package/dist/coreRoutes.js.map +1 -0
  37. package/dist/generated/graphql-schemas/__mj.d.ts +369 -3
  38. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  39. package/dist/generated/graphql-schemas/__mj.js +1750 -7
  40. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  41. package/dist/generic/CacheInvalidationResolver.d.ts +43 -8
  42. package/dist/generic/CacheInvalidationResolver.d.ts.map +1 -1
  43. package/dist/generic/CacheInvalidationResolver.js +59 -19
  44. package/dist/generic/CacheInvalidationResolver.js.map +1 -1
  45. package/dist/generic/PushStatusResolver.js +1 -1
  46. package/dist/generic/PushStatusResolver.js.map +1 -1
  47. package/dist/generic/ResolverBase.d.ts +103 -44
  48. package/dist/generic/ResolverBase.d.ts.map +1 -1
  49. package/dist/generic/ResolverBase.js +264 -305
  50. package/dist/generic/ResolverBase.js.map +1 -1
  51. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  52. package/dist/generic/RunViewResolver.js +12 -0
  53. package/dist/generic/RunViewResolver.js.map +1 -1
  54. package/dist/globalCors.d.ts +33 -0
  55. package/dist/globalCors.d.ts.map +1 -0
  56. package/dist/globalCors.js +58 -0
  57. package/dist/globalCors.js.map +1 -0
  58. package/dist/index.d.ts +11 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +112 -160
  61. package/dist/index.js.map +1 -1
  62. package/dist/multiTenancy/index.d.ts.map +1 -1
  63. package/dist/multiTenancy/index.js +22 -2
  64. package/dist/multiTenancy/index.js.map +1 -1
  65. package/dist/realtimeSessions/RealtimeSessionVerificationService.d.ts.map +1 -1
  66. package/dist/realtimeSessions/RealtimeSessionVerificationService.js +2 -1
  67. package/dist/realtimeSessions/RealtimeSessionVerificationService.js.map +1 -1
  68. package/dist/realtimeSessions/RealtimeVerifyRouter.d.ts.map +1 -1
  69. package/dist/realtimeSessions/RealtimeVerifyRouter.js +2 -1
  70. package/dist/realtimeSessions/RealtimeVerifyRouter.js.map +1 -1
  71. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts +100 -0
  72. package/dist/realtimeSessions/RecordingAssemblyScheduler.d.ts.map +1 -0
  73. package/dist/realtimeSessions/RecordingAssemblyScheduler.js +173 -0
  74. package/dist/realtimeSessions/RecordingAssemblyScheduler.js.map +1 -0
  75. package/dist/realtimeSessions/index.d.ts +2 -0
  76. package/dist/realtimeSessions/index.d.ts.map +1 -1
  77. package/dist/realtimeSessions/index.js +2 -0
  78. package/dist/realtimeSessions/index.js.map +1 -1
  79. package/dist/realtimeSessions/ownedRealtimeSession.d.ts +30 -0
  80. package/dist/realtimeSessions/ownedRealtimeSession.d.ts.map +1 -0
  81. package/dist/realtimeSessions/ownedRealtimeSession.js +47 -0
  82. package/dist/realtimeSessions/ownedRealtimeSession.js.map +1 -0
  83. package/dist/realtimeSessions/sessionAccess.d.ts +6 -0
  84. package/dist/realtimeSessions/sessionAccess.d.ts.map +1 -1
  85. package/dist/realtimeSessions/sessionAccess.js +7 -3
  86. package/dist/realtimeSessions/sessionAccess.js.map +1 -1
  87. package/dist/resolvers/ArtifactFileResolver.d.ts +5 -1
  88. package/dist/resolvers/ArtifactFileResolver.d.ts.map +1 -1
  89. package/dist/resolvers/ArtifactFileResolver.js +9 -7
  90. package/dist/resolvers/ArtifactFileResolver.js.map +1 -1
  91. package/dist/resolvers/ConversationRunEventsResolver.d.ts +8 -4
  92. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -1
  93. package/dist/resolvers/ConversationRunEventsResolver.js +6 -6
  94. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -1
  95. package/dist/resolvers/DatasetResolver.d.ts +24 -3
  96. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  97. package/dist/resolvers/DatasetResolver.js +57 -8
  98. package/dist/resolvers/DatasetResolver.js.map +1 -1
  99. package/dist/resolvers/EntityRecordNameResolver.d.ts +2 -1
  100. package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
  101. package/dist/resolvers/EntityRecordNameResolver.js +3 -2
  102. package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
  103. package/dist/resolvers/FetchEntityVectorsResolver.d.ts +18 -3
  104. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  105. package/dist/resolvers/FetchEntityVectorsResolver.js +100 -35
  106. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  107. package/dist/resolvers/FileResolver.d.ts +82 -11
  108. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  109. package/dist/resolvers/FileResolver.js +279 -101
  110. package/dist/resolvers/FileResolver.js.map +1 -1
  111. package/dist/resolvers/GetDataContextDataResolver.d.ts +33 -7
  112. package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
  113. package/dist/resolvers/GetDataContextDataResolver.js +117 -38
  114. package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
  115. package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
  116. package/dist/resolvers/GetDataResolver.js +6 -3
  117. package/dist/resolvers/GetDataResolver.js.map +1 -1
  118. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  119. package/dist/resolvers/IntegrationDiscoveryResolver.js +4 -2
  120. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  121. package/dist/resolvers/QueryResolver.d.ts +2 -0
  122. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  123. package/dist/resolvers/QueryResolver.js +13 -0
  124. package/dist/resolvers/QueryResolver.js.map +1 -1
  125. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +2 -8
  126. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  127. package/dist/resolvers/RealtimeClientSessionResolver.js +10 -26
  128. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  129. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  130. package/dist/resolvers/RunAIAgentResolver.js +35 -6
  131. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  132. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts +12 -1
  133. package/dist/resolvers/SearchKnowledgeStreamResolver.d.ts.map +1 -1
  134. package/dist/resolvers/SearchKnowledgeStreamResolver.js +15 -2
  135. package/dist/resolvers/SearchKnowledgeStreamResolver.js.map +1 -1
  136. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  137. package/dist/resolvers/SqlLoggingConfigResolver.js +2 -3
  138. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  139. package/dist/resolvers/TaskGraphFrameResolver.d.ts +2 -1
  140. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  141. package/dist/resolvers/TaskGraphFrameResolver.js +28 -1
  142. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  143. package/dist/resolvers/TestQuerySQLResolver.d.ts +24 -0
  144. package/dist/resolvers/TestQuerySQLResolver.d.ts.map +1 -1
  145. package/dist/resolvers/TestQuerySQLResolver.js +65 -13
  146. package/dist/resolvers/TestQuerySQLResolver.js.map +1 -1
  147. package/dist/resolvers/TransactionGroupResolver.d.ts +19 -2
  148. package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
  149. package/dist/resolvers/TransactionGroupResolver.js +102 -24
  150. package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
  151. package/dist/resolvers/agent-run-data-guard.d.ts +31 -0
  152. package/dist/resolvers/agent-run-data-guard.d.ts.map +1 -0
  153. package/dist/resolvers/agent-run-data-guard.js +72 -0
  154. package/dist/resolvers/agent-run-data-guard.js.map +1 -0
  155. package/dist/rest/RealtimeRecordingHandler.d.ts +49 -0
  156. package/dist/rest/RealtimeRecordingHandler.d.ts.map +1 -0
  157. package/dist/rest/RealtimeRecordingHandler.js +383 -0
  158. package/dist/rest/RealtimeRecordingHandler.js.map +1 -0
  159. package/dist/rest/ViewOperationsHandler.d.ts +3 -1
  160. package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
  161. package/dist/rest/ViewOperationsHandler.js +21 -12
  162. package/dist/rest/ViewOperationsHandler.js.map +1 -1
  163. package/dist/rest/setupRESTEndpoints.d.ts +6 -0
  164. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  165. package/dist/rest/setupRESTEndpoints.js +6 -0
  166. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  167. package/dist/serverExtensionReservedRoots.d.ts +12 -10
  168. package/dist/serverExtensionReservedRoots.d.ts.map +1 -1
  169. package/dist/serverExtensionReservedRoots.js +14 -17
  170. package/dist/serverExtensionReservedRoots.js.map +1 -1
  171. package/dist/services/MJStorageBlobStore.d.ts +8 -1
  172. package/dist/services/MJStorageBlobStore.d.ts.map +1 -1
  173. package/dist/services/MJStorageBlobStore.js +25 -19
  174. package/dist/services/MJStorageBlobStore.js.map +1 -1
  175. package/dist/services/StartTaskGraphDispatcher.js +2 -2
  176. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  177. package/dist/services/TaskGraphActionRunner.d.ts +5 -3
  178. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -1
  179. package/dist/services/TaskGraphActionRunner.js +27 -5
  180. package/dist/services/TaskGraphActionRunner.js.map +1 -1
  181. package/dist/services/TaskGraphAgentRunner.d.ts +14 -2
  182. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  183. package/dist/services/TaskGraphAgentRunner.js +157 -9
  184. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  185. package/dist/services/TaskGraphContinuationDeliverer.d.ts +54 -2
  186. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  187. package/dist/services/TaskGraphContinuationDeliverer.js +598 -15
  188. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  189. package/dist/sharedCache.d.ts.map +1 -1
  190. package/dist/sharedCache.js +3 -0
  191. package/dist/sharedCache.js.map +1 -1
  192. package/package.json +99 -98
  193. package/src/__tests__/DatasetResolver.itemFilters.test.ts +201 -0
  194. package/src/__tests__/EntityRecordNameResolver.rowSecurity.test.ts +152 -0
  195. package/src/__tests__/FetchEntityVectorsResolver.test.ts +163 -15
  196. package/src/__tests__/FileResolver.storageAccess.test.ts +562 -0
  197. package/src/__tests__/GetDataContextDataResolver.sqlItems.test.ts +416 -0
  198. package/src/__tests__/ListOperationsResolver.adhocScreen.test.ts +137 -0
  199. package/src/__tests__/LoginScreenEngine.test.ts +86 -0
  200. package/src/__tests__/MJStorageBlobStore.storageGate.test.ts +63 -0
  201. package/src/__tests__/RecordingAssemblyScheduler.test.ts +178 -0
  202. package/src/__tests__/ResolverBase.adhocReadScope.test.ts +133 -2
  203. package/src/__tests__/ResolverBase.balancedClause.test.ts +155 -0
  204. package/src/__tests__/ResolverBase.clauseUnscopedRead.test.ts +127 -0
  205. package/src/__tests__/ResolverBase.clientOldValues.test.ts +209 -6
  206. package/src/__tests__/ResolverBase.filterEscaping.test.ts +5 -2
  207. package/src/__tests__/RunAIAgentResolver.branch.test.ts +1 -0
  208. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +5 -3
  209. package/src/__tests__/RunAIAgentResolver.runDataGuard.test.ts +258 -0
  210. package/src/__tests__/RunViewResolver.cacheCheckScreen.test.ts +165 -0
  211. package/src/__tests__/SearchKnowledgeStreamResolver.test.ts +161 -0
  212. package/src/__tests__/SessionJanitor.test.ts +365 -10
  213. package/src/__tests__/SessionManager.test.ts +27 -0
  214. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +25 -0
  215. package/src/__tests__/TaskGraphAgentRunner.test.ts +266 -0
  216. package/src/__tests__/TaskGraphContinuationDeliverer.test.ts +356 -22
  217. package/src/__tests__/TaskGraphFrameResolver.test.ts +22 -0
  218. package/src/__tests__/TestQuerySQLResolver.test.ts +274 -0
  219. package/src/__tests__/TransactionGroupResolver.refusals.test.ts +98 -1
  220. package/src/__tests__/UpdateMJDataContextItem.oldValues.test.ts +220 -0
  221. package/src/__tests__/ViewOperationsHandler.clauseScreen.test.ts +157 -0
  222. package/src/__tests__/agent-run-data-guard.test.ts +130 -0
  223. package/src/__tests__/apiRootBoot.test.ts +202 -0
  224. package/src/__tests__/cacheInvalidationRecordData.test.ts +64 -0
  225. package/src/__tests__/conversationRunEvents.test.ts +56 -14
  226. package/src/__tests__/globalCors.test.ts +217 -0
  227. package/src/__tests__/multiTenancy.postgresRewrite.test.ts +181 -0
  228. package/src/__tests__/multiTenancy.security.test.ts +51 -0
  229. package/src/__tests__/multiTenancy.test.ts +1 -1
  230. package/src/__tests__/ownedRealtimeSession.test.ts +39 -0
  231. package/src/__tests__/pushStatusResolver.filter.test.ts +7 -0
  232. package/src/__tests__/realtimeRecordingHandler.test.ts +652 -0
  233. package/src/__tests__/serverExtensionHostOverlay.test.ts +66 -0
  234. package/src/__tests__/serverExtensionReservedRoots.test.ts +11 -98
  235. package/src/__tests__/sharedCache.test.ts +5 -3
  236. package/src/agentSessions/SessionJanitor.ts +369 -93
  237. package/src/agentSessions/SessionManager.ts +13 -1
  238. package/src/apiRoot.ts +78 -0
  239. package/src/auth/AuthProviderCatalogRouter.ts +26 -0
  240. package/src/auth/LoginScreenEngine.ts +50 -0
  241. package/src/auth/index.ts +1 -0
  242. package/src/auth/magicLink/MagicLinkRouter.ts +3 -2
  243. package/src/config.ts +46 -5
  244. package/src/coreRoutes.ts +166 -0
  245. package/src/generated/graphql-schemas/__mj.ts +1273 -10
  246. package/src/generic/CacheInvalidationResolver.ts +73 -18
  247. package/src/generic/PushStatusResolver.ts +1 -1
  248. package/src/generic/ResolverBase.ts +304 -325
  249. package/src/generic/RunViewResolver.ts +17 -0
  250. package/src/globalCors.ts +71 -0
  251. package/src/index.ts +116 -174
  252. package/src/multiTenancy/index.ts +24 -2
  253. package/src/realtimeSessions/RealtimeSessionVerificationService.ts +2 -1
  254. package/src/realtimeSessions/RealtimeVerifyRouter.ts +2 -1
  255. package/src/realtimeSessions/RecordingAssemblyScheduler.ts +234 -0
  256. package/src/realtimeSessions/index.ts +2 -0
  257. package/src/realtimeSessions/ownedRealtimeSession.ts +55 -0
  258. package/src/realtimeSessions/sessionAccess.ts +7 -3
  259. package/src/resolvers/ArtifactFileResolver.ts +9 -8
  260. package/src/resolvers/ConversationRunEventsResolver.ts +15 -11
  261. package/src/resolvers/DatasetResolver.ts +70 -10
  262. package/src/resolvers/EntityRecordNameResolver.ts +3 -2
  263. package/src/resolvers/FetchEntityVectorsResolver.ts +121 -39
  264. package/src/resolvers/FileResolver.ts +321 -106
  265. package/src/resolvers/GetDataContextDataResolver.ts +139 -41
  266. package/src/resolvers/GetDataResolver.ts +6 -3
  267. package/src/resolvers/IntegrationDiscoveryResolver.ts +4 -2
  268. package/src/resolvers/QueryResolver.ts +11 -0
  269. package/src/resolvers/RealtimeClientSessionResolver.ts +10 -33
  270. package/src/resolvers/RunAIAgentResolver.ts +39 -4
  271. package/src/resolvers/SearchKnowledgeStreamResolver.ts +19 -3
  272. package/src/resolvers/SqlLoggingConfigResolver.ts +2 -4
  273. package/src/resolvers/TaskGraphFrameResolver.ts +33 -1
  274. package/src/resolvers/TestQuerySQLResolver.ts +68 -13
  275. package/src/resolvers/TransactionGroupResolver.ts +131 -27
  276. package/src/resolvers/__tests__/GetDataResolver.validation.test.ts +95 -0
  277. package/src/resolvers/agent-run-data-guard.ts +89 -0
  278. package/src/rest/RealtimeRecordingHandler.ts +464 -0
  279. package/src/rest/ViewOperationsHandler.ts +29 -13
  280. package/src/rest/setupRESTEndpoints.ts +6 -0
  281. package/src/serverExtensionReservedRoots.ts +14 -17
  282. package/src/services/MJStorageBlobStore.ts +31 -30
  283. package/src/services/StartTaskGraphDispatcher.ts +2 -2
  284. package/src/services/TaskGraphActionRunner.ts +25 -5
  285. package/src/services/TaskGraphAgentRunner.ts +188 -11
  286. package/src/services/TaskGraphContinuationDeliverer.ts +704 -14
  287. package/src/sharedCache.ts +3 -0
@@ -1,6 +1,6 @@
1
1
  import { Resolver, Query, Arg, Ctx, ObjectType, Field, Float, Int } from 'type-graphql';
2
2
  import { AppContext } from '../types.js';
3
- import { CompositeKey, EntityInfo, IMetadataProvider, LogError, LogStatus, Metadata, RunView, UserInfo } from '@memberjunction/core';
3
+ import { CompositeKey, EntityInfo, IMetadataProvider, LogError, LogStatus, Metadata, RunView, RunViewParams, UserInfo } from '@memberjunction/core';
4
4
  import { MJEntityDocumentEntity, MJVectorIndexEntity, MJVectorDatabaseEntity } from '@memberjunction/core-entities';
5
5
  import { ResolverBase } from '../generic/ResolverBase.js';
6
6
  import { GetReadOnlyProvider } from '../util.js';
@@ -41,6 +41,15 @@ export class FetchEntityVectorsResult {
41
41
  ErrorMessage?: string;
42
42
  }
43
43
 
44
+ /** A stored vector's listing row, as `fetchStoredVectors` reads it from `MJ: Entity Record Documents`. */
45
+ type StoredVectorRow = { ID: string; RecordID: string };
46
+
47
+ /** A stored vector chosen for the result, with the labels of the record it belongs to. */
48
+ type LabelledVector = { row: StoredVectorRow; labels: Record<string, string> };
49
+
50
+ /** Most Entity Record Document IDs named in one `ID IN (...)` filter when fetching VectorJSON. */
51
+ const VECTOR_FETCH_CHUNK_SIZE = 1000;
52
+
44
53
  /* ───── Resolver ───── */
45
54
 
46
55
  @Resolver()
@@ -88,8 +97,8 @@ export class FetchEntityVectorsResolver extends ResolverBase {
88
97
 
89
98
  // Providers that keep their vectors in MJ, keyed by EntityDocumentID (the in-process
90
99
  // SimpleVectorServiceProvider), can't be listed through QueryIndex: they key by the
91
- // document ID rather than the index name, aren't handed the context user, and return
92
- // matches without vector values. Read the stored Entity Record Document rows instead.
100
+ // document ID rather than the index name, and return matches without vector values.
101
+ // Read the stored Entity Record Document rows instead.
93
102
  if (vectorDBInstance.QueryKeyIsEntityDocumentID) {
94
103
  const md = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true }) ?? Metadata.Provider;
95
104
  const results = await this.fetchStoredVectors(entityDoc, limit, filter, currentUser, md);
@@ -255,63 +264,136 @@ export class FetchEntityVectorsResolver extends ResolverBase {
255
264
  if (!entityInfo) {
256
265
  throw new Error(`Entity "${entityDoc.Entity}" not found in metadata`);
257
266
  }
258
- const labelsByRecordID = await this.loadRecordLabels(entityInfo, filter, contextUser);
267
+ const nameFields = this.labelFieldNames(entityInfo);
268
+ const { records, vectors } = await this.loadRecordsAndStoredVectors(entityInfo, entityDoc, nameFields, filter, contextUser);
269
+ const labelsByRecordID = this.mapRecordLabels(entityInfo, nameFields, records);
259
270
 
260
- const rv = new RunView();
261
- const docResult = await rv.RunView<{ ID: string; RecordID: string; VectorJSON: string }>({
262
- EntityName: 'MJ: Entity Record Documents',
263
- ExtraFilter: `EntityDocumentID='${EscapeSQLString(entityDoc.ID)}' AND VectorJSON IS NOT NULL`,
264
- Fields: ['ID', 'RecordID', 'VectorJSON'],
265
- IgnoreMaxRows: true,
266
- ResultType: 'simple',
267
- }, contextUser);
268
- if (!docResult.Success) {
269
- throw new Error(`Failed to load stored vectors: ${docResult.ErrorMessage}`);
270
- }
271
+ // VectorJSON is the heavy column: list without it, then fetch it only for the items returned.
272
+ const chosen = this.selectLabelledVectors(vectors, labelsByRecordID, limit);
273
+ const valuesByID = await this.loadVectorValues(chosen.map(c => c.row.ID), contextUser);
271
274
 
272
275
  const results: EntityVectorItem[] = [];
273
- for (const row of docResult.Results) {
274
- const labels = labelsByRecordID.get(row.RecordID.toLowerCase());
275
- if (!labels) continue; // filtered out, not readable by this user, or the record no longer exists
276
+ for (const { row, labels } of chosen) {
277
+ const vectorJSON = valuesByID.get(row.ID);
278
+ if (!vectorJSON) continue; // removed or cleared since the listing
276
279
  results.push({
277
280
  ID: row.ID,
278
- Values: JSON.parse(row.VectorJSON) as number[],
281
+ Values: JSON.parse(vectorJSON) as number[],
279
282
  Metadata: JSON.stringify({ Entity: entityDoc.Entity, RecordID: row.RecordID, ...labels }),
280
283
  });
281
- if (results.length >= limit) break;
282
284
  }
283
285
  return results;
284
286
  }
285
287
 
288
+ /** The first `limit` stored vectors whose record was loaded, in listing order. */
289
+ private selectLabelledVectors(
290
+ vectors: StoredVectorRow[],
291
+ labelsByRecordID: Map<string, Record<string, string>>,
292
+ limit: number
293
+ ): LabelledVector[] {
294
+ const chosen: LabelledVector[] = [];
295
+ for (const row of vectors) {
296
+ if (chosen.length >= limit) break;
297
+ const labels = labelsByRecordID.get(row.RecordID.toLowerCase());
298
+ if (!labels) continue; // filtered out, not readable by this user, or the record no longer exists
299
+ chosen.push({ row, labels });
300
+ }
301
+ return chosen;
302
+ }
303
+
286
304
  /**
287
- * Map each record that passes `filter` to its name-field values, keyed by the same compact
288
- * record-ID form the vector sync writes to `MJ: Entity Record Documents.RecordID` (lower-cased).
305
+ * Fetch `VectorJSON` for the given Entity Record Document IDs, keyed by ID. The ID lists are
306
+ * capped at {@link VECTOR_FETCH_CHUNK_SIZE} per view and all sent in one `RunViews` batch.
289
307
  */
290
- private async loadRecordLabels(
291
- entityInfo: EntityInfo,
292
- filter: string | undefined,
293
- contextUser: UserInfo
294
- ): Promise<Map<string, Record<string, string>>> {
308
+ private async loadVectorValues(ids: string[], contextUser: UserInfo): Promise<Map<string, string>> {
309
+ const valuesByID = new Map<string, string>();
310
+ if (ids.length === 0) return valuesByID;
311
+
312
+ const views: RunViewParams[] = [];
313
+ for (let i = 0; i < ids.length; i += VECTOR_FETCH_CHUNK_SIZE) {
314
+ const idList = ids.slice(i, i + VECTOR_FETCH_CHUNK_SIZE).map(id => `'${EscapeSQLString(id)}'`).join(',');
315
+ views.push({
316
+ EntityName: 'MJ: Entity Record Documents',
317
+ ExtraFilter: `ID IN (${idList})`,
318
+ Fields: ['ID', 'VectorJSON'],
319
+ IgnoreMaxRows: true,
320
+ BypassCache: true, // one-off ID lists: a cache slot per call would only hold memory
321
+ ResultType: 'simple',
322
+ });
323
+ }
324
+ const results = await new RunView().RunViews<{ ID: string; VectorJSON: string | null }>(views, contextUser);
325
+ for (const result of results) {
326
+ if (!result.Success) {
327
+ throw new Error(`Failed to load vector values: ${result.ErrorMessage}`);
328
+ }
329
+ for (const row of result.Results) {
330
+ if (row.VectorJSON) valuesByID.set(row.ID, row.VectorJSON);
331
+ }
332
+ }
333
+ return valuesByID;
334
+ }
335
+
336
+ /** The fields a stored vector is labelled with: the entity's name fields, else its NameField. */
337
+ private labelFieldNames(entityInfo: EntityInfo): string[] {
295
338
  const nameFields = entityInfo.Fields.filter(f => f.IsNameField).map(f => f.Name);
296
339
  if (nameFields.length === 0 && entityInfo.NameField) {
297
340
  nameFields.push(entityInfo.NameField.Name);
298
341
  }
299
- const keyFields = entityInfo.PrimaryKeys.map(pk => pk.Name);
342
+ return nameFields;
343
+ }
300
344
 
301
- const rv = new RunView();
302
- const result = await rv.RunView<Record<string, unknown>>({
303
- EntityName: entityInfo.Name,
304
- ExtraFilter: filter || undefined,
305
- Fields: [...new Set([...keyFields, ...nameFields])],
306
- IgnoreMaxRows: true,
307
- ResultType: 'simple',
308
- }, contextUser);
309
- if (!result.Success) {
310
- throw new Error(`Failed to load "${entityInfo.Name}" records: ${result.ErrorMessage}`);
345
+ /**
346
+ * Load the records that pass `filter` (key and name fields only) and the list of the document's
347
+ * stored vectors (ID and RecordID, no VectorJSON). The two views don't depend on each other, so
348
+ * they go in one `RunViews` round trip.
349
+ */
350
+ private async loadRecordsAndStoredVectors(
351
+ entityInfo: EntityInfo,
352
+ entityDoc: MJEntityDocumentEntity,
353
+ nameFields: string[],
354
+ filter: string | undefined,
355
+ contextUser: UserInfo
356
+ ): Promise<{ records: Record<string, unknown>[]; vectors: StoredVectorRow[] }> {
357
+ const keyFields = entityInfo.PrimaryKeys.map(pk => pk.Name);
358
+ const [recordResult, docResult] = await new RunView().RunViews<Record<string, unknown>>([
359
+ {
360
+ EntityName: entityInfo.Name,
361
+ ExtraFilter: filter || undefined,
362
+ Fields: [...new Set([...keyFields, ...nameFields])],
363
+ IgnoreMaxRows: true,
364
+ ResultType: 'simple',
365
+ },
366
+ {
367
+ EntityName: 'MJ: Entity Record Documents',
368
+ ExtraFilter: `EntityDocumentID='${EscapeSQLString(entityDoc.ID)}' AND VectorJSON IS NOT NULL`,
369
+ Fields: ['ID', 'RecordID'],
370
+ IgnoreMaxRows: true,
371
+ // A cached RunView fetches every column so its slot can serve any field set, which
372
+ // would pull each vector's VectorJSON here. Bypass the cache so Fields is honoured.
373
+ BypassCache: true,
374
+ ResultType: 'simple',
375
+ },
376
+ ], contextUser);
377
+ if (!recordResult.Success) {
378
+ throw new Error(`Failed to load "${entityInfo.Name}" records: ${recordResult.ErrorMessage}`);
379
+ }
380
+ if (!docResult.Success) {
381
+ throw new Error(`Failed to load stored vectors: ${docResult.ErrorMessage}`);
311
382
  }
383
+ return { records: recordResult.Results, vectors: docResult.Results as StoredVectorRow[] };
384
+ }
312
385
 
386
+ /**
387
+ * Map each loaded record to its name-field values, keyed by the same compact record-ID form
388
+ * the vector sync writes to `MJ: Entity Record Documents.RecordID` (lower-cased).
389
+ */
390
+ private mapRecordLabels(
391
+ entityInfo: EntityInfo,
392
+ nameFields: string[],
393
+ rows: Record<string, unknown>[]
394
+ ): Map<string, Record<string, string>> {
313
395
  const map = new Map<string, Record<string, string>>();
314
- for (const row of result.Results) {
396
+ for (const row of rows) {
315
397
  const key = CompositeKey.FromEntityRecord(entityInfo, row).ToCompactURLSegment().toLowerCase();
316
398
  const labels: Record<string, string> = {};
317
399
  for (const name of nameFields) {