@memberjunction/ng-core-entity-forms 5.42.0 → 5.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/dist/__tests__/model-prediction.logic.test.d.ts +2 -0
  2. package/dist/__tests__/model-prediction.logic.test.d.ts.map +1 -0
  3. package/dist/__tests__/model-prediction.logic.test.js +140 -0
  4. package/dist/__tests__/model-prediction.logic.test.js.map +1 -0
  5. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js +79 -105
  6. package/dist/lib/custom/AIAgentSessions/ai-agent-session-form.component.js.map +1 -1
  7. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js +7 -10
  8. package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js.map +1 -1
  9. package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
  10. package/dist/lib/custom/AIAgents/add-action-dialog.component.js +46 -51
  11. package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
  12. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +2 -0
  13. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  14. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +300 -378
  15. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  16. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +22 -29
  17. package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
  18. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +15 -17
  19. package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
  20. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +27 -34
  21. package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
  22. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts +11 -0
  23. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
  24. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +48 -47
  25. package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
  26. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +438 -454
  27. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  28. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js +48 -51
  29. package/dist/lib/custom/AIPromptRuns/chat-message-viewer.component.js.map +1 -1
  30. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +253 -282
  31. package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
  32. package/dist/lib/custom/Actions/action-execution-log-form.component.js +24 -33
  33. package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
  34. package/dist/lib/custom/Actions/action-form.component.js +263 -311
  35. package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
  36. package/dist/lib/custom/Entities/entity-form.component.d.ts +6 -0
  37. package/dist/lib/custom/Entities/entity-form.component.d.ts.map +1 -1
  38. package/dist/lib/custom/Entities/entity-form.component.js +475 -493
  39. package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
  40. package/dist/lib/custom/Lists/list-form.component.js +122 -173
  41. package/dist/lib/custom/Lists/list-form.component.js.map +1 -1
  42. package/dist/lib/custom/Queries/query-form.component.js +190 -248
  43. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  44. package/dist/lib/custom/Queries/query-run-dialog.component.js +19 -23
  45. package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
  46. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts +16 -0
  47. package/dist/lib/custom/RecordProcesses/record-process-form.component.d.ts.map +1 -0
  48. package/dist/lib/custom/RecordProcesses/record-process-form.component.js +54 -0
  49. package/dist/lib/custom/RecordProcesses/record-process-form.component.js.map +1 -0
  50. package/dist/lib/custom/SearchScopes/searchscopeprovider-form.component.js +23 -24
  51. package/dist/lib/custom/SearchScopes/searchscopeprovider-form.component.js.map +1 -1
  52. package/dist/lib/custom/Templates/template-param-dialog.component.d.ts.map +1 -1
  53. package/dist/lib/custom/Templates/template-param-dialog.component.js +25 -46
  54. package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
  55. package/dist/lib/custom/Tests/test-form.component.js +100 -130
  56. package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
  57. package/dist/lib/custom/Tests/test-run-form.component.js +187 -205
  58. package/dist/lib/custom/Tests/test-run-form.component.js.map +1 -1
  59. package/dist/lib/custom/Tests/test-suite-form.component.d.ts +8 -0
  60. package/dist/lib/custom/Tests/test-suite-form.component.d.ts.map +1 -1
  61. package/dist/lib/custom/Tests/test-suite-form.component.js +412 -489
  62. package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
  63. package/dist/lib/custom/Tests/test-suite-run-form.component.js +100 -126
  64. package/dist/lib/custom/Tests/test-suite-run-form.component.js.map +1 -1
  65. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +166 -184
  66. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
  67. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +42 -61
  68. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
  69. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +8 -17
  70. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
  71. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +0 -2
  72. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  73. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +183 -188
  74. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  75. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts +108 -0
  76. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts.map +1 -0
  77. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js +665 -0
  78. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js.map +1 -0
  79. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts +94 -0
  80. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts.map +1 -0
  81. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js +257 -0
  82. package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js.map +1 -0
  83. package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts +38 -0
  84. package/dist/lib/custom/ai-agent-run/flow/constellation.component.d.ts.map +1 -0
  85. package/dist/lib/custom/ai-agent-run/flow/constellation.component.js +200 -0
  86. package/dist/lib/custom/ai-agent-run/flow/constellation.component.js.map +1 -0
  87. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts +44 -0
  88. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.d.ts.map +1 -0
  89. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js +180 -0
  90. package/dist/lib/custom/ai-agent-run/flow/flame-cascade.component.js.map +1 -0
  91. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts +12 -0
  92. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.d.ts.map +1 -0
  93. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js +46 -0
  94. package/dist/lib/custom/ai-agent-run/flow/flow-svg.util.js.map +1 -0
  95. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts +64 -0
  96. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.d.ts.map +1 -0
  97. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js +267 -0
  98. package/dist/lib/custom/ai-agent-run/flow/flowchart.component.js.map +1 -0
  99. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts +53 -0
  100. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.d.ts.map +1 -0
  101. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js +111 -0
  102. package/dist/lib/custom/ai-agent-run/flow/pan-zoom.js.map +1 -0
  103. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts +42 -0
  104. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.d.ts.map +1 -0
  105. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js +193 -0
  106. package/dist/lib/custom/ai-agent-run/flow/subway-lines.component.js.map +1 -0
  107. package/dist/lib/custom/custom-forms.module.d.ts +58 -49
  108. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  109. package/dist/lib/custom/custom-forms.module.js +64 -16
  110. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  111. package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts +2 -0
  112. package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
  113. package/dist/lib/custom/shared/entity-selector-dialog.component.js +25 -25
  114. package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
  115. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.d.ts.map +1 -1
  116. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js +280 -216
  117. package/dist/lib/generated/Entities/MJAIAgent/mjaiagent.form.component.js.map +1 -1
  118. package/dist/lib/generated/Entities/MJAIAgentChannel/mjaiagentchannel.form.component.js +25 -21
  119. package/dist/lib/generated/Entities/MJAIAgentChannel/mjaiagentchannel.form.component.js.map +1 -1
  120. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.d.ts.map +1 -1
  121. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +68 -14
  122. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
  123. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.d.ts.map +1 -1
  124. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js +44 -32
  125. package/dist/lib/generated/Entities/MJAIAgentSession/mjaiagentsession.form.component.js.map +1 -1
  126. package/dist/lib/generated/Entities/MJAIAgentSkill/mjaiagentskill.form.component.d.ts +10 -0
  127. package/dist/lib/generated/Entities/MJAIAgentSkill/mjaiagentskill.form.component.d.ts.map +1 -0
  128. package/dist/lib/generated/Entities/MJAIAgentSkill/mjaiagentskill.form.component.js +66 -0
  129. package/dist/lib/generated/Entities/MJAIAgentSkill/mjaiagentskill.form.component.js.map +1 -0
  130. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
  131. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +55 -19
  132. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  133. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
  134. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +28 -10
  135. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
  136. package/dist/lib/generated/Entities/MJAISkill/mjaiskill.form.component.d.ts +10 -0
  137. package/dist/lib/generated/Entities/MJAISkill/mjaiskill.form.component.d.ts.map +1 -0
  138. package/dist/lib/generated/Entities/MJAISkill/mjaiskill.form.component.js +167 -0
  139. package/dist/lib/generated/Entities/MJAISkill/mjaiskill.form.component.js.map +1 -0
  140. package/dist/lib/generated/Entities/MJAISkillAction/mjaiskillaction.form.component.d.ts +10 -0
  141. package/dist/lib/generated/Entities/MJAISkillAction/mjaiskillaction.form.component.d.ts.map +1 -0
  142. package/dist/lib/generated/Entities/MJAISkillAction/mjaiskillaction.form.component.js +64 -0
  143. package/dist/lib/generated/Entities/MJAISkillAction/mjaiskillaction.form.component.js.map +1 -0
  144. package/dist/lib/generated/Entities/MJAISkillPermission/mjaiskillpermission.form.component.d.ts +10 -0
  145. package/dist/lib/generated/Entities/MJAISkillPermission/mjaiskillpermission.form.component.d.ts.map +1 -0
  146. package/dist/lib/generated/Entities/MJAISkillPermission/mjaiskillpermission.form.component.js +82 -0
  147. package/dist/lib/generated/Entities/MJAISkillPermission/mjaiskillpermission.form.component.js.map +1 -0
  148. package/dist/lib/generated/Entities/MJAISkillSubAgent/mjaiskillsubagent.form.component.d.ts +10 -0
  149. package/dist/lib/generated/Entities/MJAISkillSubAgent/mjaiskillsubagent.form.component.d.ts.map +1 -0
  150. package/dist/lib/generated/Entities/MJAISkillSubAgent/mjaiskillsubagent.form.component.js +64 -0
  151. package/dist/lib/generated/Entities/MJAISkillSubAgent/mjaiskillsubagent.form.component.js.map +1 -0
  152. package/dist/lib/generated/Entities/MJAction/mjaction.form.component.d.ts.map +1 -1
  153. package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js +35 -17
  154. package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js.map +1 -1
  155. package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.d.ts.map +1 -1
  156. package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js +59 -51
  157. package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js.map +1 -1
  158. package/dist/lib/generated/Entities/MJCollection/mjcollection.form.component.d.ts.map +1 -1
  159. package/dist/lib/generated/Entities/MJCollection/mjcollection.form.component.js +25 -7
  160. package/dist/lib/generated/Entities/MJCollection/mjcollection.form.component.js.map +1 -1
  161. package/dist/lib/generated/Entities/MJCollectionArtifact/mjcollectionartifact.form.component.js +11 -7
  162. package/dist/lib/generated/Entities/MJCollectionArtifact/mjcollectionartifact.form.component.js.map +1 -1
  163. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.d.ts.map +1 -1
  164. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js +56 -46
  165. package/dist/lib/generated/Entities/MJConversation/mjconversation.form.component.js.map +1 -1
  166. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.d.ts.map +1 -1
  167. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js +73 -59
  168. package/dist/lib/generated/Entities/MJConversationDetail/mjconversationdetail.form.component.js.map +1 -1
  169. package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.d.ts.map +1 -1
  170. package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.js +24 -4
  171. package/dist/lib/generated/Entities/MJDuplicateRunDetailMatch/mjduplicaterundetailmatch.form.component.js.map +1 -1
  172. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
  173. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +137 -87
  174. package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
  175. package/dist/lib/generated/Entities/MJEntityActionInvocation/mjentityactioninvocation.form.component.js +10 -8
  176. package/dist/lib/generated/Entities/MJEntityActionInvocation/mjentityactioninvocation.form.component.js.map +1 -1
  177. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.d.ts.map +1 -1
  178. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js +47 -29
  179. package/dist/lib/generated/Entities/MJEntityDocument/mjentitydocument.form.component.js.map +1 -1
  180. package/dist/lib/generated/Entities/MJExperiment/mjexperiment.form.component.d.ts +10 -0
  181. package/dist/lib/generated/Entities/MJExperiment/mjexperiment.form.component.d.ts.map +1 -0
  182. package/dist/lib/generated/Entities/MJExperiment/mjexperiment.form.component.js +99 -0
  183. package/dist/lib/generated/Entities/MJExperiment/mjexperiment.form.component.js.map +1 -0
  184. package/dist/lib/generated/Entities/MJExperimentSession/mjexperimentsession.form.component.d.ts +10 -0
  185. package/dist/lib/generated/Entities/MJExperimentSession/mjexperimentsession.form.component.d.ts.map +1 -0
  186. package/dist/lib/generated/Entities/MJExperimentSession/mjexperimentsession.form.component.js +101 -0
  187. package/dist/lib/generated/Entities/MJExperimentSession/mjexperimentsession.form.component.js.map +1 -0
  188. package/dist/lib/generated/Entities/MJExperimentSessionIteration/mjexperimentsessioniteration.form.component.d.ts +10 -0
  189. package/dist/lib/generated/Entities/MJExperimentSessionIteration/mjexperimentsessioniteration.form.component.d.ts.map +1 -0
  190. package/dist/lib/generated/Entities/MJExperimentSessionIteration/mjexperimentsessioniteration.form.component.js +115 -0
  191. package/dist/lib/generated/Entities/MJExperimentSessionIteration/mjexperimentsessioniteration.form.component.js.map +1 -0
  192. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.d.ts.map +1 -1
  193. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js +63 -9
  194. package/dist/lib/generated/Entities/MJFile/mjfile.form.component.js.map +1 -1
  195. package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.d.ts.map +1 -1
  196. package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js +32 -14
  197. package/dist/lib/generated/Entities/MJFileStorageProvider/mjfilestorageprovider.form.component.js.map +1 -1
  198. package/dist/lib/generated/Entities/MJMLAlgorithm/mjmlalgorithm.form.component.d.ts +10 -0
  199. package/dist/lib/generated/Entities/MJMLAlgorithm/mjmlalgorithm.form.component.d.ts.map +1 -0
  200. package/dist/lib/generated/Entities/MJMLAlgorithm/mjmlalgorithm.form.component.js +161 -0
  201. package/dist/lib/generated/Entities/MJMLAlgorithm/mjmlalgorithm.form.component.js.map +1 -0
  202. package/dist/lib/generated/Entities/MJMLAlgorithmUseCase/mjmlalgorithmusecase.form.component.d.ts +10 -0
  203. package/dist/lib/generated/Entities/MJMLAlgorithmUseCase/mjmlalgorithmusecase.form.component.d.ts.map +1 -0
  204. package/dist/lib/generated/Entities/MJMLAlgorithmUseCase/mjmlalgorithmusecase.form.component.js +89 -0
  205. package/dist/lib/generated/Entities/MJMLAlgorithmUseCase/mjmlalgorithmusecase.form.component.js.map +1 -0
  206. package/dist/lib/generated/Entities/MJMLAlgorithmUseCaseRanking/mjmlalgorithmusecaseranking.form.component.d.ts +10 -0
  207. package/dist/lib/generated/Entities/MJMLAlgorithmUseCaseRanking/mjmlalgorithmusecaseranking.form.component.d.ts.map +1 -0
  208. package/dist/lib/generated/Entities/MJMLAlgorithmUseCaseRanking/mjmlalgorithmusecaseranking.form.component.js +76 -0
  209. package/dist/lib/generated/Entities/MJMLAlgorithmUseCaseRanking/mjmlalgorithmusecaseranking.form.component.js.map +1 -0
  210. package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.d.ts +10 -0
  211. package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.d.ts.map +1 -0
  212. package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js +141 -0
  213. package/dist/lib/generated/Entities/MJMLModel/mjmlmodel.form.component.js.map +1 -0
  214. package/dist/lib/generated/Entities/MJMLModelScoringBinding/mjmlmodelscoringbinding.form.component.d.ts +10 -0
  215. package/dist/lib/generated/Entities/MJMLModelScoringBinding/mjmlmodelscoringbinding.form.component.d.ts.map +1 -0
  216. package/dist/lib/generated/Entities/MJMLModelScoringBinding/mjmlmodelscoringbinding.form.component.js +88 -0
  217. package/dist/lib/generated/Entities/MJMLModelScoringBinding/mjmlmodelscoringbinding.form.component.js.map +1 -0
  218. package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.d.ts +10 -0
  219. package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.d.ts.map +1 -0
  220. package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js +143 -0
  221. package/dist/lib/generated/Entities/MJMLTrainingPipeline/mjmltrainingpipeline.form.component.js.map +1 -0
  222. package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.d.ts +10 -0
  223. package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.d.ts.map +1 -0
  224. package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js +110 -0
  225. package/dist/lib/generated/Entities/MJMLTrainingRun/mjmltrainingrun.form.component.js.map +1 -0
  226. package/dist/lib/generated/Entities/MJOpenApp/mjopenapp.form.component.d.ts.map +1 -1
  227. package/dist/lib/generated/Entities/MJOpenApp/mjopenapp.form.component.js +56 -24
  228. package/dist/lib/generated/Entities/MJOpenApp/mjopenapp.form.component.js.map +1 -1
  229. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js +19 -17
  230. package/dist/lib/generated/Entities/MJProcessRun/mjprocessrun.form.component.js.map +1 -1
  231. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.d.ts.map +1 -1
  232. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js +46 -26
  233. package/dist/lib/generated/Entities/MJRecordProcess/mjrecordprocess.form.component.js.map +1 -1
  234. package/dist/lib/generated/Entities/MJRemoteOperation/mjremoteoperation.form.component.js +12 -6
  235. package/dist/lib/generated/Entities/MJRemoteOperation/mjremoteoperation.form.component.js.map +1 -1
  236. package/dist/lib/generated/Entities/MJRole/mjrole.form.component.d.ts.map +1 -1
  237. package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +36 -18
  238. package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
  239. package/dist/lib/generated/Entities/MJSchemaInfo/mjschemainfo.form.component.js +8 -6
  240. package/dist/lib/generated/Entities/MJSchemaInfo/mjschemainfo.form.component.js.map +1 -1
  241. package/dist/lib/generated/Entities/MJScopedPromptPart/mjscopedpromptpart.form.component.d.ts +10 -0
  242. package/dist/lib/generated/Entities/MJScopedPromptPart/mjscopedpromptpart.form.component.d.ts.map +1 -0
  243. package/dist/lib/generated/Entities/MJScopedPromptPart/mjscopedpromptpart.form.component.js +78 -0
  244. package/dist/lib/generated/Entities/MJScopedPromptPart/mjscopedpromptpart.form.component.js.map +1 -0
  245. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
  246. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +145 -109
  247. package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
  248. package/dist/lib/generated/generated-forms.module.d.ts +356 -335
  249. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  250. package/dist/lib/generated/generated-forms.module.js +304 -226
  251. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  252. package/dist/lib/panels/ai-agents/agent-realtime.panel.js +44 -44
  253. package/dist/lib/panels/ai-agents/agent-realtime.panel.js.map +1 -1
  254. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts +43 -0
  255. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.d.ts.map +1 -0
  256. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js +240 -0
  257. package/dist/lib/panels/ai-skill-sharing/ai-skill-sharing-panel.component.js.map +1 -0
  258. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts +69 -0
  259. package/dist/lib/panels/model-predictions/model-prediction.logic.d.ts.map +1 -0
  260. package/dist/lib/panels/model-predictions/model-prediction.logic.js +130 -0
  261. package/dist/lib/panels/model-predictions/model-prediction.logic.js.map +1 -0
  262. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts +83 -0
  263. package/dist/lib/panels/model-predictions/model-prediction.panel.d.ts.map +1 -0
  264. package/dist/lib/panels/model-predictions/model-prediction.panel.js +293 -0
  265. package/dist/lib/panels/model-predictions/model-prediction.panel.js.map +1 -0
  266. package/package.json +38 -36
  267. package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.d.ts +0 -82
  268. package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.d.ts.map +0 -1
  269. package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js +0 -1033
  270. package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js.map +0 -1
