@memberjunction/ai-agent-manager 6.1.4 → 6.2.0-edge.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +107 -61
- package/dist/agent-spec-sync.d.ts +17 -1
- package/dist/agent-spec-sync.d.ts.map +1 -1
- package/dist/agent-spec-sync.js +121 -89
- package/dist/agent-spec-sync.js.map +1 -1
- package/package.json +9 -9
- package/src/agent-spec-sync.ts +129 -90
package/src/agent-spec-sync.ts
CHANGED
|
@@ -128,7 +128,16 @@ export class AgentSpecSync {
|
|
|
128
128
|
/**
|
|
129
129
|
* The raw specification data structure containing all agent configuration
|
|
130
130
|
*/
|
|
131
|
-
public
|
|
131
|
+
public Spec: AgentSpec;
|
|
132
|
+
|
|
133
|
+
/** @deprecated Use {@link Spec}. */
|
|
134
|
+
public get spec(): AgentSpec {
|
|
135
|
+
return this.Spec;
|
|
136
|
+
}
|
|
137
|
+
/** @deprecated Use {@link Spec}. */
|
|
138
|
+
public set spec(value: AgentSpec) {
|
|
139
|
+
this.Spec = value;
|
|
140
|
+
}
|
|
132
141
|
|
|
133
142
|
/**
|
|
134
143
|
* Tracks whether this spec has been loaded from the database
|
|
@@ -183,11 +192,11 @@ export class AgentSpecSync {
|
|
|
183
192
|
*/
|
|
184
193
|
constructor(spec?: Partial<AgentSpec>, contextUser?: UserInfo, provider?: IMetadataProvider) {
|
|
185
194
|
if (spec) {
|
|
186
|
-
this.
|
|
195
|
+
this.Spec = this.initializeSpec(spec);
|
|
187
196
|
this._isDirty = true;
|
|
188
197
|
} else {
|
|
189
198
|
// Create minimal empty spec
|
|
190
|
-
this.
|
|
199
|
+
this.Spec = {
|
|
191
200
|
ID: '', // Will be set on save if empty
|
|
192
201
|
Name: '',
|
|
193
202
|
StartingPayloadValidationMode: 'Fail',
|
|
@@ -223,17 +232,27 @@ export class AgentSpecSync {
|
|
|
223
232
|
* Get all mutations tracked during the last save operation
|
|
224
233
|
* @returns Array of mutations
|
|
225
234
|
*/
|
|
226
|
-
public
|
|
235
|
+
public GetMutations(): AgentSpecSyncMutation[] {
|
|
227
236
|
return [...this._mutations];
|
|
228
237
|
}
|
|
229
238
|
|
|
239
|
+
/** @deprecated Use {@link GetMutations}. */
|
|
240
|
+
public getMutations(): AgentSpecSyncMutation[] {
|
|
241
|
+
return this.GetMutations();
|
|
242
|
+
}
|
|
243
|
+
|
|
230
244
|
/**
|
|
231
245
|
* Clear all tracked mutations
|
|
232
246
|
*/
|
|
233
|
-
public
|
|
247
|
+
public ClearMutations(): void {
|
|
234
248
|
this._mutations = [];
|
|
235
249
|
}
|
|
236
250
|
|
|
251
|
+
/** @deprecated Use {@link ClearMutations}. */
|
|
252
|
+
public clearMutations(): void {
|
|
253
|
+
return this.ClearMutations();
|
|
254
|
+
}
|
|
255
|
+
|
|
237
256
|
// ===== STATIC FACTORY METHODS =====
|
|
238
257
|
|
|
239
258
|
/**
|
|
@@ -475,7 +494,7 @@ export class AgentSpecSync {
|
|
|
475
494
|
}
|
|
476
495
|
|
|
477
496
|
// Step 3: Map entities to raw spec format
|
|
478
|
-
this.
|
|
497
|
+
this.Spec = this.mapEntitiesToRawSpec(
|
|
479
498
|
agentEntity,
|
|
480
499
|
actionsResult.Results || [],
|
|
481
500
|
childAgentsResult.Results || [],
|
|
@@ -487,9 +506,9 @@ export class AgentSpecSync {
|
|
|
487
506
|
);
|
|
488
507
|
|
|
489
508
|
// Step 4: Recursively load sub-agents if requested
|
|
490
|
-
if (includeSubAgents && this.
|
|
509
|
+
if (includeSubAgents && this.Spec.SubAgents && this.Spec.SubAgents.length > 0) {
|
|
491
510
|
// Recursively load complete specs for all sub-agents
|
|
492
|
-
for (const subAgentSpec of this.
|
|
511
|
+
for (const subAgentSpec of this.Spec.SubAgents) {
|
|
493
512
|
if (subAgentSpec.SubAgent && subAgentSpec.SubAgent.ID) {
|
|
494
513
|
try {
|
|
495
514
|
// Load the complete sub-agent spec recursively
|
|
@@ -786,12 +805,12 @@ export class AgentSpecSync {
|
|
|
786
805
|
*/
|
|
787
806
|
async SaveToDatabase(validate: boolean = true): Promise<AgentSpecSyncResult> {
|
|
788
807
|
// Clear previous mutations
|
|
789
|
-
this.
|
|
808
|
+
this.ClearMutations();
|
|
790
809
|
|
|
791
810
|
if (!this._isDirty && this._isLoaded) {
|
|
792
811
|
// No changes to save
|
|
793
812
|
return {
|
|
794
|
-
agentId: this.
|
|
813
|
+
agentId: this.Spec.ID,
|
|
795
814
|
success: true,
|
|
796
815
|
mutations: []
|
|
797
816
|
};
|
|
@@ -799,12 +818,12 @@ export class AgentSpecSync {
|
|
|
799
818
|
|
|
800
819
|
try {
|
|
801
820
|
// Step 0: Delete orphaned records (if this is an update)
|
|
802
|
-
if (this._isLoaded && this.
|
|
803
|
-
console.log(`🗑️ SaveToDatabase: Loading current database state for agent ${this.
|
|
804
|
-
const dbState = await this.loadCurrentDatabaseState(this.
|
|
821
|
+
if (this._isLoaded && this.Spec.ID) {
|
|
822
|
+
console.log(`🗑️ SaveToDatabase: Loading current database state for agent ${this.Spec.ID}...`);
|
|
823
|
+
const dbState = await this.loadCurrentDatabaseState(this.Spec.ID);
|
|
805
824
|
|
|
806
825
|
console.log(`🔍 SaveToDatabase: Identifying orphaned records...`);
|
|
807
|
-
const orphans = this.identifyOrphans(dbState, this.
|
|
826
|
+
const orphans = this.identifyOrphans(dbState, this.Spec);
|
|
808
827
|
|
|
809
828
|
console.log(`🗑️ SaveToDatabase: Deleting ${orphans.paths.length} paths, ${orphans.actions.length} actions, ${orphans.steps.length} steps, ${orphans.prompts.length} prompts, ${orphans.relationships.length} relationships, orphaning ${orphans.childAgents.length} child agents...`);
|
|
810
829
|
await this.deleteOrphans(orphans);
|
|
@@ -836,14 +855,14 @@ export class AgentSpecSync {
|
|
|
836
855
|
return {
|
|
837
856
|
agentId,
|
|
838
857
|
success: true,
|
|
839
|
-
mutations: this.
|
|
858
|
+
mutations: this.GetMutations()
|
|
840
859
|
};
|
|
841
860
|
} catch (error) {
|
|
842
861
|
// Return failure with whatever mutations were completed before error
|
|
843
862
|
return {
|
|
844
|
-
agentId: this.
|
|
863
|
+
agentId: this.Spec.ID || '',
|
|
845
864
|
success: false,
|
|
846
|
-
mutations: this.
|
|
865
|
+
mutations: this.GetMutations()
|
|
847
866
|
};
|
|
848
867
|
}
|
|
849
868
|
}
|
|
@@ -864,85 +883,85 @@ export class AgentSpecSync {
|
|
|
864
883
|
);
|
|
865
884
|
|
|
866
885
|
// Track if this is an update or create
|
|
867
|
-
const isUpdate = !!this.
|
|
886
|
+
const isUpdate = !!this.Spec.ID;
|
|
868
887
|
|
|
869
888
|
// If ID exists, load existing record
|
|
870
|
-
if (this.
|
|
871
|
-
const loaded = await agentEntity.Load(this.
|
|
889
|
+
if (this.Spec.ID) {
|
|
890
|
+
const loaded = await agentEntity.Load(this.Spec.ID);
|
|
872
891
|
if (!loaded) {
|
|
873
|
-
throw new Error(`Cannot update non-existent agent with ID ${this.
|
|
892
|
+
throw new Error(`Cannot update non-existent agent with ID ${this.Spec.ID}`);
|
|
874
893
|
}
|
|
875
894
|
}
|
|
876
895
|
|
|
877
896
|
// Map spec to entity fields
|
|
878
|
-
agentEntity.Name = this.
|
|
879
|
-
agentEntity.Description = this.
|
|
880
|
-
agentEntity.IconClass = this.
|
|
881
|
-
agentEntity.LogoURL = this.
|
|
882
|
-
agentEntity.ParentID = this.
|
|
883
|
-
agentEntity.DriverClass = this.
|
|
884
|
-
agentEntity.ModelSelectionMode = this.
|
|
897
|
+
agentEntity.Name = this.Spec.Name;
|
|
898
|
+
agentEntity.Description = this.Spec.Description || null;
|
|
899
|
+
agentEntity.IconClass = this.Spec.IconClass || null;
|
|
900
|
+
agentEntity.LogoURL = this.Spec.LogoURL || null;
|
|
901
|
+
agentEntity.ParentID = this.Spec.ParentID || null;
|
|
902
|
+
agentEntity.DriverClass = this.Spec.DriverClass || null;
|
|
903
|
+
agentEntity.ModelSelectionMode = this.Spec.ModelSelectionMode || 'Agent Type';
|
|
885
904
|
|
|
886
905
|
// Handle TypeID - supports lookup references or direct GUID
|
|
887
|
-
if ((this.
|
|
888
|
-
agentEntity.TypeID = (this.
|
|
906
|
+
if ((this.Spec as any).TypeID) {
|
|
907
|
+
agentEntity.TypeID = (this.Spec as any).TypeID;
|
|
889
908
|
}
|
|
890
909
|
|
|
891
910
|
// Handle Status - defaults to Active if not specified. Typed rather than cast: the cast is
|
|
892
911
|
// what let `'Inactive'` — a value the CHECK constraint rejects — reach the entity unchallenged.
|
|
893
|
-
agentEntity.Status = this.
|
|
912
|
+
agentEntity.Status = this.Spec.Status ?? 'Active';
|
|
894
913
|
|
|
895
914
|
// Serialize JSON fields
|
|
896
915
|
agentEntity.PayloadDownstreamPaths = JSON.stringify(
|
|
897
|
-
this.
|
|
916
|
+
this.Spec.PayloadDownstreamPaths || ['*']
|
|
898
917
|
);
|
|
899
918
|
agentEntity.PayloadUpstreamPaths = JSON.stringify(
|
|
900
|
-
this.
|
|
919
|
+
this.Spec.PayloadUpstreamPaths || ['*']
|
|
901
920
|
);
|
|
902
|
-
agentEntity.PayloadSelfReadPaths = this.
|
|
903
|
-
? JSON.stringify(this.
|
|
921
|
+
agentEntity.PayloadSelfReadPaths = this.Spec.PayloadSelfReadPaths
|
|
922
|
+
? JSON.stringify(this.Spec.PayloadSelfReadPaths)
|
|
904
923
|
: null;
|
|
905
|
-
agentEntity.PayloadSelfWritePaths = this.
|
|
906
|
-
? JSON.stringify(this.
|
|
924
|
+
agentEntity.PayloadSelfWritePaths = this.Spec.PayloadSelfWritePaths
|
|
925
|
+
? JSON.stringify(this.Spec.PayloadSelfWritePaths)
|
|
907
926
|
: null;
|
|
908
|
-
agentEntity.PayloadScope = this.
|
|
927
|
+
agentEntity.PayloadScope = this.Spec.PayloadScope || null;
|
|
909
928
|
|
|
910
929
|
// Validation fields
|
|
911
|
-
agentEntity.FinalPayloadValidation = this.
|
|
912
|
-
agentEntity.FinalPayloadValidationMode = this.
|
|
913
|
-
agentEntity.FinalPayloadValidationMaxRetries = this.
|
|
930
|
+
agentEntity.FinalPayloadValidation = this.Spec.FinalPayloadValidation || null;
|
|
931
|
+
agentEntity.FinalPayloadValidationMode = this.Spec.FinalPayloadValidationMode || 'Retry';
|
|
932
|
+
agentEntity.FinalPayloadValidationMaxRetries = this.Spec.FinalPayloadValidationMaxRetries || 3;
|
|
914
933
|
|
|
915
|
-
agentEntity.StartingPayloadValidation = this.
|
|
916
|
-
agentEntity.StartingPayloadValidationMode = this.
|
|
934
|
+
agentEntity.StartingPayloadValidation = this.Spec.StartingPayloadValidation || null;
|
|
935
|
+
agentEntity.StartingPayloadValidationMode = this.Spec.StartingPayloadValidationMode || 'Fail';
|
|
917
936
|
|
|
918
937
|
// Resource limits
|
|
919
|
-
agentEntity.MaxCostPerRun = this.
|
|
920
|
-
agentEntity.MaxTokensPerRun = this.
|
|
921
|
-
agentEntity.MaxIterationsPerRun = this.
|
|
922
|
-
agentEntity.MaxTimePerRun = this.
|
|
938
|
+
agentEntity.MaxCostPerRun = this.Spec.MaxCostPerRun || null;
|
|
939
|
+
agentEntity.MaxTokensPerRun = this.Spec.MaxTokensPerRun || null;
|
|
940
|
+
agentEntity.MaxIterationsPerRun = this.Spec.MaxIterationsPerRun || null;
|
|
941
|
+
agentEntity.MaxTimePerRun = this.Spec.MaxTimePerRun || null;
|
|
923
942
|
|
|
924
943
|
// Execution frequency
|
|
925
|
-
agentEntity.MinExecutionsPerRun = this.
|
|
926
|
-
agentEntity.MaxExecutionsPerRun = this.
|
|
944
|
+
agentEntity.MinExecutionsPerRun = this.Spec.MinExecutionsPerRun || null;
|
|
945
|
+
agentEntity.MaxExecutionsPerRun = this.Spec.MaxExecutionsPerRun || null;
|
|
927
946
|
|
|
928
947
|
// Other config
|
|
929
|
-
agentEntity.DefaultPromptEffortLevel = this.
|
|
930
|
-
agentEntity.ChatHandlingOption = this.
|
|
931
|
-
agentEntity.DefaultArtifactTypeID = this.
|
|
948
|
+
agentEntity.DefaultPromptEffortLevel = this.Spec.DefaultPromptEffortLevel || null;
|
|
949
|
+
agentEntity.ChatHandlingOption = this.Spec.ChatHandlingOption || null;
|
|
950
|
+
agentEntity.DefaultArtifactTypeID = this.Spec.DefaultArtifactTypeID || null;
|
|
932
951
|
|
|
933
952
|
// Set OwnerUserID - always use contextUser if available (user creating/modifying the agent)
|
|
934
953
|
if (this._contextUser) {
|
|
935
954
|
agentEntity.OwnerUserID = this._contextUser.ID;
|
|
936
|
-
} else if (this.
|
|
955
|
+
} else if (this.Spec.OwnerUserID) {
|
|
937
956
|
// Fallback to spec value if no contextUser provided
|
|
938
|
-
agentEntity.OwnerUserID = this.
|
|
957
|
+
agentEntity.OwnerUserID = this.Spec.OwnerUserID;
|
|
939
958
|
}
|
|
940
959
|
|
|
941
|
-
agentEntity.InvocationMode = this.
|
|
960
|
+
agentEntity.InvocationMode = this.Spec.InvocationMode || 'Any';
|
|
942
961
|
|
|
943
962
|
// Requirements and design documentation
|
|
944
|
-
agentEntity.FunctionalRequirements = this.
|
|
945
|
-
agentEntity.TechnicalDesign = this.
|
|
963
|
+
agentEntity.FunctionalRequirements = this.Spec.FunctionalRequirements || null;
|
|
964
|
+
agentEntity.TechnicalDesign = this.Spec.TechnicalDesign || null;
|
|
946
965
|
|
|
947
966
|
// Validate if requested
|
|
948
967
|
if (validate) {
|
|
@@ -960,14 +979,14 @@ export class AgentSpecSync {
|
|
|
960
979
|
}
|
|
961
980
|
|
|
962
981
|
// Update spec with saved ID
|
|
963
|
-
this.
|
|
982
|
+
this.Spec.ID = agentEntity.ID;
|
|
964
983
|
|
|
965
984
|
// Track the mutation
|
|
966
985
|
this.trackMutation(
|
|
967
986
|
'MJ: AI Agents',
|
|
968
987
|
isUpdate ? 'Update' : 'Create',
|
|
969
988
|
agentEntity.ID,
|
|
970
|
-
`${isUpdate ? 'Updated' : 'Created'} agent: ${this.
|
|
989
|
+
`${isUpdate ? 'Updated' : 'Created'} agent: ${this.Spec.Name}`
|
|
971
990
|
);
|
|
972
991
|
|
|
973
992
|
return agentEntity.ID;
|
|
@@ -985,13 +1004,13 @@ export class AgentSpecSync {
|
|
|
985
1004
|
* @throws {Error} If any action save fails
|
|
986
1005
|
*/
|
|
987
1006
|
private async saveActions(agentId: string): Promise<void> {
|
|
988
|
-
if (!this.
|
|
1007
|
+
if (!this.Spec.Actions || this.Spec.Actions.length === 0) {
|
|
989
1008
|
return;
|
|
990
1009
|
}
|
|
991
1010
|
|
|
992
1011
|
const md = this.providerToUse;
|
|
993
1012
|
|
|
994
|
-
for (const actionSpec of this.
|
|
1013
|
+
for (const actionSpec of this.Spec.Actions) {
|
|
995
1014
|
const actionEntity = await md.GetEntityObject<MJAIAgentActionEntity>(
|
|
996
1015
|
'MJ: AI Agent Actions',
|
|
997
1016
|
this._contextUser
|
|
@@ -1046,11 +1065,11 @@ export class AgentSpecSync {
|
|
|
1046
1065
|
* @throws {Error} If any sub-agent save fails
|
|
1047
1066
|
*/
|
|
1048
1067
|
private async saveSubAgents(agentId: string): Promise<void> {
|
|
1049
|
-
if (!this.
|
|
1068
|
+
if (!this.Spec.SubAgents || this.Spec.SubAgents.length === 0) {
|
|
1050
1069
|
return;
|
|
1051
1070
|
}
|
|
1052
1071
|
|
|
1053
|
-
for (const SubAgentSpec of this.
|
|
1072
|
+
for (const SubAgentSpec of this.Spec.SubAgents) {
|
|
1054
1073
|
if (SubAgentSpec.Type === 'child') {
|
|
1055
1074
|
await this.saveChildSubAgent(agentId, SubAgentSpec);
|
|
1056
1075
|
} else {
|
|
@@ -1194,20 +1213,20 @@ export class AgentSpecSync {
|
|
|
1194
1213
|
* @throws {Error} If any prompt save fails
|
|
1195
1214
|
*/
|
|
1196
1215
|
private async savePrompts(agentId: string): Promise<void> {
|
|
1197
|
-
console.log(`💬 savePrompts: Called with agentId=${agentId}, Prompts=${this.
|
|
1216
|
+
console.log(`💬 savePrompts: Called with agentId=${agentId}, Prompts=${this.Spec.Prompts ? this.Spec.Prompts.length : 'undefined'}`);
|
|
1198
1217
|
|
|
1199
|
-
if (!this.
|
|
1218
|
+
if (!this.Spec.Prompts || this.Spec.Prompts.length === 0) {
|
|
1200
1219
|
console.log('💬 savePrompts: No prompts to save, returning early');
|
|
1201
1220
|
return;
|
|
1202
1221
|
}
|
|
1203
1222
|
|
|
1204
|
-
console.log(`💬 savePrompts: Processing ${this.
|
|
1223
|
+
console.log(`💬 savePrompts: Processing ${this.Spec.Prompts.length} prompt(s)...`);
|
|
1205
1224
|
const md = this.providerToUse;
|
|
1206
1225
|
const rv = RunView.FromMetadataProvider(this._provider);
|
|
1207
1226
|
|
|
1208
1227
|
// Step 1: Create or update AIPrompt records
|
|
1209
|
-
for (let i = 0; i < this.
|
|
1210
|
-
const promptSpec = this.
|
|
1228
|
+
for (let i = 0; i < this.Spec.Prompts.length; i++) {
|
|
1229
|
+
const promptSpec = this.Spec.Prompts[i];
|
|
1211
1230
|
|
|
1212
1231
|
// Check if this is an update (has PromptID) or create (no PromptID)
|
|
1213
1232
|
let promptEntity = await md.GetEntityObject<any>(
|
|
@@ -1228,8 +1247,8 @@ export class AgentSpecSync {
|
|
|
1228
1247
|
}
|
|
1229
1248
|
|
|
1230
1249
|
// Set all required fields (both create and update)
|
|
1231
|
-
promptEntity.Name = `${this.
|
|
1232
|
-
promptEntity.Description = `Agent prompt ${i + 1} for ${this.
|
|
1250
|
+
promptEntity.Name = `${this.Spec.Name} - Prompt ${i + 1}`;
|
|
1251
|
+
promptEntity.Description = `Agent prompt ${i + 1} for ${this.Spec.Name}`;
|
|
1233
1252
|
promptEntity.TypeID = 'a6da423e-f36b-1410-8dac-00021f8b792e'; // Chat type
|
|
1234
1253
|
promptEntity.Status = 'Active';
|
|
1235
1254
|
promptEntity.ResponseFormat = 'JSON';
|
|
@@ -1257,7 +1276,7 @@ export class AgentSpecSync {
|
|
|
1257
1276
|
|
|
1258
1277
|
const saved = await promptEntity.Save();
|
|
1259
1278
|
if (!saved) {
|
|
1260
|
-
throw new Error(`Failed to save prompt ${i + 1} for agent ${this.
|
|
1279
|
+
throw new Error(`Failed to save prompt ${i + 1} for agent ${this.Spec.Name}`);
|
|
1261
1280
|
}
|
|
1262
1281
|
|
|
1263
1282
|
// Track mutation
|
|
@@ -1320,7 +1339,7 @@ export class AgentSpecSync {
|
|
|
1320
1339
|
console.log(`✅ savePrompts: ${isJunctionUpdate ? 'Updated' : 'Created'} AIAgentPrompt junction with ID: ${agentPromptEntity.ID}`);
|
|
1321
1340
|
}
|
|
1322
1341
|
|
|
1323
|
-
console.log(`✅ savePrompts: Successfully saved all ${this.
|
|
1342
|
+
console.log(`✅ savePrompts: Successfully saved all ${this.Spec.Prompts.length} prompt(s)`);
|
|
1324
1343
|
}
|
|
1325
1344
|
|
|
1326
1345
|
/**
|
|
@@ -1334,17 +1353,17 @@ export class AgentSpecSync {
|
|
|
1334
1353
|
* @throws {Error} If any step save fails
|
|
1335
1354
|
*/
|
|
1336
1355
|
private async saveSteps(agentId: string): Promise<void> {
|
|
1337
|
-
console.log(`🔷 saveSteps: Called with agentId=${agentId}, Steps=${this.
|
|
1356
|
+
console.log(`🔷 saveSteps: Called with agentId=${agentId}, Steps=${this.Spec.Steps ? this.Spec.Steps.length : 'undefined'}`);
|
|
1338
1357
|
|
|
1339
|
-
if (!this.
|
|
1358
|
+
if (!this.Spec.Steps || this.Spec.Steps.length === 0) {
|
|
1340
1359
|
console.log('🔷 saveSteps: No steps to save, returning early');
|
|
1341
1360
|
return;
|
|
1342
1361
|
}
|
|
1343
1362
|
|
|
1344
|
-
console.log(`🔷 saveSteps: Processing ${this.
|
|
1363
|
+
console.log(`🔷 saveSteps: Processing ${this.Spec.Steps.length} step(s)...`);
|
|
1345
1364
|
const md = this.providerToUse;
|
|
1346
1365
|
|
|
1347
|
-
for (const stepSpec of this.
|
|
1366
|
+
for (const stepSpec of this.Spec.Steps) {
|
|
1348
1367
|
const stepEntity = await md.GetEntityObject<MJAIAgentStepEntity>(
|
|
1349
1368
|
'MJ: AI Agent Steps',
|
|
1350
1369
|
this._contextUser
|
|
@@ -1438,7 +1457,7 @@ export class AgentSpecSync {
|
|
|
1438
1457
|
|
|
1439
1458
|
const saved = await stepEntity.Save();
|
|
1440
1459
|
if (!saved) {
|
|
1441
|
-
throw new Error(`Failed to save step "${stepSpec.Name}" for agent ${this.
|
|
1460
|
+
throw new Error(`Failed to save step "${stepSpec.Name}" for agent ${this.Spec.Name}`);
|
|
1442
1461
|
}
|
|
1443
1462
|
|
|
1444
1463
|
// Track mutation
|
|
@@ -1455,7 +1474,7 @@ export class AgentSpecSync {
|
|
|
1455
1474
|
console.log(`✅ saveSteps: Created AIAgentStep with ID: ${stepEntity.ID}`);
|
|
1456
1475
|
}
|
|
1457
1476
|
|
|
1458
|
-
console.log(`✅ saveSteps: Successfully saved all ${this.
|
|
1477
|
+
console.log(`✅ saveSteps: Successfully saved all ${this.Spec.Steps.length} step(s)`);
|
|
1459
1478
|
}
|
|
1460
1479
|
|
|
1461
1480
|
/**
|
|
@@ -1469,27 +1488,27 @@ export class AgentSpecSync {
|
|
|
1469
1488
|
* @throws {Error} If any path save fails
|
|
1470
1489
|
*/
|
|
1471
1490
|
private async saveStepPaths(agentId: string): Promise<void> {
|
|
1472
|
-
console.log(`🔶 saveStepPaths: Called with agentId=${agentId}, Paths=${this.
|
|
1491
|
+
console.log(`🔶 saveStepPaths: Called with agentId=${agentId}, Paths=${this.Spec.Paths ? this.Spec.Paths.length : 'undefined'}`);
|
|
1473
1492
|
|
|
1474
|
-
if (!this.
|
|
1493
|
+
if (!this.Spec.Paths || this.Spec.Paths.length === 0) {
|
|
1475
1494
|
console.log('🔶 saveStepPaths: No paths to save, returning early');
|
|
1476
1495
|
return;
|
|
1477
1496
|
}
|
|
1478
1497
|
|
|
1479
|
-
console.log(`🔶 saveStepPaths: Processing ${this.
|
|
1498
|
+
console.log(`🔶 saveStepPaths: Processing ${this.Spec.Paths.length} path(s)...`);
|
|
1480
1499
|
const md = this.providerToUse;
|
|
1481
1500
|
|
|
1482
1501
|
// Create a map of step names to IDs for easy lookup
|
|
1483
1502
|
const stepNameToId = new Map<string, string>();
|
|
1484
|
-
if (this.
|
|
1485
|
-
for (const step of this.
|
|
1503
|
+
if (this.Spec.Steps) {
|
|
1504
|
+
for (const step of this.Spec.Steps) {
|
|
1486
1505
|
if (step.ID) {
|
|
1487
1506
|
stepNameToId.set(step.Name, step.ID);
|
|
1488
1507
|
}
|
|
1489
1508
|
}
|
|
1490
1509
|
}
|
|
1491
1510
|
|
|
1492
|
-
for (const pathSpec of this.
|
|
1511
|
+
for (const pathSpec of this.Spec.Paths) {
|
|
1493
1512
|
const pathEntity = await md.GetEntityObject<MJAIAgentStepPathEntity>(
|
|
1494
1513
|
'MJ: AI Agent Step Paths',
|
|
1495
1514
|
this._contextUser
|
|
@@ -1541,7 +1560,7 @@ export class AgentSpecSync {
|
|
|
1541
1560
|
console.log(`✅ saveStepPaths: Created AIAgentStepPath with ID: ${pathEntity.ID}`);
|
|
1542
1561
|
}
|
|
1543
1562
|
|
|
1544
|
-
console.log(`✅ saveStepPaths: Successfully saved all ${this.
|
|
1563
|
+
console.log(`✅ saveStepPaths: Successfully saved all ${this.Spec.Paths.length} path(s)`);
|
|
1545
1564
|
}
|
|
1546
1565
|
|
|
1547
1566
|
// ===== UTILITY METHODS =====
|
|
@@ -1641,7 +1660,7 @@ export class AgentSpecSync {
|
|
|
1641
1660
|
* ```
|
|
1642
1661
|
*/
|
|
1643
1662
|
public toJSON(): AgentSpec {
|
|
1644
|
-
return { ...this.
|
|
1663
|
+
return { ...this.Spec };
|
|
1645
1664
|
}
|
|
1646
1665
|
|
|
1647
1666
|
/**
|
|
@@ -1649,19 +1668,29 @@ export class AgentSpecSync {
|
|
|
1649
1668
|
*
|
|
1650
1669
|
* @returns True if there are unsaved changes, false otherwise
|
|
1651
1670
|
*/
|
|
1652
|
-
public get
|
|
1671
|
+
public get IsDirty(): boolean {
|
|
1653
1672
|
return this._isDirty;
|
|
1654
1673
|
}
|
|
1655
1674
|
|
|
1675
|
+
/** @deprecated Use {@link IsDirty}. */
|
|
1676
|
+
public get isDirty(): boolean {
|
|
1677
|
+
return this.IsDirty;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1656
1680
|
/**
|
|
1657
1681
|
* Check if this spec has been loaded from the database.
|
|
1658
1682
|
*
|
|
1659
1683
|
* @returns True if loaded from database, false if created in memory
|
|
1660
1684
|
*/
|
|
1661
|
-
public get
|
|
1685
|
+
public get IsLoaded(): boolean {
|
|
1662
1686
|
return this._isLoaded;
|
|
1663
1687
|
}
|
|
1664
1688
|
|
|
1689
|
+
/** @deprecated Use {@link IsLoaded}. */
|
|
1690
|
+
public get isLoaded(): boolean {
|
|
1691
|
+
return this.IsLoaded;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1665
1694
|
/**
|
|
1666
1695
|
* Mark the spec as having changes.
|
|
1667
1696
|
*
|
|
@@ -1677,10 +1706,15 @@ export class AgentSpecSync {
|
|
|
1677
1706
|
* await spec.SaveToDatabase();
|
|
1678
1707
|
* ```
|
|
1679
1708
|
*/
|
|
1680
|
-
public
|
|
1709
|
+
public MarkDirty(): void {
|
|
1681
1710
|
this._isDirty = true;
|
|
1682
1711
|
}
|
|
1683
1712
|
|
|
1713
|
+
/** @deprecated Use {@link MarkDirty}. */
|
|
1714
|
+
public markDirty(): void {
|
|
1715
|
+
return this.MarkDirty();
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1684
1718
|
/**
|
|
1685
1719
|
* Mark the spec as having been loaded from the database.
|
|
1686
1720
|
*
|
|
@@ -1698,10 +1732,15 @@ export class AgentSpecSync {
|
|
|
1698
1732
|
* await childSync.SaveToDatabase();
|
|
1699
1733
|
* ```
|
|
1700
1734
|
*/
|
|
1701
|
-
public
|
|
1735
|
+
public MarkLoaded(): void {
|
|
1702
1736
|
this._isLoaded = true;
|
|
1703
1737
|
}
|
|
1704
1738
|
|
|
1739
|
+
/** @deprecated Use {@link MarkLoaded}. */
|
|
1740
|
+
public markLoaded(): void {
|
|
1741
|
+
return this.MarkLoaded();
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1705
1744
|
// ===== DELETE/ORPHAN METHODS =====
|
|
1706
1745
|
|
|
1707
1746
|
/**
|