@memberjunction/ng-core-entity-forms 6.2.0-edge.3 → 6.2.0-edge.5

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.
Files changed (179) hide show
  1. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +12 -0
  2. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  3. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +43 -26
  4. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  5. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +7 -1
  6. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
  7. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +191 -178
  8. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  9. package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.d.ts +48 -0
  10. package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.d.ts.map +1 -0
  11. package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.js +195 -0
  12. package/dist/lib/custom/AIPromptRuns/prompt-run-data-capture-note.component.js.map +1 -0
  13. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +324 -322
  14. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  15. package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts +16 -3
  16. package/dist/lib/custom/Conversations/conversation-overview.panel.d.ts.map +1 -1
  17. package/dist/lib/custom/Conversations/conversation-overview.panel.js +103 -43
  18. package/dist/lib/custom/Conversations/conversation-overview.panel.js.map +1 -1
  19. package/dist/lib/custom/Entities/entity-form.component.d.ts +8 -0
  20. package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
  21. package/dist/lib/custom/Entities/entity-form.component.js +18 -4
  22. package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
  23. package/dist/lib/custom/Files/file-form.component.d.ts +5 -5
  24. package/dist/lib/custom/Files/file-form.component.d.ts.map +1 -1
  25. package/dist/lib/custom/Files/file-form.component.js +227 -157
  26. package/dist/lib/custom/Files/file-form.component.js.map +1 -1
  27. package/dist/lib/custom/Files/file-form.logic.d.ts +24 -0
  28. package/dist/lib/custom/Files/file-form.logic.d.ts.map +1 -0
  29. package/dist/lib/custom/Files/file-form.logic.js +57 -0
  30. package/dist/lib/custom/Files/file-form.logic.js.map +1 -0
  31. package/dist/lib/custom/Lists/list-form.component.d.ts.map +1 -1
  32. package/dist/lib/custom/Lists/list-form.component.js +3 -2
  33. package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
  34. package/dist/lib/custom/Queries/query-form.component.js +2 -2
  35. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -1
  36. package/dist/lib/custom/RecordProcesses/record-process-form.component.js +6 -3
  37. package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -1
  38. package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts +3 -3
  39. package/dist/lib/custom/SearchScopes/searchscope-form.component.d.ts.map +1 -1
  40. package/dist/lib/custom/SearchScopes/searchscope-form.component.js +5 -7
  41. package/dist/lib/custom/SearchScopes/searchscope-form.component.js.map +1 -1
  42. package/dist/lib/custom/Templates/templates-form.component.js +2 -2
  43. package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts +34 -0
  44. package/dist/lib/custom/ai-agent-run/agent-run-cost-split.d.ts.map +1 -0
  45. package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js +33 -0
  46. package/dist/lib/custom/ai-agent-run/agent-run-cost-split.js.map +1 -0
  47. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +3 -0
  48. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
  49. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +261 -242
  50. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
  51. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
  52. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +8 -8
  53. package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
  54. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts +37 -5
  55. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts.map +1 -1
  56. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +155 -79
  57. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
  58. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts +8 -0
  59. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
  60. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +59 -8
  61. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
  62. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +34 -9
  63. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  64. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +164 -43
  65. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  66. package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js +3 -1
  67. package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js.map +1 -1
  68. package/dist/lib/custom/custom-forms.module.d.ts +82 -79
  69. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  70. package/dist/lib/custom/custom-forms.module.js +16 -2
  71. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  72. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
  73. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +65 -47
  74. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
  75. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +115 -117
  76. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
  77. package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.d.ts.map +1 -1
  78. package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.js +64 -24
  79. package/dist/lib/generated/Entities/MJAIAgentRunStep/mjaiagentrunstep.form.component.js.map +1 -1
  80. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js +74 -52
  81. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js.map +1 -1
  82. package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.d.ts +10 -0
  83. package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.d.ts.map +1 -0
  84. package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.js +86 -0
  85. package/dist/lib/generated/Entities/MJAIAgentSessionRecordingShard/mjaiagentsessionrecordingshard.form.component.js.map +1 -0
  86. package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.d.ts +10 -0
  87. package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.d.ts.map +1 -0
  88. package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.js +132 -0
  89. package/dist/lib/generated/Entities/MJAIAgentUserPolicy/mjaiagentuserpolicy.form.component.js.map +1 -0
  90. package/dist/lib/generated/Entities/MJAIBridgeAgentIdentity/mjaibridgeagentidentity.form.component.js +12 -10
  91. package/dist/lib/generated/Entities/MJAIBridgeAgentIdentity/mjaibridgeagentidentity.form.component.js.map +1 -1
  92. package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.d.ts.map +1 -1
  93. package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +86 -32
  94. package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
  95. package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.d.ts.map +1 -1
  96. package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.js +25 -7
  97. package/dist/lib/generated/Entities/MJAIPersona/mjaipersona.form.component.js.map +1 -1
  98. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
  99. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +180 -160
  100. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  101. package/dist/lib/generated/Entities/MJActionParam/mjactionparam.form.component.js +16 -14
  102. package/dist/lib/generated/Entities/MJActionParam/mjactionparam.form.component.js.map +1 -1
  103. package/dist/lib/generated/Entities/MJArchiveConfiguration/mjarchiveconfiguration.form.component.js +23 -21
  104. package/dist/lib/generated/Entities/MJArchiveConfiguration/mjarchiveconfiguration.form.component.js.map +1 -1
  105. package/dist/lib/generated/Entities/MJArchiveRun/mjarchiverun.form.component.js +21 -19
  106. package/dist/lib/generated/Entities/MJArchiveRun/mjarchiverun.form.component.js.map +1 -1
  107. package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js +30 -20
  108. package/dist/lib/generated/Entities/MJCommunicationProvider/mjcommunicationprovider.form.component.js.map +1 -1
  109. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.d.ts.map +1 -1
  110. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +32 -14
  111. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
  112. package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.d.ts +10 -0
  113. package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.d.ts.map +1 -0
  114. package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.js +111 -0
  115. package/dist/lib/generated/Entities/MJConversationBranch/mjconversationbranch.form.component.js.map +1 -0
  116. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.d.ts.map +1 -1
  117. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js +59 -67
  118. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js.map +1 -1
  119. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
  120. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +35 -17
  121. package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
  122. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  123. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +112 -94
  124. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  125. package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.d.ts +10 -0
  126. package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.d.ts.map +1 -0
  127. package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.js +130 -0
  128. package/dist/lib/generated/Entities/MJFeaturePipelineVersion/mjfeaturepipelineversion.form.component.js.map +1 -0
  129. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js +26 -14
  130. package/dist/lib/generated/Entities/MJFeatureValue/mjfeaturevalue.form.component.js.map +1 -1
  131. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js +23 -19
  132. package/dist/lib/generated/Entities/MJFeatureValueCache/mjfeaturevaluecache.form.component.js.map +1 -1
  133. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +29 -27
  134. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
  135. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js +17 -15
  136. package/dist/lib/generated/Entities/MJProcessRunDetail/mjprocessrundetail.form.component.js.map +1 -1
  137. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
  138. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +27 -9
  139. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
  140. package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.d.ts +10 -0
  141. package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.d.ts.map +1 -0
  142. package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.js +106 -0
  143. package/dist/lib/generated/Entities/MJScopedNotificationConfig/mjscopednotificationconfig.form.component.js.map +1 -0
  144. package/dist/lib/generated/Entities/MJTest/mjtest.form.component.d.ts.map +1 -1
  145. package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js +24 -6
  146. package/dist/lib/generated/Entities/MJTest/mjtest.form.component.js.map +1 -1
  147. package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.d.ts.map +1 -1
  148. package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.js +29 -11
  149. package/dist/lib/generated/Entities/MJTestRun/mjtestrun.form.component.js.map +1 -1
  150. package/dist/lib/generated/Entities/MJTheme/mjtheme.form.component.d.ts.map +1 -1
  151. package/dist/lib/generated/Entities/MJTheme/mjtheme.form.component.js +13 -3
  152. package/dist/lib/generated/Entities/MJTheme/mjtheme.form.component.js.map +1 -1
  153. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
  154. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +788 -714
  155. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
  156. package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.d.ts.map +1 -1
  157. package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.js +24 -6
  158. package/dist/lib/generated/Entities/MJUserNotificationType/mjusernotificationtype.form.component.js.map +1 -1
  159. package/dist/lib/generated/Entities/MJUserRoutine/mjuserroutine.form.component.js +31 -25
  160. package/dist/lib/generated/Entities/MJUserRoutine/mjuserroutine.form.component.js.map +1 -1
  161. package/dist/lib/generated/generated-forms.module.d.ts +286 -281
  162. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  163. package/dist/lib/generated/generated-forms.module.js +15 -0
  164. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  165. package/dist/lib/panels/feature-values/feature-values.logic.d.ts +55 -0
  166. package/dist/lib/panels/feature-values/feature-values.logic.d.ts.map +1 -0
  167. package/dist/lib/panels/feature-values/feature-values.logic.js +88 -0
  168. package/dist/lib/panels/feature-values/feature-values.logic.js.map +1 -0
  169. package/dist/lib/panels/feature-values/feature-values.panel.d.ts +39 -0
  170. package/dist/lib/panels/feature-values/feature-values.panel.d.ts.map +1 -0
  171. package/dist/lib/panels/feature-values/feature-values.panel.js +303 -0
  172. package/dist/lib/panels/feature-values/feature-values.panel.js.map +1 -0
  173. package/dist/lib/shared/components/template-editor.component.js +2 -2
  174. package/dist/lib/shared/components/template-editor.component.js.map +1 -1
  175. package/dist/public-api.d.ts +1 -0
  176. package/dist/public-api.d.ts.map +1 -1
  177. package/dist/public-api.js +1 -0
  178. package/dist/public-api.js.map +1 -1
  179. package/package.json +48 -47
@@ -8,6 +8,8 @@ import { Component, ViewChild, inject } from '@angular/core';
8
8
  import { Subject } from 'rxjs';
9
9
  import { BaseEntity, CompositeKey, LogError, ResolveEntityEventRow } from '@memberjunction/core';
10
10
  import { LoadAgentRunTree, MAX_AGENT_RUN_TREE_DEPTH, WalkAgentRunTree, } from '@memberjunction/ai-core-plus';
11
+ import { WorkflowSaveOperation } from '@memberjunction/core-entities';
12
+ import { AIEngineBase } from '@memberjunction/ai-engine-base';
11
13
  import { BaseFormComponent } from '@memberjunction/ng-base-forms';
12
14
  import { MJGlobal, MJEventType, RegisterClass, UUIDsEqual } from '@memberjunction/global';
13
15
  import { SharedService, NavigationService } from '@memberjunction/ng-shared';
