@memberjunction/ai-engine-base 3.4.0 → 4.0.0
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/dist/AIAgentPermissionHelper.d.ts +45 -0
- package/dist/AIAgentPermissionHelper.d.ts.map +1 -1
- package/dist/AIAgentPermissionHelper.js +73 -20
- package/dist/AIAgentPermissionHelper.js.map +1 -1
- package/dist/AICredentialBindingEntityExtended.d.ts +33 -1
- package/dist/AICredentialBindingEntityExtended.d.ts.map +1 -1
- package/dist/AICredentialBindingEntityExtended.js +58 -22
- package/dist/AICredentialBindingEntityExtended.js.map +1 -1
- package/dist/BaseAIEngine.d.ts +310 -1
- package/dist/BaseAIEngine.d.ts.map +1 -1
- package/dist/BaseAIEngine.js +378 -41
- package/dist/BaseAIEngine.js.map +1 -1
- package/dist/PriceUnitTypes.d.ts +32 -1
- package/dist/PriceUnitTypes.d.ts.map +1 -1
- package/dist/PriceUnitTypes.js +40 -21
- package/dist/PriceUnitTypes.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -28
- package/dist/index.js.map +1 -1
- package/package.json +13 -12
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { UserInfo } from "@memberjunction/core";
|
|
2
2
|
import { AIAgentEntity } from "@memberjunction/core-entities";
|
|
3
|
+
/**
|
|
4
|
+
* Effective permissions for a user on a specific AI agent
|
|
5
|
+
*/
|
|
3
6
|
export interface EffectiveAgentPermissions {
|
|
4
7
|
canView: boolean;
|
|
5
8
|
canRun: boolean;
|
|
@@ -7,11 +10,53 @@ export interface EffectiveAgentPermissions {
|
|
|
7
10
|
canDelete: boolean;
|
|
8
11
|
isOwner: boolean;
|
|
9
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Helper class for managing AI Agent permissions.
|
|
15
|
+
* Provides methods to check user permissions, get accessible agents, and uses AIEngineBase cached metadata.
|
|
16
|
+
*/
|
|
10
17
|
export declare class AIAgentPermissionHelper {
|
|
18
|
+
/**
|
|
19
|
+
* Checks if a user has a specific permission for an agent.
|
|
20
|
+
* @param agentId - The ID of the agent to check
|
|
21
|
+
* @param user - The user to check permissions for
|
|
22
|
+
* @param permission - The permission level to check ('view', 'run', 'edit', or 'delete')
|
|
23
|
+
* @returns True if the user has the specified permission
|
|
24
|
+
*/
|
|
11
25
|
static HasPermission(agentId: string, user: UserInfo, permission: 'view' | 'run' | 'edit' | 'delete'): Promise<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Gets the aggregate permissions for a user on a specific agent.
|
|
28
|
+
* Implements hierarchical permission logic:
|
|
29
|
+
* - Delete implies Edit, Run, and View
|
|
30
|
+
* - Edit implies Run and View
|
|
31
|
+
* - Run implies View
|
|
32
|
+
*
|
|
33
|
+
* Default behavior when no permission records exist:
|
|
34
|
+
* - Anyone can View and Run (open by default)
|
|
35
|
+
* - Only owner can Edit and Delete
|
|
36
|
+
*
|
|
37
|
+
* Checks ownership first, then combines all matching user and role permissions.
|
|
38
|
+
* @param agentId - The ID of the agent
|
|
39
|
+
* @param user - The user to check permissions for
|
|
40
|
+
* @returns Object containing all effective permissions and ownership status
|
|
41
|
+
*/
|
|
12
42
|
static GetEffectivePermissions(agentId: string, user: UserInfo): Promise<EffectiveAgentPermissions>;
|
|
43
|
+
/**
|
|
44
|
+
* Gets all agents that a user has access to with a specific permission level.
|
|
45
|
+
* Uses cached metadata from AIEngineBase instead of querying database.
|
|
46
|
+
* @param user - The user to check permissions for
|
|
47
|
+
* @param permission - The minimum permission level required ('view', 'run', 'edit', or 'delete')
|
|
48
|
+
* @returns Array of agents the user can access with the specified permission
|
|
49
|
+
*/
|
|
13
50
|
static GetAccessibleAgents(user: UserInfo, permission: 'view' | 'run' | 'edit' | 'delete'): Promise<AIAgentEntity[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Clears the AIEngineBase cache. Useful when permissions have been modified.
|
|
53
|
+
* This forces a reload of all cached metadata including permissions.
|
|
54
|
+
*/
|
|
14
55
|
static ClearCache(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Refreshes the AIEngineBase cache to pick up permission changes.
|
|
58
|
+
* @param user - The user context for server-side operations
|
|
59
|
+
*/
|
|
15
60
|
static RefreshCache(user: UserInfo): Promise<void>;
|
|
16
61
|
}
|
|
17
62
|
//# sourceMappingURL=AIAgentPermissionHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIAgentPermissionHelper.d.ts","sourceRoot":"","sources":["../src/AIAgentPermissionHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AIAgentPermissionHelper.d.ts","sourceRoot":"","sources":["../src/AIAgentPermissionHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,uBAAuB;IAChC;;;;;;OAMG;WACiB,aAAa,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAC/C,OAAO,CAAC,OAAO,CAAC;IAiBnB;;;;;;;;;;;;;;;OAeG;WACiB,uBAAuB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,QAAQ,GACf,OAAO,CAAC,yBAAyB,CAAC;IAiFrC;;;;;;OAMG;WACiB,mBAAmB,CACnC,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAC/C,OAAO,CAAC,aAAa,EAAE,CAAC;IAsB3B;;;OAGG;WACW,UAAU,IAAI,IAAI;IAOhC;;;OAGG;WACiB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;CAOlE"}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { LogError } from "@memberjunction/core";
|
|
2
|
+
import { AIEngineBase } from "./BaseAIEngine.js";
|
|
3
|
+
/**
|
|
4
|
+
* Helper class for managing AI Agent permissions.
|
|
5
|
+
* Provides methods to check user permissions, get accessible agents, and uses AIEngineBase cached metadata.
|
|
6
|
+
*/
|
|
7
|
+
export class AIAgentPermissionHelper {
|
|
8
|
+
/**
|
|
9
|
+
* Checks if a user has a specific permission for an agent.
|
|
10
|
+
* @param agentId - The ID of the agent to check
|
|
11
|
+
* @param user - The user to check permissions for
|
|
12
|
+
* @param permission - The permission level to check ('view', 'run', 'edit', or 'delete')
|
|
13
|
+
* @returns True if the user has the specified permission
|
|
14
|
+
*/
|
|
7
15
|
static async HasPermission(agentId, user, permission) {
|
|
8
16
|
const effective = await this.GetEffectivePermissions(agentId, user);
|
|
9
17
|
switch (permission) {
|
|
@@ -19,13 +27,32 @@ class AIAgentPermissionHelper {
|
|
|
19
27
|
return false;
|
|
20
28
|
}
|
|
21
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Gets the aggregate permissions for a user on a specific agent.
|
|
32
|
+
* Implements hierarchical permission logic:
|
|
33
|
+
* - Delete implies Edit, Run, and View
|
|
34
|
+
* - Edit implies Run and View
|
|
35
|
+
* - Run implies View
|
|
36
|
+
*
|
|
37
|
+
* Default behavior when no permission records exist:
|
|
38
|
+
* - Anyone can View and Run (open by default)
|
|
39
|
+
* - Only owner can Edit and Delete
|
|
40
|
+
*
|
|
41
|
+
* Checks ownership first, then combines all matching user and role permissions.
|
|
42
|
+
* @param agentId - The ID of the agent
|
|
43
|
+
* @param user - The user to check permissions for
|
|
44
|
+
* @returns Object containing all effective permissions and ownership status
|
|
45
|
+
*/
|
|
22
46
|
static async GetEffectivePermissions(agentId, user) {
|
|
23
47
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
48
|
+
// Ensure AIEngineBase is loaded with cached metadata
|
|
49
|
+
await AIEngineBase.Instance.Config(false, user);
|
|
50
|
+
// Find agent from cached metadata
|
|
51
|
+
const agent = AIEngineBase.Instance.Agents.find(a => a.ID === agentId);
|
|
26
52
|
if (!agent) {
|
|
27
53
|
throw new Error(`Agent ${agentId} not found in cached metadata`);
|
|
28
54
|
}
|
|
55
|
+
// Check if user is owner - owners have all permissions
|
|
29
56
|
const isOwner = agent.OwnerUserID === user.ID;
|
|
30
57
|
if (isOwner) {
|
|
31
58
|
return {
|
|
@@ -36,22 +63,30 @@ class AIAgentPermissionHelper {
|
|
|
36
63
|
isOwner: true
|
|
37
64
|
};
|
|
38
65
|
}
|
|
39
|
-
|
|
66
|
+
// Get permissions from cached metadata
|
|
67
|
+
const agentPermissions = AIEngineBase.Instance.AgentPermissions.filter(p => p.AgentID === agentId);
|
|
68
|
+
// DEFAULT BEHAVIOR: If no permission records exist, grant View and Run to everyone
|
|
69
|
+
// This minimizes administrative overhead while protecting Edit/Delete through ownership
|
|
40
70
|
if (agentPermissions.length === 0) {
|
|
41
71
|
return {
|
|
42
72
|
canView: true,
|
|
43
73
|
canRun: true,
|
|
44
|
-
canEdit: false,
|
|
45
|
-
canDelete: false,
|
|
74
|
+
canEdit: false, // Only owner can edit
|
|
75
|
+
canDelete: false, // Only owner can delete
|
|
46
76
|
isOwner: false
|
|
47
77
|
};
|
|
48
78
|
}
|
|
79
|
+
// Get user's role IDs
|
|
49
80
|
const userRoleIds = user.UserRoles?.map(ur => ur.RoleID) || [];
|
|
81
|
+
// Find all matching permissions (direct user permissions or role permissions)
|
|
50
82
|
const matchingPermissions = agentPermissions.filter(p => p.UserID === user.ID || (p.RoleID && userRoleIds.includes(p.RoleID)));
|
|
83
|
+
// Aggregate base permissions - any matching permission grants access (OR logic)
|
|
51
84
|
const hasDelete = matchingPermissions.some(p => p.CanDelete === true);
|
|
52
85
|
const hasEdit = matchingPermissions.some(p => p.CanEdit === true);
|
|
53
86
|
const hasRun = matchingPermissions.some(p => p.CanRun === true);
|
|
54
87
|
const hasView = matchingPermissions.some(p => p.CanView === true);
|
|
88
|
+
// Apply hierarchical logic:
|
|
89
|
+
// Delete → Edit → Run → View
|
|
55
90
|
const canDelete = hasDelete;
|
|
56
91
|
const canEdit = hasDelete || hasEdit;
|
|
57
92
|
const canRun = hasDelete || hasEdit || hasRun;
|
|
@@ -65,7 +100,8 @@ class AIAgentPermissionHelper {
|
|
|
65
100
|
};
|
|
66
101
|
}
|
|
67
102
|
catch (error) {
|
|
68
|
-
|
|
103
|
+
LogError(error, 'Error getting effective permissions for agent');
|
|
104
|
+
// Fail closed - deny all permissions on error
|
|
69
105
|
return {
|
|
70
106
|
canView: false,
|
|
71
107
|
canRun: false,
|
|
@@ -75,11 +111,20 @@ class AIAgentPermissionHelper {
|
|
|
75
111
|
};
|
|
76
112
|
}
|
|
77
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Gets all agents that a user has access to with a specific permission level.
|
|
116
|
+
* Uses cached metadata from AIEngineBase instead of querying database.
|
|
117
|
+
* @param user - The user to check permissions for
|
|
118
|
+
* @param permission - The minimum permission level required ('view', 'run', 'edit', or 'delete')
|
|
119
|
+
* @returns Array of agents the user can access with the specified permission
|
|
120
|
+
*/
|
|
78
121
|
static async GetAccessibleAgents(user, permission) {
|
|
79
122
|
try {
|
|
80
|
-
|
|
123
|
+
// Ensure AIEngineBase is loaded with cached metadata
|
|
124
|
+
await AIEngineBase.Instance.Config(false, user);
|
|
125
|
+
// Filter agents from cached metadata based on permissions
|
|
81
126
|
const accessibleAgents = [];
|
|
82
|
-
for (const agent of
|
|
127
|
+
for (const agent of AIEngineBase.Instance.Agents) {
|
|
83
128
|
const hasAccess = await this.HasPermission(agent.ID, user, permission);
|
|
84
129
|
if (hasAccess) {
|
|
85
130
|
accessibleAgents.push(agent);
|
|
@@ -88,23 +133,31 @@ class AIAgentPermissionHelper {
|
|
|
88
133
|
return accessibleAgents;
|
|
89
134
|
}
|
|
90
135
|
catch (error) {
|
|
91
|
-
|
|
136
|
+
LogError(error, 'Error getting accessible agents');
|
|
92
137
|
return [];
|
|
93
138
|
}
|
|
94
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Clears the AIEngineBase cache. Useful when permissions have been modified.
|
|
142
|
+
* This forces a reload of all cached metadata including permissions.
|
|
143
|
+
*/
|
|
95
144
|
static ClearCache() {
|
|
96
|
-
|
|
97
|
-
|
|
145
|
+
// Force reload by calling Config with forceRefresh=true
|
|
146
|
+
AIEngineBase.Instance.Config(true).catch(error => {
|
|
147
|
+
LogError(error, 'Error clearing AIEngineBase cache');
|
|
98
148
|
});
|
|
99
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Refreshes the AIEngineBase cache to pick up permission changes.
|
|
152
|
+
* @param user - The user context for server-side operations
|
|
153
|
+
*/
|
|
100
154
|
static async RefreshCache(user) {
|
|
101
155
|
try {
|
|
102
|
-
await
|
|
156
|
+
await AIEngineBase.Instance.Config(true, user);
|
|
103
157
|
}
|
|
104
158
|
catch (error) {
|
|
105
|
-
|
|
159
|
+
LogError(error, 'Error refreshing AIEngineBase cache');
|
|
106
160
|
}
|
|
107
161
|
}
|
|
108
162
|
}
|
|
109
|
-
exports.AIAgentPermissionHelper = AIAgentPermissionHelper;
|
|
110
163
|
//# sourceMappingURL=AIAgentPermissionHelper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AIAgentPermissionHelper.js","sourceRoot":"","sources":["../src/AIAgentPermissionHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AIAgentPermissionHelper.js","sourceRoot":"","sources":["../src/AIAgentPermissionHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,45 @@
|
|
|
1
1
|
import { ValidationResult } from '@memberjunction/core';
|
|
2
2
|
import { AICredentialBindingEntity } from '@memberjunction/core-entities';
|
|
3
|
+
/**
|
|
4
|
+
* Extended AICredentialBindingEntity class that validates credential types match vendor expectations.
|
|
5
|
+
* When a credential is bound, this validates that the credential's CredentialTypeID matches the
|
|
6
|
+
* CredentialTypeID expected by the vendor (as declared on the AIVendor record).
|
|
7
|
+
*/
|
|
3
8
|
export declare class AICredentialBindingEntityExtended extends AICredentialBindingEntity {
|
|
9
|
+
/**
|
|
10
|
+
* Async validation that checks credential type compatibility.
|
|
11
|
+
* Uses AIEngineBase.Instance for cached AI entity data and RunView for credentials.
|
|
12
|
+
*/
|
|
4
13
|
ValidateAsync(): Promise<ValidationResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Turn on async validation
|
|
16
|
+
*/
|
|
5
17
|
get DefaultSkipAsyncValidation(): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Validates that the bound credential's type matches the vendor's expected credential type.
|
|
20
|
+
* The vendor is determined based on the binding type:
|
|
21
|
+
* - Vendor binding: directly references the vendor
|
|
22
|
+
* - ModelVendor binding: gets vendor from the ModelVendor record
|
|
23
|
+
* - PromptModel binding: gets vendor from the PromptModel -> ModelVendor -> Vendor chain
|
|
24
|
+
*/
|
|
6
25
|
private validateCredentialTypeMatch;
|
|
26
|
+
/**
|
|
27
|
+
* Gets the expected CredentialTypeID from the vendor based on the binding type.
|
|
28
|
+
* Uses AIEngineBase cached data for lookups.
|
|
29
|
+
*/
|
|
7
30
|
private getExpectedCredentialTypeId;
|
|
31
|
+
/**
|
|
32
|
+
* Gets the expected credential type name for error messages.
|
|
33
|
+
*/
|
|
8
34
|
private getExpectedCredentialTypeName;
|
|
35
|
+
/**
|
|
36
|
+
* Gets the vendor name for error messages based on the binding type.
|
|
37
|
+
*/
|
|
9
38
|
private getVendorNameForError;
|
|
39
|
+
/**
|
|
40
|
+
* Loads the credential using RunView.
|
|
41
|
+
* Credentials are not cached in AIEngineBase, so we need to query them.
|
|
42
|
+
*/
|
|
10
43
|
private loadCredential;
|
|
11
44
|
}
|
|
12
|
-
export declare function LoadAICredentialBindingEntityExtended(): void;
|
|
13
45
|
//# sourceMappingURL=AICredentialBindingEntityExtended.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AICredentialBindingEntityExtended.d.ts","sourceRoot":"","sources":["../src/AICredentialBindingEntityExtended.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,gBAAgB,EAA4C,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,yBAAyB,EAAoB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"AICredentialBindingEntityExtended.d.ts","sourceRoot":"","sources":["../src/AICredentialBindingEntityExtended.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,gBAAgB,EAA4C,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,yBAAyB,EAAoB,MAAM,+BAA+B,CAAC;AAG5F;;;;GAIG;AACH,qBACa,iCAAkC,SAAQ,yBAAyB;IAE5E;;;OAGG;IACmB,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAYhE;;OAEG;IACH,IAAa,0BAA0B,IAAI,OAAO,CAEjD;IAED;;;;;;OAMG;YACW,2BAA2B;IAmCzC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAgCnC;;OAEG;IACH,OAAO,CAAC,6BAA6B;IA6BrC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA6B7B;;;OAGG;YACW,cAAc;CAkB/B"}
|
|
@@ -1,51 +1,79 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
2
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
3
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
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;
|
|
6
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
6
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
8
|
+
import { BaseEntity, RunView, ValidationErrorInfo, ValidationErrorType } from '@memberjunction/core';
|
|
9
|
+
import { AICredentialBindingEntity } from '@memberjunction/core-entities';
|
|
10
|
+
import { AIEngineBase } from './BaseAIEngine.js';
|
|
11
|
+
/**
|
|
12
|
+
* Extended AICredentialBindingEntity class that validates credential types match vendor expectations.
|
|
13
|
+
* When a credential is bound, this validates that the credential's CredentialTypeID matches the
|
|
14
|
+
* CredentialTypeID expected by the vendor (as declared on the AIVendor record).
|
|
15
|
+
*/
|
|
16
|
+
let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended extends AICredentialBindingEntity {
|
|
17
|
+
/**
|
|
18
|
+
* Async validation that checks credential type compatibility.
|
|
19
|
+
* Uses AIEngineBase.Instance for cached AI entity data and RunView for credentials.
|
|
20
|
+
*/
|
|
15
21
|
async ValidateAsync() {
|
|
22
|
+
// Start with base validation (including synchronous validation)
|
|
16
23
|
const result = await super.ValidateAsync();
|
|
24
|
+
// Only validate credential type if we have both a credential and can determine the vendor
|
|
17
25
|
if (this.CredentialID) {
|
|
18
26
|
await this.validateCredentialTypeMatch(result);
|
|
19
27
|
}
|
|
20
28
|
return result;
|
|
21
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Turn on async validation
|
|
32
|
+
*/
|
|
22
33
|
get DefaultSkipAsyncValidation() {
|
|
23
|
-
return false;
|
|
34
|
+
return false; // don't skip async validation
|
|
24
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Validates that the bound credential's type matches the vendor's expected credential type.
|
|
38
|
+
* The vendor is determined based on the binding type:
|
|
39
|
+
* - Vendor binding: directly references the vendor
|
|
40
|
+
* - ModelVendor binding: gets vendor from the ModelVendor record
|
|
41
|
+
* - PromptModel binding: gets vendor from the PromptModel -> ModelVendor -> Vendor chain
|
|
42
|
+
*/
|
|
25
43
|
async validateCredentialTypeMatch(result) {
|
|
44
|
+
// Get the expected credential type from the vendor
|
|
26
45
|
const vendorCredentialTypeId = this.getExpectedCredentialTypeId();
|
|
46
|
+
// If the vendor doesn't have a credential type requirement, skip validation
|
|
27
47
|
if (!vendorCredentialTypeId) {
|
|
28
48
|
return;
|
|
29
49
|
}
|
|
50
|
+
// Load the credential to get its type
|
|
30
51
|
const credential = await this.loadCredential();
|
|
31
52
|
if (!credential) {
|
|
32
|
-
result.Errors.push(new
|
|
53
|
+
result.Errors.push(new ValidationErrorInfo('CredentialID', `Could not load credential with ID '${this.CredentialID}' to validate type compatibility.`, this.CredentialID, ValidationErrorType.Warning));
|
|
33
54
|
return;
|
|
34
55
|
}
|
|
56
|
+
// Compare credential types
|
|
35
57
|
if (credential.CredentialTypeID !== vendorCredentialTypeId) {
|
|
36
58
|
const vendorName = this.getVendorNameForError();
|
|
37
59
|
const expectedTypeName = this.getExpectedCredentialTypeName();
|
|
38
|
-
result.Errors.push(new
|
|
60
|
+
result.Errors.push(new ValidationErrorInfo('CredentialID', `Credential type mismatch: The credential '${credential.Name}' has type '${credential.CredentialType || credential.CredentialTypeID}' but vendor '${vendorName}' expects type '${expectedTypeName || vendorCredentialTypeId}'.`, this.CredentialID, ValidationErrorType.Failure));
|
|
39
61
|
}
|
|
40
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the expected CredentialTypeID from the vendor based on the binding type.
|
|
65
|
+
* Uses AIEngineBase cached data for lookups.
|
|
66
|
+
*/
|
|
41
67
|
getExpectedCredentialTypeId() {
|
|
42
|
-
const engine =
|
|
68
|
+
const engine = AIEngineBase.Instance;
|
|
43
69
|
switch (this.BindingType) {
|
|
44
70
|
case 'Vendor': {
|
|
71
|
+
// Direct vendor binding - get type from the vendor
|
|
45
72
|
const vendor = engine.Vendors.find(v => v.ID === this.AIVendorID);
|
|
46
73
|
return vendor?.CredentialTypeID ?? null;
|
|
47
74
|
}
|
|
48
75
|
case 'ModelVendor': {
|
|
76
|
+
// ModelVendor binding - get vendor from ModelVendor, then get type
|
|
49
77
|
const modelVendor = engine.ModelVendors.find(mv => mv.ID === this.AIModelVendorID);
|
|
50
78
|
if (modelVendor) {
|
|
51
79
|
const vendor = engine.Vendors.find(v => v.ID === modelVendor.VendorID);
|
|
@@ -54,6 +82,7 @@ let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended
|
|
|
54
82
|
return null;
|
|
55
83
|
}
|
|
56
84
|
case 'PromptModel': {
|
|
85
|
+
// PromptModel binding - get vendor from PromptModel's VendorID
|
|
57
86
|
const promptModel = engine.PromptModels.find(pm => pm.ID === this.AIPromptModelID);
|
|
58
87
|
if (promptModel && promptModel.VendorID) {
|
|
59
88
|
const vendor = engine.Vendors.find(v => v.ID === promptModel.VendorID);
|
|
@@ -65,8 +94,11 @@ let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended
|
|
|
65
94
|
return null;
|
|
66
95
|
}
|
|
67
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the expected credential type name for error messages.
|
|
99
|
+
*/
|
|
68
100
|
getExpectedCredentialTypeName() {
|
|
69
|
-
const engine =
|
|
101
|
+
const engine = AIEngineBase.Instance;
|
|
70
102
|
switch (this.BindingType) {
|
|
71
103
|
case 'Vendor': {
|
|
72
104
|
const vendor = engine.Vendors.find(v => v.ID === this.AIVendorID);
|
|
@@ -92,8 +124,11 @@ let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended
|
|
|
92
124
|
return null;
|
|
93
125
|
}
|
|
94
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Gets the vendor name for error messages based on the binding type.
|
|
129
|
+
*/
|
|
95
130
|
getVendorNameForError() {
|
|
96
|
-
const engine =
|
|
131
|
+
const engine = AIEngineBase.Instance;
|
|
97
132
|
switch (this.BindingType) {
|
|
98
133
|
case 'Vendor': {
|
|
99
134
|
const vendor = engine.Vendors.find(v => v.ID === this.AIVendorID);
|
|
@@ -119,15 +154,19 @@ let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended
|
|
|
119
154
|
return 'Unknown';
|
|
120
155
|
}
|
|
121
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Loads the credential using RunView.
|
|
159
|
+
* Credentials are not cached in AIEngineBase, so we need to query them.
|
|
160
|
+
*/
|
|
122
161
|
async loadCredential() {
|
|
123
162
|
if (!this.CredentialID) {
|
|
124
163
|
return null;
|
|
125
164
|
}
|
|
126
|
-
const rv = new
|
|
165
|
+
const rv = new RunView();
|
|
127
166
|
const result = await rv.RunView({
|
|
128
167
|
EntityName: 'MJ: Credentials',
|
|
129
168
|
ResultType: 'entity_object',
|
|
130
|
-
CacheLocal: true
|
|
169
|
+
CacheLocal: true // load all records and use cache for speed, filter client side below
|
|
131
170
|
}, this.ContextCurrentUser);
|
|
132
171
|
if (result.Success && result.Results && result.Results.length > 0) {
|
|
133
172
|
return result.Results.find(c => c.ID === this.CredentialID);
|
|
@@ -135,11 +174,8 @@ let AICredentialBindingEntityExtended = class AICredentialBindingEntityExtended
|
|
|
135
174
|
return null;
|
|
136
175
|
}
|
|
137
176
|
};
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
(0, global_1.RegisterClass)(core_1.BaseEntity, 'MJ: AI Credential Bindings')
|
|
177
|
+
AICredentialBindingEntityExtended = __decorate([
|
|
178
|
+
RegisterClass(BaseEntity, 'MJ: AI Credential Bindings')
|
|
141
179
|
], AICredentialBindingEntityExtended);
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
exports.LoadAICredentialBindingEntityExtended = LoadAICredentialBindingEntityExtended;
|
|
180
|
+
export { AICredentialBindingEntityExtended };
|
|
145
181
|
//# sourceMappingURL=AICredentialBindingEntityExtended.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AICredentialBindingEntityExtended.js","sourceRoot":"","sources":["../src/AICredentialBindingEntityExtended.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AICredentialBindingEntityExtended.js","sourceRoot":"","sources":["../src/AICredentialBindingEntityExtended.ts"],"names":[],"mappings":"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"}
|