@@ -1,18 +1,15 @@
1
1
  import { Component, Input } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  import * as i1 from "@angular/forms";
4
- import * as i2 from "@memberjunction/ng-code-editor";
4
+ import * as i2 from "@memberjunction/ng-ui-components";
5
+ import * as i3 from "@memberjunction/ng-code-editor";
5
6
  const _forTrack0 = ($index, $item) => $item.id;
6
7
  function ChatMessageViewerComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
7
- i0.ɵɵelementStart(0, "div", 9);
8
- i0.ɵɵelement(1, "i", 11);
9
- i0.ɵɵelementStart(2, "p");
10
- i0.ɵɵtext(3, "No messages to display");
11
- i0.ɵɵelementEnd()();
8
+ i0.ɵɵelement(0, "mj-empty-state", 9);
12
9
  } }
13
10
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_1_Template(rf, ctx) { if (rf & 1) {
14
- i0.ɵɵelementStart(0, "div", 27);
15
- i0.ɵɵelement(1, "mj-code-editor", 29);
11
+ i0.ɵɵelementStart(0, "div", 26);
12
+ i0.ɵɵelement(1, "mj-code-editor", 28);
16
13
  i0.ɵɵelementEnd();
17
14
  } if (rf & 2) {
18
15
  const item_r4 = i0.ɵɵnextContext(3).$implicit;
@@ -21,8 +18,8 @@ function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Condition
21
18
  i0.ɵɵproperty("value", ctx_r2.getContentString(item_r4.message.content))("readonly", true)("language", ctx_r2.getContentLanguage(item_r4.message.content));
22
19
  } }
23
20
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Conditional_10_Template(rf, ctx) { if (rf & 1) {
24
- i0.ɵɵelementStart(0, "div", 38);
25
- i0.ɵɵelement(1, "mj-code-editor", 39);
21
+ i0.ɵɵelementStart(0, "div", 37);
22
+ i0.ɵɵelement(1, "mj-code-editor", 38);
26
23
  i0.ɵɵelementEnd();
27
24
  } if (rf & 2) {
28
25
  const part_r6 = i0.ɵɵnextContext().$implicit;
@@ -31,20 +28,20 @@ function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Condition
31
28
  } }
32
29
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Template(rf, ctx) { if (rf & 1) {
33
30
  const _r5 = i0.ɵɵgetCurrentView();
34
- i0.ɵɵelementStart(0, "div", 31)(1, "div", 32);
31
+ i0.ɵɵelementStart(0, "div", 30)(1, "div", 31);
35
32
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Template_div_click_1_listener() { const part_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(6); return i0.ɵɵresetView(ctx_r2.toggleContentPart(part_r6.id)); });
36
- i0.ɵɵelementStart(2, "div", 33);
37
- i0.ɵɵelement(3, "i", 34);
33
+ i0.ɵɵelementStart(2, "div", 32);
34
+ i0.ɵɵelement(3, "i", 33);
38
35
  i0.ɵɵtext(4);
39
36
  i0.ɵɵelementEnd();
40
- i0.ɵɵelementStart(5, "div", 35)(6, "button", 36);
37
+ i0.ɵɵelementStart(5, "div", 34)(6, "button", 35);
41
38
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Template_button_click_6_listener($event) { const part_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(6); ctx_r2.openFullScreen(part_r6.value, part_r6.language, part_r6.key); return i0.ɵɵresetView($event.stopPropagation()); });
42
- i0.ɵɵelement(7, "i", 24);
39
+ i0.ɵɵelement(7, "i", 23);
43
40
  i0.ɵɵelementEnd();
44
- i0.ɵɵelementStart(8, "button", 37);
41
+ i0.ɵɵelementStart(8, "button", 36);
45
42
  i0.ɵɵelement(9, "i");
46
43
  i0.ɵɵelementEnd()()();
47
- i0.ɵɵconditionalCreate(10, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Conditional_10_Template, 2, 3, "div", 38);
44
+ i0.ɵɵconditionalCreate(10, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Conditional_10_Template, 2, 3, "div", 37);
48
45
  i0.ɵɵelementEnd();
49
46
  } if (rf & 2) {
50
47
  const part_r6 = ctx.$implicit;
@@ -57,20 +54,20 @@ function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Condition
57
54
  i0.ɵɵconditional(part_r6.expanded ? 10 : -1);
58
55
  } }
59
56
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_Template(rf, ctx) { if (rf & 1) {
60
- i0.ɵɵelementStart(0, "div", 28);
61
- i0.ɵɵrepeaterCreate(1, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Template, 11, 6, "div", 30, _forTrack0);
57
+ i0.ɵɵelementStart(0, "div", 27);
58
+ i0.ɵɵrepeaterCreate(1, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_For_2_Template, 11, 6, "div", 29, _forTrack0);
62
59
  i0.ɵɵelementEnd();
63
60
  } if (rf & 2) {
64
61
  const ctx_r6 = i0.ɵɵnextContext(3);
65
62
  const item_r4 = ctx_r6.$implicit;
66
- const ɵ$index_43_r2 = ctx_r6.$index;
63
+ const ɵ$index_38_r2 = ctx_r6.$index;
67
64
  const ctx_r2 = i0.ɵɵnextContext(2);
68
65
  i0.ɵɵadvance();
69
- i0.ɵɵrepeater(ctx_r2.getContentParts(item_r4.message.content, ɵ$index_43_r2));
66
+ i0.ɵɵrepeater(ctx_r2.getContentParts(item_r4.message.content, ɵ$index_38_r2));
70
67
  } }
