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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/generated/graphql-schemas/__mj.d.ts +1010 -0
  3. package/dist/generated/graphql-schemas/__mj.d.ts.map +1 -1
  4. package/dist/generated/graphql-schemas/__mj.js +5178 -3
  5. package/dist/generated/graphql-schemas/__mj.js.map +1 -1
  6. package/dist/generic/FireAndForgetHeartbeat.d.ts +15 -1
  7. package/dist/generic/FireAndForgetHeartbeat.d.ts.map +1 -1
  8. package/dist/generic/FireAndForgetHeartbeat.js +16 -2
  9. package/dist/generic/FireAndForgetHeartbeat.js.map +1 -1
  10. package/dist/generic/OrphanedConversationDetailReconciler.d.ts +31 -0
  11. package/dist/generic/OrphanedConversationDetailReconciler.d.ts.map +1 -0
  12. package/dist/generic/OrphanedConversationDetailReconciler.js +215 -0
  13. package/dist/generic/OrphanedConversationDetailReconciler.js.map +1 -0
  14. package/dist/generic/PushStatusResolver.d.ts +38 -0
  15. package/dist/generic/PushStatusResolver.d.ts.map +1 -1
  16. package/dist/generic/PushStatusResolver.js +84 -1
  17. package/dist/generic/PushStatusResolver.js.map +1 -1
  18. package/dist/generic/ResolverBase.d.ts +13 -1
  19. package/dist/generic/ResolverBase.d.ts.map +1 -1
  20. package/dist/generic/ResolverBase.js +49 -47
  21. package/dist/generic/ResolverBase.js.map +1 -1
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +90 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/resolvers/AgentRunStatusPublisher.d.ts +55 -0
  27. package/dist/resolvers/AgentRunStatusPublisher.d.ts.map +1 -0
  28. package/dist/resolvers/AgentRunStatusPublisher.js +141 -0
  29. package/dist/resolvers/AgentRunStatusPublisher.js.map +1 -0
  30. package/dist/resolvers/ConversationRunEventsResolver.d.ts +90 -0
  31. package/dist/resolvers/ConversationRunEventsResolver.d.ts.map +1 -0
  32. package/dist/resolvers/ConversationRunEventsResolver.js +283 -0
  33. package/dist/resolvers/ConversationRunEventsResolver.js.map +1 -0
  34. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts +98 -0
  35. package/dist/resolvers/DuplicateEntryCheckResolver.d.ts.map +1 -0
  36. package/dist/resolvers/DuplicateEntryCheckResolver.js +227 -0
  37. package/dist/resolvers/DuplicateEntryCheckResolver.js.map +1 -0
  38. package/dist/resolvers/FetchEntityVectorsResolver.d.ts.map +1 -1
  39. package/dist/resolvers/FetchEntityVectorsResolver.js +2 -1
  40. package/dist/resolvers/FetchEntityVectorsResolver.js.map +1 -1
  41. package/dist/resolvers/MergeRecordsResolver.d.ts +7 -0
  42. package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
  43. package/dist/resolvers/MergeRecordsResolver.js +16 -2
  44. package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
  45. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +44 -6
  46. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  47. package/dist/resolvers/RealtimeClientSessionResolver.js +90 -34
  48. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  49. package/dist/resolvers/RunAIAgentResolver.d.ts +0 -16
  50. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  51. package/dist/resolvers/RunAIAgentResolver.js +23 -153
  52. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  53. package/dist/resolvers/RunDecisionResolver.d.ts +149 -0
  54. package/dist/resolvers/RunDecisionResolver.d.ts.map +1 -0
  55. package/dist/resolvers/RunDecisionResolver.js +396 -0
  56. package/dist/resolvers/RunDecisionResolver.js.map +1 -0
  57. package/dist/resolvers/VectorizeEntityResolver.d.ts +1 -1
  58. package/dist/resolvers/VectorizeEntityResolver.d.ts.map +1 -1
  59. package/dist/resolvers/VectorizeEntityResolver.js +14 -10
  60. package/dist/resolvers/VectorizeEntityResolver.js.map +1 -1
  61. package/package.json +94 -92
  62. package/src/__tests__/AgentRunStatusPublisher.test.ts +175 -0
  63. package/src/__tests__/DuplicateEntryCheckResolver.test.ts +300 -0
  64. package/src/__tests__/RealtimeClientSessionResolver.test.ts +216 -2
  65. package/src/__tests__/RemoteBrowserActionRecovery.test.ts +7 -1
  66. package/src/__tests__/RemoteBrowserAudioStream.test.ts +7 -1
  67. package/src/__tests__/RemoteBrowserSnapshot.test.ts +7 -1
  68. package/src/__tests__/ResolverBase.clientOldValues.test.ts +52 -0
  69. package/src/__tests__/RunAIAgentResolver.historyFrom.test.ts +182 -12
  70. package/src/__tests__/RunAIAgentResolver.streaming.test.ts +18 -27
  71. package/src/__tests__/RunDecisionResolver.test.ts +699 -0
  72. package/src/__tests__/TaskGraphActionRunner.durablePayload.test.ts +2 -0
  73. package/src/__tests__/VectorizeEntityResolver.test.ts +106 -0
  74. package/src/__tests__/conversationRunEvents.test.ts +399 -0
  75. package/src/__tests__/orphanedConversationDetailReconciler.test.ts +283 -0
  76. package/src/__tests__/pushStatusFanOut.test.ts +206 -0
  77. package/src/auth/__tests__/backward-compatibility.test.ts +1 -0
  78. package/src/generated/graphql-schemas/__mj.ts +3637 -4
  79. package/src/generic/FireAndForgetHeartbeat.ts +16 -2
  80. package/src/generic/OrphanedConversationDetailReconciler.ts +267 -0
  81. package/src/generic/PushStatusResolver.ts +97 -1
  82. package/src/generic/ResolverBase.ts +49 -49
  83. package/src/index.ts +102 -2
  84. package/src/resolvers/AgentRunStatusPublisher.ts +175 -0
  85. package/src/resolvers/ConversationRunEventsResolver.ts +308 -0
  86. package/src/resolvers/DuplicateEntryCheckResolver.ts +232 -0
  87. package/src/resolvers/FetchEntityVectorsResolver.ts +2 -1
  88. package/src/resolvers/MergeRecordsResolver.ts +14 -2
  89. package/src/resolvers/RealtimeClientSessionResolver.ts +93 -35
  90. package/src/resolvers/RunAIAgentResolver.ts +28 -174
  91. package/src/resolvers/RunDecisionResolver.ts +435 -0
  92. package/src/resolvers/VectorizeEntityResolver.ts +16 -11
  93. package/src/resolvers/__tests__/MergeRecordsResolver.test.ts +93 -0
