@memberjunction/ai-agent-manager 2.106.0 → 2.108.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @memberjunction/ai-agent-manager@2.106.0 build
2
+ > @memberjunction/ai-agent-manager@2.108.0 build
3
3
  > tsc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @memberjunction/ai-agent-manager
2
2
 
3
+ ## 2.108.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d205a6c: migration
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [d205a6c]
12
+ - Updated dependencies [656d86c]
13
+ - @memberjunction/ai-core-plus@2.108.0
14
+ - @memberjunction/core-entities@2.108.0
15
+ - @memberjunction/core@2.108.0
16
+ - @memberjunction/global@2.108.0
17
+
18
+ ## 2.107.0
19
+
3
20
  ## 2.106.0
4
21
 
5
22
  ## 2.105.0
@@ -0,0 +1,355 @@
1
+ import { UserInfo } from '@memberjunction/core';
2
+ import { AgentSpec } from '@memberjunction/ai-core-plus';
3
+ /**
4
+ * AgentSpecSync provides a high-level interface for working with AI Agent metadata in MemberJunction.
5
+ *
6
+ * This class serves as a bi-directional bridge between the simple, serializable {@link AgentSpec}
7
+ * format and the complex MemberJunction database metadata across three core entities:
8
+ * - {@link AIAgentEntity} - Core agent configuration
9
+ * - {@link AIAgentActionEntity} - Agent-action relationships
10
+ * - {@link AIAgentRelationshipEntity} - Parent-child agent relationships
11
+ *
12
+ * ## Key Features
13
+ *
14
+ * - **Load from Database**: Load complete agent hierarchies including all sub-agents and actions
15
+ * - **Save to Database**: Persist changes atomically with full validation
16
+ * - **Recursive Support**: Handles n-level agent hierarchies automatically
17
+ * - **Type Safety**: Full TypeScript typing with proper entity types
18
+ * - **Dirty Tracking**: Knows when changes need to be saved
19
+ * - **JSON Serialization**: Easy export for APIs and storage
20
+ *
21
+ * ## Usage Examples
22
+ *
23
+ * ### Load an existing agent
24
+ * ```typescript
25
+ * const spec = await AgentSpecSync.LoadFromDatabase('agent-uuid', contextUser);
26
+ * console.log('Agent Name:', spec.spec.Name);
27
+ * console.log('Actions:', spec.spec.Actions?.length);
28
+ * ```
29
+ *
30
+ * ### Create a new agent
31
+ * ```typescript
32
+ * const newAgent = new AgentSpecSync({
33
+ * Name: 'My New Agent',
34
+ * Description: 'Does amazing things',
35
+ * IconClass: 'fa-robot',
36
+ * InvocationMode: 'Any'
37
+ * }, contextUser);
38
+ *
39
+ * const agentId = await newAgent.SaveToDatabase();
40
+ * ```
41
+ *
42
+ * ### Modify and save
43
+ * ```typescript
44
+ * const spec = await AgentSpecSync.LoadFromDatabase('agent-uuid', contextUser);
45
+ * spec.spec.Description = 'Updated description';
46
+ * spec.spec.MaxCostPerRun = 10.00;
47
+ * spec.markDirty();
48
+ * await spec.SaveToDatabase();
49
+ * ```
50
+ *
51
+ * @module @memberjunction/ai-agent-manager
52
+ */
53
+ export declare class AgentSpecSync {
54
+ /**
55
+ * The raw specification data structure containing all agent configuration
56
+ */
57
+ spec: AgentSpec;
58
+ /**
59
+ * Tracks whether this spec has been loaded from the database
60
+ * @private
61
+ */
62
+ private _isLoaded;
63
+ /**
64
+ * Tracks whether this spec has unsaved changes
65
+ * @private
66
+ */
67
+ private _isDirty;
68
+ /**
69
+ * Context user for database operations (required for server-side operations)
70
+ * @private
71
+ */
72
+ private _contextUser?;
73
+ /**
74
+ * Create a new AgentSpecSync instance.
75
+ *
76
+ * Note: This constructor is typically not called directly. Instead, use the static factory methods:
77
+ * - {@link LoadFromDatabase} - Load existing agent from database
78
+ * - {@link LoadByName} - Load agent by name
79
+ * - {@link FromRawSpec} - Create from raw spec data
80
+ *
81
+ * @param spec - Optional initial spec data (for creating new agents or working with existing data)
82
+ * @param contextUser - Optional context user (required for server-side operations)
83
+ */
84
+ constructor(spec?: Partial<AgentSpec>, contextUser?: UserInfo);
85
+ /**
86
+ * Load an agent and its complete hierarchy from the database by ID.
87
+ *
88
+ * This method efficiently loads the agent along with all its actions and sub-agents
89
+ * using batched queries to minimize database round trips. When `includeSubAgents` is true,
90
+ * it recursively loads the entire agent hierarchy.
91
+ *
92
+ * @param agentId - The unique ID of the agent to load
93
+ * @param contextUser - Optional context user (required for server-side operations)
94
+ * @param includeSubAgents - Whether to recursively load all sub-agents (default: true)
95
+ * @returns Promise resolving to AgentSpecSync instance with loaded data
96
+ * @throws {Error} If agent with specified ID is not found
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * // Load agent with all sub-agents
101
+ * const spec = await AgentSpecSync.LoadFromDatabase(
102
+ * 'agent-uuid-here',
103
+ * contextUser,
104
+ * true
105
+ * );
106
+ * ```
107
+ */
108
+ static LoadFromDatabase(agentId: string, contextUser?: UserInfo, includeSubAgents?: boolean): Promise<AgentSpecSync>;
109
+ /**
110
+ * Load an agent by name (must be unique).
111
+ *
112
+ * Searches for an agent with the specified name and loads it. If multiple agents
113
+ * have the same name, an error is thrown. Agent names should be unique within
114
+ * the system for this method to work reliably.
115
+ *
116
+ * @param agentName - The name of the agent to load
117
+ * @param contextUser - Optional context user (required for server-side operations)
118
+ * @param includeSubAgents - Whether to recursively load sub-agents (default: true)
119
+ * @returns Promise resolving to AgentSpecSync instance with loaded data
120
+ * @throws {Error} If agent is not found or multiple agents have the same name
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const spec = await AgentSpecSync.LoadByName('My Agent', contextUser);
125
+ * ```
126
+ */
127
+ static LoadByName(agentName: string, contextUser?: UserInfo, includeSubAgents?: boolean): Promise<AgentSpecSync>;
128
+ /**
129
+ * Create a new agent spec from a raw specification.
130
+ *
131
+ * This creates an in-memory AgentSpecSync instance from raw data. The agent is not
132
+ * saved to the database until {@link SaveToDatabase} is called.
133
+ *
134
+ * @param rawSpec - The raw spec data conforming to {@link AgentSpec} interface
135
+ * @param contextUser - Optional context user (required when saving server-side)
136
+ * @returns New AgentSpecSync instance (not yet saved to database)
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * const rawSpec: AgentSpec = {
141
+ * ID: '',
142
+ * Name: 'New Agent',
143
+ * Description: 'Agent description',
144
+ * InvocationMode: 'Any',
145
+ * Actions: [],
146
+ * SubAgents: []
147
+ * };
148
+ * const spec = AgentSpecSync.FromRawSpec(rawSpec, contextUser);
149
+ * await spec.SaveToDatabase();
150
+ * ```
151
+ */
152
+ static FromRawSpec(rawSpec: AgentSpec, contextUser?: UserInfo): AgentSpecSync;
153
+ /**
154
+ * Load the complete agent specification from database entities.
155
+ *
156
+ * This method orchestrates loading from AIAgent, AIAgentAction, and AIAgentRelationship tables
157
+ * using batched queries for optimal performance. It handles both child agents (ParentID-based)
158
+ * and related agents (relationship-based).
159
+ *
160
+ * @private
161
+ * @param agentId - The agent ID to load
162
+ * @param includeSubAgents - Whether to recursively load sub-agents
163
+ * @throws {Error} If agent is not found
164
+ */
165
+ private loadFromEntities;
166
+ /**
167
+ * Map database entities to AgentSpec format.
168
+ *
169
+ * Transforms the normalized database entities into a single denormalized specification
170
+ * object that's easy to work with in code. Handles JSON parsing for all structured fields.
171
+ *
172
+ * @private
173
+ * @param agent - The main agent entity
174
+ * @param actions - Array of agent action entities
175
+ * @param childAgents - Array of child agent entities (ParentID-based)
176
+ * @param relatedAgents - Array of related agent relationship entities
177
+ * @returns Fully populated AgentSpec object
178
+ */
179
+ private mapEntitiesToRawSpec;
180
+ /**
181
+ * Map AIAgentActionEntity to AgentActionSpec format.
182
+ *
183
+ * @private
184
+ * @param action - The agent action entity from the database
185
+ * @returns Mapped action spec
186
+ */
187
+ private mapActionEntityToSpec;
188
+ /**
189
+ * Map child agent (ParentID-based) to SubAgentSpec format.
190
+ *
191
+ * @private
192
+ * @param childAgent - The child agent entity
193
+ * @returns Mapped sub-agent spec
194
+ */
195
+ private mapChildAgentToSpec;
196
+ /**
197
+ * Map related agent (relationship-based) to SubAgentSpec format.
198
+ *
199
+ * @private
200
+ * @param relationship - The agent relationship entity
201
+ * @returns Mapped sub-agent spec
202
+ */
203
+ private mapRelatedAgentToSpec;
204
+ /**
205
+ * Save the current spec to the database.
206
+ *
207
+ * This will create new records or update existing ones based on whether IDs exist.
208
+ * The save operation is performed atomically - if any part fails, no changes are committed.
209
+ *
210
+ * Validation is performed before saving. All entity-level validations defined in the
211
+ * database schema are executed, and any failures will prevent the save.
212
+ *
213
+ * @param validate - Whether to validate before saving (default: true)
214
+ * @returns Promise resolving to the saved agent ID
215
+ * @throws {Error} If validation fails or save operation fails
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * const spec = new AgentSpecSync({
220
+ * Name: 'New Agent',
221
+ * InvocationMode: 'Any'
222
+ * }, contextUser);
223
+ *
224
+ * const agentId = await spec.SaveToDatabase();
225
+ * console.log('Saved with ID:', agentId);
226
+ * ```
227
+ */
228
+ SaveToDatabase(validate?: boolean): Promise<string>;
229
+ /**
230
+ * Save the main AIAgent entity.
231
+ *
232
+ * @private
233
+ * @param validate - Whether to perform validation before saving
234
+ * @returns Promise resolving to the saved agent ID
235
+ * @throws {Error} If validation fails or save fails
236
+ */
237
+ private saveAgentEntity;
238
+ /**
239
+ * Save all actions for this agent.
240
+ *
241
+ * Creates or updates agent action records. Existing actions are updated, new actions
242
+ * are created. This method does not delete actions that are no longer in the spec -
243
+ * use a separate delete method for that.
244
+ *
245
+ * @private
246
+ * @param agentId - The parent agent ID
247
+ * @throws {Error} If any action save fails
248
+ */
249
+ private saveActions;
250
+ /**
251
+ * Save all sub-agents (both child and related types).
252
+ *
253
+ * Handles both ParentID-based child agents and relationship-based related agents.
254
+ * For child agents, updates the ParentID on the sub-agent entity. For related agents,
255
+ * creates or updates the relationship record.
256
+ *
257
+ * @private
258
+ * @param agentId - The parent agent ID
259
+ * @throws {Error} If any sub-agent save fails
260
+ */
261
+ private saveSubAgents;
262
+ /**
263
+ * Save a child sub-agent (ParentID-based relationship).
264
+ *
265
+ * For child agents, the relationship is established by setting the ParentID field
266
+ * on the child agent entity. If the SubAgentID is empty, this indicates a new
267
+ * child agent that needs to be created.
268
+ *
269
+ * @private
270
+ * @param parentId - The parent agent ID
271
+ * @param SubAgentSpec - The sub-agent specification
272
+ * @throws {Error} If child agent doesn't exist or save fails
273
+ */
274
+ private saveChildSubAgent;
275
+ /**
276
+ * Save a related sub-agent (relationship-based).
277
+ *
278
+ * Creates or updates an AIAgentRelationship record that links the parent and
279
+ * sub-agent. This includes the input/output mapping and context path configurations.
280
+ *
281
+ * @private
282
+ * @param agentId - The parent agent ID
283
+ * @param SubAgentSpec - The sub-agent specification
284
+ * @throws {Error} If relationship save fails
285
+ */
286
+ private saveRelatedSubAgent;
287
+ /**
288
+ * Parse a JSON string field, returning undefined if null/empty.
289
+ *
290
+ * Safely parses JSON fields from the database, handling null/undefined values
291
+ * and logging errors if parsing fails.
292
+ *
293
+ * @private
294
+ * @param jsonString - The JSON string to parse
295
+ * @returns Parsed object or undefined if null/empty/invalid
296
+ */
297
+ private parseJsonField;
298
+ /**
299
+ * Initialize a spec with defaults for any missing required fields.
300
+ *
301
+ * Takes a partial spec and fills in defaults for any missing fields to ensure
302
+ * a valid AgentSpec structure.
303
+ *
304
+ * @private
305
+ * @param partial - Partial agent specification
306
+ * @returns Complete AgentSpec with defaults
307
+ */
308
+ private initializeSpec;
309
+ /**
310
+ * Get a clean serializable version of the spec.
311
+ *
312
+ * Returns a plain JavaScript object suitable for JSON serialization,
313
+ * API responses, or storage. This is useful when you need to send the
314
+ * agent spec over the wire or store it in a file.
315
+ *
316
+ * @returns Clean copy of the agent specification
317
+ *
318
+ * @example
319
+ * ```typescript
320
+ * const spec = await AgentSpecSync.LoadFromDatabase('agent-uuid', contextUser);
321
+ * const json = spec.toJSON();
322
+ * res.json(json); // Send as API response
323
+ * ```
324
+ */
325
+ toJSON(): AgentSpec;
326
+ /**
327
+ * Check if this spec has unsaved changes.
328
+ *
329
+ * @returns True if there are unsaved changes, false otherwise
330
+ */
331
+ get isDirty(): boolean;
332
+ /**
333
+ * Check if this spec has been loaded from the database.
334
+ *
335
+ * @returns True if loaded from database, false if created in memory
336
+ */
337
+ get isLoaded(): boolean;
338
+ /**
339
+ * Mark the spec as having changes.
340
+ *
341
+ * Call this method after modifying the spec to indicate that changes need to be saved.
342
+ * The spec is automatically marked dirty when created with the constructor, but if you
343
+ * load a spec and then modify it, you should call this method.
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * const spec = await AgentSpecSync.LoadFromDatabase('agent-uuid', contextUser);
348
+ * spec.spec.Description = 'New description';
349
+ * spec.markDirty();
350
+ * await spec.SaveToDatabase();
351
+ * ```
352
+ */
353
+ markDirty(): void;
354
+ }
355
+ //# sourceMappingURL=agent-spec-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-spec-sync.d.ts","sourceRoot":"","sources":["../src/agent-spec-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,QAAQ,EAEX,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EACH,SAAS,EAGZ,MAAM,8BAA8B,CAAC;AAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,qBAAa,aAAa;IACtB;;OAEG;IACI,IAAI,EAAE,SAAS,CAAC;IAEvB;;;OAGG;IACH,OAAO,CAAC,SAAS,CAAkB;IAEnC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAkB;IAElC;;;OAGG;IACH,OAAO,CAAC,YAAY,CAAC,CAAW;IAEhC;;;;;;;;;;OAUG;gBACS,IAAI,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC,EAAE,QAAQ;IAmB7D;;;;;;;;;;;;;;;;;;;;;;OAsBG;WACU,gBAAgB,CACzB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,QAAQ,EACtB,gBAAgB,GAAE,OAAc,GACjC,OAAO,CAAC,aAAa,CAAC;IAMzB;;;;;;;;;;;;;;;;;OAiBG;WACU,UAAU,CACnB,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,QAAQ,EACtB,gBAAgB,GAAE,OAAc,GACjC,OAAO,CAAC,aAAa,CAAC;IAyBzB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,QAAQ,GAAG,aAAa;IAM7E;;;;;;;;;;;OAWG;YACW,gBAAgB;IAkE9B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,oBAAoB;IA8D5B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACG,cAAc,CAAC,QAAQ,GAAE,OAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB/D;;;;;;;OAOG;YACW,eAAe;IAsF7B;;;;;;;;;;OAUG;YACW,WAAW;IAuCzB;;;;;;;;;;OAUG;YACW,aAAa;IAc3B;;;;;;;;;;;OAWG;YACW,iBAAiB;IA4B/B;;;;;;;;;;OAUG;YACW,mBAAmB;IA+CjC;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;IAUtB;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;IAoCtB;;;;;;;;;;;;;;;OAeG;IACI,MAAM,IAAI,SAAS;IAI1B;;;;OAIG;IACH,IAAW,OAAO,IAAI,OAAO,CAE5B;IAED;;;;OAIG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED;;;;;;;;;;;;;;OAcG;IACI,SAAS,IAAI,IAAI;CAG3B"}