71
68
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Template(rf, ctx) { if (rf & 1) {
72
- i0.ɵɵelementStart(0, "div", 26);
73
- i0.ɵɵconditionalCreate(1, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_1_Template, 2, 3, "div", 27)(2, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_Template, 3, 0, "div", 28);
69
+ i0.ɵɵelementStart(0, "div", 25);
70
+ i0.ɵɵconditionalCreate(1, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_1_Template, 2, 3, "div", 26)(2, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Conditional_2_Template, 3, 0, "div", 27);
74
71
  i0.ɵɵelementEnd();
75
72
  } if (rf & 2) {
76
73
  const item_r4 = i0.ɵɵnextContext(2).$implicit;
@@ -80,36 +77,36 @@ function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Condition
80
77
  } }
81
78
  function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
82
79
  const _r1 = i0.ɵɵgetCurrentView();
83
- i0.ɵɵelementStart(0, "div", 12)(1, "div", 13);
84
- i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r1); const ɵ$index_43_r2 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleMessage(ɵ$index_43_r2)); });
85
- i0.ɵɵelementStart(2, "div", 14)(3, "span", 15);
80
+ i0.ɵɵelementStart(0, "div", 11)(1, "div", 12);
81
+ i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r1); const ɵ$index_38_r2 = i0.ɵɵnextContext().$index; const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.toggleMessage(ɵ$index_38_r2)); });
82
+ i0.ɵɵelementStart(2, "div", 13)(3, "span", 14);
86
83
  i0.ɵɵtext(4);
87
84
  i0.ɵɵelementEnd();
88
85
  i0.ɵɵelement(5, "i");
89
- i0.ɵɵelementStart(6, "span", 16);
86
+ i0.ɵɵelementStart(6, "span", 15);
90
87
  i0.ɵɵtext(7);
91
88
  i0.ɵɵelementEnd();
92
- i0.ɵɵelementStart(8, "span", 17)(9, "span", 18);
89
+ i0.ɵɵelementStart(8, "span", 16)(9, "span", 17);
93
90
  i0.ɵɵtext(10);
94
91
  i0.ɵɵelementEnd();
95
- i0.ɵɵelementStart(11, "span", 19);
92
+ i0.ɵɵelementStart(11, "span", 18);
96
93
  i0.ɵɵtext(12, "\u2022");
97
94
  i0.ɵɵelementEnd();
98
- i0.ɵɵelementStart(13, "span", 18);
95
+ i0.ɵɵelementStart(13, "span", 17);
99
96
  i0.ɵɵtext(14);
100
97
  i0.ɵɵelementEnd()()();
101
- i0.ɵɵelementStart(15, "div", 20)(16, "button", 21);
98
+ i0.ɵɵelementStart(15, "div", 19)(16, "button", 20);
102
99
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template_button_click_16_listener($event) { i0.ɵɵrestoreView(_r1); const item_r4 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.copyMessageContent(item_r4.message.content); return i0.ɵɵresetView($event.stopPropagation()); });
103
- i0.ɵɵelement(17, "i", 22);
100
+ i0.ɵɵelement(17, "i", 21);
104
101
  i0.ɵɵelementEnd();
105
- i0.ɵɵelementStart(18, "button", 23);
102
+ i0.ɵɵelementStart(18, "button", 22);
106
103
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template_button_click_18_listener($event) { i0.ɵɵrestoreView(_r1); const item_r4 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(2); ctx_r2.openFullScreen(ctx_r2.getContentString(item_r4.message.content), ctx_r2.getContentLanguage(item_r4.message.content), ctx_r2.getRoleLabel(item_r4.message.role) + " #" + item_r4.sequenceNumber); return i0.ɵɵresetView($event.stopPropagation()); });
107
- i0.ɵɵelement(19, "i", 24);
104
+ i0.ɵɵelement(19, "i", 23);
108
105
  i0.ɵɵelementEnd();
109
- i0.ɵɵelementStart(20, "button", 25);
106
+ i0.ɵɵelementStart(20, "button", 24);
110
107
  i0.ɵɵelement(21, "i");
111
108
  i0.ɵɵelementEnd()()();
112
- i0.ɵɵconditionalCreate(22, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Template, 3, 1, "div", 26);
109
+ i0.ɵɵconditionalCreate(22, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Conditional_22_Template, 3, 1, "div", 25);
113
110
  i0.ɵɵelementEnd();
114
111
  } if (rf & 2) {
115
112
  const item_r4 = i0.ɵɵnextContext().$implicit;
@@ -132,7 +129,7 @@ function ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template(
132
129
  i0.ɵɵconditional(item_r4.expanded ? 22 : -1);
133
130
  } }
134
131
  function ChatMessageViewerComponent_Conditional_19_For_1_Template(rf, ctx) { if (rf & 1) {
135
- i0.ɵɵconditionalCreate(0, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template, 23, 12, "div", 12);
132
+ i0.ɵɵconditionalCreate(0, ChatMessageViewerComponent_Conditional_19_For_1_Conditional_0_Template, 23, 12, "div", 11);
136
133
  } if (rf & 2) {
137
134
  const item_r4 = ctx.$implicit;
138
135
  i0.ɵɵconditional(item_r4.visible ? 0 : -1);
@@ -145,24 +142,24 @@ function ChatMessageViewerComponent_Conditional_19_Template(rf, ctx) { if (rf &
145
142
  } }
146
143
  function ChatMessageViewerComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
147
144
  const _r8 = i0.ɵɵgetCurrentView();
148
- i0.ɵɵelementStart(0, "div", 40);
145
+ i0.ɵɵelementStart(0, "div", 39);
149
146
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_20_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeFullScreen()); });
150
- i0.ɵɵelementStart(1, "div", 41);
147
+ i0.ɵɵelementStart(1, "div", 40);
151
148
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_20_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r8); return i0.ɵɵresetView($event.stopPropagation()); });
152
- i0.ɵɵelementStart(2, "div", 42)(3, "span", 43);
153
- i0.ɵɵelement(4, "i", 24);
149
+ i0.ɵɵelementStart(2, "div", 41)(3, "span", 42);
150
+ i0.ɵɵelement(4, "i", 23);
154
151
  i0.ɵɵtext(5);
155
152
  i0.ɵɵelementEnd();
156
- i0.ɵɵelementStart(6, "div", 44)(7, "button", 45);
153
+ i0.ɵɵelementStart(6, "div", 43)(7, "button", 44);
157
154
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_20_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.copyToClipboard(ctx_r2.FullScreenContent)); });
158
- i0.ɵɵelement(8, "i", 22);
155
+ i0.ɵɵelement(8, "i", 21);
159
156
  i0.ɵɵelementEnd();
160
- i0.ɵɵelementStart(9, "button", 46);
157
+ i0.ɵɵelementStart(9, "button", 45);
161
158
  i0.ɵɵlistener("click", function ChatMessageViewerComponent_Conditional_20_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeFullScreen()); });
162
- i0.ɵɵelement(10, "i", 47);
159
+ i0.ɵɵelement(10, "i", 46);
163
160
  i0.ɵɵelementEnd()()();
164
- i0.ɵɵelementStart(11, "div", 48);
165
- i0.ɵɵelement(12, "mj-code-editor", 49);
161
+ i0.ɵɵelementStart(11, "div", 47);
162
+ i0.ɵɵelement(12, "mj-code-editor", 48);
166
163
  i0.ɵɵelementEnd()()();
167
164
  } if (rf & 2) {
168
165
  const ctx_r2 = i0.ɵɵnextContext();
@@ -534,7 +531,7 @@ export class ChatMessageViewerComponent {
534
531
  });
535
532
  }
536
533
  static { this.ɵfac = function ChatMessageViewerComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ChatMessageViewerComponent)(); }; }