@@ -215,20 +217,20 @@ function MJAIAgentRunFormComponentExtended_Conditional_40_Template(rf, ctx) { if
215
217
  function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template(rf, ctx) { if (rf & 1) {
216
218
  const _r7 = i0.ɵɵgetCurrentView();
217
219
  i0.ɵɵelementStart(0, "as-split-area", 53)(1, "mj-ai-agent-run-step-detail", 55);
218
- i0.ɵɵlistener("closePanel", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_closePanel_1_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.closeJsonPanel()); })("navigateToActionLog", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_navigateToActionLog_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.navigateToActionLog($event)); })("copyToClipboard", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_copyToClipboard_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.copyToClipboard($event)); });
220
+ i0.ɵɵlistener("closePanel", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_closePanel_1_listener() { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.closeJsonPanel()); })("navigateToActionLog", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_navigateToActionLog_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.navigateToActionLog($event)); })("copyToClipboard", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_copyToClipboard_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.copyToClipboard($event)); })("SaveAsWorkflowRequested", function MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template_mj_ai_agent_run_step_detail_SaveAsWorkflowRequested_1_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.OnSaveAsWorkflowRequested($event)); });
219
221
  i0.ɵɵelementEnd()();
220
222
  } if (rf & 2) {
221
223
  const ctx_r0 = i0.ɵɵnextContext(2);
222
224
  i0.ɵɵproperty("size", 45);
223
225
  i0.ɵɵadvance();
224
- i0.ɵɵproperty("selectedTimelineItem", ctx_r0.selectedTimelineItem)("Provider", ctx_r0.ProviderToUse);
226
+ i0.ɵɵproperty("selectedTimelineItem", ctx_r0.selectedTimelineItem)("Provider", ctx_r0.ProviderToUse)("SavingWorkflow", ctx_r0.SavingWorkflow);
225
227
  } }
226
228
  function MJAIAgentRunFormComponentExtended_Conditional_55_Template(rf, ctx) { if (rf & 1) {
227
229
  const _r6 = i0.ɵɵgetCurrentView();
228
230
  i0.ɵɵelementStart(0, "div", 35)(1, "as-split", 52)(2, "as-split-area", 53)(3, "mj-ai-agent-run-timeline", 54);
229
231
  i0.ɵɵlistener("itemSelected", function MJAIAgentRunFormComponentExtended_Conditional_55_Template_mj_ai_agent_run_timeline_itemSelected_3_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.selectTimelineItem($event)); })("navigateToEntity", function MJAIAgentRunFormComponentExtended_Conditional_55_Template_mj_ai_agent_run_timeline_navigateToEntity_3_listener($event) { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.navigateToEntityRecord($event)); });
230
232
  i0.ɵɵelementEnd()();
231
- i0.ɵɵconditionalCreate(4, MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template, 2, 3, "as-split-area", 53);
233
+ i0.ɵɵconditionalCreate(4, MJAIAgentRunFormComponentExtended_Conditional_55_Conditional_4_Template, 2, 4, "as-split-area", 53);
232
234
  i0.ɵɵelementEnd()();
