@memberjunction/ng-tasks 5.30.1 → 5.31.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/ng-tasks@5.30.1 build
2
+ > @memberjunction/ng-tasks@5.31.0 build
3
3
  > ngc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @memberjunction/ng-tasks
2
2
 
3
+ ## 5.31.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 7ed7a4b: no metadata/migration changes
8
+ - 6779c1e: Lazy field hydration in BaseEntity + smarter engine startup (~30x warm-load speedup, ~14s to ~470ms). Defers per-row Field construction until something mutates or walks Fields, removes a speculative per-view fast-start path, adds a `deferred` flag to `@RegisterForStartup` and an `EnsureLoaded()` shortcut on `BaseEngine` / `AIEngine`. DeveloperModeService and WorkspaceStateManager swapped weak `Get`/`Set` calls for typed accessors. EnsureLoaded calls added at AI engine consumption sites.
9
+ - Updated dependencies [fc8b9b8]
10
+ - Updated dependencies [cde4d2c]
11
+ - Updated dependencies [7ed7a4b]
12
+ - Updated dependencies [60e7541]
13
+ - Updated dependencies [18be074]
14
+ - Updated dependencies [17b8087]
15
+ - Updated dependencies [6779c1e]
16
+ - Updated dependencies [de34786]
17
+ - Updated dependencies [5db36d9]
18
+ - Updated dependencies [0e3365f]
19
+ - @memberjunction/core-entities@5.31.0
20
+ - @memberjunction/ai-engine-base@5.31.0
21
+ - @memberjunction/ai-core-plus@5.31.0
22
+ - @memberjunction/ng-shared-generic@5.31.0
23
+ - @memberjunction/core@5.31.0
24
+ - @memberjunction/global@5.31.0
25
+
3
26
  ## 5.30.1
4
27
 