537
- static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatMessageViewerComponent, selectors: [["mj-chat-message-viewer"]], inputs: { messages: "messages" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 21, vars: 11, consts: [[1, "chat-message-viewer"], [1, "filter-controls"], [1, "filter-checkbox"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "filter-label"], [1, "fa-solid", "fa-cog"], [1, "fa-solid", "fa-user"], [1, "fa-solid", "fa-robot"], [1, "messages-container"], [1, "empty-state"], [1, "fullscreen-overlay"], [1, "fa-solid", "fa-comments"], [1, "message-card"], [1, "message-header", 3, "click"], [1, "message-role"], [1, "sequence-number"], [1, "role-label"], [1, "content-stats"], [1, "stat-item"], [1, "stat-divider"], [1, "message-actions"], ["type", "button", "title", "Copy message content", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-copy"], ["type", "button", "title", "View full screen", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-expand"], ["type", "button", 1, "toggle-button"], [1, "message-content"], [1, "text-content"], [1, "multi-part-content"], [2, "max-height", "600px", "overflow-y", "auto", 3, "value", "readonly", "language"], [1, "content-part", 3, "collapsed"], [1, "content-part"], [1, "content-part-label", 3, "click"], [1, "content-part-label-content"], [1, "fa-solid", "fa-tag"], [1, "content-part-actions"], ["type", "button", "title", "View full screen", 1, "content-part-toggle", 3, "click"], ["type", "button", 1, "content-part-toggle"], [1, "content-part-editor"], [2, "max-height", "400px", "overflow-y", "auto", 3, "value", "readonly", "language"], [1, "fullscreen-overlay", 3, "click"], [1, "fullscreen-container", 3, "click"], [1, "fullscreen-header"], [1, "fullscreen-title"], [1, "fullscreen-actions"], ["type", "button", "title", "Copy content", 1, "action-button", 3, "click"], ["type", "button", "title", "Close", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fullscreen-body"], [2, "height", "100%", "width", "100%", 3, "value", "readonly", "language"]], template: function ChatMessageViewerComponent_Template(rf, ctx) { if (rf & 1) {
534
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ChatMessageViewerComponent, selectors: [["mj-chat-message-viewer"]], inputs: { messages: "messages" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 21, vars: 11, consts: [[1, "chat-message-viewer"], [1, "filter-controls"], [1, "filter-checkbox"], ["type", "checkbox", 1, "mj-checkbox", 3, "ngModelChange", "ngModel"], [1, "filter-label"], [1, "fa-solid", "fa-cog"], [1, "fa-solid", "fa-user"], [1, "fa-solid", "fa-robot"], [1, "messages-container"], ["Icon", "fa-solid fa-comments", "Title", "No messages to display"], [1, "fullscreen-overlay"], [1, "message-card"], [1, "message-header", 3, "click"], [1, "message-role"], [1, "sequence-number"], [1, "role-label"], [1, "content-stats"], [1, "stat-item"], [1, "stat-divider"], [1, "message-actions"], ["type", "button", "title", "Copy message content", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-copy"], ["type", "button", "title", "View full screen", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-expand"], ["type", "button", 1, "toggle-button"], [1, "message-content"], [1, "text-content"], [1, "multi-part-content"], [2, "max-height", "600px", "overflow-y", "auto", 3, "value", "readonly", "language"], [1, "content-part", 3, "collapsed"], [1, "content-part"], [1, "content-part-label", 3, "click"], [1, "content-part-label-content"], [1, "fa-solid", "fa-tag"], [1, "content-part-actions"], ["type", "button", "title", "View full screen", 1, "content-part-toggle", 3, "click"], ["type", "button", 1, "content-part-toggle"], [1, "content-part-editor"], [2, "max-height", "400px", "overflow-y", "auto", 3, "value", "readonly", "language"], [1, "fullscreen-overlay", 3, "click"], [1, "fullscreen-container", 3, "click"], [1, "fullscreen-header"], [1, "fullscreen-title"], [1, "fullscreen-actions"], ["type", "button", "title", "Copy content", 1, "action-button", 3, "click"], ["type", "button", "title", "Close", 1, "action-button", 3, "click"], [1, "fa-solid", "fa-times"], [1, "fullscreen-body"], [2, "height", "100%", "width", "100%", 3, "value", "readonly", "language"]], template: function ChatMessageViewerComponent_Template(rf, ctx) { if (rf & 1) {
538
535
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "label", 2)(3, "input", 3);
539
536
  i0.ɵɵtwoWayListener("ngModelChange", function ChatMessageViewerComponent_Template_input_ngModelChange_3_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.showSystem, $event) || (ctx.showSystem = $event); return $event; });
540
537
  i0.ɵɵlistener("ngModelChange", function ChatMessageViewerComponent_Template_input_ngModelChange_3_listener() { return ctx.onFilterChange(); });
@@ -560,7 +557,7 @@ export class ChatMessageViewerComponent {
560
557
  i0.ɵɵtext(16, " Assistant ");
561
558
  i0.ɵɵelementEnd()()();
562
559
  i0.ɵɵelementStart(17, "div", 8);
563
- i0.ɵɵconditionalCreate(18, ChatMessageViewerComponent_Conditional_18_Template, 4, 0, "div", 9)(19, ChatMessageViewerComponent_Conditional_19_Template, 2, 0);
560
+ i0.ɵɵconditionalCreate(18, ChatMessageViewerComponent_Conditional_18_Template, 1, 0, "mj-empty-state", 9)(19, ChatMessageViewerComponent_Conditional_19_Template, 2, 0);
564
561
  i0.ɵɵelementEnd();
565
562
  i0.ɵɵconditionalCreate(20, ChatMessageViewerComponent_Conditional_20_Template, 13, 4, "div", 10);
566
563
  i0.ɵɵelementEnd();
@@ -581,11 +578,11 @@ export class ChatMessageViewerComponent {
581
578
  i0.ɵɵconditional(ctx.displayMessages.length === 0 ? 18 : 19);
582
579
  i0.ɵɵadvance(2);
583
580
  i0.ɵɵconditional(ctx.FullScreenContent ? 20 : -1);
584
- } }, dependencies: [i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.CodeEditorComponent], styles: [".chat-message-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden; \n\n}\n\n\n\n\n.filter-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n padding: 0.75rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n margin-bottom: 1rem;\n flex-shrink: 0; \n\n}\n\n.filter-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n cursor: pointer;\n user-select: none;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n margin-right: 0.5rem;\n}\n\n.filter-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.filter-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n padding-bottom: 1rem; \n\n max-height: 800px;\n}\n\n.empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 3rem;\n margin-bottom: 1rem;\n}\n\n.empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n font-size: 1rem;\n margin: 0;\n}\n\n\n\n.message-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 0.75rem;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.message-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-sm);\n}\n\n.message-card[_ngcontent-%COMP%]:last-child {\n margin-bottom: 2rem; \n\n}\n\n.message-card[data-role=\"system\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.message-card[data-role=\"user\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-status-success);\n}\n\n.message-card[data-role=\"assistant\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background-color: var(--mj-bg-surface-sunken);\n cursor: pointer;\n user-select: none;\n}\n\n.message-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.message-role[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.sequence-number[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 0.85rem;\n margin-right: 4px;\n}\n\n.message-role[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n}\n\n.content-stats[_ngcontent-%COMP%] {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n font-weight: 400;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.stat-divider[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.role-label[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.875rem;\n text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.message-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-button[_ngcontent-%COMP%], \n.toggle-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s ease;\n}\n\n.action-button[_ngcontent-%COMP%]:hover, \n.toggle-button[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.action-button[_ngcontent-%COMP%] {\n padding: 0.25rem 0.5rem;\n}\n\n.action-button[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n}\n\n\n\n.message-content[_ngcontent-%COMP%] {\n padding: 1rem;\n}\n\n.content-blocks[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.content-block-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n border-radius: 9999px;\n font-size: 0.75rem;\n color: var(--mj-brand-primary-hover);\n}\n\n.content-block-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n\n\n.text-content[_ngcontent-%COMP%], \n.json-content[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.json-content[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.text-content[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%], \n.json-content[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n min-height: 100px;\n}\n\n\n\n.multi-part-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.content-part[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.content-part-label[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s;\n}\n\n.content-part-label[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-border-default);\n}\n\n.content-part-label-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.content-part-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n.content-part-toggle[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.content-part-toggle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.content-part.collapsed[_ngcontent-%COMP%] .content-part-label[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.content-part-editor[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.content-part-editor[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n min-height: 80px;\n}\n\n\n\n.chat-message-viewer[_ngcontent-%COMP%] .cm-editor[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n.chat-message-viewer[_ngcontent-%COMP%] .cm-editor.cm-focused[_ngcontent-%COMP%] {\n outline: none;\n}\n\n\n\n.content-part-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n\n.fullscreen-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n z-index: 10000;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.6));\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\n\n.fullscreen-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n max-width: 95vw;\n max-height: 95vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n overflow: hidden;\n}\n\n.fullscreen-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.fullscreen-title[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.fullscreen-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.fullscreen-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fullscreen-actions[_ngcontent-%COMP%] .action-button[_ngcontent-%COMP%] {\n font-size: 1rem;\n padding: 0.375rem 0.5rem;\n}\n\n.fullscreen-body[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.fullscreen-body[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n}\n\n\n\n@media (max-width: 640px) {\n .filter-controls[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .filter-checkbox[_ngcontent-%COMP%] {\n min-width: calc(50% - 0.375rem);\n }\n}"] }); }
581
+ } }, dependencies: [i1.CheckboxControlValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJEmptyStateComponent, i3.CodeEditorComponent], styles: [".chat-message-viewer[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden; \n\n}\n\n\n\n\n.filter-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n padding: 0.75rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n margin-bottom: 1rem;\n flex-shrink: 0; \n\n}\n\n.filter-checkbox[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n cursor: pointer;\n user-select: none;\n}\n\n.filter-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n margin-right: 0.5rem;\n}\n\n.filter-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.filter-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1rem;\n}\n\n\n\n.messages-container[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n padding-bottom: 1rem; \n\n max-height: 800px;\n}\n\n\n\n.message-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 0.75rem;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.message-card[_ngcontent-%COMP%]:hover {\n box-shadow: var(--mj-shadow-sm);\n}\n\n.message-card[_ngcontent-%COMP%]:last-child {\n margin-bottom: 2rem; \n\n}\n\n.message-card[data-role=\"system\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.message-card[data-role=\"user\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-status-success);\n}\n\n.message-card[data-role=\"assistant\"][_ngcontent-%COMP%] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background-color: var(--mj-bg-surface-sunken);\n cursor: pointer;\n user-select: none;\n}\n\n.message-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.message-role[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.sequence-number[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 0.85rem;\n margin-right: 4px;\n}\n\n.message-role[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 1.125rem;\n}\n\n.content-stats[_ngcontent-%COMP%] {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n font-weight: 400;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n white-space: nowrap;\n}\n\n.stat-divider[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n}\n\n.role-label[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.875rem;\n text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.message-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-button[_ngcontent-%COMP%], \n.toggle-button[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s ease;\n}\n\n.action-button[_ngcontent-%COMP%]:hover, \n.toggle-button[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.action-button[_ngcontent-%COMP%] {\n padding: 0.25rem 0.5rem;\n}\n\n.action-button[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-primary);\n}\n\n\n\n.message-content[_ngcontent-%COMP%] {\n padding: 1rem;\n}\n\n.content-blocks[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.content-block-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n border-radius: 9999px;\n font-size: 0.75rem;\n color: var(--mj-brand-primary-hover);\n}\n\n.content-block-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n\n\n.text-content[_ngcontent-%COMP%], \n.json-content[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.json-content[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.text-content[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%], \n.json-content[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n min-height: 100px;\n}\n\n\n\n.multi-part-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.content-part[_ngcontent-%COMP%] {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.content-part-label[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s;\n}\n\n.content-part-label[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-border-default);\n}\n\n.content-part-label-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.content-part-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n.content-part-toggle[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.content-part-toggle[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-primary);\n}\n\n.content-part.collapsed[_ngcontent-%COMP%] .content-part-label[_ngcontent-%COMP%] {\n border-bottom: none;\n}\n\n.content-part-editor[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.content-part-editor[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n min-height: 80px;\n}\n\n\n\n.chat-message-viewer[_ngcontent-%COMP%] .cm-editor[_ngcontent-%COMP%] {\n font-size: 0.875rem;\n}\n\n.chat-message-viewer[_ngcontent-%COMP%] .cm-editor.cm-focused[_ngcontent-%COMP%] {\n outline: none;\n}\n\n\n\n.content-part-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n\n.fullscreen-overlay[_ngcontent-%COMP%] {\n position: fixed;\n inset: 0;\n z-index: 10000;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.6));\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\n\n.fullscreen-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n max-width: 95vw;\n max-height: 95vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n overflow: hidden;\n}\n\n.fullscreen-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.fullscreen-title[_ngcontent-%COMP%] {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.fullscreen-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n}\n\n.fullscreen-actions[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fullscreen-actions[_ngcontent-%COMP%] .action-button[_ngcontent-%COMP%] {\n font-size: 1rem;\n padding: 0.375rem 0.5rem;\n}\n\n.fullscreen-body[_ngcontent-%COMP%] {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.fullscreen-body[_ngcontent-%COMP%] mj-code-editor[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n}\n\n\n\n@media (max-width: 640px) {\n .filter-controls[_ngcontent-%COMP%] {\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .filter-checkbox[_ngcontent-%COMP%] {\n min-width: calc(50% - 0.375rem);\n }\n}"] }); }
585
582
  }