@@ -0,0 +1,283 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Arg, Ctx, Field, Int, ObjectType, Query, Resolver } from 'type-graphql';
14
+ import { RunView } from '@memberjunction/core';
15
+ import { EscapeSQLString } from '@memberjunction/global';
16
+ import { GetReadOnlyProvider } from '../util.js';
17
+ const RUN_FIELDS = ['ID', 'Status', 'Result'];
18
+ const STEP_FIELDS = [
19
+ 'StepNumber', 'StepType', 'StepName', 'Status', 'Success', 'ErrorMessage', 'StartedAt', 'CompletedAt',
20
+ ];
21
+ /**
22
+ * One step of an agent run, projected for the client's progress view.
23
+ *
24
+ * Carries metadata only. `InputData`, `OutputData` and the payload snapshots are
25
+ * deliberately excluded: they are the largest columns on the row and a run can hold
26
+ * hundreds of steps, so including them would let a single tail call return tens of
27
+ * megabytes. The final result is delivered once, via `FinalPayload`, when the run
28
+ * reaches a terminal state.
29
+ */
30
+ let ConversationRunEvent = class ConversationRunEvent {
31
+ };
32
+ __decorate([
33
+ Field(() => Int),
34
+ __metadata("design:type", Number)
35
+ ], ConversationRunEvent.prototype, "Seq", void 0);
36
+ __decorate([
37
+ Field(() => String),
38
+ __metadata("design:type", String)
39
+ ], ConversationRunEvent.prototype, "StepType", void 0);
40
+ __decorate([
41
+ Field(() => String),
42
+ __metadata("design:type", String)
43
+ ], ConversationRunEvent.prototype, "StepName", void 0);
44
+ __decorate([
45
+ Field(() => String),
46
+ __metadata("design:type", String)
47
+ ], ConversationRunEvent.prototype, "Status", void 0);
48
+ __decorate([
49
+ Field(() => Boolean, { nullable: true }),
50
+ __metadata("design:type", Boolean)
51
+ ], ConversationRunEvent.prototype, "Success", void 0);
52
+ __decorate([
53
+ Field(() => String, { nullable: true }),
54
+ __metadata("design:type", String)
55
+ ], ConversationRunEvent.prototype, "ErrorMessage", void 0);
56
+ __decorate([
57
+ Field(() => Date),
58
+ __metadata("design:type", Date)
59
+ ], ConversationRunEvent.prototype, "StartedAt", void 0);
60
+ __decorate([
61
+ Field(() => Date, { nullable: true }),
62
+ __metadata("design:type", Date)
63
+ ], ConversationRunEvent.prototype, "CompletedAt", void 0);
64
+ ConversationRunEvent = __decorate([
65
+ ObjectType()
66
+ ], ConversationRunEvent);
67
+ export { ConversationRunEvent };
68
+ /** Result of a tail call. */
69
+ let ConversationRunEventsOutput = class ConversationRunEventsOutput {
70
+ };
71
+ __decorate([
72
+ Field(() => Boolean),
73
+ __metadata("design:type", Boolean)
74
+ ], ConversationRunEventsOutput.prototype, "Success", void 0);
75
+ __decorate([
76
+ Field(() => String),
77
+ __metadata("design:type", String)
78
+ ], ConversationRunEventsOutput.prototype, "Message", void 0);
79
+ __decorate([
80
+ Field(() => [ConversationRunEvent]),
81
+ __metadata("design:type", Array)
82
+ ], ConversationRunEventsOutput.prototype, "Events", void 0);
83
+ __decorate([
84
+ Field(() => Int),
85
+ __metadata("design:type", Number)
86
+ ], ConversationRunEventsOutput.prototype, "LatestSeq", void 0);
87
+ __decorate([
88
+ Field(() => Boolean),
89
+ __metadata("design:type", Boolean)
90
+ ], ConversationRunEventsOutput.prototype, "IsInFlight", void 0);
91
+ __decorate([
92
+ Field(() => String, { nullable: true }),
93
+ __metadata("design:type", String)
94
+ ], ConversationRunEventsOutput.prototype, "RunID", void 0);
95
+ __decorate([
96
+ Field(() => String, { nullable: true }),
97
+ __metadata("design:type", String)
98
+ ], ConversationRunEventsOutput.prototype, "RunStatus", void 0);
99
+ __decorate([
100
+ Field(() => String, { nullable: true }),
101
+ __metadata("design:type", String)
102
+ ], ConversationRunEventsOutput.prototype, "FinalPayload", void 0);
103
+ __decorate([
104
+ Field(() => String, { nullable: true }),
105
+ __metadata("design:type", String)
106
+ ], ConversationRunEventsOutput.prototype, "DetailStatus", void 0);
107
+ ConversationRunEventsOutput = __decorate([
108
+ ObjectType()
109
+ ], ConversationRunEventsOutput);
110
+ export { ConversationRunEventsOutput };
111
+ /**
112
+ * Every read here sets `BypassCache`. This is the last-resort recovery path, and the rows it
113
+ * judges are written by callers that fire no cache invalidation — `spSweepStaleAIAgentRuns`
114
+ * force-fails a run with a direct set-based UPDATE. `TrustServerCacheCompletely` defaults on, so
115
+ * a cached read would keep reporting a swept run as `Running` and recovery would never fire.
116
+ */
117
+ /** Ceiling on events returned per call. A client with a gap larger than this pages. */
118
+ const MAX_EVENTS_PER_TAIL = 200;
119
+ /**
120
+ * Run statuses that mean execution is still in progress. `Paused` is a run parked on a workflow
121
+ * that is still executing; the orphan reconciler and the process panel treat it the same way.
122
+ */
123
+ const IN_FLIGHT_STATUSES = ['Running', 'Paused'];
124
+ /**
125
+ * Durable, resumable read of an agent run's progress (MJ #4222).
126
+ *
127
+ * The `statusUpdates` subscription is the only live path a conversation has, and it has no
128
+ * replay: the server topic is an in-memory PubSub and the client subject is explicitly
129
+ * unbuffered. Anything published while a socket is half-open is gone, and the client cannot
130
+ * tell the difference between "nothing happened" and "I missed everything".
131
+ *
132
+ * This query is the durable counterpart, mirroring `IntegrationTailRunEvents` — the same
133
+ * shape the integration subsystem already uses, where the subscription is a latency
134
+ * optimization over a log rather than the only delivery path. A client keeps the `LatestSeq`
135
+ * it has seen and re-reads from there after any interruption.
136
+ *
137
+ * It is a READ MODEL over tables that already exist. `AIAgentRunStep` rows are inserted when
138
+ * a step starts and updated when it finishes, so progress is visible mid-run, and
139
+ * `StepNumber` is already monotonic per run. No new table and no migration.
140
+ *
141
+ * Authorization is delegated to `RunView` executed as the calling user, so MJ's existing
142
+ * row-level security decides what is visible. A caller who cannot read the conversation
143
+ * detail gets the same answer as one asking about a detail that does not exist.
144
+ */
145
+ let ConversationRunEventsResolver = class ConversationRunEventsResolver {
146
+ async TailConversationEvents(conversationDetailID, ctx, sinceSeq) {
147
+ const from = Math.max(0, sinceSeq ?? 0);
148
+ const empty = (message) => ({
149
+ Success: false,
150
+ Message: message,
151
+ Events: [],
152
+ LatestSeq: from,
153
+ IsInFlight: true,
154
+ });
155
+ try {
156
+ const user = ctx.userPayload?.userRecord;
157
+ if (!user) {
158
+ return empty('User is not authenticated');
159
+ }
160
+ const provider = GetReadOnlyProvider(ctx.providers, { allowFallbackToReadWrite: true });
161
+ const detail = await this.loadDetail(provider, conversationDetailID, user);
162
+ if (!detail) {
163
+ // Not found and not authorized are deliberately indistinguishable — answering
164
+ // "exists but denied" would confirm the id to someone probing for one.
165
+ return empty(`Conversation detail '${conversationDetailID}' not found`);
166
+ }
167
+ const run = await this.loadLatestRun(provider, conversationDetailID, user);
168
+ if (!run) {
169
+ // The mutation is acknowledged before the run row exists, so this is an
170
+ // ordinary early-poll result, not an error. Reported as success with nothing
171
+ // to show so a client does not treat a race as a failure.
172
+ return {
173
+ Success: true,
174
+ Message: 'No agent run yet for this conversation detail',
175
+ Events: [],
176
+ LatestSeq: from,
177
+ IsInFlight: false,
178
+ DetailStatus: detail.Status ?? undefined,
179
+ };
180
+ }
181
+ const isInFlight = IN_FLIGHT_STATUSES.includes(run.Status);
182
+ const steps = await this.loadSteps(provider, run.ID, from, user);
183
+ const events = steps.map((s) => this.toEvent(s));
184
+ return {
185
+ Success: true,
186
+ Message: `${events.length} event(s)`,
187
+ Events: events,
188
+ // Never rewind: a quiet run returns the cursor the caller already held.
189
+ LatestSeq: events.length > 0 ? events[events.length - 1].Seq : from,
190
+ IsInFlight: isInFlight,
191
+ RunID: run.ID,
192
+ RunStatus: run.Status,
193
+ // Only meaningful once terminal; sending it mid-run would hand the client a
194
+ // partial payload it could mistake for the final answer.
195
+ //
196
+ // `AIAgentRun.Result` is agent-dependent — it is null on a large share of
197
+ // genuinely successful runs — so the conversation detail's own message is the
198
+ // fallback. That is the text the chat renders, so it is the answer a caller
199
+ // waiting on this field actually wants.
200
+ FinalPayload: isInFlight ? undefined : (run.Result ?? detail.Message ?? undefined),
201
+ DetailStatus: detail.Status ?? undefined,
202
+ };
203
+ }
204
+ catch (e) {
205
+ const message = e instanceof Error ? e.message : String(e);
206
+ return empty(`TailConversationEvents failed: ${message}`);
207
+ }
208
+ }
209
+ /** Loads the conversation detail as the calling user; null when absent or not permitted. */
210
+ async loadDetail(provider, conversationDetailID, user) {
211
+ const rv = RunView.FromMetadataProvider(provider);
212
+ const result = await rv.RunView({
213
+ EntityName: 'MJ: Conversation Details',
214
+ ExtraFilter: `ID='${this.escape(conversationDetailID)}'`,
215
+ MaxRows: 1,
216
+ ResultType: 'entity_object',
217
+ BypassCache: true,
218
+ }, user);
219
+ return result.Success ? result.Results?.[0] : undefined;
220
+ }
221
+ /**
222
+ * Newest run for the detail. A conversation detail can be retried, and the latest run is
223
+ * the one the UI is showing.
224
+ */
225
+ async loadLatestRun(provider, conversationDetailID, user) {
226
+ const rv = RunView.FromMetadataProvider(provider);
227
+ const result = await rv.RunView({
228
+ EntityName: 'MJ: AI Agent Runs',
229
+ ExtraFilter: `ConversationDetailID='${this.escape(conversationDetailID)}'`,
230
+ OrderBy: '__mj_CreatedAt DESC',
231
+ MaxRows: 1,
232
+ Fields: RUN_FIELDS,
233
+ ResultType: 'simple',
234
+ BypassCache: true,
235
+ }, user);
236
+ return result.Success ? result.Results?.[0] : undefined;
237
+ }
238
+ /** Steps after `sinceSeq`, oldest first, bounded by {@link MAX_EVENTS_PER_TAIL}. */
239
+ async loadSteps(provider, agentRunID, sinceSeq, user) {
240
+ const rv = RunView.FromMetadataProvider(provider);
241
+ const result = await rv.RunView({
242
+ EntityName: 'MJ: AI Agent Run Steps',
243
+ ExtraFilter: `AgentRunID='${this.escape(agentRunID)}' AND StepNumber > ${Math.floor(sinceSeq)}`,
244
+ OrderBy: 'StepNumber ASC',
245
+ MaxRows: MAX_EVENTS_PER_TAIL,
246
+ Fields: STEP_FIELDS,
247
+ ResultType: 'simple',
248
+ BypassCache: true,
249
+ }, user);
250
+ return result.Success ? (result.Results ?? []) : [];
251
+ }
252
+ /** Projects a plain step row to an event. Plain rows may carry dates as strings. */
253
+ toEvent(step) {
254
+ return {
255
+ Seq: step.StepNumber,
256
+ StepType: step.StepType,
257
+ StepName: step.StepName,
258
+ Status: step.Status,
259
+ Success: step.Success ?? undefined,
260
+ ErrorMessage: step.ErrorMessage ?? undefined,
261
+ StartedAt: new Date(step.StartedAt),
262
+ CompletedAt: step.CompletedAt != null ? new Date(step.CompletedAt) : undefined,
263
+ };
264
+ }
265
+ /** Escapes a value for the `ExtraFilter` string. Ids are UUIDs, but never trust the shape. */
266
+ escape(value) {
267
+ return EscapeSQLString(value);
268
+ }
269
+ };
270
+ __decorate([
271
+ Query(() => ConversationRunEventsOutput),
272
+ __param(0, Arg('conversationDetailID', () => String)),
273
+ __param(1, Ctx()),
274
+ __param(2, Arg('sinceSeq', () => Int, { defaultValue: 0 })),
275
+ __metadata("design:type", Function),
276
+ __metadata("design:paramtypes", [String, Object, Number]),
277
+ __metadata("design:returntype", Promise)
278
+ ], ConversationRunEventsResolver.prototype, "TailConversationEvents", null);
279
+ ConversationRunEventsResolver = __decorate([
280
+ Resolver()
281
+ ], ConversationRunEventsResolver);
282
+ export { ConversationRunEventsResolver };
283
+ //# sourceMappingURL=ConversationRunEventsResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationRunEventsResolver.js","sourceRoot":"","sources":["../../src/resolvers/ConversationRunEventsResolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { AppContext, UserPayload } from '../types.js';
2
+ import { IMetadataProvider } from '@memberjunction/core';
3
+ import { DuplicateRecordDetector } from '@memberjunction/ai-vector-dupe';
4
+ import type { DuplicateEntryCheckStatus } from '@memberjunction/ai-vector-dupe';
5
+ import { ResolverBase } from '../generic/ResolverBase.js';
6
+ /**
7
+ * The most characters `valuesJSON` may hold. A larger request is refused before it is parsed. The
8
+ * form sends each field's text cut to 500 characters, so a real entry stays well under it; the
9
+ * detector then cuts what reaches the template and the decision model on its own.
10
+ */
11
+ export declare const DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH: number;
12
+ /**
13
+ * How a `CheckDuplicateEntry` call ended: a detector status, or `NotAuthorized` when the caller may
14
+ * not run the check (an API key without the scopes, or a user who cannot read the entity). Nothing
15
+ * ran, and a form stops asking about the entity for the session, as it does on `NotConfigured`.
16
+ */
17
+ export type DuplicateEntryCheckOutputStatus = DuplicateEntryCheckStatus | 'NotAuthorized';
18
+ /** One existing record the entry-time check flags as a possible duplicate. */
19
+ export declare class DuplicateEntryCandidateOutput {
20
+ /** The candidate's primary key as a compact URL segment; `CompositeKey.FromURLSegment` reads it back. */
21
+ RecordID: string;
22
+ /** The candidate's name, or its key when the caller may not read a name. */
23
+ DisplayName: string;
24
+ /** The vector similarity score that surfaced the candidate. */
25
+ VectorScore: number;
26
+ /** The decision's probability that the candidate is the same entity; null when it gave no answer. */
27
+ Probability: number | null;
28
+ }
29
+ /**
30
+ * The result of the `CheckDuplicateEntry` mutation. The mutation never throws to the client: an
31
+ * authorization denial is `Status: 'NotAuthorized'` and any other failure is `Status: 'Failed'`,
32
+ * each with an `ErrorMessage`.
33
+ */
34
+ export declare class DuplicateEntryCheckOutput {
35
+ /** `Checked`, `NotConfigured`, `NotAuthorized` or `Failed`. */
36
+ Status: DuplicateEntryCheckOutputStatus;
37
+ ErrorMessage?: string;
38
+ /** The flagged candidates, most probable first. Empty unless `Status` is `Checked`. */
39
+ Candidates: DuplicateEntryCandidateOutput[];
40
+ /** How long the check took on the server, in milliseconds. */
41
+ ElapsedMs: number;
42
+ }
43
+ /** What the resolver needs from the detector. `DuplicateRecordDetector` provides it. */
44
+ export type DuplicateEntryChecker = Pick<DuplicateRecordDetector, 'CheckRecordValues'>;
45
+ /**
46
+ * Checks the values a person is entering for a new record against the entity's existing records,
47
+ * through `DuplicateRecordDetector.CheckRecordValues`, and returns the plausible duplicates to flag.
48
+ * It only flags: it saves, merges and blocks nothing.
49
+ */
50
+ export declare class DuplicateEntryCheckResolver extends ResolverBase {
51
+ /**
52
+ * Flags existing records that may duplicate a new record being entered.
53
+ *
54
+ * Authorization comes before any other work. An API key needs two scopes: `view:run` on the
55
+ * entity, the scope `RunDynamicView` checks, since the check reads the entity's records; and
56
+ * `prompt:execute`, the scope `ExecuteSimplePrompt` checks, since each check pays for an embedding
57
+ * and a decision-model call. A session without an API key skips both. Then the user needs read
58
+ * permission on the entity. A denial is `NotAuthorized`, and is not logged. The detector then
59
+ * narrows the candidates to the rows the user can read.
60
+ *
61
+ * The detector bounds the check's time on the server (`DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS` in
62
+ * `@memberjunction/ai-vector-dupe`), a little above the form's own budget.
63
+ *
64
+ * @param entityName The entity the new record belongs to.
65
+ * @param valuesJSON The entered values as the JSON of an object, by field name, at most
66
+ * {@link DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH} characters. Each value is a string,
67
+ * number, boolean or null. Fields the entity does not have, primary keys, read-only fields and
68
+ * MJ system fields are ignored.
69
+ */
70
+ CheckDuplicateEntry(entityName: string, valuesJSON: string, { userPayload, providers }: AppContext): Promise<DuplicateEntryCheckOutput>;
71
+ /**
72
+ * The check without the GraphQL plumbing: authorizes, reads the values, and runs the detector.
73
+ * Never throws.
74
+ *
75
+ * @param provider the request's metadata provider; the global one when null
76
+ */
77
+ RunEntryCheck(entityName: string, valuesJSON: string, userPayload: UserPayload, provider: IMetadataProvider | null): Promise<DuplicateEntryCheckOutput>;
78
+ /** The detector a check runs on, bound to the request's provider. */
79
+ protected CreateEntryChecker(provider: IMetadataProvider | null): DuplicateEntryChecker;
80
+ /**
81
+ * Why the caller may not run the check, or null when they may: the API-key scopes, then the
82
+ * user's read permission on the entity. A denial is an answer, not a fault, so nothing is logged.
83
+ */
84
+ private authorizeEntryCheck;
85
+ /**
86
+ * Reads the entered values: the JSON of an object of scalar values, at most
87
+ * {@link DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH} characters, kept to the fields a person
88
+ * can enter (matched by name, case-insensitively, and keyed by the field's real name).
89
+ */
90
+ private parseValues;
91
+ /** Whether a person can enter the field: not a primary key, not read-only, not an MJ system field. */
92
+ private isEnterable;
93
+ private isEntryValue;
94
+ private isPlainObject;
95
+ private mapResult;
96
+ private failure;
97
+ }
98
+ //# sourceMappingURL=DuplicateEntryCheckResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuplicateEntryCheckResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/DuplicateEntryCheckResolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAA+B,iBAAiB,EAAsB,MAAM,sBAAsB,CAAC;AAC1G,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,KAAK,EAA6B,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D;;;;GAIG;AACH,eAAO,MAAM,4CAA4C,QAAY,CAAC;AAEtE;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,yBAAyB,GAAG,eAAe,CAAC;AAK1F,8EAA8E;AAC9E,qBACa,6BAA6B;IACtC,yGAAyG;IAEzG,QAAQ,EAAE,MAAM,CAAC;IAEjB,4EAA4E;IAE5E,WAAW,EAAE,MAAM,CAAC;IAEpB,+DAA+D;IAE/D,WAAW,EAAE,MAAM,CAAC;IAEpB,qGAAqG;IAErG,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;GAIG;AACH,qBACa,yBAAyB;IAClC,+DAA+D;IAE/D,MAAM,EAAE,+BAA+B,CAAC;IAGxC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,uFAAuF;IAEvF,UAAU,EAAE,6BAA6B,EAAE,CAAC;IAE5C,8DAA8D;IAE9D,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,wFAAwF;AACxF,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,uBAAuB,EAAE,mBAAmB,CAAC,CAAC;AAEvF;;;;GAIG;AACH,qBACa,2BAA4B,SAAQ,YAAY;IACzD;;;;;;;;;;;;;;;;;;OAkBG;IAEG,mBAAmB,CACF,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAC9B,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,UAAU,GAC9C,OAAO,CAAC,yBAAyB,CAAC;IAKrC;;;;;OAKG;IACU,aAAa,CACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GACnC,OAAO,CAAC,yBAAyB,CAAC;IA4BrC,qEAAqE;IACrE,SAAS,CAAC,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,qBAAqB;IAIvF;;;OAGG;YACW,mBAAmB;IAejC;;;;OAIG;IACH,OAAO,CAAC,WAAW;IA0BnB,sGAAsG;IACtG,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,SAAS;IAcjB,OAAO,CAAC,OAAO;CAGlB"}
@@ -0,0 +1,227 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Resolver, Mutation, Arg, Ctx, ObjectType, Field, Float, Int } from 'type-graphql';
14
+ import { LogError, Metadata } from '@memberjunction/core';
15
+ import { DuplicateRecordDetector } from '@memberjunction/ai-vector-dupe';
16
+ import { ResolverBase } from '../generic/ResolverBase.js';
17
+ import { GetReadOnlyProvider } from '../util.js';
18
+ /**
19
+ * The most characters `valuesJSON` may hold. A larger request is refused before it is parsed. The
20
+ * form sends each field's text cut to 500 characters, so a real entry stays well under it; the
21
+ * detector then cuts what reaches the template and the decision model on its own.
22
+ */
23
+ export const DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH = 16 * 1024;
24
+ /** One existing record the entry-time check flags as a possible duplicate. */
25
+ let DuplicateEntryCandidateOutput = class DuplicateEntryCandidateOutput {
26
+ };
27
+ __decorate([
28
+ Field(),
29
+ __metadata("design:type", String)
30
+ ], DuplicateEntryCandidateOutput.prototype, "RecordID", void 0);
31
+ __decorate([
32
+ Field(),
33
+ __metadata("design:type", String)
34
+ ], DuplicateEntryCandidateOutput.prototype, "DisplayName", void 0);
35
+ __decorate([
36
+ Field(() => Float),
37
+ __metadata("design:type", Number)
38
+ ], DuplicateEntryCandidateOutput.prototype, "VectorScore", void 0);
39
+ __decorate([
40
+ Field(() => Float, { nullable: true }),
41
+ __metadata("design:type", Number)
42
+ ], DuplicateEntryCandidateOutput.prototype, "Probability", void 0);
43
+ DuplicateEntryCandidateOutput = __decorate([
44
+ ObjectType()
45
+ ], DuplicateEntryCandidateOutput);
46
+ export { DuplicateEntryCandidateOutput };
47
+ /**
48
+ * The result of the `CheckDuplicateEntry` mutation. The mutation never throws to the client: an
49
+ * authorization denial is `Status: 'NotAuthorized'` and any other failure is `Status: 'Failed'`,
50
+ * each with an `ErrorMessage`.
51
+ */
52
+ let DuplicateEntryCheckOutput = class DuplicateEntryCheckOutput {
53
+ };
54
+ __decorate([
55
+ Field(() => String),
56
+ __metadata("design:type", String)
57
+ ], DuplicateEntryCheckOutput.prototype, "Status", void 0);
58
+ __decorate([
59
+ Field({ nullable: true }),
60
+ __metadata("design:type", String)
61
+ ], DuplicateEntryCheckOutput.prototype, "ErrorMessage", void 0);
62
+ __decorate([
63
+ Field(() => [DuplicateEntryCandidateOutput]),
64
+ __metadata("design:type", Array)
65
+ ], DuplicateEntryCheckOutput.prototype, "Candidates", void 0);
66
+ __decorate([
67
+ Field(() => Int),
68
+ __metadata("design:type", Number)
69
+ ], DuplicateEntryCheckOutput.prototype, "ElapsedMs", void 0);
70
+ DuplicateEntryCheckOutput = __decorate([
71
+ ObjectType()
72
+ ], DuplicateEntryCheckOutput);
73
+ export { DuplicateEntryCheckOutput };
74
+ /**
75
+ * Checks the values a person is entering for a new record against the entity's existing records,
76
+ * through `DuplicateRecordDetector.CheckRecordValues`, and returns the plausible duplicates to flag.
77
+ * It only flags: it saves, merges and blocks nothing.
78
+ */
79
+ let DuplicateEntryCheckResolver = class DuplicateEntryCheckResolver extends ResolverBase {
80
+ /**
81
+ * Flags existing records that may duplicate a new record being entered.
82
+ *
83
+ * Authorization comes before any other work. An API key needs two scopes: `view:run` on the
84
+ * entity, the scope `RunDynamicView` checks, since the check reads the entity's records; and
85
+ * `prompt:execute`, the scope `ExecuteSimplePrompt` checks, since each check pays for an embedding
86
+ * and a decision-model call. A session without an API key skips both. Then the user needs read
87
+ * permission on the entity. A denial is `NotAuthorized`, and is not logged. The detector then
88
+ * narrows the candidates to the rows the user can read.
89
+ *
90
+ * The detector bounds the check's time on the server (`DUPLICATE_ENTRY_CHECK_SERVER_BUDGET_MS` in
91
+ * `@memberjunction/ai-vector-dupe`), a little above the form's own budget.
92
+ *
93
+ * @param entityName The entity the new record belongs to.
94
+ * @param valuesJSON The entered values as the JSON of an object, by field name, at most
95
+ * {@link DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH} characters. Each value is a string,
96
+ * number, boolean or null. Fields the entity does not have, primary keys, read-only fields and
97
+ * MJ system fields are ignored.
98
+ */
99
+ async CheckDuplicateEntry(entityName, valuesJSON, { userPayload, providers }) {
100
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
101
+ return this.RunEntryCheck(entityName, valuesJSON, userPayload, provider);
102
+ }
103
+ /**
104
+ * The check without the GraphQL plumbing: authorizes, reads the values, and runs the detector.
105
+ * Never throws.
106
+ *
107
+ * @param provider the request's metadata provider; the global one when null
108
+ */
109
+ async RunEntryCheck(entityName, valuesJSON, userPayload, provider) {
110
+ const startTime = Date.now();
111
+ const entity = (provider ?? new Metadata()).EntityByName(entityName);
112
+ if (!entity) {
113
+ return this.failure('Failed', 'Entity not found in metadata', startTime);
114
+ }
115
+ const denial = await this.authorizeEntryCheck(entity, userPayload, provider);
116
+ if (denial) {
117
+ return this.failure('NotAuthorized', denial, startTime);
118
+ }
119
+ try {
120
+ const user = this.GetUserFromPayload(userPayload);
121
+ if (!user) {
122
+ return this.failure('Failed', 'Unable to determine current user', startTime);
123
+ }
124
+ const values = this.parseValues(valuesJSON, entity);
125
+ if ('Error' in values) {
126
+ return this.failure('Failed', values.Error, startTime);
127
+ }
128
+ const result = await this.CreateEntryChecker(provider).CheckRecordValues(entity.Name, values.Values, user);
129
+ return this.mapResult(result);
130
+ }
131
+ catch (error) {
132
+ const message = error instanceof Error ? error.message : String(error);
133
+ LogError(`CheckDuplicateEntry failed for ${entityName}: ${message}`);
134
+ return this.failure('Failed', message || 'Unknown error occurred', startTime);
135
+ }
136
+ }
137
+ /** The detector a check runs on, bound to the request's provider. */
138
+ CreateEntryChecker(provider) {
139
+ return new DuplicateRecordDetector(provider);
140
+ }
141
+ /**
142
+ * Why the caller may not run the check, or null when they may: the API-key scopes, then the
143
+ * user's read permission on the entity. A denial is an answer, not a fault, so nothing is logged.
144
+ */
145
+ async authorizeEntryCheck(entity, userPayload, provider) {
146
+ try {
147
+ await this.CheckAPIKeyScopeAuthorization('view:run', entity.Name, userPayload);
148
+ await this.CheckAPIKeyScopeAuthorization('prompt:execute', '*', userPayload);
149
+ this.CheckUserReadPermissions(entity.Name, userPayload, provider ?? undefined);
150
+ return null;
151
+ }
152
+ catch (error) {
153
+ return error instanceof Error ? error.message : String(error);
154
+ }
155
+ }
156
+ /**
157
+ * Reads the entered values: the JSON of an object of scalar values, at most
158
+ * {@link DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH} characters, kept to the fields a person
159
+ * can enter (matched by name, case-insensitively, and keyed by the field's real name).
160
+ */
161
+ parseValues(valuesJSON, entity) {
162
+ if (valuesJSON.length > DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH) {
163
+ return { Error: `valuesJSON is ${valuesJSON.length} characters; the limit is ${DUPLICATE_ENTRY_CHECK_MAX_VALUES_JSON_LENGTH}` };
164
+ }
165
+ let parsed;
166
+ try {
167
+ parsed = JSON.parse(valuesJSON);
168
+ }
169
+ catch (e) {
170
+ return { Error: `valuesJSON is not valid JSON: ${e instanceof Error ? e.message : String(e)}` };
171
+ }
172
+ if (!this.isPlainObject(parsed)) {
173
+ return { Error: 'valuesJSON must be the JSON of an object of field values' };
174
+ }
175
+ const values = {};
176
+ for (const [name, value] of Object.entries(parsed)) {
177
+ if (!this.isEntryValue(value)) {
178
+ return { Error: `valuesJSON field '${name}' must be a string, number, boolean or null` };
179
+ }
180
+ const field = entity.FieldByName(name);
181
+ if (field && this.isEnterable(field)) {
182
+ values[field.Name] = value;
183
+ }
184
+ }
185
+ return { Values: values };
186
+ }
187
+ /** Whether a person can enter the field: not a primary key, not read-only, not an MJ system field. */
188
+ isEnterable(field) {
189
+ return !field.IsPrimaryKey && !field.ReadOnly && !field.Name.startsWith('__mj_');
190
+ }
191
+ isEntryValue(value) {
192
+ return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
193
+ }
194
+ isPlainObject(value) {
195
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
196
+ }
197
+ mapResult(result) {
198
+ return {
199
+ Status: result.Status,
200
+ ErrorMessage: result.ErrorMessage,
201
+ Candidates: result.Candidates.map(c => ({
202
+ RecordID: c.RecordID,
203
+ DisplayName: c.DisplayName,
204
+ VectorScore: c.VectorScore,
205
+ Probability: c.Probability,
206
+ })),
207
+ ElapsedMs: result.ElapsedMs,
208
+ };
209
+ }
210
+ failure(status, errorMessage, startTime) {
211
+ return { Status: status, ErrorMessage: errorMessage, Candidates: [], ElapsedMs: Date.now() - startTime };
212
+ }
213
+ };
214
+ __decorate([
215
+ Mutation(() => DuplicateEntryCheckOutput),
216
+ __param(0, Arg('entityName')),
217
+ __param(1, Arg('valuesJSON')),
218
+ __param(2, Ctx()),
219
+ __metadata("design:type", Function),
220
+ __metadata("design:paramtypes", [String, String, Object]),
221
+ __metadata("design:returntype", Promise)
222
+ ], DuplicateEntryCheckResolver.prototype, "CheckDuplicateEntry", null);
223
+ DuplicateEntryCheckResolver = __decorate([
224
+ Resolver()
225
+ ], DuplicateEntryCheckResolver);
226
+ export { DuplicateEntryCheckResolver };
227
+ //# sourceMappingURL=DuplicateEntryCheckResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuplicateEntryCheckResolver.js","sourceRoot":"","sources":["../../src/resolvers/DuplicateEntryCheckResolver.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FetchEntityVectorsResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/FetchEntityVectorsResolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAO1D,qBACa,gBAAgB;IAEzB,EAAE,EAAE,MAAM,CAAC;IAGX,MAAM,EAAE,MAAM,EAAE,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBACa,wBAAwB;IAEjC,OAAO,EAAE,OAAO,CAAC;IAGjB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAG5B,UAAU,EAAE,MAAM,CAAC;IAGnB,SAAS,EAAE,MAAM,CAAC;IAGlB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAID,qBACa,0BAA2B,SAAQ,YAAY;IAGlD,kBAAkB,CACK,gBAAgB,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC7C,MAAM,EAAE,MAAM,GAAG,SAAS,EACtD,EAAE,WAAW,EAAE,GAAE,UAA6B,GACtD,OAAO,CAAC,wBAAwB,CAAC;IAsFpC,gCAAgC;YAClB,kBAAkB;IAiBhC;;;;OAIG;YACW,kBAAkB;IAsChC,sEAAsE;YACxD,sBAAsB;IA4BpC,OAAO,CAAC,WAAW;CAStB"}
1
+ {"version":3,"file":"FetchEntityVectorsResolver.d.ts","sourceRoot":"","sources":["../../src/resolvers/FetchEntityVectorsResolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAQ1D,qBACa,gBAAgB;IAEzB,EAAE,EAAE,MAAM,CAAC;IAGX,MAAM,EAAE,MAAM,EAAE,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBACa,wBAAwB;IAEjC,OAAO,EAAE,OAAO,CAAC;IAGjB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAG5B,UAAU,EAAE,MAAM,CAAC;IAGnB,SAAS,EAAE,MAAM,CAAC;IAGlB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAID,qBACa,0BAA2B,SAAQ,YAAY;IAGlD,kBAAkB,CACK,gBAAgB,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC7C,MAAM,EAAE,MAAM,GAAG,SAAS,EACtD,EAAE,WAAW,EAAE,GAAE,UAA6B,GACtD,OAAO,CAAC,wBAAwB,CAAC;IAsFpC,gCAAgC;YAClB,kBAAkB;IAiBhC;;;;OAIG;YACW,kBAAkB;IAsChC,sEAAsE;YACxD,sBAAsB;IA4BpC,OAAO,CAAC,WAAW;CAStB"}