@memberjunction/ng-core-entity-forms 6.2.0-edge.0 → 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/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.d.ts +1 -1
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js +2 -2
- package/dist/lib/custom/AIAgentCategories/ai-agent-category-overview.panel.js.map +1 -1
- package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts +90 -16
- package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js +218 -70
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts +80 -16
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +146 -46
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +329 -27
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +794 -262
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts +76 -0
- package/dist/lib/custom/AIAgents/ai-agent-management.service.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-management.service.js +77 -33
- package/dist/lib/custom/AIAgents/ai-agent-management.service.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts +69 -15
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +182 -74
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts +105 -25
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +272 -112
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts +32 -6
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +71 -19
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts +10 -0
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.js +27 -7
- package/dist/lib/custom/AIAgents/new-agent-dialog.service.js.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts +65 -15
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +152 -52
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts +81 -15
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +145 -45
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts +71 -17
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +175 -67
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +173 -27
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +385 -93
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.d.ts +64 -4
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +129 -29
- package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts +260 -27
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +686 -238
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts +10 -0
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js +17 -9
- package/dist/lib/custom/AIPrompts/ai-prompt-management.service.js.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts +74 -16
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js +174 -58
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts +108 -14
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +258 -70
- package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts +198 -14
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +387 -107
- package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
- package/dist/lib/custom/BridgeProviders/bridge-provider-features.d.ts +12 -6
- package/dist/lib/custom/BridgeProviders/bridge-provider-features.d.ts.map +1 -1
- package/dist/lib/custom/BridgeProviders/bridge-provider-features.js +41 -29
- package/dist/lib/custom/BridgeProviders/bridge-provider-features.js.map +1 -1
- package/dist/lib/custom/BridgeProviders/bridge-provider-form.component.js +14 -14
- package/dist/lib/custom/BridgeProviders/bridge-provider-form.component.js.map +1 -1
- package/dist/lib/custom/Companies/company-overview.panel.d.ts +1 -1
- package/dist/lib/custom/Companies/company-overview.panel.js +2 -2
- package/dist/lib/custom/Companies/company-overview.panel.js.map +1 -1
- package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts +1 -1
- package/dist/lib/custom/Conversations/conversation-overview.panel.js +2 -2
- package/dist/lib/custom/Conversations/conversation-overview.panel.js.map +1 -1
- package/dist/lib/custom/Employees/employee-overview.panel.d.ts +1 -1
- package/dist/lib/custom/Employees/employee-overview.panel.js +2 -2
- package/dist/lib/custom/Employees/employee-overview.panel.js.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.d.ts +209 -28
- package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.js +494 -138
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts +5 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.d.ts.map +1 -1
- package/dist/lib/custom/EntityActions/entityaction.form.component.js +10 -2
- package/dist/lib/custom/EntityActions/entityaction.form.component.js.map +1 -1
- package/dist/lib/custom/Files/file-form.component.d.ts +1 -1
- package/dist/lib/custom/Files/file-form.component.js +2 -2
- package/dist/lib/custom/Files/file-form.component.js.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.d.ts +300 -36
- package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Lists/list-form.component.js +664 -208
- package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts +31 -0
- package/dist/lib/custom/MLModels/ml-model-view-models.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ml-model-view-models.js +52 -16
- package/dist/lib/custom/MLModels/ml-model-view-models.js.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts +107 -10
- package/dist/lib/custom/MLModels/ps-model-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/MLModels/ps-model-detail.component.js +291 -101
- package/dist/lib/custom/MLModels/ps-model-detail.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts +201 -26
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +429 -109
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.d.ts +107 -14
- package/dist/lib/custom/Queries/query-run-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.js +249 -79
- package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
- package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts +110 -4
- package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
- package/dist/lib/custom/RecordProcesses/record-process-form.component.js +858 -86
- package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts +1 -1
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js +4 -4
- package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
- package/dist/lib/custom/SessionBridges/session-bridge-form.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-param-dialog.component.d.ts +77 -13
- package/dist/lib/custom/Templates/template-param-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/template-param-dialog.component.js +196 -78
- package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.d.ts +49 -7
- package/dist/lib/custom/Templates/template-params-grid.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.js +132 -44
- package/dist/lib/custom/Templates/template-params-grid.component.js.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.d.ts +142 -17
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +333 -113
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/entity-link-pill.component.d.ts +24 -4
- package/dist/lib/custom/Tests/entity-link-pill.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/entity-link-pill.component.js +64 -20
- package/dist/lib/custom/Tests/entity-link-pill.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.d.ts +217 -27
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +549 -169
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-checks.d.ts +2 -0
- package/dist/lib/custom/Tests/test-run-checks.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-checks.js +5 -1
- package/dist/lib/custom/Tests/test-run-checks.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-feedback-form.component.d.ts +2 -0
- package/dist/lib/custom/Tests/test-run-feedback-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-feedback-form.component.js +5 -1
- package/dist/lib/custom/Tests/test-run-feedback-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.d.ts +146 -18
- package/dist/lib/custom/Tests/test-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-run-form.component.js +362 -106
- package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts +390 -47
- package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +1015 -343
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts +214 -26
- package/dist/lib/custom/Tests/test-suite-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-suite-run-form.component.js +535 -159
- package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
- package/dist/lib/custom/Users/user-overview.panel.d.ts +1 -1
- package/dist/lib/custom/Users/user-overview.panel.js +2 -2
- package/dist/lib/custom/Users/user-overview.panel.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +208 -29
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +446 -138
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.d.ts +6 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js +16 -4
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts +50 -6
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +84 -12
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts +89 -5
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +216 -70
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts +62 -3
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js +140 -42
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts +81 -10
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +165 -37
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +140 -15
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +326 -100
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts +101 -15
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js +281 -97
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts +43 -25
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js +100 -64
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts +14 -2
- package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/constellation.component.js +71 -53
- package/dist/lib/custom/ai-agent-run/flow/constellation.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts +14 -2
- package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js +70 -52
- package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts +8 -0
- package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js +22 -6
- package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts +24 -2
- package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js +91 -59
- package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts +10 -2
- package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js +33 -17
- package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts +2 -0
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js +34 -30
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts +14 -2
- package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js +69 -51
- package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts +38 -12
- package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.js +103 -51
- package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +59 -51
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js +76 -74
- package/dist/lib/generated/Entities/MJAIVendor/mjaivendor.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJProject/mjproject.form.component.js +27 -25
- package/dist/lib/generated/Entities/MJProject/mjproject.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +155 -119
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts +5 -1
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts.map +1 -1
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js +11 -3
- package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js.map +1 -1
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.d.ts +2 -0
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.d.ts.map +1 -1
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js +16 -12
- package/dist/lib/panels/content-sources/tag-pipeline-configuration.panel.js.map +1 -1
- package/dist/lib/panels/content-sources/website-crawler-settings.panel.d.ts +1 -1
- package/dist/lib/panels/content-sources/website-crawler-settings.panel.js +2 -2
- package/dist/lib/panels/content-sources/website-crawler-settings.panel.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +45 -19
- package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.logic.js +95 -43
- package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +20 -16
- package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -1
- package/dist/lib/panels/model-predictions/model-prediction.panel.js +73 -65
- package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.d.ts +133 -14
- package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +322 -124
- package/dist/lib/shared/components/template-editor.component.js.map +1 -1
- package/package.json +43 -42
|
@@ -2483,13 +2483,13 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2483
2483
|
constructor() {
|
|
2484
2484
|
super(...arguments);
|
|
2485
2485
|
/** Toolbar config — hide right-hand section controls since this form has a custom layout */
|
|
2486
|
-
this.
|
|
2486
|
+
this.ToolbarConfig = CUSTOM_LAYOUT_TOOLBAR_CONFIG;
|
|
2487
2487
|
/** Subject for managing component lifecycle and cleaning up subscriptions */
|
|
2488
2488
|
this.destroy$ = new Subject();
|
|
2489
2489
|
/** Track active timeouts for cleanup */
|
|
2490
2490
|
this.activeTimeouts = [];
|
|
2491
2491
|
/** The agent type entity for this agent */
|
|
2492
|
-
this.
|
|
2492
|
+
this.AgentType = null;
|
|
2493
2493
|
/** Reference to the dynamically loaded custom section component */
|
|
2494
2494
|
this.customSectionComponent = null;
|
|
2495
2495
|
/** Track if custom section has been loaded to avoid reloading */
|
|
@@ -2498,44 +2498,44 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2498
2498
|
this.customSectionComponentRef = null;
|
|
2499
2499
|
// === Related Entity Data for Display ===
|
|
2500
2500
|
/** Array of sub-agent entities for card display (DEPRECATED - use allSubAgents) */
|
|
2501
|
-
this.
|
|
2501
|
+
this.SubAgents = [];
|
|
2502
2502
|
/** Unified sub-agent data (both child and related) */
|
|
2503
2503
|
this.allSubAgents = [];
|
|
2504
2504
|
/** Current filter for sub-agents display */
|
|
2505
|
-
this.
|
|
2505
|
+
this.SubAgentFilter = 'all';
|
|
2506
2506
|
/** Array of agent prompt entities for card display */
|
|
2507
|
-
this.
|
|
2507
|
+
this.AgentPrompts = [];
|
|
2508
2508
|
/** Array of agent action entities for card display */
|
|
2509
|
-
this.
|
|
2509
|
+
this.AgentActions = [];
|
|
2510
2510
|
/** Array of learning cycle entities for display */
|
|
2511
|
-
this.
|
|
2511
|
+
this.LearningCycles = [];
|
|
2512
2512
|
/** Array of agent note entities for display */
|
|
2513
|
-
this.
|
|
2513
|
+
this.AgentNotes = [];
|
|
2514
2514
|
/** Array of recent execution records for history display */
|
|
2515
|
-
this.
|
|
2516
|
-
this.
|
|
2515
|
+
this.RecentExecutions = [];
|
|
2516
|
+
this.TotalExecutionHistoryCount = 0;
|
|
2517
2517
|
/** Track which execution cards are expanded */
|
|
2518
|
-
this.
|
|
2518
|
+
this.ExpandedExecutions = {};
|
|
2519
2519
|
/** Search functionality for execution history */
|
|
2520
|
-
this.
|
|
2521
|
-
this.
|
|
2520
|
+
this.ExecutionSearchText = '';
|
|
2521
|
+
this.FilteredExecutions = [];
|
|
2522
2522
|
/** Which record type the Execution History section shows: agent runs (default) or realtime voice sessions */
|
|
2523
|
-
this.
|
|
2523
|
+
this.ExecutionHistoryView = 'runs';
|
|
2524
2524
|
/** Voice/realtime sessions where this agent is the co-agent or the delegation target */
|
|
2525
|
-
this.
|
|
2526
|
-
this.
|
|
2527
|
-
this.
|
|
2525
|
+
this.AgentSessions = [];
|
|
2526
|
+
this.TotalSessionCount = 0;
|
|
2527
|
+
this.LoadingSessions = false;
|
|
2528
2528
|
/** Pagination state for execution history */
|
|
2529
|
-
this.
|
|
2530
|
-
this.
|
|
2531
|
-
this.
|
|
2529
|
+
this.ExecutionHistoryPageSize = 20;
|
|
2530
|
+
this.ExecutionHistoryCurrentPage = 1;
|
|
2531
|
+
this.IsLoadingPage = false;
|
|
2532
2532
|
/** Cache all loaded execution records for pagination */
|
|
2533
2533
|
this.allLoadedExecutions = [];
|
|
2534
2534
|
// === Loading States ===
|
|
2535
2535
|
/** Main loading state for initial data load */
|
|
2536
|
-
this.
|
|
2536
|
+
this.IsLoadingData = true;
|
|
2537
2537
|
/** Individual loading states for each section, start off true until loading complete */
|
|
2538
|
-
this.
|
|
2538
|
+
this.LoadingStates = {
|
|
2539
2539
|
executionHistory: true,
|
|
2540
2540
|
subAgents: true,
|
|
2541
2541
|
prompts: true,
|
|
@@ -2599,18 +2599,18 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2599
2599
|
this.FormTabs = [];
|
|
2600
2600
|
// === Dropdown Data ===
|
|
2601
2601
|
/** Model selection mode options for the dropdown */
|
|
2602
|
-
this.
|
|
2602
|
+
this.ModelSelectionModes = [
|
|
2603
2603
|
{ text: 'Agent Type', value: 'Agent Type' },
|
|
2604
2604
|
{ text: 'Agent', value: 'Agent' }
|
|
2605
2605
|
];
|
|
2606
2606
|
/** Agent status options for the dropdown */
|
|
2607
|
-
this.
|
|
2607
|
+
this.StatusOptions = [
|
|
2608
2608
|
{ text: 'Active', value: 'Active' },
|
|
2609
2609
|
{ text: 'Pending', value: 'Pending' },
|
|
2610
2610
|
{ text: 'Disabled', value: 'Disabled' }
|
|
2611
2611
|
];
|
|
2612
2612
|
/** Agent types loaded from the database */
|
|
2613
|
-
this.
|
|
2613
|
+
this.AgentTypes = [];
|
|
2614
2614
|
/** TreeDropdown configuration for the agent category field */
|
|
2615
2615
|
this.CategoryBranchConfig = {
|
|
2616
2616
|
EntityName: 'MJ: AI Agent Categories',
|
|
@@ -2623,7 +2623,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2623
2623
|
/** Current category selection for the TreeDropdown */
|
|
2624
2624
|
this.SelectedCategoryKey = null;
|
|
2625
2625
|
/** Currently selected context compression prompt */
|
|
2626
|
-
this.
|
|
2626
|
+
this.SelectedContextCompressionPrompt = null;
|
|
2627
2627
|
// === Permission Checks for Related Entities ===
|
|
2628
2628
|
/** Cache for permission checks to avoid repeated calculations */
|
|
2629
2629
|
this._permissionCache = new Map();
|
|
@@ -2639,7 +2639,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2639
2639
|
*/
|
|
2640
2640
|
this.IsFormInitializing = true;
|
|
2641
2641
|
/** Flag to indicate if there are unsaved changes */
|
|
2642
|
-
this.
|
|
2642
|
+
this.HasUnsavedChanges = false;
|
|
2643
2643
|
// Emergency circuit breaker to prevent infinite loops
|
|
2644
2644
|
this._changeDetectionCount = 0;
|
|
2645
2645
|
// === Original State for Cancel/Revert ===
|
|
@@ -2671,6 +2671,10 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2671
2671
|
this.isPerformingCancel = false;
|
|
2672
2672
|
}
|
|
2673
2673
|
static { MJAIAgentFormComponentExtended_1 = this; }
|
|
2674
|
+
/** @deprecated Use {@link ToolbarConfig}. */
|
|
2675
|
+
get toolbarConfig() {
|
|
2676
|
+
return this.ToolbarConfig;
|
|
2677
|
+
}
|
|
2674
2678
|
/** Custom-layout AI Agent form looks best full-width on first open. */
|
|
2675
2679
|
getDefaultFormWidthMode() { return 'full-width'; }
|
|
2676
2680
|
/** Helper method to create tracked setTimeout calls */
|
|
@@ -2690,16 +2694,32 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2690
2694
|
this.activeTimeouts.splice(index, 1);
|
|
2691
2695
|
}
|
|
2692
2696
|
}
|
|
2693
|
-
set
|
|
2697
|
+
set CustomSectionContainer(container) {
|
|
2694
2698
|
this._customSectionContainer = container;
|
|
2695
2699
|
// When the container becomes available, load the custom section if needed
|
|
2696
|
-
if (container && this.
|
|
2700
|
+
if (container && this.AgentType?.UIFormSectionKey && !this.customSectionLoaded) {
|
|
2697
2701
|
this.setTrackedTimeout(() => this.loadCustomFormSection(), 0);
|
|
2698
2702
|
}
|
|
2699
2703
|
}
|
|
2700
|
-
get
|
|
2704
|
+
get CustomSectionContainer() {
|
|
2701
2705
|
return this._customSectionContainer;
|
|
2702
2706
|
}
|
|
2707
|
+
/** @deprecated Use {@link CustomSectionContainer} instead. */
|
|
2708
|
+
set customSectionContainer(container) {
|
|
2709
|
+
this.CustomSectionContainer = container;
|
|
2710
|
+
}
|
|
2711
|
+
/** @deprecated Use {@link CustomSectionContainer} instead. */
|
|
2712
|
+
get customSectionContainer() {
|
|
2713
|
+
return this.CustomSectionContainer;
|
|
2714
|
+
}
|
|
2715
|
+
/** @deprecated Use {@link AgentType}. */
|
|
2716
|
+
get agentType() {
|
|
2717
|
+
return this.AgentType;
|
|
2718
|
+
}
|
|
2719
|
+
/** @deprecated Use {@link AgentType}. */
|
|
2720
|
+
set agentType(value) {
|
|
2721
|
+
this.AgentType = value;
|
|
2722
|
+
}
|
|
2703
2723
|
/** Update custom section when EditMode changes */
|
|
2704
2724
|
ngDoCheck() {
|
|
2705
2725
|
if (this.customSectionComponent && this.customSectionComponent.EditMode !== this.EditMode) {
|
|
@@ -2708,44 +2728,96 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2708
2728
|
}
|
|
2709
2729
|
// === Related Entity Counts ===
|
|
2710
2730
|
/** Number of sub-agents under this agent (for backward compatibility) */
|
|
2711
|
-
get
|
|
2731
|
+
get SubAgentCount() {
|
|
2712
2732
|
return this.allSubAgents.length;
|
|
2713
2733
|
}
|
|
2734
|
+
/** @deprecated Use {@link SubAgentCount}. */
|
|
2735
|
+
get subAgentCount() {
|
|
2736
|
+
return this.SubAgentCount;
|
|
2737
|
+
}
|
|
2714
2738
|
/** Number of child sub-agents (ParentID-based) */
|
|
2715
|
-
get
|
|
2739
|
+
get ChildSubAgentCount() {
|
|
2716
2740
|
return this.allSubAgents.filter(s => s.type === 'child').length;
|
|
2717
2741
|
}
|
|
2742
|
+
/** @deprecated Use {@link ChildSubAgentCount}. */
|
|
2743
|
+
get childSubAgentCount() {
|
|
2744
|
+
return this.ChildSubAgentCount;
|
|
2745
|
+
}
|
|
2718
2746
|
/** Number of related sub-agents (Relationship-based) */
|
|
2719
|
-
get
|
|
2747
|
+
get RelatedSubAgentCount() {
|
|
2720
2748
|
return this.allSubAgents.filter(s => s.type === 'related').length;
|
|
2721
2749
|
}
|
|
2750
|
+
/** @deprecated Use {@link RelatedSubAgentCount}. */
|
|
2751
|
+
get relatedSubAgentCount() {
|
|
2752
|
+
return this.RelatedSubAgentCount;
|
|
2753
|
+
}
|
|
2722
2754
|
/** Total number of sub-agents across both types */
|
|
2723
|
-
get
|
|
2755
|
+
get TotalSubAgentCount() {
|
|
2724
2756
|
return this.allSubAgents.length;
|
|
2725
2757
|
}
|
|
2758
|
+
/** @deprecated Use {@link TotalSubAgentCount}. */
|
|
2759
|
+
get totalSubAgentCount() {
|
|
2760
|
+
return this.TotalSubAgentCount;
|
|
2761
|
+
}
|
|
2726
2762
|
/** Number of prompts associated with this agent */
|
|
2763
|
+
get PromptCount() {
|
|
2764
|
+
return this.AgentPrompts.length;
|
|
2765
|
+
}
|
|
2766
|
+
/** @deprecated Use {@link PromptCount}. */
|
|
2727
2767
|
get promptCount() {
|
|
2728
|
-
return this.
|
|
2768
|
+
return this.PromptCount;
|
|
2729
2769
|
}
|
|
2730
2770
|
/** Number of actions configured for this agent */
|
|
2771
|
+
get ActionCount() {
|
|
2772
|
+
return this.AgentActions.length;
|
|
2773
|
+
}
|
|
2774
|
+
/** @deprecated Use {@link ActionCount}. */
|
|
2731
2775
|
get actionCount() {
|
|
2732
|
-
return this.
|
|
2776
|
+
return this.ActionCount;
|
|
2733
2777
|
}
|
|
2734
2778
|
/** Number of learning cycles for this agent */
|
|
2779
|
+
get LearningCycleCount() {
|
|
2780
|
+
return this.LearningCycles.length;
|
|
2781
|
+
}
|
|
2782
|
+
/** @deprecated Use {@link LearningCycleCount}. */
|
|
2735
2783
|
get learningCycleCount() {
|
|
2736
|
-
return this.
|
|
2784
|
+
return this.LearningCycleCount;
|
|
2737
2785
|
}
|
|
2738
2786
|
/** Number of notes associated with this agent */
|
|
2787
|
+
get NoteCount() {
|
|
2788
|
+
return this.AgentNotes.length;
|
|
2789
|
+
}
|
|
2790
|
+
/** @deprecated Use {@link NoteCount}. */
|
|
2739
2791
|
get noteCount() {
|
|
2740
|
-
return this.
|
|
2792
|
+
return this.NoteCount;
|
|
2741
2793
|
}
|
|
2742
2794
|
/** Number of execution history records */
|
|
2795
|
+
get ExecutionHistoryCount() {
|
|
2796
|
+
return this.RecentExecutions.length;
|
|
2797
|
+
}
|
|
2798
|
+
/** @deprecated Use {@link ExecutionHistoryCount}. */
|
|
2743
2799
|
get executionHistoryCount() {
|
|
2744
|
-
return this.
|
|
2800
|
+
return this.ExecutionHistoryCount;
|
|
2801
|
+
}
|
|
2802
|
+
/** @deprecated Use {@link SubAgents}. */
|
|
2803
|
+
get subAgents() {
|
|
2804
|
+
return this.SubAgents;
|
|
2805
|
+
}
|
|
2806
|
+
/** @deprecated Use {@link SubAgents}. */
|
|
2807
|
+
set subAgents(value) {
|
|
2808
|
+
this.SubAgents = value;
|
|
2809
|
+
}
|
|
2810
|
+
/** @deprecated Use {@link SubAgentFilter}. */
|
|
2811
|
+
get subAgentFilter() {
|
|
2812
|
+
return this.SubAgentFilter;
|
|
2813
|
+
}
|
|
2814
|
+
/** @deprecated Use {@link SubAgentFilter}. */
|
|
2815
|
+
set subAgentFilter(value) {
|
|
2816
|
+
this.SubAgentFilter = value;
|
|
2745
2817
|
}
|
|
2746
2818
|
/** Filtered sub-agents based on current filter */
|
|
2747
|
-
get
|
|
2748
|
-
switch (this.
|
|
2819
|
+
get FilteredSubAgents() {
|
|
2820
|
+
switch (this.SubAgentFilter) {
|
|
2749
2821
|
case 'child':
|
|
2750
2822
|
return this.allSubAgents.filter(s => s.type === 'child');
|
|
2751
2823
|
case 'related':
|
|
@@ -2754,9 +2826,157 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2754
2826
|
return this.allSubAgents;
|
|
2755
2827
|
}
|
|
2756
2828
|
}
|
|
2829
|
+
/** @deprecated Use {@link FilteredSubAgents}. */
|
|
2830
|
+
get filteredSubAgents() {
|
|
2831
|
+
return this.FilteredSubAgents;
|
|
2832
|
+
}
|
|
2833
|
+
/** @deprecated Use {@link AgentPrompts}. */
|
|
2834
|
+
get agentPrompts() {
|
|
2835
|
+
return this.AgentPrompts;
|
|
2836
|
+
}
|
|
2837
|
+
/** @deprecated Use {@link AgentPrompts}. */
|
|
2838
|
+
set agentPrompts(value) {
|
|
2839
|
+
this.AgentPrompts = value;
|
|
2840
|
+
}
|
|
2841
|
+
/** @deprecated Use {@link AgentActions}. */
|
|
2842
|
+
get agentActions() {
|
|
2843
|
+
return this.AgentActions;
|
|
2844
|
+
}
|
|
2845
|
+
/** @deprecated Use {@link AgentActions}. */
|
|
2846
|
+
set agentActions(value) {
|
|
2847
|
+
this.AgentActions = value;
|
|
2848
|
+
}
|
|
2849
|
+
/** @deprecated Use {@link LearningCycles}. */
|
|
2850
|
+
get learningCycles() {
|
|
2851
|
+
return this.LearningCycles;
|
|
2852
|
+
}
|
|
2853
|
+
/** @deprecated Use {@link LearningCycles}. */
|
|
2854
|
+
set learningCycles(value) {
|
|
2855
|
+
this.LearningCycles = value;
|
|
2856
|
+
}
|
|
2857
|
+
/** @deprecated Use {@link AgentNotes}. */
|
|
2858
|
+
get agentNotes() {
|
|
2859
|
+
return this.AgentNotes;
|
|
2860
|
+
}
|
|
2861
|
+
/** @deprecated Use {@link AgentNotes}. */
|
|
2862
|
+
set agentNotes(value) {
|
|
2863
|
+
this.AgentNotes = value;
|
|
2864
|
+
}
|
|
2865
|
+
/** @deprecated Use {@link RecentExecutions}. */
|
|
2866
|
+
get recentExecutions() {
|
|
2867
|
+
return this.RecentExecutions;
|
|
2868
|
+
}
|
|
2869
|
+
/** @deprecated Use {@link RecentExecutions}. */
|
|
2870
|
+
set recentExecutions(value) {
|
|
2871
|
+
this.RecentExecutions = value;
|
|
2872
|
+
}
|
|
2873
|
+
/** @deprecated Use {@link TotalExecutionHistoryCount}. */
|
|
2874
|
+
get totalExecutionHistoryCount() {
|
|
2875
|
+
return this.TotalExecutionHistoryCount;
|
|
2876
|
+
}
|
|
2877
|
+
/** @deprecated Use {@link TotalExecutionHistoryCount}. */
|
|
2878
|
+
set totalExecutionHistoryCount(value) {
|
|
2879
|
+
this.TotalExecutionHistoryCount = value;
|
|
2880
|
+
}
|
|
2881
|
+
/** @deprecated Use {@link ExpandedExecutions}. */
|
|
2882
|
+
get expandedExecutions() {
|
|
2883
|
+
return this.ExpandedExecutions;
|
|
2884
|
+
}
|
|
2885
|
+
/** @deprecated Use {@link ExpandedExecutions}. */
|
|
2886
|
+
set expandedExecutions(value) {
|
|
2887
|
+
this.ExpandedExecutions = value;
|
|
2888
|
+
}
|
|
2889
|
+
/** @deprecated Use {@link ExecutionSearchText}. */
|
|
2890
|
+
get executionSearchText() {
|
|
2891
|
+
return this.ExecutionSearchText;
|
|
2892
|
+
}
|
|
2893
|
+
/** @deprecated Use {@link ExecutionSearchText}. */
|
|
2894
|
+
set executionSearchText(value) {
|
|
2895
|
+
this.ExecutionSearchText = value;
|
|
2896
|
+
}
|
|
2897
|
+
/** @deprecated Use {@link FilteredExecutions}. */
|
|
2898
|
+
get filteredExecutions() {
|
|
2899
|
+
return this.FilteredExecutions;
|
|
2900
|
+
}
|
|
2901
|
+
/** @deprecated Use {@link FilteredExecutions}. */
|
|
2902
|
+
set filteredExecutions(value) {
|
|
2903
|
+
this.FilteredExecutions = value;
|
|
2904
|
+
}
|
|
2757
2905
|
/** Message shown when the execution-history search matches nothing. */
|
|
2758
2906
|
get ExecutionSearchEmptyMessage() {
|
|
2759
|
-
return `No execution history found matching "${this.
|
|
2907
|
+
return `No execution history found matching "${this.ExecutionSearchText}"`;
|
|
2908
|
+
}
|
|
2909
|
+
/** @deprecated Use {@link ExecutionHistoryView}. */
|
|
2910
|
+
get executionHistoryView() {
|
|
2911
|
+
return this.ExecutionHistoryView;
|
|
2912
|
+
}
|
|
2913
|
+
/** @deprecated Use {@link ExecutionHistoryView}. */
|
|
2914
|
+
set executionHistoryView(value) {
|
|
2915
|
+
this.ExecutionHistoryView = value;
|
|
2916
|
+
}
|
|
2917
|
+
/** @deprecated Use {@link AgentSessions}. */
|
|
2918
|
+
get agentSessions() {
|
|
2919
|
+
return this.AgentSessions;
|
|
2920
|
+
}
|
|
2921
|
+
/** @deprecated Use {@link AgentSessions}. */
|
|
2922
|
+
set agentSessions(value) {
|
|
2923
|
+
this.AgentSessions = value;
|
|
2924
|
+
}
|
|
2925
|
+
/** @deprecated Use {@link TotalSessionCount}. */
|
|
2926
|
+
get totalSessionCount() {
|
|
2927
|
+
return this.TotalSessionCount;
|
|
2928
|
+
}
|
|
2929
|
+
/** @deprecated Use {@link TotalSessionCount}. */
|
|
2930
|
+
set totalSessionCount(value) {
|
|
2931
|
+
this.TotalSessionCount = value;
|
|
2932
|
+
}
|
|
2933
|
+
/** @deprecated Use {@link LoadingSessions}. */
|
|
2934
|
+
get loadingSessions() {
|
|
2935
|
+
return this.LoadingSessions;
|
|
2936
|
+
}
|
|
2937
|
+
/** @deprecated Use {@link LoadingSessions}. */
|
|
2938
|
+
set loadingSessions(value) {
|
|
2939
|
+
this.LoadingSessions = value;
|
|
2940
|
+
}
|
|
2941
|
+
/** @deprecated Use {@link ExecutionHistoryPageSize}. */
|
|
2942
|
+
get executionHistoryPageSize() {
|
|
2943
|
+
return this.ExecutionHistoryPageSize;
|
|
2944
|
+
}
|
|
2945
|
+
/** @deprecated Use {@link ExecutionHistoryPageSize}. */
|
|
2946
|
+
set executionHistoryPageSize(value) {
|
|
2947
|
+
this.ExecutionHistoryPageSize = value;
|
|
2948
|
+
}
|
|
2949
|
+
/** @deprecated Use {@link ExecutionHistoryCurrentPage}. */
|
|
2950
|
+
get executionHistoryCurrentPage() {
|
|
2951
|
+
return this.ExecutionHistoryCurrentPage;
|
|
2952
|
+
}
|
|
2953
|
+
/** @deprecated Use {@link ExecutionHistoryCurrentPage}. */
|
|
2954
|
+
set executionHistoryCurrentPage(value) {
|
|
2955
|
+
this.ExecutionHistoryCurrentPage = value;
|
|
2956
|
+
}
|
|
2957
|
+
/** @deprecated Use {@link IsLoadingPage}. */
|
|
2958
|
+
get isLoadingPage() {
|
|
2959
|
+
return this.IsLoadingPage;
|
|
2960
|
+
}
|
|
2961
|
+
/** @deprecated Use {@link IsLoadingPage}. */
|
|
2962
|
+
set isLoadingPage(value) {
|
|
2963
|
+
this.IsLoadingPage = value;
|
|
2964
|
+
}
|
|
2965
|
+
/** @deprecated Use {@link IsLoadingData}. */
|
|
2966
|
+
get isLoadingData() {
|
|
2967
|
+
return this.IsLoadingData;
|
|
2968
|
+
}
|
|
2969
|
+
/** @deprecated Use {@link IsLoadingData}. */
|
|
2970
|
+
set isLoadingData(value) {
|
|
2971
|
+
this.IsLoadingData = value;
|
|
2972
|
+
}
|
|
2973
|
+
/** @deprecated Use {@link LoadingStates}. */
|
|
2974
|
+
get loadingStates() {
|
|
2975
|
+
return this.LoadingStates;
|
|
2976
|
+
}
|
|
2977
|
+
/** @deprecated Use {@link LoadingStates}. */
|
|
2978
|
+
set loadingStates(value) {
|
|
2979
|
+
this.LoadingStates = value;
|
|
2760
2980
|
}
|
|
2761
2981
|
/**
|
|
2762
2982
|
* Loads the permission summary for the scopes currently assigned to
|
|
@@ -2818,8 +3038,8 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2818
3038
|
/** The slice of state the tab rules read — kept small so the rules stay unit-testable. */
|
|
2819
3039
|
get formTabContext() {
|
|
2820
3040
|
return {
|
|
2821
|
-
AgentTypeName: this.
|
|
2822
|
-
UIFormSectionKey: this.
|
|
3041
|
+
AgentTypeName: this.AgentType?.Name ?? null,
|
|
3042
|
+
UIFormSectionKey: this.AgentType?.UIFormSectionKey ?? null,
|
|
2823
3043
|
HasRecordID: !!this.record?.ID,
|
|
2824
3044
|
};
|
|
2825
3045
|
}
|
|
@@ -2851,6 +3071,30 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2851
3071
|
get customSectionLoadedForTab() {
|
|
2852
3072
|
return this.customSectionLoaded;
|
|
2853
3073
|
}
|
|
3074
|
+
/** @deprecated Use {@link ModelSelectionModes}. */
|
|
3075
|
+
get modelSelectionModes() {
|
|
3076
|
+
return this.ModelSelectionModes;
|
|
3077
|
+
}
|
|
3078
|
+
/** @deprecated Use {@link ModelSelectionModes}. */
|
|
3079
|
+
set modelSelectionModes(value) {
|
|
3080
|
+
this.ModelSelectionModes = value;
|
|
3081
|
+
}
|
|
3082
|
+
/** @deprecated Use {@link StatusOptions}. */
|
|
3083
|
+
get statusOptions() {
|
|
3084
|
+
return this.StatusOptions;
|
|
3085
|
+
}
|
|
3086
|
+
/** @deprecated Use {@link StatusOptions}. */
|
|
3087
|
+
set statusOptions(value) {
|
|
3088
|
+
this.StatusOptions = value;
|
|
3089
|
+
}
|
|
3090
|
+
/** @deprecated Use {@link AgentTypes}. */
|
|
3091
|
+
get agentTypes() {
|
|
3092
|
+
return this.AgentTypes;
|
|
3093
|
+
}
|
|
3094
|
+
/** @deprecated Use {@link AgentTypes}. */
|
|
3095
|
+
set agentTypes(value) {
|
|
3096
|
+
this.AgentTypes = value;
|
|
3097
|
+
}
|
|
2854
3098
|
/** Handle category selection change from the TreeDropdown */
|
|
2855
3099
|
OnCategoryChange(value) {
|
|
2856
3100
|
if (value && !Array.isArray(value)) {
|
|
@@ -2862,12 +3106,20 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2862
3106
|
}
|
|
2863
3107
|
this.SelectedCategoryKey = Array.isArray(value) ? null : value;
|
|
2864
3108
|
}
|
|
3109
|
+
/** @deprecated Use {@link SelectedContextCompressionPrompt}. */
|
|
3110
|
+
get selectedContextCompressionPrompt() {
|
|
3111
|
+
return this.SelectedContextCompressionPrompt;
|
|
3112
|
+
}
|
|
3113
|
+
/** @deprecated Use {@link SelectedContextCompressionPrompt}. */
|
|
3114
|
+
set selectedContextCompressionPrompt(value) {
|
|
3115
|
+
this.SelectedContextCompressionPrompt = value;
|
|
3116
|
+
}
|
|
2865
3117
|
/**
|
|
2866
3118
|
* Loads agent types from the database for the dropdown
|
|
2867
3119
|
* @private
|
|
2868
3120
|
*/
|
|
2869
3121
|
async loadAgentTypes() {
|
|
2870
|
-
this.
|
|
3122
|
+
this.AgentTypes = AIEngineBase.Instance.AgentTypes;
|
|
2871
3123
|
}
|
|
2872
3124
|
/**
|
|
2873
3125
|
* Loads the context compression prompt details for display
|
|
@@ -2875,18 +3127,18 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2875
3127
|
*/
|
|
2876
3128
|
async loadContextCompressionPrompt() {
|
|
2877
3129
|
if (!this.record?.ContextCompressionPromptID) {
|
|
2878
|
-
this.
|
|
3130
|
+
this.SelectedContextCompressionPrompt = null;
|
|
2879
3131
|
return;
|
|
2880
3132
|
}
|
|
2881
|
-
this.
|
|
2882
|
-
if (!this.
|
|
3133
|
+
this.SelectedContextCompressionPrompt = AIEngineBase.Instance.Prompts.find(p => UUIDsEqual(p.ID, this.record.ContextCompressionPromptID));
|
|
3134
|
+
if (!this.SelectedContextCompressionPrompt) {
|
|
2883
3135
|
console.warn('Context compression prompt not found:', this.record.ContextCompressionPromptID);
|
|
2884
3136
|
}
|
|
2885
3137
|
}
|
|
2886
3138
|
/**
|
|
2887
3139
|
* Opens the prompt selector dialog for context compression prompt
|
|
2888
3140
|
*/
|
|
2889
|
-
async
|
|
3141
|
+
async OpenContextCompressionPromptSelector() {
|
|
2890
3142
|
try {
|
|
2891
3143
|
const dialogRef = this.dialogService.open({
|
|
2892
3144
|
title: 'Select Context Compression Prompt',
|
|
@@ -2897,18 +3149,18 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2897
3149
|
const promptSelector = dialogRef.Content.instance;
|
|
2898
3150
|
// Configure the prompt selector for single selection
|
|
2899
3151
|
promptSelector.config = {
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
3152
|
+
Title: 'Select Context Compression Prompt',
|
|
3153
|
+
MultiSelect: false,
|
|
3154
|
+
SelectedPromptIds: this.record.ContextCompressionPromptID ? [this.record.ContextCompressionPromptID] : [],
|
|
3155
|
+
ShowCreateNew: false
|
|
2904
3156
|
};
|
|
2905
3157
|
// Subscribe to the result
|
|
2906
3158
|
promptSelector.result.subscribe({
|
|
2907
3159
|
next: (result) => {
|
|
2908
|
-
if (result && result.
|
|
2909
|
-
const selectedPrompt = result.
|
|
3160
|
+
if (result && result.SelectedPrompts.length > 0) {
|
|
3161
|
+
const selectedPrompt = result.SelectedPrompts[0];
|
|
2910
3162
|
this.record.ContextCompressionPromptID = selectedPrompt.ID;
|
|
2911
|
-
this.
|
|
3163
|
+
this.SelectedContextCompressionPrompt = selectedPrompt;
|
|
2912
3164
|
this.cdr.detectChanges();
|
|
2913
3165
|
}
|
|
2914
3166
|
},
|
|
@@ -2922,14 +3174,22 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
2922
3174
|
MJNotificationService.Instance.CreateSimpleNotification('Error opening prompt selector. Please try again.', 'error', 3000);
|
|
2923
3175
|
}
|
|
2924
3176
|
}
|
|
3177
|
+
/** @deprecated Use {@link OpenContextCompressionPromptSelector}. */
|
|
3178
|
+
async openContextCompressionPromptSelector() {
|
|
3179
|
+
return this.OpenContextCompressionPromptSelector();
|
|
3180
|
+
}
|
|
2925
3181
|
/**
|
|
2926
3182
|
* Clears the selected context compression prompt
|
|
2927
3183
|
*/
|
|
2928
|
-
|
|
3184
|
+
ClearContextCompressionPrompt() {
|
|
2929
3185
|
this.record.ContextCompressionPromptID = null;
|
|
2930
|
-
this.
|
|
3186
|
+
this.SelectedContextCompressionPrompt = null;
|
|
2931
3187
|
this.cdr.detectChanges();
|
|
2932
3188
|
}
|
|
3189
|
+
/** @deprecated Use {@link ClearContextCompressionPrompt}. */
|
|
3190
|
+
clearContextCompressionPrompt() {
|
|
3191
|
+
return this.ClearContextCompressionPrompt();
|
|
3192
|
+
}
|
|
2933
3193
|
// Main AI Agent permissions inherited from BaseFormComponent:
|
|
2934
3194
|
// - UserCanEdit (Update permission)
|
|
2935
3195
|
// - UserCanRead (Read permission)
|
|
@@ -3050,9 +3310,21 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3050
3310
|
/**
|
|
3051
3311
|
* Clears the permission cache. Call this when user context changes or permissions are updated.
|
|
3052
3312
|
*/
|
|
3053
|
-
|
|
3313
|
+
ClearPermissionCache() {
|
|
3054
3314
|
this._permissionCache.clear();
|
|
3055
3315
|
}
|
|
3316
|
+
/** @deprecated Use {@link ClearPermissionCache}. */
|
|
3317
|
+
clearPermissionCache() {
|
|
3318
|
+
return this.ClearPermissionCache();
|
|
3319
|
+
}
|
|
3320
|
+
/** @deprecated Use {@link HasUnsavedChanges}. */
|
|
3321
|
+
get hasUnsavedChanges() {
|
|
3322
|
+
return this.HasUnsavedChanges;
|
|
3323
|
+
}
|
|
3324
|
+
/** @deprecated Use {@link HasUnsavedChanges}. */
|
|
3325
|
+
set hasUnsavedChanges(value) {
|
|
3326
|
+
this.HasUnsavedChanges = value;
|
|
3327
|
+
}
|
|
3056
3328
|
/**
|
|
3057
3329
|
* Surfaces the type section's own edits to the toolbar and the navigate-away guard.
|
|
3058
3330
|
*
|
|
@@ -3129,14 +3401,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3129
3401
|
return;
|
|
3130
3402
|
// Reset pagination state on refresh
|
|
3131
3403
|
if (forceRefresh) {
|
|
3132
|
-
this.
|
|
3133
|
-
this.
|
|
3404
|
+
this.ExecutionHistoryCurrentPage = 1;
|
|
3405
|
+
this.IsLoadingPage = false;
|
|
3134
3406
|
this.allLoadedExecutions = [];
|
|
3135
3407
|
// Don't clear recentExecutions - keep existing data visible while loading
|
|
3136
3408
|
}
|
|
3137
3409
|
// Set loading state
|
|
3138
|
-
this.
|
|
3139
|
-
this.
|
|
3410
|
+
this.IsLoadingData = true;
|
|
3411
|
+
this.LoadingStates = {
|
|
3140
3412
|
executionHistory: true,
|
|
3141
3413
|
subAgents: true,
|
|
3142
3414
|
prompts: true,
|
|
@@ -3185,7 +3457,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3185
3457
|
});
|
|
3186
3458
|
}
|
|
3187
3459
|
// Also populate the deprecated subAgents array for backward compatibility
|
|
3188
|
-
this.
|
|
3460
|
+
this.SubAgents = [...childAgents];
|
|
3189
3461
|
// Load related sub-agents (Relationship-based)
|
|
3190
3462
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
3191
3463
|
const relationshipsResult = await rv.RunView({
|
|
@@ -3221,11 +3493,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3221
3493
|
// Single assignment — happens AFTER the awaits above, i.e. outside the host's CD pass, so
|
|
3222
3494
|
// totalSubAgentCount changes exactly once against settled state (no NG0100).
|
|
3223
3495
|
this.allSubAgents = newSubAgents;
|
|
3224
|
-
this.
|
|
3496
|
+
this.AgentPrompts = AIEngineBase.Instance.Prompts.filter(p => {
|
|
3225
3497
|
const filteredAgentPrompts = AIEngineBase.Instance.AgentPrompts.filter(ap => UUIDsEqual(ap.AgentID, this.record.ID));
|
|
3226
3498
|
return filteredAgentPrompts.some(ap => UUIDsEqual(ap.PromptID, p.ID));
|
|
3227
3499
|
});
|
|
3228
|
-
this.
|
|
3500
|
+
this.AgentActions = ActionEngineBase.Instance.Actions.filter(a => {
|
|
3229
3501
|
const filteredAgentActions = AIEngineBase.Instance.AgentActions.filter(aa => UUIDsEqual(aa.AgentID, this.record.ID));
|
|
3230
3502
|
return filteredAgentActions.some(aa => UUIDsEqual(aa.ActionID, a.ID));
|
|
3231
3503
|
});
|
|
@@ -3256,7 +3528,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3256
3528
|
],
|
|
3257
3529
|
ExtraFilter: `AgentID='${this.record.ID}'`,
|
|
3258
3530
|
OrderBy: '__mj_CreatedAt DESC',
|
|
3259
|
-
MaxRows: this.
|
|
3531
|
+
MaxRows: this.ExecutionHistoryPageSize
|
|
3260
3532
|
},
|
|
3261
3533
|
// Agent permissions (to determine open-to-everyone state)
|
|
3262
3534
|
{
|
|
@@ -3268,14 +3540,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3268
3540
|
]);
|
|
3269
3541
|
// Process results in the same order as queries
|
|
3270
3542
|
if (results && results.length > 0) {
|
|
3271
|
-
this.
|
|
3272
|
-
this.
|
|
3273
|
-
this.
|
|
3274
|
-
this.
|
|
3543
|
+
this.LearningCycles = results[0].Results || [];
|
|
3544
|
+
this.AgentNotes = results[1].Results || [];
|
|
3545
|
+
this.RecentExecutions = results[2].Results || [];
|
|
3546
|
+
this.TotalExecutionHistoryCount = results[2].TotalRowCount;
|
|
3275
3547
|
// Initialize cache with first page of results
|
|
3276
|
-
this.allLoadedExecutions = [...this.
|
|
3548
|
+
this.allLoadedExecutions = [...this.RecentExecutions];
|
|
3277
3549
|
// Initialize filtered executions
|
|
3278
|
-
this.
|
|
3550
|
+
this.FilteredExecutions = [...this.RecentExecutions];
|
|
3279
3551
|
// Determine open-to-everyone state from permissions query
|
|
3280
3552
|
const permissionRows = results[3]?.Results || [];
|
|
3281
3553
|
this.IsOpenToEveryone = permissionRows.length === 0;
|
|
@@ -3293,8 +3565,8 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3293
3565
|
}
|
|
3294
3566
|
finally {
|
|
3295
3567
|
// Clear loading states
|
|
3296
|
-
this.
|
|
3297
|
-
this.
|
|
3568
|
+
this.IsLoadingData = false;
|
|
3569
|
+
this.LoadingStates = {
|
|
3298
3570
|
executionHistory: false,
|
|
3299
3571
|
subAgents: false,
|
|
3300
3572
|
prompts: false,
|
|
@@ -3316,37 +3588,45 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3316
3588
|
*/
|
|
3317
3589
|
createOriginalSnapshot() {
|
|
3318
3590
|
this.originalSnapshots = {
|
|
3319
|
-
agentPrompts: [...this.
|
|
3320
|
-
agentActions: [...this.
|
|
3321
|
-
subAgents: [...this.
|
|
3322
|
-
promptCount: this.
|
|
3323
|
-
actionCount: this.
|
|
3324
|
-
subAgentCount: this.
|
|
3325
|
-
learningCycleCount: this.
|
|
3326
|
-
noteCount: this.
|
|
3327
|
-
executionHistoryCount: this.
|
|
3591
|
+
agentPrompts: [...this.AgentPrompts], // Deep copy of arrays
|
|
3592
|
+
agentActions: [...this.AgentActions],
|
|
3593
|
+
subAgents: [...this.SubAgents],
|
|
3594
|
+
promptCount: this.PromptCount,
|
|
3595
|
+
actionCount: this.ActionCount,
|
|
3596
|
+
subAgentCount: this.SubAgentCount,
|
|
3597
|
+
learningCycleCount: this.LearningCycleCount,
|
|
3598
|
+
noteCount: this.NoteCount,
|
|
3599
|
+
executionHistoryCount: this.ExecutionHistoryCount
|
|
3328
3600
|
};
|
|
3329
3601
|
}
|
|
3330
3602
|
/**
|
|
3331
3603
|
* Navigates to the next page of execution history
|
|
3332
3604
|
*/
|
|
3333
|
-
async
|
|
3334
|
-
if (!this.
|
|
3605
|
+
async GoToNextPage() {
|
|
3606
|
+
if (!this.HasNextPage || this.IsLoadingPage || !this.record?.ID) {
|
|
3335
3607
|
return;
|
|
3336
3608
|
}
|
|
3337
|
-
const nextPage = this.
|
|
3609
|
+
const nextPage = this.ExecutionHistoryCurrentPage + 1;
|
|
3338
3610
|
await this.loadPage(nextPage);
|
|
3339
3611
|
}
|
|
3612
|
+
/** @deprecated Use {@link GoToNextPage}. */
|
|
3613
|
+
async goToNextPage() {
|
|
3614
|
+
return this.GoToNextPage();
|
|
3615
|
+
}
|
|
3340
3616
|
/**
|
|
3341
3617
|
* Navigates to the previous page of execution history
|
|
3342
3618
|
*/
|
|
3343
|
-
async
|
|
3344
|
-
if (!this.
|
|
3619
|
+
async GoToPreviousPage() {
|
|
3620
|
+
if (!this.HasPreviousPage || this.IsLoadingPage) {
|
|
3345
3621
|
return;
|
|
3346
3622
|
}
|
|
3347
|
-
const previousPage = this.
|
|
3623
|
+
const previousPage = this.ExecutionHistoryCurrentPage - 1;
|
|
3348
3624
|
await this.loadPage(previousPage);
|
|
3349
3625
|
}
|
|
3626
|
+
/** @deprecated Use {@link GoToPreviousPage}. */
|
|
3627
|
+
async goToPreviousPage() {
|
|
3628
|
+
return this.GoToPreviousPage();
|
|
3629
|
+
}
|
|
3350
3630
|
/**
|
|
3351
3631
|
* Loads a specific page of execution history, using cache when available
|
|
3352
3632
|
*/
|
|
@@ -3354,21 +3634,21 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3354
3634
|
if (!this.record?.ID) {
|
|
3355
3635
|
return;
|
|
3356
3636
|
}
|
|
3357
|
-
this.
|
|
3637
|
+
this.IsLoadingPage = true;
|
|
3358
3638
|
this.cdr.detectChanges();
|
|
3359
3639
|
try {
|
|
3360
|
-
const startIndex = (pageNumber - 1) * this.
|
|
3361
|
-
const endIndex = startIndex + this.
|
|
3640
|
+
const startIndex = (pageNumber - 1) * this.ExecutionHistoryPageSize;
|
|
3641
|
+
const endIndex = startIndex + this.ExecutionHistoryPageSize;
|
|
3362
3642
|
// Check if we have this page in cache
|
|
3363
3643
|
const cachedPageData = this.allLoadedExecutions.slice(startIndex, endIndex);
|
|
3364
|
-
const hasFullPageInCache = cachedPageData.length === this.
|
|
3365
|
-
const isLastPage = endIndex >= this.
|
|
3644
|
+
const hasFullPageInCache = cachedPageData.length === this.ExecutionHistoryPageSize;
|
|
3645
|
+
const isLastPage = endIndex >= this.TotalExecutionHistoryCount;
|
|
3366
3646
|
const hasPartialPageInCache = isLastPage && cachedPageData.length > 0 &&
|
|
3367
|
-
cachedPageData.length === (this.
|
|
3647
|
+
cachedPageData.length === (this.TotalExecutionHistoryCount - startIndex);
|
|
3368
3648
|
if (hasFullPageInCache || hasPartialPageInCache) {
|
|
3369
3649
|
// We have the page in cache (either full page or complete last page)
|
|
3370
|
-
this.
|
|
3371
|
-
this.
|
|
3650
|
+
this.ExecutionHistoryCurrentPage = pageNumber;
|
|
3651
|
+
this.RecentExecutions = cachedPageData;
|
|
3372
3652
|
await this.applySearchFilter();
|
|
3373
3653
|
}
|
|
3374
3654
|
else {
|
|
@@ -3383,7 +3663,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3383
3663
|
],
|
|
3384
3664
|
ExtraFilter: `AgentID='${this.record.ID}'`,
|
|
3385
3665
|
OrderBy: '__mj_CreatedAt DESC',
|
|
3386
|
-
MaxRows: this.
|
|
3666
|
+
MaxRows: this.ExecutionHistoryPageSize,
|
|
3387
3667
|
StartRow: startIndex > 0 ? startIndex : undefined,
|
|
3388
3668
|
ResultType: 'entity_object'
|
|
3389
3669
|
});
|
|
@@ -3394,8 +3674,8 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3394
3674
|
}
|
|
3395
3675
|
// Insert the new results into cache
|
|
3396
3676
|
this.allLoadedExecutions.splice(startIndex, result.Results.length, ...result.Results);
|
|
3397
|
-
this.
|
|
3398
|
-
this.
|
|
3677
|
+
this.ExecutionHistoryCurrentPage = pageNumber;
|
|
3678
|
+
this.RecentExecutions = result.Results;
|
|
3399
3679
|
await this.applySearchFilter();
|
|
3400
3680
|
}
|
|
3401
3681
|
}
|
|
@@ -3404,28 +3684,40 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3404
3684
|
console.error('Error loading page:', error);
|
|
3405
3685
|
}
|
|
3406
3686
|
finally {
|
|
3407
|
-
this.
|
|
3687
|
+
this.IsLoadingPage = false;
|
|
3408
3688
|
this.cdr.detectChanges();
|
|
3409
3689
|
}
|
|
3410
3690
|
}
|
|
3411
3691
|
/**
|
|
3412
3692
|
* Checks if there is a next page available
|
|
3413
3693
|
*/
|
|
3694
|
+
get HasNextPage() {
|
|
3695
|
+
const maxPage = Math.ceil(this.TotalExecutionHistoryCount / this.ExecutionHistoryPageSize);
|
|
3696
|
+
return this.ExecutionHistoryCurrentPage < maxPage;
|
|
3697
|
+
}
|
|
3698
|
+
/** @deprecated Use {@link HasNextPage}. */
|
|
3414
3699
|
get hasNextPage() {
|
|
3415
|
-
|
|
3416
|
-
return this.executionHistoryCurrentPage < maxPage;
|
|
3700
|
+
return this.HasNextPage;
|
|
3417
3701
|
}
|
|
3418
3702
|
/**
|
|
3419
3703
|
* Checks if there is a previous page available
|
|
3420
3704
|
*/
|
|
3705
|
+
get HasPreviousPage() {
|
|
3706
|
+
return this.ExecutionHistoryCurrentPage > 1;
|
|
3707
|
+
}
|
|
3708
|
+
/** @deprecated Use {@link HasPreviousPage}. */
|
|
3421
3709
|
get hasPreviousPage() {
|
|
3422
|
-
return this.
|
|
3710
|
+
return this.HasPreviousPage;
|
|
3423
3711
|
}
|
|
3424
3712
|
/**
|
|
3425
3713
|
* Gets the total number of pages
|
|
3426
3714
|
*/
|
|
3715
|
+
get TotalPages() {
|
|
3716
|
+
return Math.ceil(this.TotalExecutionHistoryCount / this.ExecutionHistoryPageSize);
|
|
3717
|
+
}
|
|
3718
|
+
/** @deprecated Use {@link TotalPages}. */
|
|
3427
3719
|
get totalPages() {
|
|
3428
|
-
return
|
|
3720
|
+
return this.TotalPages;
|
|
3429
3721
|
}
|
|
3430
3722
|
/**
|
|
3431
3723
|
* Loads the agent type entity for this agent
|
|
@@ -3437,14 +3729,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3437
3729
|
}
|
|
3438
3730
|
try {
|
|
3439
3731
|
const md = this.ProviderToUse;
|
|
3440
|
-
this.
|
|
3441
|
-
if (this.
|
|
3442
|
-
await this.
|
|
3732
|
+
this.AgentType = await md.GetEntityObject('MJ: AI Agent Types');
|
|
3733
|
+
if (this.AgentType) {
|
|
3734
|
+
await this.AgentType.Load(this.record.TypeID);
|
|
3443
3735
|
}
|
|
3444
3736
|
}
|
|
3445
3737
|
catch (error) {
|
|
3446
3738
|
console.error('Error loading agent type:', error);
|
|
3447
|
-
this.
|
|
3739
|
+
this.AgentType = null;
|
|
3448
3740
|
}
|
|
3449
3741
|
// The tab strip depends on the type (only some types ship a designer), so it cannot be built
|
|
3450
3742
|
// until the type is known.
|
|
@@ -3455,18 +3747,18 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3455
3747
|
* @private
|
|
3456
3748
|
*/
|
|
3457
3749
|
loadCustomFormSection() {
|
|
3458
|
-
if (!this.
|
|
3750
|
+
if (!this.AgentType?.UIFormSectionKey || !this.customSectionContainer) {
|
|
3459
3751
|
return;
|
|
3460
3752
|
}
|
|
3461
3753
|
// Check if component still exists in container
|
|
3462
3754
|
if (this.customSectionLoaded && this.customSectionContainer.length > 0) {
|
|
3463
3755
|
return;
|
|
3464
3756
|
}
|
|
3465
|
-
this.
|
|
3757
|
+
this.LoadingStates.customSection = true;
|
|
3466
3758
|
this.cdr.markForCheck();
|
|
3467
3759
|
try {
|
|
3468
3760
|
// Build the full registration key (Entity.Section pattern)
|
|
3469
|
-
const sectionKey = `AI Agents.${this.
|
|
3761
|
+
const sectionKey = `AI Agents.${this.AgentType.UIFormSectionKey}`;
|
|
3470
3762
|
// Get the component registration from the class factory
|
|
3471
3763
|
const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseFormSectionComponent, sectionKey);
|
|
3472
3764
|
if (registration && registration.SubClass) {
|
|
@@ -3487,7 +3779,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3487
3779
|
console.error('Error loading custom form section:', error);
|
|
3488
3780
|
}
|
|
3489
3781
|
finally {
|
|
3490
|
-
this.
|
|
3782
|
+
this.LoadingStates.customSection = false;
|
|
3491
3783
|
this.cdr.markForCheck();
|
|
3492
3784
|
}
|
|
3493
3785
|
}
|
|
@@ -3495,15 +3787,19 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3495
3787
|
* Handles state change events for the custom section panel
|
|
3496
3788
|
* @param event The panel bar state change event
|
|
3497
3789
|
*/
|
|
3498
|
-
|
|
3790
|
+
OnCustomSectionStateChange(event) {
|
|
3499
3791
|
// When panel is expanded, check if we need to load or reload the custom section
|
|
3500
|
-
if (event.expanded && this.
|
|
3792
|
+
if (event.expanded && this.AgentType?.UIFormSectionKey) {
|
|
3501
3793
|
// Always try to load on expand to handle cases where container might have been recreated
|
|
3502
3794
|
this.setTrackedTimeout(() => {
|
|
3503
3795
|
this.loadCustomFormSection();
|
|
3504
3796
|
}, 0);
|
|
3505
3797
|
}
|
|
3506
3798
|
}
|
|
3799
|
+
/** @deprecated Use {@link OnCustomSectionStateChange}. */
|
|
3800
|
+
onCustomSectionStateChange(event) {
|
|
3801
|
+
return this.OnCustomSectionStateChange(event);
|
|
3802
|
+
}
|
|
3507
3803
|
// === User Preferences (Header & Section State) ===
|
|
3508
3804
|
/** Load saved preferences for header state and section expand/collapse */
|
|
3509
3805
|
loadUserPreferences() {
|
|
@@ -3556,7 +3852,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3556
3852
|
this.SectionStates[item.id] = item.expanded;
|
|
3557
3853
|
// Keep existing custom section load logic
|
|
3558
3854
|
if (item.id === 'custom' && item.expanded) {
|
|
3559
|
-
this.
|
|
3855
|
+
this.OnCustomSectionStateChange({ expanded: true });
|
|
3560
3856
|
}
|
|
3561
3857
|
}
|
|
3562
3858
|
}
|
|
@@ -3569,11 +3865,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3569
3865
|
restoreFromSnapshots() {
|
|
3570
3866
|
if (this.originalSnapshots) {
|
|
3571
3867
|
// Restore arrays (create new copies to ensure reactivity)
|
|
3572
|
-
this.
|
|
3573
|
-
this.
|
|
3574
|
-
this.
|
|
3868
|
+
this.AgentPrompts = [...this.originalSnapshots.agentPrompts];
|
|
3869
|
+
this.AgentActions = [...this.originalSnapshots.agentActions];
|
|
3870
|
+
this.SubAgents = [...this.originalSnapshots.subAgents];
|
|
3575
3871
|
// Reset other UI state
|
|
3576
|
-
this.
|
|
3872
|
+
this.HasUnsavedChanges = false;
|
|
3577
3873
|
// Mark for check instead of forcing immediate detection
|
|
3578
3874
|
this.cdr.markForCheck();
|
|
3579
3875
|
}
|
|
@@ -3593,7 +3889,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3593
3889
|
// Restore our UI state after parent cancel
|
|
3594
3890
|
this.restoreFromSnapshots();
|
|
3595
3891
|
// Reset the unsaved changes flag
|
|
3596
|
-
this.
|
|
3892
|
+
this.HasUnsavedChanges = false;
|
|
3597
3893
|
}
|
|
3598
3894
|
finally {
|
|
3599
3895
|
// Always reset the flag
|
|
@@ -3605,7 +3901,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3605
3901
|
* Validates that the agent has been saved before allowing testing.
|
|
3606
3902
|
* Shows a notification if the agent needs to be saved first.
|
|
3607
3903
|
*/
|
|
3608
|
-
|
|
3904
|
+
OpenTestHarness() {
|
|
3609
3905
|
if (!this.record?.ID) {
|
|
3610
3906
|
MJNotificationService.Instance.CreateSimpleNotification('Please save the AI agent before testing', 'warning', 4000);
|
|
3611
3907
|
return;
|
|
@@ -3614,18 +3910,30 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3614
3910
|
// Don't pass viewContainerRef so window is top-level
|
|
3615
3911
|
this.testHarnessService.openForAgent(this.record.ID);
|
|
3616
3912
|
}
|
|
3617
|
-
|
|
3913
|
+
/** @deprecated Use {@link OpenTestHarness}. */
|
|
3914
|
+
openTestHarness() {
|
|
3915
|
+
return this.OpenTestHarness();
|
|
3916
|
+
}
|
|
3917
|
+
OpenPermissionsDialog() {
|
|
3618
3918
|
if (!this.record?.ID) {
|
|
3619
3919
|
MJNotificationService.Instance.CreateSimpleNotification('Please save the AI agent before managing permissions', 'warning', 4000);
|
|
3620
3920
|
return;
|
|
3621
3921
|
}
|
|
3622
3922
|
this.ShowPermissionsDialog = true;
|
|
3623
3923
|
}
|
|
3624
|
-
|
|
3924
|
+
/** @deprecated Use {@link OpenPermissionsDialog}. */
|
|
3925
|
+
openPermissionsDialog() {
|
|
3926
|
+
return this.OpenPermissionsDialog();
|
|
3927
|
+
}
|
|
3928
|
+
async OnPermissionsDialogClosed() {
|
|
3625
3929
|
this.ShowPermissionsDialog = false;
|
|
3626
3930
|
// Refresh open-to-everyone state in case permissions were added/removed
|
|
3627
3931
|
await this.refreshPermissionState();
|
|
3628
3932
|
}
|
|
3933
|
+
/** @deprecated Use {@link OnPermissionsDialogClosed}. */
|
|
3934
|
+
async onPermissionsDialogClosed() {
|
|
3935
|
+
return this.OnPermissionsDialogClosed();
|
|
3936
|
+
}
|
|
3629
3937
|
async refreshPermissionState() {
|
|
3630
3938
|
if (!this.record?.ID)
|
|
3631
3939
|
return;
|
|
@@ -3646,7 +3954,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3646
3954
|
* Uses standard color coding: green for active, yellow for pending, gray for disabled.
|
|
3647
3955
|
* @returns CSS color value for the status badge
|
|
3648
3956
|
*/
|
|
3649
|
-
|
|
3957
|
+
GetStatusBadgeColor() {
|
|
3650
3958
|
switch (this.record?.Status) {
|
|
3651
3959
|
case 'Active': return 'var(--mj-status-success)';
|
|
3652
3960
|
case 'Pending': return 'var(--mj-status-warning)';
|
|
@@ -3654,6 +3962,10 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3654
3962
|
default: return 'var(--mj-text-muted)';
|
|
3655
3963
|
}
|
|
3656
3964
|
}
|
|
3965
|
+
/** @deprecated Use {@link GetStatusBadgeColor}. */
|
|
3966
|
+
getStatusBadgeColor() {
|
|
3967
|
+
return this.GetStatusBadgeColor();
|
|
3968
|
+
}
|
|
3657
3969
|
/**
|
|
3658
3970
|
* Event handler for test harness visibility changes.
|
|
3659
3971
|
* Updates the component state when the test harness is opened or closed.
|
|
@@ -3662,25 +3974,37 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3662
3974
|
/**
|
|
3663
3975
|
* Gets the count of sub-agents
|
|
3664
3976
|
*/
|
|
3977
|
+
GetSubAgentCount() {
|
|
3978
|
+
return this.SubAgentCount;
|
|
3979
|
+
}
|
|
3980
|
+
/** @deprecated Use {@link GetSubAgentCount}. */
|
|
3665
3981
|
getSubAgentCount() {
|
|
3666
|
-
return this.
|
|
3982
|
+
return this.GetSubAgentCount();
|
|
3667
3983
|
}
|
|
3668
3984
|
/**
|
|
3669
3985
|
* Gets the count of prompts
|
|
3670
3986
|
*/
|
|
3987
|
+
GetPromptCount() {
|
|
3988
|
+
return this.PromptCount;
|
|
3989
|
+
}
|
|
3990
|
+
/** @deprecated Use {@link GetPromptCount}. */
|
|
3671
3991
|
getPromptCount() {
|
|
3672
|
-
return this.
|
|
3992
|
+
return this.GetPromptCount();
|
|
3673
3993
|
}
|
|
3674
3994
|
/**
|
|
3675
3995
|
* Gets the count of actions
|
|
3676
3996
|
*/
|
|
3997
|
+
GetActionCount() {
|
|
3998
|
+
return this.ActionCount;
|
|
3999
|
+
}
|
|
4000
|
+
/** @deprecated Use {@link GetActionCount}. */
|
|
3677
4001
|
getActionCount() {
|
|
3678
|
-
return this.
|
|
4002
|
+
return this.GetActionCount();
|
|
3679
4003
|
}
|
|
3680
4004
|
/**
|
|
3681
4005
|
* Gets the icon for the execution mode
|
|
3682
4006
|
*/
|
|
3683
|
-
|
|
4007
|
+
GetExecutionModeIcon(mode) {
|
|
3684
4008
|
switch (mode) {
|
|
3685
4009
|
case 'Sequential':
|
|
3686
4010
|
return 'fa-solid fa-list-ol';
|
|
@@ -3690,52 +4014,76 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3690
4014
|
return 'fa-solid fa-robot';
|
|
3691
4015
|
}
|
|
3692
4016
|
}
|
|
4017
|
+
/** @deprecated Use {@link GetExecutionModeIcon}. */
|
|
4018
|
+
getExecutionModeIcon(mode) {
|
|
4019
|
+
return this.GetExecutionModeIcon(mode);
|
|
4020
|
+
}
|
|
3693
4021
|
/**
|
|
3694
4022
|
* Gets the agent's display icon
|
|
3695
4023
|
* Prioritizes LogoURL, falls back to IconClass, then default robot icon
|
|
3696
4024
|
*/
|
|
3697
|
-
|
|
4025
|
+
GetAgentIcon() {
|
|
3698
4026
|
if (this.record?.LogoURL) {
|
|
3699
4027
|
// LogoURL is used in img tag, not here
|
|
3700
4028
|
return '';
|
|
3701
4029
|
}
|
|
3702
4030
|
return this.record?.IconClass || 'fa-solid fa-robot';
|
|
3703
4031
|
}
|
|
4032
|
+
/** @deprecated Use {@link GetAgentIcon}. */
|
|
4033
|
+
getAgentIcon() {
|
|
4034
|
+
return this.GetAgentIcon();
|
|
4035
|
+
}
|
|
3704
4036
|
/**
|
|
3705
4037
|
* Checks if the agent has a logo URL (for image display)
|
|
3706
4038
|
*/
|
|
3707
|
-
|
|
4039
|
+
HasLogoURL() {
|
|
3708
4040
|
return !!this.record?.LogoURL;
|
|
3709
4041
|
}
|
|
4042
|
+
/** @deprecated Use {@link HasLogoURL}. */
|
|
4043
|
+
hasLogoURL() {
|
|
4044
|
+
return this.HasLogoURL();
|
|
4045
|
+
}
|
|
3710
4046
|
/**
|
|
3711
4047
|
* Gets the icon for a sub-agent
|
|
3712
4048
|
* Prioritizes LogoURL, falls back to IconClass, then default robot icon
|
|
3713
4049
|
*/
|
|
3714
|
-
|
|
4050
|
+
GetSubAgentIcon(subAgent) {
|
|
3715
4051
|
if (subAgent?.LogoURL) {
|
|
3716
4052
|
// LogoURL is used in img tag, not here
|
|
3717
4053
|
return '';
|
|
3718
4054
|
}
|
|
3719
4055
|
return subAgent?.IconClass || 'fa-solid fa-robot';
|
|
3720
4056
|
}
|
|
4057
|
+
/** @deprecated Use {@link GetSubAgentIcon}. */
|
|
4058
|
+
getSubAgentIcon(subAgent) {
|
|
4059
|
+
return this.GetSubAgentIcon(subAgent);
|
|
4060
|
+
}
|
|
3721
4061
|
/**
|
|
3722
4062
|
* Gets the icon class for an action
|
|
3723
4063
|
* Falls back to default bolt icon if no IconClass is set
|
|
3724
4064
|
*/
|
|
3725
|
-
|
|
4065
|
+
GetActionIcon(action) {
|
|
3726
4066
|
return action?.IconClass || 'fa-solid fa-bolt';
|
|
3727
4067
|
}
|
|
4068
|
+
/** @deprecated Use {@link GetActionIcon}. */
|
|
4069
|
+
getActionIcon(action) {
|
|
4070
|
+
return this.GetActionIcon(action);
|
|
4071
|
+
}
|
|
3728
4072
|
/**
|
|
3729
4073
|
* Checks if a sub-agent has a logo URL
|
|
3730
4074
|
*/
|
|
3731
|
-
|
|
4075
|
+
HasSubAgentLogoURL(subAgent) {
|
|
3732
4076
|
return !!subAgent?.LogoURL;
|
|
3733
4077
|
}
|
|
4078
|
+
/** @deprecated Use {@link HasSubAgentLogoURL}. */
|
|
4079
|
+
hasSubAgentLogoURL(subAgent) {
|
|
4080
|
+
return this.HasSubAgentLogoURL(subAgent);
|
|
4081
|
+
}
|
|
3734
4082
|
/**
|
|
3735
4083
|
* Creates a new sub-agent using the CreateAgentService slide-in panel.
|
|
3736
4084
|
* Uses the new unified agent creation UI from @memberjunction/ng-agents.
|
|
3737
4085
|
*/
|
|
3738
|
-
async
|
|
4086
|
+
async CreateSubAgent() {
|
|
3739
4087
|
try {
|
|
3740
4088
|
this.createAgentService.OpenSubAgentSlideIn(this.record.ID, this.record.Name || 'Agent').pipe(takeUntil(this.destroy$)).subscribe({
|
|
3741
4089
|
next: async (dialogResult) => {
|
|
@@ -3754,6 +4102,10 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3754
4102
|
MJNotificationService.Instance.CreateSimpleNotification('Error creating sub-agent. Please try again.', 'error', 3000);
|
|
3755
4103
|
}
|
|
3756
4104
|
}
|
|
4105
|
+
/** @deprecated Use {@link CreateSubAgent}. */
|
|
4106
|
+
async createSubAgent() {
|
|
4107
|
+
return this.CreateSubAgent();
|
|
4108
|
+
}
|
|
3757
4109
|
/**
|
|
3758
4110
|
* Handles the result from the create sub-agent slide-in.
|
|
3759
4111
|
* Adds entities to PendingRecords for atomic save with parent.
|
|
@@ -3790,8 +4142,8 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3790
4142
|
}
|
|
3791
4143
|
}
|
|
3792
4144
|
// Update UI to show the new sub-agent
|
|
3793
|
-
this.
|
|
3794
|
-
this.
|
|
4145
|
+
this.SubAgents.push(subAgent);
|
|
4146
|
+
this.HasUnsavedChanges = true;
|
|
3795
4147
|
// Mark for check instead of forcing immediate detection
|
|
3796
4148
|
this.cdr.markForCheck();
|
|
3797
4149
|
MJNotificationService.Instance.CreateSimpleNotification(`Sub-agent "${subAgent.Name}" created and will be saved when you save the parent agent`, 'success', 4000);
|
|
@@ -3804,9 +4156,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3804
4156
|
/**
|
|
3805
4157
|
* Adds a new prompt to the agent (deferred until save)
|
|
3806
4158
|
*/
|
|
3807
|
-
async
|
|
4159
|
+
async AddPrompt() {
|
|
3808
4160
|
// Get currently linked and pending prompt IDs for pre-selection
|
|
3809
|
-
const currentPromptIds = this.
|
|
4161
|
+
const currentPromptIds = this.AgentPrompts.map(ap => ap.ID);
|
|
3810
4162
|
const pendingAddIds = this.PendingRecords
|
|
3811
4163
|
.filter(p => p.entityObject.EntityInfo.Name === 'MJ: AI Agent Prompts' && p.action === 'save')
|
|
3812
4164
|
.map(p => p.entityObject.Get('PromptID'));
|
|
@@ -3821,9 +4173,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3821
4173
|
viewContainerRef: this.viewContainerRef
|
|
3822
4174
|
}).pipe(takeUntil(this.destroy$)).subscribe({
|
|
3823
4175
|
next: async (result) => {
|
|
3824
|
-
if (result && result.
|
|
4176
|
+
if (result && result.SelectedPrompts.length > 0) {
|
|
3825
4177
|
// Filter out already linked or pending prompts
|
|
3826
|
-
const newPrompts = result.
|
|
4178
|
+
const newPrompts = result.SelectedPrompts.filter(prompt => !allLinkedIds.some(id => UUIDsEqual(id, prompt.ID)));
|
|
3827
4179
|
if (newPrompts.length === 0) {
|
|
3828
4180
|
MJNotificationService.Instance.CreateSimpleNotification('All selected prompts are already linked to this agent', 'info', 3000);
|
|
3829
4181
|
return;
|
|
@@ -3842,9 +4194,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3842
4194
|
action: 'save'
|
|
3843
4195
|
});
|
|
3844
4196
|
}
|
|
3845
|
-
this.
|
|
4197
|
+
this.HasUnsavedChanges = true;
|
|
3846
4198
|
// Update UI to show the new prompts (cast to extended type for display)
|
|
3847
|
-
this.
|
|
4199
|
+
this.AgentPrompts.push(...newPrompts);
|
|
3848
4200
|
// Mark for check instead of forcing immediate detection
|
|
3849
4201
|
this.cdr.markForCheck();
|
|
3850
4202
|
// Show success notification
|
|
@@ -3866,10 +4218,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3866
4218
|
MJNotificationService.Instance.CreateSimpleNotification('Error adding prompts. Please try again.', 'error', 3000);
|
|
3867
4219
|
}
|
|
3868
4220
|
}
|
|
4221
|
+
/** @deprecated Use {@link AddPrompt}. */
|
|
4222
|
+
async addPrompt() {
|
|
4223
|
+
return this.AddPrompt();
|
|
4224
|
+
}
|
|
3869
4225
|
/**
|
|
3870
4226
|
* Handle context compression toggle and reset related fields when disabled
|
|
3871
4227
|
*/
|
|
3872
|
-
|
|
4228
|
+
OnContextCompressionToggle(value) {
|
|
3873
4229
|
const enabled = value === true || value === 'true';
|
|
3874
4230
|
if (!enabled) {
|
|
3875
4231
|
// Reset context compression related fields to null when disabled
|
|
@@ -3880,12 +4236,16 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3880
4236
|
this.cdr.markForCheck();
|
|
3881
4237
|
}
|
|
3882
4238
|
}
|
|
4239
|
+
/** @deprecated Use {@link OnContextCompressionToggle}. */
|
|
4240
|
+
onContextCompressionToggle(value) {
|
|
4241
|
+
return this.OnContextCompressionToggle(value);
|
|
4242
|
+
}
|
|
3883
4243
|
/**
|
|
3884
4244
|
* Opens the modern Add Action dialog for selecting actions (deferred until save)
|
|
3885
4245
|
*/
|
|
3886
|
-
async
|
|
4246
|
+
async ConfigureActions() {
|
|
3887
4247
|
// Get currently linked and pending action IDs for pre-selection
|
|
3888
|
-
const currentActionIds = this.
|
|
4248
|
+
const currentActionIds = this.AgentActions.map(aa => aa.ID);
|
|
3889
4249
|
const pendingAddIds = this.PendingRecords
|
|
3890
4250
|
.filter(p => p.entityObject.EntityInfo.Name === 'MJ: AI Agent Actions' && p.action === 'save')
|
|
3891
4251
|
.map(p => p.entityObject.Get('ActionID'));
|
|
@@ -3917,9 +4277,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3917
4277
|
action: 'save'
|
|
3918
4278
|
});
|
|
3919
4279
|
}
|
|
3920
|
-
this.
|
|
4280
|
+
this.HasUnsavedChanges = true;
|
|
3921
4281
|
// Update UI to show the new actions
|
|
3922
|
-
this.
|
|
4282
|
+
this.AgentActions.push(...newActions);
|
|
3923
4283
|
// Mark for check instead of forcing immediate detection
|
|
3924
4284
|
this.cdr.markForCheck();
|
|
3925
4285
|
// Show success notification
|
|
@@ -3932,10 +4292,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3932
4292
|
}
|
|
3933
4293
|
});
|
|
3934
4294
|
}
|
|
4295
|
+
/** @deprecated Use {@link ConfigureActions}. */
|
|
4296
|
+
async configureActions() {
|
|
4297
|
+
return this.ConfigureActions();
|
|
4298
|
+
}
|
|
3935
4299
|
/**
|
|
3936
4300
|
* Gets the status icon for execution runs
|
|
3937
4301
|
*/
|
|
3938
|
-
|
|
4302
|
+
GetExecutionStatusIcon(status) {
|
|
3939
4303
|
switch (status?.toLowerCase()) {
|
|
3940
4304
|
case 'completed':
|
|
3941
4305
|
case 'success':
|
|
@@ -3952,10 +4316,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3952
4316
|
return 'fa-solid fa-question-circle';
|
|
3953
4317
|
}
|
|
3954
4318
|
}
|
|
4319
|
+
/** @deprecated Use {@link GetExecutionStatusIcon}. */
|
|
4320
|
+
getExecutionStatusIcon(status) {
|
|
4321
|
+
return this.GetExecutionStatusIcon(status);
|
|
4322
|
+
}
|
|
3955
4323
|
/**
|
|
3956
4324
|
* Gets the status color for execution runs
|
|
3957
4325
|
*/
|
|
3958
|
-
|
|
4326
|
+
GetExecutionStatusColor(status) {
|
|
3959
4327
|
switch (status?.toLowerCase()) {
|
|
3960
4328
|
case 'completed':
|
|
3961
4329
|
case 'success':
|
|
@@ -3972,12 +4340,20 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3972
4340
|
return 'var(--mj-text-muted)';
|
|
3973
4341
|
}
|
|
3974
4342
|
}
|
|
4343
|
+
/** @deprecated Use {@link GetExecutionStatusColor}. */
|
|
4344
|
+
getExecutionStatusColor(status) {
|
|
4345
|
+
return this.GetExecutionStatusColor(status);
|
|
4346
|
+
}
|
|
3975
4347
|
// ────────────────────────────────────────────────────────────────────
|
|
3976
4348
|
// Voice/Realtime Sessions (Execution History peer record type)
|
|
3977
4349
|
// ────────────────────────────────────────────────────────────────────
|
|
3978
4350
|
/** Switches the Execution History section between agent runs and voice sessions. */
|
|
4351
|
+
SetExecutionHistoryView(view) {
|
|
4352
|
+
this.ExecutionHistoryView = view;
|
|
4353
|
+
}
|
|
4354
|
+
/** @deprecated Use {@link SetExecutionHistoryView}. */
|
|
3979
4355
|
setExecutionHistoryView(view) {
|
|
3980
|
-
this.
|
|
4356
|
+
return this.SetExecutionHistoryView(view);
|
|
3981
4357
|
}
|
|
3982
4358
|
/**
|
|
3983
4359
|
* Loads the realtime voice sessions this agent participated in — either as
|
|
@@ -3991,7 +4367,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
3991
4367
|
if (!this.record?.ID || !this.UserCanViewSessions) {
|
|
3992
4368
|
return;
|
|
3993
4369
|
}
|
|
3994
|
-
this.
|
|
4370
|
+
this.LoadingSessions = true;
|
|
3995
4371
|
try {
|
|
3996
4372
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
3997
4373
|
const result = await rv.RunView({
|
|
@@ -4007,8 +4383,8 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4007
4383
|
const items = (result.Results ?? [])
|
|
4008
4384
|
.map(row => this.buildSessionHistoryItem(row))
|
|
4009
4385
|
.filter(item => item.isCoAgent || item.isTarget);
|
|
4010
|
-
this.
|
|
4011
|
-
this.
|
|
4386
|
+
this.AgentSessions = items;
|
|
4387
|
+
this.TotalSessionCount = items.length;
|
|
4012
4388
|
await this.loadSessionChannelCounts(items);
|
|
4013
4389
|
}
|
|
4014
4390
|
else {
|
|
@@ -4019,7 +4395,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4019
4395
|
console.error('Error loading agent sessions:', error);
|
|
4020
4396
|
}
|
|
4021
4397
|
finally {
|
|
4022
|
-
this.
|
|
4398
|
+
this.LoadingSessions = false;
|
|
4023
4399
|
this.cdr.markForCheck();
|
|
4024
4400
|
}
|
|
4025
4401
|
}
|
|
@@ -4073,7 +4449,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4073
4449
|
}
|
|
4074
4450
|
}
|
|
4075
4451
|
/** Status color for a session lifecycle status (Active / Idle / Closed). */
|
|
4076
|
-
|
|
4452
|
+
GetSessionStatusColor(status) {
|
|
4077
4453
|
switch (status) {
|
|
4078
4454
|
case 'Active':
|
|
4079
4455
|
return 'var(--mj-status-success)';
|
|
@@ -4085,8 +4461,12 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4085
4461
|
return 'var(--mj-text-muted)';
|
|
4086
4462
|
}
|
|
4087
4463
|
}
|
|
4464
|
+
/** @deprecated Use {@link GetSessionStatusColor}. */
|
|
4465
|
+
getSessionStatusColor(status) {
|
|
4466
|
+
return this.GetSessionStatusColor(status);
|
|
4467
|
+
}
|
|
4088
4468
|
/** Status icon for a session lifecycle status. */
|
|
4089
|
-
|
|
4469
|
+
GetSessionStatusIcon(status) {
|
|
4090
4470
|
switch (status) {
|
|
4091
4471
|
case 'Active':
|
|
4092
4472
|
return 'fa-solid fa-tower-broadcast';
|
|
@@ -4098,18 +4478,30 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4098
4478
|
return 'fa-solid fa-question-circle';
|
|
4099
4479
|
}
|
|
4100
4480
|
}
|
|
4481
|
+
/** @deprecated Use {@link GetSessionStatusIcon}. */
|
|
4482
|
+
getSessionStatusIcon(status) {
|
|
4483
|
+
return this.GetSessionStatusIcon(status);
|
|
4484
|
+
}
|
|
4101
4485
|
/** Session duration: created → closed (terminal) or last-active (still open). */
|
|
4102
|
-
|
|
4486
|
+
FormatSessionDuration(item) {
|
|
4103
4487
|
const end = item.row.ClosedAt ?? item.row.LastActiveAt;
|
|
4104
4488
|
if (!end)
|
|
4105
4489
|
return 'N/A';
|
|
4106
|
-
return this.
|
|
4490
|
+
return this.FormatExecutionTimeFromDates(item.row.__mj_CreatedAt, end);
|
|
4491
|
+
}
|
|
4492
|
+
/** @deprecated Use {@link FormatSessionDuration}. */
|
|
4493
|
+
formatSessionDuration(item) {
|
|
4494
|
+
return this.FormatSessionDuration(item);
|
|
4107
4495
|
}
|
|
4108
4496
|
/** Opens an AI Agent Session record (renders via the custom session form). */
|
|
4109
|
-
|
|
4497
|
+
OpenSessionRecord(sessionId) {
|
|
4110
4498
|
this.sharedService.OpenEntityRecord('MJ: AI Agent Sessions', CompositeKey.FromID(sessionId));
|
|
4111
4499
|
}
|
|
4112
|
-
|
|
4500
|
+
/** @deprecated Use {@link OpenSessionRecord}. */
|
|
4501
|
+
openSessionRecord(sessionId) {
|
|
4502
|
+
return this.OpenSessionRecord(sessionId);
|
|
4503
|
+
}
|
|
4504
|
+
FormatExecutionTimeFromDates(startDate, endDate) {
|
|
4113
4505
|
if (!startDate || !endDate)
|
|
4114
4506
|
return 'N/A';
|
|
4115
4507
|
// check to see if we have dates or timestamps
|
|
@@ -4136,12 +4528,16 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4136
4528
|
if (isNaN(startTime) || isNaN(endTime))
|
|
4137
4529
|
return 'N/A';
|
|
4138
4530
|
const milliseconds = endTime - startTime;
|
|
4139
|
-
return this.
|
|
4531
|
+
return this.FormatExecutionTime(milliseconds);
|
|
4532
|
+
}
|
|
4533
|
+
/** @deprecated Use {@link FormatExecutionTimeFromDates}. */
|
|
4534
|
+
formatExecutionTimeFromDates(startDate, endDate) {
|
|
4535
|
+
return this.FormatExecutionTimeFromDates(startDate, endDate);
|
|
4140
4536
|
}
|
|
4141
4537
|
/**
|
|
4142
4538
|
* Formats execution time
|
|
4143
4539
|
*/
|
|
4144
|
-
|
|
4540
|
+
FormatExecutionTime(milliseconds) {
|
|
4145
4541
|
if (!milliseconds)
|
|
4146
4542
|
return 'N/A';
|
|
4147
4543
|
if (milliseconds >= 60000) {
|
|
@@ -4156,10 +4552,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4156
4552
|
return `${milliseconds}ms`;
|
|
4157
4553
|
}
|
|
4158
4554
|
}
|
|
4555
|
+
/** @deprecated Use {@link FormatExecutionTime}. */
|
|
4556
|
+
formatExecutionTime(milliseconds) {
|
|
4557
|
+
return this.FormatExecutionTime(milliseconds);
|
|
4558
|
+
}
|
|
4159
4559
|
/**
|
|
4160
4560
|
* Formats token count with appropriate units (K for thousands, M for millions)
|
|
4161
4561
|
*/
|
|
4162
|
-
|
|
4562
|
+
FormatTokenCount(tokens) {
|
|
4163
4563
|
if (tokens == null || tokens === 0)
|
|
4164
4564
|
return '0';
|
|
4165
4565
|
if (tokens >= 1000000) {
|
|
@@ -4172,10 +4572,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4172
4572
|
return tokens.toString();
|
|
4173
4573
|
}
|
|
4174
4574
|
}
|
|
4575
|
+
/** @deprecated Use {@link FormatTokenCount}. */
|
|
4576
|
+
formatTokenCount(tokens) {
|
|
4577
|
+
return this.FormatTokenCount(tokens);
|
|
4578
|
+
}
|
|
4175
4579
|
/**
|
|
4176
4580
|
* Formats cost with appropriate precision
|
|
4177
4581
|
*/
|
|
4178
|
-
|
|
4582
|
+
FormatCost(cost) {
|
|
4179
4583
|
if (cost == null || cost === 0)
|
|
4180
4584
|
return '0.00';
|
|
4181
4585
|
if (cost >= 1) {
|
|
@@ -4188,7 +4592,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4188
4592
|
return cost.toFixed(4);
|
|
4189
4593
|
}
|
|
4190
4594
|
}
|
|
4191
|
-
|
|
4595
|
+
/** @deprecated Use {@link FormatCost}. */
|
|
4596
|
+
formatCost(cost) {
|
|
4597
|
+
return this.FormatCost(cost);
|
|
4598
|
+
}
|
|
4599
|
+
GetRunningTime(startDate) {
|
|
4192
4600
|
if (!startDate)
|
|
4193
4601
|
return 'N/A';
|
|
4194
4602
|
const startTime = new Date(startDate).getTime();
|
|
@@ -4200,13 +4608,17 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4200
4608
|
// Update cache every second to avoid constant changes
|
|
4201
4609
|
if (!cached || now - cached.timestamp > 1000) {
|
|
4202
4610
|
const milliseconds = now - startTime;
|
|
4203
|
-
const timeString = this.
|
|
4611
|
+
const timeString = this.FormatExecutionTime(milliseconds);
|
|
4204
4612
|
this._runningTimeCache.set(cacheKey, { time: timeString, timestamp: now });
|
|
4205
4613
|
// Don't trigger change detection here - let the background timer handle it
|
|
4206
4614
|
return timeString;
|
|
4207
4615
|
}
|
|
4208
4616
|
return cached.time;
|
|
4209
4617
|
}
|
|
4618
|
+
/** @deprecated Use {@link GetRunningTime}. */
|
|
4619
|
+
getRunningTime(startDate) {
|
|
4620
|
+
return this.GetRunningTime(startDate);
|
|
4621
|
+
}
|
|
4210
4622
|
/**
|
|
4211
4623
|
* Starts the background timer for updating running times
|
|
4212
4624
|
*/
|
|
@@ -4229,39 +4641,55 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4229
4641
|
/**
|
|
4230
4642
|
* Gets the priority badge color
|
|
4231
4643
|
*/
|
|
4232
|
-
|
|
4644
|
+
GetPriorityBadgeColor(priority) {
|
|
4233
4645
|
if (priority <= 1)
|
|
4234
4646
|
return 'var(--mj-status-error)'; // High priority - red
|
|
4235
4647
|
if (priority <= 5)
|
|
4236
4648
|
return 'var(--mj-status-warning)'; // Medium priority - yellow
|
|
4237
4649
|
return 'var(--mj-status-success)'; // Low priority - green
|
|
4238
4650
|
}
|
|
4651
|
+
/** @deprecated Use {@link GetPriorityBadgeColor}. */
|
|
4652
|
+
getPriorityBadgeColor(priority) {
|
|
4653
|
+
return this.GetPriorityBadgeColor(priority);
|
|
4654
|
+
}
|
|
4239
4655
|
/**
|
|
4240
4656
|
* Gets the priority label
|
|
4241
4657
|
*/
|
|
4242
|
-
|
|
4658
|
+
GetPriorityLabel(priority) {
|
|
4243
4659
|
if (priority <= 1)
|
|
4244
4660
|
return 'High';
|
|
4245
4661
|
if (priority <= 5)
|
|
4246
4662
|
return 'Medium';
|
|
4247
4663
|
return 'Low';
|
|
4248
4664
|
}
|
|
4665
|
+
/** @deprecated Use {@link GetPriorityLabel}. */
|
|
4666
|
+
getPriorityLabel(priority) {
|
|
4667
|
+
return this.GetPriorityLabel(priority);
|
|
4668
|
+
}
|
|
4249
4669
|
/**
|
|
4250
4670
|
* Navigates to a related entity
|
|
4251
4671
|
*/
|
|
4252
|
-
|
|
4672
|
+
NavigateToEntity(entityName, recordId) {
|
|
4253
4673
|
this.sharedService.OpenEntityRecord(entityName, CompositeKey.FromURLSegment(this.ProviderToUse.EntityByName(entityName), recordId));
|
|
4254
4674
|
}
|
|
4675
|
+
/** @deprecated Use {@link NavigateToEntity}. */
|
|
4676
|
+
navigateToEntity(entityName, recordId) {
|
|
4677
|
+
return this.NavigateToEntity(entityName, recordId);
|
|
4678
|
+
}
|
|
4255
4679
|
/**
|
|
4256
4680
|
* Toggles the expanded state of an execution card
|
|
4257
4681
|
*/
|
|
4682
|
+
ToggleExecutionExpanded(executionId) {
|
|
4683
|
+
this.ExpandedExecutions[executionId] = !this.ExpandedExecutions[executionId];
|
|
4684
|
+
}
|
|
4685
|
+
/** @deprecated Use {@link ToggleExecutionExpanded}. */
|
|
4258
4686
|
toggleExecutionExpanded(executionId) {
|
|
4259
|
-
|
|
4687
|
+
return this.ToggleExecutionExpanded(executionId);
|
|
4260
4688
|
}
|
|
4261
4689
|
/**
|
|
4262
4690
|
* Handles search text changes - debounced to avoid excessive processing
|
|
4263
4691
|
*/
|
|
4264
|
-
|
|
4692
|
+
OnExecutionSearchChange() {
|
|
4265
4693
|
// Debounce search to avoid excessive processing during typing
|
|
4266
4694
|
if (this._searchDebounceTimer) {
|
|
4267
4695
|
clearTimeout(this._searchDebounceTimer);
|
|
@@ -4270,21 +4698,25 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4270
4698
|
this.applySearchFilter();
|
|
4271
4699
|
}, 300);
|
|
4272
4700
|
}
|
|
4701
|
+
/** @deprecated Use {@link OnExecutionSearchChange}. */
|
|
4702
|
+
onExecutionSearchChange() {
|
|
4703
|
+
return this.OnExecutionSearchChange();
|
|
4704
|
+
}
|
|
4273
4705
|
/**
|
|
4274
4706
|
* Applies search filter across all cached records and loads from database if needed
|
|
4275
4707
|
*/
|
|
4276
4708
|
async applySearchFilter() {
|
|
4277
|
-
if (!this.
|
|
4709
|
+
if (!this.ExecutionSearchText || this.ExecutionSearchText.trim() === '') {
|
|
4278
4710
|
// No search text - show current page's executions
|
|
4279
|
-
this.
|
|
4711
|
+
this.FilteredExecutions = [...this.RecentExecutions];
|
|
4280
4712
|
return;
|
|
4281
4713
|
}
|
|
4282
|
-
const searchLower = this.
|
|
4714
|
+
const searchLower = this.ExecutionSearchText.toLowerCase().trim();
|
|
4283
4715
|
// First, search across all cached records
|
|
4284
4716
|
const cachedMatches = this.allLoadedExecutions.filter(execution => execution && execution.ID.toLowerCase().includes(searchLower));
|
|
4285
4717
|
if (cachedMatches.length > 0) {
|
|
4286
4718
|
// Found matches in cache
|
|
4287
|
-
this.
|
|
4719
|
+
this.FilteredExecutions = cachedMatches;
|
|
4288
4720
|
}
|
|
4289
4721
|
else {
|
|
4290
4722
|
// No matches in cache - search database
|
|
@@ -4313,27 +4745,31 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4313
4745
|
ResultType: 'entity_object'
|
|
4314
4746
|
});
|
|
4315
4747
|
if (result.Success && result.Results) {
|
|
4316
|
-
this.
|
|
4748
|
+
this.FilteredExecutions = result.Results;
|
|
4317
4749
|
}
|
|
4318
4750
|
else {
|
|
4319
|
-
this.
|
|
4751
|
+
this.FilteredExecutions = [];
|
|
4320
4752
|
}
|
|
4321
4753
|
}
|
|
4322
4754
|
catch (error) {
|
|
4323
4755
|
console.error('Error searching executions:', error);
|
|
4324
|
-
this.
|
|
4756
|
+
this.FilteredExecutions = [];
|
|
4325
4757
|
}
|
|
4326
4758
|
}
|
|
4327
4759
|
/**
|
|
4328
4760
|
* Opens the full execution record in a new view
|
|
4329
4761
|
*/
|
|
4330
|
-
|
|
4762
|
+
OpenExecutionRecord(executionId) {
|
|
4331
4763
|
this.sharedService.OpenEntityRecord('MJ: AI Agent Runs', CompositeKey.FromID(executionId));
|
|
4332
4764
|
}
|
|
4765
|
+
/** @deprecated Use {@link OpenExecutionRecord}. */
|
|
4766
|
+
openExecutionRecord(executionId) {
|
|
4767
|
+
return this.OpenExecutionRecord(executionId);
|
|
4768
|
+
}
|
|
4333
4769
|
/**
|
|
4334
4770
|
* Gets a preview of the execution result for collapsed view
|
|
4335
4771
|
*/
|
|
4336
|
-
|
|
4772
|
+
GetExecutionResultPreview(execution, trimLongMessages) {
|
|
4337
4773
|
try {
|
|
4338
4774
|
if (!execution.Result)
|
|
4339
4775
|
return 'No result';
|
|
@@ -4363,10 +4799,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4363
4799
|
return result;
|
|
4364
4800
|
}
|
|
4365
4801
|
}
|
|
4802
|
+
/** @deprecated Use {@link GetExecutionResultPreview}. */
|
|
4803
|
+
getExecutionResultPreview(execution, trimLongMessages) {
|
|
4804
|
+
return this.GetExecutionResultPreview(execution, trimLongMessages);
|
|
4805
|
+
}
|
|
4366
4806
|
/**
|
|
4367
4807
|
* Gets the full execution result message for expanded view
|
|
4368
4808
|
*/
|
|
4369
|
-
|
|
4809
|
+
GetExecutionResultMessage(execution) {
|
|
4370
4810
|
try {
|
|
4371
4811
|
if (!execution.Result)
|
|
4372
4812
|
return 'No result';
|
|
@@ -4384,38 +4824,58 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4384
4824
|
return execution.Result || '';
|
|
4385
4825
|
}
|
|
4386
4826
|
}
|
|
4827
|
+
/** @deprecated Use {@link GetExecutionResultMessage}. */
|
|
4828
|
+
getExecutionResultMessage(execution) {
|
|
4829
|
+
return this.GetExecutionResultMessage(execution);
|
|
4830
|
+
}
|
|
4387
4831
|
/**
|
|
4388
4832
|
* Refreshes the related data and updates snapshots
|
|
4389
4833
|
*/
|
|
4390
|
-
async
|
|
4834
|
+
async RefreshRelatedData() {
|
|
4391
4835
|
if (this.record?.ID) {
|
|
4392
4836
|
await this.loadRelatedCounts(true); // force refresh
|
|
4393
4837
|
MJNotificationService.Instance.CreateSimpleNotification('Related data refreshed', 'success', 2000);
|
|
4394
4838
|
}
|
|
4395
4839
|
}
|
|
4840
|
+
/** @deprecated Use {@link RefreshRelatedData}. */
|
|
4841
|
+
async refreshRelatedData() {
|
|
4842
|
+
return this.RefreshRelatedData();
|
|
4843
|
+
}
|
|
4396
4844
|
/**
|
|
4397
4845
|
* Manually refreshes the snapshot for cancel/revert functionality
|
|
4398
4846
|
* Useful when you want to reset the "original state" to the current state
|
|
4399
4847
|
*/
|
|
4400
|
-
|
|
4848
|
+
RefreshSnapshot() {
|
|
4401
4849
|
this.createOriginalSnapshot();
|
|
4402
4850
|
MJNotificationService.Instance.CreateSimpleNotification('Current state saved as new baseline', 'info', 2000);
|
|
4403
4851
|
}
|
|
4852
|
+
/** @deprecated Use {@link RefreshSnapshot}. */
|
|
4853
|
+
refreshSnapshot() {
|
|
4854
|
+
return this.RefreshSnapshot();
|
|
4855
|
+
}
|
|
4404
4856
|
/**
|
|
4405
4857
|
* Debug method to check current pending records state
|
|
4406
4858
|
* Useful for troubleshooting cancel/revert issues
|
|
4407
4859
|
*/
|
|
4408
|
-
|
|
4860
|
+
DebugPendingRecords() {
|
|
4409
4861
|
// Debug method for troubleshooting - console output removed for production
|
|
4410
4862
|
}
|
|
4863
|
+
/** @deprecated Use {@link DebugPendingRecords}. */
|
|
4864
|
+
debugPendingRecords() {
|
|
4865
|
+
return this.DebugPendingRecords();
|
|
4866
|
+
}
|
|
4411
4867
|
/**
|
|
4412
4868
|
* Adds a new note to the agent
|
|
4413
4869
|
*/
|
|
4414
|
-
|
|
4870
|
+
AddNote() {
|
|
4415
4871
|
MJNotificationService.Instance.CreateSimpleNotification('Opening new note form...', 'info', 2000);
|
|
4416
4872
|
// In a full implementation, this would open a new AI Agent Note form
|
|
4417
4873
|
// with AgentID pre-populated to this.record.ID
|
|
4418
4874
|
}
|
|
4875
|
+
/** @deprecated Use {@link AddNote}. */
|
|
4876
|
+
addNote() {
|
|
4877
|
+
return this.AddNote();
|
|
4878
|
+
}
|
|
4419
4879
|
/**
|
|
4420
4880
|
* Creates a new prompt and links it to the agent
|
|
4421
4881
|
*/
|
|
@@ -4438,11 +4898,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4438
4898
|
action: 'save'
|
|
4439
4899
|
});
|
|
4440
4900
|
// Add template to PendingRecords if created
|
|
4441
|
-
if (result.
|
|
4901
|
+
if (result.Template) {
|
|
4442
4902
|
// Set UserID on template (required field)
|
|
4443
|
-
result.
|
|
4903
|
+
result.Template.UserID = currentUserId;
|
|
4444
4904
|
this.PendingRecords.push({
|
|
4445
|
-
entityObject: result.
|
|
4905
|
+
entityObject: result.Template,
|
|
4446
4906
|
action: 'save'
|
|
4447
4907
|
});
|
|
4448
4908
|
}
|
|
@@ -4468,9 +4928,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4468
4928
|
entityObject: agentPrompt,
|
|
4469
4929
|
action: 'save'
|
|
4470
4930
|
});
|
|
4471
|
-
this.
|
|
4931
|
+
this.HasUnsavedChanges = true;
|
|
4472
4932
|
// Update UI to show the new prompt
|
|
4473
|
-
this.
|
|
4933
|
+
this.AgentPrompts.push(result.prompt);
|
|
4474
4934
|
// Trigger change detection to update UI
|
|
4475
4935
|
this.cdr.detectChanges();
|
|
4476
4936
|
MJNotificationService.Instance.CreateSimpleNotification(`New prompt "${result.prompt.Name}" will be created and linked when you save the agent`, 'success', 4000);
|
|
@@ -4495,7 +4955,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4495
4955
|
/**
|
|
4496
4956
|
* Removes a prompt from the agent (deferred until save)
|
|
4497
4957
|
*/
|
|
4498
|
-
async
|
|
4958
|
+
async RemovePrompt(prompt, event) {
|
|
4499
4959
|
event.stopPropagation(); // Prevent navigation
|
|
4500
4960
|
const confirmDialog = this.dialogService.open({
|
|
4501
4961
|
title: 'Remove Prompt',
|
|
@@ -4540,11 +5000,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4540
5000
|
}
|
|
4541
5001
|
}
|
|
4542
5002
|
// Remove from UI immediately
|
|
4543
|
-
const promptIndex = this.
|
|
5003
|
+
const promptIndex = this.AgentPrompts.findIndex(p => UUIDsEqual(p.ID, prompt.ID));
|
|
4544
5004
|
if (promptIndex >= 0) {
|
|
4545
|
-
this.
|
|
5005
|
+
this.AgentPrompts.splice(promptIndex, 1);
|
|
4546
5006
|
}
|
|
4547
|
-
this.
|
|
5007
|
+
this.HasUnsavedChanges = true;
|
|
4548
5008
|
// Mark for check instead of forcing immediate detection
|
|
4549
5009
|
this.cdr.markForCheck();
|
|
4550
5010
|
MJNotificationService.Instance.CreateSimpleNotification(`Prompt "${prompt.Name}" will be removed when you save the agent`, 'info', 4000);
|
|
@@ -4559,20 +5019,28 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4559
5019
|
console.error('Error with dialog:', dialogError);
|
|
4560
5020
|
}
|
|
4561
5021
|
}
|
|
5022
|
+
/** @deprecated Use {@link RemovePrompt}. */
|
|
5023
|
+
async removePrompt(prompt, event) {
|
|
5024
|
+
return this.RemovePrompt(prompt, event);
|
|
5025
|
+
}
|
|
4562
5026
|
/**
|
|
4563
5027
|
* Updates payload field values from code editor
|
|
4564
5028
|
*/
|
|
4565
|
-
|
|
5029
|
+
UpdatePayloadField(fieldName, value) {
|
|
4566
5030
|
if (this.record) {
|
|
4567
5031
|
// Handle the value - it might be a string or an event
|
|
4568
5032
|
const newValue = typeof value === 'string' ? value : value?.target?.value || value;
|
|
4569
5033
|
this.record[fieldName] = newValue;
|
|
4570
5034
|
}
|
|
4571
5035
|
}
|
|
5036
|
+
/** @deprecated Use {@link UpdatePayloadField}. */
|
|
5037
|
+
updatePayloadField(fieldName, value) {
|
|
5038
|
+
return this.UpdatePayloadField(fieldName, value);
|
|
5039
|
+
}
|
|
4572
5040
|
/**
|
|
4573
5041
|
* Opens the sub-agent selector dialog for adding sub-agents (deferred until save)
|
|
4574
5042
|
*/
|
|
4575
|
-
async
|
|
5043
|
+
async AddSubAgents() {
|
|
4576
5044
|
try {
|
|
4577
5045
|
// Get list of already pending sub-agent IDs to filter duplicates
|
|
4578
5046
|
const pendingSubAgentIds = this.PendingRecords
|
|
@@ -4580,7 +5048,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4580
5048
|
p.action === 'save' &&
|
|
4581
5049
|
p.entityObject.Get('ParentID') === this.record.ID)
|
|
4582
5050
|
.map(p => p.entityObject.Get('ID'));
|
|
4583
|
-
const existingSubAgentIds = this.
|
|
5051
|
+
const existingSubAgentIds = this.SubAgents.map(agent => agent.ID);
|
|
4584
5052
|
const allLinkedIds = [...pendingSubAgentIds, ...existingSubAgentIds];
|
|
4585
5053
|
this.agentManagementService.openSubAgentSelectorDialog({
|
|
4586
5054
|
title: 'Add Sub-Agents',
|
|
@@ -4590,9 +5058,9 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4590
5058
|
viewContainerRef: this.viewContainerRef
|
|
4591
5059
|
}).pipe(takeUntil(this.destroy$)).subscribe({
|
|
4592
5060
|
next: async (result) => {
|
|
4593
|
-
if (result && result.
|
|
5061
|
+
if (result && result.SelectedAgents && result.SelectedAgents.length > 0) {
|
|
4594
5062
|
// Filter out already linked or pending agents
|
|
4595
|
-
const newAgents = result.
|
|
5063
|
+
const newAgents = result.SelectedAgents.filter(agent => !allLinkedIds.some(id => UUIDsEqual(id, agent.ID)));
|
|
4596
5064
|
if (newAgents.length === 0) {
|
|
4597
5065
|
MJNotificationService.Instance.CreateSimpleNotification('All selected agents are already linked to this agent', 'info', 3000);
|
|
4598
5066
|
return;
|
|
@@ -4610,17 +5078,17 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4610
5078
|
action: 'save'
|
|
4611
5079
|
});
|
|
4612
5080
|
}
|
|
4613
|
-
this.
|
|
5081
|
+
this.HasUnsavedChanges = true;
|
|
4614
5082
|
// Update UI to show the new sub-agents
|
|
4615
|
-
this.
|
|
5083
|
+
this.SubAgents.push(...newAgents);
|
|
4616
5084
|
// Mark for check instead of forcing immediate detection
|
|
4617
5085
|
this.cdr.markForCheck();
|
|
4618
5086
|
// Show success notification
|
|
4619
5087
|
MJNotificationService.Instance.CreateSimpleNotification(`${newAgents.length} agent${newAgents.length === 1 ? '' : 's'} will be converted to sub-agent${newAgents.length === 1 ? '' : 's'} when you save`, 'info', 4000);
|
|
4620
5088
|
}
|
|
4621
|
-
else if (result && result.
|
|
5089
|
+
else if (result && result.CreateNew) {
|
|
4622
5090
|
// User wants to create a new sub-agent
|
|
4623
|
-
await this.
|
|
5091
|
+
await this.CreateSubAgent();
|
|
4624
5092
|
}
|
|
4625
5093
|
},
|
|
4626
5094
|
error: (error) => {
|
|
@@ -4634,10 +5102,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4634
5102
|
MJNotificationService.Instance.CreateSimpleNotification('Error adding sub-agents. Please try again.', 'error', 3000);
|
|
4635
5103
|
}
|
|
4636
5104
|
}
|
|
5105
|
+
/** @deprecated Use {@link AddSubAgents}. */
|
|
5106
|
+
async addSubAgents() {
|
|
5107
|
+
return this.AddSubAgents();
|
|
5108
|
+
}
|
|
4637
5109
|
/**
|
|
4638
5110
|
* Removes a sub-agent from this agent (deferred until save)
|
|
4639
5111
|
*/
|
|
4640
|
-
async
|
|
5112
|
+
async RemoveSubAgent(subAgent, event) {
|
|
4641
5113
|
event.stopPropagation(); // Prevent navigation
|
|
4642
5114
|
const confirmDialog = this.dialogService.open({
|
|
4643
5115
|
title: 'Remove Sub-Agent',
|
|
@@ -4674,11 +5146,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4674
5146
|
});
|
|
4675
5147
|
}
|
|
4676
5148
|
// Remove from UI immediately
|
|
4677
|
-
const subAgentIndex = this.
|
|
5149
|
+
const subAgentIndex = this.SubAgents.findIndex(sa => UUIDsEqual(sa.ID, subAgent.ID));
|
|
4678
5150
|
if (subAgentIndex >= 0) {
|
|
4679
|
-
this.
|
|
5151
|
+
this.SubAgents.splice(subAgentIndex, 1);
|
|
4680
5152
|
}
|
|
4681
|
-
this.
|
|
5153
|
+
this.HasUnsavedChanges = true;
|
|
4682
5154
|
// Mark for check instead of forcing immediate detection
|
|
4683
5155
|
this.cdr.markForCheck();
|
|
4684
5156
|
MJNotificationService.Instance.CreateSimpleNotification(`"${subAgent.Name}" will be removed as a sub-agent when you save`, 'info', 4000);
|
|
@@ -4693,34 +5165,54 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4693
5165
|
console.error('Error with dialog:', dialogError);
|
|
4694
5166
|
}
|
|
4695
5167
|
}
|
|
5168
|
+
/** @deprecated Use {@link RemoveSubAgent}. */
|
|
5169
|
+
async removeSubAgent(subAgent, event) {
|
|
5170
|
+
return this.RemoveSubAgent(subAgent, event);
|
|
5171
|
+
}
|
|
4696
5172
|
/**
|
|
4697
5173
|
* Sets the sub-agent filter to show all, child, or related sub-agents
|
|
4698
5174
|
*/
|
|
5175
|
+
SetSubAgentFilter(filter) {
|
|
5176
|
+
this.SubAgentFilter = filter;
|
|
5177
|
+
}
|
|
5178
|
+
/** @deprecated Use {@link SetSubAgentFilter}. */
|
|
4699
5179
|
setSubAgentFilter(filter) {
|
|
4700
|
-
this.
|
|
5180
|
+
return this.SetSubAgentFilter(filter);
|
|
4701
5181
|
}
|
|
4702
5182
|
/**
|
|
4703
5183
|
* Gets the badge color for a sub-agent based on its type
|
|
4704
5184
|
*/
|
|
4705
|
-
|
|
5185
|
+
GetSubAgentBadgeColor(item) {
|
|
4706
5186
|
return item.type === 'child' ? 'var(--mj-status-info)' : 'var(--mj-brand-primary)';
|
|
4707
5187
|
}
|
|
5188
|
+
/** @deprecated Use {@link GetSubAgentBadgeColor}. */
|
|
5189
|
+
getSubAgentBadgeColor(item) {
|
|
5190
|
+
return this.GetSubAgentBadgeColor(item);
|
|
5191
|
+
}
|
|
4708
5192
|
/**
|
|
4709
5193
|
* Gets the badge icon for a sub-agent based on its type
|
|
4710
5194
|
*/
|
|
4711
|
-
|
|
5195
|
+
GetSubAgentBadgeIcon(item) {
|
|
4712
5196
|
return item.type === 'child' ? 'fa-solid fa-link' : 'fa-solid fa-share-nodes';
|
|
4713
5197
|
}
|
|
5198
|
+
/** @deprecated Use {@link GetSubAgentBadgeIcon}. */
|
|
5199
|
+
getSubAgentBadgeIcon(item) {
|
|
5200
|
+
return this.GetSubAgentBadgeIcon(item);
|
|
5201
|
+
}
|
|
4714
5202
|
/**
|
|
4715
5203
|
* Gets the badge text for a sub-agent based on its type
|
|
4716
5204
|
*/
|
|
4717
|
-
|
|
5205
|
+
GetSubAgentBadgeText(item) {
|
|
4718
5206
|
return item.type === 'child' ? 'CHILD' : 'RELATED';
|
|
4719
5207
|
}
|
|
5208
|
+
/** @deprecated Use {@link GetSubAgentBadgeText}. */
|
|
5209
|
+
getSubAgentBadgeText(item) {
|
|
5210
|
+
return this.GetSubAgentBadgeText(item);
|
|
5211
|
+
}
|
|
4720
5212
|
/**
|
|
4721
5213
|
* Gets the payload information string for display
|
|
4722
5214
|
*/
|
|
4723
|
-
|
|
5215
|
+
GetSubAgentPayloadInfo(item) {
|
|
4724
5216
|
if (item.type === 'child') {
|
|
4725
5217
|
return 'Shared Payload';
|
|
4726
5218
|
}
|
|
@@ -4739,20 +5231,28 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4739
5231
|
}
|
|
4740
5232
|
return 'No Mapping';
|
|
4741
5233
|
}
|
|
5234
|
+
/** @deprecated Use {@link GetSubAgentPayloadInfo}. */
|
|
5235
|
+
getSubAgentPayloadInfo(item) {
|
|
5236
|
+
return this.GetSubAgentPayloadInfo(item);
|
|
5237
|
+
}
|
|
4742
5238
|
/**
|
|
4743
5239
|
* Opens a dialog to configure the output mapping for a related sub-agent
|
|
4744
5240
|
*/
|
|
4745
|
-
async
|
|
5241
|
+
async ConfigureOutputMapping(item, event) {
|
|
4746
5242
|
event.stopPropagation();
|
|
4747
5243
|
if (item.type !== 'related' || !item.relationship)
|
|
4748
5244
|
return;
|
|
4749
5245
|
// TODO: Implement JSON editor dialog for SubAgentOutputMapping
|
|
4750
5246
|
MJNotificationService.Instance.CreateSimpleNotification('Output mapping configuration coming soon', 'info', 3000);
|
|
4751
5247
|
}
|
|
5248
|
+
/** @deprecated Use {@link ConfigureOutputMapping}. */
|
|
5249
|
+
async configureOutputMapping(item, event) {
|
|
5250
|
+
return this.ConfigureOutputMapping(item, event);
|
|
5251
|
+
}
|
|
4752
5252
|
/**
|
|
4753
5253
|
* Unlinks a related sub-agent (removes the relationship)
|
|
4754
5254
|
*/
|
|
4755
|
-
async
|
|
5255
|
+
async UnlinkRelatedSubAgent(item, event) {
|
|
4756
5256
|
event.stopPropagation();
|
|
4757
5257
|
if (item.type !== 'related' || !item.relationship)
|
|
4758
5258
|
return;
|
|
@@ -4794,30 +5294,46 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4794
5294
|
console.error('Error with dialog:', dialogError);
|
|
4795
5295
|
}
|
|
4796
5296
|
}
|
|
5297
|
+
/** @deprecated Use {@link UnlinkRelatedSubAgent}. */
|
|
5298
|
+
async unlinkRelatedSubAgent(item, event) {
|
|
5299
|
+
return this.UnlinkRelatedSubAgent(item, event);
|
|
5300
|
+
}
|
|
4797
5301
|
/**
|
|
4798
5302
|
* Removes a child sub-agent (updated to work with UnifiedSubAgent)
|
|
4799
5303
|
*/
|
|
4800
|
-
async
|
|
5304
|
+
async RemoveChildSubAgent(item, event) {
|
|
4801
5305
|
// Delegate to existing removeSubAgent method
|
|
4802
|
-
await this.
|
|
5306
|
+
await this.RemoveSubAgent(item.agent, event);
|
|
5307
|
+
}
|
|
5308
|
+
/** @deprecated Use {@link RemoveChildSubAgent}. */
|
|
5309
|
+
async removeChildSubAgent(item, event) {
|
|
5310
|
+
return this.RemoveChildSubAgent(item, event);
|
|
4803
5311
|
}
|
|
4804
5312
|
/**
|
|
4805
5313
|
* Creates a new child sub-agent (renamed from createSubAgent for clarity)
|
|
4806
5314
|
*/
|
|
5315
|
+
async CreateChildSubAgent() {
|
|
5316
|
+
await this.CreateSubAgent();
|
|
5317
|
+
}
|
|
5318
|
+
/** @deprecated Use {@link CreateChildSubAgent}. */
|
|
4807
5319
|
async createChildSubAgent() {
|
|
4808
|
-
|
|
5320
|
+
return this.CreateChildSubAgent();
|
|
4809
5321
|
}
|
|
4810
5322
|
/**
|
|
4811
5323
|
* Opens dialog to link an existing agent as a related sub-agent
|
|
4812
5324
|
*/
|
|
4813
|
-
async
|
|
5325
|
+
async LinkRelatedSubAgent() {
|
|
4814
5326
|
// TODO: Implement dialog to select existing agents and create relationship
|
|
4815
5327
|
MJNotificationService.Instance.CreateSimpleNotification('Link related sub-agent dialog coming soon', 'info', 3000);
|
|
4816
5328
|
}
|
|
5329
|
+
/** @deprecated Use {@link LinkRelatedSubAgent}. */
|
|
5330
|
+
async linkRelatedSubAgent() {
|
|
5331
|
+
return this.LinkRelatedSubAgent();
|
|
5332
|
+
}
|
|
4817
5333
|
/**
|
|
4818
5334
|
* Removes an action from the agent (deferred until save)
|
|
4819
5335
|
*/
|
|
4820
|
-
async
|
|
5336
|
+
async RemoveAction(action, event) {
|
|
4821
5337
|
event.stopPropagation(); // Prevent navigation
|
|
4822
5338
|
const confirmDialog = this.dialogService.open({
|
|
4823
5339
|
title: 'Remove Action',
|
|
@@ -4862,11 +5378,11 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4862
5378
|
}
|
|
4863
5379
|
}
|
|
4864
5380
|
// Remove from UI immediately
|
|
4865
|
-
const actionIndex = this.
|
|
5381
|
+
const actionIndex = this.AgentActions.findIndex(a => UUIDsEqual(a.ID, action.ID));
|
|
4866
5382
|
if (actionIndex >= 0) {
|
|
4867
|
-
this.
|
|
5383
|
+
this.AgentActions.splice(actionIndex, 1);
|
|
4868
5384
|
}
|
|
4869
|
-
this.
|
|
5385
|
+
this.HasUnsavedChanges = true;
|
|
4870
5386
|
// Mark for check instead of forcing immediate detection
|
|
4871
5387
|
this.cdr.markForCheck();
|
|
4872
5388
|
MJNotificationService.Instance.CreateSimpleNotification(`Action "${action.Name}" will be removed when you save the agent`, 'info', 4000);
|
|
@@ -4881,10 +5397,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4881
5397
|
console.error('Error with action dialog:', dialogError);
|
|
4882
5398
|
}
|
|
4883
5399
|
}
|
|
5400
|
+
/** @deprecated Use {@link RemoveAction}. */
|
|
5401
|
+
async removeAction(action, event) {
|
|
5402
|
+
return this.RemoveAction(action, event);
|
|
5403
|
+
}
|
|
4884
5404
|
/**
|
|
4885
5405
|
* Opens the advanced settings dialog for a prompt
|
|
4886
5406
|
*/
|
|
4887
|
-
async
|
|
5407
|
+
async OpenPromptAdvancedSettings(prompt, event) {
|
|
4888
5408
|
event.stopPropagation(); // Prevent navigation
|
|
4889
5409
|
try {
|
|
4890
5410
|
// Find the corresponding MJAIAgentPromptEntity for this prompt
|
|
@@ -4904,12 +5424,12 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4904
5424
|
if (formData) {
|
|
4905
5425
|
try {
|
|
4906
5426
|
// Update the agent prompt entity with new values
|
|
4907
|
-
agentPrompt.ExecutionOrder = formData.
|
|
4908
|
-
agentPrompt.Purpose = formData.
|
|
4909
|
-
agentPrompt.ConfigurationID = formData.
|
|
4910
|
-
agentPrompt.ContextBehavior = formData.
|
|
4911
|
-
agentPrompt.ContextMessageCount = formData.
|
|
4912
|
-
agentPrompt.Status = formData.
|
|
5427
|
+
agentPrompt.ExecutionOrder = formData.ExecutionOrder;
|
|
5428
|
+
agentPrompt.Purpose = formData.Purpose;
|
|
5429
|
+
agentPrompt.ConfigurationID = formData.ConfigurationID;
|
|
5430
|
+
agentPrompt.ContextBehavior = formData.ContextBehavior;
|
|
5431
|
+
agentPrompt.ContextMessageCount = formData.ContextMessageCount;
|
|
5432
|
+
agentPrompt.Status = formData.Status;
|
|
4913
5433
|
// Save immediately to database
|
|
4914
5434
|
const saveResult = await agentPrompt.Save();
|
|
4915
5435
|
if (saveResult) {
|
|
@@ -4938,10 +5458,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4938
5458
|
MJNotificationService.Instance.CreateSimpleNotification('Error opening prompt advanced settings. Please try again.', 'error', 3000);
|
|
4939
5459
|
}
|
|
4940
5460
|
}
|
|
5461
|
+
/** @deprecated Use {@link OpenPromptAdvancedSettings}. */
|
|
5462
|
+
async openPromptAdvancedSettings(prompt, event) {
|
|
5463
|
+
return this.OpenPromptAdvancedSettings(prompt, event);
|
|
5464
|
+
}
|
|
4941
5465
|
/**
|
|
4942
5466
|
* Opens the advanced settings dialog for a sub-agent
|
|
4943
5467
|
*/
|
|
4944
|
-
async
|
|
5468
|
+
async OpenSubAgentAdvancedSettings(subAgentEntity, event) {
|
|
4945
5469
|
event.stopPropagation(); // Prevent navigation
|
|
4946
5470
|
try {
|
|
4947
5471
|
// Get all sub-agents under the same parent for validation
|
|
@@ -4955,23 +5479,23 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4955
5479
|
if (formData) {
|
|
4956
5480
|
try {
|
|
4957
5481
|
// Update the sub-agent entity with new values
|
|
4958
|
-
subAgentEntity.ExecutionOrder = formData.
|
|
4959
|
-
subAgentEntity.ExecutionMode = formData.
|
|
4960
|
-
subAgentEntity.Status = formData.
|
|
4961
|
-
subAgentEntity.TypeID = formData.
|
|
4962
|
-
subAgentEntity.ExposeAsAction = formData.
|
|
5482
|
+
subAgentEntity.ExecutionOrder = formData.ExecutionOrder;
|
|
5483
|
+
subAgentEntity.ExecutionMode = formData.ExecutionMode;
|
|
5484
|
+
subAgentEntity.Status = formData.Status;
|
|
5485
|
+
subAgentEntity.TypeID = formData.TypeID;
|
|
5486
|
+
subAgentEntity.ExposeAsAction = formData.ExposeAsAction;
|
|
4963
5487
|
// Save immediately to database
|
|
4964
5488
|
const saveResult = await subAgentEntity.Save();
|
|
4965
5489
|
if (saveResult) {
|
|
4966
5490
|
MJNotificationService.Instance.CreateSimpleNotification('Sub-agent settings updated successfully', 'success', 3000);
|
|
4967
5491
|
// Update the local sub-agent data to reflect changes
|
|
4968
|
-
const localSubAgent = this.
|
|
5492
|
+
const localSubAgent = this.SubAgents.find(sa => UUIDsEqual(sa.ID, subAgentEntity.ID));
|
|
4969
5493
|
if (localSubAgent) {
|
|
4970
|
-
localSubAgent.ExecutionOrder = formData.
|
|
4971
|
-
localSubAgent.ExecutionMode = formData.
|
|
4972
|
-
localSubAgent.Status = formData.
|
|
4973
|
-
localSubAgent.TypeID = formData.
|
|
4974
|
-
localSubAgent.ExposeAsAction = formData.
|
|
5494
|
+
localSubAgent.ExecutionOrder = formData.ExecutionOrder;
|
|
5495
|
+
localSubAgent.ExecutionMode = formData.ExecutionMode;
|
|
5496
|
+
localSubAgent.Status = formData.Status;
|
|
5497
|
+
localSubAgent.TypeID = formData.TypeID;
|
|
5498
|
+
localSubAgent.ExposeAsAction = formData.ExposeAsAction;
|
|
4975
5499
|
}
|
|
4976
5500
|
// Mark for check instead of forcing immediate detection
|
|
4977
5501
|
this.cdr.markForCheck();
|
|
@@ -4997,6 +5521,10 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
4997
5521
|
MJNotificationService.Instance.CreateSimpleNotification('Error opening sub-agent advanced settings. Please try again.', 'error', 3000);
|
|
4998
5522
|
}
|
|
4999
5523
|
}
|
|
5524
|
+
/** @deprecated Use {@link OpenSubAgentAdvancedSettings}. */
|
|
5525
|
+
async openSubAgentAdvancedSettings(subAgentEntity, event) {
|
|
5526
|
+
return this.OpenSubAgentAdvancedSettings(subAgentEntity, event);
|
|
5527
|
+
}
|
|
5000
5528
|
/**
|
|
5001
5529
|
* Override PopulatePendingRecords to preserve our pending records before parent clears them
|
|
5002
5530
|
* However, during cancel operations, we want to clear all pending records completely
|
|
@@ -5036,7 +5564,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5036
5564
|
this.record.ContextCompressionMessageThreshold = null;
|
|
5037
5565
|
this.record.ContextCompressionPromptID = null;
|
|
5038
5566
|
this.record.ContextCompressionMessageRetentionCount = null;
|
|
5039
|
-
this.
|
|
5567
|
+
this.SelectedContextCompressionPrompt = null;
|
|
5040
5568
|
}
|
|
5041
5569
|
const md = this.ProviderToUse;
|
|
5042
5570
|
const transactionGroup = await md.CreateTransactionGroup();
|
|
@@ -5133,7 +5661,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5133
5661
|
if (this.customSectionComponent) {
|
|
5134
5662
|
const contributed = await this.customSectionComponent.ContributeToSave(transactionGroup);
|
|
5135
5663
|
if (!contributed) {
|
|
5136
|
-
MJNotificationService.Instance.CreateSimpleNotification(`The ${this.
|
|
5664
|
+
MJNotificationService.Instance.CreateSimpleNotification(`The ${this.AgentType?.Name ?? 'type'} configuration could not be prepared for saving. Nothing was saved.`, 'error', 4000);
|
|
5137
5665
|
return false;
|
|
5138
5666
|
}
|
|
5139
5667
|
}
|
|
@@ -5144,7 +5672,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5144
5672
|
// edits saved that a failed submit had discarded.
|
|
5145
5673
|
this.customSectionComponent?.OnHostSaveCompleted();
|
|
5146
5674
|
// Clear our local state since save was successful
|
|
5147
|
-
this.
|
|
5675
|
+
this.HasUnsavedChanges = false;
|
|
5148
5676
|
// Clear pending records since they've been saved
|
|
5149
5677
|
this.PendingRecords.length = 0;
|
|
5150
5678
|
// Reload related data to reflect database state
|
|
@@ -5165,11 +5693,15 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5165
5693
|
/**
|
|
5166
5694
|
* Navigates to the parent agent when the "Child of..." badge is clicked
|
|
5167
5695
|
*/
|
|
5168
|
-
|
|
5696
|
+
NavigateToParentAgent() {
|
|
5169
5697
|
if (this.record.ParentID) {
|
|
5170
|
-
this.
|
|
5698
|
+
this.NavigateToEntity('MJ: AI Agents', this.record.ParentID);
|
|
5171
5699
|
}
|
|
5172
5700
|
}
|
|
5701
|
+
/** @deprecated Use {@link NavigateToParentAgent}. */
|
|
5702
|
+
navigateToParentAgent() {
|
|
5703
|
+
return this.NavigateToParentAgent();
|
|
5704
|
+
}
|
|
5173
5705
|
/**
|
|
5174
5706
|
* Opens the substrate behind an invocation pathway.
|
|
5175
5707
|
*
|
|
@@ -5178,7 +5710,7 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5178
5710
|
* the job of this layer.
|
|
5179
5711
|
*/
|
|
5180
5712
|
OnInvocationOpenRequested(event) {
|
|
5181
|
-
this.
|
|
5713
|
+
this.NavigateToEntity(event.EntityName, event.RecordID);
|
|
5182
5714
|
}
|
|
5183
5715
|
/**
|
|
5184
5716
|
* Component cleanup - critical for preventing memory leaks
|
|
@@ -5198,21 +5730,21 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5198
5730
|
this._runningTimeUpdater = null;
|
|
5199
5731
|
}
|
|
5200
5732
|
// Clear all data arrays to release memory
|
|
5201
|
-
this.
|
|
5202
|
-
this.
|
|
5203
|
-
this.
|
|
5204
|
-
this.
|
|
5205
|
-
this.
|
|
5206
|
-
this.
|
|
5733
|
+
this.SubAgents.length = 0;
|
|
5734
|
+
this.AgentPrompts.length = 0;
|
|
5735
|
+
this.AgentActions.length = 0;
|
|
5736
|
+
this.RecentExecutions.length = 0;
|
|
5737
|
+
this.LearningCycles.length = 0;
|
|
5738
|
+
this.AgentNotes.length = 0;
|
|
5207
5739
|
// Reset pagination state
|
|
5208
|
-
this.
|
|
5209
|
-
this.
|
|
5210
|
-
this.
|
|
5740
|
+
this.ExecutionHistoryCurrentPage = 1;
|
|
5741
|
+
this.TotalExecutionHistoryCount = 0;
|
|
5742
|
+
this.IsLoadingPage = false;
|
|
5211
5743
|
this.allLoadedExecutions = [];
|
|
5212
5744
|
// Clear maps and objects
|
|
5213
5745
|
this._permissionCache.clear();
|
|
5214
5746
|
this._runningTimeCache.clear();
|
|
5215
|
-
this.
|
|
5747
|
+
this.ExpandedExecutions = {};
|
|
5216
5748
|
this.originalSnapshots = null;
|
|
5217
5749
|
// Clean up component references
|
|
5218
5750
|
if (this.customSectionComponentRef) {
|
|
@@ -5220,14 +5752,14 @@ let MJAIAgentFormComponentExtended = class MJAIAgentFormComponentExtended extend
|
|
|
5220
5752
|
this.customSectionComponentRef = null;
|
|
5221
5753
|
}
|
|
5222
5754
|
this.customSectionComponent = null;
|
|
5223
|
-
this.
|
|
5755
|
+
this.AgentType = null;
|
|
5224
5756
|
}
|
|
5225
5757
|
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵMJAIAgentFormComponentExtended_BaseFactory; return function MJAIAgentFormComponentExtended_Factory(__ngFactoryType__) { return (ɵMJAIAgentFormComponentExtended_BaseFactory || (ɵMJAIAgentFormComponentExtended_BaseFactory = i0.ɵɵgetInheritedFactory(MJAIAgentFormComponentExtended)))(__ngFactoryType__ || MJAIAgentFormComponentExtended); }; })(); }
|
|
5226
5758
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJAIAgentFormComponentExtended, selectors: [["mj-ai-agent-form"]], viewQuery: function MJAIAgentFormComponentExtended_Query(rf, ctx) { if (rf & 1) {
|
|
5227
5759
|
i0.ɵɵviewQuery(_c0, 5, ViewContainerRef);
|
|
5228
5760
|
} if (rf & 2) {
|
|
5229
5761
|
let _t;
|
|
5230
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
5762
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.CustomSectionContainer = _t.first);
|
|
5231
5763
|
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 2, consts: [["form", "ngForm"], ["customSectionContainer", ""], [3, "Record", "FormComponent", "ToolbarConfig", "WidthMode"], [3, "Agent"], [3, "Navigate", "DeleteRequested", "FavoriteToggled", "HistoryRequested", "ListManagementRequested", "Record", "FormComponent", "ToolbarConfig", "WidthMode"], [1, "record-form"], [1, "agent-header"], [1, "agent-header-mini"], [1, "agent-form-loading"], [1, "agent-header-content"], ["title", "Minimize header", 1, "agent-header-toggle", 3, "click"], [1, "fa-solid", "fa-chevron-up"], [1, "agent-overview"], [1, "agent-icon-wrapper"], [1, "agent-logo", 3, "src", "alt"], [3, "class"], [1, "agent-info"], ["type", "text", "name", "agentName", "placeholder", "Enter agent name...", 1, "mj-input", "agent-name-input", 3, "ngModel"], [1, "agent-name"], [1, "agent-meta"], [1, "status-badge", 3, "background-color"], [1, "execution-mode"], [1, "parent-agent", "clickable", 3, "title"], [1, "agent-actions"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Refresh all data", 3, "click"], [1, "fa-solid", "fa-refresh"], ["type", "text", "name", "agentName", "placeholder", "Enter agent name...", 1, "mj-input", "agent-name-input", 3, "ngModelChange", "ngModel"], [1, "status-badge"], [1, "fa-solid", "fa-circle"], [1, "parent-agent", "clickable", 3, "click", "title"], [1, "fa-solid", "fa-sitemap"], [1, "fa-solid", "fa-external-link", 2, "margin-left", "4px", "font-size", "10px"], ["mjButton", "", "variant", "primary", "size", "lg", "title", "Run this AI agent", 3, "click", "disabled"], [1, "fa-solid", "fa-play"], ["mjButton", "", "size", "lg", 3, "click", "title"], [1, "fa-solid"], ["title", "Expand header", 1, "agent-header-mini-expand", 3, "click"], [1, "fa-solid", "fa-chevron-down"], [1, "agent-header-mini-name"], [1, "agent-header-mini-status", 3, "background-color"], [1, "agent-header-mini-spacer"], ["title", "Refresh", 1, "agent-header-mini-btn", 3, "click"], [1, "agent-header-mini-status"], ["title", "Run agent", 1, "agent-header-mini-btn", "agent-header-mini-btn--primary", 3, "click", "disabled"], [1, "agent-header-mini-btn", 3, "click", "title"], ["text", "Loading agent...", "size", "medium"], [1, "agent-tabbar"], [1, "agent-pane", "agent-pane--designer", 3, "agent-pane--hidden"], [1, "agent-pane", "agent-pane--invocations", 3, "agent-pane--hidden"], [1, "form-content", "agent-pane"], ["id", "history", 3, "Expanded", "Disabled"], ["id", "actions", 3, "Expanded", "Disabled"], ["id", "subagents", 3, "Expanded", "Disabled"], ["id", "prompts", 3, "Expanded", "Disabled"], ["id", "learning", 3, "Expanded", "Disabled"], ["id", "notes", 3, "Expanded", "Disabled"], ["id", "search", 3, "Expanded"], ["id", "payload", 3, "Expanded"], ["mjAccordionTitle", ""], [1, "panel-content"], [1, "section-header"], [1, "section-description"], [1, "payload-section"], [1, "payload-section-title"], [1, "fa-solid", "fa-target"], [1, "payload-field-container"], [1, "payload-field-info"], [1, "payload-field-label"], [1, "payload-field-description"], [1, "payload-field-input"], ["FieldName", "PayloadScope", "Type", "textbox", "Caption", "", 2, "width", "100%", 3, "EditMode", "Record"], [1, "payload-field-example"], [1, "fa-solid", "fa-lightbulb"], [1, "fa-solid", "fa-route"], [1, "payload-paths-grid"], [1, "payload-path-card"], [1, "payload-path-header"], [1, "payload-path-icon", "downstream"], [1, "fa-solid", "fa-arrow-down"], [1, "payload-path-info"], [1, "payload-path-content"], [1, "json-editor-container"], ["language", "json", 2, "height", "100px", "width", "100%", 3, "valueChange", "value", "readonly", "lineWrapping"], [1, "payload-path-hint"], [1, "fa-solid", "fa-info-circle"], [1, "payload-path-icon", "upstream"], [1, "fa-solid", "fa-arrow-up"], [1, "payload-path-icon", "self-read"], [1, "fa-solid", "fa-eye"], [1, "payload-path-icon", "self-write"], [1, "fa-solid", "fa-pen"], [1, "fa-solid", "fa-shield-check"], [1, "payload-validation-container"], [1, "payload-validation-settings"], [1, "validation-field-group"], [1, "validation-field-label"], [1, "validation-field-description"], ["FieldName", "FinalPayloadValidationMode", "Type", "dropdownlist", "Caption", "", 2, "width", "100%", 3, "EditMode", "Record"], ["FieldName", "FinalPayloadValidationMaxRetries", "Type", "numerictextbox", "Caption", "", 2, "width", "100%", 3, "EditMode", "Record"], [1, "payload-validation-schema"], [1, "validation-schema-label"], [1, "fa-solid", "fa-code"], [1, "validation-schema-description"], [1, "validation-schema-editor"], ["language", "json", 2, "height", "200px", "width", "100%", 3, "valueChange", "value", "readonly", "lineWrapping"], ["id", "guardrails", 3, "Expanded"], [1, "form-fields-grid"], ["FieldName", "MaxCostPerRun", "Type", "numerictextbox", "Caption", "Max Cost ($)", "Description", "Maximum cost per run", 3, "EditMode", "Record"], ["FieldName", "MaxTokensPerRun", "Type", "numerictextbox", "Caption", "Max Tokens", "Description", "Maximum tokens per run", 3, "EditMode", "Record"], ["FieldName", "MaxIterationsPerRun", "Type", "numerictextbox", "Caption", "Max Iterations", "Description", "Maximum prompt iterations", 3, "EditMode", "Record"], ["FieldName", "MaxTimePerRun", "Type", "numerictextbox", "Caption", "Max Time (seconds)", "Description", "Maximum execution time", 3, "EditMode", "Record"], ["id", "config", 3, "Expanded"], [1, "config-section"], [1, "config-section-title"], [1, "fa-solid", "fa-id-card"], [1, "config-grid"], [1, "config-card"], [1, "config-card-header"], [1, "config-card-icon"], [1, "fa-solid", "fa-toggle-on"], [1, "config-card-info"], [1, "config-card-content"], ["TextField", "text", "ValueField", "value", "name", "agentStatus", 1, "config-field-input", 3, "ngModel", "Data", "ValuePrimitive"], [1, "config-field-display"], ["TextField", "Name", "ValueField", "ID", "name", "agentTypeID", 1, "config-field-input", 3, "ngModel", "Data", "ValuePrimitive"], [1, "fa-solid", "fa-folder-tree"], ["SelectionMode", "single", "SelectableTypes", "branch", "Placeholder", "Select a category...", 3, "BranchConfig", "Value", "Clearable", "EnableSearch"], [1, "fa-solid", "fa-bolt"], ["FieldName", "ExposeAsAction", "Type", "checkbox", "Caption", "", 3, "EditMode", "Record"], [1, "config-card", "full-width"], [1, "fa-solid", "fa-align-left"], ["FieldName", "Description", "Type", "textarea", "Caption", "", 2, "width", "100%", 3, "EditMode", "Record"], [1, "fa-solid", "fa-layer-group"], ["FieldName", "ExecutionMode", "Type", "dropdownlist", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-sort-numeric-down"], ["FieldName", "ExecutionOrder", "Type", "numerictextbox", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-tachometer-alt"], ["FieldName", "DefaultPromptEffortLevel", "Type", "numerictextbox", "Caption", "", 3, "EditMode", "Record"], [1, "config-card-hint"], ["FieldName", "DriverClass", "Type", "textbox", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-palette"], [1, "fa-solid", "fa-icons"], ["FieldName", "IconClass", "Type", "textbox", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-image"], ["FieldName", "LogoURL", "Type", "textbox", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-compress"], ["FieldName", "EnableContextCompression", "Type", "checkbox", "Caption", "", 3, "valueChange", "EditMode", "Record"], [3, "TabChange", "Tabs", "ActiveKey"], [1, "agent-pane", "agent-pane--designer"], ["size", "medium", 3, "text"], [1, "agent-pane", "agent-pane--invocations"], [3, "RecordOpenRequested", "Provider", "AgentID", "Active", "ExposeAsAction", "ParentAgentName", "ParentAgentID"], [1, "panel-content", "execution-history-panel"], ["role", "tablist", 1, "history-view-toggle"], [1, "fa-solid", "fa-history"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["type", "button", 1, "history-toggle-option", 3, "click"], [1, "fa-solid", "fa-person-running"], [1, "history-toggle-count"], [1, "fa-solid", "fa-tower-broadcast"], ["text", "Loading sessions...", "size", "medium"], ["Icon", "fa-solid fa-tower-broadcast", "Title", "No Voice Sessions", "Message", "This agent hasn't participated in any realtime voice sessions yet \u2014 neither as the co-agent nor as a delegation target.", "Size", "compact"], [1, "execution-history-list"], ["title", "Open session", 1, "execution-card", "session-card"], ["title", "Open session", 1, "execution-card", "session-card", 3, "click"], [1, "execution-header"], [1, "execution-left-section"], [1, "execution-status"], [1, "status-indicator"], [1, "execution-info"], [1, "execution-title"], [1, "session-role-chip"], [1, "session-role-chip", "session-role-chip--target"], [1, "execution-date"], [1, "execution-metrics"], [1, "metric-item"], [1, "session-status-pill"], [1, "fa-solid", "fa-stopwatch"], [1, "metric-label"], [1, "metric-value"], [1, "fa-solid", "fa-plug"], [1, "fa-solid", "fa-user"], [1, "execution-actions"], ["title", "View session details", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "fa-solid", "fa-bullseye"], ["text", "Loading execution history...", "size", "medium"], ["Icon", "fa-solid fa-clock-rotate-left", "Title", "No Execution History", "Message", "This agent hasn't been executed yet. Use the Test Agent button to run the agent and see execution history here.", "Size", "compact"], [1, "execution-search-bar"], [1, "search-input-wrapper"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search by Run ID...", 1, "mj-input", 3, "ngModelChange", "ngModel", "ngModelOptions"], ["Variant", "no-results", "Title", "No Matching Results", "Size", "compact", 3, "Message"], [1, "execution-card", 3, "expanded"], [1, "pagination-controls"], [1, "execution-card"], [1, "execution-header", 3, "click"], [1, "fa-solid", "fa-chevron-right", "expand-icon"], ["title", "View details", 1, "action-btn", 3, "click"], [1, "execution-expanded-content"], [1, "fa-solid", "fa-cog"], [1, "fa-solid", "fa-clock"], [1, "fa-solid", "fa-microchip"], [1, "fa-solid", "fa-dollar-sign"], [1, "detailed-metrics"], [1, "metrics-grid"], [1, "metric-detail"], [1, "metric-info"], [1, "metric-title"], [1, "metric-data"], [1, "result-section"], [1, "error-section"], [1, "fa-solid", "fa-check-circle"], [1, "fa-solid", "fa-calculator"], [1, "fa-solid", "fa-comments"], [1, "fa-solid", "fa-file-text"], ["language", "json", 2, "max-height", "200px", "width", "100%", 3, "value", "readonly", "lineWrapping"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "error-content"], ["mjButton", "", "variant", "outline", 1, "page-nav-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-left"], [1, "page-info"], [1, "fa-solid", "fa-chevron-right"], ["mjButton", "", "variant", "flat", "size", "sm", 1, "view-all-btn", 3, "click"], [1, "fa-solid", "fa-external-link"], [1, "record-count"], [1, "loading-state"], [1, "header-actions"], ["mjButton", "", "variant", "primary", "size", "sm"], ["Icon", "fa-solid fa-bolt", "Title", "No Actions Configured", "Message", "Add actions to enable this agent to perform specific tasks and operations.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "ActionText"], [1, "entity-list"], ["mjButton", "", "variant", "primary", "size", "sm", 3, "click"], [1, "fa-solid", "fa-plus"], ["Icon", "fa-solid fa-bolt", "Title", "No Actions Configured", "Message", "Add actions to enable this agent to perform specific tasks and operations.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "Action", "ActionText"], [1, "entity-item", "action-item"], [1, "view-more-item"], [1, "entity-item", "action-item", 3, "click"], [1, "item-icon"], [1, "item-content"], [1, "item-title"], [1, "item-preview"], [1, "item-meta"], [1, "meta-tag"], [1, "status-tag"], [1, "item-actions"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove action", 1, "error-action"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove action", 1, "error-action", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "view-more-item", 3, "click"], [1, "section-header", "sub-agent-filter-header"], [1, "filter-controls"], [1, "mj-button-group"], ["mjButton", "", "size", "sm", 3, "click"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-share-nodes"], ["Icon", "fa-solid fa-sitemap", "Title", "No Sub-Agents", "Message", "Sub-agents help build complex workflows through hierarchical orchestration.", "Size", "compact"], ["mjButton", "", "variant", "primary", "size", "sm", "title", "Create a new child sub-agent that shares this agent's payload", 3, "click"], ["mjButton", "", "size", "sm", "title", "Link an existing agent as a related sub-agent with payload mapping", 3, "click"], [1, "empty-state-info"], [1, "info-card"], [1, "fa-solid", "fa-link", 2, "color", "var(--mj-status-info)"], [1, "fa-solid", "fa-share-nodes", 2, "color", "var(--mj-brand-primary)"], [1, "entity-item", "sub-agent-item", 3, "child-sub-agent", "related-sub-agent"], [1, "entity-item", "sub-agent-item", 3, "click"], [1, "sub-agent-type-badge"], [1, "sub-agent-logo", 3, "src", "alt"], [1, "meta-tag", "payload-info"], [1, "fa-solid", "fa-database"], [1, "status-tag", 3, "background-color"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Configure output mapping"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Advanced settings"], ["mjButton", "", "variant", "flat", "size", "sm", 1, "error-action", 3, "title"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Configure output mapping", 3, "click"], [1, "fa-solid", "fa-exchange-alt"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Advanced settings", 3, "click"], ["mjButton", "", "variant", "flat", "size", "sm", 1, "error-action", 3, "click", "title"], [1, "prompt-controls"], [1, "model-selection-mode"], [1, "model-selection-label"], [1, "fa-solid", "fa-sliders"], ["name", "modelSelectionMode", "TextField", "text", "ValueField", "value", 1, "model-selection-dropdown", 3, "ngModel", "Data", "ValuePrimitive"], [1, "model-selection-value"], ["Icon", "fa-solid fa-comments", "Title", "No Prompts Configured", "Message", "Add prompts to define how this agent processes requests and generates responses.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "ActionText"], ["name", "modelSelectionMode", "TextField", "text", "ValueField", "value", 1, "model-selection-dropdown", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], ["Icon", "fa-solid fa-comments", "Title", "No Prompts Configured", "Message", "Add prompts to define how this agent processes requests and generates responses.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "Action", "ActionText"], [1, "entity-item", "prompt-item"], [1, "entity-item", "prompt-item", 3, "click"], [1, "fa-solid", "fa-comment-dots"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove prompt", 1, "error-action"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove prompt", 1, "error-action", 3, "click"], ["Icon", "fa-solid fa-brain", "Title", "No Learning Cycles", "Message", "Learning cycles will appear here as the agent processes requests and improves over time.", "Size", "compact"], [1, "fa-solid", "fa-brain"], [1, "entity-item", "learning-item"], [1, "entity-item", "learning-item", 3, "click"], [1, "fa-solid", "fa-calendar"], ["Icon", "fa-solid fa-sticky-note", "Title", "No Notes", "Message", "Add notes to document important information, observations, or instructions for this agent.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "ActionText"], [1, "fa-solid", "fa-sticky-note"], ["Icon", "fa-solid fa-sticky-note", "Title", "No Notes", "Message", "Add notes to document important information, observations, or instructions for this agent.", "ActionIcon", "fa-solid fa-plus", "Size", "compact", 3, "Action", "ActionText"], [1, "entity-item", "note-item"], [1, "entity-item", "note-item", 3, "click"], [1, "agent-search-access"], [1, "agent-search-access-option"], ["type", "radio", "name", "SearchScopeAccess", "value", "All", 3, "change", "checked", "disabled"], [1, "fa-solid", "fa-globe"], [1, "agent-search-access-text"], [1, "agent-search-access-title"], [1, "agent-search-access-desc"], ["type", "radio", "name", "SearchScopeAccess", "value", "Assigned", 3, "change", "checked", "disabled"], [1, "fa-solid", "fa-user-check"], ["type", "radio", "name", "SearchScopeAccess", "value", "None", 3, "change", "checked", "disabled"], [1, "fa-solid", "fa-ban"], [1, "fa-solid", "fa-magnifying-glass"], [1, "agent-search-grid-header"], ["ChildEntityName", "MJ: AI Agent Search Scopes", "ParentFieldName", "AgentID", "AddButtonLabel", "+ Assign another scope", "EmptyMessage", "No scopes assigned yet. Assign at least one if this agent will use Scoped Search.", 3, "RowsChanged", "ParentID", "Columns", "Disabled"], [1, "agent-search-section", 2, "margin-top", "16px"], [2, "margin", "0 0 8px 0"], [1, "fa-solid", "fa-shield-halved"], [1, "section-description", 2, "margin-bottom", "8px"], [2, "color", "var(--mj-text-muted)"], [2, "color", "var(--mj-text-muted)", "font-style", "italic"], [2, "margin-bottom", "12px", "padding", "8px 12px", "background", "var(--mj-bg-surface-card)", "border", "1px solid var(--mj-border-subtle)", "border-radius", "4px"], [2, "font-weight", "600", "margin-bottom", "4px"], [2, "color", "var(--mj-text-muted)", "font-size", "0.9em"], [2, "margin", "4px 0 0 16px", "padding", "0"], [2, "font-size", "0.9em", "padding", "2px 0"], [1, "fa-solid", "fa-cogs"], ["TextField", "text", "ValueField", "value", "name", "agentStatus", 1, "config-field-input", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], ["TextField", "Name", "ValueField", "ID", "name", "agentTypeID", 1, "config-field-input", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], ["SelectionMode", "single", "SelectableTypes", "branch", "Placeholder", "Select a category...", 3, "ValueChange", "BranchConfig", "Value", "Clearable", "EnableSearch"], [1, "fa-solid", "fa-hashtag"], ["FieldName", "ContextCompressionMessageThreshold", "Type", "numerictextbox", "Caption", "", 3, "EditMode", "Record"], [1, "fa-solid", "fa-save"], ["FieldName", "ContextCompressionMessageRetentionCount", "Type", "numerictextbox", "Caption", "", 3, "EditMode", "Record"], [1, "prompt-selector-container"], [1, "prompt-display"], [1, "prompt-name"], [1, "no-prompt"], [1, "prompt-actions"], ["type", "button", "mjButton", "", "variant", "outline", "size", "sm", 1, "prompt-select-btn", 3, "click"], ["type", "button", "mjButton", "", "variant", "flat", "size", "sm", "title", "Clear selection", 1, "prompt-clear-btn"], ["type", "button", "mjButton", "", "variant", "flat", "size", "sm", "title", "Clear selection", 1, "prompt-clear-btn", 3, "click"], [1, "fa-solid", "fa-times"], [3, "Closed", "PermissionsChanged", "Agent"]], template: function MJAIAgentFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
5232
5764
|
i0.ɵɵconditionalCreate(0, MJAIAgentFormComponentExtended_Conditional_0_Template, 7, 7, "mj-record-form-container", 2);
|
|
5233
5765
|
i0.ɵɵconditionalCreate(1, MJAIAgentFormComponentExtended_Conditional_1_Template, 1, 1, "mj-agent-permissions-dialog", 3);
|
|
@@ -5244,7 +5776,7 @@ export { MJAIAgentFormComponentExtended };
|
|
|
5244
5776
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJAIAgentFormComponentExtended, [{
|
|
5245
5777
|
type: Component,
|
|
5246
5778
|
args: [{ standalone: false, selector: 'mj-ai-agent-form', template: "@if (record) {\n<mj-record-form-container [Record]=\"record\" [FormComponent]=\"this\"\n [ToolbarConfig]=\"toolbarConfig\"\n [WidthMode]=\"'full-width'\"\n (Navigate)=\"OnFormNavigate($event)\"\n (DeleteRequested)=\"OnDeleteRequested()\"\n (FavoriteToggled)=\"OnFavoriteToggled()\"\n (HistoryRequested)=\"OnHistoryRequested()\"\n (ListManagementRequested)=\"OnListManagementRequested()\">\n <form class=\"record-form\" #form=\"ngForm\">\n <!-- Agent Header \u2014 expanded view -->\n @if (!HeaderCollapsed) {\n <div class=\"agent-header\">\n <div class=\"agent-header-content\">\n <button class=\"agent-header-toggle\" (click)=\"ToggleHeaderCollapsed()\"\n title=\"Minimize header\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <div class=\"agent-overview\">\n <div class=\"agent-icon-wrapper\">\n @if (hasLogoURL()) {\n <img [src]=\"record.LogoURL\" [alt]=\"record.Name + ' logo'\" class=\"agent-logo\">\n } @else {\n <i [class]=\"getAgentIcon()\"></i>\n }\n </div>\n <div class=\"agent-info\">\n @if (EditMode) {\n <input type=\"text\" class=\"mj-input agent-name-input\"\n [(ngModel)]=\"record.Name\"\n name=\"agentName\"\n placeholder=\"Enter agent name...\">\n } @else {\n <h1 class=\"agent-name\">{{ record.Name || 'Untitled AI Agent' }}</h1>\n }\n <div class=\"agent-meta\">\n @if (record.Status) {\n <span class=\"status-badge\" [style.background-color]=\"getStatusBadgeColor()\">\n <i class=\"fa-solid fa-circle\"></i>\n {{ record.Status }}\n </span>\n }\n @if (record.Type) {\n <span class=\"execution-mode\">\n Agent Type: {{ record.Type }}\n </span>\n }\n @if (record.Parent) {\n <span class=\"parent-agent clickable\"\n (click)=\"navigateToParentAgent()\"\n title=\"Open parent agent: {{ record.Parent }}\">\n <i class=\"fa-solid fa-sitemap\"></i>\n Child of {{ record.Parent }}\n <i class=\"fa-solid fa-external-link\" style=\"margin-left: 4px; font-size: 10px;\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"agent-actions\">\n @if (record.ID) {\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openTestHarness()\"\n [disabled]=\"record.Status !== 'Active'\"\n title=\"Run this AI agent\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n <button mjButton size=\"lg\"\n (click)=\"openPermissionsDialog()\"\n [title]=\"IsOpenToEveryone ? 'Open to everyone \u2014 click to manage permissions' : 'Restricted \u2014 click to manage permissions'\">\n <i class=\"fa-solid\" [class.fa-lock-open]=\"IsOpenToEveryone\" [class.fa-lock]=\"!IsOpenToEveryone\"\n [style.color]=\"IsOpenToEveryone ? 'var(--mj-status-success)' : null\"></i>\n {{ IsOpenToEveryone ? 'Open' : 'Restricted' }}\n </button>\n }\n <button mjButton variant=\"outline\" size=\"sm\" (click)=\"refreshRelatedData()\" title=\"Refresh all data\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n <!-- Agent Header \u2014 minimized floating bar -->\n @if (HeaderCollapsed) {\n <div class=\"agent-header-mini\">\n <button class=\"agent-header-mini-expand\" (click)=\"ToggleHeaderCollapsed()\"\n title=\"Expand header\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n <span class=\"agent-header-mini-name\">{{ record.Name || 'Untitled AI Agent' }}</span>\n @if (record.Status) {\n <span class=\"agent-header-mini-status\" [style.background-color]=\"getStatusBadgeColor()\">\n {{ record.Status }}\n </span>\n }\n <div class=\"agent-header-mini-spacer\"></div>\n @if (record.ID) {\n <button class=\"agent-header-mini-btn agent-header-mini-btn--primary\"\n (click)=\"openTestHarness()\"\n [disabled]=\"record.Status !== 'Active'\"\n title=\"Run agent\">\n <i class=\"fa-solid fa-play\"></i>\n </button>\n <button class=\"agent-header-mini-btn\"\n (click)=\"openPermissionsDialog()\"\n [title]=\"IsOpenToEveryone ? 'Open to everyone' : 'Restricted'\">\n <i class=\"fa-solid\" [class.fa-lock-open]=\"IsOpenToEveryone\" [class.fa-lock]=\"!IsOpenToEveryone\"\n [style.color]=\"IsOpenToEveryone ? 'var(--mj-status-success)' : null\"></i>\n </button>\n }\n <button class=\"agent-header-mini-btn\"\n (click)=\"refreshRelatedData()\" title=\"Refresh\">\n <i class=\"fa-solid fa-refresh\"></i>\n </button>\n </div>\n }\n <!-- The tab strip and every pane depend on the agent's TYPE, which loads asynchronously.\n Without this the form rendered its header over an empty area for the whole load \u2014\n no tabs, no designer, and the details pane hidden because no tab was active yet. -->\n @if (IsFormInitializing) {\n <div class=\"agent-form-loading\">\n <mj-loading text=\"Loading agent...\" size=\"medium\"></mj-loading>\n </div>\n } @else {\n <!-- Tabs, not accordions. For an agent type that ships a designer, the diagram IS the agent;\n leaving it as one collapsed panel among eleven made the record's most important view its\n least reachable one. Invocations is offered for every agent, because \"what runs this when\n I'm not looking?\" is a question you can ask of any of them. -->\n @if (FormTabs.length > 1) {\n <div class=\"agent-tabbar\">\n <mj-tab-nav [Tabs]=\"FormTabs\" [ActiveKey]=\"ActiveFormTab || ''\" (TabChange)=\"OnFormTabChange($event)\"></mj-tab-nav>\n </div>\n }\n\n @if (HasDesignerTab) {\n <!-- Hidden with CSS rather than removed with @if: the designer holds UNSAVED edits, and\n destroying it on a tab switch would discard them without a word. Keeping it mounted also\n means the canvas keeps its zoom and node positions across trips to Details. -->\n <div class=\"agent-pane agent-pane--designer\" [class.agent-pane--hidden]=\"ActiveFormTab !== 'designer'\">\n @if (loadingStates.customSection) {\n <mj-loading text=\"Loading {{ agentType?.Name }} configuration...\" size=\"medium\"></mj-loading>\n }\n <ng-container #customSectionContainer></ng-container>\n </div>\n }\n\n @if (record.ID) {\n <div class=\"agent-pane agent-pane--invocations\" [class.agent-pane--hidden]=\"ActiveFormTab !== 'invocations'\">\n <mj-agent-invocations\n [Provider]=\"Provider\"\n [AgentID]=\"record.ID\"\n [Active]=\"ActiveFormTab === 'invocations'\"\n [ExposeAsAction]=\"record.ExposeAsAction\"\n [ParentAgentName]=\"record.Parent\"\n [ParentAgentID]=\"record.ParentID\"\n (RecordOpenRequested)=\"OnInvocationOpenRequested($event)\">\n </mj-agent-invocations>\n </div>\n }\n\n <!-- Single Pane Layout with Expander Panels -->\n <div class=\"form-content agent-pane\" [class.agent-pane--hidden]=\"ActiveFormTab !== 'details'\">\n <!-- Requests & History -->\n @if (record.ID) {\n <mj-accordion-panel id=\"history\"\n [Expanded]=\"GetSectionExpanded('history', false)\"\n [Disabled]=\"loadingStates.executionHistory\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-history\"></i> Execution History\n @if (loadingStates.executionHistory) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (executionHistoryCount > 0) {\n <span> ({{ executionHistoryCount }}@if (executionHistoryCount < totalExecutionHistoryCount) { of {{ totalExecutionHistoryCount }}})</span>\n }\n </ng-template>\n <div class=\"panel-content execution-history-panel\">\n <!-- Segmented toggle: agent runs vs. realtime voice sessions -->\n @if (UserCanViewSessions) {\n <div class=\"history-view-toggle\" role=\"tablist\">\n <button type=\"button\" class=\"history-toggle-option\"\n [class.active]=\"executionHistoryView === 'runs'\"\n (click)=\"setExecutionHistoryView('runs')\">\n <i class=\"fa-solid fa-person-running\"></i> Runs\n @if (totalExecutionHistoryCount > 0) {\n <span class=\"history-toggle-count\">{{ totalExecutionHistoryCount }}</span>\n }\n </button>\n <button type=\"button\" class=\"history-toggle-option\"\n [class.active]=\"executionHistoryView === 'sessions'\"\n (click)=\"setExecutionHistoryView('sessions')\">\n <i class=\"fa-solid fa-tower-broadcast\"></i> Sessions\n @if (totalSessionCount > 0) {\n <span class=\"history-toggle-count\">{{ totalSessionCount }}</span>\n }\n </button>\n </div>\n }\n @if (executionHistoryView === 'sessions') {\n <!-- Voice/realtime sessions list -->\n @if (loadingSessions) {\n <mj-loading text=\"Loading sessions...\" size=\"medium\"></mj-loading>\n } @else if (agentSessions.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-tower-broadcast\"\n Title=\"No Voice Sessions\"\n Message=\"This agent hasn't participated in any realtime voice sessions yet \u2014 neither as the co-agent nor as a delegation target.\"\n Size=\"compact\" />\n } @else {\n <div class=\"execution-history-list\">\n @for (item of agentSessions; track item.row.ID) {\n <div class=\"execution-card session-card\" (click)=\"openSessionRecord(item.row.ID)\" title=\"Open session\">\n <div class=\"execution-header\">\n <div class=\"execution-left-section\">\n <div class=\"execution-status\">\n <div class=\"status-indicator\" [style.background-color]=\"getSessionStatusColor(item.row.Status)\">\n <i [class]=\"getSessionStatusIcon(item.row.Status)\"></i>\n </div>\n <div class=\"execution-info\">\n <div class=\"execution-title\">\n Session #{{ item.row.ID.substring(0, 8) }}\n @if (item.isCoAgent) {\n <span class=\"session-role-chip\">as co-agent</span>\n }\n @if (item.isTarget) {\n <span class=\"session-role-chip session-role-chip--target\">as target</span>\n }\n </div>\n <div class=\"execution-date\">{{ item.row.__mj_CreatedAt | date:'MMM d, h:mm a' }}</div>\n </div>\n </div>\n <div class=\"execution-metrics\">\n <div class=\"metric-item\">\n <span class=\"session-status-pill\" [attr.data-status]=\"item.row.Status\">{{ item.row.Status }}</span>\n </div>\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-stopwatch\"></i>\n <span class=\"metric-label\">Duration:</span>\n <span class=\"metric-value\">{{ formatSessionDuration(item) }}</span>\n </div>\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-plug\"></i>\n <span class=\"metric-label\">Channels:</span>\n <span class=\"metric-value\">{{ item.channelCount }}</span>\n </div>\n @if (item.isCoAgent && item.targetAgentName) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-bullseye\"></i>\n <span class=\"metric-label\">Target:</span>\n <span class=\"metric-value\">{{ item.targetAgentName }}</span>\n </div>\n }\n @if (item.isTarget && !item.isCoAgent && item.row.Agent) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-tower-broadcast\"></i>\n <span class=\"metric-label\">Co-agent:</span>\n <span class=\"metric-value\">{{ item.row.Agent }}</span>\n </div>\n }\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-user\"></i>\n <span class=\"metric-label\">User:</span>\n <span class=\"metric-value\">{{ item.row.User }}</span>\n </div>\n </div>\n </div>\n <div class=\"execution-actions\">\n <button class=\"action-btn\" (click)=\"openSessionRecord(item.row.ID); $event.stopPropagation()\" title=\"View session details\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n }\n } @else {\n @if (loadingStates.executionHistory) {\n <mj-loading text=\"Loading execution history...\" size=\"medium\"></mj-loading>\n } @else if (executionHistoryCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-clock-rotate-left\"\n Title=\"No Execution History\"\n Message=\"This agent hasn't been executed yet. Use the Test Agent button to run the agent and see execution history here.\"\n Size=\"compact\" />\n } @else {\n <!-- Search Bar -->\n <div class=\"execution-search-bar\">\n <div class=\"search-input-wrapper\">\n <i class=\"fa-solid fa-search\"></i>\n <input type=\"text\" class=\"mj-input\"\n [(ngModel)]=\"executionSearchText\"\n (ngModelChange)=\"onExecutionSearchChange()\"\n [ngModelOptions]=\"{standalone: true}\"\n placeholder=\"Search by Run ID...\">\n </div>\n </div>\n <div class=\"execution-history-list\">\n @if (filteredExecutions.length === 0) {\n <mj-empty-state\n Variant=\"no-results\"\n Title=\"No Matching Results\"\n [Message]=\"ExecutionSearchEmptyMessage\"\n Size=\"compact\" />\n }\n @for (execution of filteredExecutions; track execution.ID) {\n <div class=\"execution-card\" [class.expanded]=\"expandedExecutions[execution.ID]\">\n <div class=\"execution-header\" (click)=\"toggleExecutionExpanded(execution.ID)\">\n <div class=\"execution-left-section\">\n <div class=\"execution-status\">\n <div class=\"status-indicator\" [style.background-color]=\"getExecutionStatusColor(execution.Status)\">\n <i [class]=\"getExecutionStatusIcon(execution.Status)\"></i>\n </div>\n <div class=\"execution-info\">\n <div class=\"execution-title\">\n <i class=\"fa-solid fa-chevron-right expand-icon\" [class.expanded]=\"expandedExecutions[execution.ID]\"></i>\n Execution #{{ execution.ID.substring(0, 8) }}\n </div>\n <div class=\"execution-date\">{{ execution.__mj_CreatedAt | date:'MMM d, h:mm a' }}</div>\n </div>\n </div>\n <div class=\"execution-metrics\">\n @if (execution.Configuration) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-cog\"></i>\n <span class=\"metric-label\">Config:</span>\n <span class=\"metric-value\">{{ execution.Configuration }}</span>\n </div>\n }\n @if (execution.CompletedAt) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-stopwatch\"></i>\n <span class=\"metric-label\">Duration:</span>\n <span class=\"metric-value\">{{ formatExecutionTimeFromDates(execution.StartedAt, execution.CompletedAt) }}</span>\n </div>\n } @else if (execution.Status === 'Running') {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-clock\"></i>\n <span class=\"metric-label\">Running:</span>\n <!-- <span class=\"metric-value\">{{ execution.StartedAt | runningTime }}</span> -->\n </div>\n }\n @if (execution.TotalTokensUsedRollup || execution.TotalTokensUsed) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-microchip\"></i>\n <span class=\"metric-label\">Tokens:</span>\n <span class=\"metric-value\">{{ formatTokenCount(execution.TotalTokensUsedRollup || execution.TotalTokensUsed) }}</span>\n </div>\n }\n @if (execution.TotalCostRollup || execution.TotalCost) {\n <div class=\"metric-item\">\n <i class=\"fa-solid fa-dollar-sign\"></i>\n <span class=\"metric-label\">Cost:</span>\n <span class=\"metric-value\">${{ formatCost(execution.TotalCostRollup || execution.TotalCost) }}</span>\n </div>\n }\n </div>\n </div>\n <div class=\"execution-actions\">\n <button class=\"action-btn\" (click)=\"openExecutionRecord(execution.ID); $event.stopPropagation()\" title=\"View details\">\n <i class=\"fa-solid fa-external-link-alt\"></i>\n </button>\n </div>\n </div>\n @if (expandedExecutions[execution.ID]) {\n <div class=\"execution-expanded-content\">\n <!-- Detailed Metrics -->\n <div class=\"detailed-metrics\">\n <div class=\"metrics-grid\">\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-clock\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Started</span>\n <span class=\"metric-data\">{{ execution.StartedAt | date:'medium' }}</span>\n </div>\n </div>\n @if (execution.CompletedAt) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-check-circle\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Completed</span>\n <span class=\"metric-data\">{{ execution.CompletedAt | date:'medium' }}</span>\n </div>\n </div>\n }\n @if (execution.TotalTokensUsed) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-microchip\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Direct Tokens</span>\n <span class=\"metric-data\">{{ formatTokenCount(execution.TotalTokensUsed) }}</span>\n </div>\n </div>\n }\n @if (execution.TotalTokensUsedRollup && execution.TotalTokensUsedRollup !== execution.TotalTokensUsed) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-sitemap\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Total + Sub-agents</span>\n <span class=\"metric-data\">{{ formatTokenCount(execution.TotalTokensUsedRollup) }}</span>\n </div>\n </div>\n }\n @if (execution.TotalCost) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-dollar-sign\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Direct Cost</span>\n <span class=\"metric-data\">${{ formatCost(execution.TotalCost) }}</span>\n </div>\n </div>\n }\n @if (execution.TotalCostRollup && execution.TotalCostRollup !== execution.TotalCost) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-calculator\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Total + Sub-agents</span>\n <span class=\"metric-data\">${{ formatCost(execution.TotalCostRollup) }}</span>\n </div>\n </div>\n }\n @if (execution.ConversationID) {\n <div class=\"metric-detail\">\n <i class=\"fa-solid fa-comments\"></i>\n <div class=\"metric-info\">\n <span class=\"metric-title\">Conversation</span>\n <span class=\"metric-data\">{{ execution.ConversationID.substring(0, 8) }}...</span>\n </div>\n </div>\n }\n </div>\n </div>\n @if (execution.Result) {\n <div class=\"result-section\">\n <h5><i class=\"fa-solid fa-file-text\"></i> Result</h5>\n <mj-code-editor\n [value]=\"getExecutionResultPreview(execution, false)\"\n [readonly]=\"true\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"max-height: 200px; width: 100%;\">\n </mj-code-editor>\n </div>\n }\n @if (execution.ErrorMessage) {\n <div class=\"error-section\">\n <h5><i class=\"fa-solid fa-exclamation-triangle\"></i> Error</h5>\n <div class=\"error-content\">{{ execution.ErrorMessage }}</div>\n </div>\n }\n </div>\n }\n </div>\n }\n <!-- Pagination Controls -->\n @if (totalPages > 1) {\n <div class=\"pagination-controls\">\n <button mjButton\n variant=\"outline\"\n (click)=\"goToPreviousPage()\"\n [disabled]=\"!hasPreviousPage || isLoadingPage\"\n class=\"page-nav-btn\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n Previous\n </button>\n <div class=\"page-info\">\n @if (isLoadingPage) {\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n Loading...\n } @else {\n Page {{ executionHistoryCurrentPage }} of {{ totalPages }}\n <span class=\"record-count\">({{ totalExecutionHistoryCount }} total)</span>\n }\n </div>\n <button mjButton\n variant=\"outline\"\n (click)=\"goToNextPage()\"\n [disabled]=\"!hasNextPage || isLoadingPage\"\n class=\"page-nav-btn\">\n Next\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"navigateToEntity('MJ: AI Agent Runs', '')\"\n class=\"view-all-btn\">\n <i class=\"fa-solid fa-external-link\"></i>\n View All in Grid\n </button>\n </div>\n }\n </div>\n }\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Actions -->\n @if (record.ID) {\n <mj-accordion-panel id=\"actions\"\n [Expanded]=\"GetSectionExpanded('actions', false)\"\n [Disabled]=\"loadingStates.actions\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-bolt\"></i> Actions\n @if (loadingStates.actions) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (actionCount > 0) {\n <span> ({{ actionCount }})</span>\n }\n </ng-template>\n <div class=\"panel-content\">\n @if (loadingStates.actions) {\n <div class=\"loading-state\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <p>Loading actions...</p>\n </div>\n } @else {\n <div class=\"section-header\">\n <div class=\"header-actions\">\n @if (EditMode && UserCanCreateActions) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"configureActions()\">\n <i class=\"fa-solid fa-plus\"></i> Add Action\n </button>\n }\n </div>\n </div>\n @if (actionCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-bolt\"\n Title=\"No Actions Configured\"\n Message=\"Add actions to enable this agent to perform specific tasks and operations.\"\n [ActionText]=\"(EditMode && UserCanCreateActions) ? 'Configure First Action' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"configureActions()\"\n Size=\"compact\" />\n } @else {\n <div class=\"entity-list\">\n @for (action of agentActions; track action.ID) {\n <div class=\"entity-item action-item\" (click)=\"navigateToEntity('MJ: Actions', action.ID)\">\n <div class=\"item-icon\">\n <i [class]=\"getActionIcon(action)\"></i>\n </div>\n <div class=\"item-content\">\n <div class=\"item-title\">{{ action.Name || 'Untitled Action' }}</div>\n @if (action.Description) {\n <div class=\"item-preview\">{{ action.Description }}</div>\n }\n <div class=\"item-meta\">\n @if (action.Type) {\n <span class=\"meta-tag\">{{ action.Type }}</span>\n }\n <span class=\"status-tag\" [class.active]=\"action.Status==='Active'\" [class.inactive]=\"action.Status!=='Active'\">\n <i class=\"fa-solid\" [class.fa-check-circle]=\"action.Status==='Active'\" [class.fa-times-circle]=\"action.Status!=='Active'\"></i>\n {{ action.Status }}\n </span>\n </div>\n </div>\n <div class=\"item-actions\">\n @if (EditMode && UserCanDeleteActions) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"removeAction(action, $event)\"\n title=\"Remove action\"\n class=\"error-action\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n </div>\n }\n @if (actionCount > agentActions.length) {\n <div class=\"view-more-item\" (click)=\"navigateToEntity('MJ: AI Agent Actions', '')\">\n <span>View all {{ actionCount }} actions...</span>\n </div>\n }\n </div>\n }\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Sub-Agents (Unified View with Filter) -->\n @if (record.ID) {\n <mj-accordion-panel id=\"subagents\"\n [Expanded]=\"GetSectionExpanded('subagents', false)\"\n [Disabled]=\"loadingStates.subAgents\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-sitemap\"></i> Sub-Agents\n @if (loadingStates.subAgents) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (totalSubAgentCount > 0) {\n <span> ({{ totalSubAgentCount }})</span>\n }\n </ng-template>\n <div class=\"panel-content\">\n <!-- Filter Controls -->\n <div class=\"section-header sub-agent-filter-header\">\n <div class=\"filter-controls\">\n <div class=\"mj-button-group\">\n <button mjButton\n size=\"sm\"\n [class.active]=\"subAgentFilter === 'all'\"\n (click)=\"setSubAgentFilter('all')\">\n <i class=\"fa-solid fa-layer-group\"></i>\n All ({{ totalSubAgentCount }})\n </button>\n <button mjButton\n size=\"sm\"\n [class.active]=\"subAgentFilter === 'child'\"\n (click)=\"setSubAgentFilter('child')\">\n <i class=\"fa-solid fa-link\"></i>\n Child ({{ childSubAgentCount }})\n </button>\n <button mjButton\n size=\"sm\"\n [class.active]=\"subAgentFilter === 'related'\"\n (click)=\"setSubAgentFilter('related')\">\n <i class=\"fa-solid fa-share-nodes\"></i>\n Related ({{ relatedSubAgentCount }})\n </button>\n </div>\n </div>\n <div class=\"header-actions\">\n @if (EditMode && UserCanCreateSubAgents) {\n <button mjButton\n variant=\"primary\"\n size=\"sm\"\n (click)=\"createChildSubAgent()\"\n title=\"Create a new child sub-agent that shares this agent's payload\">\n <i class=\"fa-solid fa-link\"></i>\n Create Child\n </button>\n <button mjButton\n size=\"sm\"\n (click)=\"linkRelatedSubAgent()\"\n title=\"Link an existing agent as a related sub-agent with payload mapping\">\n <i class=\"fa-solid fa-share-nodes\"></i>\n Link Related\n </button>\n }\n </div>\n </div>\n <!-- Empty State -->\n @if (totalSubAgentCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-sitemap\"\n Title=\"No Sub-Agents\"\n Message=\"Sub-agents help build complex workflows through hierarchical orchestration.\"\n Size=\"compact\">\n <div class=\"empty-state-info\">\n <div class=\"info-card\">\n <i class=\"fa-solid fa-link\" style=\"color: var(--mj-status-info);\"></i>\n <strong>Child Sub-Agents</strong>\n <p>Share payload structure, dedicated to parent</p>\n </div>\n <div class=\"info-card\">\n <i class=\"fa-solid fa-share-nodes\" style=\"color: var(--mj-brand-primary);\"></i>\n <strong>Related Sub-Agents</strong>\n <p>Reusable agents with payload mapping</p>\n </div>\n </div>\n </mj-empty-state>\n } @else {\n <!-- Unified Sub-Agent List -->\n <div class=\"entity-list\">\n @for (item of filteredSubAgents; track item.agent.ID) {\n <div class=\"entity-item sub-agent-item\"\n [class.child-sub-agent]=\"item.type === 'child'\"\n [class.related-sub-agent]=\"item.type === 'related'\"\n (click)=\"navigateToEntity('MJ: AI Agents', item.agent.ID)\">\n <!-- Type Badge -->\n <div class=\"sub-agent-type-badge\"\n [style.background-color]=\"getSubAgentBadgeColor(item)\">\n <i [class]=\"getSubAgentBadgeIcon(item)\"></i>\n {{ getSubAgentBadgeText(item) }}\n </div>\n <!-- Agent Icon -->\n <div class=\"item-icon\">\n @if (hasSubAgentLogoURL(item.agent)) {\n <img [src]=\"item.agent.LogoURL\"\n [alt]=\"item.agent.Name + ' logo'\"\n class=\"sub-agent-logo\">\n } @else {\n <i [class]=\"getSubAgentIcon(item.agent)\"></i>\n }\n </div>\n <!-- Agent Content -->\n <div class=\"item-content\">\n <div class=\"item-title\">{{ item.agent.Name || 'Untitled Sub-Agent' }}</div>\n @if (item.agent.Description) {\n <div class=\"item-preview\">{{ item.agent.Description }}</div>\n }\n <div class=\"item-meta\">\n <!-- Payload Info -->\n <span class=\"meta-tag payload-info\">\n <i class=\"fa-solid fa-database\"></i>\n {{ getSubAgentPayloadInfo(item) }}\n </span>\n <!-- Status -->\n @if (item.agent.Status) {\n <span class=\"status-tag\"\n [style.background-color]=\"getStatusBadgeColor()\">\n {{ item.agent.Status }}\n </span>\n }\n <!-- Agent Type -->\n @if (item.agent.Type) {\n <span class=\"meta-tag\">{{ item.agent.Type }}</span>\n }\n </div>\n </div>\n <!-- Actions -->\n <div class=\"item-actions\">\n @if (EditMode) {\n <!-- Output Mapping Config (Related only) -->\n @if (item.type === 'related') {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"configureOutputMapping(item, $event)\"\n title=\"Configure output mapping\">\n <i class=\"fa-solid fa-exchange-alt\"></i>\n </button>\n }\n <!-- Advanced Settings (Child only) -->\n @if (item.type === 'child' && UserCanCreateSubAgents) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"openSubAgentAdvancedSettings(item.agent, $event)\"\n title=\"Advanced settings\">\n <i class=\"fa-solid fa-cog\"></i>\n </button>\n }\n <!-- Remove/Unlink -->\n @if (UserCanDeleteSubAgents) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"item.type === 'child' ? removeChildSubAgent(item, $event) : unlinkRelatedSubAgent(item, $event)\"\n [title]=\"item.type === 'child' ? 'Delete child sub-agent' : 'Unlink related sub-agent'\"\n class=\"error-action\">\n <i [class]=\"item.type === 'child' ? 'fa-solid fa-trash' : 'fa-solid fa-unlink'\"></i>\n </button>\n }\n }\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Prompts (With Model Selection) -->\n @if (record.ID) {\n <mj-accordion-panel id=\"prompts\"\n [Expanded]=\"GetSectionExpanded('prompts', false)\"\n [Disabled]=\"loadingStates.prompts\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-comments\"></i> Prompts\n @if (loadingStates.prompts) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (promptCount > 0) {\n <span> ({{ promptCount }})</span>\n }\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"prompt-controls\">\n <!-- Model Selection Mode Control -->\n <div class=\"model-selection-mode\">\n <label class=\"model-selection-label\">\n <i class=\"fa-solid fa-sliders\"></i>\n Model Selection:\n </label>\n @if (EditMode) {\n <mj-dropdown\n [(ngModel)]=\"record.ModelSelectionMode\"\n name=\"modelSelectionMode\"\n [Data]=\"modelSelectionModes\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n class=\"model-selection-dropdown\">\n </mj-dropdown>\n } @else {\n <span class=\"model-selection-value\">{{ record.ModelSelectionMode || 'Agent Type' }}</span>\n }\n </div>\n </div>\n <div class=\"header-actions\">\n @if (EditMode && UserCanCreateNewPrompts) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addPrompt()\">\n <i class=\"fa-solid fa-plus\"></i> Add Prompt\n </button>\n }\n </div>\n </div>\n @if (promptCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-comments\"\n Title=\"No Prompts Configured\"\n Message=\"Add prompts to define how this agent processes requests and generates responses.\"\n [ActionText]=\"(EditMode && UserCanCreateNewPrompts) ? 'Create First Prompt' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"addPrompt()\"\n Size=\"compact\" />\n } @else {\n <div class=\"entity-list\">\n @for (prompt of agentPrompts; track prompt.ID) {\n <div class=\"entity-item prompt-item\" (click)=\"navigateToEntity('MJ: AI Prompts', prompt.ID)\">\n <div class=\"item-icon\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n </div>\n <div class=\"item-content\">\n <div class=\"item-title\">{{ prompt.Name }}</div>\n @if (prompt.TemplateText) {\n <div class=\"item-preview\">{{ prompt.TemplateText.substring(0, 120) }}{{ prompt.TemplateText.length > 120 ? '...' : '' }}</div>\n }\n <div class=\"item-meta\">\n @if (prompt.PromptRole) {\n <span class=\"meta-tag\">{{ prompt.PromptRole }}</span>\n }\n </div>\n </div>\n <div class=\"item-actions\">\n @if (EditMode && UserCanCreatePrompts) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"openPromptAdvancedSettings(prompt, $event)\"\n title=\"Advanced settings\">\n <i class=\"fa-solid fa-cog\"></i>\n </button>\n }\n @if (EditMode && UserCanDeletePrompts) {\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"removePrompt(prompt, $event)\"\n title=\"Remove prompt\"\n class=\"error-action\">\n <i class=\"fa-solid fa-trash\"></i>\n </button>\n }\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n </div>\n }\n @if (promptCount > agentPrompts.length) {\n <div class=\"view-more-item\" (click)=\"navigateToEntity('MJ: AI Prompts', '')\">\n <span>View all {{ promptCount }} prompts...</span>\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Learning & Analytics -->\n @if (record.ID) {\n <mj-accordion-panel id=\"learning\"\n [Expanded]=\"GetSectionExpanded('learning', false)\"\n [Disabled]=\"loadingStates.learningCycles\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-brain\"></i> Learning Cycles\n @if (loadingStates.learningCycles) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (learningCycleCount > 0) {\n <span> ({{ learningCycleCount }})</span>\n }\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Monitor and manage learning cycles, training sessions, and performance analytics.\n </div>\n </div>\n @if (learningCycleCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-brain\"\n Title=\"No Learning Cycles\"\n Message=\"Learning cycles will appear here as the agent processes requests and improves over time.\"\n Size=\"compact\" />\n } @else {\n <div class=\"entity-list\">\n @for (cycle of learningCycles; track cycle.ID) {\n <div class=\"entity-item learning-item\" (click)=\"navigateToEntity('MJ: AI Agent Learning Cycles', cycle.ID)\">\n <div class=\"item-icon\">\n <i class=\"fa-solid fa-brain\"></i>\n </div>\n <div class=\"item-content\">\n <div class=\"item-title\">Learning Cycle {{ cycle.ID.substring(0, 8) }}</div>\n <div class=\"item-meta\">\n @if (cycle.StartedAt) {\n <span class=\"meta-tag\">\n <i class=\"fa-solid fa-calendar\"></i>\n {{ cycle.StartedAt | date:'short' }}\n </span>\n }\n @if (cycle.Status) {\n <span class=\"status-tag\">{{ cycle.Status }}</span>\n }\n </div>\n </div>\n <div class=\"item-actions\">\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n </div>\n }\n @if (learningCycleCount > learningCycles.length) {\n <div class=\"view-more-item\" (click)=\"navigateToEntity('MJ: AI Agent Learning Cycles', '')\">\n <span>View all {{ learningCycleCount }} cycles...</span>\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Notes & Documentation -->\n @if (record.ID) {\n <mj-accordion-panel id=\"notes\"\n [Expanded]=\"GetSectionExpanded('notes', false)\"\n [Disabled]=\"loadingStates.notes\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-sticky-note\"></i> Notes\n @if (loadingStates.notes) {\n <span><i class=\"fa-solid fa-spinner fa-spin\"></i></span>\n } @else if (noteCount > 0) {\n <span> ({{ noteCount }})</span>\n }\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Manage notes, documentation, and annotations for this agent.\n </div>\n <div class=\"header-actions\">\n @if (EditMode && UserCanCreateNotes) {\n <button mjButton variant=\"primary\" size=\"sm\" (click)=\"addNote()\">\n <i class=\"fa-solid fa-plus\"></i> Add Note\n </button>\n }\n </div>\n </div>\n @if (noteCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-sticky-note\"\n Title=\"No Notes\"\n Message=\"Add notes to document important information, observations, or instructions for this agent.\"\n [ActionText]=\"(EditMode && UserCanCreateNotes) ? 'Create First Note' : ''\"\n ActionIcon=\"fa-solid fa-plus\"\n (Action)=\"addNote()\"\n Size=\"compact\" />\n } @else {\n <div class=\"entity-list\">\n @for (note of agentNotes; track note.ID) {\n <div class=\"entity-item note-item\" (click)=\"navigateToEntity('MJ: AI Agent Notes', note.ID)\">\n <div class=\"item-icon\">\n <i class=\"fa-solid fa-sticky-note\"></i>\n </div>\n <div class=\"item-content\">\n <div class=\"item-title\">{{ note.Type || 'Note' }}</div>\n @if (note.Note) {\n <div class=\"item-preview\">{{ note.Note.substring(0, 100) }}{{ note.Note.length > 100 ? '...' : '' }}</div>\n }\n <div class=\"item-meta\">\n @if (note.__mj_CreatedAt) {\n <span class=\"meta-tag\">\n <i class=\"fa-solid fa-calendar\"></i>\n {{ note.__mj_CreatedAt | date:'short' }}\n </span>\n }\n </div>\n </div>\n <div class=\"item-actions\">\n <i class=\"fa-solid fa-external-link\"></i>\n </div>\n </div>\n }\n @if (noteCount > agentNotes.length) {\n <div class=\"view-more-item\" (click)=\"navigateToEntity('MJ: AI Agent Notes', '')\">\n <span>View all {{ noteCount }} notes...</span>\n </div>\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Search -->\n @if (record.ID) {\n <mj-accordion-panel id=\"search\"\n [Expanded]=\"GetSectionExpanded('search', false)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-magnifying-glass\"></i> Search\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Control this agent's access to <strong>Scoped Search</strong> and assign the scopes it can use for pre-execution RAG or agent-invoked search.\n </div>\n </div>\n\n <!-- Scope Access mode -->\n <div class=\"agent-search-access\">\n <label class=\"agent-search-access-option\" [class.active]=\"record.SearchScopeAccess === 'All'\">\n <input type=\"radio\" name=\"SearchScopeAccess\" value=\"All\" [checked]=\"record.SearchScopeAccess === 'All'\" [disabled]=\"!EditMode\" (change)=\"record.SearchScopeAccess = 'All'\">\n <i class=\"fa-solid fa-globe\"></i>\n <div class=\"agent-search-access-text\">\n <div class=\"agent-search-access-title\">All</div>\n <div class=\"agent-search-access-desc\">Can use any scope including Global. No scope restriction.</div>\n </div>\n </label>\n <label class=\"agent-search-access-option\" [class.active]=\"record.SearchScopeAccess === 'Assigned'\">\n <input type=\"radio\" name=\"SearchScopeAccess\" value=\"Assigned\" [checked]=\"record.SearchScopeAccess === 'Assigned'\" [disabled]=\"!EditMode\" (change)=\"record.SearchScopeAccess = 'Assigned'\">\n <i class=\"fa-solid fa-user-check\"></i>\n <div class=\"agent-search-access-text\">\n <div class=\"agent-search-access-title\">Assigned</div>\n <div class=\"agent-search-access-desc\">Can use ONLY scopes listed below. Other scopes are rejected with ACCESS_DENIED.</div>\n </div>\n </label>\n <label class=\"agent-search-access-option\" [class.active]=\"record.SearchScopeAccess === 'None'\">\n <input type=\"radio\" name=\"SearchScopeAccess\" value=\"None\" [checked]=\"record.SearchScopeAccess === 'None'\" [disabled]=\"!EditMode\" (change)=\"record.SearchScopeAccess = 'None'\">\n <i class=\"fa-solid fa-ban\"></i>\n <div class=\"agent-search-access-text\">\n <div class=\"agent-search-access-title\">None</div>\n <div class=\"agent-search-access-desc\">No search capability. The Scoped Search action is disabled for this agent.</div>\n </div>\n </label>\n </div>\n\n <!-- Assigned scopes grid -->\n @if (record.SearchScopeAccess !== 'None') {\n <div class=\"agent-search-grid-header\">\n <h4>Assigned Scopes</h4>\n <p class=\"section-description\">\n <strong>Pre-Execution</strong> scopes are injected automatically before the first LLM call.\n <strong>Agent-Invoked</strong> scopes are callable via the Scoped Search tool during execution.\n <strong>Both</strong> covers both paths.\n </p>\n </div>\n <mj-search-scope-child-grid\n [ParentID]=\"record.ID\"\n ChildEntityName=\"MJ: AI Agent Search Scopes\"\n ParentFieldName=\"AgentID\"\n [Columns]=\"AgentSearchScopeColumns\"\n [Disabled]=\"!EditMode\"\n AddButtonLabel=\"+ Assign another scope\"\n EmptyMessage=\"No scopes assigned yet. Assign at least one if this agent will use Scoped Search.\"\n (RowsChanged)=\"LoadPermissionSummary()\">\n </mj-search-scope-child-grid>\n\n <!-- Phase 2A: read-only audit summary of who has\n permission on each of this agent's assigned scopes.\n Editing happens in the Knowledge Hub Config dashboard\n (see \"Permissions\" subtab under Search Scopes). -->\n <div class=\"agent-search-section\" style=\"margin-top: 16px;\">\n <h4 style=\"margin: 0 0 8px 0;\">\n <i class=\"fa-solid fa-shield-halved\"></i> Effective scope permissions\n </h4>\n <p class=\"section-description\" style=\"margin-bottom: 8px;\">\n Per-user / per-role grants on the scopes assigned above. Edit grants in\n <strong>Knowledge Hub Config → Search Scopes → Permissions</strong>.\n </p>\n @if (IsLoadingPermissions) {\n <div style=\"color: var(--mj-text-muted);\">Loading permissions…</div>\n } @else if (PermissionSummary.length === 0) {\n <div style=\"color: var(--mj-text-muted); font-style: italic;\">\n No scopes assigned yet \u2014 permissions will appear here once you add scopes above.\n </div>\n } @else {\n @for (s of PermissionSummary; track s.ScopeID) {\n <div style=\"margin-bottom: 12px; padding: 8px 12px; background: var(--mj-bg-surface-card); border: 1px solid var(--mj-border-subtle); border-radius: 4px;\">\n <div style=\"font-weight: 600; margin-bottom: 4px;\">{{ s.ScopeName }}</div>\n @if (s.Permissions.length === 0) {\n <div style=\"color: var(--mj-text-muted); font-size: 0.9em;\">\n No explicit permissions. Access falls back to this agent's <code>SearchScopeAccess</code> setting.\n </div>\n } @else {\n <ul style=\"margin: 4px 0 0 16px; padding: 0;\">\n @for (p of s.Permissions; track p.Principal + p.Level) {\n <li style=\"font-size: 0.9em; padding: 2px 0;\">\n <i class=\"fa-solid\" [class.fa-user]=\"p.PrincipalType === 'User'\" [class.fa-users]=\"p.PrincipalType === 'Role'\"></i>\n <strong>{{ p.Principal }}</strong>\n <span style=\"color: var(--mj-text-muted);\">({{ p.PrincipalType }})</span>\n — <span [style.color]=\"p.Level === 'None' ? 'var(--mj-status-error-text)' : 'var(--mj-text-primary)'\">{{ p.Level }}</span>\n </li>\n }\n </ul>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Payload -->\n <mj-accordion-panel id=\"payload\"\n [Expanded]=\"GetSectionExpanded('payload', false)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-exchange-alt\"></i> Payload Management\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Configure how this agent handles data payloads, path routing, and validation between parent and child agents.\n </div>\n </div>\n <!-- Payload Scope Section -->\n <div class=\"payload-section\">\n <h3 class=\"payload-section-title\">\n <i class=\"fa-solid fa-target\"></i>\n Payload Scope\n </h3>\n <div class=\"payload-field-container\">\n <div class=\"payload-field-info\">\n <label class=\"payload-field-label\">Payload Scope Path</label>\n <p class=\"payload-field-description\">\n Specify a path within the parent payload that this sub-agent should operate on.\n Leave empty to receive the entire payload.\n </p>\n </div>\n <div class=\"payload-field-input\">\n <mj-form-field\n FieldName=\"PayloadScope\"\n Type=\"textbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\"\n style=\"width: 100%;\">\n </mj-form-field>\n <div class=\"payload-field-example\">\n <i class=\"fa-solid fa-lightbulb\"></i>\n <span>Example: <code>/customer/profile</code> or <code>/analysis/results</code></span>\n </div>\n </div>\n </div>\n </div>\n <!-- Path Configuration Section -->\n <div class=\"payload-section\">\n <h3 class=\"payload-section-title\">\n <i class=\"fa-solid fa-route\"></i>\n Path Configuration\n </h3>\n <div class=\"payload-paths-grid\">\n <!-- Downstream Paths -->\n <div class=\"payload-path-card\">\n <div class=\"payload-path-header\">\n <div class=\"payload-path-icon downstream\">\n <i class=\"fa-solid fa-arrow-down\"></i>\n </div>\n <div class=\"payload-path-info\">\n <h4>Downstream Paths</h4>\n <p>JSON array of paths to pass to sub-agents</p>\n </div>\n </div>\n <div class=\"payload-path-content\">\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"record.PayloadDownstreamPaths || '["*"]'\"\n [readonly]=\"!EditMode\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"height: 100px; width: 100%;\"\n (valueChange)=\"updatePayloadField('PayloadDownstreamPaths', $event)\">\n </mj-code-editor>\n </div>\n <div class=\"payload-path-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Use <code>[\"*\"]</code> to pass entire payload or specify paths like <code>[\"user.id\", \"order.*\"]</code>\n </div>\n </div>\n </div>\n <!-- Upstream Paths -->\n <div class=\"payload-path-card\">\n <div class=\"payload-path-header\">\n <div class=\"payload-path-icon upstream\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n </div>\n <div class=\"payload-path-info\">\n <h4>Upstream Paths</h4>\n <p>JSON array of paths sub-agents can write back</p>\n </div>\n </div>\n <div class=\"payload-path-content\">\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"record.PayloadUpstreamPaths || '["*"]'\"\n [readonly]=\"!EditMode\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"height: 100px; width: 100%;\"\n (valueChange)=\"updatePayloadField('PayloadUpstreamPaths', $event)\">\n </mj-code-editor>\n </div>\n <div class=\"payload-path-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Use <code>[\"*\"]</code> to allow all writes or limit to specific paths\n </div>\n </div>\n </div>\n <!-- Self Read Paths -->\n <div class=\"payload-path-card\">\n <div class=\"payload-path-header\">\n <div class=\"payload-path-icon self-read\">\n <i class=\"fa-solid fa-eye\"></i>\n </div>\n <div class=\"payload-path-info\">\n <h4>Self Read Paths</h4>\n <p>JSON array of paths this agent can read</p>\n </div>\n </div>\n <div class=\"payload-path-content\">\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"record.PayloadSelfReadPaths || '[]'\"\n [readonly]=\"!EditMode\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"height: 100px; width: 100%;\"\n (valueChange)=\"updatePayloadField('PayloadSelfReadPaths', $event)\">\n </mj-code-editor>\n </div>\n <div class=\"payload-path-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Paths this agent's prompts can read from the payload\n </div>\n </div>\n </div>\n <!-- Self Write Paths -->\n <div class=\"payload-path-card\">\n <div class=\"payload-path-header\">\n <div class=\"payload-path-icon self-write\">\n <i class=\"fa-solid fa-pen\"></i>\n </div>\n <div class=\"payload-path-info\">\n <h4>Self Write Paths</h4>\n <p>JSON array of paths this agent can write to</p>\n </div>\n </div>\n <div class=\"payload-path-content\">\n <div class=\"json-editor-container\">\n <mj-code-editor\n [value]=\"record.PayloadSelfWritePaths || '[]'\"\n [readonly]=\"!EditMode\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"height: 100px; width: 100%;\"\n (valueChange)=\"updatePayloadField('PayloadSelfWritePaths', $event)\">\n </mj-code-editor>\n </div>\n <div class=\"payload-path-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Paths this agent's prompts can write back to the payload\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Validation Section -->\n <div class=\"payload-section\">\n <h3 class=\"payload-section-title\">\n <i class=\"fa-solid fa-shield-check\"></i>\n Final Payload Validation\n </h3>\n <div class=\"payload-validation-container\">\n <div class=\"payload-validation-settings\">\n <div class=\"validation-field-group\">\n <label class=\"validation-field-label\">Validation Mode</label>\n <p class=\"validation-field-description\">How to handle validation failures</p>\n <mj-form-field\n FieldName=\"FinalPayloadValidationMode\"\n Type=\"dropdownlist\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\"\n style=\"width: 100%;\">\n </mj-form-field>\n </div>\n <div class=\"validation-field-group\">\n <label class=\"validation-field-label\">Max Retries</label>\n <p class=\"validation-field-description\">Maximum validation retry attempts</p>\n <mj-form-field\n FieldName=\"FinalPayloadValidationMaxRetries\"\n Type=\"numerictextbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\"\n style=\"width: 100%;\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"payload-validation-schema\">\n <label class=\"validation-schema-label\">\n <i class=\"fa-solid fa-code\"></i>\n Validation Schema\n </label>\n <p class=\"validation-schema-description\">\n JSON schema or validation rules for the final payload structure\n </p>\n <div class=\"validation-schema-editor\">\n <mj-code-editor\n [value]=\"record.FinalPayloadValidation || '{}'\"\n [readonly]=\"!EditMode\"\n language=\"json\"\n [lineWrapping]=\"true\"\n style=\"height: 200px; width: 100%;\"\n (valueChange)=\"updatePayloadField('FinalPayloadValidation', $event)\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Execution Guardrails (New Separate Panel) -->\n <mj-accordion-panel id=\"guardrails\"\n [Expanded]=\"GetSectionExpanded('guardrails', false)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-shield-halved\"></i> Execution Guardrails\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Set limits to prevent runaway agent executions and control resource usage.\n </div>\n </div>\n <div class=\"form-fields-grid\">\n <mj-form-field\n FieldName=\"MaxCostPerRun\"\n Type=\"numerictextbox\"\n Caption=\"Max Cost ($)\"\n Description=\"Maximum cost per run\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <mj-form-field\n FieldName=\"MaxTokensPerRun\"\n Type=\"numerictextbox\"\n Caption=\"Max Tokens\"\n Description=\"Maximum tokens per run\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <mj-form-field\n FieldName=\"MaxIterationsPerRun\"\n Type=\"numerictextbox\"\n Caption=\"Max Iterations\"\n Description=\"Maximum prompt iterations\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <mj-form-field\n FieldName=\"MaxTimePerRun\"\n Type=\"numerictextbox\"\n Caption=\"Max Time (seconds)\"\n Description=\"Maximum execution time\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Configuration (Settings Panel) -->\n <mj-accordion-panel id=\"config\"\n [Expanded]=\"GetSectionExpanded('config', false)\">\n <ng-template mjAccordionTitle>\n <i class=\"fa-solid fa-cogs\"></i> Configuration\n </ng-template>\n <div class=\"panel-content\">\n <div class=\"section-header\">\n <div class=\"section-description\">\n Configure agent behavior, execution settings, and advanced features.\n </div>\n </div>\n <!-- Identity & Behavior Section -->\n <div class=\"config-section\">\n <h3 class=\"config-section-title\">\n <i class=\"fa-solid fa-id-card\"></i>\n Identity & Behavior\n </h3>\n <div class=\"config-grid\">\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Agent Status</h4>\n <p>Current availability and operational status</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n @if (EditMode) {\n <mj-dropdown\n [(ngModel)]=\"record.Status\"\n [Data]=\"statusOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n name=\"agentStatus\"\n class=\"config-field-input\">\n </mj-dropdown>\n } @else {\n <span class=\"config-field-display\">{{ record.Status || 'Not Set' }}</span>\n }\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-sitemap\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Agent Type</h4>\n <p>Category and system-level behavior</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n @if (EditMode) {\n <mj-dropdown\n [(ngModel)]=\"record.TypeID\"\n [Data]=\"agentTypes\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n name=\"agentTypeID\"\n class=\"config-field-input\">\n </mj-dropdown>\n } @else {\n <span class=\"config-field-display\">{{ record.Type || 'Not Set' }}</span>\n }\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-folder-tree\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Category</h4>\n <p>Organizational category for this agent</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n @if (EditMode) {\n <mj-tree-dropdown\n [BranchConfig]=\"CategoryBranchConfig\"\n [Value]=\"SelectedCategoryKey\"\n SelectionMode=\"single\"\n SelectableTypes=\"branch\"\n Placeholder=\"Select a category...\"\n [Clearable]=\"true\"\n [EnableSearch]=\"true\"\n (ValueChange)=\"OnCategoryChange($event)\">\n </mj-tree-dropdown>\n } @else {\n <span class=\"config-field-display\">{{ record.Category || 'Not Set' }}</span>\n }\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-bolt\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Expose as Action</h4>\n <p>Make available as an action for other agents</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"ExposeAsAction\"\n Type=\"checkbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"config-card full-width\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-align-left\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Description</h4>\n <p>Detailed agent description and purpose</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"Description\"\n Type=\"textarea\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\"\n style=\"width: 100%;\">\n </mj-form-field>\n </div>\n </div>\n </div>\n </div>\n <!-- Execution Settings Section -->\n <div class=\"config-section\">\n <h3 class=\"config-section-title\">\n <i class=\"fa-solid fa-play\"></i>\n Execution Settings\n </h3>\n <div class=\"config-grid\">\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-layer-group\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Execution Mode</h4>\n <p>How sub-agents are executed</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"ExecutionMode\"\n Type=\"dropdownlist\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-sort-numeric-down\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Execution Order</h4>\n <p>Order when run with siblings</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"ExecutionOrder\"\n Type=\"numerictextbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-tachometer-alt\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Default Effort Level</h4>\n <p>Default effort level for all prompts (1-100)</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"DefaultPromptEffortLevel\"\n Type=\"numerictextbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <div class=\"config-card-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Higher values request more thorough reasoning (1=minimal, 100=maximum)\n </div>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-code\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Driver Class</h4>\n <p>Custom implementation class</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"DriverClass\"\n Type=\"textbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n </div>\n </div>\n <!-- Visual Identity Section -->\n <div class=\"config-section\">\n <h3 class=\"config-section-title\">\n <i class=\"fa-solid fa-palette\"></i>\n Visual Identity\n </h3>\n <div class=\"config-grid\">\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-icons\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Icon Class</h4>\n <p>Font Awesome icon class</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"IconClass\"\n Type=\"textbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <div class=\"config-card-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Example: <code>fa-solid fa-robot</code>\n </div>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-image\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Logo URL</h4>\n <p>URL for agent logo image</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"LogoURL\"\n Type=\"textbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n <div class=\"config-card-hint\">\n <i class=\"fa-solid fa-info-circle\"></i>\n Takes precedence over Icon Class\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Context Compression Section -->\n <div class=\"config-section\">\n <h3 class=\"config-section-title\">\n <i class=\"fa-solid fa-compress\"></i>\n Context Compression\n </h3>\n <div class=\"config-grid\">\n <div class=\"config-card full-width\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-toggle-on\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Enable Context Compression</h4>\n <p>Automatically compress conversation context when message threshold is reached</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"EnableContextCompression\"\n Type=\"checkbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\"\n (valueChange)=\"onContextCompressionToggle($event)\">\n </mj-form-field>\n </div>\n </div>\n @if (record.EnableContextCompression) {\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-hashtag\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Message Threshold</h4>\n <p>Messages before compression triggers</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"ContextCompressionMessageThreshold\"\n Type=\"numerictextbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-save\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Messages to Keep</h4>\n <p>Recent messages to retain uncompressed</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n <mj-form-field\n FieldName=\"ContextCompressionMessageRetentionCount\"\n Type=\"numerictextbox\"\n Caption=\"\"\n [EditMode]=\"EditMode\"\n [Record]=\"record\">\n </mj-form-field>\n </div>\n </div>\n <div class=\"config-card\">\n <div class=\"config-card-header\">\n <div class=\"config-card-icon\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n </div>\n <div class=\"config-card-info\">\n <h4>Compression Prompt</h4>\n <p>Prompt used for summarization</p>\n </div>\n </div>\n <div class=\"config-card-content\">\n @if (EditMode) {\n <div class=\"prompt-selector-container\">\n <div class=\"prompt-display\">\n @if (selectedContextCompressionPrompt) {\n <span class=\"prompt-name\">{{ selectedContextCompressionPrompt.Name }}</span>\n } @else {\n <span class=\"no-prompt\">No prompt selected</span>\n }\n </div>\n <div class=\"prompt-actions\">\n <button type=\"button\"\n mjButton\n variant=\"outline\"\n size=\"sm\"\n (click)=\"openContextCompressionPromptSelector()\"\n class=\"prompt-select-btn\">\n <i class=\"fa-solid fa-search\"></i>\n {{ selectedContextCompressionPrompt ? 'Change' : 'Select' }} Prompt\n </button>\n @if (selectedContextCompressionPrompt) {\n <button type=\"button\"\n mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"clearContextCompressionPrompt()\"\n class=\"prompt-clear-btn\"\n title=\"Clear selection\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n </div>\n </div>\n } @else {\n <span class=\"config-field-display\">{{ selectedContextCompressionPrompt?.Name || record.ContextCompressionPrompt || 'Not Set' }}</span>\n }\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n </form>\n</mj-record-form-container>\n}\n\n<!-- Permissions Dialog (from @memberjunction/ng-agents) -->\n@if (ShowPermissionsDialog) {\n <mj-agent-permissions-dialog\n [Agent]=\"record\"\n (Closed)=\"onPermissionsDialogClosed()\"\n (PermissionsChanged)=\"refreshRelatedData()\">\n </mj-agent-permissions-dialog>\n}", styles: ["/* AI Agent Form - Modern Redesign */\n.record-form-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-page);\n}\n\n.record-form {\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n/* Agent Header Section - Compact Design */\n.agent-header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 8px 16px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n transition: padding 0.2s ease;\n}\n\n.agent-header-content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n}\n\n/* Header collapse toggle button */\n.agent-header-toggle {\n background: none;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n padding: 0;\n transition: all 0.15s ease;\n}\n\n.agent-header-toggle:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-strong);\n}\n\n.agent-header-toggle i {\n font-size: 10px;\n}\n\n.agent-overview {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.agent-icon-wrapper {\n width: 36px;\n height: 36px;\n background: var(--mj-brand-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n flex-shrink: 0;\n transition: all 0.2s ease;\n}\n\n.agent-icon-wrapper i {\n color: var(--mj-text-inverse);\n font-size: 18px;\n}\n\n/* \u2500\u2500 Minimized Floating Header Bar \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.agent-header-mini {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 12px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n height: 32px;\n}\n\n.agent-header-mini-expand {\n background: none;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n width: 22px;\n height: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: var(--mj-text-disabled);\n padding: 0;\n flex-shrink: 0;\n transition: all 0.15s ease;\n}\n\n.agent-header-mini-expand:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-strong);\n}\n\n.agent-header-mini-expand i {\n font-size: 9px;\n}\n\n.agent-header-mini-name {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 300px;\n}\n\n.agent-header-mini-status {\n padding: 1px 7px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n color: var(--mj-text-inverse);\n flex-shrink: 0;\n}\n\n.agent-header-mini-spacer {\n flex: 1;\n}\n\n.agent-header-mini-btn {\n background: none;\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: var(--mj-text-muted);\n padding: 0;\n flex-shrink: 0;\n transition: all 0.15s ease;\n}\n\n.agent-header-mini-btn:hover:not(:disabled) {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-strong);\n}\n\n.agent-header-mini-btn:disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.agent-header-mini-btn--primary {\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.agent-header-mini-btn--primary:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 50%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.agent-header-mini-btn i {\n font-size: 11px;\n}\n\n.agent-icon-wrapper img.agent-logo {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 8px;\n}\n\n.agent-info {\n flex: 1;\n min-width: 0;\n}\n\n.agent-name {\n font-size: 18px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n line-height: 1.2;\n}\n\n.agent-name-input {\n font-size: 16px !important;\n font-weight: 500 !important;\n height: 30px !important;\n width: 100% !important;\n max-width: 350px !important;\n}\n\n.agent-meta {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.status-badge {\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.status-badge.active {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n}\n\n.status-badge.pending {\n background: var(--mj-status-warning);\n color: var(--mj-text-primary);\n}\n\n.status-badge.disabled {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n}\n\n.execution-mode,\n.parent-agent {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 4px 10px;\n border-radius: 12px;\n}\n\n.execution-mode i,\n.parent-agent i {\n font-size: 12px;\n opacity: 0.8;\n}\n\n.parent-agent.clickable {\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.parent-agent.clickable:hover {\n background: var(--mj-border-default);\n color: var(--mj-brand-primary);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.parent-agent.clickable:active {\n transform: translateY(0);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n/* Prompt Controls Section */\n.prompt-controls {\n flex: 1;\n margin-right: 16px;\n}\n\n.agent-meta-info {\n display: flex;\n gap: 24px;\n margin-top: 12px;\n flex-wrap: wrap;\n}\n\n.meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.meta-label {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.meta-value {\n font-size: 14px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.agent-description {\n margin-top: 16px;\n color: var(--mj-text-muted);\n line-height: 1.6;\n font-size: 15px;\n}\n\n.agent-description-input {\n width: 100%;\n max-width: 600px;\n min-height: 80px;\n resize: vertical;\n}\n\n/* Action Buttons Section */\n.agent-actions {\n display: flex;\n flex-direction: row;\n gap: 8px;\n flex-shrink: 0;\n align-items: center;\n}\n\n.action-buttons-row {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.action-button {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 20px;\n border-radius: 8px;\n font-weight: 500;\n font-size: 14px;\n transition: all 0.2s ease;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);\n}\n\n.action-button:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);\n}\n\n.action-button.primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.action-button.primary:hover {\n background: var(--mj-brand-primary-hover);\n}\n\n.action-button.secondary {\n background: var(--mj-text-muted);\n color: var(--mj-text-inverse);\n}\n\n.action-button.secondary:hover {\n background: var(--mj-text-secondary);\n}\n\n.action-warnings {\n margin-top: 8px;\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n/* Panel-Based Form Content */\n.form-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-page);\n padding: 8px 12px;\n}\n\n/* Panel Content */\n.panel-content {\n padding: 16px;\n background: var(--mj-bg-surface);\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n gap: 16px;\n flex-wrap: wrap;\n}\n\n.section-description {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.6;\n margin-bottom: 16px;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-shrink: 0;\n}\n\n.tab-section {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n padding: 24px;\n margin-bottom: 24px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\n border: 1px solid var(--mj-border-default);\n}\n\n.section-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 16px;\n border-bottom: 2px solid var(--mj-bg-surface-sunken);\n}\n\n.section-title {\n display: flex;\n align-items: center;\n gap: 12px;\n margin: 0;\n color: var(--mj-text-primary);\n font-size: 18px;\n font-weight: 600;\n}\n\n.section-title i {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n\n.section-description {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.6;\n margin-top: 8px;\n}\n\n/* Form Fields Grid */\n.form-fields-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n gap: 20px;\n margin-top: 20px;\n}\n\n.form-field-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.form-field-label {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n/* Sub-grids styling (legacy) */\n.sub-grid-container {\n height: 500px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n display: none; /* Hidden as we now use cards */\n}\n\n/* Empty States */\n/* Loading State */\n.loading-state {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i {\n font-size: 36px;\n color: var(--mj-brand-primary);\n margin-bottom: 16px;\n display: block;\n}\n\n.loading-state p {\n margin: 0;\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n/* Loading State */\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: color-mix(in srgb, var(--mj-bg-surface) 90%, transparent);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n}\n\n.loading-spinner {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n}\n\n.spinner-icon {\n width: 48px;\n height: 48px;\n border: 4px solid var(--mj-bg-surface-sunken);\n border-top: 4px solid var(--mj-brand-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n/* Quick Actions */\n.quick-actions {\n display: flex;\n gap: 16px;\n margin-top: 20px;\n padding-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.quick-action-card {\n flex: 1;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n cursor: pointer;\n transition: all 0.2s ease;\n text-align: center;\n}\n\n.quick-action-card:hover {\n background: var(--mj-bg-surface);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-2px);\n}\n\n.quick-action-icon {\n font-size: 32px;\n color: var(--mj-brand-primary);\n margin-bottom: 8px;\n}\n\n.quick-action-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 4px;\n}\n\n.quick-action-description {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n/* Header Actions */\n.header-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n\n/* Entity List Interface */\n.entity-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 16px;\n}\n\n.entity-item {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.entity-item:hover {\n background: var(--mj-bg-surface);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n transform: translateY(-1px);\n}\n\n.item-icon {\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.prompt-item .item-icon {\n background: var(--mj-status-success);\n}\n\n.action-item .item-icon {\n background: var(--mj-status-warning);\n}\n\n.sub-agent-item .item-icon {\n background: var(--mj-brand-primary);\n}\n\n.model-item .item-icon {\n background: var(--mj-brand-primary);\n}\n\n.learning-item .item-icon {\n background: var(--mj-status-error);\n}\n\n.note-item .item-icon {\n background: var(--mj-status-warning);\n}\n\n.item-icon i {\n color: var(--mj-text-muted);\n font-size: 18px;\n}\n\n.prompt-item .item-icon i,\n.action-item .item-icon i,\n.sub-agent-item .item-icon i,\n.model-item .item-icon i,\n.learning-item .item-icon i,\n.note-item .item-icon i {\n color: var(--mj-text-inverse);\n}\n\n.item-icon img.sub-agent-logo {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 6px;\n}\n\n.item-content {\n flex: 1;\n min-width: 0;\n}\n\n.item-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n line-height: 1.3;\n}\n\n.item-preview {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.4;\n margin: 4px 0 8px 0;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.item-meta {\n display: flex;\n gap: 12px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.meta-tag,\n.priority-tag,\n.status-tag {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n padding: 3px 8px;\n border-radius: 6px;\n font-weight: 500;\n}\n\n.meta-tag {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.priority-tag {\n color: var(--mj-text-inverse);\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n.status-tag {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-tag.active {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-tag.inactive {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.item-actions {\n opacity: 0;\n transition: opacity 0.2s ease;\n color: var(--mj-text-muted);\n font-size: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.entity-item:hover .item-actions {\n opacity: 1;\n}\n\n.entity-item:hover .item-actions > i {\n color: var(--mj-brand-primary);\n}\n\n.view-more-item {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 10px;\n text-align: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.view-more-item:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* Pagination Controls */\n.pagination-controls {\n display: flex;\n gap: 12px;\n align-items: center;\n justify-content: center;\n padding: 16px;\n margin-top: 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n}\n\n.page-nav-btn {\n min-width: 120px;\n font-weight: 500;\n}\n\n.page-nav-btn i {\n font-size: 12px;\n}\n\n.page-nav-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.page-info {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n padding: 0 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n min-width: 200px;\n text-align: center;\n}\n\n.page-info .record-count {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-weight: normal;\n}\n\n.page-info .fa-spinner {\n margin-right: 8px;\n color: var(--mj-brand-primary);\n}\n\n.view-all-btn {\n color: var(--mj-text-muted);\n white-space: nowrap;\n margin-left: auto;\n}\n\n.view-all-btn:hover {\n color: var(--mj-brand-primary);\n}\n\n.view-all-btn i {\n margin-right: 4px;\n}\n\n/* Payload Section Styles */\n.payload-config-section,\n.payload-paths-section,\n.payload-validation-section {\n margin-bottom: 32px;\n}\n\n.subsection-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 16px 0;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.subsection-title i {\n color: var(--mj-brand-primary);\n}\n\n.subsection-divider {\n margin-top: 32px;\n margin-bottom: 16px;\n padding-top: 24px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.payload-config-grid {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 16px;\n margin-bottom: 24px;\n}\n\n.payload-field-group {\n margin-bottom: 20px;\n}\n\n.payload-field-label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n}\n\n.payload-field-label i {\n color: var(--mj-text-muted);\n font-size: 16px;\n}\n\n.field-description {\n font-size: 12px;\n font-weight: normal;\n color: var(--mj-text-muted);\n margin-left: auto;\n}\n\n/* Code editor styling */\n.payload-field-group mj-code-editor {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.payload-field-group mj-code-editor:hover {\n border-color: var(--mj-brand-primary);\n}\n\n/* Payload textarea styling */\n.payload-field-group mj-form-field ::ng-deep textarea {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 13px;\n line-height: 1.5;\n min-height: 120px;\n resize: vertical;\n}\n\n/* Execution History Panel */\n.execution-history-panel {\n max-height: 500px;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Timeline List for Execution History */\n.timeline-list {\n display: flex;\n flex-direction: column;\n gap: 16px;\n margin-top: 16px;\n}\n\n.timeline-item {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.timeline-item:hover {\n background: var(--mj-bg-surface);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n\n.timeline-marker {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.timeline-marker i {\n color: var(--mj-text-inverse);\n font-size: 14px;\n}\n\n.timeline-content {\n flex: 1;\n min-width: 0;\n}\n\n.timeline-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 8px 0;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 16px;\n}\n\n.timeline-date {\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n padding: 2px 8px;\n border-radius: 6px;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.timeline-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 8px;\n}\n\n.timeline-preview {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Modern Card-Based Interface (Legacy - Keep for backward compatibility) */\n.cards-container {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));\n gap: 20px;\n margin-top: 16px;\n}\n\n.entity-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 20px;\n cursor: pointer;\n transition: all 0.3s ease;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n position: relative;\n overflow: hidden;\n}\n\n.entity-card:hover {\n transform: translateY(-4px);\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);\n border-color: var(--mj-brand-primary);\n}\n\n.entity-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 4px;\n background: var(--mj-brand-primary);\n opacity: 0;\n transition: opacity 0.3s ease;\n}\n\n.entity-card:hover::before {\n opacity: 1;\n}\n\n.card-header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.card-icon {\n width: 40px;\n height: 40px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.sub-agent-card .card-icon {\n background: var(--mj-brand-primary);\n}\n\n.prompt-card .card-icon {\n background: var(--mj-status-success);\n}\n\n.action-card .card-icon {\n background: var(--mj-status-warning);\n}\n\n.card-icon i {\n font-size: 18px;\n color: var(--mj-text-muted);\n}\n\n.sub-agent-card .card-icon i,\n.prompt-card .card-icon i,\n.action-card .card-icon i {\n color: var(--mj-text-inverse);\n}\n\n.card-title-section {\n flex: 1;\n min-width: 0;\n}\n\n.card-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0 0 4px 0;\n line-height: 1.3;\n word-wrap: break-word;\n}\n\n.card-description {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.5;\n margin: 8px 0;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.card-meta {\n display: flex;\n gap: 16px;\n margin-top: 12px;\n flex-wrap: wrap;\n}\n\n.meta-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--mj-text-muted);\n padding: 4px 8px;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n}\n\n.meta-item i {\n font-size: 11px;\n opacity: 0.8;\n}\n\n.meta-item.active {\n color: var(--mj-status-success);\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n}\n\n.meta-item.inactive {\n color: var(--mj-status-error);\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n}\n\n.card-actions {\n opacity: 0;\n transition: opacity 0.3s ease;\n color: var(--mj-text-muted);\n}\n\n.entity-card:hover .card-actions {\n opacity: 1;\n color: var(--mj-brand-primary);\n}\n\n/* Badge Styles */\n.priority-badge {\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.type-badge {\n padding: 2px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 500;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.3px;\n}\n\n/* View All Card */\n.view-all-card {\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 120px;\n cursor: pointer;\n transition: all 0.3s ease;\n}\n\n.view-all-card:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n transform: translateY(-2px);\n}\n\n.view-all-content {\n text-align: center;\n color: var(--mj-text-muted);\n font-weight: 500;\n}\n\n.view-all-content i {\n font-size: 24px;\n margin-bottom: 8px;\n display: block;\n}\n\n/* Timeline Interface for History */\n.timeline-container {\n position: relative;\n margin-top: 16px;\n}\n\n.timeline-item {\n display: flex;\n flex-direction: column;\n margin-bottom: 24px;\n transition: all 0.3s ease;\n border-radius: 12px;\n padding: 16px;\n background: transparent;\n border: 1px solid transparent;\n}\n\n.timeline-item:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-default);\n}\n\n.timeline-item.expanded {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n}\n\n.timeline-item.view-all {\n cursor: pointer;\n background: var(--mj-bg-surface-card);\n border: 2px dashed var(--mj-border-default);\n}\n\n.timeline-item.view-all:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-brand-primary);\n}\n\n.timeline-item > div:first-child {\n display: flex;\n align-items: flex-start;\n}\n\n.timeline-marker {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 16px;\n flex-shrink: 0;\n position: relative;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.timeline-marker::after {\n content: '';\n position: absolute;\n top: 50px;\n left: 50%;\n transform: translateX(-50%);\n width: 2px;\n height: 24px;\n background: var(--mj-border-default);\n}\n\n.timeline-item:last-child .timeline-marker::after {\n display: none;\n}\n\n.timeline-marker i {\n color: var(--mj-text-inverse);\n font-size: 16px;\n}\n\n.timeline-marker.view-all-marker {\n background: var(--mj-text-muted);\n}\n\n.timeline-content {\n flex: 1;\n min-width: 0;\n display: flex;\n align-items: flex-start;\n}\n\n.timeline-header {\n flex: 1;\n cursor: pointer;\n}\n\n.timeline-header > div:first-child {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 8px;\n gap: 16px;\n}\n\n.expand-icon {\n transition: transform 0.3s ease;\n margin-right: 8px;\n color: var(--mj-text-muted);\n}\n\n.expand-icon.expanded {\n transform: rotate(90deg);\n}\n\n.timeline-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin: 0;\n line-height: 1.3;\n}\n\n.timeline-date {\n font-size: 12px;\n color: var(--mj-text-muted);\n white-space: nowrap;\n background: var(--mj-bg-surface-card);\n padding: 4px 8px;\n border-radius: 6px;\n margin-left: auto;\n}\n\n.timeline-preview {\n font-size: 13px;\n color: var(--mj-text-muted);\n line-height: 1.5;\n margin-top: 8px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.timeline-status {\n display: flex;\n align-items: center;\n gap: 12px;\n margin-bottom: 8px;\n}\n\n.execution-time {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 4px 8px;\n border-radius: 6px;\n}\n\n.timeline-description {\n color: var(--mj-text-muted);\n font-size: 14px;\n line-height: 1.5;\n margin: 8px 0;\n}\n\n.timeline-error {\n color: var(--mj-status-error);\n font-size: 13px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n padding: 8px 12px;\n border-radius: 6px;\n margin-top: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.timeline-error i {\n flex-shrink: 0;\n}\n\n/* Expanded Content Styles */\n.timeline-expanded-content {\n margin-top: 20px;\n padding-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n animation: fadeIn 0.3s ease;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.result-section,\n.error-section {\n margin-bottom: 20px;\n}\n\n.result-section h5,\n.error-section h5 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-section h5 {\n color: var(--mj-status-error);\n}\n\n.result-content,\n.error-content {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 12px 16px;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-text-secondary);\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 200px;\n overflow-y: auto;\n}\n\n/* Code editor styling within result section */\n.result-section mj-code-editor {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.error-content {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.execution-details {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 16px;\n margin-bottom: 20px;\n}\n\n.detail-row {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n}\n\n.detail-label {\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n min-width: 80px;\n}\n\n.detail-value {\n font-size: 14px;\n color: var(--mj-text-secondary);\n word-break: break-all;\n}\n\n.timeline-actions {\n display: flex;\n gap: 12px;\n justify-content: flex-end;\n}\n\n.btn-primary {\n padding: 8px 16px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 8px;\n transition: all 0.2s ease;\n}\n\n.btn-primary:hover {\n background: var(--mj-brand-primary-hover);\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.btn-primary i {\n font-size: 12px;\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n /* Header Responsiveness */\n .agent-header {\n padding: 16px;\n }\n\n .agent-header-content {\n flex-direction: column;\n gap: 16px;\n }\n\n .agent-overview {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n\n .agent-meta {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .agent-actions {\n width: 100%;\n align-self: stretch;\n }\n\n .action-button {\n flex: 1;\n justify-content: center;\n }\n\n /* Panel Responsiveness */\n .form-content {\n padding: 12px;\n }\n\n ::ng-deep .k-panelbar > .k-panelbar-item > .k-header {\n padding: 16px 20px;\n font-size: 15px;\n }\n\n .panel-content {\n padding: 20px 16px;\n }\n\n .section-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n\n .header-actions {\n flex-wrap: wrap;\n align-self: stretch;\n }\n\n /* Entity List Responsiveness */\n .entity-item {\n padding: 12px;\n gap: 12px;\n }\n\n .item-icon {\n width: 36px;\n height: 36px;\n }\n\n .item-icon i {\n font-size: 16px;\n }\n\n .item-title {\n font-size: 15px;\n }\n\n .item-preview {\n font-size: 13px;\n }\n\n .item-meta {\n gap: 8px;\n }\n\n /* Timeline Responsiveness */\n .timeline-item {\n padding: 12px;\n gap: 12px;\n }\n\n .timeline-marker {\n width: 28px;\n height: 28px;\n }\n\n .timeline-marker i {\n font-size: 12px;\n }\n\n .timeline-title {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .timeline-date {\n align-self: flex-start;\n }\n\n /* Form Field Responsiveness */\n .form-fields-grid {\n grid-template-columns: 1fr;\n gap: 16px;\n }\n\n /* Legacy card support */\n .cards-container {\n grid-template-columns: 1fr;\n }\n}\n\n/* Execution History Panel - Max Height and Scroll */\n.execution-history-panel {\n max-height: 500px;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n/* Custom scrollbar for execution history */\n.execution-history-panel::-webkit-scrollbar {\n width: 8px;\n}\n\n.execution-history-panel::-webkit-scrollbar-track {\n background: var(--mj-bg-surface-sunken);\n border-radius: 4px;\n}\n\n.execution-history-panel::-webkit-scrollbar-thumb {\n background: var(--mj-border-strong);\n border-radius: 4px;\n}\n\n.execution-history-panel::-webkit-scrollbar-thumb:hover {\n background: var(--mj-text-disabled);\n}\n\n/* Execution History Search Bar */\n.execution-search-bar {\n margin-bottom: 16px;\n padding: 0 4px;\n}\n\n.execution-search-bar .fa-search {\n color: var(--mj-text-secondary);\n margin-right: 8px;\n font-size: 14px;\n}\n\n/* New Execution History Card Design */\n.execution-history-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 8px;\n}\n\n.execution-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n transition: all 0.2s ease;\n cursor: pointer;\n}\n\n.execution-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 10%, transparent);\n transform: translateY(-1px);\n}\n\n.execution-card.expanded {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 6px 20px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.execution-header {\n padding: 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n\n.execution-left-section {\n display: flex;\n flex-direction: column;\n gap: 12px;\n flex: 1;\n min-width: 0;\n}\n\n.execution-status {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-shrink: 0;\n}\n\n.status-indicator {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.status-indicator i {\n color: var(--mj-text-inverse);\n font-size: 14px;\n}\n\n.execution-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.execution-title {\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.execution-date {\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.execution-metrics {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n flex-wrap: wrap;\n margin-left: 44px; /* Align with execution title text, accounting for status indicator + gap */\n}\n\n.metric-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n background: var(--mj-bg-surface-card);\n padding: 6px 10px;\n border-radius: 6px;\n color: var(--mj-text-secondary);\n white-space: nowrap;\n}\n\n.metric-item i {\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.metric-label {\n font-weight: 500;\n}\n\n.metric-value {\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.execution-actions {\n display: flex;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.action-btn {\n width: 32px;\n height: 32px;\n border: none;\n background: var(--mj-bg-surface-card);\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n}\n\n.action-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n transform: translateY(-1px);\n}\n\n.action-btn i {\n font-size: 12px;\n}\n\n.expand-icon {\n transition: transform 0.2s ease;\n color: var(--mj-text-muted);\n margin-right: 4px;\n}\n\n.expand-icon.expanded {\n transform: rotate(90deg);\n}\n\n/* Execution Expanded Content */\n.execution-expanded-content {\n padding: 16px;\n border-top: 1px solid var(--mj-bg-surface-sunken);\n background: var(--mj-bg-surface-card);\n animation: slideDown 0.2s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n }\n to {\n opacity: 1;\n max-height: 500px;\n padding-top: 16px;\n padding-bottom: 16px;\n }\n}\n\n.detailed-metrics {\n margin-bottom: 20px;\n}\n\n.metrics-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n}\n\n.metric-detail {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n\n.metric-detail i {\n color: var(--mj-brand-primary);\n font-size: 16px;\n width: 20px;\n text-align: center;\n}\n\n.metric-info {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex: 1;\n}\n\n.metric-title {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-data {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.result-section {\n margin-top: 16px;\n}\n\n.result-section h5 {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin-bottom: 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-section h5 {\n color: var(--mj-status-error);\n}\n\n.error-content {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 20%, var(--mj-bg-surface));\n border-radius: 8px;\n padding: 12px 16px;\n font-size: 14px;\n line-height: 1.6;\n color: var(--mj-status-error);\n white-space: pre-wrap;\n word-break: break-word;\n max-height: 150px;\n overflow-y: auto;\n}\n\n/* Responsive adjustments for execution history */\n@media (max-width: 768px) {\n .execution-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 12px;\n }\n\n .execution-left-section {\n width: 100%;\n }\n\n .execution-metrics {\n margin-left: 0; /* Remove left margin on mobile */\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n width: 100%;\n }\n\n .metric-item {\n font-size: 11px;\n padding: 4px 8px;\n }\n\n .metrics-grid {\n grid-template-columns: 1fr;\n }\n}\n\n/* === PAYLOAD MANAGEMENT SECTION === */\n.payload-section {\n margin-bottom: 2rem;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n.payload-section-title {\n margin: 0;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n font-size: 1.1rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.payload-section-title i {\n color: var(--mj-brand-primary);\n font-size: 1.2rem;\n}\n\n/* Payload Scope Styling */\n.payload-field-container {\n padding: 1.5rem;\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 2rem;\n align-items: start;\n}\n\n.payload-field-info {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.payload-field-label {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 0.95rem;\n}\n\n.payload-field-description {\n color: var(--mj-text-muted);\n font-size: 0.9rem;\n line-height: 1.5;\n margin: 0;\n}\n\n.payload-field-input {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.payload-field-example {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.85rem;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n padding: 0.5rem 0.75rem;\n border-radius: 6px;\n border: 1px solid var(--mj-bg-surface-sunken);\n}\n\n.payload-field-example i {\n color: var(--mj-status-warning);\n font-size: 0.9rem;\n}\n\n.payload-field-example code {\n background: var(--mj-bg-surface-sunken);\n padding: 0.2rem 0.4rem;\n border-radius: 4px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n}\n\n/* Path Configuration Grid */\n.payload-paths-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n}\n\n.payload-path-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.payload-path-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.payload-path-header {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.payload-path-icon {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.payload-path-icon.downstream {\n background: var(--mj-status-success);\n}\n\n.payload-path-icon.upstream {\n background: var(--mj-brand-primary);\n}\n\n.payload-path-icon.self-read {\n background: var(--mj-brand-primary);\n}\n\n.payload-path-icon.self-write {\n background: var(--mj-status-warning);\n}\n\n.payload-path-icon i {\n color: var(--mj-text-inverse);\n font-size: 1.2rem;\n}\n\n.payload-path-info h4 {\n margin: 0 0 0.25rem 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.payload-path-info p {\n margin: 0;\n font-size: 0.85rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.payload-path-content {\n padding: 1rem;\n}\n\n.json-editor-container {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n margin-bottom: 0.75rem;\n}\n\n.json-editor-container:hover {\n border-color: var(--mj-brand-primary);\n}\n\n.payload-path-hint {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.payload-path-hint i {\n color: var(--mj-brand-primary);\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n.payload-path-hint code {\n background: var(--mj-bg-surface-sunken);\n padding: 0.1rem 0.3rem;\n border-radius: 3px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n/* Payload Validation Container */\n.payload-validation-container {\n padding: 1.5rem;\n display: grid;\n grid-template-columns: 1fr 2fr;\n gap: 2rem;\n align-items: start;\n}\n\n.payload-validation-settings {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.validation-field-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.validation-field-label {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 0.95rem;\n}\n\n.validation-field-description {\n color: var(--mj-text-muted);\n font-size: 0.9rem;\n line-height: 1.4;\n margin: 0 0 0.5rem 0;\n}\n\n.payload-validation-schema {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n}\n\n.validation-schema-label {\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-size: 0.95rem;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.validation-schema-label i {\n color: var(--mj-brand-primary);\n}\n\n.validation-schema-description {\n color: var(--mj-text-muted);\n font-size: 0.9rem;\n line-height: 1.4;\n margin: 0;\n}\n\n.validation-schema-editor {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.validation-schema-editor:hover {\n border-color: var(--mj-brand-primary);\n}\n\n/* === CONFIGURATION SECTION === */\n.config-section {\n margin-bottom: 2rem;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n}\n\n.config-section-title {\n margin: 0;\n padding: 1rem 1.5rem;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n color: var(--mj-text-secondary);\n font-size: 1.1rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.config-section-title i {\n color: var(--mj-brand-primary);\n font-size: 1.2rem;\n}\n\n.config-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));\n gap: 1.5rem;\n padding: 1.5rem;\n width: 100%;\n}\n\n.config-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.config-card:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.config-card.full-width {\n grid-column: 1 / -1;\n}\n\n.config-card-header {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.config-card-icon {\n width: 40px;\n height: 40px;\n border-radius: 8px;\n background: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.config-card-icon i {\n color: var(--mj-text-inverse);\n font-size: 1.2rem;\n}\n\n.config-card-info h4 {\n margin: 0 0 0.25rem 0;\n font-size: 1rem;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.config-card-info p {\n margin: 0;\n font-size: 0.85rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n}\n\n.config-card-content {\n padding: 1rem;\n}\n\n/* Custom field styling for config cards */\n.config-field-input {\n width: 100%;\n min-width: 250px;\n}\n\n.config-card-content ::ng-deep mj-form-field {\n width: 100% !important;\n}\n\n.config-field-display {\n color: var(--mj-text-secondary);\n font-size: 14px;\n font-weight: 500;\n padding: 8px 0;\n display: block;\n min-height: 20px;\n}\n\n/* Prompt selector styling */\n.prompt-selector-container {\n display: flex;\n align-items: center;\n gap: 12px;\n width: 100%;\n}\n\n.prompt-display {\n flex: 1;\n min-width: 0;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n}\n\n.prompt-name {\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 14px;\n}\n\n.no-prompt {\n color: var(--mj-text-muted);\n font-style: italic;\n font-size: 14px;\n}\n\n.prompt-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n\n.prompt-select-btn {\n white-space: nowrap;\n}\n\n.prompt-clear-btn {\n min-width: 32px;\n}\n\n.config-card-hint {\n display: flex;\n align-items: flex-start;\n gap: 0.5rem;\n font-size: 0.8rem;\n color: var(--mj-text-muted);\n line-height: 1.4;\n margin-top: 0.5rem;\n}\n\n.config-card-hint i {\n color: var(--mj-brand-primary);\n margin-top: 0.1rem;\n flex-shrink: 0;\n}\n\n.config-card-hint code {\n background: var(--mj-bg-surface-sunken);\n padding: 0.1rem 0.3rem;\n border-radius: 3px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n\n/* === RESPONSIVE DESIGN === */\n@media (max-width: 768px) {\n .payload-field-container,\n .payload-validation-container {\n grid-template-columns: 1fr;\n gap: 1rem;\n }\n\n .payload-paths-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n\n .config-grid {\n grid-template-columns: 1fr;\n gap: 1rem;\n padding: 1rem;\n }\n\n .payload-section-title,\n .config-section-title {\n padding: 0.75rem 1rem;\n font-size: 1rem;\n }\n\n .payload-path-header,\n .config-card-header {\n padding: 0.75rem;\n }\n\n .payload-path-content,\n .config-card-content {\n padding: 0.75rem;\n }\n\n .payload-field-container,\n .payload-validation-container {\n padding: 1rem;\n }\n}\n\n/* ===================================\n Unified Sub-Agents with Filtering\n =================================== */\n\n/* Filter Controls */\n.sub-agent-filter-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n flex-wrap: wrap;\n gap: 12px;\n}\n\n.filter-controls {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n/* Sub-Agent Type Badge */\n.sub-agent-type-badge {\n position: absolute;\n top: 8px;\n right: 8px;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 10px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n display: flex;\n align-items: center;\n gap: 4px;\n z-index: 1;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n/* Sub-Agent Item Styling */\n.sub-agent-item {\n position: relative;\n padding-left: 8px;\n transition: all 0.2s ease;\n}\n\n.sub-agent-item.child-sub-agent {\n border-left: 4px solid var(--mj-brand-primary);\n}\n\n.sub-agent-item.related-sub-agent {\n border-left: 4px solid var(--mj-brand-primary);\n}\n\n.sub-agent-item:hover {\n transform: translateX(4px);\n}\n\n/* Payload Info Tag */\n.payload-info {\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-secondary);\n font-family: 'Roboto Mono', monospace;\n font-size: 11px;\n}\n\n/* Empty State Info Cards */\n.empty-state-info {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n margin: 24px 0;\n max-width: 600px;\n margin-left: auto;\n margin-right: auto;\n}\n\n.info-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 16px;\n text-align: left;\n}\n\n.info-card i {\n font-size: 24px;\n margin-bottom: 8px;\n display: block;\n}\n\n.info-card strong {\n display: block;\n margin-bottom: 4px;\n font-size: 14px;\n}\n\n.info-card p {\n margin: 0;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n/* Responsive adjustments for sub-agent filters */\n@media (max-width: 768px) {\n .sub-agent-filter-header {\n flex-direction: column;\n align-items: stretch;\n }\n\n .filter-controls,\n .header-actions {\n width: 100%;\n justify-content: center;\n }\n\n .empty-state-info {\n grid-template-columns: 1fr;\n }\n}\n\n/* ===== Search Scope Access (mockup #5) ===== */\n.agent-search-access {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n margin: 8px 0 20px;\n}\n\n.agent-search-access-option {\n display: grid;\n grid-template-columns: 24px 28px 1fr;\n align-items: start;\n gap: 10px;\n padding: 14px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.agent-search-access-option:hover {\n background: var(--mj-bg-surface-hover);\n border-color: var(--mj-border-strong);\n}\n\n.agent-search-access-option.active {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n}\n\n.agent-search-access-option input[type=\"radio\"] {\n accent-color: var(--mj-brand-primary);\n margin-top: 2px;\n}\n\n.agent-search-access-option > i {\n font-size: 20px;\n color: var(--mj-brand-primary);\n text-align: center;\n margin-top: 2px;\n}\n\n.agent-search-access-text {\n min-width: 0;\n}\n\n.agent-search-access-title {\n font-weight: 600;\n color: var(--mj-text-primary);\n font-size: 0.9rem;\n}\n\n.agent-search-access-desc {\n font-size: 0.8rem;\n color: var(--mj-text-secondary);\n margin-top: 2px;\n line-height: 1.3;\n}\n\n.agent-search-grid-header {\n margin: 8px 0 12px;\n}\n\n.agent-search-grid-header h4 {\n margin: 0 0 4px;\n color: var(--mj-text-primary);\n font-size: 1rem;\n font-weight: 600;\n}\n\n@media (max-width: 768px) {\n .agent-search-access {\n grid-template-columns: 1fr;\n }\n}\n\n/* \u2500\u2500 Execution History: Runs | Sessions segmented toggle \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.history-view-toggle {\n display: inline-flex;\n gap: 2px;\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 3px;\n margin-bottom: 14px;\n}\n\n.history-toggle-option {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n padding: 6px 16px;\n border: none;\n border-radius: 8px;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.history-toggle-option:hover {\n color: var(--mj-text-secondary);\n}\n\n.history-toggle-option.active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.history-toggle-count {\n font-size: 11px;\n font-weight: 600;\n padding: 1px 7px;\n border-radius: 10px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n color: var(--mj-text-secondary);\n}\n\n.history-toggle-option.active .history-toggle-count {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500 Voice session rows in Execution History \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n.session-card {\n cursor: pointer;\n}\n\n.session-role-chip {\n display: inline-flex;\n align-items: center;\n margin-left: 8px;\n padding: 1px 8px;\n border-radius: 10px;\n font-size: 10.5px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 22%, transparent);\n color: var(--mj-brand-primary);\n}\n\n.session-role-chip--target {\n background: color-mix(in srgb, var(--mj-status-info) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-info) 22%, transparent);\n color: var(--mj-status-info);\n}\n\n.session-status-pill {\n display: inline-flex;\n align-items: center;\n padding: 2px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-border-default);\n}\n\n.session-status-pill[data-status=\"Active\"] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n border-color: color-mix(in srgb, var(--mj-status-success) 25%, transparent);\n}\n\n.session-status-pill[data-status=\"Idle\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n border-color: color-mix(in srgb, var(--mj-status-warning) 25%, transparent);\n}\n\n/* \u2500\u2500 Form tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Panes are hidden with `display: none`, never removed from the DOM. The\n designer pane holds UNSAVED canvas edits; @if-ing it away on a tab switch\n would discard them silently, and would also throw away the canvas's zoom and\n node positions on every trip to Details. */\n\n.agent-tabbar {\n flex: 0 0 auto;\n padding: 8px 12px 0;\n background: var(--mj-bg-page);\n}\n\n.agent-pane {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n.agent-pane--hidden {\n display: none;\n}\n\n.agent-pane--designer {\n overflow: hidden;\n padding: 8px 12px 12px;\n background: var(--mj-bg-page);\n}\n\n/* The designer's dynamically-created section has no height of its own, so without\n this the flow canvas collapses to zero and renders as an empty strip. */\n.agent-pane--designer > ng-component,\n.agent-pane--designer > * {\n flex: 1;\n min-height: 0;\n}\n\n.agent-pane--invocations {\n overflow-y: auto;\n overflow-x: hidden;\n background: var(--mj-bg-page);\n}\n\n/* Initial load: the form's header renders as soon as the record arrives, but the tab strip and\n every pane wait on the agent TYPE. This fills that window so the page reads as loading rather\n than as broken. */\n.agent-form-loading {\n flex: 1;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 240px;\n padding: 32px;\n background: var(--mj-bg-page);\n}\n"] }]
|
|
5247
|
-
}], null, {
|
|
5779
|
+
}], null, { CustomSectionContainer: [{
|
|
5248
5780
|
type: ViewChild,
|
|
5249
5781
|
args: ['customSectionContainer', { read: ViewContainerRef }]
|
|
5250
5782
|
}] }); })();
|