@memberjunction/core-entities-server 6.2.0-edge.6 → 6.2.0-edge.8
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.
- package/README.md +155 -100
- package/dist/custom/AnchoredConversationReadSecurityHook.d.ts +22 -0
- package/dist/custom/AnchoredConversationReadSecurityHook.d.ts.map +1 -0
- package/dist/custom/AnchoredConversationReadSecurityHook.js +293 -0
- package/dist/custom/AnchoredConversationReadSecurityHook.js.map +1 -0
- package/dist/custom/MJAIAgentExampleEntityServer.server.d.ts +2 -0
- package/dist/custom/MJAIAgentExampleEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJAIAgentExampleEntityServer.server.js +8 -5
- package/dist/custom/MJAIAgentExampleEntityServer.server.js.map +1 -1
- package/dist/custom/MJAIAgentNoteEntityServer.server.d.ts +2 -0
- package/dist/custom/MJAIAgentNoteEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJAIAgentNoteEntityServer.server.js +8 -5
- package/dist/custom/MJAIAgentNoteEntityServer.server.js.map +1 -1
- package/dist/custom/MJAIAgentRelationshipEntityServer.server.d.ts +17 -0
- package/dist/custom/MJAIAgentRelationshipEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJAIAgentRelationshipEntityServer.server.js +71 -0
- package/dist/custom/MJAIAgentRelationshipEntityServer.server.js.map +1 -0
- package/dist/custom/MJAIAgentSessionEntityServer.server.d.ts +8 -22
- package/dist/custom/MJAIAgentSessionEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJAIAgentSessionEntityServer.server.js +24 -1
- package/dist/custom/MJAIAgentSessionEntityServer.server.js.map +1 -1
- package/dist/custom/MJAIAgentUserPolicyEntityServer.server.d.ts +23 -0
- package/dist/custom/MJAIAgentUserPolicyEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJAIAgentUserPolicyEntityServer.server.js +53 -0
- package/dist/custom/MJAIAgentUserPolicyEntityServer.server.js.map +1 -0
- package/dist/custom/MJAIPromptEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJAIPromptEntityServer.server.js +2 -1
- package/dist/custom/MJAIPromptEntityServer.server.js.map +1 -1
- package/dist/custom/MJBrandKitEntityServer.server.d.ts +14 -0
- package/dist/custom/MJBrandKitEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJBrandKitEntityServer.server.js +75 -0
- package/dist/custom/MJBrandKitEntityServer.server.js.map +1 -0
- package/dist/custom/MJCompanyIntegrationEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJCompanyIntegrationEntityServer.server.js +1 -0
- package/dist/custom/MJCompanyIntegrationEntityServer.server.js.map +1 -1
- package/dist/custom/MJComponentEntityServer.server.d.ts +2 -0
- package/dist/custom/MJComponentEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJComponentEntityServer.server.js +5 -1
- package/dist/custom/MJComponentEntityServer.server.js.map +1 -1
- package/dist/custom/MJConversationDetailEntityServer.server.d.ts +20 -30
- package/dist/custom/MJConversationDetailEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJConversationDetailEntityServer.server.js +89 -35
- package/dist/custom/MJConversationDetailEntityServer.server.js.map +1 -1
- package/dist/custom/MJConversationEntityServer.server.d.ts +19 -4
- package/dist/custom/MJConversationEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJConversationEntityServer.server.js +169 -11
- package/dist/custom/MJConversationEntityServer.server.js.map +1 -1
- package/dist/custom/MJEntityDocumentEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJEntityDocumentEntityServer.server.js +1 -0
- package/dist/custom/MJEntityDocumentEntityServer.server.js.map +1 -1
- package/dist/custom/MJListDetailEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJListDetailEntityServer.server.js +1 -0
- package/dist/custom/MJListDetailEntityServer.server.js.map +1 -1
- package/dist/custom/MJProjectEntityServer.server.d.ts +21 -0
- package/dist/custom/MJProjectEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJProjectEntityServer.server.js +106 -0
- package/dist/custom/MJProjectEntityServer.server.js.map +1 -0
- package/dist/custom/MJQueryEntityServer.server.d.ts +177 -47
- package/dist/custom/MJQueryEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJQueryEntityServer.server.js +479 -164
- package/dist/custom/MJQueryEntityServer.server.js.map +1 -1
- package/dist/custom/MJQuerySQLEntityServer.server.d.ts +15 -18
- package/dist/custom/MJQuerySQLEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJQuerySQLEntityServer.server.js +34 -42
- package/dist/custom/MJQuerySQLEntityServer.server.js.map +1 -1
- package/dist/custom/MJTagEntityServer.server.d.ts +2 -0
- package/dist/custom/MJTagEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJTagEntityServer.server.js +13 -7
- package/dist/custom/MJTagEntityServer.server.js.map +1 -1
- package/dist/custom/MJUserRoutineEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJUserRoutineEntityServer.server.js +8 -1
- package/dist/custom/MJUserRoutineEntityServer.server.js.map +1 -1
- package/dist/custom/RestrictedFieldCommentClassifier.d.ts +73 -0
- package/dist/custom/RestrictedFieldCommentClassifier.d.ts.map +1 -0
- package/dist/custom/RestrictedFieldCommentClassifier.js +240 -0
- package/dist/custom/RestrictedFieldCommentClassifier.js.map +1 -0
- package/dist/custom/query-extraction/childRowWriter.d.ts +77 -0
- package/dist/custom/query-extraction/childRowWriter.d.ts.map +1 -0
- package/dist/custom/query-extraction/childRowWriter.js +277 -0
- package/dist/custom/query-extraction/childRowWriter.js.map +1 -0
- package/dist/custom/query-extraction/compositionTargets.d.ts +40 -0
- package/dist/custom/query-extraction/compositionTargets.d.ts.map +1 -0
- package/dist/custom/query-extraction/compositionTargets.js +99 -0
- package/dist/custom/query-extraction/compositionTargets.js.map +1 -0
- package/dist/custom/query-extraction/declared.d.ts +79 -0
- package/dist/custom/query-extraction/declared.d.ts.map +1 -0
- package/dist/custom/query-extraction/declared.js +91 -0
- package/dist/custom/query-extraction/declared.js.map +1 -0
- package/dist/custom/query-extraction/describeFacts.d.ts +40 -0
- package/dist/custom/query-extraction/describeFacts.d.ts.map +1 -0
- package/dist/custom/query-extraction/describeFacts.js +225 -0
- package/dist/custom/query-extraction/describeFacts.js.map +1 -0
- package/dist/custom/query-extraction/descriptionPass.d.ts +23 -0
- package/dist/custom/query-extraction/descriptionPass.d.ts.map +1 -0
- package/dist/custom/query-extraction/descriptionPass.js +95 -0
- package/dist/custom/query-extraction/descriptionPass.js.map +1 -0
- package/dist/custom/query-extraction/extractQuery.d.ts +25 -0
- package/dist/custom/query-extraction/extractQuery.d.ts.map +1 -0
- package/dist/custom/query-extraction/extractQuery.js +146 -0
- package/dist/custom/query-extraction/extractQuery.js.map +1 -0
- package/dist/custom/query-extraction/extractionTypes.d.ts +133 -0
- package/dist/custom/query-extraction/extractionTypes.d.ts.map +1 -0
- package/dist/custom/query-extraction/extractionTypes.js +2 -0
- package/dist/custom/query-extraction/extractionTypes.js.map +1 -0
- package/dist/custom/query-extraction/index.d.ts +16 -0
- package/dist/custom/query-extraction/index.d.ts.map +1 -1
- package/dist/custom/query-extraction/index.js +11 -1
- package/dist/custom/query-extraction/index.js.map +1 -1
- package/dist/custom/query-extraction/pipeline.d.ts +6 -2
- package/dist/custom/query-extraction/pipeline.d.ts.map +1 -1
- package/dist/custom/query-extraction/pipeline.js +21 -14
- package/dist/custom/query-extraction/pipeline.js.map +1 -1
- package/dist/custom/query-extraction/resolve.d.ts +7 -2
- package/dist/custom/query-extraction/resolve.d.ts.map +1 -1
- package/dist/custom/query-extraction/resolve.js +17 -14
- package/dist/custom/query-extraction/resolve.js.map +1 -1
- package/dist/custom/query-extraction/sourceBinding.d.ts +57 -0
- package/dist/custom/query-extraction/sourceBinding.d.ts.map +1 -0
- package/dist/custom/query-extraction/sourceBinding.js +104 -0
- package/dist/custom/query-extraction/sourceBinding.js.map +1 -0
- package/dist/custom/query-extraction/sync.d.ts +27 -3
- package/dist/custom/query-extraction/sync.d.ts.map +1 -1
- package/dist/custom/query-extraction/sync.js +69 -44
- package/dist/custom/query-extraction/sync.js.map +1 -1
- package/dist/custom/query-extraction/templateFacts.d.ts +62 -0
- package/dist/custom/query-extraction/templateFacts.d.ts.map +1 -0
- package/dist/custom/query-extraction/templateFacts.js +229 -0
- package/dist/custom/query-extraction/templateFacts.js.map +1 -0
- package/dist/custom/query-extraction/types.d.ts +4 -0
- package/dist/custom/query-extraction/types.d.ts.map +1 -1
- package/dist/custom/query-refresh/QueryExtractionService.d.ts +54 -0
- package/dist/custom/query-refresh/QueryExtractionService.d.ts.map +1 -0
- package/dist/custom/query-refresh/QueryExtractionService.js +207 -0
- package/dist/custom/query-refresh/QueryExtractionService.js.map +1 -0
- package/dist/custom/query-refresh/QueryRefreshExtractionServerOperation.d.ts +28 -0
- package/dist/custom/query-refresh/QueryRefreshExtractionServerOperation.d.ts.map +1 -0
- package/dist/custom/query-refresh/QueryRefreshExtractionServerOperation.js +106 -0
- package/dist/custom/query-refresh/QueryRefreshExtractionServerOperation.js.map +1 -0
- package/dist/custom/query-refresh/index.d.ts +14 -0
- package/dist/custom/query-refresh/index.d.ts.map +1 -0
- package/dist/custom/query-refresh/index.js +10 -0
- package/dist/custom/query-refresh/index.js.map +1 -0
- package/dist/custom/query-refresh/queryRebind.d.ts +33 -0
- package/dist/custom/query-refresh/queryRebind.d.ts.map +1 -0
- package/dist/custom/query-refresh/queryRebind.js +85 -0
- package/dist/custom/query-refresh/queryRebind.js.map +1 -0
- package/dist/custom/query-refresh/refreshAuthorization.d.ts +29 -0
- package/dist/custom/query-refresh/refreshAuthorization.d.ts.map +1 -0
- package/dist/custom/query-refresh/refreshAuthorization.js +66 -0
- package/dist/custom/query-refresh/refreshAuthorization.js.map +1 -0
- package/dist/custom/query-refresh/refreshFormat.d.ts +16 -0
- package/dist/custom/query-refresh/refreshFormat.d.ts.map +1 -0
- package/dist/custom/query-refresh/refreshFormat.js +67 -0
- package/dist/custom/query-refresh/refreshFormat.js.map +1 -0
- package/dist/custom/query-refresh/refreshOrder.d.ts +25 -0
- package/dist/custom/query-refresh/refreshOrder.d.ts.map +1 -0
- package/dist/custom/query-refresh/refreshOrder.js +95 -0
- package/dist/custom/query-refresh/refreshOrder.js.map +1 -0
- package/dist/custom/query-refresh/refreshSelection.d.ts +15 -0
- package/dist/custom/query-refresh/refreshSelection.d.ts.map +1 -0
- package/dist/custom/query-refresh/refreshSelection.js +99 -0
- package/dist/custom/query-refresh/refreshSelection.js.map +1 -0
- package/dist/custom/query-refresh/refreshTypes.d.ts +81 -0
- package/dist/custom/query-refresh/refreshTypes.d.ts.map +1 -0
- package/dist/custom/query-refresh/refreshTypes.js +5 -0
- package/dist/custom/query-refresh/refreshTypes.js.map +1 -0
- package/dist/custom/util.d.ts +8 -0
- package/dist/custom/util.d.ts.map +1 -1
- package/dist/custom/util.js +18 -1
- package/dist/custom/util.js.map +1 -1
- package/dist/engines/QueryEngineServer.d.ts +8 -5
- package/dist/engines/QueryEngineServer.d.ts.map +1 -1
- package/dist/engines/QueryEngineServer.js +16 -23
- package/dist/engines/QueryEngineServer.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +30 -30
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { BaseEntity, GetDataHooks, LogError, Metadata, RegisterDataHook, RunView, WellKnownUserSource } from '@memberjunction/core';
|
|
2
|
+
import { EscapeSQLString, NormalizeUUID } from '@memberjunction/global';
|
|
3
|
+
import { FilterAnchoredConversationsForUser } from '@memberjunction/core-entities';
|
|
4
|
+
const INTERNAL_SECURITY_QUERY_PARAMS = new WeakSet();
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the entity name targeted by `params` without additional I/O.
|
|
7
|
+
*/
|
|
8
|
+
function resolveTargetEntityName(params) {
|
|
9
|
+
if (typeof params.EntityName === 'string' && params.EntityName.trim().length > 0) {
|
|
10
|
+
return params.EntityName.trim();
|
|
11
|
+
}
|
|
12
|
+
const viewEntityName = params.ViewEntity?.Get('Entity');
|
|
13
|
+
if (typeof viewEntityName === 'string' && viewEntityName.trim().length > 0) {
|
|
14
|
+
return viewEntityName.trim();
|
|
15
|
+
}
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
function resolveProviderForUser(contextUser) {
|
|
19
|
+
return (contextUser.OwningProvider ??
|
|
20
|
+
Metadata.Provider ?? // global-provider-ok: fallback when UserInfo was constructed without an OwningProvider
|
|
21
|
+
null);
|
|
22
|
+
}
|
|
23
|
+
function readRowField(row, fieldName) {
|
|
24
|
+
if (!row || typeof row !== 'object') {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
if (row instanceof BaseEntity) {
|
|
28
|
+
return row.Get(fieldName);
|
|
29
|
+
}
|
|
30
|
+
return row[fieldName];
|
|
31
|
+
}
|
|
32
|
+
function hasOwnOrEntityField(row, fieldName) {
|
|
33
|
+
if (!row || typeof row !== 'object') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (row instanceof BaseEntity) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return Object.prototype.hasOwnProperty.call(row, fieldName);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Server-side `PostRunView` data hook enforcing Row-Level Security (RLS) and Field-Level Security (FLS)
|
|
43
|
+
* on anchored conversations (`MJ: Conversations` where `AnchorType IS NOT NULL`) and their comment
|
|
44
|
+
* messages (`MJ: Conversation Details`).
|
|
45
|
+
*
|
|
46
|
+
* Guarantees that even a raw `RunView` call over GraphQL, REST, or server code cannot return:
|
|
47
|
+
* - Anchored conversation threads (`MJ: Conversations`) attached to a linked record that `contextUser`
|
|
48
|
+
* cannot read (entity permissions + RLS), or anchored/stamped with restricted fields (`AnchorKey` /
|
|
49
|
+
* `AnchorMetadata.restrictedFields`) that `contextUser` is denied Read access to (FLS).
|
|
50
|
+
* - Comment messages (`MJ: Conversation Details`) belonging to any such anchored conversation thread.
|
|
51
|
+
*
|
|
52
|
+
* Never mutates `results.Results` in place (safe with frozen cache entries); returns a replacement
|
|
53
|
+
* `RunViewResult` whenever rows are filtered out.
|
|
54
|
+
*/
|
|
55
|
+
export const AnchoredConversationPostRunViewHook = async (params, results, contextUser) => {
|
|
56
|
+
if (!results?.Success ||
|
|
57
|
+
!Array.isArray(results.Results) ||
|
|
58
|
+
results.Results.length === 0 ||
|
|
59
|
+
!contextUser ||
|
|
60
|
+
INTERNAL_SECURITY_QUERY_PARAMS.has(params)) {
|
|
61
|
+
return results;
|
|
62
|
+
}
|
|
63
|
+
const entityName = resolveTargetEntityName(params);
|
|
64
|
+
if (entityName !== 'MJ: Conversations' && entityName !== 'MJ: Conversation Details') {
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
const provider = resolveProviderForUser(contextUser);
|
|
68
|
+
if (!provider || provider.ProviderType !== 'Database') {
|
|
69
|
+
return results;
|
|
70
|
+
}
|
|
71
|
+
if (WellKnownUserSource.Instance.IsSystemUser(contextUser)) {
|
|
72
|
+
return results;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
if (entityName === 'MJ: Conversations') {
|
|
76
|
+
return await filterConversationsRunViewResult(provider, contextUser, results);
|
|
77
|
+
}
|
|
78
|
+
return await filterConversationDetailsRunViewResult(provider, contextUser, results);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
LogError(`AnchoredConversationPostRunViewHook failed on ${entityName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
async function filterConversationsRunViewResult(provider, contextUser, results) {
|
|
86
|
+
const rows = results.Results;
|
|
87
|
+
// Check if any row is missing security columns due to a narrow `Fields` projection
|
|
88
|
+
const missingMetadataIds = [];
|
|
89
|
+
for (const row of rows) {
|
|
90
|
+
const hasSecurityCols = hasOwnOrEntityField(row, 'AnchorType') &&
|
|
91
|
+
hasOwnOrEntityField(row, 'LinkedEntityID') &&
|
|
92
|
+
hasOwnOrEntityField(row, 'LinkedRecordID') &&
|
|
93
|
+
hasOwnOrEntityField(row, 'AnchorKey') &&
|
|
94
|
+
hasOwnOrEntityField(row, 'AnchorMetadata');
|
|
95
|
+
if (!hasSecurityCols) {
|
|
96
|
+
const id = String(readRowField(row, 'ID') ?? '').trim();
|
|
97
|
+
if (id) {
|
|
98
|
+
missingMetadataIds.push(id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const hydratedById = new Map();
|
|
103
|
+
if (missingMetadataIds.length > 0) {
|
|
104
|
+
const fetched = await fetchConversationsSecurityMetadataByIds(provider, contextUser, missingMetadataIds, false);
|
|
105
|
+
for (const item of fetched) {
|
|
106
|
+
if (item.ID) {
|
|
107
|
+
hydratedById.set(NormalizeUUID(item.ID), item);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Collect anchored candidates
|
|
112
|
+
const anchoredCandidates = [];
|
|
113
|
+
for (let i = 0; i < rows.length; i++) {
|
|
114
|
+
const row = rows[i];
|
|
115
|
+
const rowId = String(readRowField(row, 'ID') ?? '').trim();
|
|
116
|
+
const hydrated = rowId ? hydratedById.get(NormalizeUUID(rowId)) : undefined;
|
|
117
|
+
const anchorType = (hydrated ? hydrated.AnchorType : readRowField(row, 'AnchorType'));
|
|
118
|
+
const linkedEntityId = (hydrated ? hydrated.LinkedEntityID : readRowField(row, 'LinkedEntityID'));
|
|
119
|
+
const linkedRecordId = (hydrated ? hydrated.LinkedRecordID : readRowField(row, 'LinkedRecordID'));
|
|
120
|
+
if (!anchorType && (!linkedEntityId || !linkedRecordId)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
// Only filter anchored comment threads (or conversations linked to a record that carry an anchor)
|
|
124
|
+
if (!anchorType) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const anchorKey = (hydrated ? hydrated.AnchorKey : readRowField(row, 'AnchorKey'));
|
|
128
|
+
const anchorMetadata = (hydrated ? hydrated.AnchorMetadata : readRowField(row, 'AnchorMetadata'));
|
|
129
|
+
const anchorMetadataObject = (hydrated ? hydrated.AnchorMetadataObject : readRowField(row, 'AnchorMetadataObject'));
|
|
130
|
+
anchoredCandidates.push({
|
|
131
|
+
__rowIndex: i,
|
|
132
|
+
ID: rowId || undefined,
|
|
133
|
+
LinkedEntityID: linkedEntityId ?? null,
|
|
134
|
+
LinkedRecordID: linkedRecordId ?? null,
|
|
135
|
+
AnchorType: anchorType,
|
|
136
|
+
AnchorKey: anchorKey ?? null,
|
|
137
|
+
AnchorMetadata: anchorMetadata ?? null,
|
|
138
|
+
AnchorMetadataObject: anchorMetadataObject ?? null
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (anchoredCandidates.length === 0) {
|
|
142
|
+
return results;
|
|
143
|
+
}
|
|
144
|
+
const allowedAnchored = await FilterAnchoredConversationsForUser(provider, contextUser, anchoredCandidates);
|
|
145
|
+
if (allowedAnchored.length === anchoredCandidates.length) {
|
|
146
|
+
return results;
|
|
147
|
+
}
|
|
148
|
+
const allowedRowIndexes = new Set(allowedAnchored.map((c) => c.__rowIndex));
|
|
149
|
+
const anchoredRowIndexes = new Set(anchoredCandidates.map((c) => c.__rowIndex));
|
|
150
|
+
const filteredRows = rows.filter((_row, index) => !anchoredRowIndexes.has(index) || allowedRowIndexes.has(index));
|
|
151
|
+
const removedCount = rows.length - filteredRows.length;
|
|
152
|
+
return {
|
|
153
|
+
...results,
|
|
154
|
+
Results: filteredRows,
|
|
155
|
+
RowCount: filteredRows.length,
|
|
156
|
+
TotalRowCount: Math.max(filteredRows.length, (results.TotalRowCount ?? results.RowCount ?? rows.length) - removedCount)
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
async function filterConversationDetailsRunViewResult(provider, contextUser, results) {
|
|
160
|
+
const rows = results.Results;
|
|
161
|
+
const missingConvIdDetailIds = [];
|
|
162
|
+
for (const row of rows) {
|
|
163
|
+
if (!hasOwnOrEntityField(row, 'ConversationID')) {
|
|
164
|
+
const detailId = String(readRowField(row, 'ID') ?? '').trim();
|
|
165
|
+
if (detailId) {
|
|
166
|
+
missingConvIdDetailIds.push(detailId);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const convIdByDetailId = new Map();
|
|
171
|
+
if (missingConvIdDetailIds.length > 0) {
|
|
172
|
+
const fetchedDetails = await fetchDetailConversationIdsByIds(provider, contextUser, missingConvIdDetailIds);
|
|
173
|
+
for (const d of fetchedDetails) {
|
|
174
|
+
if (d.ID && d.ConversationID) {
|
|
175
|
+
convIdByDetailId.set(NormalizeUUID(d.ID), d.ConversationID);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const conversationIdsByNorm = new Map();
|
|
180
|
+
const rowConvNormByIndex = new Map();
|
|
181
|
+
for (let i = 0; i < rows.length; i++) {
|
|
182
|
+
const row = rows[i];
|
|
183
|
+
let convId = String(readRowField(row, 'ConversationID') ?? '').trim();
|
|
184
|
+
if (!convId) {
|
|
185
|
+
const detailId = String(readRowField(row, 'ID') ?? '').trim();
|
|
186
|
+
if (detailId) {
|
|
187
|
+
convId = convIdByDetailId.get(NormalizeUUID(detailId)) ?? '';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (convId) {
|
|
191
|
+
const norm = NormalizeUUID(convId);
|
|
192
|
+
conversationIdsByNorm.set(norm, convId);
|
|
193
|
+
rowConvNormByIndex.set(i, norm);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (conversationIdsByNorm.size === 0) {
|
|
197
|
+
return results;
|
|
198
|
+
}
|
|
199
|
+
// Fetch only parent conversations that are anchored (`AnchorType IS NOT NULL`)
|
|
200
|
+
const anchoredParents = await fetchConversationsSecurityMetadataByIds(provider, contextUser, [...conversationIdsByNorm.values()], true);
|
|
201
|
+
if (anchoredParents.length === 0) {
|
|
202
|
+
return results;
|
|
203
|
+
}
|
|
204
|
+
const allowedParents = await FilterAnchoredConversationsForUser(provider, contextUser, anchoredParents);
|
|
205
|
+
if (allowedParents.length === anchoredParents.length) {
|
|
206
|
+
return results;
|
|
207
|
+
}
|
|
208
|
+
const allowedNormIds = new Set(allowedParents.map((c) => NormalizeUUID(String(c.ID ?? ''))));
|
|
209
|
+
const deniedNormIds = new Set();
|
|
210
|
+
for (const parent of anchoredParents) {
|
|
211
|
+
const norm = NormalizeUUID(String(parent.ID ?? ''));
|
|
212
|
+
if (norm && !allowedNormIds.has(norm)) {
|
|
213
|
+
deniedNormIds.add(norm);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (deniedNormIds.size === 0) {
|
|
217
|
+
return results;
|
|
218
|
+
}
|
|
219
|
+
const filteredRows = rows.filter((_row, index) => {
|
|
220
|
+
const convNorm = rowConvNormByIndex.get(index);
|
|
221
|
+
return !convNorm || !deniedNormIds.has(convNorm);
|
|
222
|
+
});
|
|
223
|
+
const removedCount = rows.length - filteredRows.length;
|
|
224
|
+
return {
|
|
225
|
+
...results,
|
|
226
|
+
Results: filteredRows,
|
|
227
|
+
RowCount: filteredRows.length,
|
|
228
|
+
TotalRowCount: Math.max(filteredRows.length, (results.TotalRowCount ?? results.RowCount ?? rows.length) - removedCount)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async function fetchConversationsSecurityMetadataByIds(provider, contextUser, conversationIds, anchoredOnly) {
|
|
232
|
+
const uniqueEscaped = Array.from(new Set(conversationIds
|
|
233
|
+
.map((id) => id.trim())
|
|
234
|
+
.filter((id) => id.length > 0)
|
|
235
|
+
.map((id) => `'${EscapeSQLString(id)}'`)));
|
|
236
|
+
if (uniqueEscaped.length === 0) {
|
|
237
|
+
return [];
|
|
238
|
+
}
|
|
239
|
+
const systemUser = (await WellKnownUserSource.Instance.GetSystemUser(provider)) ?? contextUser;
|
|
240
|
+
const rv = RunView.FromMetadataProvider(provider);
|
|
241
|
+
const filterClauses = [`ID IN (${uniqueEscaped.join(',')})`];
|
|
242
|
+
if (anchoredOnly) {
|
|
243
|
+
filterClauses.push(`AnchorType IS NOT NULL`);
|
|
244
|
+
}
|
|
245
|
+
const params = {
|
|
246
|
+
EntityName: 'MJ: Conversations',
|
|
247
|
+
ExtraFilter: filterClauses.join(' AND '),
|
|
248
|
+
Fields: ['ID', 'LinkedEntityID', 'LinkedRecordID', 'AnchorType', 'AnchorKey', 'AnchorMetadata'],
|
|
249
|
+
ResultType: 'simple'
|
|
250
|
+
};
|
|
251
|
+
INTERNAL_SECURITY_QUERY_PARAMS.add(params);
|
|
252
|
+
const res = await rv.RunView(params, systemUser);
|
|
253
|
+
if (!res?.Success || !Array.isArray(res.Results)) {
|
|
254
|
+
return [];
|
|
255
|
+
}
|
|
256
|
+
return res.Results;
|
|
257
|
+
}
|
|
258
|
+
async function fetchDetailConversationIdsByIds(provider, contextUser, detailIds) {
|
|
259
|
+
const uniqueEscaped = Array.from(new Set(detailIds
|
|
260
|
+
.map((id) => id.trim())
|
|
261
|
+
.filter((id) => id.length > 0)
|
|
262
|
+
.map((id) => `'${EscapeSQLString(id)}'`)));
|
|
263
|
+
if (uniqueEscaped.length === 0) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
const systemUser = (await WellKnownUserSource.Instance.GetSystemUser(provider)) ?? contextUser;
|
|
267
|
+
const rv = RunView.FromMetadataProvider(provider);
|
|
268
|
+
const params = {
|
|
269
|
+
EntityName: 'MJ: Conversation Details',
|
|
270
|
+
ExtraFilter: `ID IN (${uniqueEscaped.join(',')})`,
|
|
271
|
+
Fields: ['ID', 'ConversationID'],
|
|
272
|
+
ResultType: 'simple'
|
|
273
|
+
};
|
|
274
|
+
INTERNAL_SECURITY_QUERY_PARAMS.add(params);
|
|
275
|
+
const res = await rv.RunView(params, systemUser);
|
|
276
|
+
if (!res?.Success || !Array.isArray(res.Results)) {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
return res.Results;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Ensures {@link AnchoredConversationPostRunViewHook} is registered in the global `PostRunView`
|
|
283
|
+
* data hooks store. Safe to call multiple times (idempotent).
|
|
284
|
+
*/
|
|
285
|
+
export function EnsureAnchoredConversationReadHookRegistered() {
|
|
286
|
+
const existing = GetDataHooks('PostRunView');
|
|
287
|
+
if (!existing.includes(AnchoredConversationPostRunViewHook)) {
|
|
288
|
+
RegisterDataHook('PostRunView', AnchoredConversationPostRunViewHook);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Auto-register when @memberjunction/core-entities-server is loaded
|
|
292
|
+
EnsureAnchoredConversationReadHookRegistered();
|
|
293
|
+
//# sourceMappingURL=AnchoredConversationReadSecurityHook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnchoredConversationReadSecurityHook.js","sourceRoot":"","sources":["../../src/custom/AnchoredConversationReadSecurityHook.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,8 @@ export declare class MJAIAgentExampleEntityServer extends MJAIAgentExampleEntity
|
|
|
13
13
|
* Override EmbedTextLocal to use helper
|
|
14
14
|
*/
|
|
15
15
|
protected EmbedTextLocal(textToEmbed: string): Promise<SimpleEmbeddingResult>;
|
|
16
|
+
/** A stored vector from a model other than the default local one is re-embedded on save. */
|
|
17
|
+
protected IsEmbeddingStale(embeddingModelID: string | null): Promise<boolean>;
|
|
16
18
|
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
17
19
|
Delete(options?: EntityDeleteOptions): Promise<boolean>;
|
|
18
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJAIAgentExampleEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentExampleEntityServer.server.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,mBAAmB,EAAE,iBAAiB,EAAY,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAIvE;;;;;;;GAOG;AACH,qBACa,4BAA6B,SAAQ,sBAAsB;IACpE;;OAEG;cACsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI7E,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MJAIAgentExampleEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentExampleEntityServer.server.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,mBAAmB,EAAE,iBAAiB,EAAY,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAIvE;;;;;;;GAOG;AACH,qBACa,4BAA6B,SAAQ,sBAAsB;IACpE;;OAEG;cACsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI5F,4FAA4F;cACnE,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7E,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAiCnD,MAAM,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CAQzE"}
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { RegisterClass } from "@memberjunction/global";
|
|
8
8
|
import { BaseEntity, LogError } from "@memberjunction/core";
|
|
9
9
|
import { MJAIAgentExampleEntity } from "@memberjunction/core-entities";
|
|
10
|
-
import { EmbedTextLocalHelper } from "./util.js";
|
|
10
|
+
import { EmbedTextLocalHelper, IsLocalEmbeddingStaleHelper } from "./util.js";
|
|
11
11
|
import { AIEngine } from "@memberjunction/aiengine";
|
|
12
12
|
/**
|
|
13
13
|
* Server-side extension of MJAIAgentExampleEntity that:
|
|
@@ -24,12 +24,15 @@ let MJAIAgentExampleEntityServer = class MJAIAgentExampleEntityServer extends MJ
|
|
|
24
24
|
async EmbedTextLocal(textToEmbed) {
|
|
25
25
|
return EmbedTextLocalHelper(this, textToEmbed);
|
|
26
26
|
}
|
|
27
|
+
/** A stored vector from a model other than the default local one is re-embedded on save. */
|
|
28
|
+
async IsEmbeddingStale(embeddingModelID) {
|
|
29
|
+
return IsLocalEmbeddingStaleHelper(this, embeddingModelID);
|
|
30
|
+
}
|
|
27
31
|
async Save(options) {
|
|
28
32
|
try {
|
|
29
|
-
// 1. Generate/refresh the embedding
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (shouldGenerateEmbedding && this.ExampleInput && this.ExampleInput.trim().length > 0) {
|
|
33
|
+
// 1. Generate/refresh the embedding. GenerateEmbedding skips it unless the ExampleInput is
|
|
34
|
+
// new or dirty, or its stored vector is from another model (IsEmbeddingStale).
|
|
35
|
+
if (this.ExampleInput && this.ExampleInput.trim().length > 0) {
|
|
33
36
|
await this.GenerateEmbeddingByFieldName("ExampleInput", "EmbeddingVector", "EmbeddingModelID", "EmbeddingVectorBinary");
|
|
34
37
|
}
|
|
35
38
|
else if (!this.ExampleInput || this.ExampleInput.trim().length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJAIAgentExampleEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIAgentExampleEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAA0C,QAAQ,EAAyB,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"MJAIAgentExampleEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIAgentExampleEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAA0C,QAAQ,EAAyB,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,QAAQ,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD;;;;;;;GAOG;AAEI,IAAM,4BAA4B,GAAlC,MAAM,4BAA6B,SAAQ,sBAAsB;IACpE;;OAEG;IACgB,KAAK,CAAC,cAAc,CAAC,WAAmB;QACvD,OAAO,oBAAoB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACnD,CAAC;IAED,4FAA4F;IACzE,KAAK,CAAC,gBAAgB,CAAC,gBAA+B;QACrE,OAAO,2BAA2B,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC/D,CAAC;IAEQ,KAAK,CAAC,IAAI,CAAC,OAA2B;QAC3C,IAAI,CAAC;YACD,2FAA2F;YAC3F,kFAAkF;YAClF,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3D,MAAM,IAAI,CAAC,4BAA4B,CAAC,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,uBAAuB,CAAC,CAAC;YAC5H,CAAC;iBAAM,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACrE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;gBAC5B,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;gBAClC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;YACjC,CAAC;YAED,mFAAmF;YACnF,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YAEzB,uEAAuE;YACvE,wEAAwE;YACxE,wEAAwE;YACxE,MAAM,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;gBACnF,QAAQ,CAAC,QAAQ,CAAC,iCAAiC,CAAC,IAAI,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACJ,QAAQ,CAAC,QAAQ,CAAC,4BAA4B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,QAAQ,CAAC,kCAAkC,EAAE,CAAC,CAAC,CAAC;YAChD,6DAA6D;YAC7D,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAEQ,KAAK,CAAC,MAAM,CAAC,OAA6B;QAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;YAChB,QAAQ,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;CACJ,CAAA;AAtDY,4BAA4B;IADxC,aAAa,CAAC,UAAU,EAAE,uBAAuB,CAAC;GACtC,4BAA4B,CAsDxC"}
|
|
@@ -17,6 +17,8 @@ export declare class MJAIAgentNoteEntityServer extends MJAIAgentNoteEntity {
|
|
|
17
17
|
* Override EmbedTextLocal to use helper
|
|
18
18
|
*/
|
|
19
19
|
protected EmbedTextLocal(textToEmbed: string): Promise<SimpleEmbeddingResult>;
|
|
20
|
+
/** A stored vector from a model other than the default local one is re-embedded on save. */
|
|
21
|
+
protected IsEmbeddingStale(embeddingModelID: string | null): Promise<boolean>;
|
|
20
22
|
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
21
23
|
Delete(options?: EntityDeleteOptions): Promise<boolean>;
|
|
22
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJAIAgentNoteEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentNoteEntityServer.server.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,mBAAmB,EAAE,iBAAiB,EAAY,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,mBAAmB,EAA0B,MAAM,+BAA+B,CAAC;AAI5F;;;;;;;;;;;GAWG;AACH,qBACa,yBAA0B,SAAQ,mBAAmB;IAC9D;;OAEG;cACsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI7E,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MJAIAgentNoteEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentNoteEntityServer.server.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,mBAAmB,EAAE,iBAAiB,EAAY,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,mBAAmB,EAA0B,MAAM,+BAA+B,CAAC;AAI5F;;;;;;;;;;;GAWG;AACH,qBACa,yBAA0B,SAAQ,mBAAmB;IAC9D;;OAEG;cACsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI5F,4FAA4F;cACnE,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7E,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAwCnD,MAAM,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;CAQzE"}
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
import { RegisterClass } from "@memberjunction/global";
|
|
8
8
|
import { BaseEntity, LogError } from "@memberjunction/core";
|
|
9
9
|
import { MJAIAgentNoteEntity, IsInjectableNoteStatus } from "@memberjunction/core-entities";
|
|
10
|
-
import { EmbedTextLocalHelper } from "./util.js";
|
|
10
|
+
import { EmbedTextLocalHelper, IsLocalEmbeddingStaleHelper } from "./util.js";
|
|
11
11
|
import { AIEngine } from "@memberjunction/aiengine";
|
|
12
12
|
/**
|
|
13
13
|
* Server-side extension of MJAIAgentNoteEntity that:
|
|
@@ -28,12 +28,15 @@ let MJAIAgentNoteEntityServer = class MJAIAgentNoteEntityServer extends MJAIAgen
|
|
|
28
28
|
async EmbedTextLocal(textToEmbed) {
|
|
29
29
|
return EmbedTextLocalHelper(this, textToEmbed);
|
|
30
30
|
}
|
|
31
|
+
/** A stored vector from a model other than the default local one is re-embedded on save. */
|
|
32
|
+
async IsEmbeddingStale(embeddingModelID) {
|
|
33
|
+
return IsLocalEmbeddingStaleHelper(this, embeddingModelID);
|
|
34
|
+
}
|
|
31
35
|
async Save(options) {
|
|
32
36
|
try {
|
|
33
|
-
// 1. Generate/refresh the embedding
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (shouldGenerateEmbedding && this.Note && this.Note.trim().length > 0) {
|
|
37
|
+
// 1. Generate/refresh the embedding. GenerateEmbedding skips it unless the Note is new or
|
|
38
|
+
// dirty, or its stored vector is from another model (IsEmbeddingStale).
|
|
39
|
+
if (this.Note && this.Note.trim().length > 0) {
|
|
37
40
|
await this.GenerateEmbeddingByFieldName("Note", "EmbeddingVector", "EmbeddingModelID", "EmbeddingVectorBinary");
|
|
38
41
|
}
|
|
39
42
|
else if (!this.Note || this.Note.trim().length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJAIAgentNoteEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIAgentNoteEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,UAAU,EAA0C,QAAQ,EAAyB,MAAM,sBAAsB,CAAC;AAC3H,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"MJAIAgentNoteEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIAgentNoteEntityServer.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ValidationErrorInfo, ValidationResult } from '@memberjunction/core';
|
|
2
|
+
import { MJAIAgentRelationshipEntity } from '@memberjunction/core-entities';
|
|
3
|
+
/**
|
|
4
|
+
* Server-side `MJ: AI Agent Relationships` entity enforcing that when `ConfigurationPresetID` is set,
|
|
5
|
+
* the referenced `MJ: AI Agent Configurations` preset exists and belongs to the relationship's `SubAgentID`.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MJAIAgentRelationshipEntityServer extends MJAIAgentRelationshipEntity {
|
|
8
|
+
get DefaultSkipAsyncValidation(): boolean;
|
|
9
|
+
ValidateAsync(): Promise<ValidationResult>;
|
|
10
|
+
private validateConfigurationPreset;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* PURE invariant core for `ConfigurationPresetID` on `MJ: AI Agent Relationships`:
|
|
14
|
+
* when set, the referenced preset must exist and its `AgentID` must match `SubAgentID`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function BuildConfigurationPresetOwnershipError(configurationPresetID: string | null, subAgentID: string | null, presetAgentID: string | null, presetName?: string): ValidationErrorInfo | null;
|
|
17
|
+
//# sourceMappingURL=MJAIAgentRelationshipEntityServer.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MJAIAgentRelationshipEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentRelationshipEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,mBAAmB,EAAuB,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEjI,OAAO,EAAgC,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAE1G;;;GAGG;AACH,qBACa,iCAAkC,SAAQ,2BAA2B;IAC9E,IAAoB,0BAA0B,IAAI,OAAO,CAExD;IAEqB,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC;YAuBlD,2BAA2B;CAoB5C;AAED;;;GAGG;AACH,wBAAgB,sCAAsC,CAClD,qBAAqB,EAAE,MAAM,GAAG,IAAI,EACpC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,UAAU,CAAC,EAAE,MAAM,GACpB,mBAAmB,GAAG,IAAI,CAsB5B"}
|
|
@@ -0,0 +1,71 @@
|
|
|
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
|
+
import { BaseEntity, ValidationErrorInfo, ValidationErrorType } from '@memberjunction/core';
|
|
8
|
+
import { RegisterClass, UUIDsEqual } from '@memberjunction/global';
|
|
9
|
+
import { MJAIAgentRelationshipEntity } from '@memberjunction/core-entities';
|
|
10
|
+
/**
|
|
11
|
+
* Server-side `MJ: AI Agent Relationships` entity enforcing that when `ConfigurationPresetID` is set,
|
|
12
|
+
* the referenced `MJ: AI Agent Configurations` preset exists and belongs to the relationship's `SubAgentID`.
|
|
13
|
+
*/
|
|
14
|
+
let MJAIAgentRelationshipEntityServer = class MJAIAgentRelationshipEntityServer extends MJAIAgentRelationshipEntity {
|
|
15
|
+
get DefaultSkipAsyncValidation() {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
async ValidateAsync() {
|
|
19
|
+
const result = await super.ValidateAsync();
|
|
20
|
+
if (!result.Success) {
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
if (!this.ConfigurationPresetID) {
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
const presetDirty = this.GetFieldByName('ConfigurationPresetID')?.Dirty ?? false;
|
|
27
|
+
const subAgentDirty = this.GetFieldByName('SubAgentID')?.Dirty ?? false;
|
|
28
|
+
if (!this.IsSaved || presetDirty || subAgentDirty) {
|
|
29
|
+
const presetError = await this.validateConfigurationPreset();
|
|
30
|
+
if (presetError) {
|
|
31
|
+
result.Errors.push(presetError);
|
|
32
|
+
result.Success = false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
async validateConfigurationPreset() {
|
|
38
|
+
if (!this.ConfigurationPresetID) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const md = this.ProviderToUse;
|
|
42
|
+
const preset = await md.GetEntityObject('MJ: AI Agent Configurations', this.ContextCurrentUser);
|
|
43
|
+
const loaded = await preset.Load(this.ConfigurationPresetID);
|
|
44
|
+
if (!loaded) {
|
|
45
|
+
return BuildConfigurationPresetOwnershipError(this.ConfigurationPresetID, this.SubAgentID, null);
|
|
46
|
+
}
|
|
47
|
+
return BuildConfigurationPresetOwnershipError(this.ConfigurationPresetID, this.SubAgentID, preset.AgentID ?? null, preset.Name ?? undefined);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
MJAIAgentRelationshipEntityServer = __decorate([
|
|
51
|
+
RegisterClass(BaseEntity, 'MJ: AI Agent Relationships')
|
|
52
|
+
], MJAIAgentRelationshipEntityServer);
|
|
53
|
+
export { MJAIAgentRelationshipEntityServer };
|
|
54
|
+
/**
|
|
55
|
+
* PURE invariant core for `ConfigurationPresetID` on `MJ: AI Agent Relationships`:
|
|
56
|
+
* when set, the referenced preset must exist and its `AgentID` must match `SubAgentID`.
|
|
57
|
+
*/
|
|
58
|
+
export function BuildConfigurationPresetOwnershipError(configurationPresetID, subAgentID, presetAgentID, presetName) {
|
|
59
|
+
if (!configurationPresetID) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (presetAgentID === null) {
|
|
63
|
+
return new ValidationErrorInfo('ConfigurationPresetID', `ConfigurationPresetID references preset '${configurationPresetID}' but no such AI Agent Configuration exists.`, configurationPresetID, ValidationErrorType.Failure);
|
|
64
|
+
}
|
|
65
|
+
if (!subAgentID || !UUIDsEqual(presetAgentID, subAgentID)) {
|
|
66
|
+
const label = presetName ? `'${presetName}' (${configurationPresetID})` : `'${configurationPresetID}'`;
|
|
67
|
+
return new ValidationErrorInfo('ConfigurationPresetID', `Configuration preset ${label} belongs to agent '${presetAgentID}', not sub-agent '${subAgentID}'.`, configurationPresetID, ValidationErrorType.Failure);
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=MJAIAgentRelationshipEntityServer.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MJAIAgentRelationshipEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJAIAgentRelationshipEntityServer.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +1,15 @@
|
|
|
1
1
|
import { ValidationResult } from '@memberjunction/core';
|
|
2
2
|
import { MJAIAgentSessionEntity } from '@memberjunction/core-entities';
|
|
3
|
-
/**
|
|
4
|
-
* Server-side `MJ: AI Agent Sessions` entity.
|
|
5
|
-
*
|
|
6
|
-
* It keeps the **server-authoritative keys** inside `Config` (the janitor's
|
|
7
|
-
* `maxSessionDeadlineIso`, the `identityVerification` state) out of the session owner's reach, and keeps an
|
|
8
|
-
* anonymous visitor from re-pointing an existing session's `ConversationID` (the anonymous ownership key —
|
|
9
|
-
* see `CheckAnonymousOwnershipKeyChange`). The
|
|
10
|
-
* owner can legitimately write the row — the `UI` and `Widget Guest` roles hold `CanUpdate` on their
|
|
11
|
-
* own sessions — so the protection has to live at the entity, where the generated CRUD mutations,
|
|
12
|
-
* `StartAgentSession(configJson)` and every other path converge on `Save`.
|
|
13
|
-
*
|
|
14
|
-
* The recording ledger's columns need no subclass: they are protected in metadata
|
|
15
|
-
* (`AllowUpdateAPI=false`, #6010), so an entity save cannot write them and only the ledger's stored
|
|
16
|
-
* procedures do.
|
|
17
|
-
*
|
|
18
|
-
* See {@link FindProtectedSessionConfigChanges} for what is protected and why, and
|
|
19
|
-
* `RunWithTrustedSessionConfigWrites` for how server code opts in.
|
|
20
|
-
*
|
|
21
|
-
* Uses the **synchronous** `Validate()` rather than `ValidateAsync()` on purpose: `Validate()` runs on
|
|
22
|
-
* every save, whereas async validation can be skipped by an option, and a guard that a caller can opt
|
|
23
|
-
* out of is not a guard.
|
|
24
|
-
*/
|
|
25
3
|
export declare class MJAIAgentSessionEntityServer extends MJAIAgentSessionEntity {
|
|
26
4
|
Validate(): ValidationResult;
|
|
5
|
+
/**
|
|
6
|
+
* Returns a refusal when an untrusted save writes or overwrites a server-only `CloseReason`, else null. The owner may
|
|
7
|
+
* close their own row as `Explicit` or `Error`; `TimeLimit` is stamped only after `SessionManager.CloseSession`
|
|
8
|
+
* verifies it against the stored deadline, and `Idle`, `Janitor` and `Shutdown` belong to the janitor and the
|
|
9
|
+
* host. A stamped server-only reason is the record of how the session ended, so the owner cannot replace it either.
|
|
10
|
+
* Server code that stamps them saves inside `RunWithTrustedSessionConfigWrites`.
|
|
11
|
+
*/
|
|
12
|
+
private checkServerManagedCloseReason;
|
|
27
13
|
/** Returns a refusal when an untrusted save changes a protected `Config` key, else null. */
|
|
28
14
|
private checkProtectedConfigKeys;
|
|
29
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJAIAgentSessionEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentSessionEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwD,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"MJAIAgentSessionEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJAIAgentSessionEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwD,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AA8BvE,qBACa,4BAA6B,SAAQ,sBAAsB;IACpD,QAAQ,IAAI,gBAAgB;IAc5C;;;;;;OAMG;IACH,OAAO,CAAC,6BAA6B;IAkBrC,4FAA4F;IAC5F,OAAO,CAAC,wBAAwB;CAmCnC"}
|
|
@@ -13,7 +13,8 @@ import { CheckAnonymousOwnershipKeyChange, IsSetByTransactionVariable } from './
|
|
|
13
13
|
* Server-side `MJ: AI Agent Sessions` entity.
|
|
14
14
|
*
|
|
15
15
|
* It keeps the **server-authoritative keys** inside `Config` (the janitor's
|
|
16
|
-
* `maxSessionDeadlineIso`, the `identityVerification` state)
|
|
16
|
+
* `maxSessionDeadlineIso`, the `identityVerification` state) and the server-only `CloseReason` values (`TimeLimit`,
|
|
17
|
+
* `Idle`, `Janitor`, `Shutdown`) out of the session owner's reach, and keeps an
|
|
17
18
|
* anonymous visitor from re-pointing an existing session's `ConversationID` (the anonymous ownership key —
|
|
18
19
|
* see `CheckAnonymousOwnershipKeyChange`). The
|
|
19
20
|
* owner can legitimately write the row — the `UI` and `Widget Guest` roles hold `CanUpdate` on their
|
|
@@ -31,11 +32,14 @@ import { CheckAnonymousOwnershipKeyChange, IsSetByTransactionVariable } from './
|
|
|
31
32
|
* every save, whereas async validation can be skipped by an option, and a guard that a caller can opt
|
|
32
33
|
* out of is not a guard.
|
|
33
34
|
*/
|
|
35
|
+
/** The close reasons a session owner may record; every other value is stamped by the server. */
|
|
36
|
+
const OWNER_CLOSE_REASONS = new Set(['Explicit', 'Error']);
|
|
34
37
|
let MJAIAgentSessionEntityServer = class MJAIAgentSessionEntityServer extends MJAIAgentSessionEntity {
|
|
35
38
|
Validate() {
|
|
36
39
|
const result = super.Validate();
|
|
37
40
|
const violations = [
|
|
38
41
|
this.checkProtectedConfigKeys(),
|
|
42
|
+
this.checkServerManagedCloseReason(),
|
|
39
43
|
CheckAnonymousOwnershipKeyChange(this, 'ConversationID'),
|
|
40
44
|
].filter((v) => v !== null);
|
|
41
45
|
if (violations.length > 0) {
|
|
@@ -44,6 +48,25 @@ let MJAIAgentSessionEntityServer = class MJAIAgentSessionEntityServer extends MJ
|
|
|
44
48
|
}
|
|
45
49
|
return result;
|
|
46
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Returns a refusal when an untrusted save writes or overwrites a server-only `CloseReason`, else null. The owner may
|
|
53
|
+
* close their own row as `Explicit` or `Error`; `TimeLimit` is stamped only after `SessionManager.CloseSession`
|
|
54
|
+
* verifies it against the stored deadline, and `Idle`, `Janitor` and `Shutdown` belong to the janitor and the
|
|
55
|
+
* host. A stamped server-only reason is the record of how the session ended, so the owner cannot replace it either.
|
|
56
|
+
* Server code that stamps them saves inside `RunWithTrustedSessionConfigWrites`.
|
|
57
|
+
*/
|
|
58
|
+
checkServerManagedCloseReason() {
|
|
59
|
+
const field = this.GetFieldByName('CloseReason');
|
|
60
|
+
if (IsTrustedSessionConfigWriteActive() || !field?.Dirty) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const previous = typeof field.OldValue === 'string' ? field.OldValue : null;
|
|
64
|
+
const serverOnly = [this.CloseReason, previous].find((reason) => reason !== null && !OWNER_CLOSE_REASONS.has(reason));
|
|
65
|
+
if (serverOnly === undefined) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return new ValidationErrorInfo('CloseReason', `CloseReason '${serverOnly}' is server-managed; a session owner can close a session only as Explicit or Error, and cannot change a reason the server recorded.`, this.CloseReason, ValidationErrorType.Failure);
|
|
69
|
+
}
|
|
47
70
|
/** Returns a refusal when an untrusted save changes a protected `Config` key, else null. */
|
|
48
71
|
checkProtectedConfigKeys() {
|
|
49
72
|
if (IsTrustedSessionConfigWriteActive()) {
|