@memberjunction/ng-core-entity-forms 6.2.0-edge.0 → 6.2.0-edge.2
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-form-tabs.d.ts +1 -0
- package/dist/lib/custom/AIAgents/agent-form-tabs.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/agent-form-tabs.js +2 -0
- package/dist/lib/custom/AIAgents/agent-form-tabs.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 +1322 -783
- 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 +694 -252
- 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/pending-records.d.ts +11 -0
- package/dist/lib/custom/AIPrompts/pending-records.d.ts.map +1 -0
- package/dist/lib/custom/AIPrompts/pending-records.js +21 -0
- package/dist/lib/custom/AIPrompts/pending-records.js.map +1 -0
- 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 +217 -29
- package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Entities/entity-form.component.js +734 -285
- 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 +129 -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 +904 -90
- package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
- package/dist/lib/custom/Rubrics/evaluation-form.component.d.ts +37 -0
- package/dist/lib/custom/Rubrics/evaluation-form.component.d.ts.map +1 -0
- package/dist/lib/custom/Rubrics/evaluation-form.component.js +399 -0
- package/dist/lib/custom/Rubrics/evaluation-form.component.js.map +1 -0
- package/dist/lib/custom/Rubrics/record-forms.component.d.ts +69 -0
- package/dist/lib/custom/Rubrics/record-forms.component.d.ts.map +1 -0
- package/dist/lib/custom/Rubrics/record-forms.component.js +587 -0
- package/dist/lib/custom/Rubrics/record-forms.component.js.map +1 -0
- package/dist/lib/custom/Rubrics/rubric-form.component.d.ts +67 -0
- package/dist/lib/custom/Rubrics/rubric-form.component.d.ts.map +1 -0
- package/dist/lib/custom/Rubrics/rubric-form.component.js +534 -0
- package/dist/lib/custom/Rubrics/rubric-form.component.js.map +1 -0
- package/dist/lib/custom/Rubrics/rubric-form.panels.d.ts +25 -0
- package/dist/lib/custom/Rubrics/rubric-form.panels.d.ts.map +1 -0
- package/dist/lib/custom/Rubrics/rubric-form.panels.js +299 -0
- package/dist/lib/custom/Rubrics/rubric-form.panels.js.map +1 -0
- package/dist/lib/custom/Rubrics/scale-form.component.d.ts +31 -0
- package/dist/lib/custom/Rubrics/scale-form.component.d.ts.map +1 -0
- package/dist/lib/custom/Rubrics/scale-form.component.js +395 -0
- package/dist/lib/custom/Rubrics/scale-form.component.js.map +1 -0
- 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 +153 -19
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +434 -217
- 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 +223 -27
- package/dist/lib/custom/Tests/test-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +951 -530
- 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 +395 -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 +1719 -1007
- 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 +3 -3
- 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/custom-forms.module.d.ts +56 -48
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +60 -0
- package/dist/lib/custom/custom-forms.module.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/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +61 -43
- package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRubric/mjaiagentrubric.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJAIAgentRubric/mjaiagentrubric.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentRubric/mjaiagentrubric.form.component.js +74 -0
- package/dist/lib/generated/Entities/MJAIAgentRubric/mjaiagentrubric.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +37 -19
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.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 +78 -52
- 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/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +156 -84
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJFeaturePipelineType/mjfeaturepipelinetype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineType/mjfeaturepipelinetype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineType/mjfeaturepipelinetype.form.component.js +62 -0
- package/dist/lib/generated/Entities/MJFeaturePipelineType/mjfeaturepipelinetype.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.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/MJRecordChange/mjrecordchange.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRecordChange/mjrecordchange.form.component.js +24 -16
- package/dist/lib/generated/Entities/MJRecordChange/mjrecordchange.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRecordCloneLog/mjrecordclonelog.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRecordCloneLog/mjrecordclonelog.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRecordCloneLog/mjrecordclonelog.form.component.js +107 -0
- package/dist/lib/generated/Entities/MJRecordCloneLog/mjrecordclonelog.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRecordCloneLogItem/mjrecordclonelogitem.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRecordCloneLogItem/mjrecordclonelogitem.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRecordCloneLogItem/mjrecordclonelogitem.form.component.js +74 -0
- package/dist/lib/generated/Entities/MJRecordCloneLogItem/mjrecordclonelogitem.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubric/mjrubric.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubric/mjrubric.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubric/mjrubric.form.component.js +135 -0
- package/dist/lib/generated/Entities/MJRubric/mjrubric.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricBand/mjrubricband.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricBand/mjrubricband.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricBand/mjrubricband.form.component.js +87 -0
- package/dist/lib/generated/Entities/MJRubricBand/mjrubricband.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCategory/mjrubriccategory.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricCategory/mjrubriccategory.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCategory/mjrubriccategory.form.component.js +107 -0
- package/dist/lib/generated/Entities/MJRubricCategory/mjrubriccategory.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCriterion/mjrubriccriterion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricCriterion/mjrubriccriterion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCriterion/mjrubriccriterion.form.component.js +155 -0
- package/dist/lib/generated/Entities/MJRubricCriterion/mjrubriccriterion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCriterionLevel/mjrubriccriterionlevel.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricCriterionLevel/mjrubriccriterionlevel.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricCriterionLevel/mjrubriccriterionlevel.form.component.js +62 -0
- package/dist/lib/generated/Entities/MJRubricCriterionLevel/mjrubriccriterionlevel.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricEvaluation/mjrubricevaluation.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricEvaluation/mjrubricevaluation.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricEvaluation/mjrubricevaluation.form.component.js +183 -0
- package/dist/lib/generated/Entities/MJRubricEvaluation/mjrubricevaluation.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricEvaluationScore/mjrubricevaluationscore.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricEvaluationScore/mjrubricevaluationscore.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricEvaluationScore/mjrubricevaluationscore.form.component.js +120 -0
- package/dist/lib/generated/Entities/MJRubricEvaluationScore/mjrubricevaluationscore.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricScale/mjrubricscale.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricScale/mjrubricscale.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricScale/mjrubricscale.form.component.js +107 -0
- package/dist/lib/generated/Entities/MJRubricScale/mjrubricscale.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricScaleLevel/mjrubricscalelevel.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricScaleLevel/mjrubricscalelevel.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricScaleLevel/mjrubricscalelevel.form.component.js +103 -0
- package/dist/lib/generated/Entities/MJRubricScaleLevel/mjrubricscalelevel.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJRubricVersion/mjrubricversion.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJRubricVersion/mjrubricversion.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJRubricVersion/mjrubricversion.form.component.js +171 -0
- package/dist/lib/generated/Entities/MJRubricVersion/mjrubricversion.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js +24 -16
- package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTestSuite/mjtestsuite.form.component.js +27 -25
- package/dist/lib/generated/Entities/MJTestSuite/mjtestsuite.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTestSuiteRun/mjtestsuiterun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTestSuiteRun/mjtestsuiterun.form.component.js +19 -11
- package/dist/lib/generated/Entities/MJTestSuiteRun/mjtestsuiterun.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 +209 -119
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +436 -422
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +44 -2
- package/dist/lib/generated/generated-forms.module.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/panels/record-clone/entity-clone-config-editor.component.d.ts +116 -0
- package/dist/lib/panels/record-clone/entity-clone-config-editor.component.d.ts.map +1 -0
- package/dist/lib/panels/record-clone/entity-clone-config-editor.component.js +820 -0
- package/dist/lib/panels/record-clone/entity-clone-config-editor.component.js.map +1 -0
- package/dist/lib/shared/components/template-editor.component.d.ts +158 -15
- package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +389 -127
- package/dist/lib/shared/components/template-editor.component.js.map +1 -1
- package/dist/public-api.d.ts +5 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +5 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +47 -42
|
@@ -14,6 +14,7 @@ import { MJAIPromptFormComponent } from '../../generated/Entities/MJAIPrompt/mja
|
|
|
14
14
|
import { AIEngineBase } from '@memberjunction/ai-engine-base';
|
|
15
15
|
import { AITestHarnessDialogService } from '@memberjunction/ng-ai-test-harness';
|
|
16
16
|
import { AIPromptManagementService } from './ai-prompt-management.service';
|
|
17
|
+
import { DedupePendingRecordsByEntity } from './pending-records';
|
|
17
18
|
import * as i0 from "@angular/core";
|
|
18
19
|
import * as i1 from "@angular/forms";
|
|
19
20
|
import * as i2 from "@memberjunction/ng-ui-components";
|
|
@@ -1540,48 +1541,244 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1540
1541
|
this.testHarnessService = inject(AITestHarnessDialogService);
|
|
1541
1542
|
this.viewContainerRef = inject(ViewContainerRef);
|
|
1542
1543
|
this.promptManagementService = inject(AIPromptManagementService);
|
|
1543
|
-
this.
|
|
1544
|
-
this.
|
|
1545
|
-
this.
|
|
1546
|
-
this.
|
|
1547
|
-
this.
|
|
1548
|
-
this.
|
|
1549
|
-
this.
|
|
1550
|
-
this.
|
|
1544
|
+
this.ToolbarConfig = CUSTOM_LAYOUT_TOOLBAR_CONFIG;
|
|
1545
|
+
this.Template = null;
|
|
1546
|
+
this.TemplateContent = null;
|
|
1547
|
+
this.TemplateParams = [];
|
|
1548
|
+
this.IsLoadingTemplate = true;
|
|
1549
|
+
this.IsLoadingTemplateParams = false;
|
|
1550
|
+
this.TemplateNotFoundInDatabase = false;
|
|
1551
|
+
this.ShowTestHarness = false;
|
|
1551
1552
|
// Model management
|
|
1552
|
-
this.
|
|
1553
|
-
this.
|
|
1554
|
-
this.
|
|
1555
|
-
this.
|
|
1553
|
+
this.PromptModels = [];
|
|
1554
|
+
this.AvailableModels = [];
|
|
1555
|
+
this.AvailableVendors = [];
|
|
1556
|
+
this.IsLoadingModels = false;
|
|
1556
1557
|
// Vendor management per model
|
|
1557
|
-
this.
|
|
1558
|
+
this.ModelVendorsMap = new Map();
|
|
1558
1559
|
// AI Prompt Types
|
|
1559
|
-
this.
|
|
1560
|
-
this.
|
|
1560
|
+
this.AvailablePromptTypes = [];
|
|
1561
|
+
this.IsLoadingPromptTypes = false;
|
|
1561
1562
|
// AI Configurations
|
|
1562
|
-
this.
|
|
1563
|
-
this.
|
|
1563
|
+
this.AvailableConfigurations = [];
|
|
1564
|
+
this.IsLoadingConfigurations = false;
|
|
1564
1565
|
// Result Selector Tree Data
|
|
1565
|
-
this.
|
|
1566
|
-
this.
|
|
1566
|
+
this.ResultSelectorTreeData = [];
|
|
1567
|
+
this.IsLoadingResultSelectorData = false;
|
|
1567
1568
|
// Drag and drop state
|
|
1568
|
-
this.
|
|
1569
|
+
this.DraggedIndex = -1;
|
|
1569
1570
|
// Execution History
|
|
1570
|
-
this.
|
|
1571
|
-
this.
|
|
1572
|
-
this.
|
|
1573
|
-
this.
|
|
1571
|
+
this.ExecutionHistory = [];
|
|
1572
|
+
this.IsLoadingHistory = false;
|
|
1573
|
+
this.HistorySortField = 'runAt';
|
|
1574
|
+
this.HistorySortDirection = 'desc';
|
|
1574
1575
|
// Removed custom transaction tracking - we'll use base form's _pendingRecords instead
|
|
1575
|
-
this.
|
|
1576
|
+
this.HasUnsavedChanges = false;
|
|
1576
1577
|
// Store original state for cancel/revert functionality
|
|
1577
1578
|
this.originalTemplateID = null;
|
|
1578
1579
|
// === Permission Checks for Related Entities ===
|
|
1579
1580
|
/** Cache for permission checks to avoid repeated calculations */
|
|
1580
1581
|
this._permissionCache = new Map();
|
|
1581
|
-
this.
|
|
1582
|
+
this.__inferenceProvider_VendorTypeDefinitionID = '';
|
|
1583
|
+
}
|
|
1584
|
+
/** @deprecated Use {@link ToolbarConfig}. */
|
|
1585
|
+
get toolbarConfig() {
|
|
1586
|
+
return this.ToolbarConfig;
|
|
1582
1587
|
}
|
|
1583
1588
|
/** Custom-layout AI Prompt form looks best full-width on first open. */
|
|
1584
1589
|
getDefaultFormWidthMode() { return 'full-width'; }
|
|
1590
|
+
/** @deprecated Use {@link Template}. */
|
|
1591
|
+
get template() {
|
|
1592
|
+
return this.Template;
|
|
1593
|
+
}
|
|
1594
|
+
/** @deprecated Use {@link Template}. */
|
|
1595
|
+
set template(value) {
|
|
1596
|
+
this.Template = value;
|
|
1597
|
+
}
|
|
1598
|
+
/** @deprecated Use {@link TemplateContent}. */
|
|
1599
|
+
get templateContent() {
|
|
1600
|
+
return this.TemplateContent;
|
|
1601
|
+
}
|
|
1602
|
+
/** @deprecated Use {@link TemplateContent}. */
|
|
1603
|
+
set templateContent(value) {
|
|
1604
|
+
this.TemplateContent = value;
|
|
1605
|
+
}
|
|
1606
|
+
/** @deprecated Use {@link TemplateParams}. */
|
|
1607
|
+
get templateParams() {
|
|
1608
|
+
return this.TemplateParams;
|
|
1609
|
+
}
|
|
1610
|
+
/** @deprecated Use {@link TemplateParams}. */
|
|
1611
|
+
set templateParams(value) {
|
|
1612
|
+
this.TemplateParams = value;
|
|
1613
|
+
}
|
|
1614
|
+
/** @deprecated Use {@link IsLoadingTemplate}. */
|
|
1615
|
+
get isLoadingTemplate() {
|
|
1616
|
+
return this.IsLoadingTemplate;
|
|
1617
|
+
}
|
|
1618
|
+
/** @deprecated Use {@link IsLoadingTemplate}. */
|
|
1619
|
+
set isLoadingTemplate(value) {
|
|
1620
|
+
this.IsLoadingTemplate = value;
|
|
1621
|
+
} // Default to loading state
|
|
1622
|
+
/** @deprecated Use {@link IsLoadingTemplateParams}. */
|
|
1623
|
+
get isLoadingTemplateParams() {
|
|
1624
|
+
return this.IsLoadingTemplateParams;
|
|
1625
|
+
}
|
|
1626
|
+
/** @deprecated Use {@link IsLoadingTemplateParams}. */
|
|
1627
|
+
set isLoadingTemplateParams(value) {
|
|
1628
|
+
this.IsLoadingTemplateParams = value;
|
|
1629
|
+
}
|
|
1630
|
+
/** @deprecated Use {@link TemplateNotFoundInDatabase}. */
|
|
1631
|
+
get templateNotFoundInDatabase() {
|
|
1632
|
+
return this.TemplateNotFoundInDatabase;
|
|
1633
|
+
}
|
|
1634
|
+
/** @deprecated Use {@link TemplateNotFoundInDatabase}. */
|
|
1635
|
+
set templateNotFoundInDatabase(value) {
|
|
1636
|
+
this.TemplateNotFoundInDatabase = value;
|
|
1637
|
+
}
|
|
1638
|
+
/** @deprecated Use {@link ShowTestHarness}. */
|
|
1639
|
+
get showTestHarness() {
|
|
1640
|
+
return this.ShowTestHarness;
|
|
1641
|
+
}
|
|
1642
|
+
/** @deprecated Use {@link ShowTestHarness}. */
|
|
1643
|
+
set showTestHarness(value) {
|
|
1644
|
+
this.ShowTestHarness = value;
|
|
1645
|
+
}
|
|
1646
|
+
/** @deprecated Use {@link PromptModels}. */
|
|
1647
|
+
get promptModels() {
|
|
1648
|
+
return this.PromptModels;
|
|
1649
|
+
}
|
|
1650
|
+
/** @deprecated Use {@link PromptModels}. */
|
|
1651
|
+
set promptModels(value) {
|
|
1652
|
+
this.PromptModels = value;
|
|
1653
|
+
}
|
|
1654
|
+
/** @deprecated Use {@link AvailableModels}. */
|
|
1655
|
+
get availableModels() {
|
|
1656
|
+
return this.AvailableModels;
|
|
1657
|
+
}
|
|
1658
|
+
/** @deprecated Use {@link AvailableModels}. */
|
|
1659
|
+
set availableModels(value) {
|
|
1660
|
+
this.AvailableModels = value;
|
|
1661
|
+
}
|
|
1662
|
+
/** @deprecated Use {@link AvailableVendors}. */
|
|
1663
|
+
get availableVendors() {
|
|
1664
|
+
return this.AvailableVendors;
|
|
1665
|
+
}
|
|
1666
|
+
/** @deprecated Use {@link AvailableVendors}. */
|
|
1667
|
+
set availableVendors(value) {
|
|
1668
|
+
this.AvailableVendors = value;
|
|
1669
|
+
}
|
|
1670
|
+
/** @deprecated Use {@link IsLoadingModels}. */
|
|
1671
|
+
get isLoadingModels() {
|
|
1672
|
+
return this.IsLoadingModels;
|
|
1673
|
+
}
|
|
1674
|
+
/** @deprecated Use {@link IsLoadingModels}. */
|
|
1675
|
+
set isLoadingModels(value) {
|
|
1676
|
+
this.IsLoadingModels = value;
|
|
1677
|
+
}
|
|
1678
|
+
/** @deprecated Use {@link ModelVendorsMap}. */
|
|
1679
|
+
get modelVendorsMap() {
|
|
1680
|
+
return this.ModelVendorsMap;
|
|
1681
|
+
}
|
|
1682
|
+
/** @deprecated Use {@link ModelVendorsMap}. */
|
|
1683
|
+
set modelVendorsMap(value) {
|
|
1684
|
+
this.ModelVendorsMap = value;
|
|
1685
|
+
}
|
|
1686
|
+
/** @deprecated Use {@link AvailablePromptTypes}. */
|
|
1687
|
+
get availablePromptTypes() {
|
|
1688
|
+
return this.AvailablePromptTypes;
|
|
1689
|
+
}
|
|
1690
|
+
/** @deprecated Use {@link AvailablePromptTypes}. */
|
|
1691
|
+
set availablePromptTypes(value) {
|
|
1692
|
+
this.AvailablePromptTypes = value;
|
|
1693
|
+
}
|
|
1694
|
+
/** @deprecated Use {@link IsLoadingPromptTypes}. */
|
|
1695
|
+
get isLoadingPromptTypes() {
|
|
1696
|
+
return this.IsLoadingPromptTypes;
|
|
1697
|
+
}
|
|
1698
|
+
/** @deprecated Use {@link IsLoadingPromptTypes}. */
|
|
1699
|
+
set isLoadingPromptTypes(value) {
|
|
1700
|
+
this.IsLoadingPromptTypes = value;
|
|
1701
|
+
}
|
|
1702
|
+
/** @deprecated Use {@link AvailableConfigurations}. */
|
|
1703
|
+
get availableConfigurations() {
|
|
1704
|
+
return this.AvailableConfigurations;
|
|
1705
|
+
}
|
|
1706
|
+
/** @deprecated Use {@link AvailableConfigurations}. */
|
|
1707
|
+
set availableConfigurations(value) {
|
|
1708
|
+
this.AvailableConfigurations = value;
|
|
1709
|
+
}
|
|
1710
|
+
/** @deprecated Use {@link IsLoadingConfigurations}. */
|
|
1711
|
+
get isLoadingConfigurations() {
|
|
1712
|
+
return this.IsLoadingConfigurations;
|
|
1713
|
+
}
|
|
1714
|
+
/** @deprecated Use {@link IsLoadingConfigurations}. */
|
|
1715
|
+
set isLoadingConfigurations(value) {
|
|
1716
|
+
this.IsLoadingConfigurations = value;
|
|
1717
|
+
}
|
|
1718
|
+
/** @deprecated Use {@link ResultSelectorTreeData}. */
|
|
1719
|
+
get resultSelectorTreeData() {
|
|
1720
|
+
return this.ResultSelectorTreeData;
|
|
1721
|
+
}
|
|
1722
|
+
/** @deprecated Use {@link ResultSelectorTreeData}. */
|
|
1723
|
+
set resultSelectorTreeData(value) {
|
|
1724
|
+
this.ResultSelectorTreeData = value;
|
|
1725
|
+
}
|
|
1726
|
+
/** @deprecated Use {@link IsLoadingResultSelectorData}. */
|
|
1727
|
+
get isLoadingResultSelectorData() {
|
|
1728
|
+
return this.IsLoadingResultSelectorData;
|
|
1729
|
+
}
|
|
1730
|
+
/** @deprecated Use {@link IsLoadingResultSelectorData}. */
|
|
1731
|
+
set isLoadingResultSelectorData(value) {
|
|
1732
|
+
this.IsLoadingResultSelectorData = value;
|
|
1733
|
+
}
|
|
1734
|
+
/** @deprecated Use {@link DraggedIndex}. */
|
|
1735
|
+
get draggedIndex() {
|
|
1736
|
+
return this.DraggedIndex;
|
|
1737
|
+
}
|
|
1738
|
+
/** @deprecated Use {@link DraggedIndex}. */
|
|
1739
|
+
set draggedIndex(value) {
|
|
1740
|
+
this.DraggedIndex = value;
|
|
1741
|
+
}
|
|
1742
|
+
/** @deprecated Use {@link ExecutionHistory}. */
|
|
1743
|
+
get executionHistory() {
|
|
1744
|
+
return this.ExecutionHistory;
|
|
1745
|
+
}
|
|
1746
|
+
/** @deprecated Use {@link ExecutionHistory}. */
|
|
1747
|
+
set executionHistory(value) {
|
|
1748
|
+
this.ExecutionHistory = value;
|
|
1749
|
+
}
|
|
1750
|
+
/** @deprecated Use {@link IsLoadingHistory}. */
|
|
1751
|
+
get isLoadingHistory() {
|
|
1752
|
+
return this.IsLoadingHistory;
|
|
1753
|
+
}
|
|
1754
|
+
/** @deprecated Use {@link IsLoadingHistory}. */
|
|
1755
|
+
set isLoadingHistory(value) {
|
|
1756
|
+
this.IsLoadingHistory = value;
|
|
1757
|
+
}
|
|
1758
|
+
/** @deprecated Use {@link HistorySortField}. */
|
|
1759
|
+
get historySortField() {
|
|
1760
|
+
return this.HistorySortField;
|
|
1761
|
+
}
|
|
1762
|
+
/** @deprecated Use {@link HistorySortField}. */
|
|
1763
|
+
set historySortField(value) {
|
|
1764
|
+
this.HistorySortField = value;
|
|
1765
|
+
}
|
|
1766
|
+
/** @deprecated Use {@link HistorySortDirection}. */
|
|
1767
|
+
get historySortDirection() {
|
|
1768
|
+
return this.HistorySortDirection;
|
|
1769
|
+
}
|
|
1770
|
+
/** @deprecated Use {@link HistorySortDirection}. */
|
|
1771
|
+
set historySortDirection(value) {
|
|
1772
|
+
this.HistorySortDirection = value;
|
|
1773
|
+
}
|
|
1774
|
+
/** @deprecated Use {@link HasUnsavedChanges}. */
|
|
1775
|
+
get hasUnsavedChanges() {
|
|
1776
|
+
return this.HasUnsavedChanges;
|
|
1777
|
+
}
|
|
1778
|
+
/** @deprecated Use {@link HasUnsavedChanges}. */
|
|
1779
|
+
set hasUnsavedChanges(value) {
|
|
1780
|
+
this.HasUnsavedChanges = value;
|
|
1781
|
+
}
|
|
1585
1782
|
// Main AI Prompt permissions inherited from BaseFormComponent:
|
|
1586
1783
|
// - UserCanEdit (Update permission)
|
|
1587
1784
|
// - UserCanRead (Read permission)
|
|
@@ -1669,25 +1866,41 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1669
1866
|
/**
|
|
1670
1867
|
* Clears the permission cache. Call this when user context changes or permissions are updated.
|
|
1671
1868
|
*/
|
|
1672
|
-
|
|
1869
|
+
ClearPermissionCache() {
|
|
1673
1870
|
this._permissionCache.clear();
|
|
1674
1871
|
}
|
|
1872
|
+
/** @deprecated Use {@link ClearPermissionCache}. */
|
|
1873
|
+
clearPermissionCache() {
|
|
1874
|
+
return this.ClearPermissionCache();
|
|
1875
|
+
}
|
|
1675
1876
|
// Template editor configuration
|
|
1676
|
-
get
|
|
1877
|
+
get TemplateEditorConfig() {
|
|
1677
1878
|
return {
|
|
1678
1879
|
allowEdit: this.EditMode && this.UserCanUpdateTemplateContents,
|
|
1679
1880
|
showRunButton: false,
|
|
1680
1881
|
compactMode: false
|
|
1681
1882
|
};
|
|
1682
1883
|
}
|
|
1884
|
+
/** @deprecated Use {@link TemplateEditorConfig}. */
|
|
1885
|
+
get templateEditorConfig() {
|
|
1886
|
+
return this.TemplateEditorConfig;
|
|
1887
|
+
}
|
|
1683
1888
|
get _metadata() { return this.ProviderToUse; }
|
|
1889
|
+
/** @deprecated Use {@link TemplateEditor}. */
|
|
1890
|
+
get templateEditor() {
|
|
1891
|
+
return this.TemplateEditor;
|
|
1892
|
+
}
|
|
1893
|
+
/** @deprecated Use {@link TemplateEditor}. */
|
|
1894
|
+
set templateEditor(value) {
|
|
1895
|
+
this.TemplateEditor = value;
|
|
1896
|
+
}
|
|
1684
1897
|
async ngOnInit() {
|
|
1685
1898
|
await super.ngOnInit();
|
|
1686
1899
|
// make sure AI Engine Base is configured, this will load stuff only if not already
|
|
1687
1900
|
// loaded in the current process space
|
|
1688
1901
|
await AIEngineBase.Instance.Config(false, this._metadata.CurrentUser);
|
|
1689
|
-
this.
|
|
1690
|
-
if (!this.
|
|
1902
|
+
this.__inferenceProvider_VendorTypeDefinitionID = AIEngineBase.Instance.InferenceProviderTypeID || '';
|
|
1903
|
+
if (!this.__inferenceProvider_VendorTypeDefinitionID) {
|
|
1691
1904
|
console.error('Inference Provider Vendor Type Definition ID not found');
|
|
1692
1905
|
MJNotificationService.Instance.CreateSimpleNotification('Inference Provider Vendor Type Definition not found', 'error', 5000);
|
|
1693
1906
|
return;
|
|
@@ -1699,26 +1912,26 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1699
1912
|
}
|
|
1700
1913
|
else {
|
|
1701
1914
|
// No template ID, so we're not loading
|
|
1702
|
-
this.
|
|
1915
|
+
this.IsLoadingTemplate = false;
|
|
1703
1916
|
}
|
|
1704
1917
|
// Load available models, vendors, prompt types, configurations, prompt models, and result selector data
|
|
1705
1918
|
await Promise.all([
|
|
1706
|
-
this.
|
|
1707
|
-
this.
|
|
1708
|
-
this.
|
|
1709
|
-
this.
|
|
1710
|
-
this.
|
|
1711
|
-
this.
|
|
1919
|
+
this.LoadAvailableModels(),
|
|
1920
|
+
this.LoadAvailableVendors(),
|
|
1921
|
+
this.LoadAvailablePromptTypes(),
|
|
1922
|
+
this.LoadAvailableConfigurations(),
|
|
1923
|
+
this.LoadPromptModels(),
|
|
1924
|
+
this.LoadResultSelectorTreeData()
|
|
1712
1925
|
]);
|
|
1713
1926
|
// Load execution history if record is saved
|
|
1714
1927
|
if (this.record?.IsSaved) {
|
|
1715
|
-
await this.
|
|
1928
|
+
await this.LoadExecutionHistory();
|
|
1716
1929
|
}
|
|
1717
1930
|
// Set defaults for new records
|
|
1718
1931
|
if (!this.record.IsSaved) {
|
|
1719
1932
|
// Default to first prompt type if not set
|
|
1720
|
-
if (!this.record.TypeID && this.
|
|
1721
|
-
this.record.TypeID = this.
|
|
1933
|
+
if (!this.record.TypeID && this.AvailablePromptTypes.length > 0) {
|
|
1934
|
+
this.record.TypeID = this.AvailablePromptTypes[0].ID;
|
|
1722
1935
|
}
|
|
1723
1936
|
// Default status to Pending if not set
|
|
1724
1937
|
if (!this.record.Status) {
|
|
@@ -1731,8 +1944,8 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1731
1944
|
*/
|
|
1732
1945
|
async loadTemplate() {
|
|
1733
1946
|
if (!this.record?.TemplateID) {
|
|
1734
|
-
this.
|
|
1735
|
-
this.
|
|
1947
|
+
this.Template = null;
|
|
1948
|
+
this.TemplateNotFoundInDatabase = false;
|
|
1736
1949
|
return;
|
|
1737
1950
|
}
|
|
1738
1951
|
// First check if we already have this template in pending records (newly created)
|
|
@@ -1740,23 +1953,23 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1740
1953
|
p.entityObject.Get('ID') === this.record.TemplateID);
|
|
1741
1954
|
if (pendingTemplate) {
|
|
1742
1955
|
// Use the pending template
|
|
1743
|
-
this.
|
|
1744
|
-
this.
|
|
1745
|
-
this.
|
|
1956
|
+
this.Template = pendingTemplate.entityObject;
|
|
1957
|
+
this.TemplateNotFoundInDatabase = false;
|
|
1958
|
+
this.IsLoadingTemplate = false;
|
|
1746
1959
|
// Clear template content and params since this is a new template
|
|
1747
|
-
this.
|
|
1748
|
-
this.
|
|
1960
|
+
this.TemplateContent = null;
|
|
1961
|
+
this.TemplateParams = [];
|
|
1749
1962
|
this.cdr.detectChanges();
|
|
1750
1963
|
return;
|
|
1751
1964
|
}
|
|
1752
|
-
this.
|
|
1753
|
-
this.
|
|
1965
|
+
this.IsLoadingTemplate = true;
|
|
1966
|
+
this.TemplateNotFoundInDatabase = false; // Reset the flag
|
|
1754
1967
|
try {
|
|
1755
|
-
this.
|
|
1756
|
-
await this.
|
|
1757
|
-
if (!this.
|
|
1758
|
-
this.
|
|
1759
|
-
this.
|
|
1968
|
+
this.Template = await this._metadata.GetEntityObject('MJ: Templates');
|
|
1969
|
+
await this.Template.Load(this.record.TemplateID);
|
|
1970
|
+
if (!this.Template.IsSaved) {
|
|
1971
|
+
this.Template = null;
|
|
1972
|
+
this.TemplateNotFoundInDatabase = true; // Set flag when template not found
|
|
1760
1973
|
console.warn(`Template with ID ${this.record.TemplateID} not found`);
|
|
1761
1974
|
}
|
|
1762
1975
|
else {
|
|
@@ -1769,49 +1982,53 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1769
1982
|
}
|
|
1770
1983
|
catch (error) {
|
|
1771
1984
|
console.error('Error loading template:', error);
|
|
1772
|
-
this.
|
|
1773
|
-
this.
|
|
1985
|
+
this.Template = null;
|
|
1986
|
+
this.TemplateNotFoundInDatabase = true; // Set flag on error
|
|
1774
1987
|
MJNotificationService.Instance.CreateSimpleNotification('Error loading associated template', 'error', 5000);
|
|
1775
1988
|
}
|
|
1776
1989
|
finally {
|
|
1777
|
-
this.
|
|
1990
|
+
this.IsLoadingTemplate = false;
|
|
1778
1991
|
this.cdr.detectChanges();
|
|
1779
1992
|
}
|
|
1780
1993
|
}
|
|
1781
1994
|
/**
|
|
1782
1995
|
* Handles template ID changes in the form
|
|
1783
1996
|
*/
|
|
1784
|
-
async
|
|
1997
|
+
async OnTemplateIdChange() {
|
|
1785
1998
|
if (this.record?.TemplateID) {
|
|
1786
1999
|
await this.loadTemplate();
|
|
1787
2000
|
}
|
|
1788
2001
|
else {
|
|
1789
|
-
this.
|
|
1790
|
-
this.
|
|
2002
|
+
this.Template = null;
|
|
2003
|
+
this.TemplateParams = [];
|
|
1791
2004
|
}
|
|
1792
|
-
this.
|
|
2005
|
+
this.HasUnsavedChanges = true;
|
|
2006
|
+
}
|
|
2007
|
+
/** @deprecated Use {@link OnTemplateIdChange}. */
|
|
2008
|
+
async onTemplateIdChange() {
|
|
2009
|
+
return this.OnTemplateIdChange();
|
|
1793
2010
|
}
|
|
1794
2011
|
/**
|
|
1795
2012
|
* Opens a dialog to link an existing template
|
|
1796
2013
|
*/
|
|
1797
|
-
async
|
|
2014
|
+
async LinkExistingTemplate() {
|
|
1798
2015
|
try {
|
|
1799
2016
|
this.promptManagementService.openTemplateSelectorDialog({
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
2017
|
+
Title: 'Link Existing Template',
|
|
2018
|
+
MultiSelect: false,
|
|
2019
|
+
ShowCreateNew: true,
|
|
2020
|
+
ShowActiveOnly: true,
|
|
2021
|
+
SelectedTemplateIds: this.record.TemplateID ? [this.record.TemplateID] : [],
|
|
1805
2022
|
viewContainerRef: this.viewContainerRef
|
|
1806
2023
|
}).subscribe({
|
|
1807
2024
|
next: async (result) => {
|
|
1808
|
-
if (result && result.
|
|
1809
|
-
const selectedTemplate = result.
|
|
2025
|
+
if (result && result.SelectedTemplates.length > 0) {
|
|
2026
|
+
const selectedTemplate = result.SelectedTemplates[0];
|
|
1810
2027
|
// First, clean up any pending changes related to the old template
|
|
1811
2028
|
this.cleanupOldTemplateRecords();
|
|
1812
2029
|
// Update the AI prompt to reference the selected template
|
|
1813
2030
|
this.record.TemplateID = selectedTemplate.ID;
|
|
1814
|
-
this.
|
|
2031
|
+
this.HasUnsavedChanges = true;
|
|
1815
2032
|
// Load the selected template
|
|
1816
2033
|
await this.loadTemplate();
|
|
1817
2034
|
// Trigger change detection to update UI
|
|
@@ -1820,7 +2037,7 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1820
2037
|
}
|
|
1821
2038
|
else if (result && result.createNew) {
|
|
1822
2039
|
// User wants to create a new template
|
|
1823
|
-
await this.
|
|
2040
|
+
await this.CreateNewTemplate();
|
|
1824
2041
|
}
|
|
1825
2042
|
},
|
|
1826
2043
|
error: (error) => {
|
|
@@ -1834,20 +2051,28 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1834
2051
|
MJNotificationService.Instance.CreateSimpleNotification('Error linking template. Please try again.', 'error', 3000);
|
|
1835
2052
|
}
|
|
1836
2053
|
}
|
|
2054
|
+
/** @deprecated Use {@link LinkExistingTemplate}. */
|
|
2055
|
+
async linkExistingTemplate() {
|
|
2056
|
+
return this.LinkExistingTemplate();
|
|
2057
|
+
}
|
|
1837
2058
|
/**
|
|
1838
2059
|
* Opens the current template in a new window
|
|
1839
2060
|
*/
|
|
1840
|
-
|
|
1841
|
-
if (!this.
|
|
2061
|
+
OpenTemplateInNewWindow() {
|
|
2062
|
+
if (!this.Template?.ID)
|
|
1842
2063
|
return;
|
|
1843
2064
|
// TODO: Get the proper URL for template editing
|
|
1844
|
-
const templateUrl = `/templates/${this.
|
|
2065
|
+
const templateUrl = `/templates/${this.Template.ID}`;
|
|
1845
2066
|
window.open(templateUrl, '_blank');
|
|
1846
2067
|
}
|
|
2068
|
+
/** @deprecated Use {@link OpenTemplateInNewWindow}. */
|
|
2069
|
+
openTemplateInNewWindow() {
|
|
2070
|
+
return this.OpenTemplateInNewWindow();
|
|
2071
|
+
}
|
|
1847
2072
|
/**
|
|
1848
2073
|
* Creates a new template for this AI prompt (deferred until save)
|
|
1849
2074
|
*/
|
|
1850
|
-
async
|
|
2075
|
+
async CreateNewTemplate() {
|
|
1851
2076
|
try {
|
|
1852
2077
|
// First, clean up any pending changes related to the old template
|
|
1853
2078
|
this.cleanupOldTemplateRecords();
|
|
@@ -1864,14 +2089,14 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1864
2089
|
});
|
|
1865
2090
|
// Update the AI prompt to reference the new template
|
|
1866
2091
|
this.record.TemplateID = newTemplate.ID;
|
|
1867
|
-
this.
|
|
2092
|
+
this.HasUnsavedChanges = true;
|
|
1868
2093
|
// Set the template for UI purposes
|
|
1869
|
-
this.
|
|
2094
|
+
this.Template = newTemplate;
|
|
1870
2095
|
// Clear existing template content and params since we have a new template
|
|
1871
|
-
this.
|
|
1872
|
-
this.
|
|
1873
|
-
this.
|
|
1874
|
-
this.
|
|
2096
|
+
this.TemplateContent = null;
|
|
2097
|
+
this.TemplateParams = [];
|
|
2098
|
+
this.IsLoadingTemplate = false;
|
|
2099
|
+
this.TemplateNotFoundInDatabase = false;
|
|
1875
2100
|
// Force UI update in next microtask to ensure template editor refreshes
|
|
1876
2101
|
Promise.resolve().then(() => {
|
|
1877
2102
|
this.cdr.detectChanges();
|
|
@@ -1884,6 +2109,10 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1884
2109
|
MJNotificationService.Instance.CreateSimpleNotification(`Error creating new template: ${errorMessage}`, 'error', 6000);
|
|
1885
2110
|
}
|
|
1886
2111
|
}
|
|
2112
|
+
/** @deprecated Use {@link CreateNewTemplate}. */
|
|
2113
|
+
async createNewTemplate() {
|
|
2114
|
+
return this.CreateNewTemplate();
|
|
2115
|
+
}
|
|
1887
2116
|
/**
|
|
1888
2117
|
* Cleans up any pending records related to the old template when changing templates
|
|
1889
2118
|
*/
|
|
@@ -1903,56 +2132,56 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1903
2132
|
* Loads template content for the current template
|
|
1904
2133
|
*/
|
|
1905
2134
|
async loadTemplateContent() {
|
|
1906
|
-
if (!this.
|
|
1907
|
-
this.
|
|
2135
|
+
if (!this.Template?.ID) {
|
|
2136
|
+
this.TemplateContent = null;
|
|
1908
2137
|
return;
|
|
1909
2138
|
}
|
|
1910
2139
|
try {
|
|
1911
2140
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1912
2141
|
const results = await rv.RunView({
|
|
1913
2142
|
EntityName: 'MJ: Template Contents',
|
|
1914
|
-
ExtraFilter: `TemplateID = '${this.
|
|
2143
|
+
ExtraFilter: `TemplateID = '${this.Template.ID}'`,
|
|
1915
2144
|
OrderBy: 'Priority ASC',
|
|
1916
2145
|
ResultType: 'entity_object'
|
|
1917
2146
|
});
|
|
1918
2147
|
// Get the first content (highest priority)
|
|
1919
|
-
this.
|
|
2148
|
+
this.TemplateContent = results.Results?.[0] || null;
|
|
1920
2149
|
}
|
|
1921
2150
|
catch (error) {
|
|
1922
2151
|
console.error('Error loading template content:', error);
|
|
1923
|
-
this.
|
|
2152
|
+
this.TemplateContent = null;
|
|
1924
2153
|
}
|
|
1925
2154
|
}
|
|
1926
2155
|
/**
|
|
1927
2156
|
* Loads template parameters for the current template
|
|
1928
2157
|
*/
|
|
1929
2158
|
async loadTemplateParams() {
|
|
1930
|
-
if (!this.
|
|
1931
|
-
this.
|
|
2159
|
+
if (!this.Template?.ID) {
|
|
2160
|
+
this.TemplateParams = [];
|
|
1932
2161
|
return;
|
|
1933
2162
|
}
|
|
1934
|
-
this.
|
|
2163
|
+
this.IsLoadingTemplateParams = true;
|
|
1935
2164
|
try {
|
|
1936
2165
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1937
2166
|
const results = await rv.RunView({
|
|
1938
2167
|
EntityName: 'MJ: Template Params',
|
|
1939
|
-
ExtraFilter: `TemplateID = '${this.
|
|
2168
|
+
ExtraFilter: `TemplateID = '${this.Template.ID}'`,
|
|
1940
2169
|
OrderBy: 'Name ASC'
|
|
1941
2170
|
});
|
|
1942
|
-
this.
|
|
2171
|
+
this.TemplateParams = results.Results || [];
|
|
1943
2172
|
}
|
|
1944
2173
|
catch (error) {
|
|
1945
2174
|
console.error('Error loading template params:', error);
|
|
1946
|
-
this.
|
|
2175
|
+
this.TemplateParams = [];
|
|
1947
2176
|
}
|
|
1948
2177
|
finally {
|
|
1949
|
-
this.
|
|
2178
|
+
this.IsLoadingTemplateParams = false;
|
|
1950
2179
|
}
|
|
1951
2180
|
}
|
|
1952
2181
|
/**
|
|
1953
2182
|
* Opens the AI prompt execution dialog
|
|
1954
2183
|
*/
|
|
1955
|
-
|
|
2184
|
+
ExecuteAIPrompt() {
|
|
1956
2185
|
if (!this.record?.ID) {
|
|
1957
2186
|
MJNotificationService.Instance.CreateSimpleNotification('Please save the AI prompt before executing', 'warning', 4000);
|
|
1958
2187
|
return;
|
|
@@ -1962,12 +2191,16 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1962
2191
|
return;
|
|
1963
2192
|
}
|
|
1964
2193
|
// Use test harness instead
|
|
1965
|
-
this.
|
|
2194
|
+
this.OpenTestHarness();
|
|
2195
|
+
}
|
|
2196
|
+
/** @deprecated Use {@link ExecuteAIPrompt}. */
|
|
2197
|
+
executeAIPrompt() {
|
|
2198
|
+
return this.ExecuteAIPrompt();
|
|
1966
2199
|
}
|
|
1967
2200
|
/**
|
|
1968
2201
|
* Opens the test harness
|
|
1969
2202
|
*/
|
|
1970
|
-
|
|
2203
|
+
OpenTestHarness() {
|
|
1971
2204
|
if (!this.record?.ID) {
|
|
1972
2205
|
MJNotificationService.Instance.CreateSimpleNotification('Please save the AI prompt before testing', 'warning', 4000);
|
|
1973
2206
|
return;
|
|
@@ -1978,7 +2211,7 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1978
2211
|
next: (result) => {
|
|
1979
2212
|
if (result.success) {
|
|
1980
2213
|
// Reload execution history
|
|
1981
|
-
this.
|
|
2214
|
+
this.LoadExecutionHistory();
|
|
1982
2215
|
}
|
|
1983
2216
|
},
|
|
1984
2217
|
error: (error) => {
|
|
@@ -1987,28 +2220,40 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
1987
2220
|
}
|
|
1988
2221
|
});
|
|
1989
2222
|
}
|
|
2223
|
+
/** @deprecated Use {@link OpenTestHarness}. */
|
|
2224
|
+
openTestHarness() {
|
|
2225
|
+
return this.OpenTestHarness();
|
|
2226
|
+
}
|
|
1990
2227
|
/**
|
|
1991
2228
|
* Handles when test harness is closed
|
|
1992
2229
|
*/
|
|
2230
|
+
OnTestHarnessVisibilityChanged(isVisible) {
|
|
2231
|
+
this.ShowTestHarness = isVisible;
|
|
2232
|
+
}
|
|
2233
|
+
/** @deprecated Use {@link OnTestHarnessVisibilityChanged}. */
|
|
1993
2234
|
onTestHarnessVisibilityChanged(isVisible) {
|
|
1994
|
-
this.
|
|
2235
|
+
return this.OnTestHarnessVisibilityChanged(isVisible);
|
|
1995
2236
|
}
|
|
1996
2237
|
/**
|
|
1997
2238
|
* Handles template content changes from the editor
|
|
1998
2239
|
*/
|
|
1999
|
-
|
|
2240
|
+
OnTemplateContentChange(content) {
|
|
2000
2241
|
// Handle template content changes if needed
|
|
2001
2242
|
console.log('Template content changed:', content);
|
|
2002
2243
|
// Mark as having unsaved changes
|
|
2003
|
-
this.
|
|
2244
|
+
this.HasUnsavedChanges = true;
|
|
2004
2245
|
// If we have content changes, we need to ensure they're added to pending records
|
|
2005
2246
|
// This is typically handled by the template editor component itself
|
|
2006
2247
|
}
|
|
2248
|
+
/** @deprecated Use {@link OnTemplateContentChange}. */
|
|
2249
|
+
onTemplateContentChange(content) {
|
|
2250
|
+
return this.OnTemplateContentChange(content);
|
|
2251
|
+
}
|
|
2007
2252
|
/**
|
|
2008
2253
|
* Handles template content record deletion
|
|
2009
2254
|
* This method should be called by the template editor to properly manage deletions
|
|
2010
2255
|
*/
|
|
2011
|
-
|
|
2256
|
+
HandleTemplateContentDelete(templateContent) {
|
|
2012
2257
|
if (templateContent.IsSaved) {
|
|
2013
2258
|
// If it's saved, add to pending deletions
|
|
2014
2259
|
this.PendingRecords.push({
|
|
@@ -2029,13 +2274,17 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2029
2274
|
}
|
|
2030
2275
|
}
|
|
2031
2276
|
}
|
|
2032
|
-
this.
|
|
2277
|
+
this.HasUnsavedChanges = true;
|
|
2278
|
+
}
|
|
2279
|
+
/** @deprecated Use {@link HandleTemplateContentDelete}. */
|
|
2280
|
+
handleTemplateContentDelete(templateContent) {
|
|
2281
|
+
return this.HandleTemplateContentDelete(templateContent);
|
|
2033
2282
|
}
|
|
2034
2283
|
/**
|
|
2035
2284
|
* Handles template content record creation/modification
|
|
2036
2285
|
* This method should be called by the template editor to properly manage saves
|
|
2037
2286
|
*/
|
|
2038
|
-
|
|
2287
|
+
HandleTemplateContentSave(templateContent) {
|
|
2039
2288
|
if (templateContent.Dirty || !templateContent.IsSaved) {
|
|
2040
2289
|
// Add to pending saves
|
|
2041
2290
|
this.PendingRecords.push({
|
|
@@ -2043,41 +2292,37 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2043
2292
|
action: 'save'
|
|
2044
2293
|
});
|
|
2045
2294
|
}
|
|
2046
|
-
this.
|
|
2295
|
+
this.HasUnsavedChanges = true;
|
|
2296
|
+
}
|
|
2297
|
+
/** @deprecated Use {@link HandleTemplateContentSave}. */
|
|
2298
|
+
handleTemplateContentSave(templateContent) {
|
|
2299
|
+
return this.HandleTemplateContentSave(templateContent);
|
|
2047
2300
|
}
|
|
2048
2301
|
/**
|
|
2049
2302
|
* Adds template content changes to pending records
|
|
2050
2303
|
*/
|
|
2051
2304
|
addTemplateContentsToPendingRecords() {
|
|
2052
|
-
//
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
// and communicate them through the MJ event system
|
|
2056
|
-
// If the template editor has a method to get pending changes, we would call it here
|
|
2057
|
-
if (this.templateEditor && typeof this.templateEditor.getPendingChanges === 'function') {
|
|
2058
|
-
try {
|
|
2059
|
-
const pendingChanges = this.templateEditor.getPendingChanges();
|
|
2060
|
-
if (pendingChanges && pendingChanges.length > 0) {
|
|
2061
|
-
this.PendingRecords.push(...pendingChanges);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
catch (error) {
|
|
2065
|
-
console.warn('Template editor does not support getPendingChanges method:', error);
|
|
2066
|
-
}
|
|
2305
|
+
// The embedded editor's new/dirty Template Contents ride along in this form's save transaction.
|
|
2306
|
+
if (this.TemplateEditor) {
|
|
2307
|
+
this.PendingRecords.push(...this.TemplateEditor.GetPendingChanges());
|
|
2067
2308
|
}
|
|
2068
2309
|
}
|
|
2069
2310
|
/**
|
|
2070
2311
|
* Handles template run requests from the editor
|
|
2071
2312
|
*/
|
|
2072
|
-
|
|
2313
|
+
OnTemplateRun(template) {
|
|
2073
2314
|
console.log('Template run requested:', template);
|
|
2074
2315
|
// Could open the template parameter dialog here if needed
|
|
2075
2316
|
MJNotificationService.Instance.CreateSimpleNotification('Template run functionality coming soon', 'info', 3000);
|
|
2076
2317
|
}
|
|
2318
|
+
/** @deprecated Use {@link OnTemplateRun}. */
|
|
2319
|
+
onTemplateRun(template) {
|
|
2320
|
+
return this.OnTemplateRun(template);
|
|
2321
|
+
}
|
|
2077
2322
|
/**
|
|
2078
2323
|
* Gets the display text for parallelization mode
|
|
2079
2324
|
*/
|
|
2080
|
-
|
|
2325
|
+
GetParallelizationModeDisplay() {
|
|
2081
2326
|
switch (this.record?.ParallelizationMode) {
|
|
2082
2327
|
case 'None': return 'None';
|
|
2083
2328
|
case 'StaticCount': return `Static count (${this.record.ParallelCount || 1})`;
|
|
@@ -2086,10 +2331,14 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2086
2331
|
default: return 'Unknown';
|
|
2087
2332
|
}
|
|
2088
2333
|
}
|
|
2334
|
+
/** @deprecated Use {@link GetParallelizationModeDisplay}. */
|
|
2335
|
+
getParallelizationModeDisplay() {
|
|
2336
|
+
return this.GetParallelizationModeDisplay();
|
|
2337
|
+
}
|
|
2089
2338
|
/**
|
|
2090
2339
|
* Gets the display text for output type
|
|
2091
2340
|
*/
|
|
2092
|
-
|
|
2341
|
+
GetOutputTypeDisplay() {
|
|
2093
2342
|
const type = this.record?.OutputType || 'string';
|
|
2094
2343
|
const validationBehavior = this.record?.ValidationBehavior || 'Warn';
|
|
2095
2344
|
if (validationBehavior === 'None') {
|
|
@@ -2099,47 +2348,71 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2099
2348
|
return `${type} (${validationBehavior})`;
|
|
2100
2349
|
}
|
|
2101
2350
|
}
|
|
2351
|
+
/** @deprecated Use {@link GetOutputTypeDisplay}. */
|
|
2352
|
+
getOutputTypeDisplay() {
|
|
2353
|
+
return this.GetOutputTypeDisplay();
|
|
2354
|
+
}
|
|
2102
2355
|
/**
|
|
2103
2356
|
* Gets the color for validation behavior display
|
|
2104
2357
|
*/
|
|
2105
|
-
|
|
2358
|
+
GetValidationColor() {
|
|
2106
2359
|
switch (this.record?.ValidationBehavior) {
|
|
2107
2360
|
case 'Strict': return '#dc3545'; // red
|
|
2108
2361
|
case 'Warn': return '#ffc107'; // yellow
|
|
2109
2362
|
default: return '#6c757d'; // default gray
|
|
2110
2363
|
}
|
|
2111
2364
|
}
|
|
2365
|
+
/** @deprecated Use {@link GetValidationColor}. */
|
|
2366
|
+
getValidationColor() {
|
|
2367
|
+
return this.GetValidationColor();
|
|
2368
|
+
}
|
|
2112
2369
|
/**
|
|
2113
2370
|
* Checks if ParallelCount field should be visible
|
|
2114
2371
|
*/
|
|
2115
|
-
get
|
|
2372
|
+
get ShowParallelCount() {
|
|
2116
2373
|
return this.record?.ParallelizationMode === 'StaticCount';
|
|
2117
2374
|
}
|
|
2375
|
+
/** @deprecated Use {@link ShowParallelCount}. */
|
|
2376
|
+
get showParallelCount() {
|
|
2377
|
+
return this.ShowParallelCount;
|
|
2378
|
+
}
|
|
2118
2379
|
/**
|
|
2119
2380
|
* Checks if ParallelConfigParam field should be visible
|
|
2120
2381
|
*/
|
|
2121
|
-
get
|
|
2382
|
+
get ShowParallelConfigParam() {
|
|
2122
2383
|
return this.record?.ParallelizationMode === 'ConfigParam';
|
|
2123
2384
|
}
|
|
2385
|
+
/** @deprecated Use {@link ShowParallelConfigParam}. */
|
|
2386
|
+
get showParallelConfigParam() {
|
|
2387
|
+
return this.ShowParallelConfigParam;
|
|
2388
|
+
}
|
|
2124
2389
|
/**
|
|
2125
2390
|
* Checks if OutputExample field should be visible
|
|
2126
2391
|
*/
|
|
2127
|
-
get
|
|
2392
|
+
get ShowOutputExample() {
|
|
2128
2393
|
return this.record?.OutputType === 'object';
|
|
2129
2394
|
}
|
|
2395
|
+
/** @deprecated Use {@link ShowOutputExample}. */
|
|
2396
|
+
get showOutputExample() {
|
|
2397
|
+
return this.ShowOutputExample;
|
|
2398
|
+
}
|
|
2130
2399
|
/**
|
|
2131
2400
|
* Checks if the AI prompt can be executed
|
|
2132
2401
|
*/
|
|
2133
|
-
get
|
|
2402
|
+
get CanExecute() {
|
|
2134
2403
|
return !!(this.record?.ID &&
|
|
2135
2404
|
this.record.Status === 'Active' &&
|
|
2136
2405
|
this.record.TemplateID &&
|
|
2137
|
-
this.
|
|
2406
|
+
this.Template);
|
|
2407
|
+
}
|
|
2408
|
+
/** @deprecated Use {@link CanExecute}. */
|
|
2409
|
+
get canExecute() {
|
|
2410
|
+
return this.CanExecute;
|
|
2138
2411
|
}
|
|
2139
2412
|
/**
|
|
2140
2413
|
* Gets status badge color
|
|
2141
2414
|
*/
|
|
2142
|
-
|
|
2415
|
+
GetStatusBadgeColor() {
|
|
2143
2416
|
switch (this.record?.Status) {
|
|
2144
2417
|
case 'Active': return '#28a745';
|
|
2145
2418
|
case 'Pending': return '#ffc107';
|
|
@@ -2147,84 +2420,104 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2147
2420
|
default: return '#6c757d';
|
|
2148
2421
|
}
|
|
2149
2422
|
}
|
|
2423
|
+
/** @deprecated Use {@link GetStatusBadgeColor}. */
|
|
2424
|
+
getStatusBadgeColor() {
|
|
2425
|
+
return this.GetStatusBadgeColor();
|
|
2426
|
+
}
|
|
2150
2427
|
/**
|
|
2151
2428
|
* Loads available AI models for selection
|
|
2152
2429
|
*/
|
|
2153
|
-
async
|
|
2430
|
+
async LoadAvailableModels() {
|
|
2154
2431
|
try {
|
|
2155
2432
|
const engine = AIEngineBase.Instance;
|
|
2156
2433
|
await engine.Config(false);
|
|
2157
2434
|
const models = engine.Models;
|
|
2158
2435
|
models.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2159
|
-
this.
|
|
2436
|
+
this.AvailableModels = models;
|
|
2160
2437
|
}
|
|
2161
2438
|
catch (error) {
|
|
2162
2439
|
console.error('Error loading available models:', error);
|
|
2163
2440
|
}
|
|
2164
2441
|
}
|
|
2442
|
+
/** @deprecated Use {@link LoadAvailableModels}. */
|
|
2443
|
+
async loadAvailableModels() {
|
|
2444
|
+
return this.LoadAvailableModels();
|
|
2445
|
+
}
|
|
2165
2446
|
/**
|
|
2166
2447
|
* Loads available AI vendors for selection
|
|
2167
2448
|
*/
|
|
2168
|
-
async
|
|
2449
|
+
async LoadAvailableVendors() {
|
|
2169
2450
|
try {
|
|
2170
2451
|
const engine = AIEngineBase.Instance;
|
|
2171
2452
|
await engine.Config(false);
|
|
2172
2453
|
const vendors = engine.Vendors;
|
|
2173
2454
|
vendors.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2174
|
-
this.
|
|
2455
|
+
this.AvailableVendors = vendors;
|
|
2175
2456
|
}
|
|
2176
2457
|
catch (error) {
|
|
2177
2458
|
console.error('Error loading available vendors:', error);
|
|
2178
2459
|
}
|
|
2179
2460
|
}
|
|
2461
|
+
/** @deprecated Use {@link LoadAvailableVendors}. */
|
|
2462
|
+
async loadAvailableVendors() {
|
|
2463
|
+
return this.LoadAvailableVendors();
|
|
2464
|
+
}
|
|
2180
2465
|
/**
|
|
2181
2466
|
* Loads available AI prompt types for selection
|
|
2182
2467
|
*/
|
|
2183
|
-
async
|
|
2184
|
-
this.
|
|
2468
|
+
async LoadAvailablePromptTypes() {
|
|
2469
|
+
this.IsLoadingPromptTypes = true;
|
|
2185
2470
|
try {
|
|
2186
2471
|
const engine = AIEngineBase.Instance;
|
|
2187
2472
|
await engine.Config(false);
|
|
2188
2473
|
const promptTypes = engine.PromptTypes;
|
|
2189
2474
|
promptTypes.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2190
|
-
this.
|
|
2475
|
+
this.AvailablePromptTypes = promptTypes;
|
|
2191
2476
|
}
|
|
2192
2477
|
catch (error) {
|
|
2193
2478
|
console.error('Error loading available prompt types:', error);
|
|
2194
2479
|
}
|
|
2195
2480
|
finally {
|
|
2196
|
-
this.
|
|
2481
|
+
this.IsLoadingPromptTypes = false;
|
|
2197
2482
|
}
|
|
2198
2483
|
}
|
|
2484
|
+
/** @deprecated Use {@link LoadAvailablePromptTypes}. */
|
|
2485
|
+
async loadAvailablePromptTypes() {
|
|
2486
|
+
return this.LoadAvailablePromptTypes();
|
|
2487
|
+
}
|
|
2199
2488
|
/**
|
|
2200
2489
|
* Loads available AI configurations for selection
|
|
2201
2490
|
*/
|
|
2202
|
-
async
|
|
2203
|
-
this.
|
|
2491
|
+
async LoadAvailableConfigurations() {
|
|
2492
|
+
this.IsLoadingConfigurations = true;
|
|
2204
2493
|
try {
|
|
2205
2494
|
const engine = AIEngineBase.Instance;
|
|
2206
2495
|
await engine.Config(false);
|
|
2207
2496
|
const configurations = engine.Configurations;
|
|
2208
2497
|
configurations.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2209
|
-
this.
|
|
2498
|
+
this.AvailableConfigurations = configurations;
|
|
2210
2499
|
}
|
|
2211
2500
|
catch (error) {
|
|
2212
2501
|
console.error('Error loading available configurations:', error);
|
|
2213
2502
|
}
|
|
2214
2503
|
finally {
|
|
2215
|
-
this.
|
|
2504
|
+
this.IsLoadingConfigurations = false;
|
|
2216
2505
|
}
|
|
2217
2506
|
}
|
|
2507
|
+
/** @deprecated Use {@link LoadAvailableConfigurations}. */
|
|
2508
|
+
async loadAvailableConfigurations() {
|
|
2509
|
+
return this.LoadAvailableConfigurations();
|
|
2510
|
+
}
|
|
2218
2511
|
/**
|
|
2219
2512
|
* Loads vendors available for a specific model
|
|
2220
2513
|
*/
|
|
2221
|
-
async
|
|
2514
|
+
async LoadVendorsForModel(modelId) {
|
|
2222
2515
|
if (!modelId) {
|
|
2223
2516
|
return { vendors: [], modelVendors: [] };
|
|
2224
2517
|
}
|
|
2225
2518
|
// Check cache first
|
|
2226
|
-
if (this.
|
|
2227
|
-
return this.
|
|
2519
|
+
if (this.ModelVendorsMap.has(modelId)) {
|
|
2520
|
+
return this.ModelVendorsMap.get(modelId);
|
|
2228
2521
|
}
|
|
2229
2522
|
try {
|
|
2230
2523
|
// Load model vendors for this model, filtering by TypeID for inference providers only
|
|
@@ -2234,7 +2527,7 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2234
2527
|
// filter vendors to just the vendors in the modelVendors array in VendorID
|
|
2235
2528
|
const vendors = engine.Vendors.filter(v => modelVendors.some(mv => UUIDsEqual(mv.VendorID, v.ID)));
|
|
2236
2529
|
const result = { vendors, modelVendors };
|
|
2237
|
-
this.
|
|
2530
|
+
this.ModelVendorsMap.set(modelId, result);
|
|
2238
2531
|
return result;
|
|
2239
2532
|
}
|
|
2240
2533
|
catch (error) {
|
|
@@ -2242,28 +2535,40 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2242
2535
|
return { vendors: [], modelVendors: [] };
|
|
2243
2536
|
}
|
|
2244
2537
|
}
|
|
2538
|
+
/** @deprecated Use {@link LoadVendorsForModel}. */
|
|
2539
|
+
async loadVendorsForModel(modelId) {
|
|
2540
|
+
return this.LoadVendorsForModel(modelId);
|
|
2541
|
+
}
|
|
2245
2542
|
/**
|
|
2246
2543
|
* Gets vendors for a specific model from cache or loads them
|
|
2247
2544
|
*/
|
|
2248
|
-
async
|
|
2249
|
-
const result = await this.
|
|
2545
|
+
async GetVendorsForModel(modelId) {
|
|
2546
|
+
const result = await this.LoadVendorsForModel(modelId);
|
|
2250
2547
|
return result.vendors;
|
|
2251
2548
|
}
|
|
2549
|
+
/** @deprecated Use {@link GetVendorsForModel}. */
|
|
2550
|
+
async getVendorsForModel(modelId) {
|
|
2551
|
+
return this.GetVendorsForModel(modelId);
|
|
2552
|
+
}
|
|
2252
2553
|
/**
|
|
2253
2554
|
* Gets the status for a model-vendor combination
|
|
2254
2555
|
*/
|
|
2255
|
-
|
|
2256
|
-
const modelVendorData = this.
|
|
2556
|
+
GetModelVendorStatus(modelId, vendorId) {
|
|
2557
|
+
const modelVendorData = this.ModelVendorsMap.get(modelId);
|
|
2257
2558
|
if (!modelVendorData)
|
|
2258
2559
|
return 'Unknown';
|
|
2259
2560
|
const modelVendor = modelVendorData.modelVendors.find(mv => UUIDsEqual(mv.VendorID, vendorId));
|
|
2260
2561
|
return modelVendor?.Status || 'Unknown';
|
|
2261
2562
|
}
|
|
2563
|
+
/** @deprecated Use {@link GetModelVendorStatus}. */
|
|
2564
|
+
getModelVendorStatus(modelId, vendorId) {
|
|
2565
|
+
return this.GetModelVendorStatus(modelId, vendorId);
|
|
2566
|
+
}
|
|
2262
2567
|
/**
|
|
2263
2568
|
* Gets the color for vendor status display
|
|
2264
2569
|
*/
|
|
2265
|
-
|
|
2266
|
-
const status = this.
|
|
2570
|
+
GetVendorStatusColor(modelId, vendorId) {
|
|
2571
|
+
const status = this.GetModelVendorStatus(modelId, vendorId);
|
|
2267
2572
|
switch (status) {
|
|
2268
2573
|
case 'Active': return '#28a745'; // green
|
|
2269
2574
|
case 'Inactive': return '#dc3545'; // red
|
|
@@ -2271,19 +2576,23 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2271
2576
|
default: return '#6c757d'; // gray
|
|
2272
2577
|
}
|
|
2273
2578
|
}
|
|
2579
|
+
/** @deprecated Use {@link GetVendorStatusColor}. */
|
|
2580
|
+
getVendorStatusColor(modelId, vendorId) {
|
|
2581
|
+
return this.GetVendorStatusColor(modelId, vendorId);
|
|
2582
|
+
}
|
|
2274
2583
|
/**
|
|
2275
2584
|
* Handles model selection change and loads vendors for that model
|
|
2276
2585
|
*/
|
|
2277
|
-
async
|
|
2278
|
-
const promptModel = this.
|
|
2586
|
+
async OnModelChange(modelId, promptModelIndex) {
|
|
2587
|
+
const promptModel = this.PromptModels[promptModelIndex];
|
|
2279
2588
|
if (!promptModel)
|
|
2280
2589
|
return;
|
|
2281
2590
|
// Clear the vendor selection when model changes
|
|
2282
2591
|
promptModel.VendorID = null;
|
|
2283
|
-
this.
|
|
2592
|
+
this.HasUnsavedChanges = true;
|
|
2284
2593
|
// Load vendors for the new model
|
|
2285
2594
|
if (modelId) {
|
|
2286
|
-
const vendorData = await this.
|
|
2595
|
+
const vendorData = await this.LoadVendorsForModel(modelId);
|
|
2287
2596
|
// Auto-select first vendor if available
|
|
2288
2597
|
if (vendorData.vendors.length > 0) {
|
|
2289
2598
|
promptModel.VendorID = vendorData.vendors[0].ID;
|
|
@@ -2292,68 +2601,88 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2292
2601
|
// Trigger change detection
|
|
2293
2602
|
this.cdr.detectChanges();
|
|
2294
2603
|
}
|
|
2604
|
+
/** @deprecated Use {@link OnModelChange}. */
|
|
2605
|
+
async onModelChange(modelId, promptModelIndex) {
|
|
2606
|
+
return this.OnModelChange(modelId, promptModelIndex);
|
|
2607
|
+
}
|
|
2295
2608
|
/**
|
|
2296
2609
|
* Handles configuration change for a prompt model
|
|
2297
2610
|
*/
|
|
2298
|
-
|
|
2299
|
-
const promptModel = this.
|
|
2611
|
+
OnConfigurationChange(configurationId, promptModelIndex) {
|
|
2612
|
+
const promptModel = this.PromptModels[promptModelIndex];
|
|
2300
2613
|
if (!promptModel)
|
|
2301
2614
|
return;
|
|
2302
2615
|
promptModel.ConfigurationID = configurationId;
|
|
2303
|
-
this.
|
|
2616
|
+
this.HasUnsavedChanges = true;
|
|
2304
2617
|
// Trigger change detection
|
|
2305
2618
|
this.cdr.detectChanges();
|
|
2306
2619
|
}
|
|
2620
|
+
/** @deprecated Use {@link OnConfigurationChange}. */
|
|
2621
|
+
onConfigurationChange(configurationId, promptModelIndex) {
|
|
2622
|
+
return this.OnConfigurationChange(configurationId, promptModelIndex);
|
|
2623
|
+
}
|
|
2307
2624
|
/**
|
|
2308
2625
|
* Gets vendors for a specific model
|
|
2309
2626
|
*/
|
|
2310
|
-
|
|
2311
|
-
const modelVendorData = this.
|
|
2627
|
+
GetVendorsForModelSync(modelId) {
|
|
2628
|
+
const modelVendorData = this.ModelVendorsMap.get(modelId);
|
|
2312
2629
|
return modelVendorData?.vendors || [];
|
|
2313
2630
|
}
|
|
2631
|
+
/** @deprecated Use {@link GetVendorsForModelSync}. */
|
|
2632
|
+
getVendorsForModelSync(modelId) {
|
|
2633
|
+
return this.GetVendorsForModelSync(modelId);
|
|
2634
|
+
}
|
|
2314
2635
|
/**
|
|
2315
2636
|
* Checks if vendor dropdown should be shown (more than one vendor)
|
|
2316
2637
|
*/
|
|
2317
|
-
|
|
2638
|
+
ShouldShowVendorDropdown(modelId) {
|
|
2318
2639
|
if (!modelId)
|
|
2319
2640
|
return false;
|
|
2320
|
-
const vendors = this.
|
|
2641
|
+
const vendors = this.GetVendorsForModelSync(modelId);
|
|
2321
2642
|
return vendors.length > 1;
|
|
2322
2643
|
}
|
|
2644
|
+
/** @deprecated Use {@link ShouldShowVendorDropdown}. */
|
|
2645
|
+
shouldShowVendorDropdown(modelId) {
|
|
2646
|
+
return this.ShouldShowVendorDropdown(modelId);
|
|
2647
|
+
}
|
|
2323
2648
|
/**
|
|
2324
2649
|
* Loads prompt models for this AI prompt
|
|
2325
2650
|
*/
|
|
2326
|
-
async
|
|
2651
|
+
async LoadPromptModels() {
|
|
2327
2652
|
if (!this.record?.ID) {
|
|
2328
|
-
this.
|
|
2653
|
+
this.PromptModels = [];
|
|
2329
2654
|
return;
|
|
2330
2655
|
}
|
|
2331
|
-
this.
|
|
2656
|
+
this.IsLoadingModels = true;
|
|
2332
2657
|
try {
|
|
2333
2658
|
const engine = AIEngineBase.Instance;
|
|
2334
2659
|
await engine.Config(false);
|
|
2335
|
-
this.
|
|
2336
|
-
this.
|
|
2660
|
+
this.PromptModels = engine.PromptModels.filter(pm => UUIDsEqual(pm.PromptID, this.record.ID));
|
|
2661
|
+
this.PromptModels.sort((a, b) => {
|
|
2337
2662
|
// first sort on priority (descending), then by created date (ascending)
|
|
2338
2663
|
return b.Priority - a.Priority || new Date(a.__mj_CreatedAt).getTime() - new Date(b.__mj_CreatedAt).getTime();
|
|
2339
2664
|
});
|
|
2340
2665
|
// Load vendors for existing models
|
|
2341
|
-
const modelIds = this.
|
|
2666
|
+
const modelIds = this.PromptModels
|
|
2342
2667
|
.map(pm => pm.ModelID)
|
|
2343
2668
|
.filter(id => id); // Filter out null/undefined
|
|
2344
|
-
await Promise.all(modelIds.map(modelId => this.
|
|
2669
|
+
await Promise.all(modelIds.map(modelId => this.LoadVendorsForModel(modelId)));
|
|
2345
2670
|
}
|
|
2346
2671
|
catch (error) {
|
|
2347
2672
|
console.error('Error loading prompt models:', error);
|
|
2348
2673
|
}
|
|
2349
2674
|
finally {
|
|
2350
|
-
this.
|
|
2675
|
+
this.IsLoadingModels = false;
|
|
2351
2676
|
}
|
|
2352
2677
|
}
|
|
2678
|
+
/** @deprecated Use {@link LoadPromptModels}. */
|
|
2679
|
+
async loadPromptModels() {
|
|
2680
|
+
return this.LoadPromptModels();
|
|
2681
|
+
}
|
|
2353
2682
|
/**
|
|
2354
2683
|
* Adds a new model to the prompt (deferred until save)
|
|
2355
2684
|
*/
|
|
2356
|
-
async
|
|
2685
|
+
async AddNewModel() {
|
|
2357
2686
|
if (!this.record?.ID)
|
|
2358
2687
|
return;
|
|
2359
2688
|
try {
|
|
@@ -2366,8 +2695,8 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2366
2695
|
newModel._tempId = `temp_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
2367
2696
|
}
|
|
2368
2697
|
// ModelID will be set by user
|
|
2369
|
-
this.
|
|
2370
|
-
this.
|
|
2698
|
+
this.PromptModels.push(newModel);
|
|
2699
|
+
this.HasUnsavedChanges = true;
|
|
2371
2700
|
// Update priorities after adding
|
|
2372
2701
|
this.updateModelPriorities();
|
|
2373
2702
|
// Trigger change detection
|
|
@@ -2379,13 +2708,17 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2379
2708
|
MJNotificationService.Instance.CreateSimpleNotification('Error creating new model', 'error', 5000);
|
|
2380
2709
|
}
|
|
2381
2710
|
}
|
|
2711
|
+
/** @deprecated Use {@link AddNewModel}. */
|
|
2712
|
+
async addNewModel() {
|
|
2713
|
+
return this.AddNewModel();
|
|
2714
|
+
}
|
|
2382
2715
|
/**
|
|
2383
2716
|
* Removes a model from the prompt (deferred until save)
|
|
2384
2717
|
*/
|
|
2385
|
-
async
|
|
2386
|
-
if (index < 0 || index >= this.
|
|
2718
|
+
async RemovePromptModel(index) {
|
|
2719
|
+
if (index < 0 || index >= this.PromptModels.length)
|
|
2387
2720
|
return;
|
|
2388
|
-
const model = this.
|
|
2721
|
+
const model = this.PromptModels[index];
|
|
2389
2722
|
try {
|
|
2390
2723
|
// If it's a saved model, add it to pending deletions
|
|
2391
2724
|
if (model.IsSaved) {
|
|
@@ -2395,8 +2728,8 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2395
2728
|
});
|
|
2396
2729
|
}
|
|
2397
2730
|
// Remove from local array
|
|
2398
|
-
this.
|
|
2399
|
-
this.
|
|
2731
|
+
this.PromptModels.splice(index, 1);
|
|
2732
|
+
this.HasUnsavedChanges = true;
|
|
2400
2733
|
// Update priorities after removal
|
|
2401
2734
|
this.updateModelPriorities();
|
|
2402
2735
|
// Trigger change detection
|
|
@@ -2408,42 +2741,62 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2408
2741
|
MJNotificationService.Instance.CreateSimpleNotification('Error removing model', 'error', 5000);
|
|
2409
2742
|
}
|
|
2410
2743
|
}
|
|
2744
|
+
/** @deprecated Use {@link RemovePromptModel}. */
|
|
2745
|
+
async removePromptModel(index) {
|
|
2746
|
+
return this.RemovePromptModel(index);
|
|
2747
|
+
}
|
|
2411
2748
|
/**
|
|
2412
2749
|
* Gets the display name for a model ID
|
|
2413
2750
|
*/
|
|
2414
|
-
|
|
2751
|
+
GetModelDisplayName(modelId) {
|
|
2415
2752
|
if (!modelId)
|
|
2416
2753
|
return '';
|
|
2417
|
-
const model = this.
|
|
2754
|
+
const model = this.AvailableModels.find(m => UUIDsEqual(m.ID, modelId));
|
|
2418
2755
|
return model ? model.Name : modelId;
|
|
2419
2756
|
}
|
|
2757
|
+
/** @deprecated Use {@link GetModelDisplayName}. */
|
|
2758
|
+
getModelDisplayName(modelId) {
|
|
2759
|
+
return this.GetModelDisplayName(modelId);
|
|
2760
|
+
}
|
|
2420
2761
|
/**
|
|
2421
2762
|
* Gets the display name for a vendor ID
|
|
2422
2763
|
*/
|
|
2423
|
-
|
|
2764
|
+
GetVendorDisplayName(vendorId) {
|
|
2424
2765
|
if (!vendorId)
|
|
2425
2766
|
return '';
|
|
2426
|
-
const vendor = this.
|
|
2767
|
+
const vendor = this.AvailableVendors.find(v => UUIDsEqual(v.ID, vendorId));
|
|
2427
2768
|
return vendor ? vendor.Name : vendorId;
|
|
2428
2769
|
}
|
|
2770
|
+
/** @deprecated Use {@link GetVendorDisplayName}. */
|
|
2771
|
+
getVendorDisplayName(vendorId) {
|
|
2772
|
+
return this.GetVendorDisplayName(vendorId);
|
|
2773
|
+
}
|
|
2429
2774
|
/**
|
|
2430
2775
|
* Gets the display name for a prompt type ID
|
|
2431
2776
|
*/
|
|
2432
|
-
|
|
2777
|
+
GetPromptTypeDisplayName(typeId) {
|
|
2433
2778
|
if (!typeId)
|
|
2434
2779
|
return '';
|
|
2435
|
-
const type = this.
|
|
2780
|
+
const type = this.AvailablePromptTypes.find(t => UUIDsEqual(t.ID, typeId));
|
|
2436
2781
|
return type ? type.Name : typeId;
|
|
2437
2782
|
}
|
|
2783
|
+
/** @deprecated Use {@link GetPromptTypeDisplayName}. */
|
|
2784
|
+
getPromptTypeDisplayName(typeId) {
|
|
2785
|
+
return this.GetPromptTypeDisplayName(typeId);
|
|
2786
|
+
}
|
|
2438
2787
|
/**
|
|
2439
2788
|
* Gets the display name for a configuration ID
|
|
2440
2789
|
*/
|
|
2441
|
-
|
|
2790
|
+
GetConfigurationDisplayName(configurationId) {
|
|
2442
2791
|
if (!configurationId)
|
|
2443
2792
|
return 'Default';
|
|
2444
|
-
const config = this.
|
|
2793
|
+
const config = this.AvailableConfigurations.find(c => UUIDsEqual(c.ID, configurationId));
|
|
2445
2794
|
return config ? config.Name : configurationId;
|
|
2446
2795
|
}
|
|
2796
|
+
/** @deprecated Use {@link GetConfigurationDisplayName}. */
|
|
2797
|
+
getConfigurationDisplayName(configurationId) {
|
|
2798
|
+
return this.GetConfigurationDisplayName(configurationId);
|
|
2799
|
+
}
|
|
2447
2800
|
/**
|
|
2448
2801
|
* Override PopulatePendingRecords to add AI prompt model changes
|
|
2449
2802
|
*/
|
|
@@ -2461,6 +2814,11 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2461
2814
|
this.addPromptModelsToPendingRecords();
|
|
2462
2815
|
// Handle template content changes through the template editor
|
|
2463
2816
|
this.addTemplateContentsToPendingRecords();
|
|
2817
|
+
// The preserved copy above and the fresh collection can name the same entity (a retry after a
|
|
2818
|
+
// failed save); keep one pending record per entity object.
|
|
2819
|
+
const unique = DedupePendingRecordsByEntity(this.PendingRecords);
|
|
2820
|
+
this.PendingRecords.length = 0;
|
|
2821
|
+
this.PendingRecords.push(...unique);
|
|
2464
2822
|
}
|
|
2465
2823
|
/**
|
|
2466
2824
|
* Override StartEditMode to capture original state for cancel functionality
|
|
@@ -2485,20 +2843,20 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2485
2843
|
this.cdr.detectChanges();
|
|
2486
2844
|
});
|
|
2487
2845
|
}
|
|
2488
|
-
else if (this.
|
|
2846
|
+
else if (this.TemplateEditor) {
|
|
2489
2847
|
// Even if template didn't change, refresh the template editor to discard any unsaved content changes
|
|
2490
|
-
this.
|
|
2848
|
+
this.TemplateEditor.refreshAndDiscardChanges();
|
|
2491
2849
|
}
|
|
2492
2850
|
// Clear the stored original state
|
|
2493
2851
|
this.originalTemplateID = null;
|
|
2494
|
-
this.
|
|
2852
|
+
this.HasUnsavedChanges = false;
|
|
2495
2853
|
}
|
|
2496
2854
|
/**
|
|
2497
2855
|
* Adds prompt model changes to the pending records
|
|
2498
2856
|
*/
|
|
2499
2857
|
addPromptModelsToPendingRecords() {
|
|
2500
2858
|
// Add all prompt models that have been modified or are new
|
|
2501
|
-
for (const model of this.
|
|
2859
|
+
for (const model of this.PromptModels) {
|
|
2502
2860
|
if (model.ModelID && (model.Dirty || !model.IsSaved)) {
|
|
2503
2861
|
// Set the PromptID if it's not already set
|
|
2504
2862
|
if (!model.PromptID) {
|
|
@@ -2559,9 +2917,9 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2559
2917
|
const success = await transactionGroup.Submit();
|
|
2560
2918
|
if (success) {
|
|
2561
2919
|
// Clear our local state since save was successful
|
|
2562
|
-
this.
|
|
2920
|
+
this.HasUnsavedChanges = false;
|
|
2563
2921
|
// Reload prompt models to reflect database state
|
|
2564
|
-
await this.
|
|
2922
|
+
await this.LoadPromptModels();
|
|
2565
2923
|
// Reload template to reflect any changes
|
|
2566
2924
|
if (this.record.TemplateID) {
|
|
2567
2925
|
await this.loadTemplate();
|
|
@@ -2583,8 +2941,8 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2583
2941
|
/**
|
|
2584
2942
|
* Loads the result selector tree data (categories and prompts)
|
|
2585
2943
|
*/
|
|
2586
|
-
async
|
|
2587
|
-
this.
|
|
2944
|
+
async LoadResultSelectorTreeData() {
|
|
2945
|
+
this.IsLoadingResultSelectorData = true;
|
|
2588
2946
|
try {
|
|
2589
2947
|
// Load categories and prompts
|
|
2590
2948
|
const engine = AIEngineBase.Instance;
|
|
@@ -2594,16 +2952,20 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2594
2952
|
categories.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2595
2953
|
prompts.sort((a, b) => a.Name.localeCompare(b.Name));
|
|
2596
2954
|
// Build tree structure
|
|
2597
|
-
this.
|
|
2955
|
+
this.ResultSelectorTreeData = this.buildResultSelectorTree(categories, prompts);
|
|
2598
2956
|
}
|
|
2599
2957
|
catch (error) {
|
|
2600
2958
|
console.error('Error loading result selector tree data:', error);
|
|
2601
|
-
this.
|
|
2959
|
+
this.ResultSelectorTreeData = [];
|
|
2602
2960
|
}
|
|
2603
2961
|
finally {
|
|
2604
|
-
this.
|
|
2962
|
+
this.IsLoadingResultSelectorData = false;
|
|
2605
2963
|
}
|
|
2606
2964
|
}
|
|
2965
|
+
/** @deprecated Use {@link LoadResultSelectorTreeData}. */
|
|
2966
|
+
async loadResultSelectorTreeData() {
|
|
2967
|
+
return this.LoadResultSelectorTreeData();
|
|
2968
|
+
}
|
|
2607
2969
|
/**
|
|
2608
2970
|
* Builds the tree structure for result selector
|
|
2609
2971
|
*/
|
|
@@ -2687,13 +3049,17 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2687
3049
|
/**
|
|
2688
3050
|
* Handles result selector selection
|
|
2689
3051
|
*/
|
|
2690
|
-
|
|
3052
|
+
OnResultSelectorChange(value) {
|
|
2691
3053
|
this.record.ResultSelectorPromptID = value || null;
|
|
2692
3054
|
}
|
|
3055
|
+
/** @deprecated Use {@link OnResultSelectorChange}. */
|
|
3056
|
+
onResultSelectorChange(value) {
|
|
3057
|
+
return this.OnResultSelectorChange(value);
|
|
3058
|
+
}
|
|
2693
3059
|
/**
|
|
2694
3060
|
* Gets the display name for a prompt ID from the tree data
|
|
2695
3061
|
*/
|
|
2696
|
-
|
|
3062
|
+
GetPromptDisplayName(promptId) {
|
|
2697
3063
|
if (!promptId)
|
|
2698
3064
|
return '';
|
|
2699
3065
|
const findPromptInTree = (nodes) => {
|
|
@@ -2709,21 +3075,25 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2709
3075
|
}
|
|
2710
3076
|
return '';
|
|
2711
3077
|
};
|
|
2712
|
-
return findPromptInTree(this.
|
|
3078
|
+
return findPromptInTree(this.ResultSelectorTreeData);
|
|
3079
|
+
}
|
|
3080
|
+
/** @deprecated Use {@link GetPromptDisplayName}. */
|
|
3081
|
+
getPromptDisplayName(promptId) {
|
|
3082
|
+
return this.GetPromptDisplayName(promptId);
|
|
2713
3083
|
}
|
|
2714
3084
|
/**
|
|
2715
3085
|
* Moves a model up in the list by swapping with the previous item
|
|
2716
3086
|
*/
|
|
2717
|
-
|
|
2718
|
-
if (index > 0 && index < this.
|
|
3087
|
+
MoveModelUp(index) {
|
|
3088
|
+
if (index > 0 && index < this.PromptModels.length) {
|
|
2719
3089
|
// Create new array to ensure Angular detects the change
|
|
2720
|
-
const newModels = [...this.
|
|
3090
|
+
const newModels = [...this.PromptModels];
|
|
2721
3091
|
// Swap with previous item
|
|
2722
3092
|
[newModels[index - 1], newModels[index]] =
|
|
2723
3093
|
[newModels[index], newModels[index - 1]];
|
|
2724
3094
|
// Replace the array and force full re-render
|
|
2725
|
-
this.
|
|
2726
|
-
this.
|
|
3095
|
+
this.PromptModels = [...newModels];
|
|
3096
|
+
this.HasUnsavedChanges = true;
|
|
2727
3097
|
this.updateModelPriorities();
|
|
2728
3098
|
// Force Angular to re-evaluate all bindings
|
|
2729
3099
|
this.cdr.detectChanges();
|
|
@@ -2733,19 +3103,23 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2733
3103
|
}, 0);
|
|
2734
3104
|
}
|
|
2735
3105
|
}
|
|
3106
|
+
/** @deprecated Use {@link MoveModelUp}. */
|
|
3107
|
+
moveModelUp(index) {
|
|
3108
|
+
return this.MoveModelUp(index);
|
|
3109
|
+
}
|
|
2736
3110
|
/**
|
|
2737
3111
|
* Moves a model down in the list by swapping with the next item
|
|
2738
3112
|
*/
|
|
2739
|
-
|
|
2740
|
-
if (index >= 0 && index < this.
|
|
3113
|
+
MoveModelDown(index) {
|
|
3114
|
+
if (index >= 0 && index < this.PromptModels.length - 1) {
|
|
2741
3115
|
// Create new array to ensure Angular detects the change
|
|
2742
|
-
const newModels = [...this.
|
|
3116
|
+
const newModels = [...this.PromptModels];
|
|
2743
3117
|
// Swap with next item
|
|
2744
3118
|
[newModels[index], newModels[index + 1]] =
|
|
2745
3119
|
[newModels[index + 1], newModels[index]];
|
|
2746
3120
|
// Replace the array and force full re-render
|
|
2747
|
-
this.
|
|
2748
|
-
this.
|
|
3121
|
+
this.PromptModels = [...newModels];
|
|
3122
|
+
this.HasUnsavedChanges = true;
|
|
2749
3123
|
this.updateModelPriorities();
|
|
2750
3124
|
// Force Angular to re-evaluate all bindings
|
|
2751
3125
|
this.cdr.detectChanges();
|
|
@@ -2755,52 +3129,68 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2755
3129
|
}, 0);
|
|
2756
3130
|
}
|
|
2757
3131
|
}
|
|
3132
|
+
/** @deprecated Use {@link MoveModelDown}. */
|
|
3133
|
+
moveModelDown(index) {
|
|
3134
|
+
return this.MoveModelDown(index);
|
|
3135
|
+
}
|
|
2758
3136
|
/**
|
|
2759
3137
|
* Updates priority values based on array order
|
|
2760
3138
|
*/
|
|
2761
3139
|
updateModelPriorities() {
|
|
2762
3140
|
// Update priorities based on position (higher priority for items at top)
|
|
2763
|
-
const maxPriority = this.
|
|
2764
|
-
this.
|
|
3141
|
+
const maxPriority = this.PromptModels.length;
|
|
3142
|
+
this.PromptModels.forEach((model, index) => {
|
|
2765
3143
|
model.Priority = maxPriority - index;
|
|
2766
3144
|
});
|
|
2767
3145
|
}
|
|
2768
3146
|
/**
|
|
2769
3147
|
* Gets a stable identifier for a model (for form tracking)
|
|
2770
3148
|
*/
|
|
2771
|
-
|
|
3149
|
+
GetModelTrackId(model) {
|
|
2772
3150
|
return model.ID || model._tempId || '';
|
|
2773
3151
|
}
|
|
3152
|
+
/** @deprecated Use {@link GetModelTrackId}. */
|
|
3153
|
+
getModelTrackId(model) {
|
|
3154
|
+
return this.GetModelTrackId(model);
|
|
3155
|
+
}
|
|
2774
3156
|
/**
|
|
2775
3157
|
* Handles drag start event
|
|
2776
3158
|
*/
|
|
2777
|
-
|
|
2778
|
-
this.
|
|
3159
|
+
OnDragStart(event, index) {
|
|
3160
|
+
this.DraggedIndex = index;
|
|
2779
3161
|
event.dataTransfer.effectAllowed = 'move';
|
|
2780
3162
|
event.dataTransfer.setData('text/html', ''); // Required for Firefox
|
|
2781
3163
|
}
|
|
3164
|
+
/** @deprecated Use {@link OnDragStart}. */
|
|
3165
|
+
onDragStart(event, index) {
|
|
3166
|
+
return this.OnDragStart(event, index);
|
|
3167
|
+
}
|
|
2782
3168
|
/**
|
|
2783
3169
|
* Handles drag over event
|
|
2784
3170
|
*/
|
|
2785
|
-
|
|
3171
|
+
OnDragOver(event) {
|
|
2786
3172
|
event.preventDefault();
|
|
2787
3173
|
event.dataTransfer.dropEffect = 'move';
|
|
2788
3174
|
}
|
|
3175
|
+
/** @deprecated Use {@link OnDragOver}. */
|
|
3176
|
+
onDragOver(event) {
|
|
3177
|
+
return this.OnDragOver(event);
|
|
3178
|
+
}
|
|
2789
3179
|
/**
|
|
2790
3180
|
* Handles drop event
|
|
2791
3181
|
*/
|
|
2792
|
-
|
|
3182
|
+
OnDrop(event, dropIndex) {
|
|
2793
3183
|
event.preventDefault();
|
|
2794
|
-
if (this.
|
|
3184
|
+
if (this.DraggedIndex !== -1 && this.DraggedIndex !== dropIndex) {
|
|
2795
3185
|
// Create new array to ensure Angular detects the change
|
|
2796
|
-
const newModels = [...this.
|
|
3186
|
+
const newModels = [...this.PromptModels];
|
|
2797
3187
|
// Remove dragged item
|
|
2798
|
-
const draggedItem = newModels.splice(this.
|
|
3188
|
+
const draggedItem = newModels.splice(this.DraggedIndex, 1)[0];
|
|
2799
3189
|
// Insert at new position
|
|
2800
3190
|
newModels.splice(dropIndex, 0, draggedItem);
|
|
2801
3191
|
// Replace the array and force full re-render
|
|
2802
|
-
this.
|
|
2803
|
-
this.
|
|
3192
|
+
this.PromptModels = [...newModels];
|
|
3193
|
+
this.HasUnsavedChanges = true;
|
|
2804
3194
|
// Update priorities
|
|
2805
3195
|
this.updateModelPriorities();
|
|
2806
3196
|
// Force Angular to re-evaluate all bindings
|
|
@@ -2810,21 +3200,29 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2810
3200
|
this.cdr.detectChanges();
|
|
2811
3201
|
}, 0);
|
|
2812
3202
|
}
|
|
2813
|
-
this.
|
|
3203
|
+
this.DraggedIndex = -1;
|
|
3204
|
+
}
|
|
3205
|
+
/** @deprecated Use {@link OnDrop}. */
|
|
3206
|
+
onDrop(event, dropIndex) {
|
|
3207
|
+
return this.OnDrop(event, dropIndex);
|
|
2814
3208
|
}
|
|
2815
3209
|
/**
|
|
2816
3210
|
* Handles drag end event
|
|
2817
3211
|
*/
|
|
3212
|
+
OnDragEnd(_event) {
|
|
3213
|
+
this.DraggedIndex = -1;
|
|
3214
|
+
}
|
|
3215
|
+
/** @deprecated Use {@link OnDragEnd}. */
|
|
2818
3216
|
onDragEnd(_event) {
|
|
2819
|
-
this.
|
|
3217
|
+
return this.OnDragEnd(_event);
|
|
2820
3218
|
}
|
|
2821
3219
|
/**
|
|
2822
3220
|
* Load execution history for this prompt
|
|
2823
3221
|
*/
|
|
2824
|
-
async
|
|
3222
|
+
async LoadExecutionHistory() {
|
|
2825
3223
|
if (!this.record?.ID)
|
|
2826
3224
|
return;
|
|
2827
|
-
this.
|
|
3225
|
+
this.IsLoadingHistory = true;
|
|
2828
3226
|
try {
|
|
2829
3227
|
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
2830
3228
|
const result = await rv.RunView({
|
|
@@ -2832,26 +3230,30 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2832
3230
|
ExtraFilter: `PromptID='${this.record.ID}'`,
|
|
2833
3231
|
OrderBy: 'RunAt DESC'
|
|
2834
3232
|
});
|
|
2835
|
-
this.
|
|
2836
|
-
this.
|
|
3233
|
+
this.ExecutionHistory = result.Results;
|
|
3234
|
+
this.SortExecutionHistory();
|
|
2837
3235
|
}
|
|
2838
3236
|
catch (error) {
|
|
2839
3237
|
console.error('Error loading execution history:', error);
|
|
2840
|
-
this.
|
|
3238
|
+
this.ExecutionHistory = [];
|
|
2841
3239
|
}
|
|
2842
3240
|
finally {
|
|
2843
|
-
this.
|
|
3241
|
+
this.IsLoadingHistory = false;
|
|
2844
3242
|
}
|
|
2845
3243
|
}
|
|
3244
|
+
/** @deprecated Use {@link LoadExecutionHistory}. */
|
|
3245
|
+
async loadExecutionHistory() {
|
|
3246
|
+
return this.LoadExecutionHistory();
|
|
3247
|
+
}
|
|
2846
3248
|
/**
|
|
2847
3249
|
* Sort execution history based on current sort field and direction
|
|
2848
3250
|
*/
|
|
2849
|
-
|
|
2850
|
-
if (!this.
|
|
3251
|
+
SortExecutionHistory() {
|
|
3252
|
+
if (!this.ExecutionHistory || this.ExecutionHistory.length === 0)
|
|
2851
3253
|
return;
|
|
2852
|
-
this.
|
|
3254
|
+
this.ExecutionHistory.sort((a, b) => {
|
|
2853
3255
|
let aVal, bVal;
|
|
2854
|
-
switch (this.
|
|
3256
|
+
switch (this.HistorySortField) {
|
|
2855
3257
|
case 'runAt':
|
|
2856
3258
|
aVal = a.RunAt ? new Date(a.RunAt).getTime() : 0;
|
|
2857
3259
|
bVal = b.RunAt ? new Date(b.RunAt).getTime() : 0;
|
|
@@ -2869,7 +3271,7 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2869
3271
|
bVal = b.TokensUsed || 0;
|
|
2870
3272
|
break;
|
|
2871
3273
|
}
|
|
2872
|
-
if (this.
|
|
3274
|
+
if (this.HistorySortDirection === 'asc') {
|
|
2873
3275
|
return aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
|
|
2874
3276
|
}
|
|
2875
3277
|
else {
|
|
@@ -2877,27 +3279,39 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2877
3279
|
}
|
|
2878
3280
|
});
|
|
2879
3281
|
}
|
|
3282
|
+
/** @deprecated Use {@link SortExecutionHistory}. */
|
|
3283
|
+
sortExecutionHistory() {
|
|
3284
|
+
return this.SortExecutionHistory();
|
|
3285
|
+
}
|
|
2880
3286
|
/**
|
|
2881
3287
|
* Change sort field and direction for execution history
|
|
2882
3288
|
*/
|
|
2883
|
-
|
|
2884
|
-
if (this.
|
|
3289
|
+
ChangeHistorySort(field) {
|
|
3290
|
+
if (this.HistorySortField === field) {
|
|
2885
3291
|
// Toggle direction if same field
|
|
2886
|
-
this.
|
|
3292
|
+
this.HistorySortDirection = this.HistorySortDirection === 'asc' ? 'desc' : 'asc';
|
|
2887
3293
|
}
|
|
2888
3294
|
else {
|
|
2889
3295
|
// New field, default to desc
|
|
2890
|
-
this.
|
|
2891
|
-
this.
|
|
3296
|
+
this.HistorySortField = field;
|
|
3297
|
+
this.HistorySortDirection = 'desc';
|
|
2892
3298
|
}
|
|
2893
|
-
this.
|
|
3299
|
+
this.SortExecutionHistory();
|
|
3300
|
+
}
|
|
3301
|
+
/** @deprecated Use {@link ChangeHistorySort}. */
|
|
3302
|
+
changeHistorySort(field) {
|
|
3303
|
+
return this.ChangeHistorySort(field);
|
|
2894
3304
|
}
|
|
2895
3305
|
/**
|
|
2896
3306
|
* Navigate to a prompt run record
|
|
2897
3307
|
*/
|
|
2898
|
-
|
|
3308
|
+
NavigateToPromptRun(runId) {
|
|
2899
3309
|
SharedService.Instance.OpenEntityRecord('MJ: AI Prompt Runs', CompositeKey.FromID(runId));
|
|
2900
3310
|
}
|
|
3311
|
+
/** @deprecated Use {@link NavigateToPromptRun}. */
|
|
3312
|
+
navigateToPromptRun(runId) {
|
|
3313
|
+
return this.NavigateToPromptRun(runId);
|
|
3314
|
+
}
|
|
2901
3315
|
/**
|
|
2902
3316
|
* Format duration for display
|
|
2903
3317
|
*/
|
|
@@ -2919,43 +3333,59 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2919
3333
|
/**
|
|
2920
3334
|
* Format cost for display
|
|
2921
3335
|
*/
|
|
2922
|
-
|
|
3336
|
+
FormatCost(cost) {
|
|
2923
3337
|
if (!cost)
|
|
2924
3338
|
return '-';
|
|
2925
3339
|
return `$${cost.toFixed(4)}`;
|
|
2926
3340
|
}
|
|
3341
|
+
/** @deprecated Use {@link FormatCost}. */
|
|
3342
|
+
formatCost(cost) {
|
|
3343
|
+
return this.FormatCost(cost);
|
|
3344
|
+
}
|
|
2927
3345
|
/**
|
|
2928
3346
|
* Format tokens for display
|
|
2929
3347
|
*/
|
|
2930
|
-
|
|
3348
|
+
FormatTokens(tokens) {
|
|
2931
3349
|
if (!tokens)
|
|
2932
3350
|
return '-';
|
|
2933
3351
|
return tokens.toLocaleString();
|
|
2934
3352
|
}
|
|
3353
|
+
/** @deprecated Use {@link FormatTokens}. */
|
|
3354
|
+
formatTokens(tokens) {
|
|
3355
|
+
return this.FormatTokens(tokens);
|
|
3356
|
+
}
|
|
2935
3357
|
/**
|
|
2936
3358
|
* Get status color for execution
|
|
2937
3359
|
*/
|
|
2938
|
-
|
|
3360
|
+
GetExecutionStatusColor(success) {
|
|
2939
3361
|
if (success === true)
|
|
2940
3362
|
return '#28a745';
|
|
2941
3363
|
if (success === false)
|
|
2942
3364
|
return '#dc3545';
|
|
2943
3365
|
return '#ffc107';
|
|
2944
3366
|
}
|
|
3367
|
+
/** @deprecated Use {@link GetExecutionStatusColor}. */
|
|
3368
|
+
getExecutionStatusColor(success) {
|
|
3369
|
+
return this.GetExecutionStatusColor(success);
|
|
3370
|
+
}
|
|
2945
3371
|
/**
|
|
2946
3372
|
* Get status icon for execution
|
|
2947
3373
|
*/
|
|
2948
|
-
|
|
3374
|
+
GetExecutionStatusIcon(success) {
|
|
2949
3375
|
if (success === true)
|
|
2950
3376
|
return 'fa-check-circle';
|
|
2951
3377
|
if (success === false)
|
|
2952
3378
|
return 'fa-times-circle';
|
|
2953
3379
|
return 'fa-spinner fa-spin';
|
|
2954
3380
|
}
|
|
3381
|
+
/** @deprecated Use {@link GetExecutionStatusIcon}. */
|
|
3382
|
+
getExecutionStatusIcon(success) {
|
|
3383
|
+
return this.GetExecutionStatusIcon(success);
|
|
3384
|
+
}
|
|
2955
3385
|
/**
|
|
2956
3386
|
* Gets the icon for a template parameter type
|
|
2957
3387
|
*/
|
|
2958
|
-
|
|
3388
|
+
GetParamTypeIcon(type) {
|
|
2959
3389
|
switch (type) {
|
|
2960
3390
|
case 'Scalar': return 'fa-font';
|
|
2961
3391
|
case 'Array': return 'fa-list';
|
|
@@ -2965,10 +3395,14 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2965
3395
|
default: return 'fa-question';
|
|
2966
3396
|
}
|
|
2967
3397
|
}
|
|
3398
|
+
/** @deprecated Use {@link GetParamTypeIcon}. */
|
|
3399
|
+
getParamTypeIcon(type) {
|
|
3400
|
+
return this.GetParamTypeIcon(type);
|
|
3401
|
+
}
|
|
2968
3402
|
/**
|
|
2969
3403
|
* Gets the color for a template parameter type
|
|
2970
3404
|
*/
|
|
2971
|
-
|
|
3405
|
+
GetParamTypeColor(type) {
|
|
2972
3406
|
switch (type) {
|
|
2973
3407
|
case 'Scalar': return '#17a2b8';
|
|
2974
3408
|
case 'Array': return '#28a745';
|
|
@@ -2978,10 +3412,14 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
2978
3412
|
default: return '#6c757d';
|
|
2979
3413
|
}
|
|
2980
3414
|
}
|
|
3415
|
+
/** @deprecated Use {@link GetParamTypeColor}. */
|
|
3416
|
+
getParamTypeColor(type) {
|
|
3417
|
+
return this.GetParamTypeColor(type);
|
|
3418
|
+
}
|
|
2981
3419
|
/**
|
|
2982
3420
|
* Gets a friendly description of the parameter type
|
|
2983
3421
|
*/
|
|
2984
|
-
|
|
3422
|
+
GetParamTypeDescription(param) {
|
|
2985
3423
|
switch (param.Type) {
|
|
2986
3424
|
case 'Scalar':
|
|
2987
3425
|
return 'Single value (text, number, date, etc.)';
|
|
@@ -3003,12 +3441,16 @@ let MJAIPromptFormComponentExtended = class MJAIPromptFormComponentExtended exte
|
|
|
3003
3441
|
return 'Unknown type';
|
|
3004
3442
|
}
|
|
3005
3443
|
}
|
|
3444
|
+
/** @deprecated Use {@link GetParamTypeDescription}. */
|
|
3445
|
+
getParamTypeDescription(param) {
|
|
3446
|
+
return this.GetParamTypeDescription(param);
|
|
3447
|
+
}
|
|
3006
3448
|
static { this.ɵfac = /*@__PURE__*/ (() => { let ɵMJAIPromptFormComponentExtended_BaseFactory; return function MJAIPromptFormComponentExtended_Factory(__ngFactoryType__) { return (ɵMJAIPromptFormComponentExtended_BaseFactory || (ɵMJAIPromptFormComponentExtended_BaseFactory = i0.ɵɵgetInheritedFactory(MJAIPromptFormComponentExtended)))(__ngFactoryType__ || MJAIPromptFormComponentExtended); }; })(); }
|
|
3007
3449
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJAIPromptFormComponentExtended, selectors: [["mj-ai-prompt-form"]], viewQuery: function MJAIPromptFormComponentExtended_Query(rf, ctx) { if (rf & 1) {
|
|
3008
3450
|
i0.ɵɵviewQuery(_c0, 5);
|
|
3009
3451
|
} if (rf & 2) {
|
|
3010
3452
|
let _t;
|
|
3011
|
-
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.
|
|
3453
|
+
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.TemplateEditor = _t.first);
|
|
3012
3454
|
} }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 3, vars: 2, consts: [["form", "ngForm"], ["templateEditor", ""], [3, "Record", "FormComponent", "ToolbarConfig", "WidthMode"], [3, "Width", "Height", "MinWidth", "MinHeight", "Draggable", "Resizable", "Visible", "Title"], [3, "Navigate", "DeleteRequested", "FavoriteToggled", "HistoryRequested", "ListManagementRequested", "Record", "FormComponent", "ToolbarConfig", "WidthMode"], [1, "record-form", 2, "display", "flex", "flex-direction", "column", "height", "100%", "overflow", "hidden"], [1, "prompt-main-area", 2, "display", "flex", "flex-direction", "column", "flex", "1", "min-height", "0", "overflow-y", "auto"], [1, "prompt-header", 2, "flex-shrink", "0", "padding", "20px", "background", "var(--mj-bg-surface-sunken)", "border-bottom", "2px solid var(--mj-border-default)"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "gap", "20px"], [2, "flex", "1", "min-width", "0"], [2, "display", "flex", "align-items", "center", "gap", "12px", "margin-bottom", "8px"], [1, "fa-solid", "fa-robot", 2, "color", "var(--mj-brand-primary)", "font-size", "1.4em"], ["type", "text", "name", "promptName", "placeholder", "Enter prompt name...", 1, "mj-input", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModel"], [2, "display", "flex", "gap", "16px", "margin-bottom", "12px", "flex-wrap", "wrap"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 1, "mj-textarea", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModel", "rows"], [2, "margin", "0 0 12px 0", "color", "var(--mj-text-muted)", "font-size", "0.9em", "line-height", "1.4"], [1, "quick-config", 2, "display", "flex", "align-items", "center", "gap", "16px", "flex-wrap", "wrap"], [1, "config-item", 2, "display", "flex", "align-items", "center", "gap", "6px", "font-size", "0.85em"], [1, "fa-solid", "fa-layer-group", 2, "color", "var(--mj-text-muted)"], [2, "color", "var(--mj-text-muted)"], [2, "color", "var(--mj-text-secondary)", "font-weight", "500"], [1, "fa-solid", "fa-code", 2, "color", "var(--mj-text-muted)"], [2, "font-weight", "500"], [1, "action-buttons", 2, "display", "flex", "flex-direction", "column", "gap", "8px", "align-items", "flex-end"], [2, "display", "flex", "gap", "8px"], ["mjButton", "", "variant", "primary", "size", "lg", "title", "Run AI Prompt Test Harness"], [2, "font-size", "0.75em", "color", "#dc3545", "text-align", "right", "max-width", "200px"], [1, "configuration-sections", 2, "flex", "1", "background", "var(--mj-bg-surface-card)", "border-top", "2px solid var(--mj-border-default)", "padding", "16px", "min-height", "0"], [2, "margin-bottom", "12px", 3, "Expanded"], ["mjAccordionTitle", ""], [1, "template-section", 2, "display", "flex", "flex-direction", "column", "min-height", "400px", "padding", "8px"], [1, "loading-state", 2, "flex", "1", "display", "flex", "align-items", "center", "justify-content", "center", "color", "var(--mj-text-muted)"], ["Size", "large", "Icon", "fa-solid fa-code", "Title", "No Template Associated", "Message", "This AI prompt needs a template to define its structure and parameters. Create a new template or link to an existing one.", 1, "no-template-state"], ["Variant", "warning", "Title", "Template Not Found", "Message", "The referenced template could not be loaded. It may have been deleted or moved.", 1, "invalid-template-state"], [1, "template-editor-container", 2, "flex", "1", "display", "flex", "flex-direction", "column", "min-height", "350px"], [2, "padding", "16px 0"], [2, "display", "grid", "grid-template-columns", "1fr 1fr", "gap", "20px"], ["FieldName", "ParallelizationMode", "Type", "dropdownlist", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "ParallelCount", "Type", "numerictextbox", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "ParallelConfigParam", "Type", "textbox", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "OutputType", "Type", "dropdownlist", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "EffortLevel", "Type", "numerictextbox", "Caption", "Effort Level (1-100)", "Description", "Higher values request more thorough reasoning", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "ValidationBehavior", "Type", "dropdownlist", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "EnableCaching", "Type", "checkbox", 3, "Record", "ShowLabel", "EditMode"], [2, "margin-bottom", "16px"], [2, "display", "block", "margin-bottom", "4px", "font-weight", "600", "color", "var(--mj-text-secondary)", "font-size", "0.9em"], [2, "color", "var(--mj-text-secondary)"], [2, "margin", "0 0 12px 0", "font-size", "0.85em", "color", "var(--mj-text-muted)"], ["FieldName", "AssistantPrefill", "Type", "textarea", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "StopSequences", "Type", "textbox", 3, "Record", "ShowLabel", "EditMode"], ["FieldName", "PrefillFallbackMode", "Type", "dropdownlist", 3, "Record", "ShowLabel", "EditMode"], ["type", "text", "name", "promptName", "placeholder", "Enter prompt name...", 1, "mj-input", 2, "font-size", "1.2em", "font-weight", "600", "min-width", "300px", "flex", "1", 3, "ngModelChange", "ngModel"], [2, "margin", "0", "color", "var(--mj-text-secondary)", "font-weight", "600", "flex", "1"], [1, "status-badge", 2, "color", "white", "padding", "4px 10px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], ["name", "promptStatus", "TextField", "text", "ValueField", "value", 2, "width", "150px", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive"], [2, "color", "#dc3545"], [2, "padding", "8px", "color", "var(--mj-text-muted)", "font-style", "italic", "width", "200px"], ["name", "promptTypeID", "TextField", "Name", "ValueField", "ID", "Placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModel", "Data", "ValuePrimitive", "Filterable"], [1, "fa-solid", "fa-spinner", "fa-spin"], ["name", "promptTypeID", "TextField", "Name", "ValueField", "ID", "Placeholder", "Select prompt type...", 2, "width", "200px", 3, "ngModelChange", "ngModel", "Data", "ValuePrimitive", "Filterable"], ["name", "promptDescription", "placeholder", "Enter prompt description...", 1, "mj-textarea", 2, "width", "100%", "max-width", "600px", "margin-bottom", "12px", 3, "ngModelChange", "ngModel", "rows"], [1, "fa-solid", "fa-tag", 2, "color", "var(--mj-text-muted)"], [1, "fa-solid", "fa-database", 2, "color", "#28a745"], [2, "color", "#28a745", "font-weight", "500"], [1, "fa-solid", "fa-tachometer-alt", 2, "color", "var(--mj-text-muted)"], ["mjButton", "", "variant", "primary", "size", "lg", "title", "Run AI Prompt Test Harness", 3, "click"], [1, "fa-solid", "fa-play"], [2, "display", "flex", "align-items", "center", "gap", "8px", "font-weight", "600"], [2, "color", "var(--mj-text-muted)", "font-size", "0.9em", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "24px", "margin-right", "12px"], ["ngProjectAs", "[actions]", 5, ["", "actions", ""], 2, "display", "flex", "gap", "12px"], ["mjButton", "", "variant", "primary"], ["mjButton", "", "variant", "outline"], ["mjButton", "", "variant", "primary", 3, "click"], [1, "fa-solid", "fa-plus"], ["mjButton", "", "variant", "outline", 3, "click"], [1, "fa-solid", "fa-link"], [1, "fa-solid", "fa-arrows-rotate"], [1, "template-actions", 2, "display", "flex", "gap", "8px", "padding", "8px", "border-bottom", "1px solid var(--mj-border-default)", "background", "var(--mj-bg-surface-sunken)"], [2, "flex", "1", "background", "var(--mj-bg-surface-card)", "border-radius", "6px", "border", "1px solid var(--mj-border-default)"], [2, "display", "block", "min-height", "300px", 3, "contentChange", "runTemplate", "template", "config"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Change to a different template"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Open template in new window"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Change to a different template", 3, "click"], [1, "fa-solid", "fa-exchange-alt"], ["mjButton", "", "variant", "outline", "size", "sm", "title", "Open template in new window", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "model-management", 2, "border", "1px solid var(--mj-border-default)", "border-radius", "6px", "background", "var(--mj-bg-surface-sunken)"], [1, "loading-state", 2, "padding", "20px", "text-align", "center", "color", "var(--mj-text-muted)"], [1, "fa-solid", "fa-microchip", 2, "color", "var(--mj-text-muted)"], [1, "mj-accordion-badge"], [2, "color", "var(--mj-text-muted)", "font-size", "0.8em", "font-weight", "normal", "margin-left", "8px"], ["title", "Models are tried in order from top to bottom. The first available model will be used.", 1, "fa-solid", "fa-info-circle"], ["Size", "compact", "Icon", "fa-solid fa-circle-info", "Title", "No models configured"], ["ngProjectAs", "[actions]", "mjButton", "", "variant", "outline", "size", "sm", 5, ["", "actions", ""]], ["ngProjectAs", "[actions]", "mjButton", "", "variant", "outline", "size", "sm", 5, ["", "actions", ""], 3, "click"], [2, "padding", "12px 16px", "background", "color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface))", "border-bottom", "1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default))", "color", "var(--mj-brand-primary)", "font-size", "0.85em"], [1, "model-header", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "background", "var(--mj-bg-surface-sunken)", "font-weight", "600", "font-size", "0.85em", "color", "var(--mj-text-secondary)", "border-bottom", "1px solid var(--mj-border-default)"], ["title", "Priority order - models are tried from top to bottom"], [1, "fa-solid", "fa-sort", 2, "color", "var(--mj-text-muted)"], [1, "add-model-row", 2, "padding", "12px 16px", "text-align", "center", "background", "var(--mj-bg-surface-sunken)", "border-top", "1px solid var(--mj-border-default)"], [1, "fa-solid", "fa-info-circle", 2, "margin-right", "6px"], [1, "model-row", 2, "display", "grid", "grid-template-columns", "40px 2fr 1fr 1fr 1fr 60px", "gap", "12px", "padding", "12px 16px", "border-bottom", "1px solid var(--mj-border-default)", "align-items", "start", "transition", "background 0.2s, opacity 0.2s", 3, "dragstart", "dragover", "drop", "dragend", "draggable"], [1, "drag-handle", 2, "display", "flex", "flex-direction", "column", "align-items", "center", "justify-content", "center", "color", "var(--mj-text-muted)"], [2, "font-size", "0.9em", "font-weight", "600", 3, "title"], [1, "model-select"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select a model...", 2, "width", "100%", 3, "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], [1, "model-vendor"], [1, "model-configuration"], [2, "font-size", "0.9em"], [1, "model-created"], [2, "color", "var(--mj-text-muted)", "font-size", "0.8em"], [2, "color", "#28a745", "font-size", "0.8em", "font-style", "italic"], [1, "model-actions", 2, "display", "flex", "gap", "2px", "flex-direction", "column"], [2, "display", "grid", "grid-template-columns", "40px 1fr", "gap", "12px", "padding", "8px 16px", "border-bottom", "1px solid var(--mj-border-default)", "background", "var(--mj-bg-surface-sunken)", "font-size", "0.85em", "color", "var(--mj-text-muted)"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center", "margin-bottom", "8px"], [2, "padding", "8px", "background", "var(--mj-bg-surface-card)", "border", "1px solid var(--mj-border-default)", "border-radius", "4px", "margin-top", "8px"], ["title", "Drag to reorder priority", 1, "fa-solid", "fa-grip-vertical", 2, "cursor", "move"], [2, "font-size", "0.7em", "margin-top", "2px"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select a model...", 2, "width", "100%", 3, "ngModelChange", "ValueChange", "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], [2, "color", "var(--mj-text-muted)", "font-style", "italic", "font-size", "0.9em"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Select vendor...", 2, "width", "100%", 3, "ngModelChange", "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], [2, "font-size", "0.9em", "font-weight", "500", 3, "color"], [2, "font-size", "0.9em", "font-weight", "500"], [2, "font-size", "0.8em", "margin-left", "4px"], [2, "font-size", "0.9em", 3, "color"], [2, "color", "var(--mj-text-muted)", "font-size", "0.9em"], [2, "padding", "4px", "color", "var(--mj-text-muted)", "font-style", "italic", "font-size", "0.85em"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Default", 2, "width", "100%", 3, "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], ["TextField", "Name", "ValueField", "ID", "Placeholder", "Default", 2, "width", "100%", 3, "ngModelChange", "ValueChange", "ngModel", "name", "Data", "ValuePrimitive", "Filterable"], [2, "display", "flex", "gap", "2px", "margin-bottom", "4px"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove model", 2, "color", "var(--mj-status-error)"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Move up", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-up"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Move down", 3, "click", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "Remove model", 2, "color", "var(--mj-status-error)", 3, "click"], [1, "fa-solid", "fa-times"], [2, "margin-bottom", "6px", "font-weight", "600", "color", "var(--mj-text-secondary)", "font-size", "0.9em"], [1, "fa-solid", "fa-layer-group"], [2, "display", "grid", "grid-template-columns", "1fr 1fr 1fr", "gap", "12px", "align-items", "center"], [2, "display", "flex", "gap", "16px", "flex-wrap", "wrap", "align-items", "center"], [2, "display", "block", "margin-bottom", "2px", "font-size", "0.8em", "font-weight", "600", "color", "var(--mj-text-secondary)"], ["TextField", "text", "ValueField", "value", "Placeholder", "Select mode...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "Data", "ValuePrimitive"], ["Placeholder", "Count...", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name", "Min", "Step", "Format"], ["type", "text", "placeholder", "Parameter name...", 1, "mj-input", 2, "width", "100%", "font-size", "0.85em", 3, "ngModelChange", "ngModel", "name"], ["mjButton", "", "variant", "outline", "size", "sm", 2, "color", "var(--mj-status-success)", "border-color", "var(--mj-status-success)", 3, "click"], [1, "fa-solid", "fa-cogs", 2, "color", "var(--mj-text-muted)"], [2, "padding", "8px", "color", "var(--mj-text-muted)", "font-style", "italic"], ["name", "resultSelectorPromptID", "TextField", "text", "ValueField", "value", "Placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModel", "Data", "ValuePrimitive", "Filterable"], ["name", "resultSelectorPromptID", "TextField", "text", "ValueField", "value", "Placeholder", "Select a result selector prompt...", 2, "width", "100%", 3, "ngModelChange", "ValueChange", "ngModel", "Data", "ValuePrimitive", "Filterable"], [1, "fa-solid", "fa-wand-magic-sparkles", 2, "color", "var(--mj-text-muted)"], ["Size", "compact", "Icon", "fa-solid fa-circle-info", "Title", "This template has no parameters defined"], [1, "fa-solid", "fa-sliders", 2, "color", "var(--mj-text-muted)"], ["title", "These parameters are defined in the template and will be available when executing this prompt", 1, "fa-solid", "fa-info-circle"], [2, "display", "grid", "gap", "12px"], [1, "parameter-card", 2, "border", "1px solid var(--mj-border-default)", "border-radius", "8px", "padding", "16px", "background", "var(--mj-bg-surface-sunken)", "transition", "all 0.2s", 3, "border-left"], [2, "margin-top", "16px", "padding", "12px", "background", "color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface))", "border-radius", "6px", "border", "1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default))"], [2, "display", "flex", "align-items", "flex-start", "gap", "8px"], [1, "fa-solid", "fa-lightbulb", 2, "color", "var(--mj-brand-primary)", "margin-top", "2px"], [2, "flex", "1", "font-size", "0.85em", "color", "var(--mj-brand-primary)", "line-height", "1.5"], [1, "parameter-card", 2, "border", "1px solid var(--mj-border-default)", "border-radius", "8px", "padding", "16px", "background", "var(--mj-bg-surface-sunken)", "transition", "all 0.2s"], [2, "display", "flex", "justify-content", "space-between", "align-items", "flex-start", "margin-bottom", "8px"], [2, "display", "flex", "align-items", "center", "gap", "8px"], [2, "font-size", "1.2em"], [2, "margin", "0", "color", "var(--mj-text-secondary)", "font-weight", "600"], [2, "color", "#dc3545", "font-size", "0.9em", "margin-left", "4px"], [1, "type-badge", 2, "color", "white", "padding", "4px 8px", "border-radius", "12px", "font-size", "0.75em", "font-weight", "500"], [2, "color", "#dc3545", "font-size", "0.85em", "font-weight", "500"], [2, "color", "var(--mj-text-muted)", "font-size", "0.85em"], [2, "margin", "0 0 8px 0", "color", "var(--mj-text-muted)", "font-size", "0.9em", "line-height", "1.4"], [2, "font-size", "0.85em", "color", "var(--mj-text-secondary)"], [2, "display", "flex", "align-items", "center", "gap", "4px", "margin-bottom", "4px"], [1, "fa-solid", "fa-info-circle", 2, "color", "var(--mj-text-muted)"], [2, "display", "grid", "grid-template-columns", "repeat(auto-fit, minmax(200px, 1fr))", "gap", "12px", "margin-top", "12px"], [2, "background", "var(--mj-bg-surface-card)", "padding", "8px 12px", "border-radius", "4px", "border", "1px solid var(--mj-border-default)"], [2, "display", "block", "font-size", "0.8em", "color", "var(--mj-text-muted)", "margin-bottom", "2px"], [2, "font-size", "0.85em", "color", "var(--mj-text-secondary)", "word-break", "break-all"], [2, "font-size", "0.8em", "color", "var(--mj-text-secondary)", "word-break", "break-all"], [2, "padding", "16px"], [2, "background", "var(--mj-bg-surface-sunken)", "border", "1px solid var(--mj-border-default)", "border-radius", "4px", "padding", "12px", "font-family", "'Courier New', monospace", "font-size", "0.9em", "white-space", "pre-wrap", "overflow", "auto", "max-height", "250px"], ["Variant", "warning"], [2, "color", "#dc3545", "font-size", "0.8em", "font-weight", "normal"], ["name", "outputExample", "language", "json", "placeholder", "Enter JSON example structure...", 2, "width", "100%", "height", "200px", "border", "1px solid var(--mj-border-default)", "border-radius", "4px", 3, "ngModelChange", "ngModel"], [2, "margin-top", "8px", "color", "var(--mj-text-muted)", "font-size", "0.85em"], [1, "fa-solid", "fa-info-circle"], [2, "text-align", "center", "padding", "40px", "color", "var(--mj-text-muted)"], ["Size", "compact", "Icon", "fa-solid fa-clock-rotate-left", "Title", "No execution history yet", "Message", "Run this prompt to see execution history here"], [1, "fa-solid", "fa-history", 2, "color", "var(--mj-text-muted)"], [2, "color", "var(--mj-text-muted)", "font-weight", "normal"], [1, "fa-solid", "fa-spinner", "fa-spin", 2, "font-size", "2em", "margin-bottom", "12px"], [2, "display", "flex", "justify-content", "space-between", "align-items", "center", "margin-bottom", "16px"], [2, "display", "flex", "gap", "8px", "align-items", "center"], [1, "mj-button-group"], ["mjButton", "", "size", "sm", 3, "click"], [2, "margin-left", "4px", "font-size", "0.8em", 3, "class"], [2, "border", "1px solid var(--mj-border-default)", "border-radius", "8px", "overflow", "hidden"], [2, "width", "100%", "border-collapse", "collapse"], [2, "background", "var(--mj-bg-surface-sunken)", "border-bottom", "2px solid var(--mj-border-default)"], [2, "padding", "12px", "text-align", "left", "font-weight", "600", "color", "var(--mj-text-secondary)"], [2, "padding", "12px", "text-align", "right", "font-weight", "600", "color", "var(--mj-text-secondary)"], [2, "padding", "12px", "text-align", "center", "font-weight", "600", "color", "var(--mj-text-secondary)"], [1, "history-row", 2, "border-bottom", "1px solid var(--mj-border-default)", 3, "even-row"], [2, "margin-left", "4px", "font-size", "0.8em"], [1, "history-row", 2, "border-bottom", "1px solid var(--mj-border-default)"], [2, "padding", "12px"], [2, "display", "flex", "align-items", "center", "gap", "6px"], [2, "padding", "12px", "color", "var(--mj-text-secondary)"], [2, "padding", "12px", "text-align", "right", "color", "var(--mj-text-secondary)"], [2, "padding", "12px", "text-align", "center"], [2, "padding", "4px 8px", "border-radius", "12px", "background", "var(--mj-bg-surface-sunken)", "color", "var(--mj-text-secondary)", "font-size", "0.85em", "font-weight", "500"], ["mjButton", "", "variant", "flat", "size", "sm", "title", "View details", 3, "click"], [1, "fa-solid", "fa-external-link"], [3, "Params", "NewRecordValues", "AllowLoad", "ShowToolbar"], [1, "fa-solid", "fa-database", 2, "color", "var(--mj-text-muted)"], [2, "margin", "0 0 12px 0", "color", "var(--mj-text-secondary)"], [1, "fa-solid", "fa-link", 2, "color", "var(--mj-text-muted)"], [3, "Close", "Width", "Height", "MinWidth", "MinHeight", "Draggable", "Resizable", "Visible", "Title"], [3, "visibilityChange", "entity", "mode", "isVisible"]], template: function MJAIPromptFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
|
|
3013
3455
|
i0.ɵɵelement(0, "div");
|
|
3014
3456
|
i0.ɵɵconditionalCreate(1, MJAIPromptFormComponentExtended_Conditional_1_Template, 77, 53, "mj-record-form-container", 2);
|
|
@@ -3027,9 +3469,9 @@ export { MJAIPromptFormComponentExtended };
|
|
|
3027
3469
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJAIPromptFormComponentExtended, [{
|
|
3028
3470
|
type: Component,
|
|
3029
3471
|
args: [{ standalone: false, selector: 'mj-ai-prompt-form', template: "<!-- Dialog container -->\n<div></div>\n@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\" style=\"display: flex; flex-direction: column; height: 100%; overflow: hidden;\">\n <!-- Main Content Area - Template Editor and Configuration -->\n <div class=\"prompt-main-area\" style=\"display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto;\">\n <!-- Header Section -->\n <div class=\"prompt-header\" style=\"flex-shrink: 0; padding: 20px; background: var(--mj-bg-surface-sunken); border-bottom: 2px solid var(--mj-border-default);\">\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; gap: 20px;\">\n <!-- Left: Prompt Info -->\n <div style=\"flex: 1; min-width: 0;\">\n <div style=\"display: flex; align-items: center; gap: 12px; margin-bottom: 8px;\">\n <i class=\"fa-solid fa-robot\" style=\"color: var(--mj-brand-primary); font-size: 1.4em;\"></i>\n @if (EditMode) {\n <input type=\"text\" class=\"mj-input\" [(ngModel)]=\"record.Name\"\n name=\"promptName\"\n placeholder=\"Enter prompt name...\"\n style=\"font-size: 1.2em; font-weight: 600; min-width: 300px; flex: 1;\" />\n } @else {\n <h4 style=\"margin: 0; color: var(--mj-text-secondary); font-weight: 600; flex: 1;\">{{ record.Name || 'Untitled AI Prompt' }}</h4>\n <span class=\"status-badge\" [style.background-color]=\"getStatusBadgeColor()\"\n style=\"color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.75em; font-weight: 500;\">\n {{ record.Status }}\n </span>\n }\n </div>\n <!-- Status and Type Editors when in edit mode -->\n @if (EditMode) {\n <div style=\"display: flex; gap: 16px; margin-bottom: 12px; flex-wrap: wrap;\">\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">Status</label>\n <mj-dropdown [(ngModel)]=\"record.Status\"\n name=\"promptStatus\"\n [Data]=\"[{text: 'Active', value: 'Active'}, {text: 'Pending', value: 'Pending'}, {text: 'Disabled', value: 'Disabled'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n style=\"width: 150px;\">\n </mj-dropdown>\n </div>\n <div>\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Type <span style=\"color: #dc3545;\">*</span>\n </label>\n @if (isLoadingPromptTypes) {\n <div style=\"padding: 8px; color: var(--mj-text-muted); font-style: italic; width: 200px;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading types...\n </div>\n } @else {\n <mj-dropdown [(ngModel)]=\"record.TypeID\"\n name=\"promptTypeID\"\n [Data]=\"availablePromptTypes\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"true\"\n Placeholder=\"Select prompt type...\"\n style=\"width: 200px;\">\n </mj-dropdown>\n }\n </div>\n </div>\n }\n @if (EditMode) {\n <textarea class=\"mj-textarea\" [(ngModel)]=\"record.Description\"\n name=\"promptDescription\"\n [rows]=\"2\"\n placeholder=\"Enter prompt description...\"\n style=\"width: 100%; max-width: 600px; margin-bottom: 12px;\"></textarea>\n } @else if (record.Description) {\n <p style=\"margin: 0 0 12px 0; color: var(--mj-text-muted); font-size: 0.9em; line-height: 1.4;\">{{ record.Description }}</p>\n }\n <!-- Quick Config Row -->\n <div class=\"quick-config\" style=\"display: flex; align-items: center; gap: 16px; flex-wrap: wrap;\">\n @if (record.TypeID) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tag\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Type:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ getPromptTypeDisplayName(record.TypeID) }}</span>\n </div>\n }\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-layer-group\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Parallelization:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ getParallelizationModeDisplay() }}</span>\n </div>\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-code\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Output:</span>\n <span [style.color]=\"getValidationColor()\" style=\"font-weight: 500;\">{{ getOutputTypeDisplay() }}</span>\n </div>\n @if (record.EnableCaching) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-database\" style=\"color: #28a745;\"></i>\n <span style=\"color: #28a745; font-weight: 500;\">Caching Enabled</span>\n </div>\n }\n @if (record.EffortLevel) {\n <div class=\"config-item\" style=\"display: flex; align-items: center; gap: 6px; font-size: 0.85em;\">\n <i class=\"fa-solid fa-tachometer-alt\" style=\"color: var(--mj-text-muted);\"></i>\n <span style=\"color: var(--mj-text-muted);\">Effort Level:</span>\n <span style=\"color: var(--mj-text-secondary); font-weight: 500;\">{{ record.EffortLevel }}</span>\n </div>\n }\n </div>\n </div>\n <!-- Right: Action Buttons -->\n <div class=\"action-buttons\" style=\"display: flex; flex-direction: column; gap: 8px; align-items: flex-end;\">\n <div style=\"display: flex; gap: 8px;\">\n @if (record.ID) {\n <button mjButton variant=\"primary\" size=\"lg\"\n (click)=\"openTestHarness()\"\n title=\"Run AI Prompt Test Harness\">\n <i class=\"fa-solid fa-play\"></i> Run\n </button>\n }\n </div>\n @if (!canExecute && record.ID) {\n <div style=\"font-size: 0.75em; color: #dc3545; text-align: right; max-width: 200px;\">\n @if (record.Status !== 'Active') {\n \u2022 Prompt must be Active<br>\n }\n @if (!record.TemplateID) {\n \u2022 Template is required<br>\n }\n @if (!template && record.TemplateID) {\n \u2022 Template not found<br>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Configuration Sections with Expansion Panels -->\n <div class=\"configuration-sections\" style=\"flex: 1; background: var(--mj-bg-surface-card); border-top: 2px solid var(--mj-border-default); padding: 16px; min-height: 0;\">\n <!-- Template Editor Section -->\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-code\" style=\"color: var(--mj-text-muted);\"></i>\n Template Editor\n @if (template) {\n <span style=\"color: var(--mj-text-muted); font-size: 0.9em; font-weight: normal;\">• {{ template.Name }}</span>\n }\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div class=\"template-section\" style=\"display: flex; flex-direction: column; min-height: 400px; padding: 8px;\">\n @if (isLoadingTemplate) {\n <div class=\"loading-state\" style=\"flex: 1; display: flex; align-items: center; justify-content: center; color: var(--mj-text-muted);\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 24px; margin-right: 12px;\"></i>\n Loading template...\n </div>\n } @else if (!record.TemplateID) {\n <mj-empty-state class=\"no-template-state\"\n Size=\"large\"\n Icon=\"fa-solid fa-code\"\n Title=\"No Template Associated\"\n Message=\"This AI prompt needs a template to define its structure and parameters. Create a new template or link to an existing one.\">\n <div ngProjectAs=\"[actions]\" style=\"display: flex; gap: 12px;\">\n @if (UserCanCreateTemplates) {\n <button mjButton variant=\"primary\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button mjButton variant=\"outline\" (click)=\"linkExistingTemplate()\">\n <i class=\"fa-solid fa-link\"></i> Link Existing Template\n </button>\n }\n </div>\n </mj-empty-state>\n } @else if (templateNotFoundInDatabase) {\n <mj-empty-state class=\"invalid-template-state\"\n Variant=\"warning\"\n Title=\"Template Not Found\"\n Message=\"The referenced template could not be loaded. It may have been deleted or moved.\">\n <div ngProjectAs=\"[actions]\" style=\"display: flex; gap: 12px;\">\n <button mjButton variant=\"outline\" (click)=\"loadTemplate()\">\n <i class=\"fa-solid fa-arrows-rotate\"></i> Retry Loading\n </button>\n @if (UserCanCreateTemplates) {\n <button mjButton variant=\"primary\" (click)=\"createNewTemplate()\">\n <i class=\"fa-solid fa-plus\"></i> Create New Template\n </button>\n }\n </div>\n </mj-empty-state>\n } @else {\n <!-- Active Template Editor -->\n <div class=\"template-editor-container\" style=\"flex: 1; display: flex; flex-direction: column; min-height: 350px;\">\n <!-- Template Actions Bar -->\n @if (template && EditMode) {\n <div class=\"template-actions\" style=\"display: flex; gap: 8px; padding: 8px; border-bottom: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-sunken);\">\n @if (UserCanUpdateTemplates) {\n <button mjButton\n variant=\"outline\"\n size=\"sm\"\n (click)=\"linkExistingTemplate()\"\n title=\"Change to a different template\">\n <i class=\"fa-solid fa-exchange-alt\"></i> Change Template\n </button>\n }\n @if (UserCanReadTemplates) {\n <button mjButton\n variant=\"outline\"\n size=\"sm\"\n (click)=\"openTemplateInNewWindow()\"\n title=\"Open template in new window\">\n <i class=\"fa-solid fa-external-link-alt\"></i> Open in New Window\n </button>\n }\n </div>\n }\n <!-- Template Editor -->\n <div style=\"flex: 1; background: var(--mj-bg-surface-card); border-radius: 6px; border: 1px solid var(--mj-border-default);\">\n <mj-template-editor\n #templateEditor\n [template]=\"template\"\n [config]=\"templateEditorConfig\"\n (contentChange)=\"onTemplateContentChange($event)\"\n (runTemplate)=\"onTemplateRun($event)\"\n style=\"display: block; min-height: 300px;\">\n </mj-template-editor>\n </div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n <!-- Model Configuration Expansion Panel -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-microchip\" style=\"color: var(--mj-text-muted);\"></i>\n Models\n @if (promptModels.length > 0) {\n <span class=\"mj-accordion-badge\">{{ promptModels.length }}</span>\n }\n <span style=\"color: var(--mj-text-muted); font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"Models are tried in order from top to bottom. The first available model will be used.\"></i>\n Priority order (first available model will be used)\n </span>\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <!-- Model Management Interface -->\n <div class=\"model-management\" style=\"border: 1px solid var(--mj-border-default); border-radius: 6px; background: var(--mj-bg-surface-sunken);\">\n @if (isLoadingModels) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading models...\n </div>\n } @else {\n @if (promptModels.length === 0) {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-circle-info\"\n Title=\"No models configured\">\n @if (EditMode && UserCanCreatePromptModels) {\n <button ngProjectAs=\"[actions]\" mjButton variant=\"outline\" size=\"sm\"\n (click)=\"addNewModel()\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n }\n </mj-empty-state>\n } @else {\n <!-- Priority explanation for multiple models -->\n @if (promptModels.length > 1) {\n <div style=\"padding: 12px 16px; background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default)); color: var(--mj-brand-primary); font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\" style=\"margin-right: 6px;\"></i>\n Models are tried in priority order (highest priority first). The first available model that meets requirements will be used for execution.\n </div>\n }\n <!-- Column Headers -->\n <div class=\"model-header\" style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; background: var(--mj-bg-surface-sunken); font-weight: 600; font-size: 0.85em; color: var(--mj-text-secondary); border-bottom: 1px solid var(--mj-border-default);\">\n <div title=\"Priority order - models are tried from top to bottom\">\n <i class=\"fa-solid fa-sort\" style=\"color: var(--mj-text-muted);\"></i>\n </div>\n <div>AI Model <span style=\"color: #dc3545;\">*</span></div>\n <div>Vendor</div>\n <div>Configuration</div>\n <div>Created</div>\n <div>Actions</div>\n </div>\n @for (model of promptModels; track getModelTrackId(model) || $index; let i = $index) {\n <div class=\"model-row\"\n [draggable]=\"EditMode\"\n (dragstart)=\"onDragStart($event, i)\"\n (dragover)=\"onDragOver($event)\"\n (drop)=\"onDrop($event, i)\"\n (dragend)=\"onDragEnd($event)\"\n [style.background]=\"!model.ModelID ? '#fff3cd' : (draggedIndex === i ? 'color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface))' : 'var(--mj-bg-surface-card)')\"\n [style.border-left]=\"!model.ModelID ? '3px solid #ffc107' : 'none'\"\n [style.opacity]=\"draggedIndex === i ? '0.5' : '1'\"\n style=\"display: grid; grid-template-columns: 40px 2fr 1fr 1fr 1fr 60px; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--mj-border-default); align-items: start; transition: background 0.2s, opacity 0.2s;\">\n <!-- Drag Handle / Priority -->\n <div class=\"drag-handle\" style=\"display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--mj-text-muted);\">\n @if (EditMode) {\n <i class=\"fa-solid fa-grip-vertical\" title=\"Drag to reorder priority\" style=\"cursor: move;\"></i>\n <span style=\"font-size: 0.7em; margin-top: 2px;\">#{{ i + 1 }}</span>\n } @else {\n <span style=\"font-size: 0.9em; font-weight: 600;\" title=\"Priority {{ model.Priority }} - Higher priority numbers are tried first\">#{{ i + 1 }}</span>\n }\n </div>\n <!-- Model Selection -->\n <div class=\"model-select\">\n @if (EditMode) {\n <mj-dropdown [(ngModel)]=\"model.ModelID\"\n [name]=\"'modelId_' + getModelTrackId(model)\"\n [Data]=\"availableModels\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"true\"\n Placeholder=\"Select a model...\"\n (ValueChange)=\"onModelChange($any($event), i)\"\n style=\"width: 100%;\">\n </mj-dropdown>\n } @else {\n <span style=\"font-weight: 500;\">{{ getModelDisplayName(model.ModelID) }}</span>\n }\n </div>\n <!-- Vendor -->\n <div class=\"model-vendor\">\n @if (EditMode) {\n @if (model.ModelID) {\n @if (shouldShowVendorDropdown(model.ModelID)) {\n <mj-dropdown [(ngModel)]=\"model.VendorID\"\n [name]=\"'vendorId_' + getModelTrackId(model)\"\n [Data]=\"getVendorsForModelSync(model.ModelID)\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"true\"\n Placeholder=\"Select vendor...\"\n style=\"width: 100%;\">\n </mj-dropdown>\n } @else {\n <!-- Single vendor - just show the name -->\n @if (getVendorsForModelSync(model.ModelID).length === 1) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID)\" style=\"font-size: 0.9em; font-weight: 500;\">\n {{ getVendorsForModelSync(model.ModelID)[0].Name }}\n @if (getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, getVendorsForModelSync(model.ModelID)[0].ID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: var(--mj-text-muted); font-style: italic; font-size: 0.9em;\">No vendors available</span>\n }\n }\n } @else {\n <span style=\"color: var(--mj-text-muted); font-style: italic; font-size: 0.9em;\">Select model first</span>\n }\n } @else {\n @if (model.VendorID && model.ModelID) {\n <span [style.color]=\"getVendorStatusColor(model.ModelID, model.VendorID)\" style=\"font-size: 0.9em;\">\n {{ getVendorDisplayName(model.VendorID) }}\n @if (getModelVendorStatus(model.ModelID, model.VendorID) !== 'Active') {\n <span style=\"font-size: 0.8em; margin-left: 4px;\">({{ getModelVendorStatus(model.ModelID, model.VendorID) }})</span>\n }\n </span>\n } @else {\n <span style=\"color: var(--mj-text-muted); font-size: 0.9em;\">-</span>\n }\n }\n </div>\n <!-- Configuration -->\n <div class=\"model-configuration\">\n @if (EditMode) {\n @if (isLoadingConfigurations) {\n <div style=\"padding: 4px; color: var(--mj-text-muted); font-style: italic; font-size: 0.85em;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading...\n </div>\n } @else {\n <mj-dropdown [(ngModel)]=\"model.ConfigurationID\"\n [name]=\"'configurationId_' + getModelTrackId(model)\"\n [Data]=\"availableConfigurations\"\n TextField=\"Name\"\n ValueField=\"ID\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"true\"\n Placeholder=\"Default\"\n (ValueChange)=\"onConfigurationChange($any($event), i)\"\n style=\"width: 100%;\">\n </mj-dropdown>\n }\n } @else {\n <span style=\"font-size: 0.9em;\">{{ getConfigurationDisplayName(model.ConfigurationID) }}</span>\n }\n </div>\n <!-- Created Date -->\n <div class=\"model-created\">\n @if (model.ID) {\n <span style=\"color: var(--mj-text-muted); font-size: 0.8em;\">{{ model.__mj_CreatedAt | date:'short' }}</span>\n } @else {\n <span style=\"color: #28a745; font-size: 0.8em; font-style: italic;\">New</span>\n }\n </div>\n <!-- Actions -->\n <div class=\"model-actions\" style=\"display: flex; gap: 2px; flex-direction: column;\">\n @if (EditMode) {\n <div style=\"display: flex; gap: 2px; margin-bottom: 4px;\">\n @if (UserCanUpdatePromptModels) {\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"moveModelUp(i)\"\n [disabled]=\"i === 0\"\n title=\"Move up\">\n <i class=\"fa-solid fa-chevron-up\"></i>\n </button>\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"moveModelDown(i)\"\n [disabled]=\"i === promptModels.length - 1\"\n title=\"Move down\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n }\n </div>\n @if (UserCanDeletePromptModels) {\n <button mjButton variant=\"flat\" size=\"sm\"\n (click)=\"removePromptModel(i)\"\n title=\"Remove model\"\n style=\"color: var(--mj-status-error);\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n }\n </div>\n </div>\n <!-- Second row with additional details -->\n <div style=\"display: grid; grid-template-columns: 40px 1fr; gap: 12px; padding: 8px 16px; border-bottom: 1px solid var(--mj-border-default); background: var(--mj-bg-surface-sunken); font-size: 0.85em; color: var(--mj-text-muted);\">\n <div></div>\n <div>\n <!-- Basic model details -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center; margin-bottom: 8px;\">\n @if (model.Status) {\n <span><strong>Status:</strong> {{ model.Status }}</span>\n }\n </div>\n <!-- Parallel execution fields when prompt is ModelSpecific -->\n @if (record.ParallelizationMode === 'ModelSpecific') {\n <div style=\"padding: 8px; background: var(--mj-bg-surface-card); border: 1px solid var(--mj-border-default); border-radius: 4px; margin-top: 8px;\">\n <div style=\"margin-bottom: 6px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n <i class=\"fa-solid fa-layer-group\"></i> Model-Specific Parallel Execution\n </div>\n @if (EditMode) {\n <div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; align-items: center;\">\n <!-- Parallel Mode -->\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: var(--mj-text-secondary);\">Parallel Mode</label>\n <mj-dropdown [(ngModel)]=\"model.ParallelizationMode\"\n [name]=\"'parallelMode_' + i\"\n [Data]=\"[{text: 'None', value: 'None'}, {text: 'Static Count', value: 'StaticCount'}, {text: 'Config Param', value: 'ConfigParam'}]\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n Placeholder=\"Select mode...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </mj-dropdown>\n </div>\n <!-- Parallel Count (when StaticCount) -->\n @if (model.ParallelizationMode === 'StaticCount') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: var(--mj-text-secondary);\">Parallel Count</label>\n <mj-numeric-input [(ngModel)]=\"model.ParallelCount\"\n [name]=\"'parallelCount_' + i\"\n [Min]=\"1\"\n [Step]=\"1\"\n [Format]=\"'n0'\"\n Placeholder=\"Count...\"\n style=\"width: 100%; font-size: 0.85em;\">\n </mj-numeric-input>\n </div>\n }\n <!-- Config Param (when ConfigParam) -->\n @if (model.ParallelizationMode === 'ConfigParam') {\n <div>\n <label style=\"display: block; margin-bottom: 2px; font-size: 0.8em; font-weight: 600; color: var(--mj-text-secondary);\">Config Parameter</label>\n <input type=\"text\" class=\"mj-input\" [(ngModel)]=\"model.ParallelConfigParam\"\n [name]=\"'parallelConfigParam_' + i\"\n placeholder=\"Parameter name...\"\n style=\"width: 100%; font-size: 0.85em;\" />\n </div>\n }\n </div>\n } @else {\n <!-- Read-only display -->\n <div style=\"display: flex; gap: 16px; flex-wrap: wrap; align-items: center;\">\n @if (model.ParallelizationMode) {\n <span><strong>Parallel Mode:</strong> {{ model.ParallelizationMode }}</span>\n }\n @if (model.ParallelCount) {\n <span><strong>Parallel Count:</strong> {{ model.ParallelCount }}</span>\n }\n @if (model.ParallelConfigParam) {\n <span><strong>Config Param:</strong> {{ model.ParallelConfigParam }}</span>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (EditMode && UserCanCreatePromptModels) {\n <div class=\"add-model-row\" style=\"padding: 12px 16px; text-align: center; background: var(--mj-bg-surface-sunken); border-top: 1px solid var(--mj-border-default);\">\n <button mjButton variant=\"outline\" size=\"sm\"\n (click)=\"addNewModel()\"\n style=\"color: var(--mj-status-success); border-color: var(--mj-status-success);\">\n <i class=\"fa-solid fa-plus\"></i> Add Model\n </button>\n </div>\n }\n }\n }\n </div>\n </div>\n </mj-accordion-panel>\n }\n <!-- Advanced Configuration Expansion Panel -->\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-cogs\" style=\"color: var(--mj-text-muted);\"></i>\n Advanced Configuration\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n <!-- Left Column -->\n <div>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelizationMode\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n @if (showParallelCount) {\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelCount\"\n Type=\"numerictextbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n @if (showParallelConfigParam) {\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ParallelConfigParam\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n }\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"OutputType\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EffortLevel\"\n Type=\"numerictextbox\"\n Caption=\"Effort Level (1-100)\"\n Description=\"Higher values request more thorough reasoning\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n </div>\n <!-- Right Column -->\n <div>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"ValidationBehavior\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"EnableCaching\"\n Type=\"checkbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n <!-- Result Selector Prompt with Tree Selector -->\n <div style=\"margin-bottom: 16px;\">\n <label style=\"display: block; margin-bottom: 4px; font-weight: 600; color: var(--mj-text-secondary); font-size: 0.9em;\">\n Result Selector Prompt\n </label>\n @if (EditMode) {\n @if (isLoadingResultSelectorData) {\n <div style=\"padding: 8px; color: var(--mj-text-muted); font-style: italic;\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading prompts...\n </div>\n } @else {\n <mj-dropdown\n [(ngModel)]=\"record.ResultSelectorPromptID\"\n name=\"resultSelectorPromptID\"\n [Data]=\"resultSelectorTreeData\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"true\"\n Placeholder=\"Select a result selector prompt...\"\n style=\"width: 100%;\"\n (ValueChange)=\"onResultSelectorChange($any($event))\">\n </mj-dropdown>\n }\n } @else {\n <span style=\"color: var(--mj-text-secondary);\">{{ getPromptDisplayName(record.ResultSelectorPromptID || '') || 'None selected' }}</span>\n }\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prefill & Output Control Expansion Panel -->\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-wand-magic-sparkles\" style=\"color: var(--mj-text-muted);\"></i>\n Prefill & Output Control\n </span>\n </ng-template>\n <div style=\"padding: 16px 0;\">\n <p style=\"margin: 0 0 12px 0; font-size: 0.85em; color: var(--mj-text-muted);\">\n Assistant prefill seeds the model's response with an initial string, guiding output format and content. Stop sequences terminate generation when encountered.\n </p>\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n <!-- Left Column -->\n <div>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"AssistantPrefill\"\n Type=\"textarea\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"StopSequences\"\n Type=\"textbox\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n </div>\n <!-- Right Column -->\n <div>\n <mj-form-field\n [Record]=\"record\"\n [ShowLabel]=\"true\"\n FieldName=\"PrefillFallbackMode\"\n Type=\"dropdownlist\"\n [EditMode]=\"EditMode\">\n </mj-form-field>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Template Parameters Expansion Panel -->\n @if (template && templateParams.length > 0) {\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-sliders\" style=\"color: var(--mj-text-muted);\"></i>\n Template Parameters\n <span class=\"mj-accordion-badge\">{{ templateParams.length }}</span>\n <span style=\"color: var(--mj-text-muted); font-size: 0.8em; font-weight: normal; margin-left: 8px;\">\n <i class=\"fa-solid fa-info-circle\" title=\"These parameters are defined in the template and will be available when executing this prompt\"></i>\n Parameters defined in the template\n </span>\n </span>\n </ng-template>\n <!-- Template Parameters Display -->\n <div style=\"padding: 16px 0;\">\n @if (isLoadingTemplateParams) {\n <div class=\"loading-state\" style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading template parameters...\n </div>\n } @else if (templateParams.length === 0) {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-circle-info\"\n Title=\"This template has no parameters defined\" />\n } @else {\n <!-- Parameters Grid -->\n <div style=\"display: grid; gap: 12px;\">\n @for (param of templateParams; track param.ID) {\n <div class=\"parameter-card\"\n style=\"border: 1px solid var(--mj-border-default); border-radius: 8px; padding: 16px; background: var(--mj-bg-surface-sunken); transition: all 0.2s;\"\n [style.border-left]=\"'4px solid ' + getParamTypeColor(param.Type)\">\n <!-- Parameter Header -->\n <div style=\"display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 8px;\">\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <i [class]=\"'fa-solid ' + getParamTypeIcon(param.Type)\"\n [style.color]=\"getParamTypeColor(param.Type)\"\n style=\"font-size: 1.2em;\"></i>\n <h6 style=\"margin: 0; color: var(--mj-text-secondary); font-weight: 600;\">\n {{ param.Name }}\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.9em; margin-left: 4px;\">*</span>\n }\n </h6>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <span class=\"type-badge\"\n [style.background-color]=\"getParamTypeColor(param.Type)\"\n style=\"color: white; padding: 4px 8px; border-radius: 12px; font-size: 0.75em; font-weight: 500;\">\n {{ param.Type }}\n </span>\n @if (param.IsRequired) {\n <span style=\"color: #dc3545; font-size: 0.85em; font-weight: 500;\">Required</span>\n } @else {\n <span style=\"color: var(--mj-text-muted); font-size: 0.85em;\">Optional</span>\n }\n </div>\n </div>\n <!-- Parameter Description -->\n @if (param.Description) {\n <p style=\"margin: 0 0 8px 0; color: var(--mj-text-muted); font-size: 0.9em; line-height: 1.4;\">\n {{ param.Description }}\n </p>\n }\n <!-- Type-specific Information -->\n <div style=\"font-size: 0.85em; color: var(--mj-text-secondary);\">\n <span style=\"display: flex; align-items: center; gap: 4px; margin-bottom: 4px;\">\n <i class=\"fa-solid fa-info-circle\" style=\"color: var(--mj-text-muted);\"></i>\n {{ getParamTypeDescription(param) }}\n </span>\n </div>\n <!-- Additional Parameter Details -->\n <div style=\"display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 12px;\">\n @if (param.DefaultValue) {\n <div style=\"background: var(--mj-bg-surface-card); padding: 8px 12px; border-radius: 4px; border: 1px solid var(--mj-border-default);\">\n <label style=\"display: block; font-size: 0.8em; color: var(--mj-text-muted); margin-bottom: 2px;\">Default Value</label>\n <code style=\"font-size: 0.85em; color: var(--mj-text-secondary); word-break: break-all;\">{{ param.DefaultValue }}</code>\n </div>\n }\n @if (param.EntityID) {\n <div style=\"background: var(--mj-bg-surface-card); padding: 8px 12px; border-radius: 4px; border: 1px solid var(--mj-border-default);\">\n <label style=\"display: block; font-size: 0.8em; color: var(--mj-text-muted); margin-bottom: 2px;\">Entity</label>\n <span style=\"font-size: 0.85em; color: var(--mj-text-secondary);\">{{ param.Entity || 'Entity ID: ' + param.EntityID }}</span>\n </div>\n }\n @if (param.LinkedParameterName) {\n <div style=\"background: var(--mj-bg-surface-card); padding: 8px 12px; border-radius: 4px; border: 1px solid var(--mj-border-default);\">\n <label style=\"display: block; font-size: 0.8em; color: var(--mj-text-muted); margin-bottom: 2px;\">Linked To</label>\n <span style=\"font-size: 0.85em; color: var(--mj-text-secondary);\">\n {{ param.LinkedParameterName }}\n @if (param.LinkedParameterField) {\n ({{ param.LinkedParameterField }})\n }\n </span>\n </div>\n }\n @if (param.ExtraFilter) {\n <div style=\"background: var(--mj-bg-surface-card); padding: 8px 12px; border-radius: 4px; border: 1px solid var(--mj-border-default);\">\n <label style=\"display: block; font-size: 0.8em; color: var(--mj-text-muted); margin-bottom: 2px;\">Filter</label>\n <code style=\"font-size: 0.8em; color: var(--mj-text-secondary); word-break: break-all;\">{{ param.ExtraFilter }}</code>\n </div>\n }\n @if (param.RecordID) {\n <div style=\"background: var(--mj-bg-surface-card); padding: 8px 12px; border-radius: 4px; border: 1px solid var(--mj-border-default);\">\n <label style=\"display: block; font-size: 0.8em; color: var(--mj-text-muted); margin-bottom: 2px;\">Record ID</label>\n <code style=\"font-size: 0.85em; color: var(--mj-text-secondary);\">{{ param.RecordID }}</code>\n </div>\n }\n </div>\n </div>\n }\n </div>\n <!-- Help Text -->\n <div style=\"margin-top: 16px; padding: 12px; background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface)); border-radius: 6px; border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-border-default));\">\n <div style=\"display: flex; align-items: flex-start; gap: 8px;\">\n <i class=\"fa-solid fa-lightbulb\" style=\"color: var(--mj-brand-primary); margin-top: 2px;\"></i>\n <div style=\"flex: 1; font-size: 0.85em; color: var(--mj-brand-primary); line-height: 1.5;\">\n <strong>Using Template Parameters:</strong> When executing this prompt, you'll be prompted to provide values for all required parameters.\n Parameters can be simple values (text, numbers) or complex data structures (JSON objects, database records, or entire entity collections).\n The template will use these parameters to generate dynamic content based on the values provided at execution time.\n </div>\n </div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Output Example Expansion Panel (when OutputType = object) -->\n @if (showOutputExample) {\n <mj-accordion-panel\n [Expanded]=\"true\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-code\" style=\"color: var(--mj-text-muted);\"></i>\n Output Example (JSON)\n <span style=\"color: #dc3545; font-size: 0.8em; font-weight: normal;\">• Required for object output type</span>\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div style=\"padding: 16px;\">\n @if (EditMode) {\n <mj-code-editor\n [(ngModel)]=\"record.OutputExample\"\n name=\"outputExample\"\n language=\"json\"\n placeholder=\"Enter JSON example structure...\"\n style=\"width: 100%; height: 200px; border: 1px solid var(--mj-border-default); border-radius: 4px;\">\n </mj-code-editor>\n <div style=\"margin-top: 8px; color: var(--mj-text-muted); font-size: 0.85em;\">\n <i class=\"fa-solid fa-info-circle\"></i> Provide a JSON example that defines the expected structure for object output validation.\n </div>\n } @else if (record.OutputExample) {\n <div style=\"background: var(--mj-bg-surface-sunken); border: 1px solid var(--mj-border-default); border-radius: 4px; padding: 12px; font-family: 'Courier New', monospace; font-size: 0.9em; white-space: pre-wrap; overflow: auto; max-height: 250px;\">{{ record.OutputExample }}</div>\n } @else {\n <mj-alert Variant=\"warning\">Output example is required when output type is 'object'</mj-alert>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Execution History Expansion Panel -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-history\" style=\"color: var(--mj-text-muted);\"></i>\n Execution History\n @if (executionHistory.length > 0) {\n <span style=\"color: var(--mj-text-muted); font-weight: normal;\">({{ executionHistory.length }})</span>\n }\n </span>\n </ng-template>\n <!-- Custom Execution History Viewer -->\n <div style=\"padding: 16px;\">\n @if (isLoadingHistory) {\n <div style=\"text-align: center; padding: 40px; color: var(--mj-text-muted);\">\n <i class=\"fa-solid fa-spinner fa-spin\" style=\"font-size: 2em; margin-bottom: 12px;\"></i>\n <p>Loading execution history...</p>\n </div>\n } @else if (executionHistory.length === 0) {\n <mj-empty-state\n Size=\"compact\"\n Icon=\"fa-solid fa-clock-rotate-left\"\n Title=\"No execution history yet\"\n Message=\"Run this prompt to see execution history here\" />\n } @else {\n <!-- Sort Controls -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;\">\n <div style=\"color: var(--mj-text-muted); font-size: 0.9em;\">\n Showing {{ executionHistory.length }} executions\n </div>\n <div style=\"display: flex; gap: 8px; align-items: center;\">\n <span style=\"color: var(--mj-text-muted); font-size: 0.85em;\">Sort by:</span>\n <div class=\"mj-button-group\">\n <button mjButton\n [class.active]=\"historySortField === 'runAt'\"\n (click)=\"changeHistorySort('runAt')\"\n size=\"sm\">\n Date\n @if (historySortField === 'runAt') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\"\n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button mjButton\n [class.active]=\"historySortField === 'executionTime'\"\n (click)=\"changeHistorySort('executionTime')\"\n size=\"sm\">\n Duration\n @if (historySortField === 'executionTime') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\"\n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button mjButton\n [class.active]=\"historySortField === 'tokens'\"\n (click)=\"changeHistorySort('tokens')\"\n size=\"sm\">\n Tokens\n @if (historySortField === 'tokens') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\"\n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n <button mjButton\n [class.active]=\"historySortField === 'cost'\"\n (click)=\"changeHistorySort('cost')\"\n size=\"sm\">\n Cost\n @if (historySortField === 'cost') {\n <i [class]=\"'fa-solid fa-sort-' + (historySortDirection === 'asc' ? 'up' : 'down')\"\n style=\"margin-left: 4px; font-size: 0.8em;\"></i>\n }\n </button>\n </div>\n </div>\n </div>\n <!-- Execution History Table -->\n <div style=\"border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden;\">\n <table style=\"width: 100%; border-collapse: collapse;\">\n <thead>\n <tr style=\"background: var(--mj-bg-surface-sunken); border-bottom: 2px solid var(--mj-border-default);\">\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: var(--mj-text-secondary);\">Status</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: var(--mj-text-secondary);\">Date & Time</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: var(--mj-text-secondary);\">Model</th>\n <th style=\"padding: 12px; text-align: left; font-weight: 600; color: var(--mj-text-secondary);\">Duration</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: var(--mj-text-secondary);\">Tokens</th>\n <th style=\"padding: 12px; text-align: right; font-weight: 600; color: var(--mj-text-secondary);\">Cost</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: var(--mj-text-secondary);\">Type</th>\n <th style=\"padding: 12px; text-align: center; font-weight: 600; color: var(--mj-text-secondary);\">Actions</th>\n </tr>\n </thead>\n <tbody>\n @for (run of executionHistory; track run.ID; let i = $index) {\n <tr class=\"history-row\"\n [class.even-row]=\"i % 2 === 0\"\n style=\"border-bottom: 1px solid var(--mj-border-default);\">\n <td style=\"padding: 12px;\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i [class]=\"'fa-solid ' + getExecutionStatusIcon(run.Success)\"\n [style.color]=\"getExecutionStatusColor(run.Success)\"></i>\n <span [style.color]=\"getExecutionStatusColor(run.Success)\" style=\"font-weight: 500;\">\n {{ run.Success === true ? 'Success' : run.Success === false ? 'Failed' : 'Running' }}\n </span>\n </span>\n </td>\n <td style=\"padding: 12px; color: var(--mj-text-secondary);\">\n {{ run.RunAt | date:'short' }}\n </td>\n <td style=\"padding: 12px; color: var(--mj-text-secondary);\">\n <span style=\"display: flex; align-items: center; gap: 6px;\">\n <i class=\"fa-solid fa-microchip\" style=\"color: var(--mj-text-muted);\"></i>\n {{ run.Model || 'Unknown' }}\n </span>\n </td>\n <td style=\"padding: 12px; color: var(--mj-text-secondary);\">\n {{ formatDuration(run.ExecutionTimeMS) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: var(--mj-text-secondary);\">\n {{ formatTokens(run.TokensUsed) }}\n </td>\n <td style=\"padding: 12px; text-align: right; color: var(--mj-text-secondary);\">\n {{ formatCost(run.TotalCost || run.Cost) }}\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n @if (run.RunType) {\n <span style=\"padding: 4px 8px; border-radius: 12px; background: var(--mj-bg-surface-sunken); \n color: var(--mj-text-secondary); font-size: 0.85em; font-weight: 500;\">\n {{ run.RunType }}\n </span>\n }\n </td>\n <td style=\"padding: 12px; text-align: center;\">\n <button mjButton\n variant=\"flat\"\n size=\"sm\"\n (click)=\"navigateToPromptRun(run.ID)\"\n title=\"View details\">\n <i class=\"fa-solid fa-external-link\"></i>\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n <!-- Cache Expansion Panel -->\n @if (record.IsSaved && record.EnableCaching) {\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-database\" style=\"color: var(--mj-text-muted);\"></i>\n Result Cache\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: AI Result Cache','AIPromptID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: AI Result Cache')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n </mj-accordion-panel>\n }\n <!-- Related Items Expansion Panel -->\n @if (record.IsSaved) {\n <mj-accordion-panel\n [Expanded]=\"false\"\n style=\"margin-bottom: 12px;\">\n <ng-template mjAccordionTitle>\n <span style=\"display: flex; align-items: center; gap: 8px; font-weight: 600;\">\n <i class=\"fa-solid fa-link\" style=\"color: var(--mj-text-muted);\"></i>\n Related Items\n </span>\n </ng-template>\n <!-- Direct Content Projection -->\n <div style=\"padding: 16px 0;\">\n <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 20px;\">\n <!-- AI Agents -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: var(--mj-text-secondary);\">AI Agents Using This Prompt</h6>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: AI Agent Prompts','PromptID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: AI Agent Prompts')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n <!-- Result Selector References -->\n <div>\n <h6 style=\"margin: 0 0 12px 0; color: var(--mj-text-secondary);\">Prompts Using This as Result Selector</h6>\n <mj-explorer-entity-data-grid\n [Params]=\"BuildRelationshipViewParamsByEntityName('MJ: AI Prompts','ResultSelectorPromptID')\"\n [NewRecordValues]=\"NewRecordValues('MJ: AI Prompts')\"\n [AllowLoad]=\"true\"\n [ShowToolbar]=\"false\">\n </mj-explorer-entity-data-grid>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n }\n </div>\n </div>\n </form>\n</mj-record-form-container>\n}\n\n\n<!-- AI Prompt Test Harness -->\n@if (showTestHarness) {\n <mj-window\n [Width]=\"1200\"\n [Height]=\"800\"\n [MinWidth]=\"800\"\n [MinHeight]=\"600\"\n [Draggable]=\"true\"\n [Resizable]=\"true\"\n [Visible]=\"true\"\n (Close)=\"onTestHarnessVisibilityChanged(false)\"\n [Title]=\"'Run AI Prompt - ' + (record.Name || 'Untitled')\">\n <mj-ai-test-harness\n [entity]=\"record\"\n [mode]=\"'prompt'\"\n [isVisible]=\"showTestHarness\"\n (visibilityChange)=\"onTestHarnessVisibilityChanged($event)\">\n </mj-ai-test-harness>\n </mj-window>\n}", styles: ["/* Override shared form-styles to enable flex layout */\n:host {\n display: block;\n height: 100%;\n}\n\n.record-form-container {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n padding: 10px;\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n overflow: hidden;\n}\n\n.record-form {\n min-height: 0 !important;\n}\n\n.custom-toolbar-actions {\n margin-left: auto;\n}\n\n.status-badge {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n font-weight: 500;\n letter-spacing: 0.02em;\n}\n\n.config-summary {\n position: sticky;\n top: 0;\n max-height: 600px;\n overflow-y: auto;\n}\n\n.config-item {\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.config-item:last-child {\n border-bottom: none;\n}\n\n.template-tab-content {\n background: var(--mj-bg-surface);\n}\n\n.template-header h5 {\n font-size: 1.1em;\n}\n\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n}\n\n/* Template-editor placeholders fill the editor pane */\nmj-empty-state.no-template-state,\nmj-empty-state.invalid-template-state {\n flex: 1;\n}\n\n.template-editor-container {\n background: var(--mj-bg-surface);\n border-radius: var(--mj-radius-md);\n}\n\n/* Grid layout adjustments */\n@media (max-width: 1200px) {\n .record-form-container .mj-tab-body > div {\n grid-template-columns: 1fr !important;\n gap: 20px;\n }\n\n .config-summary {\n order: -1;\n position: static;\n max-height: none;\n }\n}\n\n/* Responsive toolbar */\n@media (max-width: 768px) {\n .custom-toolbar-actions {\n flex-direction: column;\n gap: 4px !important;\n }\n\n .status-badge {\n align-self: flex-start;\n }\n}\n\n/* Ensure proper spacing in form sections */\n.record-form-container mj-form-section {\n padding: 16px;\n}\n\n/* Smooth transitions for better UX */\n.status-badge,\n.config-item,\n.template-header {\n transition: all 0.2s ease;\n}\n\n.config-item:hover {\n background-color: var(--mj-bg-surface-sunken);\n border-radius: var(--mj-radius-sm);\n margin: 0 -8px;\n padding: 8px;\n}\n\n/* Execution History Table Styles */\n.history-row {\n transition: background 0.2s;\n}\n\n.history-row:not(.even-row) {\n background: var(--mj-bg-surface-card);\n}\n\n.history-row.even-row {\n background: var(--mj-bg-surface);\n}\n\n.history-row:hover {\n background: var(--mj-border-default) !important;\n}\n\n/* Template Parameters Styles */\n.parameter-card {\n position: relative;\n overflow: hidden;\n}\n\n.parameter-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 4px;\n background: inherit;\n transition: width 0.2s;\n}\n\n.parameter-card:hover {\n transform: translateY(-2px);\n box-shadow: var(--mj-shadow-md);\n}\n\n.parameter-card:hover::before {\n width: 6px;\n}\n\n.type-badge {\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.03em;\n transition: transform 0.2s;\n}\n\n.parameter-card:hover .type-badge {\n transform: scale(1.05);\n}\n\n/* Parameter type icons animation */\n.parameter-card i.fa-solid {\n transition: transform 0.3s;\n}\n\n.parameter-card:hover i.fa-solid {\n transform: rotate(360deg);\n}\n\n/* Grid responsive behavior */\n@media (max-width: 768px) {\n .parameter-card {\n margin-bottom: 8px;\n }\n\n .parameter-card h6 {\n font-size: 0.95em;\n }\n\n .type-badge {\n font-size: 0.7em !important;\n }\n}\n"] }]
|
|
3030
|
-
}], null, {
|
|
3472
|
+
}], null, { TemplateEditor: [{
|
|
3031
3473
|
type: ViewChild,
|
|
3032
3474
|
args: ['templateEditor']
|
|
3033
3475
|
}] }); })();
|
|
3034
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJAIPromptFormComponentExtended, { className: "MJAIPromptFormComponentExtended", filePath: "src/lib/custom/AIPrompts/ai-prompt-form.component.ts", lineNumber:
|
|
3476
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJAIPromptFormComponentExtended, { className: "MJAIPromptFormComponentExtended", filePath: "src/lib/custom/AIPrompts/ai-prompt-form.component.ts", lineNumber: 23 }); })();
|
|
3035
3477
|
//# sourceMappingURL=ai-prompt-form.component.js.map
|