@memberjunction/ng-conversations 2.128.0 → 2.130.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/components/attachment/image-viewer.component.d.ts +95 -0
- package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -0
- package/dist/lib/components/attachment/image-viewer.component.js +293 -0
- package/dist/lib/components/attachment/image-viewer.component.js.map +1 -0
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +88 -26
- package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-chat-area.component.js +542 -338
- package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +12 -3
- package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-empty-state.component.js +68 -55
- package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.d.ts +13 -1
- package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
- package/dist/lib/components/conversation/conversation-list.component.js +237 -119
- package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
- package/dist/lib/components/mention/mention-editor.component.d.ts +102 -5
- package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
- package/dist/lib/components/mention/mention-editor.component.js +349 -21
- package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
- package/dist/lib/components/message/agent-response-form.component.d.ts +18 -0
- package/dist/lib/components/message/agent-response-form.component.d.ts.map +1 -1
- package/dist/lib/components/message/agent-response-form.component.js +149 -26
- package/dist/lib/components/message/agent-response-form.component.js.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
- package/dist/lib/components/message/conversation-message-rating.component.js +3 -2
- package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
- package/dist/lib/components/message/form-question.component.js +3 -3
- package/dist/lib/components/message/message-input-box.component.d.ts +29 -2
- package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input-box.component.js +79 -12
- package/dist/lib/components/message/message-input-box.component.js.map +1 -1
- package/dist/lib/components/message/message-input.component.d.ts +60 -5
- package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-input.component.js +303 -119
- package/dist/lib/components/message/message-input.component.js.map +1 -1
- package/dist/lib/components/message/message-item.component.d.ts +41 -3
- package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-item.component.js +237 -106
- package/dist/lib/components/message/message-item.component.js.map +1 -1
- package/dist/lib/components/message/message-list.component.d.ts +7 -2
- package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
- package/dist/lib/components/message/message-list.component.js +19 -4
- package/dist/lib/components/message/message-list.component.js.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +7 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
- package/dist/lib/components/sidebar/conversation-sidebar.component.js +28 -6
- package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts +83 -10
- package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
- package/dist/lib/components/workspace/conversation-workspace.component.js +290 -103
- package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
- package/dist/lib/conversations.module.d.ts +26 -25
- package/dist/lib/conversations.module.d.ts.map +1 -1
- package/dist/lib/conversations.module.js +7 -3
- package/dist/lib/conversations.module.js.map +1 -1
- package/dist/lib/models/conversation-state.model.d.ts +2 -1
- package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.d.ts +23 -0
- package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
- package/dist/lib/services/active-tasks.service.js +91 -2
- package/dist/lib/services/active-tasks.service.js.map +1 -1
- package/dist/lib/services/agent-state.service.d.ts +2 -0
- package/dist/lib/services/agent-state.service.d.ts.map +1 -1
- package/dist/lib/services/agent-state.service.js +20 -3
- package/dist/lib/services/agent-state.service.js.map +1 -1
- package/dist/lib/services/conversation-agent.service.d.ts +38 -6
- package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-agent.service.js +233 -71
- package/dist/lib/services/conversation-agent.service.js.map +1 -1
- package/dist/lib/services/conversation-attachment.service.d.ts +79 -0
- package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -0
- package/dist/lib/services/conversation-attachment.service.js +327 -0
- package/dist/lib/services/conversation-attachment.service.js.map +1 -0
- package/dist/lib/services/conversation-data.service.d.ts +15 -1
- package/dist/lib/services/conversation-data.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-data.service.js +23 -1
- package/dist/lib/services/conversation-data.service.js.map +1 -1
- package/dist/lib/services/conversation-streaming.service.d.ts +50 -1
- package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
- package/dist/lib/services/conversation-streaming.service.js +92 -4
- package/dist/lib/services/conversation-streaming.service.js.map +1 -1
- package/dist/lib/services/mention-autocomplete.service.d.ts +1 -1
- package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.d.ts +16 -1
- package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
- package/dist/lib/services/mention-parser.service.js +30 -0
- package/dist/lib/services/mention-parser.service.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +17 -17
|
@@ -15,8 +15,9 @@ import * as i6 from "../../services/active-tasks.service";
|
|
|
15
15
|
import * as i7 from "../../services/conversation-streaming.service";
|
|
16
16
|
import * as i8 from "../../services/mention-parser.service";
|
|
17
17
|
import * as i9 from "../../services/mention-autocomplete.service";
|
|
18
|
-
import * as i10 from "
|
|
19
|
-
import * as i11 from "
|
|
18
|
+
import * as i10 from "../../services/conversation-attachment.service";
|
|
19
|
+
import * as i11 from "@angular/common";
|
|
20
|
+
import * as i12 from "./message-input-box.component";
|
|
20
21
|
const _c0 = ["inputBox"];
|
|
21
22
|
function MessageInputComponent_div_1_Template(rf, ctx) { if (rf & 1) {
|
|
22
23
|
i0.ɵɵelementStart(0, "div", 4);
|
|
@@ -39,6 +40,7 @@ export class MessageInputComponent {
|
|
|
39
40
|
streamingService;
|
|
40
41
|
mentionParser;
|
|
41
42
|
mentionAutocomplete;
|
|
43
|
+
attachmentService;
|
|
42
44
|
// Default artifact type ID for JSON (when agent doesn't specify DefaultArtifactTypeID)
|
|
43
45
|
JSON_ARTIFACT_TYPE_ID = 'ae674c7e-ea0d-49ea-89e4-0649f5eb20d4';
|
|
44
46
|
conversationId;
|
|
@@ -47,10 +49,41 @@ export class MessageInputComponent {
|
|
|
47
49
|
disabled = false;
|
|
48
50
|
placeholder = 'Type a message... (Ctrl+Enter to send)';
|
|
49
51
|
parentMessageId; // Optional: for replying in threads
|
|
50
|
-
|
|
52
|
+
enableAttachments = true; // Whether to show attachment button (based on agent modality support)
|
|
53
|
+
maxAttachments = 10; // Maximum number of attachments per message
|
|
54
|
+
maxAttachmentSizeBytes = 20 * 1024 * 1024; // Maximum size per attachment (20MB default)
|
|
55
|
+
acceptedFileTypes = 'image/*'; // Accepted MIME types pattern
|
|
51
56
|
artifactsByDetailId; // Pre-loaded artifact data for performance
|
|
52
57
|
systemArtifactsByDetailId; // Pre-loaded system artifact data (Visibility='System Only')
|
|
53
58
|
agentRunsByDetailId; // Pre-loaded agent run data for performance
|
|
59
|
+
emptyStateMode = false; // When true, emits emptyStateSubmit instead of creating messages directly
|
|
60
|
+
// Initial message to send automatically - using getter/setter for precise control
|
|
61
|
+
_initialMessage = null;
|
|
62
|
+
_initialAttachments = null;
|
|
63
|
+
_isComponentReady = false; // Track if component is ready to send
|
|
64
|
+
set initialMessage(value) {
|
|
65
|
+
// Handle case where an object with {text, attachments} is passed instead of just a string
|
|
66
|
+
// This can happen if there's a type mismatch in the binding chain
|
|
67
|
+
let actualValue = value;
|
|
68
|
+
if (value && typeof value === 'object' && 'text' in value) {
|
|
69
|
+
actualValue = value.text;
|
|
70
|
+
}
|
|
71
|
+
const previousValue = this._initialMessage;
|
|
72
|
+
this._initialMessage = actualValue;
|
|
73
|
+
// If component is ready and we have a new non-null message, trigger send
|
|
74
|
+
if (this._isComponentReady && actualValue && actualValue !== previousValue) {
|
|
75
|
+
this.triggerInitialSend();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
get initialMessage() {
|
|
79
|
+
return this._initialMessage;
|
|
80
|
+
}
|
|
81
|
+
set initialAttachments(value) {
|
|
82
|
+
this._initialAttachments = value;
|
|
83
|
+
}
|
|
84
|
+
get initialAttachments() {
|
|
85
|
+
return this._initialAttachments;
|
|
86
|
+
}
|
|
54
87
|
_conversationHistory = [];
|
|
55
88
|
get conversationHistory() {
|
|
56
89
|
return this._conversationHistory;
|
|
@@ -81,17 +114,23 @@ export class MessageInputComponent {
|
|
|
81
114
|
conversationRenamed = new EventEmitter();
|
|
82
115
|
intentCheckStarted = new EventEmitter(); // Emits when intent checking starts
|
|
83
116
|
intentCheckCompleted = new EventEmitter(); // Emits when intent checking completes
|
|
117
|
+
emptyStateSubmit = new EventEmitter(); // Emitted when in emptyStateMode
|
|
118
|
+
uploadStateChanged = new EventEmitter(); // Emits when attachment upload state changes
|
|
84
119
|
inputBox;
|
|
85
120
|
messageText = '';
|
|
86
121
|
isSending = false;
|
|
87
122
|
isProcessing = false; // True when waiting for agent/naming response
|
|
88
123
|
processingMessage = 'AI is responding...'; // Message shown during processing
|
|
124
|
+
isUploadingAttachments = false; // True when uploading attachments to server
|
|
125
|
+
uploadingMessage = 'Uploading attachments...'; // Message shown during upload
|
|
89
126
|
converationManagerAgent = null;
|
|
90
127
|
// Track completion timestamps to prevent race conditions with late progress updates
|
|
91
128
|
completionTimestamps = new Map();
|
|
92
129
|
// Track registered streaming callbacks for cleanup
|
|
93
130
|
registeredCallbacks = new Map();
|
|
94
|
-
|
|
131
|
+
// Track pending attachments from the input box
|
|
132
|
+
pendingAttachments = [];
|
|
133
|
+
constructor(dialogService, toastService, agentService, conversationData, dataCache, activeTasks, streamingService, mentionParser, mentionAutocomplete, attachmentService) {
|
|
95
134
|
this.dialogService = dialogService;
|
|
96
135
|
this.toastService = toastService;
|
|
97
136
|
this.agentService = agentService;
|
|
@@ -101,6 +140,7 @@ export class MessageInputComponent {
|
|
|
101
140
|
this.streamingService = streamingService;
|
|
102
141
|
this.mentionParser = mentionParser;
|
|
103
142
|
this.mentionAutocomplete = mentionAutocomplete;
|
|
143
|
+
this.attachmentService = attachmentService;
|
|
104
144
|
}
|
|
105
145
|
async ngOnInit() {
|
|
106
146
|
this.converationManagerAgent = await this.agentService.getConversationManagerAgent();
|
|
@@ -114,18 +154,34 @@ export class MessageInputComponent {
|
|
|
114
154
|
if (changes['conversationId'] && !changes['conversationId'].firstChange) {
|
|
115
155
|
this.focusInput();
|
|
116
156
|
}
|
|
117
|
-
// Note:
|
|
157
|
+
// Note: initialMessage/initialAttachments handled by setters, inProgressMessageIds handled by setter
|
|
118
158
|
}
|
|
119
159
|
ngAfterViewInit() {
|
|
120
160
|
// Focus input on initial load
|
|
121
161
|
this.focusInput();
|
|
162
|
+
// Mark component as ready
|
|
163
|
+
this._isComponentReady = true;
|
|
122
164
|
// If there's an initial message to send (from empty state), send it automatically
|
|
123
|
-
if (this.
|
|
124
|
-
|
|
125
|
-
this.sendMessageWithText(this.initialMessage);
|
|
126
|
-
}, 100);
|
|
165
|
+
if (this._initialMessage || (this._initialAttachments && this._initialAttachments.length > 0)) {
|
|
166
|
+
this.triggerInitialSend();
|
|
127
167
|
}
|
|
128
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Triggers sending of initial message and attachments.
|
|
171
|
+
* Called from setter or ngAfterViewInit when conditions are met.
|
|
172
|
+
*/
|
|
173
|
+
triggerInitialSend() {
|
|
174
|
+
const message = this._initialMessage;
|
|
175
|
+
const attachments = this._initialAttachments;
|
|
176
|
+
// Set pending attachments before sending
|
|
177
|
+
if (attachments && attachments.length > 0) {
|
|
178
|
+
this.pendingAttachments = [...attachments];
|
|
179
|
+
}
|
|
180
|
+
// Use setTimeout to ensure we're outside of change detection cycle
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
this.sendMessageWithText(message || '');
|
|
183
|
+
}, 100);
|
|
184
|
+
}
|
|
129
185
|
ngOnDestroy() {
|
|
130
186
|
// Unregister all streaming callbacks
|
|
131
187
|
this.unregisterAllCallbacks();
|
|
@@ -189,28 +245,24 @@ export class MessageInputComponent {
|
|
|
189
245
|
console.log(`[StreamingCallback] Message ${messageId} marked complete at ${new Date(completionTime).toISOString()}, ignoring late progress update`);
|
|
190
246
|
return;
|
|
191
247
|
}
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
|
|
248
|
+
// Default: plain message (used by RunAIAgentResolver and TaskOrchestrator without step info)
|
|
249
|
+
message.Message = progress.message;
|
|
250
|
+
// TaskOrchestrator with step info: add formatted header
|
|
195
251
|
// Prefer hierarchical step (e.g., "2.1.3") over flat stepCount
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
updatedMessage = `🔄 **${taskName}**\n\n${progressMessage}`;
|
|
252
|
+
if (progress.resolver === 'TaskOrchestrator') {
|
|
253
|
+
const stepDisplay = progress.metadata?.progress?.hierarchicalStep || progress.stepCount;
|
|
254
|
+
if (stepDisplay != null) {
|
|
255
|
+
message.Message = `**Step ${stepDisplay}**\n\n${progress.message}`;
|
|
256
|
+
}
|
|
204
257
|
}
|
|
205
|
-
message.Message = updatedMessage;
|
|
206
258
|
// Use safe save to prevent race conditions with completion
|
|
207
|
-
const saved = await this.safeSaveConversationDetail(message, `StreamingProgress:${taskName}`);
|
|
259
|
+
const saved = await this.safeSaveConversationDetail(message, `StreamingProgress:${progress.taskName || 'Agent'}`);
|
|
208
260
|
if (saved) {
|
|
209
261
|
// CRITICAL: Emit update to trigger UI refresh
|
|
210
262
|
this.messageSent.emit(message);
|
|
211
263
|
// CRITICAL: Update ActiveTasksService to keep the tasks dropdown in sync
|
|
212
|
-
this.activeTasks.updateStatusByConversationDetailId(message.ID,
|
|
213
|
-
console.log(`[StreamingCallback] Updated message ${messageId}: ${taskName}`);
|
|
264
|
+
this.activeTasks.updateStatusByConversationDetailId(message.ID, progress.message);
|
|
265
|
+
console.log(`[StreamingCallback] Updated message ${messageId}: ${progress.taskName || 'Agent'}`);
|
|
214
266
|
}
|
|
215
267
|
}
|
|
216
268
|
catch (error) {
|
|
@@ -235,20 +287,65 @@ export class MessageInputComponent {
|
|
|
235
287
|
get canSend() {
|
|
236
288
|
return !this.disabled && !this.isSending && this.messageText.trim().length > 0;
|
|
237
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Handle attachments changed from the input box
|
|
292
|
+
*/
|
|
293
|
+
onAttachmentsChanged(attachments) {
|
|
294
|
+
this.pendingAttachments = attachments;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Handle attachment errors from the input box
|
|
298
|
+
*/
|
|
299
|
+
onAttachmentError(error) {
|
|
300
|
+
this.toastService.error(error);
|
|
301
|
+
}
|
|
238
302
|
/**
|
|
239
303
|
* Handle text submitted from the input box
|
|
240
304
|
*/
|
|
241
305
|
async onTextSubmitted(text) {
|
|
242
|
-
//
|
|
243
|
-
|
|
244
|
-
|
|
306
|
+
// Check if we have either text or attachments
|
|
307
|
+
const hasText = text && text.trim().length > 0;
|
|
308
|
+
const hasAttachments = this.pendingAttachments.length > 0;
|
|
309
|
+
if (!hasText && !hasAttachments) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// In empty state mode, just emit the data and let parent handle conversation creation
|
|
313
|
+
if (this.emptyStateMode) {
|
|
314
|
+
const attachmentsToEmit = [...this.pendingAttachments];
|
|
315
|
+
this.pendingAttachments = [];
|
|
316
|
+
this.messageText = '';
|
|
317
|
+
this.emptyStateSubmit.emit({ text: text?.trim() || '', attachments: attachmentsToEmit });
|
|
245
318
|
return;
|
|
246
319
|
}
|
|
247
320
|
this.isSending = true;
|
|
321
|
+
// Store attachments locally since we'll clear them after send
|
|
322
|
+
const attachmentsToSave = [...this.pendingAttachments];
|
|
248
323
|
try {
|
|
249
|
-
const messageDetail = await this.createMessageDetailFromText(text
|
|
324
|
+
const messageDetail = await this.createMessageDetailFromText(text?.trim() || '');
|
|
250
325
|
const saved = await messageDetail.Save();
|
|
251
326
|
if (saved) {
|
|
327
|
+
// Save attachments if any were pending
|
|
328
|
+
// Attachments are stored in ConversationDetailAttachment table and loaded
|
|
329
|
+
// separately when building AI messages - no need to add tokens to Message field
|
|
330
|
+
if (attachmentsToSave.length > 0) {
|
|
331
|
+
// Show upload indicator for attachments
|
|
332
|
+
this.isUploadingAttachments = true;
|
|
333
|
+
this.uploadingMessage = `Uploading ${attachmentsToSave.length} attachment${attachmentsToSave.length > 1 ? 's' : ''}...`;
|
|
334
|
+
this.uploadStateChanged.emit({ isUploading: true, message: this.uploadingMessage });
|
|
335
|
+
try {
|
|
336
|
+
await this.attachmentService.saveAttachments(messageDetail.ID, attachmentsToSave, this.currentUser);
|
|
337
|
+
}
|
|
338
|
+
catch (attachmentError) {
|
|
339
|
+
console.error('Failed to save attachments:', attachmentError);
|
|
340
|
+
this.toastService.error('Some attachments could not be saved');
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
this.isUploadingAttachments = false;
|
|
344
|
+
this.uploadStateChanged.emit({ isUploading: false, message: '' });
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Clear pending attachments after successful send
|
|
348
|
+
this.pendingAttachments = [];
|
|
252
349
|
await this.handleSuccessfulSend(messageDetail);
|
|
253
350
|
}
|
|
254
351
|
else {
|
|
@@ -285,20 +382,24 @@ export class MessageInputComponent {
|
|
|
285
382
|
}
|
|
286
383
|
/**
|
|
287
384
|
* Send a message with custom text WITHOUT modifying the visible messageText input
|
|
288
|
-
* Used for suggested responses
|
|
385
|
+
* Used for suggested responses and initial messages from empty state.
|
|
386
|
+
* Also saves any pending attachments.
|
|
289
387
|
*/
|
|
290
388
|
async sendMessageWithText(text) {
|
|
291
|
-
|
|
389
|
+
const hasText = text && text.trim().length > 0;
|
|
390
|
+
const hasAttachments = this.pendingAttachments.length > 0;
|
|
391
|
+
if (!hasText && !hasAttachments) {
|
|
292
392
|
return;
|
|
293
393
|
}
|
|
294
394
|
if (this.isSending) {
|
|
295
395
|
return;
|
|
296
396
|
}
|
|
297
397
|
this.isSending = true;
|
|
398
|
+
const attachmentsToSave = [...this.pendingAttachments];
|
|
298
399
|
try {
|
|
299
400
|
const detail = await this.dataCache.createConversationDetail(this.currentUser);
|
|
300
401
|
detail.ConversationID = this.conversationId;
|
|
301
|
-
detail.Message = text
|
|
402
|
+
detail.Message = text?.trim() || '';
|
|
302
403
|
detail.Role = 'User';
|
|
303
404
|
detail.UserID = this.currentUser.ID; // Set the user who sent the message
|
|
304
405
|
if (this.parentMessageId) {
|
|
@@ -306,6 +407,26 @@ export class MessageInputComponent {
|
|
|
306
407
|
}
|
|
307
408
|
const saved = await detail.Save();
|
|
308
409
|
if (saved) {
|
|
410
|
+
// Save attachments if any were pending
|
|
411
|
+
if (attachmentsToSave.length > 0) {
|
|
412
|
+
// Show upload indicator for attachments
|
|
413
|
+
this.isUploadingAttachments = true;
|
|
414
|
+
this.uploadingMessage = `Uploading ${attachmentsToSave.length} attachment${attachmentsToSave.length > 1 ? 's' : ''}...`;
|
|
415
|
+
this.uploadStateChanged.emit({ isUploading: true, message: this.uploadingMessage });
|
|
416
|
+
try {
|
|
417
|
+
await this.attachmentService.saveAttachments(detail.ID, attachmentsToSave, this.currentUser);
|
|
418
|
+
}
|
|
419
|
+
catch (attachmentError) {
|
|
420
|
+
console.error('Failed to save attachments:', attachmentError);
|
|
421
|
+
this.toastService.error('Some attachments could not be saved');
|
|
422
|
+
}
|
|
423
|
+
finally {
|
|
424
|
+
this.isUploadingAttachments = false;
|
|
425
|
+
this.uploadStateChanged.emit({ isUploading: false, message: '' });
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// Clear pending attachments after successful send
|
|
429
|
+
this.pendingAttachments = [];
|
|
309
430
|
this.messageSent.emit(detail);
|
|
310
431
|
const mentionResult = this.parseMentionsFromMessage(detail.Message);
|
|
311
432
|
const isFirstMessage = this.conversationHistory.length === 0;
|
|
@@ -384,7 +505,21 @@ export class MessageInputComponent {
|
|
|
384
505
|
await this.handleAgentContinuity(messageDetail, lastAgentId, mentionResult, isFirstMessage);
|
|
385
506
|
return;
|
|
386
507
|
}
|
|
387
|
-
// Priority 3:
|
|
508
|
+
// Priority 3: Check if Sage was explicitly @mentioned with a config preset
|
|
509
|
+
// If so, treat it like agent continuity so the config preset is preserved
|
|
510
|
+
if (this.converationManagerAgent?.ID) {
|
|
511
|
+
const sageConfigPreset = this.agentService.findConfigurationPresetFromHistory(this.converationManagerAgent.ID, this.conversationHistory);
|
|
512
|
+
if (sageConfigPreset) {
|
|
513
|
+
// User explicitly @mentioned Sage with a config - use the shared execution helper directly
|
|
514
|
+
// Pass the already-found config preset to avoid redundant history search
|
|
515
|
+
await this.executeRouteWithNaming(() => this.executeAgentContinuation(messageDetail, this.converationManagerAgent.ID, this.converationManagerAgent.Name || 'Sage', this.conversationId, null, // Sage doesn't use payload continuity
|
|
516
|
+
null, // Sage doesn't use artifact info
|
|
517
|
+
sageConfigPreset // Pass the already-found config preset
|
|
518
|
+
), messageDetail.Message, isFirstMessage);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
// Priority 4: No context - use Sage with default config
|
|
388
523
|
await this.handleNoAgentContext(messageDetail, mentionResult, isFirstMessage);
|
|
389
524
|
}
|
|
390
525
|
/**
|
|
@@ -540,8 +675,9 @@ export class MessageInputComponent {
|
|
|
540
675
|
// This allows us to filter out progress messages from other concurrent agents
|
|
541
676
|
let capturedAgentRunId = null;
|
|
542
677
|
return async (progress) => {
|
|
543
|
-
|
|
544
|
-
const
|
|
678
|
+
const metadata = progress.metadata;
|
|
679
|
+
const progressAgentRun = metadata?.agentRun;
|
|
680
|
+
const progressAgentRunId = metadata?.agentRun?.ID || metadata?.agentRunId;
|
|
545
681
|
// Capture the agent run ID from the first progress message
|
|
546
682
|
if (!capturedAgentRunId && progressAgentRunId) {
|
|
547
683
|
capturedAgentRunId = progressAgentRunId;
|
|
@@ -928,44 +1064,51 @@ export class MessageInputComponent {
|
|
|
928
1064
|
}
|
|
929
1065
|
/**
|
|
930
1066
|
* Load previous payload for an agent from its most recent OUTPUT artifact.
|
|
1067
|
+
* Searches backwards through all messages from this agent until an artifact is found.
|
|
1068
|
+
* This ensures payload continuity even after clarifying exchanges without artifacts.
|
|
931
1069
|
* Checks both user-visible and system artifacts to support agents like Agent Manager.
|
|
932
1070
|
*/
|
|
933
1071
|
async loadPreviousPayloadForAgent(agentId) {
|
|
934
|
-
//
|
|
935
|
-
const
|
|
1072
|
+
// Get all messages from this agent in reverse order (most recent first)
|
|
1073
|
+
const agentMessages = this.conversationHistory
|
|
936
1074
|
.slice()
|
|
937
1075
|
.reverse()
|
|
938
|
-
.
|
|
939
|
-
if (
|
|
1076
|
+
.filter(msg => msg.Role === 'AI' && msg.AgentID === agentId);
|
|
1077
|
+
if (agentMessages.length === 0) {
|
|
940
1078
|
return { payload: null, artifactInfo: null };
|
|
941
1079
|
}
|
|
942
|
-
//
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
artifacts
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
if (artifacts && artifacts.length > 0) {
|
|
950
|
-
const artifact = artifacts[0];
|
|
951
|
-
try {
|
|
952
|
-
const version = await artifact.getVersion();
|
|
953
|
-
if (version.Content) {
|
|
954
|
-
console.log(`📦 Loaded previous payload for agent ${agentId} from artifact`);
|
|
955
|
-
return {
|
|
956
|
-
payload: JSON.parse(version.Content),
|
|
957
|
-
artifactInfo: {
|
|
958
|
-
artifactId: artifact.artifactId,
|
|
959
|
-
versionId: artifact.artifactVersionId,
|
|
960
|
-
versionNumber: artifact.versionNumber
|
|
961
|
-
}
|
|
962
|
-
};
|
|
963
|
-
}
|
|
1080
|
+
// Search through all agent messages until we find one with an artifact
|
|
1081
|
+
for (const message of agentMessages) {
|
|
1082
|
+
// Check user-visible artifacts first
|
|
1083
|
+
let artifacts = this.artifactsByDetailId?.get(message.ID);
|
|
1084
|
+
// If not found, check system artifacts (Agent Manager, etc.)
|
|
1085
|
+
if (!artifacts || artifacts.length === 0) {
|
|
1086
|
+
artifacts = this.systemArtifactsByDetailId?.get(message.ID);
|
|
964
1087
|
}
|
|
965
|
-
|
|
966
|
-
|
|
1088
|
+
// Try to load artifact content as payload
|
|
1089
|
+
if (artifacts && artifacts.length > 0) {
|
|
1090
|
+
const artifact = artifacts[0];
|
|
1091
|
+
try {
|
|
1092
|
+
const version = await artifact.getVersion();
|
|
1093
|
+
if (version.Content) {
|
|
1094
|
+
console.log(`📦 Loaded previous payload for agent ${agentId} from artifact (message: ${message.ID})`);
|
|
1095
|
+
return {
|
|
1096
|
+
payload: JSON.parse(version.Content),
|
|
1097
|
+
artifactInfo: {
|
|
1098
|
+
artifactId: artifact.artifactId,
|
|
1099
|
+
versionId: artifact.artifactVersionId,
|
|
1100
|
+
versionNumber: artifact.versionNumber
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
catch (error) {
|
|
1106
|
+
console.error('Error loading payload from artifact:', error);
|
|
1107
|
+
// Continue to next message
|
|
1108
|
+
}
|
|
967
1109
|
}
|
|
968
1110
|
}
|
|
1111
|
+
console.log(`📦 No previous payload found for agent ${agentId} after searching ${agentMessages.length} messages`);
|
|
969
1112
|
return { payload: null, artifactInfo: null };
|
|
970
1113
|
}
|
|
971
1114
|
/**
|
|
@@ -1081,9 +1224,14 @@ export class MessageInputComponent {
|
|
|
1081
1224
|
const { payload: previousPayload, artifactInfo } = agent?.ID
|
|
1082
1225
|
? await this.loadPreviousPayloadForAgent(agent.ID)
|
|
1083
1226
|
: { payload: null, artifactInfo: null };
|
|
1227
|
+
// Find configuration preset from previous @mention in conversation history
|
|
1228
|
+
const configurationPresetId = agent?.ID
|
|
1229
|
+
? this.agentService.findConfigurationPresetFromHistory(agent.ID, this.conversationHistory)
|
|
1230
|
+
: undefined;
|
|
1084
1231
|
// Invoke the sub-agent with progress callback
|
|
1085
1232
|
const subResult = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.conversationHistory, reasoning, agentResponseMessage.ID, previousPayload, // Pass previous payload for continuity
|
|
1086
|
-
this.createProgressCallback(agentResponseMessage, agentName), artifactInfo?.artifactId, artifactInfo?.versionId
|
|
1233
|
+
this.createProgressCallback(agentResponseMessage, agentName), artifactInfo?.artifactId, artifactInfo?.versionId, configurationPresetId // Pass configuration from previous @mention for continuity
|
|
1234
|
+
);
|
|
1087
1235
|
// Task will be removed automatically in markMessageComplete() when status changes to Complete/Error
|
|
1088
1236
|
// DO NOT remove here - allows UI to show task during entire execution
|
|
1089
1237
|
if (subResult && subResult.success) {
|
|
@@ -1115,9 +1263,10 @@ export class MessageInputComponent {
|
|
|
1115
1263
|
await this.updateConversationDetail(conversationManagerMessage, `👉 **${agentName}** will handle this request...\n\n⚠️ First attempt failed, retrying...`, conversationManagerMessage.Status);
|
|
1116
1264
|
// Update the existing agentResponseMessage to show retry status
|
|
1117
1265
|
await this.updateConversationDetail(agentResponseMessage, "Retrying...", agentResponseMessage.Status);
|
|
1118
|
-
// Retry the sub-agent (reuse previously loaded payload from first attempt)
|
|
1266
|
+
// Retry the sub-agent (reuse previously loaded payload and config from first attempt)
|
|
1119
1267
|
const retryResult = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.conversationHistory, reasoning, agentResponseMessage.ID, previousPayload, // Pass same payload as first attempt
|
|
1120
|
-
this.createProgressCallback(agentResponseMessage, `${agentName} (retry)`), artifactInfo?.artifactId, artifactInfo?.versionId
|
|
1268
|
+
this.createProgressCallback(agentResponseMessage, `${agentName} (retry)`), artifactInfo?.artifactId, artifactInfo?.versionId, configurationPresetId // Pass same config as first attempt
|
|
1269
|
+
);
|
|
1121
1270
|
if (retryResult && retryResult.success) {
|
|
1122
1271
|
// Retry succeeded - update the same message
|
|
1123
1272
|
if (retryResult.agentRun.AgentID) {
|
|
@@ -1178,7 +1327,6 @@ export class MessageInputComponent {
|
|
|
1178
1327
|
return;
|
|
1179
1328
|
}
|
|
1180
1329
|
const agentName = previousAgent.Name || 'Agent';
|
|
1181
|
-
console.log(`🔄 Agent continuity: Continuing with ${agentName} (AgentID: ${lastAIMessage.AgentID})`);
|
|
1182
1330
|
let previousPayload = null;
|
|
1183
1331
|
let previousArtifactInfo = null;
|
|
1184
1332
|
// Use pre-loaded artifact data (no DB queries!)
|
|
@@ -1291,8 +1439,9 @@ export class MessageInputComponent {
|
|
|
1291
1439
|
// Declare agentResponseMessage outside try block so it's accessible in catch
|
|
1292
1440
|
let agentResponseMessage = undefined;
|
|
1293
1441
|
try {
|
|
1294
|
-
//
|
|
1295
|
-
|
|
1442
|
+
// User message is sent successfully - mark complete immediately
|
|
1443
|
+
// (No UI uses User message 'In-Progress' - only AI messages need that status)
|
|
1444
|
+
userMessage.Status = 'Complete';
|
|
1296
1445
|
await userMessage.Save();
|
|
1297
1446
|
this.messageSent.emit(userMessage);
|
|
1298
1447
|
// Look up the agent to get its ID
|
|
@@ -1441,50 +1590,66 @@ export class MessageInputComponent {
|
|
|
1441
1590
|
}
|
|
1442
1591
|
}
|
|
1443
1592
|
}
|
|
1444
|
-
//
|
|
1445
|
-
const
|
|
1593
|
+
// Get all messages from this agent in reverse order (most recent first)
|
|
1594
|
+
const agentMessages = this.conversationHistory
|
|
1446
1595
|
.slice()
|
|
1447
1596
|
.reverse()
|
|
1448
|
-
.
|
|
1449
|
-
// Extract configuration from
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
if (!previousPayload && lastAIMessage) {
|
|
1462
|
-
console.log('📦 Using most recent artifact from last agent message');
|
|
1463
|
-
// Get artifacts from pre-loaded data (check both user-visible and system artifacts)
|
|
1464
|
-
let artifacts = this.artifactsByDetailId?.get(lastAIMessage.ID);
|
|
1465
|
-
if (!artifacts || artifacts.length === 0) {
|
|
1466
|
-
artifacts = this.systemArtifactsByDetailId?.get(lastAIMessage.ID);
|
|
1467
|
-
}
|
|
1468
|
-
if (artifacts && artifacts.length > 0) {
|
|
1469
|
-
try {
|
|
1470
|
-
// Use the first artifact (should only be one OUTPUT per message)
|
|
1471
|
-
const artifact = artifacts[0];
|
|
1472
|
-
const version = await artifact.getVersion();
|
|
1473
|
-
if (version.Content) {
|
|
1474
|
-
previousPayload = JSON.parse(version.Content);
|
|
1475
|
-
previousArtifactInfo = {
|
|
1476
|
-
artifactId: artifact.artifactId,
|
|
1477
|
-
versionId: artifact.artifactVersionId,
|
|
1478
|
-
versionNumber: artifact.versionNumber
|
|
1479
|
-
};
|
|
1480
|
-
console.log('📦 Loaded most recent artifact as payload', previousArtifactInfo);
|
|
1481
|
-
}
|
|
1597
|
+
.filter(msg => msg.Role === 'AI' && msg.AgentID === agentId);
|
|
1598
|
+
// Extract configuration preset from the User message that @mentioned this agent
|
|
1599
|
+
// Uses the shared helper method in the agent service
|
|
1600
|
+
previousConfigurationId = this.agentService.findConfigurationPresetFromHistory(agentId, this.conversationHistory);
|
|
1601
|
+
// Fall back to searching through all agent messages for an artifact
|
|
1602
|
+
// This ensures payload continuity even after clarifying exchanges without artifacts
|
|
1603
|
+
if (!previousPayload && agentMessages.length > 0) {
|
|
1604
|
+
console.log('📦 Searching through agent messages for most recent artifact...');
|
|
1605
|
+
for (const message of agentMessages) {
|
|
1606
|
+
// Get artifacts from pre-loaded data (check both user-visible and system artifacts)
|
|
1607
|
+
let artifacts = this.artifactsByDetailId?.get(message.ID);
|
|
1608
|
+
if (!artifacts || artifacts.length === 0) {
|
|
1609
|
+
artifacts = this.systemArtifactsByDetailId?.get(message.ID);
|
|
1482
1610
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1611
|
+
if (artifacts && artifacts.length > 0) {
|
|
1612
|
+
try {
|
|
1613
|
+
// Use the first artifact (should only be one OUTPUT per message)
|
|
1614
|
+
const artifact = artifacts[0];
|
|
1615
|
+
const version = await artifact.getVersion();
|
|
1616
|
+
if (version.Content) {
|
|
1617
|
+
previousPayload = JSON.parse(version.Content);
|
|
1618
|
+
previousArtifactInfo = {
|
|
1619
|
+
artifactId: artifact.artifactId,
|
|
1620
|
+
versionId: artifact.artifactVersionId,
|
|
1621
|
+
versionNumber: artifact.versionNumber
|
|
1622
|
+
};
|
|
1623
|
+
console.log(`📦 Loaded artifact as payload from message ${message.ID}`, previousArtifactInfo);
|
|
1624
|
+
break; // Found an artifact, stop searching
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
catch (error) {
|
|
1628
|
+
console.warn('⚠️ Could not parse artifact content:', error);
|
|
1629
|
+
// Continue to next message
|
|
1630
|
+
}
|
|
1485
1631
|
}
|
|
1486
1632
|
}
|
|
1633
|
+
if (!previousPayload) {
|
|
1634
|
+
console.log(`📦 No artifact found after searching ${agentMessages.length} messages from agent`);
|
|
1635
|
+
}
|
|
1487
1636
|
}
|
|
1637
|
+
// Execute the agent with the gathered context
|
|
1638
|
+
await this.executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, previousConfigurationId);
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Executes agent continuation with all context already gathered.
|
|
1642
|
+
* This is the shared execution logic used by both continueWithAgent and direct Sage config path.
|
|
1643
|
+
*
|
|
1644
|
+
* @param userMessage The user's message entity
|
|
1645
|
+
* @param agentId The agent ID to invoke
|
|
1646
|
+
* @param agentName The agent's display name
|
|
1647
|
+
* @param conversationId The conversation ID
|
|
1648
|
+
* @param previousPayload Optional payload from previous artifact
|
|
1649
|
+
* @param previousArtifactInfo Optional artifact info (id, versionId, versionNumber)
|
|
1650
|
+
* @param configurationId Optional configuration preset ID to use
|
|
1651
|
+
*/
|
|
1652
|
+
async executeAgentContinuation(userMessage, agentId, agentName, conversationId, previousPayload, previousArtifactInfo, configurationId) {
|
|
1488
1653
|
// Add agent to active tasks
|
|
1489
1654
|
const taskId = this.activeTasks.add({
|
|
1490
1655
|
agentName: agentName,
|
|
@@ -1497,8 +1662,9 @@ export class MessageInputComponent {
|
|
|
1497
1662
|
// Declare agentResponseMessage outside try block so it's accessible in catch
|
|
1498
1663
|
let agentResponseMessage = undefined;
|
|
1499
1664
|
try {
|
|
1500
|
-
//
|
|
1501
|
-
|
|
1665
|
+
// User message is sent successfully - mark complete immediately
|
|
1666
|
+
// (No UI uses User message 'In-Progress' - only AI messages need that status)
|
|
1667
|
+
userMessage.Status = 'Complete';
|
|
1502
1668
|
await userMessage.Save();
|
|
1503
1669
|
this.messageSent.emit(userMessage);
|
|
1504
1670
|
// Create AI response message BEFORE invoking agent (for duration tracking)
|
|
@@ -1515,7 +1681,7 @@ export class MessageInputComponent {
|
|
|
1515
1681
|
this.messageSent.emit(agentResponseMessage);
|
|
1516
1682
|
// Invoke the agent directly (continuation) with previous payload if available
|
|
1517
1683
|
const result = await this.agentService.invokeSubAgent(agentName, conversationId, userMessage, this.conversationHistory, 'Continuing previous conversation with user', agentResponseMessage.ID, previousPayload, // Pass previous OUTPUT artifact payload for continuity
|
|
1518
|
-
this.createProgressCallback(agentResponseMessage, agentName), previousArtifactInfo?.artifactId, previousArtifactInfo?.versionId,
|
|
1684
|
+
this.createProgressCallback(agentResponseMessage, agentName), previousArtifactInfo?.artifactId, previousArtifactInfo?.versionId, configurationId // Pass configuration for continuity
|
|
1519
1685
|
);
|
|
1520
1686
|
// Remove from active tasks
|
|
1521
1687
|
// Task removed in markMessageComplete() - this.activeTasks.remove(taskId);
|
|
@@ -1576,6 +1742,8 @@ export class MessageInputComponent {
|
|
|
1576
1742
|
console.warn('⚠️ GraphQLDataProvider not available');
|
|
1577
1743
|
return;
|
|
1578
1744
|
}
|
|
1745
|
+
// Convert message to plain text (strips JSON-encoded mentions like @{"id":"...","name":"Sage"} to @Sage)
|
|
1746
|
+
const plainTextMessage = this.mentionParser.toPlainText(message, this.mentionAutocomplete.getAvailableAgents(), this.mentionAutocomplete.getAvailableUsers());
|
|
1579
1747
|
const aiClient = new GraphQLAIClient(provider);
|
|
1580
1748
|
// Add 30-second timeout to prevent long delays
|
|
1581
1749
|
// If this times out, the conversation will keep its default name
|
|
@@ -1585,7 +1753,7 @@ export class MessageInputComponent {
|
|
|
1585
1753
|
const result = await Promise.race([
|
|
1586
1754
|
aiClient.RunAIPrompt({
|
|
1587
1755
|
promptId: promptId,
|
|
1588
|
-
messages: [{ role: 'user', content:
|
|
1756
|
+
messages: [{ role: 'user', content: plainTextMessage }],
|
|
1589
1757
|
}),
|
|
1590
1758
|
timeoutPromise
|
|
1591
1759
|
]);
|
|
@@ -1668,32 +1836,32 @@ export class MessageInputComponent {
|
|
|
1668
1836
|
this.completionTimestamps.delete(conversationDetailId);
|
|
1669
1837
|
}, 5000); // 5 seconds should be more than enough
|
|
1670
1838
|
}
|
|
1671
|
-
static ɵfac = function MessageInputComponent_Factory(t) { return new (t || MessageInputComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.ToastService), i0.ɵɵdirectiveInject(i3.ConversationAgentService), i0.ɵɵdirectiveInject(i4.ConversationDataService), i0.ɵɵdirectiveInject(i5.DataCacheService), i0.ɵɵdirectiveInject(i6.ActiveTasksService), i0.ɵɵdirectiveInject(i7.ConversationStreamingService), i0.ɵɵdirectiveInject(i8.MentionParserService), i0.ɵɵdirectiveInject(i9.MentionAutocompleteService)); };
|
|
1839
|
+
static ɵfac = function MessageInputComponent_Factory(t) { return new (t || MessageInputComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.ToastService), i0.ɵɵdirectiveInject(i3.ConversationAgentService), i0.ɵɵdirectiveInject(i4.ConversationDataService), i0.ɵɵdirectiveInject(i5.DataCacheService), i0.ɵɵdirectiveInject(i6.ActiveTasksService), i0.ɵɵdirectiveInject(i7.ConversationStreamingService), i0.ɵɵdirectiveInject(i8.MentionParserService), i0.ɵɵdirectiveInject(i9.MentionAutocompleteService), i0.ɵɵdirectiveInject(i10.ConversationAttachmentService)); };
|
|
1672
1840
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MessageInputComponent, selectors: [["mj-message-input"]], viewQuery: function MessageInputComponent_Query(rf, ctx) { if (rf & 1) {
|
|
1673
1841
|
i0.ɵɵviewQuery(_c0, 5);
|
|
1674
1842
|
} if (rf & 2) {
|
|
1675
1843
|
let _t;
|
|
1676
1844
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.inputBox = _t.first);
|
|
1677
|
-
} }, inputs: { conversationId: "conversationId", conversationName: "conversationName", currentUser: "currentUser", disabled: "disabled", placeholder: "placeholder", parentMessageId: "parentMessageId",
|
|
1845
|
+
} }, inputs: { conversationId: "conversationId", conversationName: "conversationName", currentUser: "currentUser", disabled: "disabled", placeholder: "placeholder", parentMessageId: "parentMessageId", enableAttachments: "enableAttachments", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", artifactsByDetailId: "artifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", emptyStateMode: "emptyStateMode", initialMessage: "initialMessage", initialAttachments: "initialAttachments", conversationHistory: "conversationHistory", inProgressMessageIds: "inProgressMessageIds" }, outputs: { messageSent: "messageSent", agentResponse: "agentResponse", agentRunDetected: "agentRunDetected", agentRunUpdate: "agentRunUpdate", messageComplete: "messageComplete", artifactCreated: "artifactCreated", conversationRenamed: "conversationRenamed", intentCheckStarted: "intentCheckStarted", intentCheckCompleted: "intentCheckCompleted", emptyStateSubmit: "emptyStateSubmit", uploadStateChanged: "uploadStateChanged" }, features: [i0.ɵɵNgOnChangesFeature], decls: 4, vars: 12, consts: [["inputBox", ""], [1, "message-input-wrapper"], ["class", "processing-indicator", 4, "ngIf"], [3, "valueChange", "textSubmitted", "attachmentsChanged", "attachmentError", "placeholder", "disabled", "showCharacterCount", "enableMentions", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "currentUser", "rows", "value"], [1, "processing-indicator"], [1, "fas", "fa-circle-notch", "fa-spin"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1678
1846
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
1679
1847
|
i0.ɵɵelementStart(0, "div", 1);
|
|
1680
1848
|
i0.ɵɵtemplate(1, MessageInputComponent_div_1_Template, 4, 1, "div", 2);
|
|
1681
1849
|
i0.ɵɵelementStart(2, "mj-message-input-box", 3, 0);
|
|
1682
1850
|
i0.ɵɵtwoWayListener("valueChange", function MessageInputComponent_Template_mj_message_input_box_valueChange_2_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.messageText, $event) || (ctx.messageText = $event); return i0.ɵɵresetView($event); });
|
|
1683
|
-
i0.ɵɵlistener("textSubmitted", function MessageInputComponent_Template_mj_message_input_box_textSubmitted_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onTextSubmitted($event)); });
|
|
1851
|
+
i0.ɵɵlistener("textSubmitted", function MessageInputComponent_Template_mj_message_input_box_textSubmitted_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onTextSubmitted($event)); })("attachmentsChanged", function MessageInputComponent_Template_mj_message_input_box_attachmentsChanged_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentsChanged($event)); })("attachmentError", function MessageInputComponent_Template_mj_message_input_box_attachmentError_2_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentError($event)); });
|
|
1684
1852
|
i0.ɵɵelementEnd()();
|
|
1685
1853
|
} if (rf & 2) {
|
|
1686
1854
|
i0.ɵɵadvance();
|
|
1687
1855
|
i0.ɵɵproperty("ngIf", ctx.isProcessing);
|
|
1688
1856
|
i0.ɵɵadvance();
|
|
1689
|
-
i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", true)("currentUser", ctx.currentUser)("rows", 3);
|
|
1857
|
+
i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", true)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes)("currentUser", ctx.currentUser)("rows", 3);
|
|
1690
1858
|
i0.ɵɵtwoWayProperty("value", ctx.messageText);
|
|
1691
|
-
} }, dependencies: [
|
|
1859
|
+
} }, dependencies: [i11.NgIf, i12.MessageInputBoxComponent], styles: [".message-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n}\n\n.processing-indicator[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: rgba(255, 255, 255, 0.95);\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--primary-color, #007bff);\n}\n.processing-indicator[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 0.9rem;\n color: var(--text-primary, #333);\n}"] });
|
|
1692
1860
|
}
|
|
1693
1861
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputComponent, [{
|
|
1694
1862
|
type: Component,
|
|
1695
|
-
args: [{ selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\">\n <!-- Processing Indicator Overlay -->\n <div class=\"processing-indicator\" *ngIf=\"isProcessing\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n\n <!-- Message Input Box -->\n <mj-message-input-box\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"true\"\n [currentUser]=\"currentUser\"\n [rows]=\"3\"\n [(value)]=\"messageText\"\n (textSubmitted)=\"onTextSubmitted($event)\">\n </mj-message-input-box>\n</div>", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n.processing-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: rgba(255, 255, 255, 0.95);\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--primary-color, #007bff);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--text-primary, #333);\n}\n"] }]
|
|
1696
|
-
}], () => [{ type: i1.DialogService }, { type: i2.ToastService }, { type: i3.ConversationAgentService }, { type: i4.ConversationDataService }, { type: i5.DataCacheService }, { type: i6.ActiveTasksService }, { type: i7.ConversationStreamingService }, { type: i8.MentionParserService }, { type: i9.MentionAutocompleteService }], { conversationId: [{
|
|
1863
|
+
args: [{ selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\">\n <!-- Processing Indicator Overlay -->\n <div class=\"processing-indicator\" *ngIf=\"isProcessing\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n\n <!-- Message Input Box -->\n <mj-message-input-box\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"true\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [currentUser]=\"currentUser\"\n [rows]=\"3\"\n [(value)]=\"messageText\"\n (textSubmitted)=\"onTextSubmitted($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\">\n </mj-message-input-box>\n</div>", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n.processing-indicator {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.75rem 1.25rem;\n background: rgba(255, 255, 255, 0.95);\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--primary-color, #007bff);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--text-primary, #333);\n}\n"] }]
|
|
1864
|
+
}], () => [{ type: i1.DialogService }, { type: i2.ToastService }, { type: i3.ConversationAgentService }, { type: i4.ConversationDataService }, { type: i5.DataCacheService }, { type: i6.ActiveTasksService }, { type: i7.ConversationStreamingService }, { type: i8.MentionParserService }, { type: i9.MentionAutocompleteService }, { type: i10.ConversationAttachmentService }], { conversationId: [{
|
|
1697
1865
|
type: Input
|
|
1698
1866
|
}], conversationName: [{
|
|
1699
1867
|
type: Input
|
|
@@ -1705,7 +1873,13 @@ export class MessageInputComponent {
|
|
|
1705
1873
|
type: Input
|
|
1706
1874
|
}], parentMessageId: [{
|
|
1707
1875
|
type: Input
|
|
1708
|
-
}],
|
|
1876
|
+
}], enableAttachments: [{
|
|
1877
|
+
type: Input
|
|
1878
|
+
}], maxAttachments: [{
|
|
1879
|
+
type: Input
|
|
1880
|
+
}], maxAttachmentSizeBytes: [{
|
|
1881
|
+
type: Input
|
|
1882
|
+
}], acceptedFileTypes: [{
|
|
1709
1883
|
type: Input
|
|
1710
1884
|
}], artifactsByDetailId: [{
|
|
1711
1885
|
type: Input
|
|
@@ -1713,6 +1887,12 @@ export class MessageInputComponent {
|
|
|
1713
1887
|
type: Input
|
|
1714
1888
|
}], agentRunsByDetailId: [{
|
|
1715
1889
|
type: Input
|
|
1890
|
+
}], emptyStateMode: [{
|
|
1891
|
+
type: Input
|
|
1892
|
+
}], initialMessage: [{
|
|
1893
|
+
type: Input
|
|
1894
|
+
}], initialAttachments: [{
|
|
1895
|
+
type: Input
|
|
1716
1896
|
}], conversationHistory: [{
|
|
1717
1897
|
type: Input
|
|
1718
1898
|
}], inProgressMessageIds: [{
|
|
@@ -1735,9 +1915,13 @@ export class MessageInputComponent {
|
|
|
1735
1915
|
type: Output
|
|
1736
1916
|
}], intentCheckCompleted: [{
|
|
1737
1917
|
type: Output
|
|
1918
|
+
}], emptyStateSubmit: [{
|
|
1919
|
+
type: Output
|
|
1920
|
+
}], uploadStateChanged: [{
|
|
1921
|
+
type: Output
|
|
1738
1922
|
}], inputBox: [{
|
|
1739
1923
|
type: ViewChild,
|
|
1740
1924
|
args: ['inputBox']
|
|
1741
1925
|
}] }); })();
|
|
1742
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber:
|
|
1926
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 30 }); })();
|
|
1743
1927
|
//# sourceMappingURL=message-input.component.js.map
|