@memberjunction/ng-conversations 2.109.0 → 2.110.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/components/collection/collection-view.component.d.ts.map +1 -1
- package/dist/lib/components/collection/collection-view.component.js +2 -1
- package/dist/lib/components/collection/collection-view.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +87 -0
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +581 -209
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.js +22 -14
- package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.d.ts +6 -1
- package/dist/lib/components/dialogs/input-dialog.component.d.ts.map +1 -1
- package/dist/lib/components/dialogs/input-dialog.component.js +61 -6
- package/dist/lib/components/dialogs/input-dialog.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +22 -14
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +133 -132
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +48 -7
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +222 -132
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +5 -1
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +16 -10
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/message/suggested-responses.component.js +3 -3
- package/dist/lib/components/message/suggested-responses.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +3 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +11 -2
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/models/conversation-complete-query.model.d.ts +11 -0
- package/dist/lib/models/conversation-complete-query.model.d.ts.map +1 -1
- package/dist/lib/models/conversation-complete-query.model.js.map +1 -1
- package/dist/lib/models/lazy-artifact-info.d.ts +1 -0
- package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -1
- package/dist/lib/models/lazy-artifact-info.js +2 -0
- package/dist/lib/models/lazy-artifact-info.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +3 -3
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-state.service.js +1 -1
- package/dist/lib/services/conversation-state.service.js.map +1 -1
- package/dist/lib/services/dialog.service.d.ts +12 -2
- package/dist/lib/services/dialog.service.d.ts.map +1 -1
- package/dist/lib/services/dialog.service.js +27 -10
- package/dist/lib/services/dialog.service.js.map +1 -1
- package/dist/lib/services/search.service.js +1 -1
- package/dist/lib/services/search.service.js.map +1 -1
- package/package.json +12 -12
|
@@ -11,30 +11,37 @@ import * as i5 from "@memberjunction/ng-artifacts";
|
|
|
11
11
|
import * as i6 from "ngx-markdown";
|
|
12
12
|
import * as i7 from "./suggested-responses.component";
|
|
13
13
|
import * as i8 from "../tasks/task-widget.component";
|
|
14
|
-
function
|
|
15
|
-
i0.ɵɵ
|
|
16
|
-
|
|
17
|
-
i0.ɵɵ
|
|
18
|
-
i0.ɵɵ
|
|
14
|
+
function MessageItemComponent_Conditional_3_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
15
|
+
i0.ɵɵelement(0, "img", 15);
|
|
16
|
+
} if (rf & 2) {
|
|
17
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
18
|
+
i0.ɵɵproperty("src", ctx_r0.userAvatarUrl, i0.ɵɵsanitizeUrl);
|
|
19
|
+
} }
|
|
20
|
+
function MessageItemComponent_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
21
|
+
i0.ɵɵelement(0, "i");
|
|
22
|
+
} if (rf & 2) {
|
|
23
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
24
|
+
i0.ɵɵclassMap(ctx_r0.userAvatarIconClass);
|
|
25
|
+
} }
|
|
26
|
+
function MessageItemComponent_Conditional_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
27
|
+
i0.ɵɵelement(0, "i", 17);
|
|
28
|
+
} }
|
|
29
|
+
function MessageItemComponent_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
30
|
+
i0.ɵɵtemplate(0, MessageItemComponent_Conditional_3_Conditional_0_Template, 1, 1, "img", 15)(1, MessageItemComponent_Conditional_3_Conditional_1_Template, 1, 2, "i", 16)(2, MessageItemComponent_Conditional_3_Conditional_2_Template, 1, 0, "i", 17);
|
|
19
31
|
} if (rf & 2) {
|
|
20
32
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
21
|
-
i0.ɵɵ
|
|
22
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r0.formattedGenerationTime, " ");
|
|
33
|
+
i0.ɵɵconditional(ctx_r0.userAvatarUrl ? 0 : ctx_r0.userAvatarIconClass ? 1 : 2);
|
|
23
34
|
} }
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
i0.ɵɵelementStart(0, "span", 19);
|
|
27
|
-
i0.ɵɵlistener("click", function MessageItemComponent_span_12_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleAgentDetails()); });
|
|
28
|
-
i0.ɵɵelement(1, "i", 20);
|
|
29
|
-
i0.ɵɵelementEnd();
|
|
35
|
+
function MessageItemComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
36
|
+
i0.ɵɵelement(0, "i", 2);
|
|
30
37
|
} if (rf & 2) {
|
|
31
38
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
32
|
-
i0.ɵɵ
|
|
39
|
+
i0.ɵɵproperty("ngClass", (ctx_r0.aiAgentInfo == null ? null : ctx_r0.aiAgentInfo.iconClass) || "fa-robot");
|
|
33
40
|
} }
|
|
34
|
-
function
|
|
35
|
-
i0.ɵɵelementStart(0, "span",
|
|
41
|
+
function MessageItemComponent_span_12_Template(rf, ctx) { if (rf & 1) {
|
|
42
|
+
i0.ɵɵelementStart(0, "span", 18);
|
|
36
43
|
i0.ɵɵelement(1, "i", 2);
|
|
37
|
-
i0.ɵɵelementStart(2, "span",
|
|
44
|
+
i0.ɵɵelementStart(2, "span", 19);
|
|
38
45
|
i0.ɵɵtext(3);
|
|
39
46
|
i0.ɵɵelementEnd()();
|
|
40
47
|
} if (rf & 2) {
|
|
@@ -45,53 +52,58 @@ function MessageItemComponent_span_13_Template(rf, ctx) { if (rf & 1) {
|
|
|
45
52
|
i0.ɵɵadvance(2);
|
|
46
53
|
i0.ɵɵtextInterpolate(ctx_r0.getStatusText());
|
|
47
54
|
} }
|
|
48
|
-
function
|
|
49
|
-
i0.ɵɵelementStart(0, "span",
|
|
50
|
-
i0.ɵɵ
|
|
55
|
+
function MessageItemComponent_span_13_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelementStart(0, "span", 20);
|
|
57
|
+
i0.ɵɵelement(1, "i", 21);
|
|
58
|
+
i0.ɵɵtext(2);
|
|
51
59
|
i0.ɵɵelementEnd();
|
|
52
60
|
} if (rf & 2) {
|
|
53
61
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
54
|
-
i0.ɵɵ
|
|
55
|
-
i0.ɵɵ
|
|
62
|
+
i0.ɵɵclassProp("in-progress", ctx_r0.isInProgressAIMessage)("active", !ctx_r0.isInProgressAIMessage && ctx_r0.isAgentRunActive)("complete", !ctx_r0.isInProgressAIMessage && !ctx_r0.isAgentRunActive && ctx_r0.messageStatus === "Complete")("failed", ctx_r0.messageStatus === "Error");
|
|
63
|
+
i0.ɵɵadvance(2);
|
|
64
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.timePillText, " ");
|
|
56
65
|
} }
|
|
57
|
-
function
|
|
58
|
-
i0.ɵɵ
|
|
59
|
-
i0.ɵɵ
|
|
66
|
+
function MessageItemComponent_span_14_Template(rf, ctx) { if (rf & 1) {
|
|
67
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
68
|
+
i0.ɵɵelementStart(0, "span", 22);
|
|
69
|
+
i0.ɵɵlistener("click", function MessageItemComponent_span_14_Template_span_click_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleAgentDetails()); });
|
|
70
|
+
i0.ɵɵelement(1, "i", 23);
|
|
60
71
|
i0.ɵɵelementEnd();
|
|
61
72
|
} if (rf & 2) {
|
|
62
73
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
63
|
-
i0.ɵɵ
|
|
64
|
-
i0.ɵɵtextInterpolate1(" ", ctx_r0._agentRunDurationFormatted, " ");
|
|
74
|
+
i0.ɵɵclassProp("expanded", ctx_r0.isAgentDetailsExpanded);
|
|
65
75
|
} }
|
|
66
|
-
function
|
|
67
|
-
i0.ɵɵelementStart(0, "span",
|
|
76
|
+
function MessageItemComponent_Conditional_16_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
77
|
+
i0.ɵɵelementStart(0, "span", 26);
|
|
68
78
|
i0.ɵɵtext(1, "(edited)");
|
|
69
79
|
i0.ɵɵelementEnd();
|
|
70
80
|
} }
|
|
71
|
-
function
|
|
81
|
+
function MessageItemComponent_Conditional_16_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
72
82
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
73
|
-
i0.ɵɵelementStart(0, "mj-artifact-message-card", 30);
|
|
74
|
-
i0.ɵɵlistener("actionPerformed", function
|
|
75
|
-
i0.ɵɵelementEnd();
|
|
83
|
+
i0.ɵɵelementStart(0, "div", 29)(1, "mj-artifact-message-card", 30);
|
|
84
|
+
i0.ɵɵlistener("actionPerformed", function MessageItemComponent_Conditional_16_Conditional_3_Template_mj_artifact_message_card_actionPerformed_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onArtifactActionPerformed($event)); });
|
|
85
|
+
i0.ɵɵelementEnd()();
|
|
76
86
|
} if (rf & 2) {
|
|
77
87
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
88
|
+
i0.ɵɵclassProp("system-artifact", ctx_r0.isSystemArtifact);
|
|
89
|
+
i0.ɵɵadvance();
|
|
78
90
|
i0.ɵɵproperty("artifactId", ctx_r0.artifact.ID)("artifact", ctx_r0.artifact)("artifactVersion", ctx_r0.artifactVersion)("currentUser", ctx_r0.currentUser);
|
|
79
91
|
} }
|
|
80
|
-
function
|
|
92
|
+
function MessageItemComponent_Conditional_16_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
81
93
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
82
94
|
i0.ɵɵelementStart(0, "mj-suggested-responses", 31);
|
|
83
|
-
i0.ɵɵlistener("responseSelected", function
|
|
95
|
+
i0.ɵɵlistener("responseSelected", function MessageItemComponent_Conditional_16_Conditional_4_Template_mj_suggested_responses_responseSelected_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onSuggestedResponseSelected($event)); });
|
|
84
96
|
i0.ɵɵelementEnd();
|
|
85
97
|
} if (rf & 2) {
|
|
86
98
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
87
99
|
i0.ɵɵproperty("suggestedResponses", ctx_r0.suggestedResponses)("disabled", ctx_r0.isProcessing)("isLastMessage", ctx_r0.isLastMessageInConversation)("isConversationOwner", ctx_r0.isConversationOwner);
|
|
88
100
|
} }
|
|
89
|
-
function
|
|
90
|
-
i0.ɵɵelementStart(0, "div",
|
|
91
|
-
i0.ɵɵelement(1, "markdown",
|
|
92
|
-
i0.ɵɵtemplate(2,
|
|
101
|
+
function MessageItemComponent_Conditional_16_Template(rf, ctx) { if (rf & 1) {
|
|
102
|
+
i0.ɵɵelementStart(0, "div", 24);
|
|
103
|
+
i0.ɵɵelement(1, "markdown", 25);
|
|
104
|
+
i0.ɵɵtemplate(2, MessageItemComponent_Conditional_16_Conditional_2_Template, 2, 0, "span", 26);
|
|
93
105
|
i0.ɵɵelementEnd();
|
|
94
|
-
i0.ɵɵtemplate(3,
|
|
106
|
+
i0.ɵɵtemplate(3, MessageItemComponent_Conditional_16_Conditional_3_Template, 2, 6, "div", 27)(4, MessageItemComponent_Conditional_16_Conditional_4_Template, 1, 4, "mj-suggested-responses", 28);
|
|
95
107
|
} if (rf & 2) {
|
|
96
108
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
97
109
|
i0.ɵɵadvance();
|
|
@@ -103,19 +115,19 @@ function MessageItemComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
|
103
115
|
i0.ɵɵadvance();
|
|
104
116
|
i0.ɵɵconditional(ctx_r0.isLastMessageInConversation && ctx_r0.isConversationOwner && ctx_r0.suggestedResponses.length > 0 ? 4 : -1);
|
|
105
117
|
} }
|
|
106
|
-
function
|
|
118
|
+
function MessageItemComponent_Conditional_17_Template(rf, ctx) { if (rf & 1) {
|
|
107
119
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
108
|
-
i0.ɵɵelementStart(0, "div",
|
|
109
|
-
i0.ɵɵtwoWayListener("ngModelChange", function
|
|
110
|
-
i0.ɵɵlistener("keydown", function
|
|
120
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "textarea", 32);
|
|
121
|
+
i0.ɵɵtwoWayListener("ngModelChange", function MessageItemComponent_Conditional_17_Template_textarea_ngModelChange_1_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵtwoWayBindingSet(ctx_r0.editedText, $event) || (ctx_r0.editedText = $event); return i0.ɵɵresetView($event); });
|
|
122
|
+
i0.ɵɵlistener("keydown", function MessageItemComponent_Conditional_17_Template_textarea_keydown_1_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onEditKeydown($event)); });
|
|
111
123
|
i0.ɵɵelementEnd();
|
|
112
124
|
i0.ɵɵelementStart(2, "div", 33)(3, "button", 34);
|
|
113
|
-
i0.ɵɵlistener("click", function
|
|
125
|
+
i0.ɵɵlistener("click", function MessageItemComponent_Conditional_17_Template_button_click_3_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.saveEdit()); });
|
|
114
126
|
i0.ɵɵelement(4, "i", 35);
|
|
115
127
|
i0.ɵɵtext(5, " Save ");
|
|
116
128
|
i0.ɵɵelementEnd();
|
|
117
129
|
i0.ɵɵelementStart(6, "button", 36);
|
|
118
|
-
i0.ɵɵlistener("click", function
|
|
130
|
+
i0.ɵɵlistener("click", function MessageItemComponent_Conditional_17_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r5); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.cancelEditing()); });
|
|
119
131
|
i0.ɵɵelement(7, "i", 37);
|
|
120
132
|
i0.ɵɵtext(8, " Cancel ");
|
|
121
133
|
i0.ɵɵelementEnd()();
|
|
@@ -127,7 +139,7 @@ function MessageItemComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
|
127
139
|
i0.ɵɵadvance();
|
|
128
140
|
i0.ɵɵtwoWayProperty("ngModel", ctx_r0.editedText);
|
|
129
141
|
} }
|
|
130
|
-
function
|
|
142
|
+
function MessageItemComponent_Conditional_18_Conditional_1_div_15_Template(rf, ctx) { if (rf & 1) {
|
|
131
143
|
i0.ɵɵelementStart(0, "div", 45)(1, "span", 46);
|
|
132
144
|
i0.ɵɵtext(2, "Steps:");
|
|
133
145
|
i0.ɵɵelementEnd();
|
|
@@ -139,7 +151,7 @@ function MessageItemComponent_Conditional_19_Conditional_1_div_15_Template(rf, c
|
|
|
139
151
|
i0.ɵɵadvance(4);
|
|
140
152
|
i0.ɵɵtextInterpolate(ctx_r0.agentRunStepCount);
|
|
141
153
|
} }
|
|
142
|
-
function
|
|
154
|
+
function MessageItemComponent_Conditional_18_Conditional_1_div_16_Template(rf, ctx) { if (rf & 1) {
|
|
143
155
|
i0.ɵɵelementStart(0, "div", 45)(1, "span", 46);
|
|
144
156
|
i0.ɵɵtext(2, "Tokens:");
|
|
145
157
|
i0.ɵɵelementEnd();
|
|
@@ -151,7 +163,7 @@ function MessageItemComponent_Conditional_19_Conditional_1_div_16_Template(rf, c
|
|
|
151
163
|
i0.ɵɵadvance(4);
|
|
152
164
|
i0.ɵɵtextInterpolate(ctx_r0.formatNumber(ctx_r0.agentRunTotalTokens));
|
|
153
165
|
} }
|
|
154
|
-
function
|
|
166
|
+
function MessageItemComponent_Conditional_18_Conditional_1_div_17_Template(rf, ctx) { if (rf & 1) {
|
|
155
167
|
i0.ɵɵelementStart(0, "div", 45)(1, "span", 46);
|
|
156
168
|
i0.ɵɵtext(2, "Cost:");
|
|
157
169
|
i0.ɵɵelementEnd();
|
|
@@ -163,7 +175,7 @@ function MessageItemComponent_Conditional_19_Conditional_1_div_17_Template(rf, c
|
|
|
163
175
|
i0.ɵɵadvance(4);
|
|
164
176
|
i0.ɵɵtextInterpolate1("\\$", ctx_r0.agentRunTotalCost.toFixed(4), "");
|
|
165
177
|
} }
|
|
166
|
-
function
|
|
178
|
+
function MessageItemComponent_Conditional_18_Conditional_1_div_18_Template(rf, ctx) { if (rf & 1) {
|
|
167
179
|
i0.ɵɵelementStart(0, "div", 45)(1, "span", 46);
|
|
168
180
|
i0.ɵɵtext(2, "Status:");
|
|
169
181
|
i0.ɵɵelementEnd();
|
|
@@ -177,12 +189,12 @@ function MessageItemComponent_Conditional_19_Conditional_1_div_18_Template(rf, c
|
|
|
177
189
|
i0.ɵɵadvance();
|
|
178
190
|
i0.ɵɵtextInterpolate1(" ", ctx_r0.agentRun.Status, " ");
|
|
179
191
|
} }
|
|
180
|
-
function
|
|
192
|
+
function MessageItemComponent_Conditional_18_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
181
193
|
const _r6 = i0.ɵɵgetCurrentView();
|
|
182
194
|
i0.ɵɵelementStart(0, "div", 39)(1, "div", 41);
|
|
183
195
|
i0.ɵɵelement(2, "i", 42);
|
|
184
196
|
i0.ɵɵelementStart(3, "span")(4, "a", 43);
|
|
185
|
-
i0.ɵɵlistener("click", function
|
|
197
|
+
i0.ɵɵlistener("click", function MessageItemComponent_Conditional_18_Conditional_1_Template_a_click_4_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openAgentRecord()); });
|
|
186
198
|
i0.ɵɵtext(5);
|
|
187
199
|
i0.ɵɵelementEnd();
|
|
188
200
|
i0.ɵɵtext(6, " Run Details ");
|
|
@@ -191,11 +203,11 @@ function MessageItemComponent_Conditional_19_Conditional_1_Template(rf, ctx) { i
|
|
|
191
203
|
i0.ɵɵtext(10, "Run ID:");
|
|
192
204
|
i0.ɵɵelementEnd();
|
|
193
205
|
i0.ɵɵelementStart(11, "span", 47)(12, "a", 48);
|
|
194
|
-
i0.ɵɵlistener("click", function
|
|
206
|
+
i0.ɵɵlistener("click", function MessageItemComponent_Conditional_18_Conditional_1_Template_a_click_12_listener() { i0.ɵɵrestoreView(_r6); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.openAgentRunRecord()); });
|
|
195
207
|
i0.ɵɵtext(13);
|
|
196
208
|
i0.ɵɵelement(14, "i", 49);
|
|
197
209
|
i0.ɵɵelementEnd()()();
|
|
198
|
-
i0.ɵɵtemplate(15,
|
|
210
|
+
i0.ɵɵtemplate(15, MessageItemComponent_Conditional_18_Conditional_1_div_15_Template, 5, 1, "div", 50)(16, MessageItemComponent_Conditional_18_Conditional_1_div_16_Template, 5, 1, "div", 50)(17, MessageItemComponent_Conditional_18_Conditional_1_div_17_Template, 5, 1, "div", 50)(18, MessageItemComponent_Conditional_18_Conditional_1_div_18_Template, 5, 3, "div", 50);
|
|
199
211
|
i0.ɵɵelementEnd()();
|
|
200
212
|
} if (rf & 2) {
|
|
201
213
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -212,20 +224,20 @@ function MessageItemComponent_Conditional_19_Conditional_1_Template(rf, ctx) { i
|
|
|
212
224
|
i0.ɵɵadvance();
|
|
213
225
|
i0.ɵɵproperty("ngIf", ctx_r0.agentRun.Status);
|
|
214
226
|
} }
|
|
215
|
-
function
|
|
227
|
+
function MessageItemComponent_Conditional_18_Conditional_2_mj_task_widget_6_Template(rf, ctx) { if (rf & 1) {
|
|
216
228
|
i0.ɵɵelement(0, "mj-task-widget", 56);
|
|
217
229
|
} if (rf & 2) {
|
|
218
230
|
const task_r7 = ctx.$implicit;
|
|
219
231
|
i0.ɵɵproperty("task", task_r7)("compact", false)("clickable", false)("showProgress", true)("showDuration", true);
|
|
220
232
|
} }
|
|
221
|
-
function
|
|
233
|
+
function MessageItemComponent_Conditional_18_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
222
234
|
i0.ɵɵelementStart(0, "div", 40)(1, "div", 52);
|
|
223
235
|
i0.ɵɵelement(2, "i", 53);
|
|
224
236
|
i0.ɵɵelementStart(3, "span");
|
|
225
237
|
i0.ɵɵtext(4);
|
|
226
238
|
i0.ɵɵelementEnd()();
|
|
227
239
|
i0.ɵɵelementStart(5, "div", 54);
|
|
228
|
-
i0.ɵɵtemplate(6,
|
|
240
|
+
i0.ɵɵtemplate(6, MessageItemComponent_Conditional_18_Conditional_2_mj_task_widget_6_Template, 1, 5, "mj-task-widget", 55);
|
|
229
241
|
i0.ɵɵelementEnd()();
|
|
230
242
|
} if (rf & 2) {
|
|
231
243
|
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
@@ -234,9 +246,9 @@ function MessageItemComponent_Conditional_19_Conditional_2_Template(rf, ctx) { i
|
|
|
234
246
|
i0.ɵɵadvance(2);
|
|
235
247
|
i0.ɵɵproperty("ngForOf", ctx_r0.detailTasks);
|
|
236
248
|
} }
|
|
237
|
-
function
|
|
238
|
-
i0.ɵɵelementStart(0, "div",
|
|
239
|
-
i0.ɵɵtemplate(1,
|
|
249
|
+
function MessageItemComponent_Conditional_18_Template(rf, ctx) { if (rf & 1) {
|
|
250
|
+
i0.ɵɵelementStart(0, "div", 12);
|
|
251
|
+
i0.ɵɵtemplate(1, MessageItemComponent_Conditional_18_Conditional_1_Template, 19, 6, "div", 39)(2, MessageItemComponent_Conditional_18_Conditional_2_Template, 7, 2, "div", 40);
|
|
240
252
|
i0.ɵɵelementEnd();
|
|
241
253
|
} if (rf & 2) {
|
|
242
254
|
const ctx_r0 = i0.ɵɵnextContext();
|
|
@@ -245,32 +257,32 @@ function MessageItemComponent_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
|
245
257
|
i0.ɵɵadvance();
|
|
246
258
|
i0.ɵɵconditional(ctx_r0.detailTasks.length > 0 ? 2 : -1);
|
|
247
259
|
} }
|
|
248
|
-
function
|
|
260
|
+
function MessageItemComponent_div_19_button_1_Template(rf, ctx) { if (rf & 1) {
|
|
249
261
|
const _r9 = i0.ɵɵgetCurrentView();
|
|
250
262
|
i0.ɵɵelementStart(0, "button", 63);
|
|
251
|
-
i0.ɵɵlistener("click", function
|
|
263
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_19_button_1_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r9); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onRetryClick()); });
|
|
252
264
|
i0.ɵɵelement(1, "i", 64);
|
|
253
265
|
i0.ɵɵtext(2, " Retry ");
|
|
254
266
|
i0.ɵɵelementEnd();
|
|
255
267
|
} }
|
|
256
|
-
function
|
|
268
|
+
function MessageItemComponent_div_19_button_4_Template(rf, ctx) { if (rf & 1) {
|
|
257
269
|
const _r10 = i0.ɵɵgetCurrentView();
|
|
258
270
|
i0.ɵɵelementStart(0, "button", 65);
|
|
259
|
-
i0.ɵɵlistener("click", function
|
|
271
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_19_button_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r10); const ctx_r0 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r0.onEditClick()); });
|
|
260
272
|
i0.ɵɵelement(1, "i", 66);
|
|
261
273
|
i0.ɵɵelementEnd();
|
|
262
274
|
} }
|
|
263
|
-
function
|
|
275
|
+
function MessageItemComponent_div_19_Template(rf, ctx) { if (rf & 1) {
|
|
264
276
|
const _r8 = i0.ɵɵgetCurrentView();
|
|
265
277
|
i0.ɵɵelementStart(0, "div", 57);
|
|
266
|
-
i0.ɵɵtemplate(1,
|
|
278
|
+
i0.ɵɵtemplate(1, MessageItemComponent_div_19_button_1_Template, 3, 0, "button", 58);
|
|
267
279
|
i0.ɵɵelementStart(2, "button", 59);
|
|
268
|
-
i0.ɵɵlistener("click", function
|
|
280
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_19_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onPinClick()); });
|
|
269
281
|
i0.ɵɵelement(3, "i", 2);
|
|
270
282
|
i0.ɵɵelementEnd();
|
|
271
|
-
i0.ɵɵtemplate(4,
|
|
283
|
+
i0.ɵɵtemplate(4, MessageItemComponent_div_19_button_4_Template, 2, 0, "button", 60);
|
|
272
284
|
i0.ɵɵelementStart(5, "button", 61);
|
|
273
|
-
i0.ɵɵlistener("click", function
|
|
285
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_19_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r8); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.onDeleteClick()); });
|
|
274
286
|
i0.ɵɵelement(6, "i", 62);
|
|
275
287
|
i0.ɵɵelementEnd()();
|
|
276
288
|
} if (rf & 2) {
|
|
@@ -284,16 +296,16 @@ function MessageItemComponent_div_20_Template(rf, ctx) { if (rf & 1) {
|
|
|
284
296
|
i0.ɵɵadvance();
|
|
285
297
|
i0.ɵɵproperty("ngIf", ctx_r0.isUserMessage);
|
|
286
298
|
} }
|
|
287
|
-
function
|
|
299
|
+
function MessageItemComponent_div_20_Template(rf, ctx) { if (rf & 1) {
|
|
288
300
|
const _r11 = i0.ɵɵgetCurrentView();
|
|
289
301
|
i0.ɵɵelementStart(0, "div", 67)(1, "button", 68);
|
|
290
|
-
i0.ɵɵlistener("click", function
|
|
302
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_20_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleReaction("like")); });
|
|
291
303
|
i0.ɵɵelement(2, "i", 69);
|
|
292
304
|
i0.ɵɵelementStart(3, "span", 70);
|
|
293
305
|
i0.ɵɵtext(4, "0");
|
|
294
306
|
i0.ɵɵelementEnd()();
|
|
295
307
|
i0.ɵɵelementStart(5, "button", 68);
|
|
296
|
-
i0.ɵɵlistener("click", function
|
|
308
|
+
i0.ɵɵlistener("click", function MessageItemComponent_div_20_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r11); const ctx_r0 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r0.toggleReaction("comment")); });
|
|
297
309
|
i0.ɵɵelement(6, "i", 71);
|
|
298
310
|
i0.ɵɵelementStart(7, "span", 70);
|
|
299
311
|
i0.ɵɵtext(8, "0");
|
|
@@ -316,6 +328,7 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
316
328
|
artifact;
|
|
317
329
|
artifactVersion;
|
|
318
330
|
agentRun = null; // Passed from parent, loaded once per conversation
|
|
331
|
+
userAvatarMap = new Map();
|
|
319
332
|
pinClicked = new EventEmitter();
|
|
320
333
|
editClicked = new EventEmitter();
|
|
321
334
|
deleteClicked = new EventEmitter();
|
|
@@ -327,11 +340,13 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
327
340
|
suggestedResponseSelected = new EventEmitter();
|
|
328
341
|
_loadTime = Date.now();
|
|
329
342
|
_elapsedTimeInterval = null;
|
|
330
|
-
_elapsedTimeFormatted = '
|
|
331
|
-
_agentRunDurationFormatted = '
|
|
343
|
+
_elapsedTimeFormatted = '0:00';
|
|
344
|
+
_agentRunDurationFormatted = '0:00';
|
|
332
345
|
isEditing = false;
|
|
333
346
|
editedText = '';
|
|
334
347
|
originalText = '';
|
|
348
|
+
// Track previous status for DoCheck comparison
|
|
349
|
+
_previousMessageStatus = undefined;
|
|
335
350
|
// Agent run details
|
|
336
351
|
isAgentDetailsExpanded = false;
|
|
337
352
|
detailTasks = [];
|
|
@@ -348,20 +363,34 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
348
363
|
async ngOnInit() {
|
|
349
364
|
// No longer need to load artifacts per message - they are preloaded in chat area
|
|
350
365
|
}
|
|
351
|
-
ngOnChanges(
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
366
|
+
ngOnChanges(_changes) {
|
|
367
|
+
// No longer need to manage timer for agentRun changes
|
|
368
|
+
// Parent's 1-second timer + agentRunDuration getter handles all agent run timing
|
|
369
|
+
// Component's timer only runs for temporary messages (handled in ngAfterViewInit)
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* DoCheck lifecycle hook - detects changes to message properties
|
|
373
|
+
* This runs on every change detection cycle, so we check if Status actually changed
|
|
374
|
+
* This is more reliable than ngOnChanges when the message object reference doesn't change
|
|
375
|
+
*/
|
|
376
|
+
ngDoCheck() {
|
|
377
|
+
if (!this.message) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const currentStatus = this.message.Status;
|
|
381
|
+
// Check if status changed from non-Complete to Complete
|
|
382
|
+
if (this._previousMessageStatus !== 'Complete' && currentStatus === 'Complete') {
|
|
383
|
+
console.log(`🎯 Message ${this.message.ID} status changed to Complete, stopping timer`);
|
|
384
|
+
// Stop the elapsed time interval
|
|
385
|
+
if (this._elapsedTimeInterval !== null) {
|
|
361
386
|
clearInterval(this._elapsedTimeInterval);
|
|
362
387
|
this._elapsedTimeInterval = null;
|
|
363
388
|
}
|
|
389
|
+
// Force change detection to update the pill color
|
|
390
|
+
this.cdRef.markForCheck();
|
|
364
391
|
}
|
|
392
|
+
// Update previous status for next check
|
|
393
|
+
this._previousMessageStatus = currentStatus;
|
|
365
394
|
}
|
|
366
395
|
ngAfterViewInit() {
|
|
367
396
|
this._loadTime = Date.now();
|
|
@@ -375,11 +404,14 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
375
404
|
}
|
|
376
405
|
}
|
|
377
406
|
/**
|
|
378
|
-
* Starts the elapsed time updater interval for temporary messages
|
|
379
|
-
*
|
|
407
|
+
* Starts the elapsed time updater interval for temporary messages only
|
|
408
|
+
* For agent runs with IDs, the parent's timer + agentRunDuration getter handles updates
|
|
409
|
+
* Updates every second for temporary messages that use _elapsedTimeFormatted
|
|
380
410
|
*/
|
|
381
411
|
startElapsedTimeUpdater() {
|
|
382
|
-
|
|
412
|
+
// Only start timer for temporary messages (no ID yet)
|
|
413
|
+
// Agent runs with IDs use the parent's timer + agentRunDuration getter
|
|
414
|
+
if (this.isInProgressAIMessage) {
|
|
383
415
|
// Initial update
|
|
384
416
|
this.updateTimers();
|
|
385
417
|
this.cdRef.markForCheck();
|
|
@@ -387,8 +419,9 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
387
419
|
if (this._elapsedTimeInterval === null) {
|
|
388
420
|
this._elapsedTimeInterval = setInterval(() => {
|
|
389
421
|
this.updateTimers();
|
|
390
|
-
// Use
|
|
391
|
-
|
|
422
|
+
// Use detectChanges to force immediate synchronous view update
|
|
423
|
+
// markForCheck only schedules a check which may not happen if parent already checked
|
|
424
|
+
this.cdRef.detectChanges();
|
|
392
425
|
}, 1000);
|
|
393
426
|
}
|
|
394
427
|
}
|
|
@@ -399,7 +432,7 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
399
432
|
*/
|
|
400
433
|
updateTimers() {
|
|
401
434
|
// Update temporary message elapsed time
|
|
402
|
-
if (this.
|
|
435
|
+
if (this.isInProgressAIMessage) {
|
|
403
436
|
this._elapsedTimeFormatted = this.formatElapsedTime(this.elapsedTimeSinceLoad);
|
|
404
437
|
}
|
|
405
438
|
// Update agent run duration for active runs
|
|
@@ -419,11 +452,11 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
419
452
|
let formattedTime = (hours > 0 ? hours + ':' : '') +
|
|
420
453
|
(minutes < 10 && hours > 0 ? '0' : '') + minutes + ':' +
|
|
421
454
|
(seconds < 10 ? '0' : '') + seconds;
|
|
422
|
-
return
|
|
455
|
+
return formattedTime;
|
|
423
456
|
}
|
|
424
457
|
formatDurationFromMs(diffMs) {
|
|
425
458
|
if (diffMs <= 0) {
|
|
426
|
-
return '
|
|
459
|
+
return '0:00';
|
|
427
460
|
}
|
|
428
461
|
let seconds = Math.floor(diffMs / 1000);
|
|
429
462
|
let minutes = Math.floor(seconds / 60);
|
|
@@ -433,7 +466,7 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
433
466
|
let formattedTime = (hours > 0 ? hours + ':' : '') +
|
|
434
467
|
(minutes < 10 && hours > 0 ? '0' : '') + minutes + ':' +
|
|
435
468
|
(seconds < 10 ? '0' : '') + seconds;
|
|
436
|
-
return
|
|
469
|
+
return formattedTime;
|
|
437
470
|
}
|
|
438
471
|
get elapsedTimeSinceLoad() {
|
|
439
472
|
return Date.now() - this._loadTime;
|
|
@@ -474,6 +507,42 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
474
507
|
get isUserMessage() {
|
|
475
508
|
return this.message.Role?.trim().toLowerCase() === 'user';
|
|
476
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* Get the actual sender name for user messages
|
|
512
|
+
* Uses the denormalized User field from the view if available,
|
|
513
|
+
* otherwise falls back to current user name
|
|
514
|
+
*/
|
|
515
|
+
get messageSenderName() {
|
|
516
|
+
// Use the denormalized User field from the ConversationDetail view
|
|
517
|
+
// This is populated from the UserID (if present) or falls back to Conversation.UserID
|
|
518
|
+
if (this.message.User) {
|
|
519
|
+
return this.message.User;
|
|
520
|
+
}
|
|
521
|
+
// Fallback to current user name (for backwards compatibility)
|
|
522
|
+
return this.currentUser.Name;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Get the user's avatar image URL from the userAvatarMap
|
|
526
|
+
* Uses fast O(1) lookup by UserID
|
|
527
|
+
*/
|
|
528
|
+
get userAvatarUrl() {
|
|
529
|
+
if (!this.isUserMessage || !this.message.UserID) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
const avatarData = this.userAvatarMap.get(this.message.UserID);
|
|
533
|
+
return avatarData?.imageUrl || null;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Get the user's avatar icon class from the userAvatarMap
|
|
537
|
+
* Uses fast O(1) lookup by UserID
|
|
538
|
+
*/
|
|
539
|
+
get userAvatarIconClass() {
|
|
540
|
+
if (!this.isUserMessage || !this.message.UserID) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
const avatarData = this.userAvatarMap.get(this.message.UserID);
|
|
544
|
+
return avatarData?.iconClass || null;
|
|
545
|
+
}
|
|
477
546
|
get isConversationManager() {
|
|
478
547
|
return this.aiAgentInfo?.name === 'Sage';
|
|
479
548
|
}
|
|
@@ -529,8 +598,8 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
529
598
|
escapeRegex(text) {
|
|
530
599
|
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
531
600
|
}
|
|
532
|
-
get
|
|
533
|
-
return this.isAIMessage &&
|
|
601
|
+
get isInProgressAIMessage() {
|
|
602
|
+
return this.isAIMessage && this.message.Status === 'In-Progress';
|
|
534
603
|
}
|
|
535
604
|
get isAgentRunActive() {
|
|
536
605
|
if (!this.agentRun) {
|
|
@@ -561,6 +630,36 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
561
630
|
get hasArtifact() {
|
|
562
631
|
return !!this.artifactVersion;
|
|
563
632
|
}
|
|
633
|
+
/**
|
|
634
|
+
* Check if the artifact is a system-only artifact
|
|
635
|
+
*/
|
|
636
|
+
get isSystemArtifact() {
|
|
637
|
+
return this.artifact?.Visibility === 'System Only';
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Unified time pill text for all AI message states
|
|
641
|
+
* Returns the appropriate time display based on message state:
|
|
642
|
+
* - Temporary messages (in-progress): Live elapsed time
|
|
643
|
+
* - Active agent runs: Live agent run duration (calculated on-demand)
|
|
644
|
+
* - Completed messages: Final generation time
|
|
645
|
+
* - Failed messages: Time before failure
|
|
646
|
+
*/
|
|
647
|
+
get timePillText() {
|
|
648
|
+
if (this.isUserMessage) {
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
// For temporary messages (in-progress), show live elapsed time
|
|
652
|
+
if (this.isInProgressAIMessage) {
|
|
653
|
+
return this._elapsedTimeFormatted;
|
|
654
|
+
}
|
|
655
|
+
// For active agent runs, calculate live duration from agentRun timestamps
|
|
656
|
+
// This getter recalculates every time using new Date(), so it updates smoothly
|
|
657
|
+
if (this.isAgentRunActive && this.agentRun?.__mj_CreatedAt) {
|
|
658
|
+
return this.agentRunDuration;
|
|
659
|
+
}
|
|
660
|
+
// For completed or failed messages, show final generation time
|
|
661
|
+
return this.formattedGenerationTime;
|
|
662
|
+
}
|
|
564
663
|
get formattedGenerationTime() {
|
|
565
664
|
// Only show generation time for AI messages
|
|
566
665
|
if (this.isUserMessage || !this.message.__mj_CreatedAt || !this.message.__mj_UpdatedAt) {
|
|
@@ -592,7 +691,7 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
592
691
|
if (this.isAIMessage) {
|
|
593
692
|
classes.push('ai-message');
|
|
594
693
|
// Show in-progress styling for AI messages that are still processing
|
|
595
|
-
if (this.
|
|
694
|
+
if (this.isInProgressAIMessage) {
|
|
596
695
|
classes.push('in-progress');
|
|
597
696
|
}
|
|
598
697
|
}
|
|
@@ -750,13 +849,6 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
750
849
|
*/
|
|
751
850
|
async toggleAgentDetails() {
|
|
752
851
|
this.isAgentDetailsExpanded = !this.isAgentDetailsExpanded;
|
|
753
|
-
console.log(`🔧 Toggle agent details for message ${this.message.ID}:`, {
|
|
754
|
-
expanded: this.isAgentDetailsExpanded,
|
|
755
|
-
hasAgentRun: this.hasAgentRun,
|
|
756
|
-
agentRunExists: !!this.agentRun,
|
|
757
|
-
agentRunId: this.agentRun?.ID,
|
|
758
|
-
messageAgentId: this.message?.AgentID
|
|
759
|
-
});
|
|
760
852
|
// Load tasks when expanding if not already loaded
|
|
761
853
|
if (this.isAgentDetailsExpanded && !this.tasksLoaded) {
|
|
762
854
|
await this.loadTasks();
|
|
@@ -917,61 +1009,57 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
917
1009
|
this.suggestedResponseSelected.emit(event);
|
|
918
1010
|
}
|
|
919
1011
|
static ɵfac = function MessageItemComponent_Factory(t) { return new (t || MessageItemComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i1.MentionParserService), i0.ɵɵdirectiveInject(i2.MentionAutocompleteService)); };
|
|
920
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MessageItemComponent, selectors: [["mj-conversation-message-item"]], inputs: { message: "message", conversation: "conversation", currentUser: "currentUser", allMessages: "allMessages", isProcessing: "isProcessing", artifact: "artifact", artifactVersion: "artifactVersion", agentRun: "agentRun" }, outputs: { pinClicked: "pinClicked", editClicked: "editClicked", deleteClicked: "deleteClicked", retryClicked: "retryClicked", artifactClicked: "artifactClicked", artifactActionPerformed: "artifactActionPerformed", messageEdited: "messageEdited", openEntityRecord: "openEntityRecord", suggestedResponseSelected: "suggestedResponseSelected" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls:
|
|
1012
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MessageItemComponent, selectors: [["mj-conversation-message-item"]], inputs: { message: "message", conversation: "conversation", currentUser: "currentUser", allMessages: "allMessages", isProcessing: "isProcessing", artifact: "artifact", artifactVersion: "artifactVersion", agentRun: "agentRun", userAvatarMap: "userAvatarMap" }, outputs: { pinClicked: "pinClicked", editClicked: "editClicked", deleteClicked: "deleteClicked", retryClicked: "retryClicked", artifactClicked: "artifactClicked", artifactActionPerformed: "artifactActionPerformed", messageEdited: "messageEdited", openEntityRecord: "openEntityRecord", suggestedResponseSelected: "suggestedResponseSelected" }, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 21, vars: 21, consts: [[1, "message-avatar"], [1, "avatar-circle"], [1, "fas", 3, "ngClass"], [1, "message-content"], [1, "message-header"], [1, "message-sender", 3, "title"], [1, "message-time"], ["class", "message-status", 3, "error", 4, "ngIf"], ["class", "time-pill", 3, "in-progress", "active", "complete", "failed", 4, "ngIf"], ["class", "agent-run-icon", "title", "Click to view agent execution details", 3, "expanded", "click", 4, "ngIf"], [1, "message-body"], [1, "message-edit-container"], [1, "agent-details-panel"], ["class", "message-actions", 4, "ngIf"], ["class", "message-reactions", 4, "ngIf"], ["alt", "User avatar", 1, "avatar-image", 3, "src"], [3, "class"], [1, "fas", "fa-user"], [1, "message-status"], [1, "status-text"], [1, "time-pill"], [1, "fas", "fa-clock"], ["title", "Click to view agent execution details", 1, "agent-run-icon", 3, "click"], [1, "fas", "fa-cog"], [1, "message-text"], [3, "data"], [1, "edited-badge"], [1, "artifact-wrapper", 3, "system-artifact"], [3, "suggestedResponses", "disabled", "isLastMessage", "isConversationOwner"], [1, "artifact-wrapper"], [3, "actionPerformed", "artifactId", "artifact", "artifactVersion", "currentUser"], [3, "responseSelected", "suggestedResponses", "disabled", "isLastMessage", "isConversationOwner"], ["rows", "4", "placeholder", "Edit your message...", 1, "message-edit-textarea", 3, "ngModelChange", "keydown", "ngModel"], [1, "edit-actions"], [1, "edit-action-btn", "save", 3, "click"], [1, "fas", "fa-check"], [1, "edit-action-btn", "cancel", 3, "click"], [1, "fas", "fa-times"], [1, "edit-hint"], [1, "agent-details-content"], [1, "agent-details-tasks"], [1, "agent-details-header"], [1, "fas", "fa-chart-line"], ["title", "Open agent details", 1, "agent-name-link", 3, "click"], [1, "agent-details-grid"], [1, "detail-row"], [1, "detail-label"], [1, "detail-value"], ["title", "Open agent run details", 1, "run-id-link", 3, "click"], [1, "fas", "fa-external-link-alt"], ["class", "detail-row", 4, "ngIf"], [1, "detail-value", "status-badge"], [1, "tasks-section-header"], [1, "fas", "fa-tasks"], [1, "tasks-list"], [3, "task", "compact", "clickable", "showProgress", "showDuration", 4, "ngFor", "ngForOf"], [3, "task", "compact", "clickable", "showProgress", "showDuration"], [1, "message-actions"], ["class", "message-action-btn retry-btn", "title", "Retry", 3, "click", 4, "ngIf"], [1, "message-action-btn", 3, "click", "title"], ["class", "message-action-btn", "title", "Edit", 3, "click", 4, "ngIf"], ["title", "Delete", 1, "message-action-btn", "danger", 3, "click"], [1, "fas", "fa-trash"], ["title", "Retry", 1, "message-action-btn", "retry-btn", 3, "click"], [1, "fas", "fa-redo"], ["title", "Edit", 1, "message-action-btn", 3, "click"], [1, "fas", "fa-edit"], [1, "message-reactions"], [1, "reaction-btn", 3, "click"], [1, "far", "fa-thumbs-up"], [1, "reaction-count"], [1, "far", "fa-comment"]], template: function MessageItemComponent_Template(rf, ctx) { if (rf & 1) {
|
|
921
1013
|
i0.ɵɵelementStart(0, "div")(1, "div", 0)(2, "div", 1);
|
|
922
|
-
i0.ɵɵ
|
|
1014
|
+
i0.ɵɵtemplate(3, MessageItemComponent_Conditional_3_Template, 3, 1)(4, MessageItemComponent_Conditional_4_Template, 1, 1, "i", 2);
|
|
923
1015
|
i0.ɵɵelementEnd()();
|
|
924
|
-
i0.ɵɵelementStart(
|
|
925
|
-
i0.ɵɵtext(
|
|
1016
|
+
i0.ɵɵelementStart(5, "div", 3)(6, "div", 4)(7, "span", 5);
|
|
1017
|
+
i0.ɵɵtext(8);
|
|
926
1018
|
i0.ɵɵelementEnd();
|
|
927
|
-
i0.ɵɵelementStart(
|
|
928
|
-
i0.ɵɵtext(
|
|
929
|
-
i0.ɵɵpipe(
|
|
1019
|
+
i0.ɵɵelementStart(9, "span", 6);
|
|
1020
|
+
i0.ɵɵtext(10);
|
|
1021
|
+
i0.ɵɵpipe(11, "date");
|
|
930
1022
|
i0.ɵɵelementEnd();
|
|
931
|
-
i0.ɵɵtemplate(
|
|
1023
|
+
i0.ɵɵtemplate(12, MessageItemComponent_span_12_Template, 4, 4, "span", 7)(13, MessageItemComponent_span_13_Template, 3, 9, "span", 8)(14, MessageItemComponent_span_14_Template, 2, 2, "span", 9);
|
|
932
1024
|
i0.ɵɵelementEnd();
|
|
933
|
-
i0.ɵɵelementStart(
|
|
934
|
-
i0.ɵɵtemplate(
|
|
1025
|
+
i0.ɵɵelementStart(15, "div", 10);
|
|
1026
|
+
i0.ɵɵtemplate(16, MessageItemComponent_Conditional_16_Template, 5, 4)(17, MessageItemComponent_Conditional_17_Template, 11, 1, "div", 11)(18, MessageItemComponent_Conditional_18_Template, 3, 2, "div", 12);
|
|
935
1027
|
i0.ɵɵelementEnd();
|
|
936
|
-
i0.ɵɵtemplate(
|
|
1028
|
+
i0.ɵɵtemplate(19, MessageItemComponent_div_19_Template, 7, 4, "div", 13)(20, MessageItemComponent_div_20_Template, 9, 0, "div", 14);
|
|
937
1029
|
i0.ɵɵelementEnd()();
|
|
938
1030
|
} if (rf & 2) {
|
|
939
1031
|
i0.ɵɵclassMap(ctx.messageClasses);
|
|
940
1032
|
i0.ɵɵadvance(2);
|
|
941
1033
|
i0.ɵɵclassProp("ai-avatar", ctx.isAIMessage)("user-avatar", ctx.isUserMessage);
|
|
942
1034
|
i0.ɵɵadvance();
|
|
943
|
-
i0.ɵɵ
|
|
944
|
-
i0.ɵɵadvance(
|
|
1035
|
+
i0.ɵɵconditional(ctx.isUserMessage ? 3 : ctx.isAIMessage ? 4 : -1);
|
|
1036
|
+
i0.ɵɵadvance(4);
|
|
945
1037
|
i0.ɵɵproperty("title", ctx.isAIMessage ? (ctx.aiAgentInfo == null ? null : ctx.aiAgentInfo.role) || "AI Assistant" : "");
|
|
946
1038
|
i0.ɵɵadvance();
|
|
947
|
-
i0.ɵɵtextInterpolate1(" ", ctx.isAIMessage ? (ctx.aiAgentInfo == null ? null : ctx.aiAgentInfo.name) || "AI Assistant" : ctx.
|
|
1039
|
+
i0.ɵɵtextInterpolate1(" ", ctx.isAIMessage ? (ctx.aiAgentInfo == null ? null : ctx.aiAgentInfo.name) || "AI Assistant" : ctx.messageSenderName, " ");
|
|
948
1040
|
i0.ɵɵadvance(2);
|
|
949
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(
|
|
1041
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(11, 18, ctx.message.__mj_CreatedAt, "short"));
|
|
950
1042
|
i0.ɵɵadvance(2);
|
|
951
|
-
i0.ɵɵproperty("ngIf", !ctx.isUserMessage && ctx.formattedGenerationTime && !ctx.isTemporaryMessage && !ctx.isAgentRunActive);
|
|
952
|
-
i0.ɵɵadvance();
|
|
953
|
-
i0.ɵɵproperty("ngIf", ctx.hasAgentRun);
|
|
954
|
-
i0.ɵɵadvance();
|
|
955
1043
|
i0.ɵɵproperty("ngIf", ctx.isUserMessage && ctx.messageStatus !== "Complete");
|
|
956
1044
|
i0.ɵɵadvance();
|
|
957
|
-
i0.ɵɵproperty("ngIf", ctx.
|
|
1045
|
+
i0.ɵɵproperty("ngIf", !ctx.isUserMessage && ctx.timePillText);
|
|
958
1046
|
i0.ɵɵadvance();
|
|
959
|
-
i0.ɵɵproperty("ngIf",
|
|
1047
|
+
i0.ɵɵproperty("ngIf", ctx.hasAgentRun);
|
|
960
1048
|
i0.ɵɵadvance(2);
|
|
961
|
-
i0.ɵɵconditional(!ctx.isEditing ?
|
|
1049
|
+
i0.ɵɵconditional(!ctx.isEditing ? 16 : -1);
|
|
962
1050
|
i0.ɵɵadvance();
|
|
963
|
-
i0.ɵɵconditional(ctx.isEditing ?
|
|
1051
|
+
i0.ɵɵconditional(ctx.isEditing ? 17 : -1);
|
|
964
1052
|
i0.ɵɵadvance();
|
|
965
|
-
i0.ɵɵconditional(ctx.isAgentDetailsExpanded && ctx.hasAgentRun ?
|
|
1053
|
+
i0.ɵɵconditional(ctx.isAgentDetailsExpanded && ctx.hasAgentRun ? 18 : -1);
|
|
966
1054
|
i0.ɵɵadvance();
|
|
967
|
-
i0.ɵɵproperty("ngIf", !ctx.isProcessing && !ctx.
|
|
1055
|
+
i0.ɵɵproperty("ngIf", !ctx.isProcessing && !ctx.isInProgressAIMessage && !ctx.isEditing);
|
|
968
1056
|
i0.ɵɵadvance();
|
|
969
|
-
i0.ɵɵproperty("ngIf", !ctx.isProcessing && !ctx.
|
|
970
|
-
} }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i5.ArtifactMessageCardComponent, i6.MarkdownComponent, i7.SuggestedResponsesComponent, i8.TaskWidgetComponent, i3.DatePipe], styles: [".message-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 8px 24px;\n transition: background-color 150ms ease;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease;\n position: relative;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-item.ai-message[_ngcontent-%COMP%] {\n background-color: transparent;\n}\n\n.message-item.user-message[_ngcontent-%COMP%] {\n background-color: transparent;\n}\n\n.message-item.pinned[_ngcontent-%COMP%] {\n border-left: 3px solid #0076B6;\n background-color: rgba(0, 118, 182, 0.08);\n}\n\n.message-item.in-progress[_ngcontent-%COMP%] {\n background: linear-gradient(90deg,\n rgba(59, 130, 246, 0.08) 0%,\n rgba(59, 130, 246, 0.12) 50%,\n rgba(59, 130, 246, 0.08) 100%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 2s ease-in-out infinite;\n border-left: 3px solid #3B82F6;\n position: relative;\n}\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .message-text[_ngcontent-%COMP%] {\n color: #1F2937;\n font-weight: 500;\n max-height: 150px;\n overflow-y: auto;\n display: block;\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n right: 12px;\n top: 22px;\n width: 16px;\n height: 16px;\n border: 2px solid #3B82F6;\n border-top-color: transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 0.8s linear infinite;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n to { transform: rotate(360deg); }\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .avatar-circle[_ngcontent-%COMP%] {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n }\n 50% {\n box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);\n }\n}\n\n.message-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n\n\n[_nghost-%COMP%] .mention-badge {\n display: inline-block;\n padding: 2px 8px;\n margin: 0 2px;\n border-radius: 4px;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .mention-badge.agent {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n}\n\n[_nghost-%COMP%] .mention-badge.user {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n}\n\n[_nghost-%COMP%] .mention-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.message-avatar[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.avatar-circle[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: white;\n}\n\n\n\n.avatar-circle.user-avatar[_ngcontent-%COMP%] {\n border-radius: 50%;\n background-color: #333;\n}\n\n\n\n.avatar-circle.ai-avatar[_ngcontent-%COMP%] {\n border-radius: 8px;\n background-color: #9333EA; \n\n}\n\n.message-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n position: relative;\n}\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n font-size: 13px;\n}\n\n.message-sender[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #333;\n}\n\n\n\n.agent-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 10px;\n font-size: 11px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.message-time[_ngcontent-%COMP%] {\n color: #9CA3AF;\n font-size: 12px;\n font-weight: 400;\n}\n\n.generation-time[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: #E0F2FE;\n border-radius: 10px;\n font-size: 11px;\n color: #0369A1;\n font-weight: 500;\n margin-left: auto;\n}\n\n.generation-time[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n.message-elapsed[_ngcontent-%COMP%] {\n color: #AAA;\n font-size: 11px;\n font-style: italic;\n}\n\n.message-body[_ngcontent-%COMP%] {\n margin-bottom: 0;\n}\n\n.message-text[_ngcontent-%COMP%] {\n color: #333;\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n\n\n.message-text[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:first-child {\n margin-top: 0;\n}\n\n.message-text[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n\n\n.message-item.user-message[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n border-radius: 12px 12px 12px 4px;\n}\n\n.message-item.ai-message[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n border-radius: 4px 12px 12px 12px;\n}\n\n\n\n.message-reactions[_ngcontent-%COMP%] {\n display: none; \n\n}\n\n\n\n.artifact-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 12px;\n padding: 16px;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 8px;\n background: linear-gradient(135deg, #F8F7FF 0%, #F3F2FF 100%);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 500px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n position: relative;\n overflow: hidden;\n}\n\n.artifact-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, #8B5CF6 0%, #6366F1 100%);\n opacity: 1;\n}\n\n.artifact-card[_ngcontent-%COMP%]:hover {\n background: linear-gradient(135deg, #F3F2FF 0%, #EBE9FF 100%);\n border-color: rgba(139, 92, 246, 0.3);\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.12);\n transform: translateY(-1px);\n}\n\n.artifact-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.artifact-card-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #8B5CF6;\n flex-shrink: 0;\n background: rgba(139, 92, 246, 0.1);\n border-radius: 6px;\n transition: all 0.2s ease;\n}\n\n.artifact-card[_ngcontent-%COMP%]:hover .artifact-card-icon[_ngcontent-%COMP%] {\n background: rgba(139, 92, 246, 0.15);\n transform: scale(1.05);\n}\n\n.artifact-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n\n.artifact-card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.artifact-card-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n letter-spacing: -0.01em;\n margin-bottom: 4px;\n}\n\n.artifact-card-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #6B7280;\n line-height: 1.5;\n}\n\n.message-actions[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transform: translateY(4px);\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n pointer-events: none;\n}\n\n.message-item[_ngcontent-%COMP%]:hover .message-actions[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n.message-action-btn[_ngcontent-%COMP%] {\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #6B7280;\n font-size: 13px;\n transition: all 150ms ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n}\n\n.message-action-btn[_ngcontent-%COMP%]:hover {\n background-color: #F3F4F6;\n color: #111827;\n}\n\n.message-action-btn.danger[_ngcontent-%COMP%]:hover {\n background-color: #FEE2E2;\n color: #DC2626;\n}\n\n.message-action-btn.retry-btn[_ngcontent-%COMP%] {\n color: #3B82F6;\n background: #EFF6FF;\n font-weight: 600;\n gap: 6px;\n padding: 6px 12px;\n min-width: auto;\n}\n\n.message-action-btn.retry-btn[_ngcontent-%COMP%]:hover {\n background-color: #DBEAFE;\n color: #2563EB;\n}\n\n\n\n.thread-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n margin-top: 8px;\n background: #EFF6FF;\n border: 1px solid #DBEAFE;\n border-radius: 16px;\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 12px;\n color: #1E40AF;\n font-weight: 500;\n}\n\n.thread-indicator[_ngcontent-%COMP%]:hover {\n background: #DBEAFE;\n border-color: #93C5FD;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(30, 64, 175, 0.1);\n}\n\n.thread-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.thread-count[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.message-item.editing[_ngcontent-%COMP%] {\n background-color: rgba(255, 243, 205, 0.3);\n border-left: 3px solid #FFA726;\n}\n\n.message-edit-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.message-edit-textarea[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid #D9D9D9;\n border-radius: 6px;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.6;\n resize: vertical;\n min-height: 80px;\n transition: border-color 150ms ease;\n}\n\n.message-edit-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #0076B6;\n box-shadow: 0 0 0 2px rgba(0, 118, 182, 0.1);\n}\n\n.edit-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.edit-action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.edit-action-btn.save[_ngcontent-%COMP%] {\n background-color: #0076B6;\n color: white;\n}\n\n.edit-action-btn.save[_ngcontent-%COMP%]:hover {\n background-color: #005A8F;\n}\n\n.edit-action-btn.cancel[_ngcontent-%COMP%] {\n background-color: #F4F4F4;\n color: #666;\n}\n\n.edit-action-btn.cancel[_ngcontent-%COMP%]:hover {\n background-color: #E0E0E0;\n color: #333;\n}\n\n.edit-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #AAA;\n font-style: italic;\n}\n\n.edited-badge[_ngcontent-%COMP%] {\n margin-left: 8px;\n font-size: 11px;\n color: #AAA;\n font-style: italic;\n font-weight: normal;\n}\n\n\n\n.message-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #6B7280;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 4px;\n margin-left: 8px;\n animation: _ngcontent-%COMP%_statusPulse 2s ease-in-out infinite;\n}\n\n.message-status[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #0076B6;\n font-size: 11px;\n}\n\n.message-status.error[_ngcontent-%COMP%] {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n.message-status.error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #DC2626;\n}\n\n.status-text[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n@keyframes _ngcontent-%COMP%_statusPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n\n\n\n\n\n\n\n\n.agent-run-icon[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n color: #9CA3AF;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n margin-left: 8px;\n}\n\n.agent-run-icon[_ngcontent-%COMP%] i.fa-cog[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n.agent-run-icon[_ngcontent-%COMP%]:hover {\n color: #6B7280;\n}\n\n.agent-run-icon.expanded[_ngcontent-%COMP%] {\n color: #9333EA;\n transform: scale(1.1);\n}\n\n@keyframes _ngcontent-%COMP%_rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n\n\n.agent-details-panel[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 16px;\n background: #F9FAFB;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.agent-details-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #6B7280;\n font-size: 13px;\n}\n\n.agent-details-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #9333EA;\n}\n\n\n\n.agent-details-error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #DC2626;\n font-size: 13px;\n}\n\n.agent-details-error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #DC2626;\n}\n\n\n\n.agent-details-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #E5E7EB;\n font-weight: 600;\n font-size: 13px;\n color: #374151;\n}\n\n.agent-details-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #9333EA;\n}\n\n.agent-name-link[_ngcontent-%COMP%] {\n color: #9333EA;\n cursor: pointer;\n text-decoration: none;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.agent-name-link[_ngcontent-%COMP%]:hover {\n color: #7C3AED;\n text-decoration: underline;\n}\n\n\n\n.agent-details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border-radius: 6px;\n border: 1px solid #E5E7EB;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #111827;\n font-weight: 600;\n font-family: 'Monaco', 'Menlo', 'Consolas', monospace;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%] {\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-pending[_ngcontent-%COMP%] {\n background: #FEF3C7;\n color: #92400E;\n}\n\n.status-badge.status-running[_ngcontent-%COMP%] {\n background: #DBEAFE;\n color: #1E40AF;\n}\n\n.status-badge.status-complete[_ngcontent-%COMP%] {\n background: #D1FAE5;\n color: #065F46;\n}\n\n.status-badge.status-failed[_ngcontent-%COMP%], \n.status-badge.status-error[_ngcontent-%COMP%] {\n background: #FEE2E2;\n color: #991B1B;\n}\n\n.status-badge.status-cancelled[_ngcontent-%COMP%] {\n background: #F3F4F6;\n color: #4B5563;\n}\n\n\n\n.run-id-link[_ngcontent-%COMP%] {\n color: #3B82F6;\n cursor: pointer;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n}\n\n.run-id-link[_ngcontent-%COMP%]:hover {\n color: #2563EB;\n text-decoration: underline;\n}\n\n.run-id-link[_ngcontent-%COMP%] i.fa-external-link-alt[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.7;\n}\n\n\n\n.agent-details-tasks[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid #E5E7EB;\n}\n\n.tasks-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-weight: 600;\n font-size: 12px;\n color: #374151;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.tasks-section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3B82F6;\n font-size: 11px;\n}\n\n.tasks-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tasks-list[_ngcontent-%COMP%] mj-task-widget[_ngcontent-%COMP%] {\n display: block;\n}\n\n\n\n.artifact-version-badge[_ngcontent-%COMP%] {\n display: inline-block;\n margin-left: 8px;\n padding: 2px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 11px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n vertical-align: middle;\n}", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[class^=\"mj-icon-\"][_ngcontent-%COMP%], \n[class*=\" mj-icon-\"][_ngcontent-%COMP%] {\n font-style: normal;\n font-variant: normal;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n display: inline-block;\n font-size: inherit;\n line-height: 1;\n}\n\n\n\n\n\n\n\n\n\n\n\n.mj-icon-skip[_ngcontent-%COMP%] {\n width: 1.4em;\n height: 1.4em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n \n\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.89918457031249 96.83947368421053'%3E%3Cg transform='translate(-0.1288232421875,-0.0)'%3E%3Cpath d='M93.85,41.56c-.84,0-1.62.2-2.37.55-3-4.35-7.49-8.12-13.04-11.04l.04-7.18v-14.44h-10.24v17.6c-1.52-.43-3.07-.8-4.67-1.11V0h-10.24v24.72s-.09,0-.14,0h-4.38s-.1,0-.14,0V7.3h-10.24v18.62c-1.6.32-3.15.69-4.67,1.11v-11.67h-10.24v6.09l.04,9.6c-5.55,2.92-10.04,6.7-13.04,11.04-.75-.35-1.53-.55-2.37-.55-4.5,0-8.14,5.61-8.14,12.51s3.64,12.53,8.14,12.53c.58,0,1.14-.12,1.67-.29,4.1,6.62,11.54,12.06,20.98,15.28l.79.13v7.05c0,2.97,1.45,5.58,3.87,6.99,1.18.69,2.5,1.04,3.85,1.03,1.4,0,2.83-.37,4.15-1.12l7.54-4.29,7.56,4.3c1.31.74,2.73,1.12,4.13,1.12s2.67-.35,3.85-1.04c2.42-1.41,3.86-4.02,3.86-6.98v-7.05l.79-.13c9.44-3.22,16.89-8.66,20.98-15.28.54.17,1.09.29,1.68.29,4.5,0,8.14-5.61,8.14-12.53s-3.63-12.51-8.14-12.51' fill='%23AAAAAA'/%3E%3Cpath d='M86.69,50.87c0-12.22-13.6-19.1-28.94-20.66-4.48-.47-9.19-.54-13.52,0-15.34,1.53-28.93,8.41-28.93,20.66,0,8.55,5.7,15.55,12.68,15.55h7.94c3.05,2.5,6.93,4.1,11.08,4.71,2.65.4,5.44.46,8.01,0,4.15-.6,8.05-2.2,11.1-4.71h7.92c6.97,0,12.68-7,12.68-15.55' fill='white' opacity='0.9'/%3E%3Cpath d='M57.83,55.82c-1.19,2.58-3.8,4.35-6.84,4.35s-5.65-1.77-6.84-4.35h13.68Z' fill='%23AAAAAA'/%3E%3Cpath d='M32.52,41.14c1.74,0,3.18,2.13,3.18,4.76s-1.44,4.74-3.18,4.74-3.16-2.13-3.16-4.74,1.41-4.76,3.16-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M69.46,41.14c1.74,0,3.16,2.13,3.16,4.76s-1.41,4.74-3.16,4.74-3.18-2.13-3.18-4.74,1.41-4.76,3.18-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M63.91,76.15c-.82-.48-1.84-.43-2.8.12l-10.13,5.75-10.11-5.75c-.96-.55-1.98-.59-2.8-.12-.82.47-1.29,1.38-1.29,2.49v10.12c0,1.11.47,2.02,1.28,2.49.38.22.8.33,1.24.33.51,0,1.05-.15,1.57-.44l10.12-5.75,10.11,5.75c.52.29,1.05.44,1.56.44.44,0,.86-.11,1.24-.33.81-.48,1.28-1.38,1.28-2.49v-10.12c0-1.11-.47-2.02-1.28-2.49' fill='white' opacity='0.9'/%3E%3C/g%3E%3C/svg%3E\");\n vertical-align: middle;\n}\n\n\n\n\n\n\n.mj-icon-skip-lightning[_ngcontent-%COMP%]::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n font-size: 1.1em;\n}\n\n\n\n\n\n\n.mj-icon-skip-brain[_ngcontent-%COMP%]::before {\n content: \"\uD83E\uDDE0\";\n font-size: 1.2em;\n}\n\n\n\n\n\n\n\n\n\n\n.mj-icon-data-analyst[_ngcontent-%COMP%]::before {\n content: \"\uD83D\uDCCA\";\n font-size: 1.1em;\n}\n\n\n\n\n\n.mj-icon-api[_ngcontent-%COMP%]::before {\n content: \"\uD83D\uDD0C\";\n font-size: 1.1em;\n}\n\n\n\n\n\n.mj-icon-processing[_ngcontent-%COMP%]::before {\n content: \"\u2699\uFE0F\";\n display: inline-block;\n animation: _ngcontent-%COMP%_rotate-icon 2s linear infinite;\n}\n\n@keyframes _ngcontent-%COMP%_rotate-icon {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n\n\n\n\n\n.mj-icon-monogram-s[_ngcontent-%COMP%]::before {\n content: \"S\";\n font-weight: 800;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 1.1em;\n color: #667eea;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"] });
|
|
1057
|
+
i0.ɵɵproperty("ngIf", !ctx.isProcessing && !ctx.isInProgressAIMessage && !ctx.isEditing);
|
|
1058
|
+
} }, dependencies: [i3.NgClass, i3.NgForOf, i3.NgIf, i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i5.ArtifactMessageCardComponent, i6.MarkdownComponent, i7.SuggestedResponsesComponent, i8.TaskWidgetComponent, i3.DatePipe], styles: [".message-item[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n padding: 8px 24px;\n transition: background-color 150ms ease;\n animation: _ngcontent-%COMP%_fadeIn 0.3s ease;\n position: relative;\n}\n\n@keyframes _ngcontent-%COMP%_fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-item.ai-message[_ngcontent-%COMP%] {\n background-color: transparent;\n}\n\n.message-item.user-message[_ngcontent-%COMP%] {\n background-color: transparent;\n}\n\n.message-item.pinned[_ngcontent-%COMP%] {\n border-left: 3px solid #0076B6;\n background-color: rgba(0, 118, 182, 0.08);\n}\n\n.message-item.in-progress[_ngcontent-%COMP%] {\n background: linear-gradient(90deg,\n rgba(59, 130, 246, 0.08) 0%,\n rgba(59, 130, 246, 0.12) 50%,\n rgba(59, 130, 246, 0.08) 100%);\n background-size: 200% 100%;\n animation: _ngcontent-%COMP%_shimmer 2s ease-in-out infinite;\n border-left: 3px solid #3B82F6;\n position: relative;\n}\n\n@keyframes _ngcontent-%COMP%_shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .message-text[_ngcontent-%COMP%] {\n color: #1F2937;\n font-weight: 500;\n max-height: 150px;\n overflow-y: auto;\n display: block;\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%]::after {\n content: '';\n position: absolute;\n right: 12px;\n top: 22px;\n width: 16px;\n height: 16px;\n border: 2px solid #3B82F6;\n border-top-color: transparent;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 0.8s linear infinite;\n}\n\n@keyframes _ngcontent-%COMP%_spin {\n to { transform: rotate(360deg); }\n}\n\n\n\n.message-item.in-progress[_ngcontent-%COMP%] .avatar-circle[_ngcontent-%COMP%] {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n animation: _ngcontent-%COMP%_pulse 2s ease-in-out infinite;\n}\n\n@keyframes _ngcontent-%COMP%_pulse {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n }\n 50% {\n box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);\n }\n}\n\n.message-item[_ngcontent-%COMP%]:hover {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n\n\n[_nghost-%COMP%] .mention-badge {\n display: inline-block;\n padding: 2px 8px;\n margin: 0 2px;\n border-radius: 4px;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n[_nghost-%COMP%] .mention-badge.agent {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n}\n\n[_nghost-%COMP%] .mention-badge.user {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n}\n\n[_nghost-%COMP%] .mention-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.message-avatar[_ngcontent-%COMP%] {\n flex-shrink: 0;\n}\n\n.avatar-circle[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: white;\n}\n\n\n\n.avatar-circle.user-avatar[_ngcontent-%COMP%] {\n border-radius: 50%;\n background-color: #333;\n}\n\n\n\n.avatar-circle.ai-avatar[_ngcontent-%COMP%] {\n border-radius: 8px;\n background-color: #9333EA; \n\n}\n\n\n\n.avatar-image[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 50%;\n}\n\n\n\n.artifact-wrapper.system-artifact[_ngcontent-%COMP%] {\n opacity: 0.85;\n position: relative;\n}\n\n.artifact-wrapper.system-artifact[_ngcontent-%COMP%]::before {\n content: 'SYSTEM';\n position: absolute;\n top: 8px;\n right: 8px;\n font-size: 9px;\n font-weight: 600;\n color: #9CA3AF;\n background: #F3F4F6;\n padding: 2px 6px;\n border-radius: 3px;\n letter-spacing: 0.5px;\n z-index: 10;\n}\n\n.message-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n position: relative;\n}\n\n.message-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n font-size: 13px;\n}\n\n.message-sender[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #333;\n}\n\n\n\n.agent-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 10px;\n font-size: 11px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.message-time[_ngcontent-%COMP%] {\n color: #9CA3AF;\n font-size: 12px;\n font-weight: 400;\n}\n\n\n\n.time-pill[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n margin-left: auto;\n transition: all 0.3s ease;\n}\n\n.time-pill[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.time-pill.complete[_ngcontent-%COMP%] {\n background: #E0F2FE;\n color: #0369A1;\n}\n\n\n\n.time-pill.in-progress[_ngcontent-%COMP%] {\n background: #F3E8FF;\n color: #7C3AED;\n animation: _ngcontent-%COMP%_pillPulse 2s ease-in-out infinite;\n}\n\n\n\n.time-pill.active[_ngcontent-%COMP%] {\n background: #E0E7FF;\n color: #4F46E5;\n animation: _ngcontent-%COMP%_pillPulse 2s ease-in-out infinite;\n}\n\n\n\n.time-pill.failed[_ngcontent-%COMP%] {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n@keyframes _ngcontent-%COMP%_pillPulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.85;\n }\n}\n\n\n\n.generation-time[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: #E0F2FE;\n border-radius: 10px;\n font-size: 11px;\n color: #0369A1;\n font-weight: 500;\n margin-left: auto;\n}\n\n.generation-time[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n}\n\n\n\n.message-elapsed[_ngcontent-%COMP%] {\n color: #AAA;\n font-size: 11px;\n font-style: italic;\n}\n\n.message-body[_ngcontent-%COMP%] {\n margin-bottom: 0;\n}\n\n.message-text[_ngcontent-%COMP%] {\n color: #333;\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n\n\n.message-text[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:first-child {\n margin-top: 0;\n}\n\n.message-text[_ngcontent-%COMP%] markdown[_ngcontent-%COMP%] > [_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n}\n\n\n\n.message-item.user-message[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n border-radius: 12px 12px 12px 4px;\n}\n\n.message-item.ai-message[_ngcontent-%COMP%] .message-content[_ngcontent-%COMP%] {\n border-radius: 4px 12px 12px 12px;\n}\n\n\n\n.message-reactions[_ngcontent-%COMP%] {\n display: none; \n\n}\n\n\n\n.artifact-card[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 12px;\n padding: 16px;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 8px;\n background: linear-gradient(135deg, #F8F7FF 0%, #F3F2FF 100%);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 500px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n position: relative;\n overflow: hidden;\n}\n\n.artifact-card[_ngcontent-%COMP%]::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, #8B5CF6 0%, #6366F1 100%);\n opacity: 1;\n}\n\n.artifact-card[_ngcontent-%COMP%]:hover {\n background: linear-gradient(135deg, #F3F2FF 0%, #EBE9FF 100%);\n border-color: rgba(139, 92, 246, 0.3);\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.12);\n transform: translateY(-1px);\n}\n\n.artifact-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.artifact-card-icon[_ngcontent-%COMP%] {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #8B5CF6;\n flex-shrink: 0;\n background: rgba(139, 92, 246, 0.1);\n border-radius: 6px;\n transition: all 0.2s ease;\n}\n\n.artifact-card[_ngcontent-%COMP%]:hover .artifact-card-icon[_ngcontent-%COMP%] {\n background: rgba(139, 92, 246, 0.15);\n transform: scale(1.05);\n}\n\n.artifact-card-icon[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 18px;\n}\n\n.artifact-card-content[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n}\n\n.artifact-card-label[_ngcontent-%COMP%] {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n letter-spacing: -0.01em;\n margin-bottom: 4px;\n}\n\n.artifact-card-description[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #6B7280;\n line-height: 1.5;\n}\n\n.message-actions[_ngcontent-%COMP%] {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transform: translateY(4px);\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n pointer-events: none;\n}\n\n.message-item[_ngcontent-%COMP%]:hover .message-actions[_ngcontent-%COMP%] {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n.message-action-btn[_ngcontent-%COMP%] {\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #6B7280;\n font-size: 13px;\n transition: all 150ms ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n}\n\n.message-action-btn[_ngcontent-%COMP%]:hover {\n background-color: #F3F4F6;\n color: #111827;\n}\n\n.message-action-btn.danger[_ngcontent-%COMP%]:hover {\n background-color: #FEE2E2;\n color: #DC2626;\n}\n\n.message-action-btn.retry-btn[_ngcontent-%COMP%] {\n color: #3B82F6;\n background: #EFF6FF;\n font-weight: 600;\n gap: 6px;\n padding: 6px 12px;\n min-width: auto;\n}\n\n.message-action-btn.retry-btn[_ngcontent-%COMP%]:hover {\n background-color: #DBEAFE;\n color: #2563EB;\n}\n\n\n\n.thread-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n margin-top: 8px;\n background: #EFF6FF;\n border: 1px solid #DBEAFE;\n border-radius: 16px;\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 12px;\n color: #1E40AF;\n font-weight: 500;\n}\n\n.thread-indicator[_ngcontent-%COMP%]:hover {\n background: #DBEAFE;\n border-color: #93C5FD;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(30, 64, 175, 0.1);\n}\n\n.thread-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 14px;\n}\n\n.thread-count[_ngcontent-%COMP%] {\n font-weight: 600;\n}\n\n\n\n.message-item.editing[_ngcontent-%COMP%] {\n background-color: rgba(255, 243, 205, 0.3);\n border-left: 3px solid #FFA726;\n}\n\n.message-edit-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.message-edit-textarea[_ngcontent-%COMP%] {\n width: 100%;\n padding: 12px;\n border: 1px solid #D9D9D9;\n border-radius: 6px;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.6;\n resize: vertical;\n min-height: 80px;\n transition: border-color 150ms ease;\n}\n\n.message-edit-textarea[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: #0076B6;\n box-shadow: 0 0 0 2px rgba(0, 118, 182, 0.1);\n}\n\n.edit-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n}\n\n.edit-action-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.edit-action-btn.save[_ngcontent-%COMP%] {\n background-color: #0076B6;\n color: white;\n}\n\n.edit-action-btn.save[_ngcontent-%COMP%]:hover {\n background-color: #005A8F;\n}\n\n.edit-action-btn.cancel[_ngcontent-%COMP%] {\n background-color: #F4F4F4;\n color: #666;\n}\n\n.edit-action-btn.cancel[_ngcontent-%COMP%]:hover {\n background-color: #E0E0E0;\n color: #333;\n}\n\n.edit-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #AAA;\n font-style: italic;\n}\n\n.edited-badge[_ngcontent-%COMP%] {\n margin-left: 8px;\n font-size: 11px;\n color: #AAA;\n font-style: italic;\n font-weight: normal;\n}\n\n\n\n.message-status[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #6B7280;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 4px;\n margin-left: 8px;\n animation: _ngcontent-%COMP%_statusPulse 2s ease-in-out infinite;\n}\n\n.message-status[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #0076B6;\n font-size: 11px;\n}\n\n.message-status.error[_ngcontent-%COMP%] {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n.message-status.error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #DC2626;\n}\n\n.status-text[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n@keyframes _ngcontent-%COMP%_statusPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n\n\n\n\n\n\n\n\n.agent-run-icon[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n color: #9CA3AF;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n margin-left: 8px;\n}\n\n.agent-run-icon[_ngcontent-%COMP%] i.fa-cog[_ngcontent-%COMP%] {\n font-size: 13px;\n}\n\n.agent-run-icon[_ngcontent-%COMP%]:hover {\n color: #6B7280;\n}\n\n.agent-run-icon.expanded[_ngcontent-%COMP%] {\n color: #9333EA;\n transform: scale(1.1);\n}\n\n@keyframes _ngcontent-%COMP%_rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n\n\n.agent-details-panel[_ngcontent-%COMP%] {\n margin-top: 12px;\n padding: 16px;\n background: #F9FAFB;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease;\n}\n\n@keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n\n\n.agent-details-loading[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #6B7280;\n font-size: 13px;\n}\n\n.agent-details-loading[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #9333EA;\n}\n\n\n\n.agent-details-error[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #DC2626;\n font-size: 13px;\n}\n\n.agent-details-error[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #DC2626;\n}\n\n\n\n.agent-details-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #E5E7EB;\n font-weight: 600;\n font-size: 13px;\n color: #374151;\n}\n\n.agent-details-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #9333EA;\n}\n\n.agent-name-link[_ngcontent-%COMP%] {\n color: #9333EA;\n cursor: pointer;\n text-decoration: none;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.agent-name-link[_ngcontent-%COMP%]:hover {\n color: #7C3AED;\n text-decoration: underline;\n}\n\n\n\n.agent-details-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.detail-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border-radius: 6px;\n border: 1px solid #E5E7EB;\n}\n\n.detail-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.detail-value[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #111827;\n font-weight: 600;\n font-family: 'Monaco', 'Menlo', 'Consolas', monospace;\n}\n\n\n\n.status-badge[_ngcontent-%COMP%] {\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-pending[_ngcontent-%COMP%] {\n background: #FEF3C7;\n color: #92400E;\n}\n\n.status-badge.status-running[_ngcontent-%COMP%] {\n background: #DBEAFE;\n color: #1E40AF;\n}\n\n.status-badge.status-complete[_ngcontent-%COMP%] {\n background: #D1FAE5;\n color: #065F46;\n}\n\n.status-badge.status-failed[_ngcontent-%COMP%], \n.status-badge.status-error[_ngcontent-%COMP%] {\n background: #FEE2E2;\n color: #991B1B;\n}\n\n.status-badge.status-cancelled[_ngcontent-%COMP%] {\n background: #F3F4F6;\n color: #4B5563;\n}\n\n\n\n.run-id-link[_ngcontent-%COMP%] {\n color: #3B82F6;\n cursor: pointer;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n}\n\n.run-id-link[_ngcontent-%COMP%]:hover {\n color: #2563EB;\n text-decoration: underline;\n}\n\n.run-id-link[_ngcontent-%COMP%] i.fa-external-link-alt[_ngcontent-%COMP%] {\n font-size: 10px;\n opacity: 0.7;\n}\n\n\n\n.agent-details-tasks[_ngcontent-%COMP%] {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid #E5E7EB;\n}\n\n.tasks-section-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-weight: 600;\n font-size: 12px;\n color: #374151;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.tasks-section-header[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #3B82F6;\n font-size: 11px;\n}\n\n.tasks-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tasks-list[_ngcontent-%COMP%] mj-task-widget[_ngcontent-%COMP%] {\n display: block;\n}\n\n\n\n.artifact-version-badge[_ngcontent-%COMP%] {\n display: inline-block;\n margin-left: 8px;\n padding: 2px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 11px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n vertical-align: middle;\n}", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[class^=\"mj-icon-\"][_ngcontent-%COMP%], \n[class*=\" mj-icon-\"][_ngcontent-%COMP%] {\n font-style: normal;\n font-variant: normal;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n display: inline-block;\n font-size: inherit;\n line-height: 1;\n}\n\n\n\n\n\n\n\n\n\n\n\n.mj-icon-skip[_ngcontent-%COMP%] {\n width: 1.4em;\n height: 1.4em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n \n\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.89918457031249 96.83947368421053'%3E%3Cg transform='translate(-0.1288232421875,-0.0)'%3E%3Cpath d='M93.85,41.56c-.84,0-1.62.2-2.37.55-3-4.35-7.49-8.12-13.04-11.04l.04-7.18v-14.44h-10.24v17.6c-1.52-.43-3.07-.8-4.67-1.11V0h-10.24v24.72s-.09,0-.14,0h-4.38s-.1,0-.14,0V7.3h-10.24v18.62c-1.6.32-3.15.69-4.67,1.11v-11.67h-10.24v6.09l.04,9.6c-5.55,2.92-10.04,6.7-13.04,11.04-.75-.35-1.53-.55-2.37-.55-4.5,0-8.14,5.61-8.14,12.51s3.64,12.53,8.14,12.53c.58,0,1.14-.12,1.67-.29,4.1,6.62,11.54,12.06,20.98,15.28l.79.13v7.05c0,2.97,1.45,5.58,3.87,6.99,1.18.69,2.5,1.04,3.85,1.03,1.4,0,2.83-.37,4.15-1.12l7.54-4.29,7.56,4.3c1.31.74,2.73,1.12,4.13,1.12s2.67-.35,3.85-1.04c2.42-1.41,3.86-4.02,3.86-6.98v-7.05l.79-.13c9.44-3.22,16.89-8.66,20.98-15.28.54.17,1.09.29,1.68.29,4.5,0,8.14-5.61,8.14-12.53s-3.63-12.51-8.14-12.51' fill='%23AAAAAA'/%3E%3Cpath d='M86.69,50.87c0-12.22-13.6-19.1-28.94-20.66-4.48-.47-9.19-.54-13.52,0-15.34,1.53-28.93,8.41-28.93,20.66,0,8.55,5.7,15.55,12.68,15.55h7.94c3.05,2.5,6.93,4.1,11.08,4.71,2.65.4,5.44.46,8.01,0,4.15-.6,8.05-2.2,11.1-4.71h7.92c6.97,0,12.68-7,12.68-15.55' fill='white' opacity='0.9'/%3E%3Cpath d='M57.83,55.82c-1.19,2.58-3.8,4.35-6.84,4.35s-5.65-1.77-6.84-4.35h13.68Z' fill='%23AAAAAA'/%3E%3Cpath d='M32.52,41.14c1.74,0,3.18,2.13,3.18,4.76s-1.44,4.74-3.18,4.74-3.16-2.13-3.16-4.74,1.41-4.76,3.16-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M69.46,41.14c1.74,0,3.16,2.13,3.16,4.76s-1.41,4.74-3.16,4.74-3.18-2.13-3.18-4.74,1.41-4.76,3.18-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M63.91,76.15c-.82-.48-1.84-.43-2.8.12l-10.13,5.75-10.11-5.75c-.96-.55-1.98-.59-2.8-.12-.82.47-1.29,1.38-1.29,2.49v10.12c0,1.11.47,2.02,1.28,2.49.38.22.8.33,1.24.33.51,0,1.05-.15,1.57-.44l10.12-5.75,10.11,5.75c.52.29,1.05.44,1.56.44.44,0,.86-.11,1.24-.33.81-.48,1.28-1.38,1.28-2.49v-10.12c0-1.11-.47-2.02-1.28-2.49' fill='white' opacity='0.9'/%3E%3C/g%3E%3C/svg%3E\");\n vertical-align: middle;\n}\n\n\n\n\n\n\n.mj-icon-skip-lightning[_ngcontent-%COMP%]::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n font-size: 1.1em;\n}\n\n\n\n\n\n\n.mj-icon-skip-brain[_ngcontent-%COMP%]::before {\n content: \"\uD83E\uDDE0\";\n font-size: 1.2em;\n}\n\n\n\n\n\n\n\n\n\n\n.mj-icon-data-analyst[_ngcontent-%COMP%]::before {\n content: \"\uD83D\uDCCA\";\n font-size: 1.1em;\n}\n\n\n\n\n\n.mj-icon-api[_ngcontent-%COMP%]::before {\n content: \"\uD83D\uDD0C\";\n font-size: 1.1em;\n}\n\n\n\n\n\n.mj-icon-processing[_ngcontent-%COMP%]::before {\n content: \"\u2699\uFE0F\";\n display: inline-block;\n animation: _ngcontent-%COMP%_rotate-icon 2s linear infinite;\n}\n\n@keyframes _ngcontent-%COMP%_rotate-icon {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n\n\n\n\n\n.mj-icon-monogram-s[_ngcontent-%COMP%]::before {\n content: \"S\";\n font-weight: 800;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 1.1em;\n color: #667eea;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"] });
|
|
971
1059
|
}
|
|
972
1060
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageItemComponent, [{
|
|
973
1061
|
type: Component,
|
|
974
|
-
args: [{ selector: 'mj-conversation-message-item', template: "<div [class]=\"messageClasses\">\n <div class=\"message-avatar\">\n <div class=\"avatar-circle\" [class.ai-avatar]=\"isAIMessage\" [class.user-avatar]=\"isUserMessage\">\n <i class=\"fas\" [ngClass]=\"isAIMessage ? (aiAgentInfo?.iconClass || 'fa-robot') : 'fa-user'\"></i>\n </div>\n </div>\n\n <div class=\"message-content\">\n <div class=\"message-header\">\n <span class=\"message-sender\" [title]=\"isAIMessage ? (aiAgentInfo?.role || 'AI Assistant') : ''\">\n {{ isAIMessage ? (aiAgentInfo?.name || 'AI Assistant') : currentUser.Name }}\n </span>\n <span class=\"message-time\">{{ message.__mj_CreatedAt | date:'short' }}</span>\n\n <!-- Generation time for completed AI messages (only show if no active agent run) -->\n <span *ngIf=\"!isUserMessage && formattedGenerationTime && !isTemporaryMessage && !isAgentRunActive\" class=\"generation-time\">\n <i class=\"fas fa-clock\"></i>\n {{ formattedGenerationTime }}\n </span>\n\n <!-- Agent run icon (clickable to expand details) -->\n <span *ngIf=\"hasAgentRun\"\n class=\"agent-run-icon\"\n (click)=\"toggleAgentDetails()\"\n [class.expanded]=\"isAgentDetailsExpanded\"\n title=\"Click to view agent execution details\">\n <i class=\"fas fa-cog\"></i>\n </span>\n\n <!-- Status indicator for user messages -->\n <span *ngIf=\"isUserMessage && messageStatus !== 'Complete'\" class=\"message-status\" [class.error]=\"messageStatus === 'Error'\">\n <i class=\"fas\" [ngClass]=\"messageStatus === 'Error' ? 'fa-exclamation-triangle' : 'fa-circle-notch fa-spin'\"></i>\n <span class=\"status-text\">{{ getStatusText() }}</span>\n </span>\n\n <!-- Elapsed time for AI messages still processing (temporary messages) -->\n <span *ngIf=\"isTemporaryMessage\" class=\"message-elapsed\">{{ _elapsedTimeFormatted }}</span>\n\n <!-- Agent run duration timer for active agent runs (live updating) -->\n <span *ngIf=\"!isTemporaryMessage && isAgentRunActive && hasAgentRun\" class=\"message-elapsed agent-run-timer\">\n {{ _agentRunDurationFormatted }}\n </span>\n </div>\n\n <div class=\"message-body\">\n @if (!isEditing) {\n <div class=\"message-text\">\n <markdown [data]=\"displayMessage\"></markdown>\n @if (isMessageEdited) {\n <span class=\"edited-badge\">(edited)</span>\n }\n </div>\n\n <!-- Artifact Message Card -->\n @if (hasArtifact && artifact && artifactVersion) {\n <mj-artifact-message-card\n [artifactId]=\"artifact.ID\"\n [artifact]=\"artifact\"\n [artifactVersion]=\"artifactVersion\"\n [currentUser]=\"currentUser\"\n (actionPerformed)=\"onArtifactActionPerformed($event)\">\n </mj-artifact-message-card>\n }\n\n <!-- Suggested Responses (shown only for last message by owner) -->\n @if (isLastMessageInConversation && isConversationOwner && suggestedResponses.length > 0) {\n <mj-suggested-responses\n [suggestedResponses]=\"suggestedResponses\"\n [disabled]=\"isProcessing\"\n [isLastMessage]=\"isLastMessageInConversation\"\n [isConversationOwner]=\"isConversationOwner\"\n (responseSelected)=\"onSuggestedResponseSelected($event)\">\n </mj-suggested-responses>\n }\n }\n\n @if (isEditing) {\n <div class=\"message-edit-container\">\n <textarea\n class=\"message-edit-textarea\"\n [(ngModel)]=\"editedText\"\n (keydown)=\"onEditKeydown($event)\"\n rows=\"4\"\n placeholder=\"Edit your message...\"></textarea>\n <div class=\"edit-actions\">\n <button class=\"edit-action-btn save\" (click)=\"saveEdit()\">\n <i class=\"fas fa-check\"></i>\n Save\n </button>\n <button class=\"edit-action-btn cancel\" (click)=\"cancelEditing()\">\n <i class=\"fas fa-times\"></i>\n Cancel\n </button>\n </div>\n <div class=\"edit-hint\">\n Press Enter to save, Shift+Enter for new line, Escape to cancel\n </div>\n </div>\n }\n\n <!-- Agent Run Details Panel (expandable) -->\n @if (isAgentDetailsExpanded && hasAgentRun) {\n <div class=\"agent-details-panel\">\n @if (agentRun) {\n <div class=\"agent-details-content\">\n <div class=\"agent-details-header\">\n <i class=\"fas fa-chart-line\"></i>\n <span>\n <a class=\"agent-name-link\" (click)=\"openAgentRecord()\" title=\"Open agent details\">\n {{ aiAgentInfo?.name || 'Agent' }}\n </a>\n Run Details\n </span>\n </div>\n\n <div class=\"agent-details-grid\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Run ID:</span>\n <span class=\"detail-value\">\n <a class=\"run-id-link\" (click)=\"openAgentRunRecord()\" title=\"Open agent run details\">\n {{ agentRun.ID }}\n <i class=\"fas fa-external-link-alt\"></i>\n </a>\n </span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunStepCount > 0\">\n <span class=\"detail-label\">Steps:</span>\n <span class=\"detail-value\">{{ agentRunStepCount }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunTotalTokens > 0\">\n <span class=\"detail-label\">Tokens:</span>\n <span class=\"detail-value\">{{ formatNumber(agentRunTotalTokens) }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunTotalCost > 0\">\n <span class=\"detail-label\">Cost:</span>\n <span class=\"detail-value\">\\${{ agentRunTotalCost.toFixed(4) }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRun.Status\">\n <span class=\"detail-label\">Status:</span>\n <span class=\"detail-value status-badge\" [class]=\"'status-' + agentRun.Status.toLowerCase()\">\n {{ agentRun.Status }}\n </span>\n </div>\n </div>\n </div>\n }\n\n <!-- Tasks Section -->\n @if (detailTasks.length > 0) {\n <div class=\"agent-details-tasks\">\n <div class=\"tasks-section-header\">\n <i class=\"fas fa-tasks\"></i>\n <span>Associated Tasks ({{ detailTasks.length }})</span>\n </div>\n <div class=\"tasks-list\">\n <mj-task-widget\n *ngFor=\"let task of detailTasks\"\n [task]=\"task\"\n [compact]=\"false\"\n [clickable]=\"false\"\n [showProgress]=\"true\"\n [showDuration]=\"true\">\n </mj-task-widget>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"message-actions\" *ngIf=\"!isProcessing && !isTemporaryMessage && !isEditing\">\n <!-- Retry button for failed AI messages -->\n <button class=\"message-action-btn retry-btn\" (click)=\"onRetryClick()\" title=\"Retry\" *ngIf=\"messageStatus === 'Error' && isAIMessage\">\n <i class=\"fas fa-redo\"></i>\n Retry\n </button>\n\n <button class=\"message-action-btn\" (click)=\"onPinClick()\" [title]=\"message.IsPinned ? 'Unpin' : 'Pin'\">\n <i class=\"fas\" [ngClass]=\"message.IsPinned ? 'fa-thumbtack' : 'fa-thumbtack'\"></i>\n </button>\n <button class=\"message-action-btn\" (click)=\"onEditClick()\" title=\"Edit\" *ngIf=\"isUserMessage\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"message-action-btn danger\" (click)=\"onDeleteClick()\" title=\"Delete\">\n <i class=\"fas fa-trash\"></i>\n </button>\n </div>\n\n <!-- Reaction Buttons -->\n <div class=\"message-reactions\" *ngIf=\"!isProcessing && !isTemporaryMessage && !isEditing\">\n <button class=\"reaction-btn\" (click)=\"toggleReaction('like')\">\n <i class=\"far fa-thumbs-up\"></i>\n <span class=\"reaction-count\">0</span>\n </button>\n <button class=\"reaction-btn\" (click)=\"toggleReaction('comment')\">\n <i class=\"far fa-comment\"></i>\n <span class=\"reaction-count\">0</span>\n </button>\n </div>\n </div>\n</div>", styles: [".message-item {\n display: flex;\n gap: 12px;\n padding: 8px 24px;\n transition: background-color 150ms ease;\n animation: fadeIn 0.3s ease;\n position: relative;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-item.ai-message {\n background-color: transparent;\n}\n\n.message-item.user-message {\n background-color: transparent;\n}\n\n.message-item.pinned {\n border-left: 3px solid #0076B6;\n background-color: rgba(0, 118, 182, 0.08);\n}\n\n.message-item.in-progress {\n background: linear-gradient(90deg,\n rgba(59, 130, 246, 0.08) 0%,\n rgba(59, 130, 246, 0.12) 50%,\n rgba(59, 130, 246, 0.08) 100%);\n background-size: 200% 100%;\n animation: shimmer 2s ease-in-out infinite;\n border-left: 3px solid #3B82F6;\n position: relative;\n}\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n/* Progress message styling - make it visually distinct */\n.message-item.in-progress .message-text {\n color: #1F2937;\n font-weight: 500;\n max-height: 150px;\n overflow-y: auto;\n display: block;\n}\n\n/* Progress icon - positioned to the right of message, pushed down to avoid overlap */\n.message-item.in-progress .message-content::after {\n content: '';\n position: absolute;\n right: 12px;\n top: 22px;\n width: 16px;\n height: 16px;\n border: 2px solid #3B82F6;\n border-top-color: transparent;\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n/* Pulse effect for avatar */\n.message-item.in-progress .avatar-circle {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n animation: pulse 2s ease-in-out infinite;\n}\n\n@keyframes pulse {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n }\n 50% {\n box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);\n }\n}\n\n.message-item:hover {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n/* Mention Pills */\n:host ::ng-deep .mention-badge {\n display: inline-block;\n padding: 2px 8px;\n margin: 0 2px;\n border-radius: 4px;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .mention-badge.agent {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n}\n\n:host ::ng-deep .mention-badge.user {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n}\n\n:host ::ng-deep .mention-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.message-avatar {\n flex-shrink: 0;\n}\n\n.avatar-circle {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: white;\n}\n\n/* User avatars are circular */\n.avatar-circle.user-avatar {\n border-radius: 50%;\n background-color: #333;\n}\n\n/* Agent avatars are square with rounded corners */\n.avatar-circle.ai-avatar {\n border-radius: 8px;\n background-color: #9333EA; /* Purple for agents */\n}\n\n.message-content {\n flex: 1;\n min-width: 0;\n position: relative;\n}\n\n.message-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n font-size: 13px;\n}\n\n.message-sender {\n font-weight: 600;\n color: #333;\n}\n\n/* Agent role badge */\n.agent-badge {\n display: inline-block;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 10px;\n font-size: 11px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.message-time {\n color: #9CA3AF;\n font-size: 12px;\n font-weight: 400;\n}\n\n.generation-time {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: #E0F2FE;\n border-radius: 10px;\n font-size: 11px;\n color: #0369A1;\n font-weight: 500;\n margin-left: auto;\n}\n\n.generation-time i {\n font-size: 10px;\n}\n\n.message-elapsed {\n color: #AAA;\n font-size: 11px;\n font-style: italic;\n}\n\n.message-body {\n margin-bottom: 0;\n}\n\n.message-text {\n color: #333;\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n/* Remove extra margin from markdown paragraphs */\n.message-text markdown > :first-child {\n margin-top: 0;\n}\n\n.message-text markdown > :last-child {\n margin-bottom: 0;\n}\n\n/* Asymmetric bubble shapes for message content */\n.message-item.user-message .message-content {\n border-radius: 12px 12px 12px 4px;\n}\n\n.message-item.ai-message .message-content {\n border-radius: 4px 12px 12px 12px;\n}\n\n/* Reaction Buttons */\n.message-reactions {\n display: none; /* Hide reactions for now - not implemented */\n}\n\n/* Artifact Card - Claude.ai Style */\n.artifact-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 12px;\n padding: 16px;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 8px;\n background: linear-gradient(135deg, #F8F7FF 0%, #F3F2FF 100%);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 500px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n position: relative;\n overflow: hidden;\n}\n\n.artifact-card::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, #8B5CF6 0%, #6366F1 100%);\n opacity: 1;\n}\n\n.artifact-card:hover {\n background: linear-gradient(135deg, #F3F2FF 0%, #EBE9FF 100%);\n border-color: rgba(139, 92, 246, 0.3);\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.12);\n transform: translateY(-1px);\n}\n\n.artifact-card-header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.artifact-card-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #8B5CF6;\n flex-shrink: 0;\n background: rgba(139, 92, 246, 0.1);\n border-radius: 6px;\n transition: all 0.2s ease;\n}\n\n.artifact-card:hover .artifact-card-icon {\n background: rgba(139, 92, 246, 0.15);\n transform: scale(1.05);\n}\n\n.artifact-card-icon i {\n font-size: 18px;\n}\n\n.artifact-card-content {\n flex: 1;\n min-width: 0;\n}\n\n.artifact-card-label {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n letter-spacing: -0.01em;\n margin-bottom: 4px;\n}\n\n.artifact-card-description {\n font-size: 13px;\n color: #6B7280;\n line-height: 1.5;\n}\n\n.message-actions {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transform: translateY(4px);\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n pointer-events: none;\n}\n\n.message-item:hover .message-actions {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n.message-action-btn {\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #6B7280;\n font-size: 13px;\n transition: all 150ms ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n}\n\n.message-action-btn:hover {\n background-color: #F3F4F6;\n color: #111827;\n}\n\n.message-action-btn.danger:hover {\n background-color: #FEE2E2;\n color: #DC2626;\n}\n\n.message-action-btn.retry-btn {\n color: #3B82F6;\n background: #EFF6FF;\n font-weight: 600;\n gap: 6px;\n padding: 6px 12px;\n min-width: auto;\n}\n\n.message-action-btn.retry-btn:hover {\n background-color: #DBEAFE;\n color: #2563EB;\n}\n\n/* Thread indicator badge */\n.thread-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n margin-top: 8px;\n background: #EFF6FF;\n border: 1px solid #DBEAFE;\n border-radius: 16px;\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 12px;\n color: #1E40AF;\n font-weight: 500;\n}\n\n.thread-indicator:hover {\n background: #DBEAFE;\n border-color: #93C5FD;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(30, 64, 175, 0.1);\n}\n\n.thread-indicator i {\n font-size: 14px;\n}\n\n.thread-count {\n font-weight: 600;\n}\n\n/* Edit mode styles */\n.message-item.editing {\n background-color: rgba(255, 243, 205, 0.3);\n border-left: 3px solid #FFA726;\n}\n\n.message-edit-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.message-edit-textarea {\n width: 100%;\n padding: 12px;\n border: 1px solid #D9D9D9;\n border-radius: 6px;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.6;\n resize: vertical;\n min-height: 80px;\n transition: border-color 150ms ease;\n}\n\n.message-edit-textarea:focus {\n outline: none;\n border-color: #0076B6;\n box-shadow: 0 0 0 2px rgba(0, 118, 182, 0.1);\n}\n\n.edit-actions {\n display: flex;\n gap: 8px;\n}\n\n.edit-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.edit-action-btn.save {\n background-color: #0076B6;\n color: white;\n}\n\n.edit-action-btn.save:hover {\n background-color: #005A8F;\n}\n\n.edit-action-btn.cancel {\n background-color: #F4F4F4;\n color: #666;\n}\n\n.edit-action-btn.cancel:hover {\n background-color: #E0E0E0;\n color: #333;\n}\n\n.edit-hint {\n font-size: 12px;\n color: #AAA;\n font-style: italic;\n}\n\n.edited-badge {\n margin-left: 8px;\n font-size: 11px;\n color: #AAA;\n font-style: italic;\n font-weight: normal;\n}\n\n/* Message status indicator */\n.message-status {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #6B7280;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 4px;\n margin-left: 8px;\n animation: statusPulse 2s ease-in-out infinite;\n}\n\n.message-status i {\n color: #0076B6;\n font-size: 11px;\n}\n\n.message-status.error {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n.message-status.error i {\n color: #DC2626;\n}\n\n.status-text {\n font-weight: 500;\n}\n\n@keyframes statusPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n\n/* ============================================\n Agent Run Icon & Details Panel\n ============================================ */\n\n/* Agent run gear icon in header - muted style for power users */\n.agent-run-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n color: #9CA3AF;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n margin-left: 8px;\n}\n\n.agent-run-icon i.fa-cog {\n font-size: 13px;\n}\n\n.agent-run-icon:hover {\n color: #6B7280;\n}\n\n.agent-run-icon.expanded {\n color: #9333EA;\n transform: scale(1.1);\n}\n\n@keyframes rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Agent details panel */\n.agent-details-panel {\n margin-top: 12px;\n padding: 16px;\n background: #F9FAFB;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n animation: slideDown 0.2s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Loading state */\n.agent-details-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #6B7280;\n font-size: 13px;\n}\n\n.agent-details-loading i {\n color: #9333EA;\n}\n\n/* Error state */\n.agent-details-error {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #DC2626;\n font-size: 13px;\n}\n\n.agent-details-error i {\n color: #DC2626;\n}\n\n/* Content header */\n.agent-details-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #E5E7EB;\n font-weight: 600;\n font-size: 13px;\n color: #374151;\n}\n\n.agent-details-header i {\n color: #9333EA;\n}\n\n.agent-name-link {\n color: #9333EA;\n cursor: pointer;\n text-decoration: none;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.agent-name-link:hover {\n color: #7C3AED;\n text-decoration: underline;\n}\n\n/* Details grid */\n.agent-details-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.detail-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border-radius: 6px;\n border: 1px solid #E5E7EB;\n}\n\n.detail-label {\n font-size: 12px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.detail-value {\n font-size: 13px;\n color: #111827;\n font-weight: 600;\n font-family: 'Monaco', 'Menlo', 'Consolas', monospace;\n}\n\n/* Status badge in details */\n.status-badge {\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-pending {\n background: #FEF3C7;\n color: #92400E;\n}\n\n.status-badge.status-running {\n background: #DBEAFE;\n color: #1E40AF;\n}\n\n.status-badge.status-complete {\n background: #D1FAE5;\n color: #065F46;\n}\n\n.status-badge.status-failed,\n.status-badge.status-error {\n background: #FEE2E2;\n color: #991B1B;\n}\n\n.status-badge.status-cancelled {\n background: #F3F4F6;\n color: #4B5563;\n}\n\n/* Run ID link styling */\n.run-id-link {\n color: #3B82F6;\n cursor: pointer;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n}\n\n.run-id-link:hover {\n color: #2563EB;\n text-decoration: underline;\n}\n\n.run-id-link i.fa-external-link-alt {\n font-size: 10px;\n opacity: 0.7;\n}\n\n/* Tasks section in agent details */\n.agent-details-tasks {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid #E5E7EB;\n}\n\n.tasks-section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-weight: 600;\n font-size: 12px;\n color: #374151;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.tasks-section-header i {\n color: #3B82F6;\n font-size: 11px;\n}\n\n.tasks-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tasks-list mj-task-widget {\n display: block;\n}\n\n/* Artifact version badge */\n.artifact-version-badge {\n display: inline-block;\n margin-left: 8px;\n padding: 2px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 11px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n vertical-align: middle;\n}", "/**\n * Custom Agent Icons for MemberJunction\n *\n * This file contains custom icon definitions for agents that need unique branding\n * beyond Font Awesome icons. Icons can be CSS-based (emoji, Unicode, SVG data URIs)\n * or reference external image files.\n *\n * USAGE IN AGENT METADATA:\n * \"IconClass\": \"mj-icon-skip\" (references .mj-icon-skip class below)\n *\n * EXTENSIBILITY FOR 3RD PARTY DEVELOPERS:\n * Third-party developers have TWO options:\n *\n * 1. CSS CLASS APPROACH (Recommended for developers):\n * - Add your own global CSS with custom icon classes\n * - Reference your class in agent metadata: \"IconClass\": \"your-custom-class\"\n * - Works with any CSS available to the application\n * - Example: If you have a global stylesheet with .acme-icon-analyzer { ... }\n * then use \"IconClass\": \"acme-icon-analyzer\"\n *\n * 2. LOGO URL APPROACH (Recommended for end users):\n * - Use the LogoURL field in agent metadata\n * - Provide a URL or data URI: \"LogoURL\": \"https://example.com/logo.png\"\n * - Supports: HTTP URLs, data URIs (data:image/png;base64,...)\n * - LogoURL takes precedence over IconClass in the UI\n * - Perfect for non-technical users or external/uploaded images\n *\n * BEST PRACTICES:\n * - Use mj-icon-* prefix for MJ core icons\n * - Use your own prefix for 3rd party icons (e.g., acme-icon-*)\n * - Keep icons simple and recognizable at 16-36px sizes\n * - Test in both light and dark themes\n * - Prefer CSS classes over LogoURL for version-controlled icons\n */\n\n/* ============================================\n BASE STYLES FOR CUSTOM ICONS\n ============================================ */\n\n/* Base styling for all custom MJ icons */\n[class^=\"mj-icon-\"],\n[class*=\" mj-icon-\"] {\n font-style: normal;\n font-variant: normal;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n display: inline-block;\n font-size: inherit;\n line-height: 1;\n}\n\n/* ============================================\n MJ CORE ICONS\n ============================================ */\n\n/**\n * Skip Brain Icon - Analytics/Intelligence Agent\n * Official Skip logo from Skip SaaS branding\n */\n.mj-icon-skip {\n width: 1.4em;\n height: 1.4em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n /* Official Skip logo SVG */\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.89918457031249 96.83947368421053'%3E%3Cg transform='translate(-0.1288232421875,-0.0)'%3E%3Cpath d='M93.85,41.56c-.84,0-1.62.2-2.37.55-3-4.35-7.49-8.12-13.04-11.04l.04-7.18v-14.44h-10.24v17.6c-1.52-.43-3.07-.8-4.67-1.11V0h-10.24v24.72s-.09,0-.14,0h-4.38s-.1,0-.14,0V7.3h-10.24v18.62c-1.6.32-3.15.69-4.67,1.11v-11.67h-10.24v6.09l.04,9.6c-5.55,2.92-10.04,6.7-13.04,11.04-.75-.35-1.53-.55-2.37-.55-4.5,0-8.14,5.61-8.14,12.51s3.64,12.53,8.14,12.53c.58,0,1.14-.12,1.67-.29,4.1,6.62,11.54,12.06,20.98,15.28l.79.13v7.05c0,2.97,1.45,5.58,3.87,6.99,1.18.69,2.5,1.04,3.85,1.03,1.4,0,2.83-.37,4.15-1.12l7.54-4.29,7.56,4.3c1.31.74,2.73,1.12,4.13,1.12s2.67-.35,3.85-1.04c2.42-1.41,3.86-4.02,3.86-6.98v-7.05l.79-.13c9.44-3.22,16.89-8.66,20.98-15.28.54.17,1.09.29,1.68.29,4.5,0,8.14-5.61,8.14-12.53s-3.63-12.51-8.14-12.51' fill='%23AAAAAA'/%3E%3Cpath d='M86.69,50.87c0-12.22-13.6-19.1-28.94-20.66-4.48-.47-9.19-.54-13.52,0-15.34,1.53-28.93,8.41-28.93,20.66,0,8.55,5.7,15.55,12.68,15.55h7.94c3.05,2.5,6.93,4.1,11.08,4.71,2.65.4,5.44.46,8.01,0,4.15-.6,8.05-2.2,11.1-4.71h7.92c6.97,0,12.68-7,12.68-15.55' fill='white' opacity='0.9'/%3E%3Cpath d='M57.83,55.82c-1.19,2.58-3.8,4.35-6.84,4.35s-5.65-1.77-6.84-4.35h13.68Z' fill='%23AAAAAA'/%3E%3Cpath d='M32.52,41.14c1.74,0,3.18,2.13,3.18,4.76s-1.44,4.74-3.18,4.74-3.16-2.13-3.16-4.74,1.41-4.76,3.16-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M69.46,41.14c1.74,0,3.16,2.13,3.16,4.76s-1.41,4.74-3.16,4.74-3.18-2.13-3.18-4.74,1.41-4.76,3.18-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M63.91,76.15c-.82-.48-1.84-.43-2.8.12l-10.13,5.75-10.11-5.75c-.96-.55-1.98-.59-2.8-.12-.82.47-1.29,1.38-1.29,2.49v10.12c0,1.11.47,2.02,1.28,2.49.38.22.8.33,1.24.33.51,0,1.05-.15,1.57-.44l10.12-5.75,10.11,5.75c.52.29,1.05.44,1.56.44.44,0,.86-.11,1.24-.33.81-.48,1.28-1.38,1.28-2.49v-10.12c0-1.11-.47-2.02-1.28-2.49' fill='white' opacity='0.9'/%3E%3C/g%3E%3C/svg%3E\");\n vertical-align: middle;\n}\n\n/**\n * Alternative Skip Icon - Lightning Bolt\n * Simple emoji-based icon for quick setup\n */\n.mj-icon-skip-lightning::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n font-size: 1.1em;\n}\n\n/**\n * Skip Icon - Brain Emoji\n * Fallback emoji option\n */\n.mj-icon-skip-brain::before {\n content: \"\uD83E\uDDE0\";\n font-size: 1.2em;\n}\n\n/* ============================================\n EXAMPLE CUSTOM ICONS FOR OTHER AGENTS\n ============================================ */\n\n/**\n * Data Analysis Icon - Chart emoji\n */\n.mj-icon-data-analyst::before {\n content: \"\uD83D\uDCCA\";\n font-size: 1.1em;\n}\n\n/**\n * API/Integration Icon - Plug emoji\n */\n.mj-icon-api::before {\n content: \"\uD83D\uDD0C\";\n font-size: 1.1em;\n}\n\n/**\n * Processing/Workflow Icon - Gear emoji with animation\n */\n.mj-icon-processing::before {\n content: \"\u2699\uFE0F\";\n display: inline-block;\n animation: rotate-icon 2s linear infinite;\n}\n\n@keyframes rotate-icon {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/**\n * Text/Letter-based Icon\n * Simple monogram icon\n */\n.mj-icon-monogram-s::before {\n content: \"S\";\n font-weight: 800;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 1.1em;\n color: #667eea;\n}\n\n/* ============================================\n TEMPLATE FOR NEW ICONS\n ============================================ */\n\n/*\n// EMOJI-BASED ICON (Simplest)\n.mj-icon-my-agent::before {\n content: \"\uD83C\uDFAF\"; // Use any emoji\n font-size: 1.2em;\n}\n\n// UNICODE SYMBOL ICON\n.mj-icon-my-agent::before {\n content: \"\\2022\"; // Unicode character\n font-size: 1.2em;\n color: #667eea;\n}\n\n// TEXT/LETTER ICON\n.mj-icon-my-agent::before {\n content: \"MA\"; // Initials/text\n font-weight: 800;\n font-size: 0.9em;\n color: #667eea;\n}\n\n// SVG DATA URI ICON (Most Control)\n.mj-icon-my-agent {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n background-image: url('data:image/svg+xml;utf8,<svg>...</svg>');\n vertical-align: middle;\n}\n\n// EXTERNAL IMAGE FILE (For existing assets)\n.mj-icon-my-agent {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n background-image: url('/assets/icons/my-agent.svg');\n vertical-align: middle;\n}\n\n// GRADIENT TEXT ICON\n.mj-icon-my-agent::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n}\n*/\n\n/* ============================================\n 3RD PARTY EXAMPLES\n These would typically be in EXTERNAL CSS files\n ============================================ */\n\n/*\n// Example: Acme Corp custom agent icons\n// This would be in acme-corp-styles.css loaded by the application\n\n.acme-icon-analyzer {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-image: url('https://acme.com/icons/analyzer.svg');\n}\n\n.acme-icon-reporter::before {\n content: \"A\";\n font-weight: 800;\n color: #FF6B35;\n}\n*/\n"] }]
|
|
1062
|
+
args: [{ selector: 'mj-conversation-message-item', template: "<div [class]=\"messageClasses\">\n <div class=\"message-avatar\">\n <div class=\"avatar-circle\" [class.ai-avatar]=\"isAIMessage\" [class.user-avatar]=\"isUserMessage\">\n @if (isUserMessage) {\n @if (userAvatarUrl) {\n <img [src]=\"userAvatarUrl\" alt=\"User avatar\" class=\"avatar-image\" />\n } @else if (userAvatarIconClass) {\n <i [class]=\"userAvatarIconClass\"></i>\n } @else {\n <i class=\"fas fa-user\"></i>\n }\n } @else if (isAIMessage) {\n <i class=\"fas\" [ngClass]=\"aiAgentInfo?.iconClass || 'fa-robot'\"></i>\n }\n </div>\n </div>\n\n <div class=\"message-content\">\n <div class=\"message-header\">\n <span class=\"message-sender\" [title]=\"isAIMessage ? (aiAgentInfo?.role || 'AI Assistant') : ''\">\n {{ isAIMessage ? (aiAgentInfo?.name || 'AI Assistant') : messageSenderName }}\n </span>\n <span class=\"message-time\">{{ message.__mj_CreatedAt | date:'short' }}</span>\n\n <!-- Status indicator for user messages -->\n <span *ngIf=\"isUserMessage && messageStatus !== 'Complete'\" class=\"message-status\" [class.error]=\"messageStatus === 'Error'\">\n <i class=\"fas\" [ngClass]=\"messageStatus === 'Error' ? 'fa-exclamation-triangle' : 'fa-circle-notch fa-spin'\"></i>\n <span class=\"status-text\">{{ getStatusText() }}</span>\n </span>\n\n <!-- Time pill - shows for AI messages in all states (in-progress, active, complete, failed) -->\n <span *ngIf=\"!isUserMessage && timePillText\"\n class=\"time-pill\"\n [class.in-progress]=\"isInProgressAIMessage\"\n [class.active]=\"!isInProgressAIMessage && isAgentRunActive\"\n [class.complete]=\"!isInProgressAIMessage && !isAgentRunActive && messageStatus === 'Complete'\"\n [class.failed]=\"messageStatus === 'Error'\">\n <i class=\"fas fa-clock\"></i>\n {{ timePillText }}\n </span>\n\n <!-- Agent run icon (clickable to expand details) - always rightmost when present -->\n <span *ngIf=\"hasAgentRun\"\n class=\"agent-run-icon\"\n (click)=\"toggleAgentDetails()\"\n [class.expanded]=\"isAgentDetailsExpanded\"\n title=\"Click to view agent execution details\">\n <i class=\"fas fa-cog\"></i>\n </span>\n </div>\n\n <div class=\"message-body\">\n @if (!isEditing) {\n <div class=\"message-text\">\n <markdown [data]=\"displayMessage\"></markdown>\n @if (isMessageEdited) {\n <span class=\"edited-badge\">(edited)</span>\n }\n </div>\n\n <!-- Artifact Message Card -->\n @if (hasArtifact && artifact && artifactVersion) {\n <div class=\"artifact-wrapper\" [class.system-artifact]=\"isSystemArtifact\">\n <mj-artifact-message-card\n [artifactId]=\"artifact.ID\"\n [artifact]=\"artifact\"\n [artifactVersion]=\"artifactVersion\"\n [currentUser]=\"currentUser\"\n (actionPerformed)=\"onArtifactActionPerformed($event)\">\n </mj-artifact-message-card>\n </div>\n }\n\n <!-- Suggested Responses (shown only for last message by owner) -->\n @if (isLastMessageInConversation && isConversationOwner && suggestedResponses.length > 0) {\n <mj-suggested-responses\n [suggestedResponses]=\"suggestedResponses\"\n [disabled]=\"isProcessing\"\n [isLastMessage]=\"isLastMessageInConversation\"\n [isConversationOwner]=\"isConversationOwner\"\n (responseSelected)=\"onSuggestedResponseSelected($event)\">\n </mj-suggested-responses>\n }\n }\n\n @if (isEditing) {\n <div class=\"message-edit-container\">\n <textarea\n class=\"message-edit-textarea\"\n [(ngModel)]=\"editedText\"\n (keydown)=\"onEditKeydown($event)\"\n rows=\"4\"\n placeholder=\"Edit your message...\"></textarea>\n <div class=\"edit-actions\">\n <button class=\"edit-action-btn save\" (click)=\"saveEdit()\">\n <i class=\"fas fa-check\"></i>\n Save\n </button>\n <button class=\"edit-action-btn cancel\" (click)=\"cancelEditing()\">\n <i class=\"fas fa-times\"></i>\n Cancel\n </button>\n </div>\n <div class=\"edit-hint\">\n Press Enter to save, Shift+Enter for new line, Escape to cancel\n </div>\n </div>\n }\n\n <!-- Agent Run Details Panel (expandable) -->\n @if (isAgentDetailsExpanded && hasAgentRun) {\n <div class=\"agent-details-panel\">\n @if (agentRun) {\n <div class=\"agent-details-content\">\n <div class=\"agent-details-header\">\n <i class=\"fas fa-chart-line\"></i>\n <span>\n <a class=\"agent-name-link\" (click)=\"openAgentRecord()\" title=\"Open agent details\">\n {{ aiAgentInfo?.name || 'Agent' }}\n </a>\n Run Details\n </span>\n </div>\n\n <div class=\"agent-details-grid\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Run ID:</span>\n <span class=\"detail-value\">\n <a class=\"run-id-link\" (click)=\"openAgentRunRecord()\" title=\"Open agent run details\">\n {{ agentRun.ID }}\n <i class=\"fas fa-external-link-alt\"></i>\n </a>\n </span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunStepCount > 0\">\n <span class=\"detail-label\">Steps:</span>\n <span class=\"detail-value\">{{ agentRunStepCount }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunTotalTokens > 0\">\n <span class=\"detail-label\">Tokens:</span>\n <span class=\"detail-value\">{{ formatNumber(agentRunTotalTokens) }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRunTotalCost > 0\">\n <span class=\"detail-label\">Cost:</span>\n <span class=\"detail-value\">\\${{ agentRunTotalCost.toFixed(4) }}</span>\n </div>\n\n <div class=\"detail-row\" *ngIf=\"agentRun.Status\">\n <span class=\"detail-label\">Status:</span>\n <span class=\"detail-value status-badge\" [class]=\"'status-' + agentRun.Status.toLowerCase()\">\n {{ agentRun.Status }}\n </span>\n </div>\n </div>\n </div>\n }\n\n <!-- Tasks Section -->\n @if (detailTasks.length > 0) {\n <div class=\"agent-details-tasks\">\n <div class=\"tasks-section-header\">\n <i class=\"fas fa-tasks\"></i>\n <span>Associated Tasks ({{ detailTasks.length }})</span>\n </div>\n <div class=\"tasks-list\">\n <mj-task-widget\n *ngFor=\"let task of detailTasks\"\n [task]=\"task\"\n [compact]=\"false\"\n [clickable]=\"false\"\n [showProgress]=\"true\"\n [showDuration]=\"true\">\n </mj-task-widget>\n </div>\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"message-actions\" *ngIf=\"!isProcessing && !isInProgressAIMessage && !isEditing\">\n <!-- Retry button for failed AI messages -->\n <button class=\"message-action-btn retry-btn\" (click)=\"onRetryClick()\" title=\"Retry\" *ngIf=\"messageStatus === 'Error' && isAIMessage\">\n <i class=\"fas fa-redo\"></i>\n Retry\n </button>\n\n <button class=\"message-action-btn\" (click)=\"onPinClick()\" [title]=\"message.IsPinned ? 'Unpin' : 'Pin'\">\n <i class=\"fas\" [ngClass]=\"message.IsPinned ? 'fa-thumbtack' : 'fa-thumbtack'\"></i>\n </button>\n <button class=\"message-action-btn\" (click)=\"onEditClick()\" title=\"Edit\" *ngIf=\"isUserMessage\">\n <i class=\"fas fa-edit\"></i>\n </button>\n <button class=\"message-action-btn danger\" (click)=\"onDeleteClick()\" title=\"Delete\">\n <i class=\"fas fa-trash\"></i>\n </button>\n </div>\n\n <!-- Reaction Buttons -->\n <div class=\"message-reactions\" *ngIf=\"!isProcessing && !isInProgressAIMessage && !isEditing\">\n <button class=\"reaction-btn\" (click)=\"toggleReaction('like')\">\n <i class=\"far fa-thumbs-up\"></i>\n <span class=\"reaction-count\">0</span>\n </button>\n <button class=\"reaction-btn\" (click)=\"toggleReaction('comment')\">\n <i class=\"far fa-comment\"></i>\n <span class=\"reaction-count\">0</span>\n </button>\n </div>\n </div>\n</div>", styles: [".message-item {\n display: flex;\n gap: 12px;\n padding: 8px 24px;\n transition: background-color 150ms ease;\n animation: fadeIn 0.3s ease;\n position: relative;\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n transform: translateY(10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.message-item.ai-message {\n background-color: transparent;\n}\n\n.message-item.user-message {\n background-color: transparent;\n}\n\n.message-item.pinned {\n border-left: 3px solid #0076B6;\n background-color: rgba(0, 118, 182, 0.08);\n}\n\n.message-item.in-progress {\n background: linear-gradient(90deg,\n rgba(59, 130, 246, 0.08) 0%,\n rgba(59, 130, 246, 0.12) 50%,\n rgba(59, 130, 246, 0.08) 100%);\n background-size: 200% 100%;\n animation: shimmer 2s ease-in-out infinite;\n border-left: 3px solid #3B82F6;\n position: relative;\n}\n\n@keyframes shimmer {\n 0% {\n background-position: -200% 0;\n }\n 100% {\n background-position: 200% 0;\n }\n}\n\n/* Progress message styling - make it visually distinct */\n.message-item.in-progress .message-text {\n color: #1F2937;\n font-weight: 500;\n max-height: 150px;\n overflow-y: auto;\n display: block;\n}\n\n/* Progress icon - positioned to the right of message, pushed down to avoid overlap */\n.message-item.in-progress .message-content::after {\n content: '';\n position: absolute;\n right: 12px;\n top: 22px;\n width: 16px;\n height: 16px;\n border: 2px solid #3B82F6;\n border-top-color: transparent;\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n/* Pulse effect for avatar */\n.message-item.in-progress .avatar-circle {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n animation: pulse 2s ease-in-out infinite;\n}\n\n@keyframes pulse {\n 0%, 100% {\n box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7);\n }\n 50% {\n box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);\n }\n}\n\n.message-item:hover {\n background-color: rgba(0, 0, 0, 0.02);\n}\n\n/* Mention Pills */\n:host ::ng-deep .mention-badge {\n display: inline-block;\n padding: 2px 8px;\n margin: 0 2px;\n border-radius: 4px;\n font-weight: 500;\n font-size: 14px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n:host ::ng-deep .mention-badge.agent {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n}\n\n:host ::ng-deep .mention-badge.user {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n color: white;\n}\n\n:host ::ng-deep .mention-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.message-avatar {\n flex-shrink: 0;\n}\n\n.avatar-circle {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n color: white;\n}\n\n/* User avatars are circular */\n.avatar-circle.user-avatar {\n border-radius: 50%;\n background-color: #333;\n}\n\n/* Agent avatars are square with rounded corners */\n.avatar-circle.ai-avatar {\n border-radius: 8px;\n background-color: #9333EA; /* Purple for agents */\n}\n\n/* Avatar images (for users with uploaded photos or URLs) */\n.avatar-image {\n width: 100%;\n height: 100%;\n object-fit: cover;\n border-radius: 50%;\n}\n\n/* System artifact styling - subtle visual distinction */\n.artifact-wrapper.system-artifact {\n opacity: 0.85;\n position: relative;\n}\n\n.artifact-wrapper.system-artifact::before {\n content: 'SYSTEM';\n position: absolute;\n top: 8px;\n right: 8px;\n font-size: 9px;\n font-weight: 600;\n color: #9CA3AF;\n background: #F3F4F6;\n padding: 2px 6px;\n border-radius: 3px;\n letter-spacing: 0.5px;\n z-index: 10;\n}\n\n.message-content {\n flex: 1;\n min-width: 0;\n position: relative;\n}\n\n.message-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 4px;\n font-size: 13px;\n}\n\n.message-sender {\n font-weight: 600;\n color: #333;\n}\n\n/* Agent role badge */\n.agent-badge {\n display: inline-block;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 10px;\n font-size: 11px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.message-time {\n color: #9CA3AF;\n font-size: 12px;\n font-weight: 400;\n}\n\n/* Time pill - unified styling for all AI message states */\n.time-pill {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 500;\n margin-left: auto;\n transition: all 0.3s ease;\n}\n\n.time-pill i {\n font-size: 10px;\n}\n\n/* Complete state - light blue (default) */\n.time-pill.complete {\n background: #E0F2FE;\n color: #0369A1;\n}\n\n/* In-progress state - purple/violet with subtle pulse */\n.time-pill.in-progress {\n background: #F3E8FF;\n color: #7C3AED;\n animation: pillPulse 2s ease-in-out infinite;\n}\n\n/* Active agent run state - indigo with subtle pulse */\n.time-pill.active {\n background: #E0E7FF;\n color: #4F46E5;\n animation: pillPulse 2s ease-in-out infinite;\n}\n\n/* Failed state - red */\n.time-pill.failed {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n@keyframes pillPulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.85;\n }\n}\n\n/* Deprecated - keeping for backward compatibility but no longer used */\n.generation-time {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 8px;\n background: #E0F2FE;\n border-radius: 10px;\n font-size: 11px;\n color: #0369A1;\n font-weight: 500;\n margin-left: auto;\n}\n\n.generation-time i {\n font-size: 10px;\n}\n\n/* Deprecated - keeping for backward compatibility but no longer used */\n.message-elapsed {\n color: #AAA;\n font-size: 11px;\n font-style: italic;\n}\n\n.message-body {\n margin-bottom: 0;\n}\n\n.message-text {\n color: #333;\n line-height: 1.5;\n word-wrap: break-word;\n}\n\n/* Remove extra margin from markdown paragraphs */\n.message-text markdown > :first-child {\n margin-top: 0;\n}\n\n.message-text markdown > :last-child {\n margin-bottom: 0;\n}\n\n/* Asymmetric bubble shapes for message content */\n.message-item.user-message .message-content {\n border-radius: 12px 12px 12px 4px;\n}\n\n.message-item.ai-message .message-content {\n border-radius: 4px 12px 12px 12px;\n}\n\n/* Reaction Buttons */\n.message-reactions {\n display: none; /* Hide reactions for now - not implemented */\n}\n\n/* Artifact Card - Claude.ai Style */\n.artifact-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n margin-top: 12px;\n padding: 16px;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 8px;\n background: linear-gradient(135deg, #F8F7FF 0%, #F3F2FF 100%);\n cursor: pointer;\n transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n max-width: 500px;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n position: relative;\n overflow: hidden;\n}\n\n.artifact-card::before {\n content: '';\n position: absolute;\n left: 0;\n top: 0;\n bottom: 0;\n width: 3px;\n background: linear-gradient(180deg, #8B5CF6 0%, #6366F1 100%);\n opacity: 1;\n}\n\n.artifact-card:hover {\n background: linear-gradient(135deg, #F3F2FF 0%, #EBE9FF 100%);\n border-color: rgba(139, 92, 246, 0.3);\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.12);\n transform: translateY(-1px);\n}\n\n.artifact-card-header {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.artifact-card-icon {\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #8B5CF6;\n flex-shrink: 0;\n background: rgba(139, 92, 246, 0.1);\n border-radius: 6px;\n transition: all 0.2s ease;\n}\n\n.artifact-card:hover .artifact-card-icon {\n background: rgba(139, 92, 246, 0.15);\n transform: scale(1.05);\n}\n\n.artifact-card-icon i {\n font-size: 18px;\n}\n\n.artifact-card-content {\n flex: 1;\n min-width: 0;\n}\n\n.artifact-card-label {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n letter-spacing: -0.01em;\n margin-bottom: 4px;\n}\n\n.artifact-card-description {\n font-size: 13px;\n color: #6B7280;\n line-height: 1.5;\n}\n\n.message-actions {\n position: absolute;\n bottom: 8px;\n right: 8px;\n display: flex;\n gap: 2px;\n opacity: 0;\n transform: translateY(4px);\n transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1);\n background: white;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n padding: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n pointer-events: none;\n}\n\n.message-item:hover .message-actions {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n.message-action-btn {\n padding: 6px 8px;\n background: transparent;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n color: #6B7280;\n font-size: 13px;\n transition: all 150ms ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 32px;\n height: 32px;\n}\n\n.message-action-btn:hover {\n background-color: #F3F4F6;\n color: #111827;\n}\n\n.message-action-btn.danger:hover {\n background-color: #FEE2E2;\n color: #DC2626;\n}\n\n.message-action-btn.retry-btn {\n color: #3B82F6;\n background: #EFF6FF;\n font-weight: 600;\n gap: 6px;\n padding: 6px 12px;\n min-width: auto;\n}\n\n.message-action-btn.retry-btn:hover {\n background-color: #DBEAFE;\n color: #2563EB;\n}\n\n/* Thread indicator badge */\n.thread-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n margin-top: 8px;\n background: #EFF6FF;\n border: 1px solid #DBEAFE;\n border-radius: 16px;\n cursor: pointer;\n transition: all 150ms ease;\n font-size: 12px;\n color: #1E40AF;\n font-weight: 500;\n}\n\n.thread-indicator:hover {\n background: #DBEAFE;\n border-color: #93C5FD;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(30, 64, 175, 0.1);\n}\n\n.thread-indicator i {\n font-size: 14px;\n}\n\n.thread-count {\n font-weight: 600;\n}\n\n/* Edit mode styles */\n.message-item.editing {\n background-color: rgba(255, 243, 205, 0.3);\n border-left: 3px solid #FFA726;\n}\n\n.message-edit-container {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.message-edit-textarea {\n width: 100%;\n padding: 12px;\n border: 1px solid #D9D9D9;\n border-radius: 6px;\n font-family: inherit;\n font-size: 14px;\n line-height: 1.6;\n resize: vertical;\n min-height: 80px;\n transition: border-color 150ms ease;\n}\n\n.message-edit-textarea:focus {\n outline: none;\n border-color: #0076B6;\n box-shadow: 0 0 0 2px rgba(0, 118, 182, 0.1);\n}\n\n.edit-actions {\n display: flex;\n gap: 8px;\n}\n\n.edit-action-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 150ms ease;\n}\n\n.edit-action-btn.save {\n background-color: #0076B6;\n color: white;\n}\n\n.edit-action-btn.save:hover {\n background-color: #005A8F;\n}\n\n.edit-action-btn.cancel {\n background-color: #F4F4F4;\n color: #666;\n}\n\n.edit-action-btn.cancel:hover {\n background-color: #E0E0E0;\n color: #333;\n}\n\n.edit-hint {\n font-size: 12px;\n color: #AAA;\n font-style: italic;\n}\n\n.edited-badge {\n margin-left: 8px;\n font-size: 11px;\n color: #AAA;\n font-style: italic;\n font-weight: normal;\n}\n\n/* Message status indicator */\n.message-status {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n color: #6B7280;\n padding: 2px 8px;\n background: #F3F4F6;\n border-radius: 4px;\n margin-left: 8px;\n animation: statusPulse 2s ease-in-out infinite;\n}\n\n.message-status i {\n color: #0076B6;\n font-size: 11px;\n}\n\n.message-status.error {\n background: #FEE2E2;\n color: #DC2626;\n}\n\n.message-status.error i {\n color: #DC2626;\n}\n\n.status-text {\n font-weight: 500;\n}\n\n@keyframes statusPulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.7; }\n}\n\n/* ============================================\n Agent Run Icon & Details Panel\n ============================================ */\n\n/* Agent run gear icon in header - muted style for power users */\n.agent-run-icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n color: #9CA3AF;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n margin-left: 8px;\n}\n\n.agent-run-icon i.fa-cog {\n font-size: 13px;\n}\n\n.agent-run-icon:hover {\n color: #6B7280;\n}\n\n.agent-run-icon.expanded {\n color: #9333EA;\n transform: scale(1.1);\n}\n\n@keyframes rotate {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Agent details panel */\n.agent-details-panel {\n margin-top: 12px;\n padding: 16px;\n background: #F9FAFB;\n border: 1px solid #E5E7EB;\n border-radius: 8px;\n animation: slideDown 0.2s ease;\n}\n\n@keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(-10px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Loading state */\n.agent-details-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #6B7280;\n font-size: 13px;\n}\n\n.agent-details-loading i {\n color: #9333EA;\n}\n\n/* Error state */\n.agent-details-error {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #DC2626;\n font-size: 13px;\n}\n\n.agent-details-error i {\n color: #DC2626;\n}\n\n/* Content header */\n.agent-details-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #E5E7EB;\n font-weight: 600;\n font-size: 13px;\n color: #374151;\n}\n\n.agent-details-header i {\n color: #9333EA;\n}\n\n.agent-name-link {\n color: #9333EA;\n cursor: pointer;\n text-decoration: none;\n font-weight: 600;\n transition: all 0.2s ease;\n}\n\n.agent-name-link:hover {\n color: #7C3AED;\n text-decoration: underline;\n}\n\n/* Details grid */\n.agent-details-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.detail-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 12px;\n background: white;\n border-radius: 6px;\n border: 1px solid #E5E7EB;\n}\n\n.detail-label {\n font-size: 12px;\n color: #6B7280;\n font-weight: 500;\n}\n\n.detail-value {\n font-size: 13px;\n color: #111827;\n font-weight: 600;\n font-family: 'Monaco', 'Menlo', 'Consolas', monospace;\n}\n\n/* Status badge in details */\n.status-badge {\n padding: 3px 8px;\n border-radius: 10px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n}\n\n.status-badge.status-pending {\n background: #FEF3C7;\n color: #92400E;\n}\n\n.status-badge.status-running {\n background: #DBEAFE;\n color: #1E40AF;\n}\n\n.status-badge.status-complete {\n background: #D1FAE5;\n color: #065F46;\n}\n\n.status-badge.status-failed,\n.status-badge.status-error {\n background: #FEE2E2;\n color: #991B1B;\n}\n\n.status-badge.status-cancelled {\n background: #F3F4F6;\n color: #4B5563;\n}\n\n/* Run ID link styling */\n.run-id-link {\n color: #3B82F6;\n cursor: pointer;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s ease;\n}\n\n.run-id-link:hover {\n color: #2563EB;\n text-decoration: underline;\n}\n\n.run-id-link i.fa-external-link-alt {\n font-size: 10px;\n opacity: 0.7;\n}\n\n/* Tasks section in agent details */\n.agent-details-tasks {\n margin-top: 16px;\n padding-top: 16px;\n border-top: 1px solid #E5E7EB;\n}\n\n.tasks-section-header {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 12px;\n font-weight: 600;\n font-size: 12px;\n color: #374151;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.tasks-section-header i {\n color: #3B82F6;\n font-size: 11px;\n}\n\n.tasks-list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.tasks-list mj-task-widget {\n display: block;\n}\n\n/* Artifact version badge */\n.artifact-version-badge {\n display: inline-block;\n margin-left: 8px;\n padding: 2px 8px;\n background: #EEF2FF;\n color: #4F46E5;\n font-size: 11px;\n font-weight: 600;\n font-family: monospace;\n border-radius: 4px;\n vertical-align: middle;\n}", "/**\n * Custom Agent Icons for MemberJunction\n *\n * This file contains custom icon definitions for agents that need unique branding\n * beyond Font Awesome icons. Icons can be CSS-based (emoji, Unicode, SVG data URIs)\n * or reference external image files.\n *\n * USAGE IN AGENT METADATA:\n * \"IconClass\": \"mj-icon-skip\" (references .mj-icon-skip class below)\n *\n * EXTENSIBILITY FOR 3RD PARTY DEVELOPERS:\n * Third-party developers have TWO options:\n *\n * 1. CSS CLASS APPROACH (Recommended for developers):\n * - Add your own global CSS with custom icon classes\n * - Reference your class in agent metadata: \"IconClass\": \"your-custom-class\"\n * - Works with any CSS available to the application\n * - Example: If you have a global stylesheet with .acme-icon-analyzer { ... }\n * then use \"IconClass\": \"acme-icon-analyzer\"\n *\n * 2. LOGO URL APPROACH (Recommended for end users):\n * - Use the LogoURL field in agent metadata\n * - Provide a URL or data URI: \"LogoURL\": \"https://example.com/logo.png\"\n * - Supports: HTTP URLs, data URIs (data:image/png;base64,...)\n * - LogoURL takes precedence over IconClass in the UI\n * - Perfect for non-technical users or external/uploaded images\n *\n * BEST PRACTICES:\n * - Use mj-icon-* prefix for MJ core icons\n * - Use your own prefix for 3rd party icons (e.g., acme-icon-*)\n * - Keep icons simple and recognizable at 16-36px sizes\n * - Test in both light and dark themes\n * - Prefer CSS classes over LogoURL for version-controlled icons\n */\n\n/* ============================================\n BASE STYLES FOR CUSTOM ICONS\n ============================================ */\n\n/* Base styling for all custom MJ icons */\n[class^=\"mj-icon-\"],\n[class*=\" mj-icon-\"] {\n font-style: normal;\n font-variant: normal;\n text-rendering: auto;\n -webkit-font-smoothing: antialiased;\n display: inline-block;\n font-size: inherit;\n line-height: 1;\n}\n\n/* ============================================\n MJ CORE ICONS\n ============================================ */\n\n/**\n * Skip Brain Icon - Analytics/Intelligence Agent\n * Official Skip logo from Skip SaaS branding\n */\n.mj-icon-skip {\n width: 1.4em;\n height: 1.4em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n /* Official Skip logo SVG */\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 101.89918457031249 96.83947368421053'%3E%3Cg transform='translate(-0.1288232421875,-0.0)'%3E%3Cpath d='M93.85,41.56c-.84,0-1.62.2-2.37.55-3-4.35-7.49-8.12-13.04-11.04l.04-7.18v-14.44h-10.24v17.6c-1.52-.43-3.07-.8-4.67-1.11V0h-10.24v24.72s-.09,0-.14,0h-4.38s-.1,0-.14,0V7.3h-10.24v18.62c-1.6.32-3.15.69-4.67,1.11v-11.67h-10.24v6.09l.04,9.6c-5.55,2.92-10.04,6.7-13.04,11.04-.75-.35-1.53-.55-2.37-.55-4.5,0-8.14,5.61-8.14,12.51s3.64,12.53,8.14,12.53c.58,0,1.14-.12,1.67-.29,4.1,6.62,11.54,12.06,20.98,15.28l.79.13v7.05c0,2.97,1.45,5.58,3.87,6.99,1.18.69,2.5,1.04,3.85,1.03,1.4,0,2.83-.37,4.15-1.12l7.54-4.29,7.56,4.3c1.31.74,2.73,1.12,4.13,1.12s2.67-.35,3.85-1.04c2.42-1.41,3.86-4.02,3.86-6.98v-7.05l.79-.13c9.44-3.22,16.89-8.66,20.98-15.28.54.17,1.09.29,1.68.29,4.5,0,8.14-5.61,8.14-12.53s-3.63-12.51-8.14-12.51' fill='%23AAAAAA'/%3E%3Cpath d='M86.69,50.87c0-12.22-13.6-19.1-28.94-20.66-4.48-.47-9.19-.54-13.52,0-15.34,1.53-28.93,8.41-28.93,20.66,0,8.55,5.7,15.55,12.68,15.55h7.94c3.05,2.5,6.93,4.1,11.08,4.71,2.65.4,5.44.46,8.01,0,4.15-.6,8.05-2.2,11.1-4.71h7.92c6.97,0,12.68-7,12.68-15.55' fill='white' opacity='0.9'/%3E%3Cpath d='M57.83,55.82c-1.19,2.58-3.8,4.35-6.84,4.35s-5.65-1.77-6.84-4.35h13.68Z' fill='%23AAAAAA'/%3E%3Cpath d='M32.52,41.14c1.74,0,3.18,2.13,3.18,4.76s-1.44,4.74-3.18,4.74-3.16-2.13-3.16-4.74,1.41-4.76,3.16-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M69.46,41.14c1.74,0,3.16,2.13,3.16,4.76s-1.41,4.74-3.16,4.74-3.18-2.13-3.18-4.74,1.41-4.76,3.18-4.76' fill='%23AAAAAA'/%3E%3Cpath d='M63.91,76.15c-.82-.48-1.84-.43-2.8.12l-10.13,5.75-10.11-5.75c-.96-.55-1.98-.59-2.8-.12-.82.47-1.29,1.38-1.29,2.49v10.12c0,1.11.47,2.02,1.28,2.49.38.22.8.33,1.24.33.51,0,1.05-.15,1.57-.44l10.12-5.75,10.11,5.75c.52.29,1.05.44,1.56.44.44,0,.86-.11,1.24-.33.81-.48,1.28-1.38,1.28-2.49v-10.12c0-1.11-.47-2.02-1.28-2.49' fill='white' opacity='0.9'/%3E%3C/g%3E%3C/svg%3E\");\n vertical-align: middle;\n}\n\n/**\n * Alternative Skip Icon - Lightning Bolt\n * Simple emoji-based icon for quick setup\n */\n.mj-icon-skip-lightning::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n font-size: 1.1em;\n}\n\n/**\n * Skip Icon - Brain Emoji\n * Fallback emoji option\n */\n.mj-icon-skip-brain::before {\n content: \"\uD83E\uDDE0\";\n font-size: 1.2em;\n}\n\n/* ============================================\n EXAMPLE CUSTOM ICONS FOR OTHER AGENTS\n ============================================ */\n\n/**\n * Data Analysis Icon - Chart emoji\n */\n.mj-icon-data-analyst::before {\n content: \"\uD83D\uDCCA\";\n font-size: 1.1em;\n}\n\n/**\n * API/Integration Icon - Plug emoji\n */\n.mj-icon-api::before {\n content: \"\uD83D\uDD0C\";\n font-size: 1.1em;\n}\n\n/**\n * Processing/Workflow Icon - Gear emoji with animation\n */\n.mj-icon-processing::before {\n content: \"\u2699\uFE0F\";\n display: inline-block;\n animation: rotate-icon 2s linear infinite;\n}\n\n@keyframes rotate-icon {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/**\n * Text/Letter-based Icon\n * Simple monogram icon\n */\n.mj-icon-monogram-s::before {\n content: \"S\";\n font-weight: 800;\n font-family: system-ui, -apple-system, sans-serif;\n font-size: 1.1em;\n color: #667eea;\n}\n\n/* ============================================\n TEMPLATE FOR NEW ICONS\n ============================================ */\n\n/*\n// EMOJI-BASED ICON (Simplest)\n.mj-icon-my-agent::before {\n content: \"\uD83C\uDFAF\"; // Use any emoji\n font-size: 1.2em;\n}\n\n// UNICODE SYMBOL ICON\n.mj-icon-my-agent::before {\n content: \"\\2022\"; // Unicode character\n font-size: 1.2em;\n color: #667eea;\n}\n\n// TEXT/LETTER ICON\n.mj-icon-my-agent::before {\n content: \"MA\"; // Initials/text\n font-weight: 800;\n font-size: 0.9em;\n color: #667eea;\n}\n\n// SVG DATA URI ICON (Most Control)\n.mj-icon-my-agent {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n background-image: url('data:image/svg+xml;utf8,<svg>...</svg>');\n vertical-align: middle;\n}\n\n// EXTERNAL IMAGE FILE (For existing assets)\n.mj-icon-my-agent {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n background-image: url('/assets/icons/my-agent.svg');\n vertical-align: middle;\n}\n\n// GRADIENT TEXT ICON\n.mj-icon-my-agent::before {\n content: \"\u26A1\";\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n}\n*/\n\n/* ============================================\n 3RD PARTY EXAMPLES\n These would typically be in EXTERNAL CSS files\n ============================================ */\n\n/*\n// Example: Acme Corp custom agent icons\n// This would be in acme-corp-styles.css loaded by the application\n\n.acme-icon-analyzer {\n width: 1em;\n height: 1em;\n display: inline-block;\n background-size: contain;\n background-image: url('https://acme.com/icons/analyzer.svg');\n}\n\n.acme-icon-reporter::before {\n content: \"A\";\n font-weight: 800;\n color: #FF6B35;\n}\n*/\n"] }]
|
|
975
1063
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.MentionParserService }, { type: i2.MentionAutocompleteService }], { message: [{
|
|
976
1064
|
type: Input
|
|
977
1065
|
}], conversation: [{
|
|
@@ -988,6 +1076,8 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
988
1076
|
type: Input
|
|
989
1077
|
}], agentRun: [{
|
|
990
1078
|
type: Input
|
|
1079
|
+
}], userAvatarMap: [{
|
|
1080
|
+
type: Input
|
|
991
1081
|
}], pinClicked: [{
|
|
992
1082
|
type: Output
|
|
993
1083
|
}], editClicked: [{
|
|
@@ -1007,5 +1097,5 @@ export class MessageItemComponent extends BaseAngularComponent {
|
|
|
1007
1097
|
}], suggestedResponseSelected: [{
|
|
1008
1098
|
type: Output
|
|
1009
1099
|
}] }); })();
|
|
1010
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageItemComponent, { className: "MessageItemComponent", filePath: "src/lib/components/message/message-item.component.ts", lineNumber:
|
|
1100
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageItemComponent, { className: "MessageItemComponent", filePath: "src/lib/components/message/message-item.component.ts", lineNumber: 35 }); })();
|
|
1011
1101
|
//# sourceMappingURL=message-item.component.js.map
|