233
235
  } if (rf & 2) {
234
236
  const ctx_r0 = i0.ɵɵnextContext();
@@ -739,7 +741,7 @@ function MJAIAgentRunFormComponentExtended_Conditional_58_Template(rf, ctx) { if
739
741
  i0.ɵɵadvance(6);
740
742
  i0.ɵɵtextInterpolate(ctx_r0.record.TotalPromptIterations != null ? i0.ɵɵpipeBind2(102, 45, ctx_r0.record.TotalPromptIterations, "1.0-0") : "N/A");
741
743
  i0.ɵɵadvance(2);
742
- i0.ɵɵconditional(ctx_r0.record.Result ? 103 : -1);
744
+ i0.ɵɵconditional(ctx_r0.ShowResultPanel ? 103 : -1);
743
745
  i0.ɵɵadvance();
744
746
  i0.ɵɵconditional(ctx_r0.record.StartingPayload ? 104 : -1);
745
747
  i0.ɵɵadvance();
@@ -790,6 +792,18 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
790
792
  this._cachedParsedStartingPayload = null;
791
793
  this._cachedParsedFinalPayload = null;
792
794
  this._cachedParsedData = null;
795
+ this._cachedStartingPayloadRaw = undefined;
796
+ this._cachedStartingPayloadObject = null;
797
+ this._cachedFinalPayloadRaw = undefined;
798
+ this._cachedFinalPayloadObject = null;
799
+ this._cachedStepStartRaw = undefined;
800
+ this._cachedStepStartItem = null;
801
+ this._cachedStepPayloadAtStartObject = null;
802
+ this._cachedStepEndRaw = undefined;
803
+ this._cachedStepEndItem = null;
804
+ this._cachedStepPayloadAtEndObject = null;
805
+ this._lastRunTreeForWorkflowRunning = null;
806
+ this._cachedWorkflowStillRunning = false;
793
807
  // Simple parsing state - true when all parsing is complete
794
808
  this._allParsingComplete = false;
795
809
  // Field injections
@@ -812,6 +826,8 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
812
826
  this.RunTreeLoading = false;
813
827
  /** Why the tree could not be loaded, or null. Surfaced rather than swallowed. */
814
828
  this.RunTreeError = null;
829
+ /** True while a workflow is being saved via `WorkflowSaveOperation`. */
830
+ this.SavingWorkflow = false;
815
831
  }
816
832
  /** @deprecated Use {@link ActiveTab}. */
817
833
  get activeTab() {
@@ -969,13 +985,20 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
969
985
  get WorkflowStillRunning() {
970
986
  if (!this.RunTree)
971
987
  return false;
972
- for (const node of WalkAgentRunTree(this.RunTree)) {
973
- if (node.NodeType !== 'Task' && node.NodeType !== 'TaskGraph')
974
- continue;
975
- if (!TERMINAL_TASK_STATUSES.has(node.Status))
976
- return true;
988
+ if (this._lastRunTreeForWorkflowRunning !== this.RunTree) {
989
+ this._lastRunTreeForWorkflowRunning = this.RunTree;
990
+ let stillRunning = false;
991
+ for (const node of WalkAgentRunTree(this.RunTree)) {
992
+ if (node.NodeType !== 'Task' && node.NodeType !== 'TaskGraph')
993
+ continue;
994
+ if (!TERMINAL_TASK_STATUSES.has(node.Status)) {
995
+ stillRunning = true;
996
+ break;
997
+ }
998
+ }
999
+ this._cachedWorkflowStillRunning = stillRunning;
977
1000
  }
978
- return false;
1001
+ return this._cachedWorkflowStillRunning;
979
1002
  }
980
1003
  /**
981
1004
  * Re-reads the tree while a detached workflow is still moving, and stops when it settles.
@@ -1005,10 +1028,12 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1005
1028
  async ngOnInit() {
1006
1029
  await super.ngOnInit();
1007
1030
  if (this.record && this.record.ID) {
1008
- await this.DataHelper.loadAgentRunData(this.record.ID);
1009
- await this.loadRunTree();
1010
- await this.loadAgent();
1011
- await this.loadCostMetrics();
1031
+ await Promise.all([
1032
+ this.DataHelper.loadAgentRunData(this.record.ID),
1033
+ this.loadRunTree(),
1034
+ this.loadAgent(),
1035
+ this.loadCostMetrics()
1036
+ ]);
1012
1037
  // Parse all JSON fields on form load for instant access later
1013
1038
  this.parseAllFields();
1014
1039
  // If the run is in progress, subscribe to BaseEntity events so we
@@ -1190,6 +1215,12 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1190
1215
  if (!this.record?.AgentID)
1191
1216
  return;
1192
1217
  try {
1218
+ const cachedAgent = AIEngineBase.Instance?.Agents?.find(a => UUIDsEqual(a.ID, this.record.AgentID));
1219
+ if (cachedAgent) {
1220
+ this.Agent = cachedAgent;
1221
+ this.cdr.detectChanges();
1222
+ return;
1223
+ }
1193
1224
  const md = this.ProviderToUse;
1194
1225
  const agent = await md.GetEntityObject('MJ: AI Agents');
1195
1226
  if (agent && await agent.Load(this.record.AgentID)) {
@@ -1379,6 +1410,44 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1379
1410
  async copyToClipboard(text) {
1380
1411
  return this.CopyToClipboard(text);
1381
1412
  }
1413
+ /**
1414
+ * Persists the selected `TaskGraph` step's `TaskGraphSpec` as a Draft Flow Agent workflow
1415
+ * via `WorkflowSaveOperation` and opens the resulting `MJ: AI Agents` record.
1416
+ */
1417
+ async OnSaveAsWorkflowRequested(spec) {
1418
+ if (!spec || this.SavingWorkflow) {
1419
+ return;
1420
+ }
1421
+ this.SavingWorkflow = true;
1422
+ try {
1423
+ const name = spec.workflowName?.trim() ||
1424
+ this.SelectedTimelineItem?.title?.trim() ||
1425
+ (this.Agent?.Name ? `${this.Agent.Name} Workflow` : 'Saved Workflow');
1426
+ const workflowSpec = {
1427
+ name,
1428
+ description: `Saved from AI Agent Run ${this.record?.ID ?? ''}`.trim(),
1429
+ status: 'Draft',
1430
+ graph: { ...spec, workflowName: name },
1431
+ triggers: [],
1432
+ };
1433
+ const op = new WorkflowSaveOperation();
1434
+ const result = await op.Execute({ spec: workflowSpec }, { provider: this.ProviderToUse, user: this.ProviderToUse.CurrentUser });
1435
+ const output = result.Output;
1436
+ if (!result.Success || !output?.success || !output.agentID) {
1437
+ SharedService.Instance.CreateSimpleNotification(output?.errorMessage ?? result.ErrorMessage ?? 'Could not save workflow.', 'error', 5000);
1438
+ return;
1439
+ }
1440
+ SharedService.Instance.CreateSimpleNotification(`Saved workflow "${name}". Opening Flow Agent record…`, 'success', 3500);
1441
+ this.navigationService.OpenEntityRecord('MJ: AI Agents', CompositeKey.FromID(output.agentID));
1442
+ }
1443
+ catch (err) {
1444
+ const msg = err instanceof Error ? err.message : String(err);
1445
+ SharedService.Instance.CreateSimpleNotification(`Failed to save workflow: ${msg}`, 'error', 5000);
1446
+ }
1447
+ finally {
1448
+ this.SavingWorkflow = false;
1449
+ }
1450
+ }
1382
1451
  /**
1383
1452
  * Get the Result field with recursive JSON parsing applied
1384
1453
  */
@@ -1557,18 +1626,23 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1557
1626
  * Get parsed Starting Payload as an object for deep diff
1558
1627
  */
1559
1628
  get StartingPayloadObject() {
1560
- if (!this.record?.StartingPayload)
1629
+ const raw = this.record?.StartingPayload;
1630
+ if (!raw)
1561
1631
  return null;
1632
+ if (this._cachedStartingPayloadRaw === raw && this._cachedStartingPayloadObject !== null) {
1633
+ return this._cachedStartingPayloadObject;
1634
+ }
1635
+ this._cachedStartingPayloadRaw = raw;
1562
1636
  try {
1563
1637
  // First, check if StartingPayload is a JSON string that needs to be parsed
1564
- let payloadData = this.record.StartingPayload;
1638
+ let payloadData = raw;
1565
1639
  try {
1566
1640
  // If StartingPayload is a JSON string, parse it first
1567
- payloadData = JSON.parse(this.record.StartingPayload);
1641
+ payloadData = JSON.parse(raw);
1568
1642
  }
1569
1643
  catch {
1570
1644
  // If it's not valid JSON, use it as-is
1571
- payloadData = this.record.StartingPayload;
1645
+ payloadData = raw;
1572
1646
  }
1573
1647
  const parseOptions = {
1574
1648
  extractInlineJson: true,
@@ -1576,9 +1650,11 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1576
1650
  debug: false
1577
1651
  };
1578
1652
  // Re-enabled ParseJSONRecursive with performance optimizations
1579
- return ParseJSONRecursive(payloadData, parseOptions);
1653
+ this._cachedStartingPayloadObject = ParseJSONRecursive(payloadData, parseOptions);
1654
+ return this._cachedStartingPayloadObject;
1580
1655
  }
1581
- catch (e) {
1656
+ catch {
1657
+ this._cachedStartingPayloadObject = null;
1582
1658
  return null;
1583
1659
  }
1584
1660
  }
@@ -1590,18 +1666,23 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1590
1666
  * Get parsed Final Payload as an object for deep diff
1591
1667
  */
1592
1668
  get FinalPayloadObject() {
1593
- if (!this.record?.FinalPayload)
1669
+ const raw = this.record?.FinalPayload;
1670
+ if (!raw)
1594
1671
  return null;
1672
+ if (this._cachedFinalPayloadRaw === raw && this._cachedFinalPayloadObject !== null) {
1673
+ return this._cachedFinalPayloadObject;
1674
+ }
1675
+ this._cachedFinalPayloadRaw = raw;
1595
1676
  try {
1596
1677
  // First, check if FinalPayload is a JSON string that needs to be parsed
1597
- let payloadData = this.record.FinalPayload;
1678
+ let payloadData = raw;
1598
1679
  try {
1599
1680
  // If FinalPayload is a JSON string, parse it first
1600
- payloadData = JSON.parse(this.record.FinalPayload);
1681
+ payloadData = JSON.parse(raw);
1601
1682
  }
1602
1683
  catch {
1603
1684
  // If it's not valid JSON, use it as-is
1604
- payloadData = this.record.FinalPayload;
1685
+ payloadData = raw;
1605
1686
  }
1606
1687
  const parseOptions = {
1607
1688
  extractInlineJson: true,
@@ -1609,9 +1690,11 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1609
1690
  debug: false
1610
1691
  };
1611
1692
  // Re-enabled ParseJSONRecursive with performance optimizations
1612
- return ParseJSONRecursive(payloadData, parseOptions);
1693
+ this._cachedFinalPayloadObject = ParseJSONRecursive(payloadData, parseOptions);
1694
+ return this._cachedFinalPayloadObject;
1613
1695
  }
1614
- catch (e) {
1696
+ catch {
1697
+ this._cachedFinalPayloadObject = null;
1615
1698
  return null;
1616
1699
  }
1617
1700
  }
@@ -1627,6 +1710,17 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1627
1710
  this._cachedParsedStartingPayload = null;
1628
1711
  this._cachedParsedFinalPayload = null;
1629
1712
  this._cachedParsedData = null;
1713
+ this._cachedStartingPayloadRaw = undefined;
1714
+ this._cachedStartingPayloadObject = null;
1715
+ this._cachedFinalPayloadRaw = undefined;
1716
+ this._cachedFinalPayloadObject = null;
1717
+ this._cachedStepStartRaw = undefined;
1718
+ this._cachedStepStartItem = null;
1719
+ this._cachedStepPayloadAtStartObject = null;
1720
+ this._cachedStepEndRaw = undefined;
1721
+ this._cachedStepEndItem = null;
1722
+ this._cachedStepPayloadAtEndObject = null;
1723
+ this._lastRunTreeForWorkflowRunning = null;
1630
1724
  this._allParsingComplete = false;
1631
1725
  }
1632
1726
  /**
@@ -1635,8 +1729,8 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1635
1729
  parseAllFields() {
1636
1730
  try {
1637
1731
  let parsedCount = 0;
1638
- // Parse all fields that exist
1639
- if (this.record?.Result) {
1732
+ // Parse each field whose panel is shown
1733
+ if (this.ShowResultPanel) {
1640
1734
  this.ParsedResult; // Triggers parsing and caching
1641
1735
  parsedCount++;
1642
1736
  }
@@ -1678,6 +1772,13 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1678
1772
  get showPayloadDiff() {
1679
1773
  return this.ShowPayloadDiff;
1680
1774
  }
1775
+ /**
1776
+ * True for an older run that has `Result` but no `FinalPayload`. When `FinalPayload` is set it
1777
+ * holds the same JSON and has its own panel.
1778
+ */
1779
+ get ShowResultPanel() {
1780
+ return !!this.record?.Result && !this.record?.FinalPayload;
1781
+ }
1681
1782
  /**
1682
1783
  * Check if selected timeline item is a step with payload changes
1683
1784
  */
@@ -1706,16 +1807,24 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1706
1807
  return null;
1707
1808
  }
1708
1809
  const stepData = this.SelectedTimelineItem.data;
1709
- if (!stepData || !stepData.PayloadAtStart) {
1810
+ const raw = stepData?.PayloadAtStart;
1811
+ if (!raw) {
1710
1812
  return null;
1711
1813
  }
1814
+ if (this._cachedStepStartItem === this.SelectedTimelineItem &&
1815
+ this._cachedStepStartRaw === raw &&
1816
+ this._cachedStepPayloadAtStartObject !== null) {
1817
+ return this._cachedStepPayloadAtStartObject;
1818
+ }
1819
+ this._cachedStepStartItem = this.SelectedTimelineItem;
1820
+ this._cachedStepStartRaw = raw;
1712
1821
  try {
1713
- let payloadData = stepData.PayloadAtStart;
1822
+ let payloadData = raw;
1714
1823
  try {
1715
- payloadData = JSON.parse(stepData.PayloadAtStart);
1824
+ payloadData = JSON.parse(raw);
1716
1825
  }
1717
1826
  catch {
1718
- payloadData = stepData.PayloadAtStart;
1827
+ payloadData = raw;
1719
1828
  }
1720
1829
  const parseOptions = {
1721
1830
  extractInlineJson: true,
@@ -1723,9 +1832,11 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1723
1832
  debug: false
1724
1833
  };
1725
1834
  // Re-enabled ParseJSONRecursive with performance optimizations
1726
- return ParseJSONRecursive(payloadData, parseOptions);
1835
+ this._cachedStepPayloadAtStartObject = ParseJSONRecursive(payloadData, parseOptions);
1836
+ return this._cachedStepPayloadAtStartObject;
1727
1837
  }
1728
- catch (e) {
1838
+ catch {
1839
+ this._cachedStepPayloadAtStartObject = null;
1729
1840
  return null;
1730
1841
  }
1731
1842
  }
@@ -1741,16 +1852,24 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1741
1852
  return null;
1742
1853
  }
1743
1854
  const stepData = this.SelectedTimelineItem.data;
1744
- if (!stepData || !stepData.PayloadAtEnd) {
1855
+ const raw = stepData?.PayloadAtEnd;
1856
+ if (!raw) {
1745
1857
  return null;
1746
1858
  }
1859
+ if (this._cachedStepEndItem === this.SelectedTimelineItem &&
1860
+ this._cachedStepEndRaw === raw &&
1861
+ this._cachedStepPayloadAtEndObject !== null) {
1862
+ return this._cachedStepPayloadAtEndObject;
1863
+ }
1864
+ this._cachedStepEndItem = this.SelectedTimelineItem;
1865
+ this._cachedStepEndRaw = raw;
1747
1866
  try {
1748
- let payloadData = stepData.PayloadAtEnd;
1867
+ let payloadData = raw;
1749
1868
  try {
1750
- payloadData = JSON.parse(stepData.PayloadAtEnd);
1869
+ payloadData = JSON.parse(raw);
1751
1870
  }
1752
1871
  catch {
1753
- payloadData = stepData.PayloadAtEnd;
1872
+ payloadData = raw;
1754
1873
  }
1755
1874
  const parseOptions = {
1756
1875
  extractInlineJson: true,
@@ -1758,9 +1877,11 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1758
1877
  debug: false
1759
1878
  };
1760
1879
  // Re-enabled ParseJSONRecursive with performance optimizations
1761
- return ParseJSONRecursive(payloadData, parseOptions);
1880
+ this._cachedStepPayloadAtEndObject = ParseJSONRecursive(payloadData, parseOptions);
1881
+ return this._cachedStepPayloadAtEndObject;
1762
1882
  }
1763
- catch (e) {
1883
+ catch {
1884
+ this._cachedStepPayloadAtEndObject = null;
1764
1885
  return null;
1765
1886
  }
1766
1887
  }
@@ -1775,7 +1896,7 @@ let MJAIAgentRunFormComponentExtended = class MJAIAgentRunFormComponentExtended
1775
1896
  let _t;
1776
1897
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.TimelineComponent = _t.first);
1777
1898
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.AnalyticsComponent = _t.first);
1778
- } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 59, vars: 35, consts: [["analyticsComponent", ""], [1, "record-form-container", "ai-agent-run-form"], [1, "record-form"], [1, "header"], [1, "header-content"], [1, "header-left"], [1, "icon-wrapper"], [1, "agent-logo", 3, "src", "alt"], [1, "fas", 3, "ngClass"], [1, "fas", "fa-robot"], [1, "header-info"], [1, "meta-info"], [1, "agent-name"], [1, "run-id"], [1, "parent-run"], ["title", "Open conversation in Chat app", 1, "conversation-pill"], [1, "header-right"], ["title", "This run executed in Plan Mode \u2014 the agent presented a plan for human approval before executing actions or sub-agents", 1, "plan-mode-badge"], [1, "status-badge"], ["title", "This run submitted a workflow that runs on the dispatcher. The run finished when the workflow was submitted; the workflow itself is still going. This view refreshes on its own.", 1, "workflow-running-badge"], [1, "header-actions"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sync-alt"], [1, "header-stats"], [1, "stat"], [1, "label"], [1, "value"], [1, "configuration-bar"], [1, "tabs"], [1, "tab", 3, "click"], [1, "fas", "fa-stream"], [1, "fas", "fa-diagram-project"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-info-circle"], [1, "content-area"], [1, "tab-content", 2, "height", "100%"], [1, "tab-content"], ["href", "javascript:void(0)", 1, "entity-link", 3, "click"], [1, "fas", "fa-level-up-alt"], [1, "parent-link", 3, "click"], ["title", "Open conversation in Chat app", 1, "conversation-pill", 3, "click"], [1, "fas", "fa-comments"], [1, "fas", "fa-external-link-alt", "pill-action"], [1, "fas", "fa-clipboard-check"], [1, "fas", "fa-circle-notch", "fa-spin"], [1, "value", "loading"], [1, "fas", "fa-spinner", "fa-spin"], [1, "config-item"], [1, "fas", "fa-cog"], [1, "config-content"], [1, "config-label"], [1, "config-value"], ["direction", "horizontal", 2, "height", "100%"], [3, "size"], [3, "itemSelected", "navigateToEntity", "aiAgentRunId", "dataHelper", "RunTree"], [3, "closePanel", "navigateToActionLog", "copyToClipboard", "selectedTimelineItem", "Provider"], [3, "aiAgentRunId", "dataHelper", "agentName", "runStatus", "agentIconClass", "agentLogoUrl", "RunTree"], [3, "agentRunId", "RunTree"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "details-grid"], [1, "detail-item"], ["href", "javascript:void(0)", 1, "entity-link"], [1, "success"], [1, "error-message"], [1, "detail-item", "full-width"], [1, "fas", "fa-cogs"], [1, "fas", "fa-tasks"], [1, "message"], [1, "fas", "fa-dollar-sign"], [1, "result-viewer"], [2, "height", "300px", "width", "100%", 3, "ngModel", "language", "readonly"], [2, "padding", "20px", "text-align", "center", "color", "var(--mj-text-muted)"], [1, "fas", "fa-code"], [1, "fas", "fa-upload"], [1, "fas", "fa-database"], [1, "fas", "fa-download"], [2, "padding", "20px", "background", "var(--mj-bg-surface-card)"], [3, "oldValue", "newValue", "title", "showSummary", "showUnchanged", "expandAll", "maxDepth", "maxStringLength", "treatNullAsUndefined"], [1, "fas", "fa-code-compare"]], template: function MJAIAgentRunFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
1899
+ } }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 59, vars: 35, consts: [["analyticsComponent", ""], [1, "record-form-container", "ai-agent-run-form"], [1, "record-form"], [1, "header"], [1, "header-content"], [1, "header-left"], [1, "icon-wrapper"], [1, "agent-logo", 3, "src", "alt"], [1, "fas", 3, "ngClass"], [1, "fas", "fa-robot"], [1, "header-info"], [1, "meta-info"], [1, "agent-name"], [1, "run-id"], [1, "parent-run"], ["title", "Open conversation in Chat app", 1, "conversation-pill"], [1, "header-right"], ["title", "This run executed in Plan Mode \u2014 the agent presented a plan for human approval before executing actions or sub-agents", 1, "plan-mode-badge"], [1, "status-badge"], ["title", "This run submitted a workflow that runs on the dispatcher. The run finished when the workflow was submitted; the workflow itself is still going. This view refreshes on its own.", 1, "workflow-running-badge"], [1, "header-actions"], ["title", "Refresh", 1, "btn-icon", 3, "click"], [1, "fas", "fa-sync-alt"], [1, "header-stats"], [1, "stat"], [1, "label"], [1, "value"], [1, "configuration-bar"], [1, "tabs"], [1, "tab", 3, "click"], [1, "fas", "fa-stream"], [1, "fas", "fa-diagram-project"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-info-circle"], [1, "content-area"], [1, "tab-content", 2, "height", "100%"], [1, "tab-content"], ["href", "javascript:void(0)", 1, "entity-link", 3, "click"], [1, "fas", "fa-level-up-alt"], [1, "parent-link", 3, "click"], ["title", "Open conversation in Chat app", 1, "conversation-pill", 3, "click"], [1, "fas", "fa-comments"], [1, "fas", "fa-external-link-alt", "pill-action"], [1, "fas", "fa-clipboard-check"], [1, "fas", "fa-circle-notch", "fa-spin"], [1, "value", "loading"], [1, "fas", "fa-spinner", "fa-spin"], [1, "config-item"], [1, "fas", "fa-cog"], [1, "config-content"], [1, "config-label"], [1, "config-value"], ["direction", "horizontal", 2, "height", "100%"], [3, "size"], [3, "itemSelected", "navigateToEntity", "aiAgentRunId", "dataHelper", "RunTree"], [3, "closePanel", "navigateToActionLog", "copyToClipboard", "SaveAsWorkflowRequested", "selectedTimelineItem", "Provider", "SavingWorkflow"], [3, "aiAgentRunId", "dataHelper", "agentName", "runStatus", "agentIconClass", "agentLogoUrl", "RunTree"], [3, "agentRunId", "RunTree"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "details-grid"], [1, "detail-item"], ["href", "javascript:void(0)", 1, "entity-link"], [1, "success"], [1, "error-message"], [1, "detail-item", "full-width"], [1, "fas", "fa-cogs"], [1, "fas", "fa-tasks"], [1, "message"], [1, "fas", "fa-dollar-sign"], [1, "result-viewer"], [2, "height", "300px", "width", "100%", 3, "ngModel", "language", "readonly"], [2, "padding", "20px", "text-align", "center", "color", "var(--mj-text-muted)"], [1, "fas", "fa-code"], [1, "fas", "fa-upload"], [1, "fas", "fa-database"], [1, "fas", "fa-download"], [2, "padding", "20px", "background", "var(--mj-bg-surface-card)"], [3, "oldValue", "newValue", "title", "showSummary", "showUnchanged", "expandAll", "maxDepth", "maxStringLength", "treatNullAsUndefined"], [1, "fas", "fa-code-compare"]], template: function MJAIAgentRunFormComponentExtended_Template(rf, ctx) { if (rf & 1) {
1779
1900
  i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3)(3, "div", 4)(4, "div", 5)(5, "div", 6);
1780
1901
  i0.ɵɵconditionalCreate(6, MJAIAgentRunFormComponentExtended_Conditional_6_Template, 1, 2, "img", 7);
1781
1902
  i0.ɵɵconditionalCreate(7, MJAIAgentRunFormComponentExtended_Conditional_7_Template, 1, 1, "i", 8);
@@ -1910,7 +2031,7 @@ MJAIAgentRunFormComponentExtended = __decorate([
1910
2031
  export { MJAIAgentRunFormComponentExtended };
1911
2032
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJAIAgentRunFormComponentExtended, [{
1912
2033
  type: Component,
1913
- args: [{ standalone: false, selector: 'mj-ai-agent-run-form', template: "<div class=\"record-form-container ai-agent-run-form\">\n <div class=\"record-form\">\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"icon-wrapper\">\n @if (agent && agent.LogoURL) {\n <img [src]=\"agent.LogoURL\" [alt]=\"agent.Name || 'Agent'\" class=\"agent-logo\" />\n }\n @if (agent && !agent.LogoURL && agent.IconClass) {\n <i class=\"fas\" [ngClass]=\"agent.IconClass\"></i>\n }\n @if (!agent || (!agent.LogoURL && !agent.IconClass)) {\n <i class=\"fas fa-robot\"></i>\n }\n </div>\n <div class=\"header-info\">\n <h2>AI Agent Run</h2>\n <div class=\"meta-info\">\n @if (agent) {\n <span class=\"agent-name\">\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agents', record.AgentID)\">\n {{ agent.Name }}\n </a>\n </span>\n }\n <span class=\"run-id\">{{ record.ID }}</span>\n @if (record.ParentRunID) {\n <span class=\"parent-run\">\n <i class=\"fas fa-level-up-alt\"></i>\n <a (click)=\"navigateToParentRun()\" class=\"parent-link\">Parent Run</a>\n </span>\n }\n <!-- Conversation Link Pill -->\n @if (record.ConversationID) {\n <span class=\"conversation-pill\" (click)=\"navigateToConversation()\" title=\"Open conversation in Chat app\">\n <i class=\"fas fa-comments\"></i>\n <span>Conversation</span>\n <i class=\"fas fa-external-link-alt pill-action\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-right\">\n @if (record.PlanMode) {\n <div class=\"plan-mode-badge\" title=\"This run executed in Plan Mode \u2014 the agent presented a plan for human approval before executing actions or sub-agents\">\n <i class=\"fas fa-clipboard-check\"></i>\n Plan Mode\n </div>\n }\n <div class=\"status-badge\" [attr.data-status]=\"record.Status\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon(record.Status || '')\"></i>\n {{ record.Status }}\n </div>\n <!-- A workflow outlives the run that submitted it, so a Completed run can still have work\n in flight. Said beside the status rather than instead of it \u2014 both are true. -->\n @if (WorkflowStillRunning) {\n <div class=\"workflow-running-badge\"\n title=\"This run submitted a workflow that runs on the dispatcher. The run finished when the workflow was submitted; the workflow itself is still going. This view refreshes on its own.\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n Workflow still running\n </div>\n }\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"refreshData()\" title=\"Refresh\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n </div>\n </div>\n </div>\n <div class=\"header-stats\">\n <div class=\"stat\">\n <span class=\"label\">Started</span>\n <span class=\"value\">{{ record.StartedAt | date:'medium' }}</span>\n </div>\n @if (record.CompletedAt) {\n <div class=\"stat\">\n <span class=\"label\">Completed</span>\n <span class=\"value\">{{ record.CompletedAt | date:'medium' }}</span>\n </div>\n }\n @if (record.CompletedAt) {\n <div class=\"stat\">\n <span class=\"label\">Duration</span>\n <span class=\"value\">{{ calculateDuration(record.StartedAt, record.CompletedAt) }}</span>\n </div>\n }\n @if (record.Success !== null && record.CompletedAt !== null) {\n <div class=\"stat\">\n <span class=\"label\">Result</span>\n <span class=\"value\" [class.success]=\"record.Success\" [class.error]=\"!record.Success\">\n {{ record.Success ? 'Success' : 'Failed' }}\n </span>\n </div>\n }\n @if (costMetrics && (costMetrics.totalTokensInput + costMetrics.totalTokensOutput) > 0) {\n <div class=\"stat\">\n <span class=\"label\">Tokens</span>\n @if (!costMetrics.isLoading) {\n <span class=\"value\">{{ (costMetrics.totalTokensInput + costMetrics.totalTokensOutput) | number:'1.0-0' }}</span>\n }\n @if (costMetrics.isLoading) {\n <span class=\"value loading\"><i class=\"fas fa-spinner fa-spin\"></i></span>\n }\n </div>\n }\n @if (costMetrics && costMetrics.totalCost > 0) {\n <div class=\"stat\">\n <span class=\"label\">Cost</span>\n @if (!costMetrics.isLoading) {\n <span class=\"value\">${{ costMetrics.totalCost | number:'1.2-4' }}</span>\n }\n @if (costMetrics.isLoading) {\n <span class=\"value loading\"><i class=\"fas fa-spinner fa-spin\"></i></span>\n }\n </div>\n }\n @if (record.EffortLevel) {\n <div class=\"stat\">\n <span class=\"label\">Effort Level</span>\n <span class=\"value\">{{ record.EffortLevel }}</span>\n </div>\n }\n </div>\n\n <!-- Configuration Bar (shown below header stats when ConfigurationID exists) -->\n @if (record.ConfigurationID) {\n <div class=\"configuration-bar\">\n <div class=\"config-item\">\n <i class=\"fas fa-cog\"></i>\n <div class=\"config-content\">\n <div class=\"config-label\">Configuration</div>\n <div class=\"config-value\">\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Configurations', record.ConfigurationID)\">\n {{ record.Configuration || 'Unknown' }}\n </a>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab\" [class.active]=\"activeTab === 'timeline'\" (click)=\"changeTab('timeline')\">\n <i class=\"fas fa-stream\"></i> Timeline\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'visualization'\" (click)=\"changeTab('visualization')\">\n <i class=\"fas fa-diagram-project\"></i> Visualization\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'analytics'\" (click)=\"changeTab('analytics')\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'details'\" (click)=\"changeTab('details')\">\n <i class=\"fas fa-info-circle\"></i> Details\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"content-area\">\n <!-- Timeline Tab -->\n @if (activeTab === 'timeline') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n <as-split direction=\"horizontal\" style=\"height: 100%;\">\n <!-- Timeline Pane -->\n <as-split-area [size]=\"selectedTimelineItem ? 55 : 100\">\n <mj-ai-agent-run-timeline\n [aiAgentRunId]=\"record.ID\"\n [dataHelper]=\"dataHelper\"\n [RunTree]=\"runTree\"\n (itemSelected)=\"selectTimelineItem($event)\"\n (navigateToEntity)=\"navigateToEntityRecord($event)\">\n </mj-ai-agent-run-timeline>\n </as-split-area>\n <!-- JSON Detail Pane -->\n @if (selectedTimelineItem) {\n <as-split-area [size]=\"45\">\n <mj-ai-agent-run-step-detail\n [selectedTimelineItem]=\"selectedTimelineItem\"\n [Provider]=\"ProviderToUse\"\n (closePanel)=\"closeJsonPanel()\"\n (navigateToActionLog)=\"navigateToActionLog($event)\"\n (copyToClipboard)=\"copyToClipboard($event)\">\n </mj-ai-agent-run-step-detail>\n </as-split-area>\n }\n </as-split>\n </div>\n }\n\n <!-- Visualization Tab (animated flow views + static flowchart) -->\n @if (activeTab === 'visualization') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n @if (visualizationLoaded) {\n <mj-ai-agent-run-flow\n [aiAgentRunId]=\"record.ID\"\n [dataHelper]=\"dataHelper\"\n [agentName]=\"agent?.Name || null\"\n [runStatus]=\"record.Status || ''\"\n [agentIconClass]=\"agent?.IconClass || null\"\n [agentLogoUrl]=\"agent?.LogoURL || null\"\n [RunTree]=\"runTree\">\n </mj-ai-agent-run-flow>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n @if (analyticsLoaded) {\n <mj-ai-agent-run-analytics\n #analyticsComponent\n [agentRunId]=\"record.ID\"\n [RunTree]=\"runTree\"\n >\n </mj-ai-agent-run-analytics>\n }\n </div>\n }\n\n <!-- Details Tab -->\n @if (activeTab === 'details') {\n <div class=\"tab-content\">\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-info-circle\"></i> General Information\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Agent</label>\n <span>\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agents', record.AgentID)\">\n {{ agent?.Name || 'N/A' }}\n </a>\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Parent Run ID</label>\n <span>\n @if (record.ParentRunID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agent Runs', record.ParentRunID)\">\n {{ record.ParentRunID }}\n </a>\n }\n @if (!record.ParentRunID) {\n <span>None (Root)</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Last Run ID</label>\n <span>\n @if (record.LastRunID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agent Runs', record.LastRunID)\">\n {{ record.LastRunID }}\n </a>\n }\n @if (!record.LastRunID) {\n <span>None</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Conversation ID</label>\n <span>\n @if (record.ConversationID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: Conversations', record.ConversationID)\">\n {{ record.ConversationID }}\n </a>\n }\n @if (!record.ConversationID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>User</label>\n <span>\n @if (record.UserID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: Users', record.UserID)\">\n {{ record.User || 'N/A' }}\n </a>\n }\n @if (!record.UserID) {\n <span>N/A</span>\n }\n </span>\n </div>\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cogs\"></i> Execution Settings\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Override Model</label>\n <span>\n @if (record.OverrideModelID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Models', record.OverrideModelID)\">\n {{ record.OverrideModel || 'N/A' }}\n </a>\n }\n @if (!record.OverrideModelID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Override Vendor</label>\n <span>\n @if (record.OverrideVendorID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Vendors', record.OverrideVendorID)\">\n {{ record.OverrideVendor || 'N/A' }}\n </a>\n }\n @if (!record.OverrideVendorID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Verbose Logging</label>\n <span>{{ record.Verbose ? 'Yes' : 'No' }}</span>\n </div>\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tasks\"></i> Execution Status\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Status</label>\n <span class=\"status-badge\" [attr.data-status]=\"record.Status\">\n {{ record.Status }}\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Success</label>\n @if (record.Success === null) {\n <span>In Progress</span>\n }\n @else if (record.Success) {\n <span class=\"success\">Yes</span>\n }\n @else {\n <span class=\"error-message\">No</span>\n }\n </div>\n @if (record.Message) {\n <div class=\"detail-item full-width\">\n <label>Message</label>\n <div class=\"message\">{{ record.Message }}</div>\n </div>\n }\n @if (record.ErrorMessage) {\n <div class=\"detail-item full-width\">\n <label>Error Message</label>\n <div class=\"error-message\">{{ record.ErrorMessage }}</div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-dollar-sign\"></i> Usage &amp; Cost\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Total Tokens Used</label>\n <span>{{ record.TotalTokensUsed ? (record.TotalTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Prompt Tokens</label>\n <span>{{ record.TotalPromptTokensUsed ? (record.TotalPromptTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Completion Tokens</label>\n <span>{{ record.TotalCompletionTokensUsed ? (record.TotalCompletionTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Total Cost</label>\n <span>{{ record.TotalCost != null ? ('$' + (record.TotalCost | number:'1.2-4')) : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Total Prompt Iterations</label>\n <span>{{ record.TotalPromptIterations != null ? (record.TotalPromptIterations | number:'1.0-0') : 'N/A' }}</span>\n </div>\n </div>\n </mj-accordion-panel>\n @if (record.Result) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-code\"></i> Result\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedResult\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading result data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.StartingPayload) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-upload\"></i> Starting Payload\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedStartingPayload\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading payload data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.Data) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-database\"></i> Execution Data\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedData\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading execution data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.FinalPayload) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-download\"></i> Final Payload\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedFinalPayload\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading final payload data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (showPayloadDiff) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-code-compare\"></i> Payload Diff\n </ng-template>\n <div style=\"padding: 20px; background: var(--mj-bg-surface-card);\">\n @if (isParsingComplete) {\n <mj-deep-diff\n [oldValue]=\"startingPayloadObject\"\n [newValue]=\"finalPayloadObject\"\n [title]=\"''\"\n [showSummary]=\"true\"\n [showUnchanged]=\"false\"\n [expandAll]=\"false\"\n [maxDepth]=\"10\"\n [maxStringLength]=\"200\"\n [treatNullAsUndefined]=\"true\">\n </mj-deep-diff>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading payload diff...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n </div>\n }\n</div>\n</div>\n</div>", styles: [".ai-agent-run-form {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.record-form-container.ai-agent-run-form > .record-form,\n.ai-agent-run-form > .record-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n\n/* Header Styles */\n.header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.icon-wrapper {\n width: 48px;\n height: 48px;\n background: var(--mj-brand-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 20px;\n overflow: hidden;\n}\n\n.agent-logo {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.header-info h2 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.meta-info {\n display: flex;\n gap: 12px;\n margin-top: 4px;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.parent-run {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.parent-link {\n color: var(--mj-status-error);\n text-decoration: none;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.parent-link:hover {\n color: var(--mj-status-error);\n text-decoration: underline;\n}\n\n.agent-name {\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.run-id {\n font-family: monospace;\n font-size: 12px;\n opacity: 0.7;\n}\n\n/* Conversation Link Pill */\n.conversation-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.conversation-pill:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.conversation-pill i:first-child {\n font-size: 11px;\n opacity: 0.9;\n}\n\n.conversation-pill .pill-action {\n font-size: 9px;\n opacity: 0.6;\n transition: opacity 0.2s ease;\n}\n\n.conversation-pill:hover .pill-action {\n opacity: 1;\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.status-badge {\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.status-badge[data-status=\"Running\"] {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.status-badge[data-status=\"Completed\"] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge[data-status=\"Failed\"] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge[data-status=\"Cancelled\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.status-badge[data-status=\"Paused\"] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge.small {\n padding: 4px 12px;\n font-size: 11px;\n}\n\n/* Plan Mode chip \u2014 shown next to the status badge when AIAgentRun.PlanMode = 1 */\n.plan-mode-badge {\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n.btn-icon {\n width: 36px;\n height: 36px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.header-stats {\n display: flex;\n gap: 24px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* Configuration Bar */\n.configuration-bar {\n display: flex;\n gap: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n margin-top: 16px;\n}\n\n.config-item {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.config-item > i {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n width: 24px;\n text-align: center;\n}\n\n.config-content {\n display: flex;\n flex-direction: column;\n}\n\n.config-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.config-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.config-value .entity-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.config-value .entity-link:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: underline;\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.stat .label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat .value {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.stat .value.success {\n color: var(--mj-status-success);\n}\n\n.stat .value.error {\n color: var(--mj-status-error);\n}\n\n/* Tabs */\n.tabs {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.tab {\n padding: 12px 24px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 8px;\n transition: all 0.2s ease;\n border-bottom: 3px solid transparent;\n}\n\n.tab:hover {\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, var(--mj-bg-surface));\n}\n\n.tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n/* Content Area */\n.content-area {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: auto;\n background: var(--mj-bg-surface);\n}\n\n.tab-content {\n height: 100%;\n min-height: 0;\n overflow: auto;\n}\n\n/* Details tab accordion panels */\n.tab-content mj-accordion-panel {\n display: block;\n margin-bottom: 8px;\n}\n\n/* JSON Detail Pane */\n.json-detail-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-sunken);\n border-left: 1px solid var(--mj-border-default);\n}\n\n.json-pane-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.json-pane-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.json-pane-header h3 i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.json-pane-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.json-meta {\n display: flex;\n gap: 20px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.json-meta .meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.json-meta .meta-item label {\n font-size: 11px;\n text-transform: uppercase;\n color: var(--mj-text-muted);\n font-weight: 600;\n letter-spacing: 0.5px;\n}\n\n.json-meta .meta-item span {\n font-size: 14px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.action-link {\n margin-bottom: 12px;\n}\n\n.action-link .btn-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n font-size: 14px;\n cursor: pointer;\n padding: 6px 12px;\n border-radius: 4px;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.action-link .btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.json-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n overflow: auto;\n padding: 20px;\n gap: 10px;\n min-height: 0;\n margin-bottom: 45px;\n}\n\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Timeline Styles */\n.timeline-container {\n height: 100%;\n overflow-y: auto;\n padding: 20px;\n}\n\n.timeline-container > .timeline {\n max-width: 900px;\n margin: 0 auto;\n}\n\n.timeline {\n position: relative;\n padding-left: 40px;\n}\n\n.timeline::before {\n content: '';\n position: absolute;\n left: 20px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.timeline-item {\n position: relative;\n margin-bottom: 24px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.timeline-item:hover {\n transform: translateX(4px);\n}\n\n.timeline-item.selected {\n transform: translateX(8px);\n}\n\n.timeline-item.selected .timeline-content {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.timeline-marker {\n position: absolute;\n left: -30px;\n top: 0;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 3px solid var(--mj-border-default);\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.timeline-marker[data-color=\"success\"] {\n border-color: var(--mj-status-success);\n color: var(--mj-status-success);\n}\n\n.timeline-marker[data-color=\"error\"] {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.timeline-marker[data-color=\"info\"] {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.timeline-marker[data-color=\"warning\"] {\n border-color: var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.timeline-marker[data-color=\"secondary\"] {\n border-color: var(--mj-text-muted);\n color: var(--mj-text-muted);\n}\n\n.timeline-marker.small {\n width: 28px;\n height: 28px;\n font-size: 12px;\n}\n\n.timeline-content {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 16px 20px;\n margin-left: 20px;\n box-shadow: var(--mj-shadow-sm);\n transition: all 0.2s ease;\n}\n\n.timeline-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.timeline-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-header h5 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.timeline-time {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-family: monospace;\n}\n\n.timeline-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.timeline-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.timeline-meta .status {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.timeline-meta .status[data-status=\"Completed\"] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.timeline-meta .status[data-status=\"Failed\"] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.timeline-meta .status[data-status=\"Running\"] {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.timeline-meta .status[data-status=\"Paused\"] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.duration {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.timeline-actions {\n position: absolute;\n right: 20px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s ease;\n}\n\n.btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.btn-expand {\n width: 24px;\n height: 24px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.btn-expand:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n/* Timeline Children */\n.timeline-children {\n position: relative;\n margin-top: 12px;\n margin-bottom: 12px;\n}\n\n.timeline-children::before {\n content: '';\n position: absolute;\n left: -10px;\n top: -12px;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.child-item {\n margin-bottom: 12px;\n}\n\n.child-item .timeline-content {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n}\n\n/* Sub-run timeline styles */\n.sub-run-timeline {\n background: color-mix(in srgb, var(--mj-brand-primary) 2%, var(--mj-bg-surface));\n border-left: 2px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n margin-left: 20px;\n padding-left: 20px;\n margin-top: 8px;\n margin-bottom: 8px;\n}\n\n.sub-run-item .timeline-marker {\n border-width: 2px;\n}\n\n.sub-run-item .timeline-content {\n transition: all 0.2s ease;\n}\n\n/* JSON Detail Pane (in splitter) */\n.json-detail-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n}\n\n.json-pane-header {\n padding: 16px 20px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n}\n\n.json-pane-header h3 {\n margin: 0;\n font-size: 16px;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n}\n\n.json-pane-content {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n}\n\n.json-meta {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n gap: 20px;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n\n.json-meta .meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.json-meta label {\n font-size: 11px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.json-meta span {\n font-size: 14px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.action-link {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.action-link .btn-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary);\n text-decoration: none;\n font-size: 14px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.action-link .btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n text-decoration: none;\n}\n\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n/* Details Tab */\n.details-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n padding: 20px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.detail-item.full-width {\n grid-column: 1 / -1;\n}\n\n.detail-item label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-item span {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.error-message {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 12px;\n border-radius: 8px;\n font-size: 13px;\n}\n\n.result-viewer,\n.state-viewer {\n padding: 20px;\n max-height: 450px;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n\n.result-viewer mj-code-editor,\n.state-viewer mj-code-editor {\n flex: 1;\n min-height: 0;\n}\n\n/* Empty States */\n.empty-state,\n.loading-state,\n.error-state {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-state i,\n.loading-state i,\n.error-state i {\n opacity: 0.3;\n margin-bottom: 16px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n \n .header-stats {\n flex-wrap: wrap;\n }\n \n .json-detail-pane {\n width: 100%;\n }\n \n .timeline {\n padding-left: 30px;\n }\n \n .timeline-marker {\n left: -25px;\n width: 32px;\n height: 32px;\n }\n \n .timeline-content {\n margin-left: 10px;\n }\n}\n\n/* Entity Link Styles */\n.entity-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n transition: all 0.2s ease;\n border-bottom: 1px solid transparent;\n display: inline-block;\n}\n\n.entity-link:hover {\n color: var(--mj-brand-primary-hover);\n border-bottom-color: var(--mj-brand-primary-hover);\n}\n\n.entity-link:active {\n color: var(--mj-brand-primary-hover);\n}\n\n/* Detail Pane Tabs */\n.detail-pane-tabs {\n display: flex;\n gap: 8px;\n margin: 8px 0 0 0;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0 16px;\n}\n\n.detail-tab {\n padding: 10px 16px;\n background: none;\n border: none;\n border-bottom: 3px solid transparent;\n color: var(--mj-text-muted);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.detail-tab:hover {\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, var(--mj-bg-surface));\n}\n\n.detail-tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.detail-tab i {\n font-size: 14px;\n}\n\n/* Detail Pane Content */\n.detail-pane-content {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n margin-bottom: 35px;\n}\n\n.detail-pane-content.with-tabs {\n /* When tabs are shown, content starts right after tabs */\n margin-top: 0;\n}\n\n/* Step Payload Diff */\n.step-payload-diff {\n height: 100%;\n overflow-y: auto;\n padding: 16px;\n}\n\n.step-payload-diff mj-deep-diff {\n display: block;\n height: 100%;\n}\n\n/* JSON Viewer adjustments when no tabs */\n.detail-pane-content:not(.with-tabs) .json-viewer {\n margin-top: 16px;\n}\n/* A detached workflow still executing after its run completed. Blue rather than green or amber: it\n is neither finished nor wrong, it is the same \"workflow\" provenance the timeline uses. */\n.workflow-running-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n white-space: nowrap;\n}\n"] }]
2034
+ args: [{ standalone: false, selector: 'mj-ai-agent-run-form', template: "<div class=\"record-form-container ai-agent-run-form\">\n <div class=\"record-form\">\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-content\">\n <div class=\"header-left\">\n <div class=\"icon-wrapper\">\n @if (agent && agent.LogoURL) {\n <img [src]=\"agent.LogoURL\" [alt]=\"agent.Name || 'Agent'\" class=\"agent-logo\" />\n }\n @if (agent && !agent.LogoURL && agent.IconClass) {\n <i class=\"fas\" [ngClass]=\"agent.IconClass\"></i>\n }\n @if (!agent || (!agent.LogoURL && !agent.IconClass)) {\n <i class=\"fas fa-robot\"></i>\n }\n </div>\n <div class=\"header-info\">\n <h2>AI Agent Run</h2>\n <div class=\"meta-info\">\n @if (agent) {\n <span class=\"agent-name\">\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agents', record.AgentID)\">\n {{ agent.Name }}\n </a>\n </span>\n }\n <span class=\"run-id\">{{ record.ID }}</span>\n @if (record.ParentRunID) {\n <span class=\"parent-run\">\n <i class=\"fas fa-level-up-alt\"></i>\n <a (click)=\"navigateToParentRun()\" class=\"parent-link\">Parent Run</a>\n </span>\n }\n <!-- Conversation Link Pill -->\n @if (record.ConversationID) {\n <span class=\"conversation-pill\" (click)=\"navigateToConversation()\" title=\"Open conversation in Chat app\">\n <i class=\"fas fa-comments\"></i>\n <span>Conversation</span>\n <i class=\"fas fa-external-link-alt pill-action\"></i>\n </span>\n }\n </div>\n </div>\n </div>\n <div class=\"header-right\">\n @if (record.PlanMode) {\n <div class=\"plan-mode-badge\" title=\"This run executed in Plan Mode \u2014 the agent presented a plan for human approval before executing actions or sub-agents\">\n <i class=\"fas fa-clipboard-check\"></i>\n Plan Mode\n </div>\n }\n <div class=\"status-badge\" [attr.data-status]=\"record.Status\">\n <i class=\"fas\" [ngClass]=\"getStatusIcon(record.Status || '')\"></i>\n {{ record.Status }}\n </div>\n <!-- A workflow outlives the run that submitted it, so a Completed run can still have work\n in flight. Said beside the status rather than instead of it \u2014 both are true. -->\n @if (WorkflowStillRunning) {\n <div class=\"workflow-running-badge\"\n title=\"This run submitted a workflow that runs on the dispatcher. The run finished when the workflow was submitted; the workflow itself is still going. This view refreshes on its own.\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n Workflow still running\n </div>\n }\n <div class=\"header-actions\">\n <button class=\"btn-icon\" (click)=\"refreshData()\" title=\"Refresh\">\n <i class=\"fas fa-sync-alt\"></i>\n </button>\n </div>\n </div>\n </div>\n <div class=\"header-stats\">\n <div class=\"stat\">\n <span class=\"label\">Started</span>\n <span class=\"value\">{{ record.StartedAt | date:'medium' }}</span>\n </div>\n @if (record.CompletedAt) {\n <div class=\"stat\">\n <span class=\"label\">Completed</span>\n <span class=\"value\">{{ record.CompletedAt | date:'medium' }}</span>\n </div>\n }\n @if (record.CompletedAt) {\n <div class=\"stat\">\n <span class=\"label\">Duration</span>\n <span class=\"value\">{{ calculateDuration(record.StartedAt, record.CompletedAt) }}</span>\n </div>\n }\n @if (record.Success !== null && record.CompletedAt !== null) {\n <div class=\"stat\">\n <span class=\"label\">Result</span>\n <span class=\"value\" [class.success]=\"record.Success\" [class.error]=\"!record.Success\">\n {{ record.Success ? 'Success' : 'Failed' }}\n </span>\n </div>\n }\n @if (costMetrics && (costMetrics.totalTokensInput + costMetrics.totalTokensOutput) > 0) {\n <div class=\"stat\">\n <span class=\"label\">Tokens</span>\n @if (!costMetrics.isLoading) {\n <span class=\"value\">{{ (costMetrics.totalTokensInput + costMetrics.totalTokensOutput) | number:'1.0-0' }}</span>\n }\n @if (costMetrics.isLoading) {\n <span class=\"value loading\"><i class=\"fas fa-spinner fa-spin\"></i></span>\n }\n </div>\n }\n @if (costMetrics && costMetrics.totalCost > 0) {\n <div class=\"stat\">\n <span class=\"label\">Cost</span>\n @if (!costMetrics.isLoading) {\n <span class=\"value\">${{ costMetrics.totalCost | number:'1.2-4' }}</span>\n }\n @if (costMetrics.isLoading) {\n <span class=\"value loading\"><i class=\"fas fa-spinner fa-spin\"></i></span>\n }\n </div>\n }\n @if (record.EffortLevel) {\n <div class=\"stat\">\n <span class=\"label\">Effort Level</span>\n <span class=\"value\">{{ record.EffortLevel }}</span>\n </div>\n }\n </div>\n\n <!-- Configuration Bar (shown below header stats when ConfigurationID exists) -->\n @if (record.ConfigurationID) {\n <div class=\"configuration-bar\">\n <div class=\"config-item\">\n <i class=\"fas fa-cog\"></i>\n <div class=\"config-content\">\n <div class=\"config-label\">Configuration</div>\n <div class=\"config-value\">\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Configurations', record.ConfigurationID)\">\n {{ record.Configuration || 'Unknown' }}\n </a>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Tabs -->\n <div class=\"tabs\">\n <button class=\"tab\" [class.active]=\"activeTab === 'timeline'\" (click)=\"changeTab('timeline')\">\n <i class=\"fas fa-stream\"></i> Timeline\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'visualization'\" (click)=\"changeTab('visualization')\">\n <i class=\"fas fa-diagram-project\"></i> Visualization\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'analytics'\" (click)=\"changeTab('analytics')\">\n <i class=\"fas fa-chart-line\"></i> Analytics\n </button>\n <button class=\"tab\" [class.active]=\"activeTab === 'details'\" (click)=\"changeTab('details')\">\n <i class=\"fas fa-info-circle\"></i> Details\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"content-area\">\n <!-- Timeline Tab -->\n @if (activeTab === 'timeline') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n <as-split direction=\"horizontal\" style=\"height: 100%;\">\n <!-- Timeline Pane -->\n <as-split-area [size]=\"selectedTimelineItem ? 55 : 100\">\n <mj-ai-agent-run-timeline\n [aiAgentRunId]=\"record.ID\"\n [dataHelper]=\"dataHelper\"\n [RunTree]=\"runTree\"\n (itemSelected)=\"selectTimelineItem($event)\"\n (navigateToEntity)=\"navigateToEntityRecord($event)\">\n </mj-ai-agent-run-timeline>\n </as-split-area>\n <!-- JSON Detail Pane -->\n @if (selectedTimelineItem) {\n <as-split-area [size]=\"45\">\n <mj-ai-agent-run-step-detail\n [selectedTimelineItem]=\"selectedTimelineItem\"\n [Provider]=\"ProviderToUse\"\n [SavingWorkflow]=\"SavingWorkflow\"\n (closePanel)=\"closeJsonPanel()\"\n (navigateToActionLog)=\"navigateToActionLog($event)\"\n (copyToClipboard)=\"copyToClipboard($event)\"\n (SaveAsWorkflowRequested)=\"OnSaveAsWorkflowRequested($event)\">\n </mj-ai-agent-run-step-detail>\n </as-split-area>\n }\n </as-split>\n </div>\n }\n\n <!-- Visualization Tab (animated flow views + static flowchart) -->\n @if (activeTab === 'visualization') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n @if (visualizationLoaded) {\n <mj-ai-agent-run-flow\n [aiAgentRunId]=\"record.ID\"\n [dataHelper]=\"dataHelper\"\n [agentName]=\"agent?.Name || null\"\n [runStatus]=\"record.Status || ''\"\n [agentIconClass]=\"agent?.IconClass || null\"\n [agentLogoUrl]=\"agent?.LogoURL || null\"\n [RunTree]=\"runTree\">\n </mj-ai-agent-run-flow>\n }\n </div>\n }\n\n <!-- Analytics Tab -->\n @if (activeTab === 'analytics') {\n <div class=\"tab-content\" style=\"height: 100%;\">\n @if (analyticsLoaded) {\n <mj-ai-agent-run-analytics\n #analyticsComponent\n [agentRunId]=\"record.ID\"\n [RunTree]=\"runTree\"\n >\n </mj-ai-agent-run-analytics>\n }\n </div>\n }\n\n <!-- Details Tab -->\n @if (activeTab === 'details') {\n <div class=\"tab-content\">\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-info-circle\"></i> General Information\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Agent</label>\n <span>\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agents', record.AgentID)\">\n {{ agent?.Name || 'N/A' }}\n </a>\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Parent Run ID</label>\n <span>\n @if (record.ParentRunID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agent Runs', record.ParentRunID)\">\n {{ record.ParentRunID }}\n </a>\n }\n @if (!record.ParentRunID) {\n <span>None (Root)</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Last Run ID</label>\n <span>\n @if (record.LastRunID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Agent Runs', record.LastRunID)\">\n {{ record.LastRunID }}\n </a>\n }\n @if (!record.LastRunID) {\n <span>None</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Conversation ID</label>\n <span>\n @if (record.ConversationID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: Conversations', record.ConversationID)\">\n {{ record.ConversationID }}\n </a>\n }\n @if (!record.ConversationID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>User</label>\n <span>\n @if (record.UserID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: Users', record.UserID)\">\n {{ record.User || 'N/A' }}\n </a>\n }\n @if (!record.UserID) {\n <span>N/A</span>\n }\n </span>\n </div>\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cogs\"></i> Execution Settings\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Override Model</label>\n <span>\n @if (record.OverrideModelID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Models', record.OverrideModelID)\">\n {{ record.OverrideModel || 'N/A' }}\n </a>\n }\n @if (!record.OverrideModelID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Override Vendor</label>\n <span>\n @if (record.OverrideVendorID) {\n <a href=\"javascript:void(0)\" class=\"entity-link\" (click)=\"openEntityRecord('MJ: AI Vendors', record.OverrideVendorID)\">\n {{ record.OverrideVendor || 'N/A' }}\n </a>\n }\n @if (!record.OverrideVendorID) {\n <span>N/A</span>\n }\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Verbose Logging</label>\n <span>{{ record.Verbose ? 'Yes' : 'No' }}</span>\n </div>\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tasks\"></i> Execution Status\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Status</label>\n <span class=\"status-badge\" [attr.data-status]=\"record.Status\">\n {{ record.Status }}\n </span>\n </div>\n <div class=\"detail-item\">\n <label>Success</label>\n @if (record.Success === null) {\n <span>In Progress</span>\n }\n @else if (record.Success) {\n <span class=\"success\">Yes</span>\n }\n @else {\n <span class=\"error-message\">No</span>\n }\n </div>\n @if (record.Message) {\n <div class=\"detail-item full-width\">\n <label>Message</label>\n <div class=\"message\">{{ record.Message }}</div>\n </div>\n }\n @if (record.ErrorMessage) {\n <div class=\"detail-item full-width\">\n <label>Error Message</label>\n <div class=\"error-message\">{{ record.ErrorMessage }}</div>\n </div>\n }\n </div>\n </mj-accordion-panel>\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-dollar-sign\"></i> Usage &amp; Cost\n </ng-template>\n <div class=\"details-grid\">\n <div class=\"detail-item\">\n <label>Total Tokens Used</label>\n <span>{{ record.TotalTokensUsed ? (record.TotalTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Prompt Tokens</label>\n <span>{{ record.TotalPromptTokensUsed ? (record.TotalPromptTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Completion Tokens</label>\n <span>{{ record.TotalCompletionTokensUsed ? (record.TotalCompletionTokensUsed | number:'1.0-0') : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Total Cost</label>\n <span>{{ record.TotalCost != null ? ('$' + (record.TotalCost | number:'1.2-4')) : 'N/A' }}</span>\n </div>\n <div class=\"detail-item\">\n <label>Total Prompt Iterations</label>\n <span>{{ record.TotalPromptIterations != null ? (record.TotalPromptIterations | number:'1.0-0') : 'N/A' }}</span>\n </div>\n </div>\n </mj-accordion-panel>\n @if (ShowResultPanel) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-code\"></i> Result\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedResult\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading result data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.StartingPayload) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-upload\"></i> Starting Payload\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedStartingPayload\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading payload data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.Data) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-database\"></i> Execution Data\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedData\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading execution data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (record.FinalPayload) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-download\"></i> Final Payload\n </ng-template>\n <div class=\"result-viewer\">\n @if (isParsingComplete) {\n <mj-code-editor\n [ngModel]=\"parsedFinalPayload\"\n [language]=\"'json'\"\n [readonly]=\"true\"\n style=\"height: 300px; width: 100%;\">\n </mj-code-editor>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading final payload data...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n @if (showPayloadDiff) {\n <mj-accordion-panel [Expanded]=\"false\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-code-compare\"></i> Payload Diff\n </ng-template>\n <div style=\"padding: 20px; background: var(--mj-bg-surface-card);\">\n @if (isParsingComplete) {\n <mj-deep-diff\n [oldValue]=\"startingPayloadObject\"\n [newValue]=\"finalPayloadObject\"\n [title]=\"''\"\n [showSummary]=\"true\"\n [showUnchanged]=\"false\"\n [expandAll]=\"false\"\n [maxDepth]=\"10\"\n [maxStringLength]=\"200\"\n [treatNullAsUndefined]=\"true\">\n </mj-deep-diff>\n } @else {\n <div style=\"padding: 20px; text-align: center; color: var(--mj-text-muted);\">\n <i class=\"fas fa-spinner fa-spin\"></i> Loading payload diff...\n </div>\n }\n </div>\n </mj-accordion-panel>\n }\n </div>\n }\n</div>\n</div>\n</div>", styles: [".ai-agent-run-form {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.record-form-container.ai-agent-run-form > .record-form,\n.ai-agent-run-form > .record-form {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n\n/* Header Styles */\n.header {\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n flex-shrink: 0;\n}\n\n.header-content {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 16px;\n}\n\n.header-left {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.icon-wrapper {\n width: 48px;\n height: 48px;\n background: var(--mj-brand-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--mj-text-inverse);\n font-size: 20px;\n overflow: hidden;\n}\n\n.agent-logo {\n width: 100%;\n height: 100%;\n object-fit: cover;\n}\n\n.header-info h2 {\n margin: 0;\n font-size: 24px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.meta-info {\n display: flex;\n gap: 12px;\n margin-top: 4px;\n font-size: 14px;\n color: var(--mj-text-muted);\n}\n\n.parent-run {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.parent-link {\n color: var(--mj-status-error);\n text-decoration: none;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.parent-link:hover {\n color: var(--mj-status-error);\n text-decoration: underline;\n}\n\n.agent-name {\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.run-id {\n font-family: monospace;\n font-size: 12px;\n opacity: 0.7;\n}\n\n/* Conversation Link Pill */\n.conversation-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 16px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n.conversation-pill:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.conversation-pill i:first-child {\n font-size: 11px;\n opacity: 0.9;\n}\n\n.conversation-pill .pill-action {\n font-size: 9px;\n opacity: 0.6;\n transition: opacity 0.2s ease;\n}\n\n.conversation-pill:hover .pill-action {\n opacity: 1;\n}\n\n.header-right {\n display: flex;\n align-items: center;\n gap: 16px;\n}\n\n.status-badge {\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.status-badge[data-status=\"Running\"] {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.status-badge[data-status=\"Completed\"] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.status-badge[data-status=\"Failed\"] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.status-badge[data-status=\"Cancelled\"] {\n background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n}\n\n.status-badge[data-status=\"Paused\"] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.status-badge.small {\n padding: 4px 12px;\n font-size: 11px;\n}\n\n/* Plan Mode chip \u2014 shown next to the status badge when AIAgentRun.PlanMode = 1 */\n.plan-mode-badge {\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 13px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n}\n\n.btn-icon {\n width: 36px;\n height: 36px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n}\n\n.btn-icon:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n.header-stats {\n display: flex;\n gap: 24px;\n padding-top: 12px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* Configuration Bar */\n.configuration-bar {\n display: flex;\n gap: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n margin-top: 16px;\n}\n\n.config-item {\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.config-item > i {\n font-size: 1.2em;\n color: var(--mj-text-muted);\n width: 24px;\n text-align: center;\n}\n\n.config-content {\n display: flex;\n flex-direction: column;\n}\n\n.config-label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.config-value {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.config-value .entity-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n cursor: pointer;\n transition: color 0.2s;\n}\n\n.config-value .entity-link:hover {\n color: var(--mj-brand-primary-hover);\n text-decoration: underline;\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.stat .label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.stat .value {\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.stat .value.success {\n color: var(--mj-status-success);\n}\n\n.stat .value.error {\n color: var(--mj-status-error);\n}\n\n/* Tabs */\n.tabs {\n display: flex;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface-sunken);\n flex-shrink: 0;\n}\n\n.tab {\n padding: 12px 24px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 8px;\n transition: all 0.2s ease;\n border-bottom: 3px solid transparent;\n}\n\n.tab:hover {\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, var(--mj-bg-surface));\n}\n\n.tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n}\n\n/* Content Area */\n.content-area {\n position: relative;\n flex: 1;\n min-height: 0;\n overflow: auto;\n background: var(--mj-bg-surface);\n}\n\n.tab-content {\n height: 100%;\n min-height: 0;\n overflow: auto;\n}\n\n/* Details tab accordion panels */\n.tab-content mj-accordion-panel {\n display: block;\n margin-bottom: 8px;\n}\n\n/* JSON Detail Pane */\n.json-detail-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface-sunken);\n border-left: 1px solid var(--mj-border-default);\n}\n\n.json-pane-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-default);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.json-pane-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.json-pane-header h3 i {\n color: var(--mj-text-muted);\n font-size: 14px;\n}\n\n.json-pane-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: auto;\n padding: 16px;\n}\n\n.json-meta {\n display: flex;\n gap: 20px;\n margin-bottom: 16px;\n flex-wrap: wrap;\n}\n\n.json-meta .meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.json-meta .meta-item label {\n font-size: 11px;\n text-transform: uppercase;\n color: var(--mj-text-muted);\n font-weight: 600;\n letter-spacing: 0.5px;\n}\n\n.json-meta .meta-item span {\n font-size: 14px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.action-link {\n margin-bottom: 12px;\n}\n\n.action-link .btn-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n font-size: 14px;\n cursor: pointer;\n padding: 6px 12px;\n border-radius: 4px;\n transition: all 0.2s;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n}\n\n.action-link .btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n color: var(--mj-brand-primary-hover);\n}\n\n.json-viewer {\n flex: 1;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n overflow: auto;\n padding: 20px;\n gap: 10px;\n min-height: 0;\n margin-bottom: 45px;\n}\n\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n padding: 8px 12px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n/* Timeline Styles */\n.timeline-container {\n height: 100%;\n overflow-y: auto;\n padding: 20px;\n}\n\n.timeline-container > .timeline {\n max-width: 900px;\n margin: 0 auto;\n}\n\n.timeline {\n position: relative;\n padding-left: 40px;\n}\n\n.timeline::before {\n content: '';\n position: absolute;\n left: 20px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.timeline-item {\n position: relative;\n margin-bottom: 24px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.timeline-item:hover {\n transform: translateX(4px);\n}\n\n.timeline-item.selected {\n transform: translateX(8px);\n}\n\n.timeline-item.selected .timeline-content {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n}\n\n.timeline-marker {\n position: absolute;\n left: -30px;\n top: 0;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: var(--mj-bg-surface);\n border: 3px solid var(--mj-border-default);\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.timeline-marker[data-color=\"success\"] {\n border-color: var(--mj-status-success);\n color: var(--mj-status-success);\n}\n\n.timeline-marker[data-color=\"error\"] {\n border-color: var(--mj-status-error);\n color: var(--mj-status-error);\n}\n\n.timeline-marker[data-color=\"info\"] {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.timeline-marker[data-color=\"warning\"] {\n border-color: var(--mj-status-warning);\n color: var(--mj-status-warning);\n}\n\n.timeline-marker[data-color=\"secondary\"] {\n border-color: var(--mj-text-muted);\n color: var(--mj-text-muted);\n}\n\n.timeline-marker.small {\n width: 28px;\n height: 28px;\n font-size: 12px;\n}\n\n.timeline-content {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n padding: 16px 20px;\n margin-left: 20px;\n box-shadow: var(--mj-shadow-sm);\n transition: all 0.2s ease;\n}\n\n.timeline-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.timeline-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.timeline-header h5 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n}\n\n.timeline-time {\n font-size: 12px;\n color: var(--mj-text-muted);\n font-family: monospace;\n}\n\n.timeline-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.timeline-meta {\n display: flex;\n gap: 16px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.timeline-meta .status {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.timeline-meta .status[data-status=\"Completed\"] {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.timeline-meta .status[data-status=\"Failed\"] {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n}\n\n.timeline-meta .status[data-status=\"Running\"] {\n background: color-mix(in srgb, var(--mj-status-info) 15%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n.timeline-meta .status[data-status=\"Paused\"] {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-secondary);\n}\n\n.duration {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.timeline-actions {\n position: absolute;\n right: 20px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.btn-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 4px;\n transition: all 0.2s ease;\n}\n\n.btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n}\n\n.btn-expand {\n width: 24px;\n height: 24px;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: all 0.2s ease;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.btn-expand:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-secondary);\n}\n\n/* Timeline Children */\n.timeline-children {\n position: relative;\n margin-top: 12px;\n margin-bottom: 12px;\n}\n\n.timeline-children::before {\n content: '';\n position: absolute;\n left: -10px;\n top: -12px;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n.child-item {\n margin-bottom: 12px;\n}\n\n.child-item .timeline-content {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n}\n\n/* Sub-run timeline styles */\n.sub-run-timeline {\n background: color-mix(in srgb, var(--mj-brand-primary) 2%, var(--mj-bg-surface));\n border-left: 2px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n margin-left: 20px;\n padding-left: 20px;\n margin-top: 8px;\n margin-bottom: 8px;\n}\n\n.sub-run-item .timeline-marker {\n border-width: 2px;\n}\n\n.sub-run-item .timeline-content {\n transition: all 0.2s ease;\n}\n\n/* JSON Detail Pane (in splitter) */\n.json-detail-pane {\n height: 100%;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border-left: 1px solid var(--mj-border-default);\n}\n\n.json-pane-header {\n padding: 16px 20px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n}\n\n.json-pane-header h3 {\n margin: 0;\n font-size: 16px;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 10px;\n font-weight: 600;\n}\n\n.json-pane-content {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n}\n\n.json-meta {\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n gap: 20px;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n\n.json-meta .meta-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.json-meta label {\n font-size: 11px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.json-meta span {\n font-size: 14px;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n.action-link {\n padding: 12px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.action-link .btn-link {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-brand-primary);\n text-decoration: none;\n font-size: 14px;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n}\n\n.action-link .btn-link:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 35%, transparent);\n text-decoration: none;\n}\n\n\n.json-toolbar {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n/* Details Tab */\n.details-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n padding: 20px;\n}\n\n.detail-item {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.detail-item.full-width {\n grid-column: 1 / -1;\n}\n\n.detail-item label {\n font-size: 12px;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.detail-item span {\n font-size: 14px;\n color: var(--mj-text-secondary);\n}\n\n.error-message {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 12px;\n border-radius: 8px;\n font-size: 13px;\n}\n\n.result-viewer,\n.state-viewer {\n padding: 20px;\n max-height: 450px;\n overflow: auto;\n display: flex;\n flex-direction: column;\n}\n\n.result-viewer mj-code-editor,\n.state-viewer mj-code-editor {\n flex: 1;\n min-height: 0;\n}\n\n/* Empty States */\n.empty-state,\n.loading-state,\n.error-state {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.empty-state i,\n.loading-state i,\n.error-state i {\n opacity: 0.3;\n margin-bottom: 16px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .header-content {\n flex-direction: column;\n gap: 16px;\n }\n \n .header-stats {\n flex-wrap: wrap;\n }\n \n .json-detail-pane {\n width: 100%;\n }\n \n .timeline {\n padding-left: 30px;\n }\n \n .timeline-marker {\n left: -25px;\n width: 32px;\n height: 32px;\n }\n \n .timeline-content {\n margin-left: 10px;\n }\n}\n\n/* Entity Link Styles */\n.entity-link {\n color: var(--mj-brand-primary);\n text-decoration: none;\n transition: all 0.2s ease;\n border-bottom: 1px solid transparent;\n display: inline-block;\n}\n\n.entity-link:hover {\n color: var(--mj-brand-primary-hover);\n border-bottom-color: var(--mj-brand-primary-hover);\n}\n\n.entity-link:active {\n color: var(--mj-brand-primary-hover);\n}\n\n/* Detail Pane Tabs */\n.detail-pane-tabs {\n display: flex;\n gap: 8px;\n margin: 8px 0 0 0;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 0 16px;\n}\n\n.detail-tab {\n padding: 10px 16px;\n background: none;\n border: none;\n border-bottom: 3px solid transparent;\n color: var(--mj-text-muted);\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.detail-tab:hover {\n color: var(--mj-text-secondary);\n background: color-mix(in srgb, var(--mj-text-primary) 2%, var(--mj-bg-surface));\n}\n\n.detail-tab.active {\n color: var(--mj-brand-primary);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.detail-tab i {\n font-size: 14px;\n}\n\n/* Detail Pane Content */\n.detail-pane-content {\n flex: 1;\n overflow-y: auto;\n min-height: 0;\n margin-bottom: 35px;\n}\n\n.detail-pane-content.with-tabs {\n /* When tabs are shown, content starts right after tabs */\n margin-top: 0;\n}\n\n/* Step Payload Diff */\n.step-payload-diff {\n height: 100%;\n overflow-y: auto;\n padding: 16px;\n}\n\n.step-payload-diff mj-deep-diff {\n display: block;\n height: 100%;\n}\n\n/* JSON Viewer adjustments when no tabs */\n.detail-pane-content:not(.with-tabs) .json-viewer {\n margin-top: 16px;\n}\n/* A detached workflow still executing after its run completed. Blue rather than green or amber: it\n is neither finished nor wrong, it is the same \"workflow\" provenance the timeline uses. */\n.workflow-running-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 12px;\n border-radius: var(--mj-radius-full, 999px);\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 30%, transparent);\n white-space: nowrap;\n}\n"] }]
1914
2035
  }], null, { TimelineComponent: [{
1915
2036
  type: ViewChild,
1916
2037
  args: [AIAgentRunTimelineComponent]
@@ -1918,5 +2039,5 @@ export { MJAIAgentRunFormComponentExtended };
1918
2039
  type: ViewChild,
1919
2040
  args: [AIAgentRunAnalyticsComponent]
1920
2041
  }] }); })();
1921
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJAIAgentRunFormComponentExtended, { className: "MJAIAgentRunFormComponentExtended", filePath: "src/lib/custom/ai-agent-run/ai-agent-run.component.ts", lineNumber: 45 }); })();
2042
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJAIAgentRunFormComponentExtended, { className: "MJAIAgentRunFormComponentExtended", filePath: "src/lib/custom/ai-agent-run/ai-agent-run.component.ts", lineNumber: 49 }); })();
1922
2043
  //# sourceMappingURL=ai-agent-run.component.js.map