5
28
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"task-detail-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;;AAGvE;;;GAGG;AACH,qBA8Pa,wBAAyB,YAAW,MAAM,EAAE,SAAS;IACvD,IAAI,EAAG,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,UAAU,qBAA4B;IACtC,gBAAgB;oBAAkC,MAAM;kBAAY,MAAM;OAAM;IAEnF,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAQ;IAEpD,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;IAInB,OAAO,CAAC,aAAa;IAWd,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM;IAYzC,SAAS,IAAI,IAAI;IASjB,YAAY,IAAI,IAAI;yCAhDhB,wBAAwB;2CAAxB,wBAAwB;CAwDpC"}
1
+ {"version":3,"file":"task-detail-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1F,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;;AAGvE;;;GAGG;AACH,qBA8Pa,wBAAyB,YAAW,MAAM,EAAE,SAAS;IACvD,IAAI,EAAG,YAAY,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChC,UAAU,qBAA4B;IACtC,gBAAgB;oBAAkC,MAAM;kBAAY,MAAM;OAAM;IAEnF,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAQ;IAEpD,QAAQ,IAAI,IAAI;IAIhB,WAAW,IAAI,IAAI;YAIL,aAAa;IAYpB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM;IAYzC,SAAS,IAAI,IAAI;IASjB,YAAY,IAAI,IAAI;yCAjDhB,wBAAwB;2CAAxB,wBAAwB;CAyDpC"}
@@ -128,12 +128,13 @@ export class TaskDetailPanelComponent {
128
128
  ngOnChanges() {
129
129
  this.loadAgentInfo();
130
130
  }
131
- loadAgentInfo() {
131
+ async loadAgentInfo() {
132
132
  if (!this.task?.AgentID) {
133
133
  this.agent = null;
134
134
  return;
135
135
  }
136
- // Get agent from AIEngineBase
136
+ // AIEngineBase is deferred at startup; ensure loaded before reading .Agents.
137
+ await AIEngineBase.Instance.EnsureLoaded();
137
138
  const agents = AIEngineBase.Instance.Agents;
138
139
  this.agent = agents.find((a) => UUIDsEqual(a.ID, this.task.AgentID)) || null;
139
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"task-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from '@angular/core';\n\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Task detail panel showing task information, agent details, and agent run\n * Reusable across list and Gantt views\n */\n@Component({\n selector: 'mj-task-detail-panel',\n standalone: true,\n imports: [],\n template: `\n <div class=\"task-detail-panel\">\n <div class=\"detail-header\">\n <h3>{{ task.Name }}</h3>\n <button class=\"close-detail-btn\" (click)=\"closePanel.emit()\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n \n <div class=\"detail-content\">\n @if (task.Description) {\n <div class=\"detail-field\">\n <label>Description</label>\n <p>{{ task.Description }}</p>\n </div>\n }\n \n <div class=\"detail-field\">\n <label>Status</label>\n <p>{{ task.Status }}</p>\n </div>\n \n @if (task.PercentComplete != null) {\n <div class=\"detail-field\">\n <label>Progress</label>\n <div class=\"detail-progress\">\n <div class=\"progress-bar-detail\">\n <div class=\"progress-fill-detail\" [style.width.%]=\"task.PercentComplete\"></div>\n </div>\n <span>{{ task.PercentComplete }}%</span>\n </div>\n </div>\n }\n \n @if (task.StartedAt) {\n <div class=\"detail-field\">\n <label>Started</label>\n <p>{{ formatDateTime(task.StartedAt) }}</p>\n </div>\n }\n \n @if (task.DueAt) {\n <div class=\"detail-field\">\n <label>Due</label>\n <p>{{ formatDateTime(task.DueAt) }}</p>\n </div>\n }\n \n @if (task.CompletedAt) {\n <div class=\"detail-field\">\n <label>Completed</label>\n <p>{{ formatDateTime(task.CompletedAt) }}</p>\n </div>\n }\n \n @if (task.User) {\n <div class=\"detail-field\">\n <label>Assigned User</label>\n <p>{{ task.User }}</p>\n </div>\n }\n \n <!-- Agent Information -->\n @if (agent) {\n <div class=\"detail-field\">\n <label>Agent</label>\n <div class=\"agent-info\" (click)=\"openAgent()\">\n <i [class]=\"'fas fa-' + ('robot')\" class=\"agent-icon\"></i>\n <span class=\"agent-name\">{{ agent.Name }}</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n \n <!-- Agent Run Information -->\n @if (agentRunId) {\n <div class=\"detail-field\">\n <label>Agent Run</label>\n <div class=\"agent-run-link\" (click)=\"openAgentRun()\">\n <span>View Run Details</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: var(--mj-border-default);\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: var(--mj-border-default);\n }\n\n .agent-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .link-icon {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: var(--mj-border-default);\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n `]\n})\nexport class TaskDetailPanelComponent implements OnInit, OnChanges {\n @Input() task!: MJTaskEntity;\n @Input() agentRunId: string | null = null;\n @Output() closePanel = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public agent: MJAIAgentEntityExtended | null = null;\n\n ngOnInit(): void {\n this.loadAgentInfo();\n }\n\n ngOnChanges(): void {\n this.loadAgentInfo();\n }\n\n private loadAgentInfo(): void {\n if (!this.task?.AgentID) {\n this.agent = null;\n return;\n }\n\n // Get agent from AIEngineBase\n const agents = AIEngineBase.Instance.Agents;\n this.agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.task.AgentID)) || null;\n }\n\n public formatDateTime(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public openAgent(): void {\n if (this.task.AgentID) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agents',\n recordId: this.task.AgentID\n });\n }\n }\n\n public openAgentRun(): void {\n if (this.agentRunId) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agent Runs',\n recordId: this.agentRunId\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"task-detail-panel.component.js","sourceRoot":"","sources":["../../../src/lib/components/task-detail-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges } from '@angular/core';\n\nimport { MJTaskEntity } from '@memberjunction/core-entities';\nimport { AIEngineBase } from '@memberjunction/ai-engine-base';\nimport { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';\nimport { UUIDsEqual } from '@memberjunction/global';\n\n/**\n * Task detail panel showing task information, agent details, and agent run\n * Reusable across list and Gantt views\n */\n@Component({\n selector: 'mj-task-detail-panel',\n standalone: true,\n imports: [],\n template: `\n <div class=\"task-detail-panel\">\n <div class=\"detail-header\">\n <h3>{{ task.Name }}</h3>\n <button class=\"close-detail-btn\" (click)=\"closePanel.emit()\">\n <i class=\"fas fa-times\"></i>\n </button>\n </div>\n \n <div class=\"detail-content\">\n @if (task.Description) {\n <div class=\"detail-field\">\n <label>Description</label>\n <p>{{ task.Description }}</p>\n </div>\n }\n \n <div class=\"detail-field\">\n <label>Status</label>\n <p>{{ task.Status }}</p>\n </div>\n \n @if (task.PercentComplete != null) {\n <div class=\"detail-field\">\n <label>Progress</label>\n <div class=\"detail-progress\">\n <div class=\"progress-bar-detail\">\n <div class=\"progress-fill-detail\" [style.width.%]=\"task.PercentComplete\"></div>\n </div>\n <span>{{ task.PercentComplete }}%</span>\n </div>\n </div>\n }\n \n @if (task.StartedAt) {\n <div class=\"detail-field\">\n <label>Started</label>\n <p>{{ formatDateTime(task.StartedAt) }}</p>\n </div>\n }\n \n @if (task.DueAt) {\n <div class=\"detail-field\">\n <label>Due</label>\n <p>{{ formatDateTime(task.DueAt) }}</p>\n </div>\n }\n \n @if (task.CompletedAt) {\n <div class=\"detail-field\">\n <label>Completed</label>\n <p>{{ formatDateTime(task.CompletedAt) }}</p>\n </div>\n }\n \n @if (task.User) {\n <div class=\"detail-field\">\n <label>Assigned User</label>\n <p>{{ task.User }}</p>\n </div>\n }\n \n <!-- Agent Information -->\n @if (agent) {\n <div class=\"detail-field\">\n <label>Agent</label>\n <div class=\"agent-info\" (click)=\"openAgent()\">\n <i [class]=\"'fas fa-' + ('robot')\" class=\"agent-icon\"></i>\n <span class=\"agent-name\">{{ agent.Name }}</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n \n <!-- Agent Run Information -->\n @if (agentRunId) {\n <div class=\"detail-field\">\n <label>Agent Run</label>\n <div class=\"agent-run-link\" (click)=\"openAgentRun()\">\n <span>View Run Details</span>\n <i class=\"fas fa-external-link-alt link-icon\"></i>\n </div>\n </div>\n }\n </div>\n </div>\n `,\n styles: [`\n .task-detail-panel {\n width: 100%;\n height: calc(100% - 45px);\n background: var(--mj-bg-surface);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n .detail-header {\n padding: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n }\n\n .detail-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n padding-right: 12px;\n }\n\n .close-detail-btn {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px;\n width: 28px;\n height: 28px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .close-detail-btn:hover {\n background: var(--mj-border-default);\n color: var(--mj-text-primary);\n }\n\n .detail-content {\n padding: 20px;\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n }\n\n .detail-field {\n margin-bottom: 20px;\n }\n\n .detail-field:last-child {\n margin-bottom: 0;\n }\n\n .detail-field label {\n display: block;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 6px;\n }\n\n .detail-field p {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-primary);\n line-height: 1.5;\n }\n\n .detail-progress {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .progress-bar-detail {\n flex: 1;\n height: 8px;\n background: var(--mj-border-default);\n border-radius: 4px;\n overflow: hidden;\n }\n\n .progress-fill-detail {\n height: calc(100% - 69px);\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n .detail-progress span {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-muted);\n min-width: 40px;\n }\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-info:hover {\n background: var(--mj-border-default);\n }\n\n .agent-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n }\n\n .agent-name {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .link-icon {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .agent-run-link {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .agent-run-link:hover {\n background: var(--mj-border-default);\n }\n\n .agent-run-link span {\n flex: 1;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n `]\n})\nexport class TaskDetailPanelComponent implements OnInit, OnChanges {\n @Input() task!: MJTaskEntity;\n @Input() agentRunId: string | null = null;\n @Output() closePanel = new EventEmitter<void>();\n @Output() openEntityRecord = new EventEmitter<{ entityName: string; recordId: string }>();\n\n public agent: MJAIAgentEntityExtended | null = null;\n\n ngOnInit(): void {\n this.loadAgentInfo();\n }\n\n ngOnChanges(): void {\n this.loadAgentInfo();\n }\n\n private async loadAgentInfo(): Promise<void> {\n if (!this.task?.AgentID) {\n this.agent = null;\n return;\n }\n\n // AIEngineBase is deferred at startup; ensure loaded before reading .Agents.\n await AIEngineBase.Instance.EnsureLoaded();\n const agents = AIEngineBase.Instance.Agents;\n this.agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.task.AgentID)) || null;\n }\n\n public formatDateTime(date: Date | null): string {\n if (!date) return '';\n const d = new Date(date);\n return d.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n }\n\n public openAgent(): void {\n if (this.task.AgentID) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agents',\n recordId: this.task.AgentID\n });\n }\n }\n\n public openAgentRun(): void {\n if (this.agentRunId) {\n this.openEntityRecord.emit({\n entityName: 'MJ: AI Agent Runs',\n recordId: this.agentRunId\n });\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-tasks",
3
- "version": "5.30.1",
3
+ "version": "5.31.0",
4
4
  "description": "MemberJunction: Angular components for task visualization and management with Gantt chart support",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,12 +15,12 @@
15
15
  "@angular/common": "21.1.3",
16
16
  "@angular/core": "21.1.3",
17
17
  "@angular/platform-browser": "21.1.3",
18
- "@memberjunction/ai-core-plus": "5.30.1",
19
- "@memberjunction/ai-engine-base": "5.30.1",
20
- "@memberjunction/core": "5.30.1",
21
- "@memberjunction/core-entities": "5.30.1",
22
- "@memberjunction/global": "5.30.1",
23
- "@memberjunction/ng-shared-generic": "5.30.1",
18
+ "@memberjunction/ai-core-plus": "5.31.0",
19
+ "@memberjunction/ai-engine-base": "5.31.0",
20
+ "@memberjunction/core": "5.31.0",
21
+ "@memberjunction/core-entities": "5.31.0",
22
+ "@memberjunction/global": "5.31.0",
23
+ "@memberjunction/ng-shared-generic": "5.31.0",
24
24
  "dhtmlx-gantt": "^9.1.1",
25
25
  "rxjs": "^7.8.2"
26
26
  },
@@ -279,13 +279,14 @@ export class TaskDetailPanelComponent implements OnInit, OnChanges {
279
279
  this.loadAgentInfo();
280
280
  }
281
281
 
282
- private loadAgentInfo(): void {
282
+ private async loadAgentInfo(): Promise<void> {
283
283
  if (!this.task?.AgentID) {
284
284
  this.agent = null;
285
285
  return;
286
286
  }
287
287
 
288
- // Get agent from AIEngineBase
288
+ // AIEngineBase is deferred at startup; ensure loaded before reading .Agents.
289
+ await AIEngineBase.Instance.EnsureLoaded();
289
290
  const agents = AIEngineBase.Instance.Agents;
290
291
  this.agent = agents.find((a: MJAIAgentEntityExtended) => UUIDsEqual(a.ID, this.task.AgentID)) || null;
291
292
  }