586
583
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ChatMessageViewerComponent, [{
587
584
  type: Component,
588
- args: [{ standalone: false, selector: 'mj-chat-message-viewer', template: "<div class=\"chat-message-viewer\">\n <!-- Filter Controls -->\n <div class=\"filter-controls\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showSystem\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-cog\" [style.color]=\"getRoleColor('system')\"></i>\n System\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showUser\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-user\" [style.color]=\"getRoleColor('user')\"></i>\n User\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showAssistant\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-robot\" [style.color]=\"getRoleColor('assistant')\"></i>\n Assistant\n </span>\n </label>\n </div>\n \n <!-- Messages List -->\n <div class=\"messages-container\">\n @if (displayMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <p>No messages to display</p>\n </div>\n } @else {\n @for (item of displayMessages; track $index; let i = $index) {\n @if (item.visible) {\n <div class=\"message-card\" [attr.data-role]=\"item.message.role\">\n <!-- Message Header -->\n <div class=\"message-header\" (click)=\"toggleMessage(i)\">\n <div class=\"message-role\">\n <span class=\"sequence-number\">#{{ item.sequenceNumber }}</span>\n <i [class]=\"'fa-solid ' + getRoleIcon(item.message.role)\" \n [style.color]=\"getRoleColor(item.message.role)\"></i>\n <span class=\"role-label\">{{ getRoleLabel(item.message.role) }}</span>\n <span class=\"content-stats\">\n <span class=\"stat-item\">{{ getContentStats(item.message.content).chars.toLocaleString() }} chars</span>\n <span class=\"stat-divider\">\u2022</span>\n <span class=\"stat-item\">~{{ getContentStats(item.message.content).approxTokens.toLocaleString() }} tokens</span>\n </span>\n </div>\n <div class=\"message-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyMessageContent(item.message.content); $event.stopPropagation()\"\n title=\"Copy message content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"openFullScreen(getContentString(item.message.content), getContentLanguage(item.message.content), getRoleLabel(item.message.role) + ' #' + item.sequenceNumber); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"toggle-button\" type=\"button\">\n <i [class]=\"item.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n \n <!-- Message Content -->\n @if (item.expanded) {\n <div class=\"message-content\">\n <!-- Main content -->\n @if (isStringContent(item.message.content)) {\n <div class=\"text-content\">\n <mj-code-editor \n [value]=\"getContentString(item.message.content)\"\n [readonly]=\"true\"\n [language]=\"getContentLanguage(item.message.content)\"\n style=\"max-height: 600px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n } @else {\n <!-- Non-string content with multiple parts -->\n <div class=\"multi-part-content\">\n @for (part of getContentParts(item.message.content, i); track part.id) {\n <div class=\"content-part\" [class.collapsed]=\"!part.expanded\">\n <div class=\"content-part-label\" (click)=\"toggleContentPart(part.id)\">\n <div class=\"content-part-label-content\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ part.key }}\n </div>\n <div class=\"content-part-actions\">\n <button class=\"content-part-toggle\" type=\"button\"\n (click)=\"openFullScreen(part.value, part.language, part.key); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"content-part-toggle\" type=\"button\">\n <i [class]=\"part.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n @if (part.expanded) {\n <div class=\"content-part-editor\">\n <mj-code-editor \n [value]=\"part.value\"\n [readonly]=\"true\"\n [language]=\"part.language\"\n style=\"max-height: 400px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Full-screen overlay -->\n @if (FullScreenContent) {\n <div class=\"fullscreen-overlay\" (click)=\"closeFullScreen()\">\n <div class=\"fullscreen-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"fullscreen-header\">\n <span class=\"fullscreen-title\">\n <i class=\"fa-solid fa-expand\"></i>\n {{ FullScreenTitle }}\n </span>\n <div class=\"fullscreen-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyToClipboard(FullScreenContent)\"\n title=\"Copy content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"closeFullScreen()\"\n title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"fullscreen-body\">\n <mj-code-editor\n [value]=\"FullScreenContent\"\n [readonly]=\"true\"\n [language]=\"FullScreenLanguage\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n</div>", styles: [".chat-message-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden; /* Prevent overflow from the parent */\n}\n\n\n/* Filter Controls */\n.filter-controls {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n padding: 0.75rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n margin-bottom: 1rem;\n flex-shrink: 0; /* Prevent filter from shrinking */\n}\n\n.filter-checkbox {\n display: flex;\n align-items: center;\n cursor: pointer;\n user-select: none;\n}\n\n.filter-checkbox input[type=\"checkbox\"] {\n margin-right: 0.5rem;\n}\n\n.filter-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.filter-label i {\n font-size: 1rem;\n}\n\n/* Messages Container */\n.messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n padding-bottom: 1rem; /* Small padding at bottom */\n max-height: 800px;\n}\n\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 3rem;\n color: var(--mj-text-muted);\n}\n\n.empty-state i {\n font-size: 3rem;\n margin-bottom: 1rem;\n}\n\n.empty-state p {\n font-size: 1rem;\n margin: 0;\n}\n\n/* Message Card */\n.message-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 0.75rem;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.message-card:hover {\n box-shadow: var(--mj-shadow-sm);\n}\n\n.message-card:last-child {\n margin-bottom: 2rem; /* Extra margin on last card to ensure it's fully visible */\n}\n\n.message-card[data-role=\"system\"] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.message-card[data-role=\"user\"] {\n border-left: 3px solid var(--mj-status-success);\n}\n\n.message-card[data-role=\"assistant\"] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* Message Header */\n.message-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background-color: var(--mj-bg-surface-sunken);\n cursor: pointer;\n user-select: none;\n}\n\n.message-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.message-role {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.sequence-number {\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 0.85rem;\n margin-right: 4px;\n}\n\n.message-role i {\n font-size: 1.125rem;\n}\n\n.content-stats {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n font-weight: 400;\n}\n\n.stat-item {\n white-space: nowrap;\n}\n\n.stat-divider {\n color: var(--mj-text-muted);\n}\n\n.role-label {\n font-weight: 600;\n font-size: 0.875rem;\n text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.message-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-button,\n.toggle-button {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s ease;\n}\n\n.action-button:hover,\n.toggle-button:hover {\n color: var(--mj-text-primary);\n}\n\n.action-button {\n padding: 0.25rem 0.5rem;\n}\n\n.action-button:hover {\n color: var(--mj-brand-primary);\n}\n\n/* Message Content */\n.message-content {\n padding: 1rem;\n}\n\n.content-blocks {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.content-block-indicator {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n border-radius: 9999px;\n font-size: 0.75rem;\n color: var(--mj-brand-primary-hover);\n}\n\n.content-block-indicator i {\n font-size: 0.875rem;\n}\n\n/* Text Content */\n.text-content,\n.json-content {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.json-content {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.text-content mj-code-editor,\n.json-content mj-code-editor {\n display: block;\n min-height: 100px;\n}\n\n/* Multi-part Content */\n.multi-part-content {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.content-part {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.content-part-label {\n background-color: var(--mj-bg-surface-sunken);\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s;\n}\n\n.content-part-label:hover {\n background-color: var(--mj-border-default);\n}\n\n.content-part-label-content {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.content-part-label i {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n.content-part-toggle {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.content-part-toggle:hover {\n color: var(--mj-text-primary);\n}\n\n.content-part.collapsed .content-part-label {\n border-bottom: none;\n}\n\n.content-part-editor {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.content-part-editor mj-code-editor {\n display: block;\n min-height: 80px;\n}\n\n/* CodeMirror Overrides for this component */\n.chat-message-viewer .cm-editor {\n font-size: 0.875rem;\n}\n\n.chat-message-viewer .cm-editor.cm-focused {\n outline: none;\n}\n\n/* Content part actions (expand + chevron side by side) */\n.content-part-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Full-screen overlay */\n.fullscreen-overlay {\n position: fixed;\n inset: 0;\n z-index: 10000;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.6));\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\n\n.fullscreen-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n max-width: 95vw;\n max-height: 95vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n overflow: hidden;\n}\n\n.fullscreen-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.fullscreen-title {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.fullscreen-title i {\n color: var(--mj-text-secondary);\n}\n\n.fullscreen-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fullscreen-actions .action-button {\n font-size: 1rem;\n padding: 0.375rem 0.5rem;\n}\n\n.fullscreen-body {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.fullscreen-body mj-code-editor {\n display: block;\n height: 100%;\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .filter-controls {\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .filter-checkbox {\n min-width: calc(50% - 0.375rem);\n }\n}"] }]
585
+ args: [{ standalone: false, selector: 'mj-chat-message-viewer', template: "<div class=\"chat-message-viewer\">\n <!-- Filter Controls -->\n <div class=\"filter-controls\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showSystem\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-cog\" [style.color]=\"getRoleColor('system')\"></i>\n System\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showUser\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-user\" [style.color]=\"getRoleColor('user')\"></i>\n User\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showAssistant\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-robot\" [style.color]=\"getRoleColor('assistant')\"></i>\n Assistant\n </span>\n </label>\n </div>\n \n <!-- Messages List -->\n <div class=\"messages-container\">\n @if (displayMessages.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages to display\" />\n } @else {\n @for (item of displayMessages; track $index; let i = $index) {\n @if (item.visible) {\n <div class=\"message-card\" [attr.data-role]=\"item.message.role\">\n <!-- Message Header -->\n <div class=\"message-header\" (click)=\"toggleMessage(i)\">\n <div class=\"message-role\">\n <span class=\"sequence-number\">#{{ item.sequenceNumber }}</span>\n <i [class]=\"'fa-solid ' + getRoleIcon(item.message.role)\" \n [style.color]=\"getRoleColor(item.message.role)\"></i>\n <span class=\"role-label\">{{ getRoleLabel(item.message.role) }}</span>\n <span class=\"content-stats\">\n <span class=\"stat-item\">{{ getContentStats(item.message.content).chars.toLocaleString() }} chars</span>\n <span class=\"stat-divider\">\u2022</span>\n <span class=\"stat-item\">~{{ getContentStats(item.message.content).approxTokens.toLocaleString() }} tokens</span>\n </span>\n </div>\n <div class=\"message-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyMessageContent(item.message.content); $event.stopPropagation()\"\n title=\"Copy message content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"openFullScreen(getContentString(item.message.content), getContentLanguage(item.message.content), getRoleLabel(item.message.role) + ' #' + item.sequenceNumber); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"toggle-button\" type=\"button\">\n <i [class]=\"item.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n \n <!-- Message Content -->\n @if (item.expanded) {\n <div class=\"message-content\">\n <!-- Main content -->\n @if (isStringContent(item.message.content)) {\n <div class=\"text-content\">\n <mj-code-editor \n [value]=\"getContentString(item.message.content)\"\n [readonly]=\"true\"\n [language]=\"getContentLanguage(item.message.content)\"\n style=\"max-height: 600px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n } @else {\n <!-- Non-string content with multiple parts -->\n <div class=\"multi-part-content\">\n @for (part of getContentParts(item.message.content, i); track part.id) {\n <div class=\"content-part\" [class.collapsed]=\"!part.expanded\">\n <div class=\"content-part-label\" (click)=\"toggleContentPart(part.id)\">\n <div class=\"content-part-label-content\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ part.key }}\n </div>\n <div class=\"content-part-actions\">\n <button class=\"content-part-toggle\" type=\"button\"\n (click)=\"openFullScreen(part.value, part.language, part.key); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"content-part-toggle\" type=\"button\">\n <i [class]=\"part.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n @if (part.expanded) {\n <div class=\"content-part-editor\">\n <mj-code-editor \n [value]=\"part.value\"\n [readonly]=\"true\"\n [language]=\"part.language\"\n style=\"max-height: 400px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Full-screen overlay -->\n @if (FullScreenContent) {\n <div class=\"fullscreen-overlay\" (click)=\"closeFullScreen()\">\n <div class=\"fullscreen-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"fullscreen-header\">\n <span class=\"fullscreen-title\">\n <i class=\"fa-solid fa-expand\"></i>\n {{ FullScreenTitle }}\n </span>\n <div class=\"fullscreen-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyToClipboard(FullScreenContent)\"\n title=\"Copy content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"closeFullScreen()\"\n title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"fullscreen-body\">\n <mj-code-editor\n [value]=\"FullScreenContent\"\n [readonly]=\"true\"\n [language]=\"FullScreenLanguage\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n</div>", styles: [".chat-message-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden; /* Prevent overflow from the parent */\n}\n\n\n/* Filter Controls */\n.filter-controls {\n display: flex;\n gap: 1.5rem;\n align-items: center;\n padding: 0.75rem;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n border: 1px solid var(--mj-border-default);\n margin-bottom: 1rem;\n flex-shrink: 0; /* Prevent filter from shrinking */\n}\n\n.filter-checkbox {\n display: flex;\n align-items: center;\n cursor: pointer;\n user-select: none;\n}\n\n.filter-checkbox input[type=\"checkbox\"] {\n margin-right: 0.5rem;\n}\n\n.filter-label {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n font-size: 0.875rem;\n font-weight: 500;\n}\n\n.filter-label i {\n font-size: 1rem;\n}\n\n/* Messages Container */\n.messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n padding-bottom: 1rem; /* Small padding at bottom */\n max-height: 800px;\n}\n\n/* Message Card */\n.message-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n margin-bottom: 0.75rem;\n overflow: hidden;\n transition: all 0.2s ease;\n}\n\n.message-card:hover {\n box-shadow: var(--mj-shadow-sm);\n}\n\n.message-card:last-child {\n margin-bottom: 2rem; /* Extra margin on last card to ensure it's fully visible */\n}\n\n.message-card[data-role=\"system\"] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.message-card[data-role=\"user\"] {\n border-left: 3px solid var(--mj-status-success);\n}\n\n.message-card[data-role=\"assistant\"] {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n/* Message Header */\n.message-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background-color: var(--mj-bg-surface-sunken);\n cursor: pointer;\n user-select: none;\n}\n\n.message-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.message-role {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.sequence-number {\n color: var(--mj-text-secondary);\n font-weight: 500;\n font-size: 0.85rem;\n margin-right: 4px;\n}\n\n.message-role i {\n font-size: 1.125rem;\n}\n\n.content-stats {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--mj-text-secondary);\n font-size: 0.8rem;\n font-weight: 400;\n}\n\n.stat-item {\n white-space: nowrap;\n}\n\n.stat-divider {\n color: var(--mj-text-muted);\n}\n\n.role-label {\n font-weight: 600;\n font-size: 0.875rem;\n text-transform: uppercase;\n letter-spacing: 0.025em;\n}\n\n.message-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.action-button,\n.toggle-button {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s ease;\n}\n\n.action-button:hover,\n.toggle-button:hover {\n color: var(--mj-text-primary);\n}\n\n.action-button {\n padding: 0.25rem 0.5rem;\n}\n\n.action-button:hover {\n color: var(--mj-brand-primary);\n}\n\n/* Message Content */\n.message-content {\n padding: 1rem;\n}\n\n.content-blocks {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5rem;\n margin-bottom: 1rem;\n}\n\n.content-block-indicator {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n padding: 0.25rem 0.75rem;\n background-color: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n border-radius: 9999px;\n font-size: 0.75rem;\n color: var(--mj-brand-primary-hover);\n}\n\n.content-block-indicator i {\n font-size: 0.875rem;\n}\n\n/* Text Content */\n.text-content,\n.json-content {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.json-content {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.text-content mj-code-editor,\n.json-content mj-code-editor {\n display: block;\n min-height: 100px;\n}\n\n/* Multi-part Content */\n.multi-part-content {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.content-part {\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.content-part-label {\n background-color: var(--mj-bg-surface-sunken);\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--mj-text-primary);\n border-bottom: 1px solid var(--mj-border-default);\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s;\n}\n\n.content-part-label:hover {\n background-color: var(--mj-border-default);\n}\n\n.content-part-label-content {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.content-part-label i {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n}\n\n.content-part-toggle {\n background: none;\n border: none;\n padding: 0.25rem;\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: color 0.2s;\n}\n\n.content-part-toggle:hover {\n color: var(--mj-text-primary);\n}\n\n.content-part.collapsed .content-part-label {\n border-bottom: none;\n}\n\n.content-part-editor {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.content-part-editor mj-code-editor {\n display: block;\n min-height: 80px;\n}\n\n/* CodeMirror Overrides for this component */\n.chat-message-viewer .cm-editor {\n font-size: 0.875rem;\n}\n\n.chat-message-viewer .cm-editor.cm-focused {\n outline: none;\n}\n\n/* Content part actions (expand + chevron side by side) */\n.content-part-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n/* Full-screen overlay */\n.fullscreen-overlay {\n position: fixed;\n inset: 0;\n z-index: 10000;\n background: var(--mj-bg-overlay, rgba(0, 0, 0, 0.6));\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n}\n\n.fullscreen-container {\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 100%;\n max-width: 95vw;\n max-height: 95vh;\n background: var(--mj-bg-surface);\n border-radius: 10px;\n border: 1px solid var(--mj-border-default);\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n overflow: hidden;\n}\n\n.fullscreen-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.fullscreen-title {\n font-weight: 600;\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.fullscreen-title i {\n color: var(--mj-text-secondary);\n}\n\n.fullscreen-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.fullscreen-actions .action-button {\n font-size: 1rem;\n padding: 0.375rem 0.5rem;\n}\n\n.fullscreen-body {\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.fullscreen-body mj-code-editor {\n display: block;\n height: 100%;\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .filter-controls {\n flex-wrap: wrap;\n gap: 0.75rem;\n }\n\n .filter-checkbox {\n min-width: calc(50% - 0.375rem);\n }\n}"] }]
589
586
  }], null, { messages: [{
590
587
  type: Input
591
588
  }] }); })();
@@ -1 +1 @@
1
- {"version":3,"file":"chat-message-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/custom/AIPromptRuns/chat-message-viewer.component.ts","../../../../src/lib/custom/AIPromptRuns/chat-message-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, OnInit, OnChanges } from '@angular/core';\nimport { ChatMessage, ChatMessageRole, ChatMessageContent, ChatMessageContentBlock } from '@memberjunction/ai';\n\ninterface MessageDisplay {\n message: ChatMessage;\n visible: boolean;\n expanded: boolean;\n sequenceNumber: number;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-message-viewer',\n templateUrl: './chat-message-viewer.component.html',\n styleUrls: ['./chat-message-viewer.component.css']\n})\nexport class ChatMessageViewerComponent implements OnInit, OnChanges {\n @Input() messages: ChatMessage[] = [];\n \n public displayMessages: MessageDisplay[] = [];\n public showSystem = true;\n public showUser = true;\n public showAssistant = true;\n \n // Full-screen overlay state\n public FullScreenContent: string | null = null;\n public FullScreenLanguage = 'markdown';\n public FullScreenTitle = '';\n\n // Track expanded state for content parts\n private contentPartStates = new Map<string, boolean>();\n \n ngOnInit() {\n this.processMessages();\n }\n \n ngOnChanges() {\n this.processMessages();\n }\n \n private processMessages() {\n this.displayMessages = this.messages.map((msg, index) => ({\n message: msg,\n visible: this.isMessageVisible(msg),\n expanded: true,\n sequenceNumber: index + 1\n }));\n }\n \n private isMessageVisible(message: ChatMessage): boolean {\n switch (message.role) {\n case 'system':\n return this.showSystem;\n case 'user':\n return this.showUser;\n case 'assistant':\n return this.showAssistant;\n default:\n return true;\n }\n }\n \n public onFilterChange() {\n this.displayMessages.forEach(dm => {\n dm.visible = this.isMessageVisible(dm.message);\n });\n }\n \n public getRoleIcon(role: string): string {\n switch (role) {\n case 'system':\n return 'fa-cog';\n case 'user':\n return 'fa-user';\n case 'assistant':\n return 'fa-robot';\n default:\n return 'fa-comment';\n }\n }\n \n public getRoleColor(role: string): string {\n switch (role) {\n case 'system':\n return '#2563eb'; // blue\n case 'user':\n return '#059669'; // green\n case 'assistant':\n return '#7c3aed'; // purple\n default:\n return '#6b7280'; // gray\n }\n }\n \n public getRoleLabel(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1);\n }\n \n public toggleMessage(index: number) {\n this.displayMessages[index].expanded = !this.displayMessages[index].expanded;\n }\n \n public getContentString(content: ChatMessageContent): string {\n if (typeof content === 'string') {\n return content;\n } else {\n const contentAny = content as any;\n // check to see if we have a text sub-property and if so\n if (contentAny.text?.trim().length > 0) {\n // we should return this \n return contentAny.text;\n }\n else {\n return JSON.stringify(content, null, 2);\n }\n }\n }\n \n public getContentLanguage(content: ChatMessageContent): string {\n const text = this.getContentString(content);\n \n // Try to detect language based on content\n if (text.trim().startsWith('{') || text.trim().startsWith('[')) {\n return 'json';\n } else if (text.includes('```') || text.includes('# ') || text.includes('**')) {\n return 'markdown';\n } else if (text.includes('function') || text.includes('const') || text.includes('let')) {\n return 'javascript';\n } else if (text.includes('SELECT') || text.includes('FROM') || text.includes('WHERE')) {\n return 'sql';\n }\n \n return 'markdown'; // default to markdown for formatting\n }\n \n public getContentBlockIcon(type: string): string {\n switch (type) {\n case 'image_url':\n return 'fa-image';\n case 'video_url':\n return 'fa-video';\n case 'audio_url':\n return 'fa-music';\n case 'file_url':\n return 'fa-file';\n default:\n return 'fa-paperclip';\n }\n }\n \n public isStringContent(content: ChatMessageContent): boolean {\n return typeof content === 'string';\n }\n \n public getContentJSON(content: ChatMessageContent): string {\n if (typeof content === 'string') {\n return content; // Shouldn't happen but just in case\n }\n // check to see if we have a text sub-property and if so\n // check to see if there are any other sub-properties that have non-empty values or non-empty-arrays/non-empty-object values\n const contentAny = content as any;\n if (contentAny.text?.trim().length > 0) {\n // check to see if there is just one more property called json, if that is the case, append that with a ```json block to the text\n // and return that\n if (contentAny.json) {\n return contentAny.text + '\\n\\n```json\\n' + JSON.stringify(contentAny.json, null, 2) + '\\n```';\n }\n else {\n // now check to see if there are any other sub-properties that have non-empty values or non-empty-arrays/non-empty-object values\n const hasNonEmptySubProps = Object.keys(contentAny).some(key => {\n if (key === 'text') return false; // skip text property\n const value = contentAny[key];\n if (typeof value === 'string' && value.trim().length > 0) return true;\n if (Array.isArray(value) && value.length > 0) return true;\n if (typeof value === 'object' && value !== null && Object.keys(value).length > 0) return true;\n return false;\n });\n if (hasNonEmptySubProps) {\n // return the full JSON with text included\n return JSON.stringify(contentAny, null, 2);\n }\n else {\n // if there are no other non-empty sub-properties, just return the text\n return contentAny.text;\n }\n }\n }\n else {\n // if there is no text property, just return the full JSON\n return JSON.stringify(content, null, 2);\n }\n }\n \n public getContentStats(content: ChatMessageContent): { chars: number; words: number; approxTokens: number } {\n let totalChars = 0;\n let totalWords = 0;\n \n if (typeof content === 'string') {\n // For string content, use the content directly\n totalChars = content.length;\n totalWords = content.trim() ? content.trim().split(/\\s+/).filter(word => word.length > 0).length : 0;\n } else {\n // For non-string content, calculate stats from all non-empty parts\n const contentAny = content as any;\n Object.keys(contentAny).forEach(key => {\n const value = contentAny[key];\n \n // Skip empty values\n if (value === null || value === undefined) return;\n \n let partText: string;\n if (typeof value === 'string') {\n partText = value;\n } else if (Array.isArray(value) && value.length > 0) {\n partText = JSON.stringify(value, null, 2);\n } else if (typeof value === 'object' && Object.keys(value).length > 0) {\n partText = JSON.stringify(value, null, 2);\n } else {\n return; // Skip empty arrays/objects\n }\n \n totalChars += partText.length;\n const partWords = partText.trim().split(/\\s+/).filter(word => word.length > 0).length;\n totalWords += partWords;\n });\n }\n \n const approxTokens = Math.round(totalWords * 1.25); // Average 1.25 tokens per word\n return { chars: totalChars, words: totalWords, approxTokens };\n }\n \n public copyMessageContent(content: ChatMessageContent) {\n const text = this.getContentString(content);\n navigator.clipboard.writeText(text).then(() => {\n console.log('Message content copied to clipboard');\n }).catch(err => {\n console.error('Failed to copy message:', err);\n });\n }\n \n /**\n * Get content parts for multi-part content display\n * Returns an array of {id, key, value, language, expanded} objects for each content part\n */\n public getContentParts(content: ChatMessageContent, messageIndex: number): Array<{id: string, key: string, value: string, language: string, expanded: boolean}> {\n if (typeof content === 'string') {\n const id = `msg-${messageIndex}-part-content`;\n return [{\n id: id,\n key: 'content', \n value: content, \n language: 'markdown',\n expanded: this.isPartExpanded(id)\n }];\n }\n \n const contentAny = content as any;\n const parts: Array<{id: string, key: string, value: string, language: string, expanded: boolean}> = [];\n \n // Process each key in the content object\n Object.keys(contentAny).forEach((key, index) => {\n const value = contentAny[key];\n \n // Skip empty values\n if (value === null || value === undefined) return;\n if (typeof value === 'string' && value.trim().length === 0) return;\n if (Array.isArray(value) && value.length === 0) return;\n if (typeof value === 'object' && Object.keys(value).length === 0) return;\n \n // Determine the display value and language\n let displayValue: string;\n let language: string;\n \n if (typeof value === 'string') {\n displayValue = value;\n language = this.detectLanguageForKey(key, value);\n } else {\n // For objects/arrays, stringify them\n displayValue = JSON.stringify(value, null, 2);\n language = 'json';\n }\n \n const id = `msg-${messageIndex}-part-${key}`;\n parts.push({\n id: id,\n key: this.formatKeyLabel(key),\n value: displayValue,\n language: language,\n expanded: this.isPartExpanded(id)\n });\n });\n \n return parts;\n }\n \n /**\n * Detect language based on key name and content\n */\n private detectLanguageForKey(key: string, value: string): string {\n // Check key-based hints first\n const keyLower = key.toLowerCase();\n if (keyLower.includes('json') || keyLower.includes('data')) return 'json';\n if (keyLower.includes('sql') || keyLower.includes('query')) return 'sql';\n if (keyLower.includes('code') || keyLower.includes('script')) return 'javascript';\n if (keyLower.includes('markdown') || keyLower.includes('md')) return 'markdown';\n if (keyLower.includes('html')) return 'html';\n if (keyLower.includes('css')) return 'css';\n if (keyLower.includes('xml')) return 'xml';\n if (keyLower.includes('yaml') || keyLower.includes('yml')) return 'yaml';\n \n // Fall back to content detection\n return this.getContentLanguage({text: value} as any);\n }\n \n /**\n * Format key name for display label\n */\n private formatKeyLabel(key: string): string {\n // Convert camelCase or snake_case to Title Case\n return key\n .replace(/([A-Z])/g, ' $1') // Add space before capitals\n .replace(/_/g, ' ') // Replace underscores with spaces\n .replace(/\\b\\w/g, l => l.toUpperCase()) // Capitalize first letter of each word\n .trim();\n }\n \n /**\n * Check if content has multiple parts (for non-string content)\n */\n public hasMultipleParts(content: ChatMessageContent): boolean {\n if (typeof content === 'string') return false;\n \n const contentAny = content as any;\n const nonEmptyKeys = Object.keys(contentAny).filter(key => {\n const value = contentAny[key];\n if (value === null || value === undefined) return false;\n if (typeof value === 'string' && value.trim().length === 0) return false;\n if (Array.isArray(value) && value.length === 0) return false;\n if (typeof value === 'object' && Object.keys(value).length === 0) return false;\n return true;\n });\n \n return nonEmptyKeys.length > 1;\n }\n \n /**\n * Check if a content part is expanded\n */\n private isPartExpanded(partId: string): boolean {\n // Default to expanded for all parts initially\n if (!this.contentPartStates.has(partId)) {\n this.contentPartStates.set(partId, true);\n }\n return this.contentPartStates.get(partId) || false;\n }\n \n /**\n * Toggle the expanded state of a content part\n */\n public toggleContentPart(partId: string): void {\n const currentState = this.contentPartStates.get(partId) || false;\n this.contentPartStates.set(partId, !currentState);\n }\n\n /**\n * Open the full-screen overlay with the given content\n */\n public openFullScreen(content: string, language: string, title: string): void {\n this.FullScreenContent = content;\n this.FullScreenLanguage = language;\n this.FullScreenTitle = title;\n }\n\n /**\n * Close the full-screen overlay\n */\n public closeFullScreen(): void {\n this.FullScreenContent = null;\n }\n\n /**\n * Copy text to clipboard\n */\n public copyToClipboard(text: string): void {\n navigator.clipboard.writeText(text).then(() => {\n console.log('Content copied to clipboard');\n }).catch(err => {\n console.error('Failed to copy:', err);\n });\n }\n}","<div class=\"chat-message-viewer\">\n <!-- Filter Controls -->\n <div class=\"filter-controls\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showSystem\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-cog\" [style.color]=\"getRoleColor('system')\"></i>\n System\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showUser\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-user\" [style.color]=\"getRoleColor('user')\"></i>\n User\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showAssistant\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-robot\" [style.color]=\"getRoleColor('assistant')\"></i>\n Assistant\n </span>\n </label>\n </div>\n \n <!-- Messages List -->\n <div class=\"messages-container\">\n @if (displayMessages.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comments\"></i>\n <p>No messages to display</p>\n </div>\n } @else {\n @for (item of displayMessages; track $index; let i = $index) {\n @if (item.visible) {\n <div class=\"message-card\" [attr.data-role]=\"item.message.role\">\n <!-- Message Header -->\n <div class=\"message-header\" (click)=\"toggleMessage(i)\">\n <div class=\"message-role\">\n <span class=\"sequence-number\">#{{ item.sequenceNumber }}</span>\n <i [class]=\"'fa-solid ' + getRoleIcon(item.message.role)\" \n [style.color]=\"getRoleColor(item.message.role)\"></i>\n <span class=\"role-label\">{{ getRoleLabel(item.message.role) }}</span>\n <span class=\"content-stats\">\n <span class=\"stat-item\">{{ getContentStats(item.message.content).chars.toLocaleString() }} chars</span>\n <span class=\"stat-divider\">•</span>\n <span class=\"stat-item\">~{{ getContentStats(item.message.content).approxTokens.toLocaleString() }} tokens</span>\n </span>\n </div>\n <div class=\"message-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyMessageContent(item.message.content); $event.stopPropagation()\"\n title=\"Copy message content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"openFullScreen(getContentString(item.message.content), getContentLanguage(item.message.content), getRoleLabel(item.message.role) + ' #' + item.sequenceNumber); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"toggle-button\" type=\"button\">\n <i [class]=\"item.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n \n <!-- Message Content -->\n @if (item.expanded) {\n <div class=\"message-content\">\n <!-- Main content -->\n @if (isStringContent(item.message.content)) {\n <div class=\"text-content\">\n <mj-code-editor \n [value]=\"getContentString(item.message.content)\"\n [readonly]=\"true\"\n [language]=\"getContentLanguage(item.message.content)\"\n style=\"max-height: 600px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n } @else {\n <!-- Non-string content with multiple parts -->\n <div class=\"multi-part-content\">\n @for (part of getContentParts(item.message.content, i); track part.id) {\n <div class=\"content-part\" [class.collapsed]=\"!part.expanded\">\n <div class=\"content-part-label\" (click)=\"toggleContentPart(part.id)\">\n <div class=\"content-part-label-content\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ part.key }}\n </div>\n <div class=\"content-part-actions\">\n <button class=\"content-part-toggle\" type=\"button\"\n (click)=\"openFullScreen(part.value, part.language, part.key); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"content-part-toggle\" type=\"button\">\n <i [class]=\"part.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n @if (part.expanded) {\n <div class=\"content-part-editor\">\n <mj-code-editor \n [value]=\"part.value\"\n [readonly]=\"true\"\n [language]=\"part.language\"\n style=\"max-height: 400px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Full-screen overlay -->\n @if (FullScreenContent) {\n <div class=\"fullscreen-overlay\" (click)=\"closeFullScreen()\">\n <div class=\"fullscreen-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"fullscreen-header\">\n <span class=\"fullscreen-title\">\n <i class=\"fa-solid fa-expand\"></i>\n {{ FullScreenTitle }}\n </span>\n <div class=\"fullscreen-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyToClipboard(FullScreenContent)\"\n title=\"Copy content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"closeFullScreen()\"\n title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"fullscreen-body\">\n <mj-code-editor\n [value]=\"FullScreenContent\"\n [readonly]=\"true\"\n [language]=\"FullScreenLanguage\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n</div>"]}
1
+ {"version":3,"file":"chat-message-viewer.component.js","sourceRoot":"","sources":["../../../../src/lib/custom/AIPromptRuns/chat-message-viewer.component.ts","../../../../src/lib/custom/AIPromptRuns/chat-message-viewer.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, OnInit, OnChanges } from '@angular/core';\nimport { ChatMessage, ChatMessageRole, ChatMessageContent, ChatMessageContentBlock } from '@memberjunction/ai';\n\ninterface MessageDisplay {\n message: ChatMessage;\n visible: boolean;\n expanded: boolean;\n sequenceNumber: number;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-chat-message-viewer',\n templateUrl: './chat-message-viewer.component.html',\n styleUrls: ['./chat-message-viewer.component.css']\n})\nexport class ChatMessageViewerComponent implements OnInit, OnChanges {\n @Input() messages: ChatMessage[] = [];\n \n public displayMessages: MessageDisplay[] = [];\n public showSystem = true;\n public showUser = true;\n public showAssistant = true;\n \n // Full-screen overlay state\n public FullScreenContent: string | null = null;\n public FullScreenLanguage = 'markdown';\n public FullScreenTitle = '';\n\n // Track expanded state for content parts\n private contentPartStates = new Map<string, boolean>();\n \n ngOnInit() {\n this.processMessages();\n }\n \n ngOnChanges() {\n this.processMessages();\n }\n \n private processMessages() {\n this.displayMessages = this.messages.map((msg, index) => ({\n message: msg,\n visible: this.isMessageVisible(msg),\n expanded: true,\n sequenceNumber: index + 1\n }));\n }\n \n private isMessageVisible(message: ChatMessage): boolean {\n switch (message.role) {\n case 'system':\n return this.showSystem;\n case 'user':\n return this.showUser;\n case 'assistant':\n return this.showAssistant;\n default:\n return true;\n }\n }\n \n public onFilterChange() {\n this.displayMessages.forEach(dm => {\n dm.visible = this.isMessageVisible(dm.message);\n });\n }\n \n public getRoleIcon(role: string): string {\n switch (role) {\n case 'system':\n return 'fa-cog';\n case 'user':\n return 'fa-user';\n case 'assistant':\n return 'fa-robot';\n default:\n return 'fa-comment';\n }\n }\n \n public getRoleColor(role: string): string {\n switch (role) {\n case 'system':\n return '#2563eb'; // blue\n case 'user':\n return '#059669'; // green\n case 'assistant':\n return '#7c3aed'; // purple\n default:\n return '#6b7280'; // gray\n }\n }\n \n public getRoleLabel(role: string): string {\n return role.charAt(0).toUpperCase() + role.slice(1);\n }\n \n public toggleMessage(index: number) {\n this.displayMessages[index].expanded = !this.displayMessages[index].expanded;\n }\n \n public getContentString(content: ChatMessageContent): string {\n if (typeof content === 'string') {\n return content;\n } else {\n const contentAny = content as any;\n // check to see if we have a text sub-property and if so\n if (contentAny.text?.trim().length > 0) {\n // we should return this \n return contentAny.text;\n }\n else {\n return JSON.stringify(content, null, 2);\n }\n }\n }\n \n public getContentLanguage(content: ChatMessageContent): string {\n const text = this.getContentString(content);\n \n // Try to detect language based on content\n if (text.trim().startsWith('{') || text.trim().startsWith('[')) {\n return 'json';\n } else if (text.includes('```') || text.includes('# ') || text.includes('**')) {\n return 'markdown';\n } else if (text.includes('function') || text.includes('const') || text.includes('let')) {\n return 'javascript';\n } else if (text.includes('SELECT') || text.includes('FROM') || text.includes('WHERE')) {\n return 'sql';\n }\n \n return 'markdown'; // default to markdown for formatting\n }\n \n public getContentBlockIcon(type: string): string {\n switch (type) {\n case 'image_url':\n return 'fa-image';\n case 'video_url':\n return 'fa-video';\n case 'audio_url':\n return 'fa-music';\n case 'file_url':\n return 'fa-file';\n default:\n return 'fa-paperclip';\n }\n }\n \n public isStringContent(content: ChatMessageContent): boolean {\n return typeof content === 'string';\n }\n \n public getContentJSON(content: ChatMessageContent): string {\n if (typeof content === 'string') {\n return content; // Shouldn't happen but just in case\n }\n // check to see if we have a text sub-property and if so\n // check to see if there are any other sub-properties that have non-empty values or non-empty-arrays/non-empty-object values\n const contentAny = content as any;\n if (contentAny.text?.trim().length > 0) {\n // check to see if there is just one more property called json, if that is the case, append that with a ```json block to the text\n // and return that\n if (contentAny.json) {\n return contentAny.text + '\\n\\n```json\\n' + JSON.stringify(contentAny.json, null, 2) + '\\n```';\n }\n else {\n // now check to see if there are any other sub-properties that have non-empty values or non-empty-arrays/non-empty-object values\n const hasNonEmptySubProps = Object.keys(contentAny).some(key => {\n if (key === 'text') return false; // skip text property\n const value = contentAny[key];\n if (typeof value === 'string' && value.trim().length > 0) return true;\n if (Array.isArray(value) && value.length > 0) return true;\n if (typeof value === 'object' && value !== null && Object.keys(value).length > 0) return true;\n return false;\n });\n if (hasNonEmptySubProps) {\n // return the full JSON with text included\n return JSON.stringify(contentAny, null, 2);\n }\n else {\n // if there are no other non-empty sub-properties, just return the text\n return contentAny.text;\n }\n }\n }\n else {\n // if there is no text property, just return the full JSON\n return JSON.stringify(content, null, 2);\n }\n }\n \n public getContentStats(content: ChatMessageContent): { chars: number; words: number; approxTokens: number } {\n let totalChars = 0;\n let totalWords = 0;\n \n if (typeof content === 'string') {\n // For string content, use the content directly\n totalChars = content.length;\n totalWords = content.trim() ? content.trim().split(/\\s+/).filter(word => word.length > 0).length : 0;\n } else {\n // For non-string content, calculate stats from all non-empty parts\n const contentAny = content as any;\n Object.keys(contentAny).forEach(key => {\n const value = contentAny[key];\n \n // Skip empty values\n if (value === null || value === undefined) return;\n \n let partText: string;\n if (typeof value === 'string') {\n partText = value;\n } else if (Array.isArray(value) && value.length > 0) {\n partText = JSON.stringify(value, null, 2);\n } else if (typeof value === 'object' && Object.keys(value).length > 0) {\n partText = JSON.stringify(value, null, 2);\n } else {\n return; // Skip empty arrays/objects\n }\n \n totalChars += partText.length;\n const partWords = partText.trim().split(/\\s+/).filter(word => word.length > 0).length;\n totalWords += partWords;\n });\n }\n \n const approxTokens = Math.round(totalWords * 1.25); // Average 1.25 tokens per word\n return { chars: totalChars, words: totalWords, approxTokens };\n }\n \n public copyMessageContent(content: ChatMessageContent) {\n const text = this.getContentString(content);\n navigator.clipboard.writeText(text).then(() => {\n console.log('Message content copied to clipboard');\n }).catch(err => {\n console.error('Failed to copy message:', err);\n });\n }\n \n /**\n * Get content parts for multi-part content display\n * Returns an array of {id, key, value, language, expanded} objects for each content part\n */\n public getContentParts(content: ChatMessageContent, messageIndex: number): Array<{id: string, key: string, value: string, language: string, expanded: boolean}> {\n if (typeof content === 'string') {\n const id = `msg-${messageIndex}-part-content`;\n return [{\n id: id,\n key: 'content', \n value: content, \n language: 'markdown',\n expanded: this.isPartExpanded(id)\n }];\n }\n \n const contentAny = content as any;\n const parts: Array<{id: string, key: string, value: string, language: string, expanded: boolean}> = [];\n \n // Process each key in the content object\n Object.keys(contentAny).forEach((key, index) => {\n const value = contentAny[key];\n \n // Skip empty values\n if (value === null || value === undefined) return;\n if (typeof value === 'string' && value.trim().length === 0) return;\n if (Array.isArray(value) && value.length === 0) return;\n if (typeof value === 'object' && Object.keys(value).length === 0) return;\n \n // Determine the display value and language\n let displayValue: string;\n let language: string;\n \n if (typeof value === 'string') {\n displayValue = value;\n language = this.detectLanguageForKey(key, value);\n } else {\n // For objects/arrays, stringify them\n displayValue = JSON.stringify(value, null, 2);\n language = 'json';\n }\n \n const id = `msg-${messageIndex}-part-${key}`;\n parts.push({\n id: id,\n key: this.formatKeyLabel(key),\n value: displayValue,\n language: language,\n expanded: this.isPartExpanded(id)\n });\n });\n \n return parts;\n }\n \n /**\n * Detect language based on key name and content\n */\n private detectLanguageForKey(key: string, value: string): string {\n // Check key-based hints first\n const keyLower = key.toLowerCase();\n if (keyLower.includes('json') || keyLower.includes('data')) return 'json';\n if (keyLower.includes('sql') || keyLower.includes('query')) return 'sql';\n if (keyLower.includes('code') || keyLower.includes('script')) return 'javascript';\n if (keyLower.includes('markdown') || keyLower.includes('md')) return 'markdown';\n if (keyLower.includes('html')) return 'html';\n if (keyLower.includes('css')) return 'css';\n if (keyLower.includes('xml')) return 'xml';\n if (keyLower.includes('yaml') || keyLower.includes('yml')) return 'yaml';\n \n // Fall back to content detection\n return this.getContentLanguage({text: value} as any);\n }\n \n /**\n * Format key name for display label\n */\n private formatKeyLabel(key: string): string {\n // Convert camelCase or snake_case to Title Case\n return key\n .replace(/([A-Z])/g, ' $1') // Add space before capitals\n .replace(/_/g, ' ') // Replace underscores with spaces\n .replace(/\\b\\w/g, l => l.toUpperCase()) // Capitalize first letter of each word\n .trim();\n }\n \n /**\n * Check if content has multiple parts (for non-string content)\n */\n public hasMultipleParts(content: ChatMessageContent): boolean {\n if (typeof content === 'string') return false;\n \n const contentAny = content as any;\n const nonEmptyKeys = Object.keys(contentAny).filter(key => {\n const value = contentAny[key];\n if (value === null || value === undefined) return false;\n if (typeof value === 'string' && value.trim().length === 0) return false;\n if (Array.isArray(value) && value.length === 0) return false;\n if (typeof value === 'object' && Object.keys(value).length === 0) return false;\n return true;\n });\n \n return nonEmptyKeys.length > 1;\n }\n \n /**\n * Check if a content part is expanded\n */\n private isPartExpanded(partId: string): boolean {\n // Default to expanded for all parts initially\n if (!this.contentPartStates.has(partId)) {\n this.contentPartStates.set(partId, true);\n }\n return this.contentPartStates.get(partId) || false;\n }\n \n /**\n * Toggle the expanded state of a content part\n */\n public toggleContentPart(partId: string): void {\n const currentState = this.contentPartStates.get(partId) || false;\n this.contentPartStates.set(partId, !currentState);\n }\n\n /**\n * Open the full-screen overlay with the given content\n */\n public openFullScreen(content: string, language: string, title: string): void {\n this.FullScreenContent = content;\n this.FullScreenLanguage = language;\n this.FullScreenTitle = title;\n }\n\n /**\n * Close the full-screen overlay\n */\n public closeFullScreen(): void {\n this.FullScreenContent = null;\n }\n\n /**\n * Copy text to clipboard\n */\n public copyToClipboard(text: string): void {\n navigator.clipboard.writeText(text).then(() => {\n console.log('Content copied to clipboard');\n }).catch(err => {\n console.error('Failed to copy:', err);\n });\n }\n}","<div class=\"chat-message-viewer\">\n <!-- Filter Controls -->\n <div class=\"filter-controls\">\n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showSystem\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-cog\" [style.color]=\"getRoleColor('system')\"></i>\n System\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showUser\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-user\" [style.color]=\"getRoleColor('user')\"></i>\n User\n </span>\n </label>\n \n <label class=\"filter-checkbox\">\n <input type=\"checkbox\" \n [(ngModel)]=\"showAssistant\" \n (ngModelChange)=\"onFilterChange()\"\n class=\"mj-checkbox\" />\n <span class=\"filter-label\">\n <i class=\"fa-solid fa-robot\" [style.color]=\"getRoleColor('assistant')\"></i>\n Assistant\n </span>\n </label>\n </div>\n \n <!-- Messages List -->\n <div class=\"messages-container\">\n @if (displayMessages.length === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-comments\"\n Title=\"No messages to display\" />\n } @else {\n @for (item of displayMessages; track $index; let i = $index) {\n @if (item.visible) {\n <div class=\"message-card\" [attr.data-role]=\"item.message.role\">\n <!-- Message Header -->\n <div class=\"message-header\" (click)=\"toggleMessage(i)\">\n <div class=\"message-role\">\n <span class=\"sequence-number\">#{{ item.sequenceNumber }}</span>\n <i [class]=\"'fa-solid ' + getRoleIcon(item.message.role)\" \n [style.color]=\"getRoleColor(item.message.role)\"></i>\n <span class=\"role-label\">{{ getRoleLabel(item.message.role) }}</span>\n <span class=\"content-stats\">\n <span class=\"stat-item\">{{ getContentStats(item.message.content).chars.toLocaleString() }} chars</span>\n <span class=\"stat-divider\">•</span>\n <span class=\"stat-item\">~{{ getContentStats(item.message.content).approxTokens.toLocaleString() }} tokens</span>\n </span>\n </div>\n <div class=\"message-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyMessageContent(item.message.content); $event.stopPropagation()\"\n title=\"Copy message content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"openFullScreen(getContentString(item.message.content), getContentLanguage(item.message.content), getRoleLabel(item.message.role) + ' #' + item.sequenceNumber); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"toggle-button\" type=\"button\">\n <i [class]=\"item.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n \n <!-- Message Content -->\n @if (item.expanded) {\n <div class=\"message-content\">\n <!-- Main content -->\n @if (isStringContent(item.message.content)) {\n <div class=\"text-content\">\n <mj-code-editor \n [value]=\"getContentString(item.message.content)\"\n [readonly]=\"true\"\n [language]=\"getContentLanguage(item.message.content)\"\n style=\"max-height: 600px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n } @else {\n <!-- Non-string content with multiple parts -->\n <div class=\"multi-part-content\">\n @for (part of getContentParts(item.message.content, i); track part.id) {\n <div class=\"content-part\" [class.collapsed]=\"!part.expanded\">\n <div class=\"content-part-label\" (click)=\"toggleContentPart(part.id)\">\n <div class=\"content-part-label-content\">\n <i class=\"fa-solid fa-tag\"></i>\n {{ part.key }}\n </div>\n <div class=\"content-part-actions\">\n <button class=\"content-part-toggle\" type=\"button\"\n (click)=\"openFullScreen(part.value, part.language, part.key); $event.stopPropagation()\"\n title=\"View full screen\">\n <i class=\"fa-solid fa-expand\"></i>\n </button>\n <button class=\"content-part-toggle\" type=\"button\">\n <i [class]=\"part.expanded ? 'fa-solid fa-chevron-up' : 'fa-solid fa-chevron-down'\"></i>\n </button>\n </div>\n </div>\n @if (part.expanded) {\n <div class=\"content-part-editor\">\n <mj-code-editor \n [value]=\"part.value\"\n [readonly]=\"true\"\n [language]=\"part.language\"\n style=\"max-height: 400px; overflow-y: auto;\">\n </mj-code-editor>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n }\n </div>\n\n <!-- Full-screen overlay -->\n @if (FullScreenContent) {\n <div class=\"fullscreen-overlay\" (click)=\"closeFullScreen()\">\n <div class=\"fullscreen-container\" (click)=\"$event.stopPropagation()\">\n <div class=\"fullscreen-header\">\n <span class=\"fullscreen-title\">\n <i class=\"fa-solid fa-expand\"></i>\n {{ FullScreenTitle }}\n </span>\n <div class=\"fullscreen-actions\">\n <button class=\"action-button\" type=\"button\"\n (click)=\"copyToClipboard(FullScreenContent)\"\n title=\"Copy content\">\n <i class=\"fa-solid fa-copy\"></i>\n </button>\n <button class=\"action-button\" type=\"button\"\n (click)=\"closeFullScreen()\"\n title=\"Close\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"fullscreen-body\">\n <mj-code-editor\n [value]=\"FullScreenContent\"\n [readonly]=\"true\"\n [language]=\"FullScreenLanguage\"\n style=\"height: 100%; width: 100%;\">\n </mj-code-editor>\n </div>\n </div>\n </div>\n }\n</div>"]}