@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.
Files changed (93) hide show
  1. package/dist/lib/components/attachment/image-viewer.component.d.ts +95 -0
  2. package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -0
  3. package/dist/lib/components/attachment/image-viewer.component.js +293 -0
  4. package/dist/lib/components/attachment/image-viewer.component.js.map +1 -0
  5. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +88 -26
  6. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  7. package/dist/lib/components/conversation/conversation-chat-area.component.js +542 -338
  8. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  9. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +12 -3
  10. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  11. package/dist/lib/components/conversation/conversation-empty-state.component.js +68 -55
  12. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  13. package/dist/lib/components/conversation/conversation-list.component.d.ts +13 -1
  14. package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
  15. package/dist/lib/components/conversation/conversation-list.component.js +237 -119
  16. package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
  17. package/dist/lib/components/mention/mention-editor.component.d.ts +102 -5
  18. package/dist/lib/components/mention/mention-editor.component.d.ts.map +1 -1
  19. package/dist/lib/components/mention/mention-editor.component.js +349 -21
  20. package/dist/lib/components/mention/mention-editor.component.js.map +1 -1
  21. package/dist/lib/components/message/agent-response-form.component.d.ts +18 -0
  22. package/dist/lib/components/message/agent-response-form.component.d.ts.map +1 -1
  23. package/dist/lib/components/message/agent-response-form.component.js +149 -26
  24. package/dist/lib/components/message/agent-response-form.component.js.map +1 -1
  25. package/dist/lib/components/message/conversation-message-rating.component.d.ts.map +1 -1
  26. package/dist/lib/components/message/conversation-message-rating.component.js +3 -2
  27. package/dist/lib/components/message/conversation-message-rating.component.js.map +1 -1
  28. package/dist/lib/components/message/form-question.component.js +3 -3
  29. package/dist/lib/components/message/message-input-box.component.d.ts +29 -2
  30. package/dist/lib/components/message/message-input-box.component.d.ts.map +1 -1
  31. package/dist/lib/components/message/message-input-box.component.js +79 -12
  32. package/dist/lib/components/message/message-input-box.component.js.map +1 -1
  33. package/dist/lib/components/message/message-input.component.d.ts +60 -5
  34. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  35. package/dist/lib/components/message/message-input.component.js +303 -119
  36. package/dist/lib/components/message/message-input.component.js.map +1 -1
  37. package/dist/lib/components/message/message-item.component.d.ts +41 -3
  38. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  39. package/dist/lib/components/message/message-item.component.js +237 -106
  40. package/dist/lib/components/message/message-item.component.js.map +1 -1
  41. package/dist/lib/components/message/message-list.component.d.ts +7 -2
  42. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  43. package/dist/lib/components/message/message-list.component.js +19 -4
  44. package/dist/lib/components/message/message-list.component.js.map +1 -1
  45. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +7 -1
  46. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  47. package/dist/lib/components/sidebar/conversation-sidebar.component.js +28 -6
  48. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  49. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +83 -10
  50. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  51. package/dist/lib/components/workspace/conversation-workspace.component.js +290 -103
  52. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  53. package/dist/lib/conversations.module.d.ts +26 -25
  54. package/dist/lib/conversations.module.d.ts.map +1 -1
  55. package/dist/lib/conversations.module.js +7 -3
  56. package/dist/lib/conversations.module.js.map +1 -1
  57. package/dist/lib/models/conversation-state.model.d.ts +2 -1
  58. package/dist/lib/models/conversation-state.model.d.ts.map +1 -1
  59. package/dist/lib/services/active-tasks.service.d.ts +23 -0
  60. package/dist/lib/services/active-tasks.service.d.ts.map +1 -1
  61. package/dist/lib/services/active-tasks.service.js +91 -2
  62. package/dist/lib/services/active-tasks.service.js.map +1 -1
  63. package/dist/lib/services/agent-state.service.d.ts +2 -0
  64. package/dist/lib/services/agent-state.service.d.ts.map +1 -1
  65. package/dist/lib/services/agent-state.service.js +20 -3
  66. package/dist/lib/services/agent-state.service.js.map +1 -1
  67. package/dist/lib/services/conversation-agent.service.d.ts +38 -6
  68. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  69. package/dist/lib/services/conversation-agent.service.js +233 -71
  70. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  71. package/dist/lib/services/conversation-attachment.service.d.ts +79 -0
  72. package/dist/lib/services/conversation-attachment.service.d.ts.map +1 -0
  73. package/dist/lib/services/conversation-attachment.service.js +327 -0
  74. package/dist/lib/services/conversation-attachment.service.js.map +1 -0
  75. package/dist/lib/services/conversation-data.service.d.ts +15 -1
  76. package/dist/lib/services/conversation-data.service.d.ts.map +1 -1
  77. package/dist/lib/services/conversation-data.service.js +23 -1
  78. package/dist/lib/services/conversation-data.service.js.map +1 -1
  79. package/dist/lib/services/conversation-streaming.service.d.ts +50 -1
  80. package/dist/lib/services/conversation-streaming.service.d.ts.map +1 -1
  81. package/dist/lib/services/conversation-streaming.service.js +92 -4
  82. package/dist/lib/services/conversation-streaming.service.js.map +1 -1
  83. package/dist/lib/services/mention-autocomplete.service.d.ts +1 -1
  84. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  85. package/dist/lib/services/mention-parser.service.d.ts +16 -1
  86. package/dist/lib/services/mention-parser.service.d.ts.map +1 -1
  87. package/dist/lib/services/mention-parser.service.js +30 -0
  88. package/dist/lib/services/mention-parser.service.js.map +1 -1
  89. package/dist/public-api.d.ts +2 -0
  90. package/dist/public-api.d.ts.map +1 -1
  91. package/dist/public-api.js +2 -0
  92. package/dist/public-api.js.map +1 -1
  93. 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 "@angular/common";
19
- import * as i11 from "./message-input-box.component";
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
- initialMessage = null; // Message to send automatically when component initializes
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
- constructor(dialogService, toastService, agentService, conversationData, dataCache, activeTasks, streamingService, mentionParser, mentionAutocomplete) {
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: inProgressMessageIds now handled by setter, not ngOnChanges
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.initialMessage) {
124
- setTimeout(() => {
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
- // Build formatted progress message
193
- const taskName = progress.taskName || 'Task';
194
- const progressMessage = progress.message;
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
- // Note: hierarchicalStep is nested inside metadata.progress from GraphQL
197
- const stepDisplay = progress.metadata?.progress?.hierarchicalStep || progress.stepCount;
198
- let updatedMessage;
199
- if (stepDisplay != null) {
200
- updatedMessage = `🔄 **${taskName}** • Step ${stepDisplay}\n\n${progressMessage}`;
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, progressMessage);
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
- // Use the text parameter directly since the box component already cleared its value
243
- if (!text || !text.trim()) {
244
- console.log('[MessageInput] Empty text, aborting');
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.trim());
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 - sends message silently without affecting user's current input
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
- if (!text || !text.trim()) {
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.trim();
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: No context - use Sage
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
- let progressAgentRun = progress.metadata?.agentRun;
544
- const progressAgentRunId = progressAgentRun?.ID || progress.metadata?.agentRunId;
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
- // Find last message from this agent
935
- const lastAgentMessage = this.conversationHistory
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
- .find(msg => msg.Role === 'AI' && msg.AgentID === agentId);
939
- if (!lastAgentMessage) {
1076
+ .filter(msg => msg.Role === 'AI' && msg.AgentID === agentId);
1077
+ if (agentMessages.length === 0) {
940
1078
  return { payload: null, artifactInfo: null };
941
1079
  }
942
- // Check user-visible artifacts first
943
- let artifacts = this.artifactsByDetailId?.get(lastAgentMessage.ID);
944
- // If not found, check system artifacts (Agent Manager, etc.)
945
- if (!artifacts || artifacts.length === 0) {
946
- artifacts = this.systemArtifactsByDetailId?.get(lastAgentMessage.ID);
947
- }
948
- // Load artifact content as payload
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
- catch (error) {
966
- console.error('Error loading previous payload:', error);
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
- // Update user message status to In-Progress
1295
- userMessage.Status = 'In-Progress';
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
- // Find the last AI message from this agent (needed for both payload and configuration)
1445
- const lastAIMessage = this.conversationHistory
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
- .find(msg => msg.Role === 'AI' && msg.AgentID === agentId);
1449
- // Extract configuration from previous agent run (for configuration continuity)
1450
- if (lastAIMessage && this.agentRunsByDetailId) {
1451
- const previousAgentRun = this.agentRunsByDetailId.get(lastAIMessage.ID);
1452
- if (previousAgentRun?.ConfigurationID) {
1453
- previousConfigurationId = previousAgentRun.ConfigurationID;
1454
- console.log(`🎯 Using configuration from previous agent run: ${previousConfigurationId}`);
1455
- }
1456
- else {
1457
- console.log('📝 No configuration found on previous agent run, will use agent default');
1458
- }
1459
- }
1460
- // Fall back to most recent artifact if no target specified or target not found
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
- catch (error) {
1484
- console.warn('⚠️ Could not parse artifact content:', error);
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
- // Update user message status to In-Progress
1501
- userMessage.Status = 'In-Progress';
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, previousConfigurationId // Pass configuration from previous agent run for continuity
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: message }],
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", initialMessage: "initialMessage", artifactsByDetailId: "artifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", conversationHistory: "conversationHistory", inProgressMessageIds: "inProgressMessageIds" }, outputs: { messageSent: "messageSent", agentResponse: "agentResponse", agentRunDetected: "agentRunDetected", agentRunUpdate: "agentRunUpdate", messageComplete: "messageComplete", artifactCreated: "artifactCreated", conversationRenamed: "conversationRenamed", intentCheckStarted: "intentCheckStarted", intentCheckCompleted: "intentCheckCompleted" }, features: [i0.ɵɵNgOnChangesFeature], decls: 4, vars: 8, consts: [["inputBox", ""], [1, "message-input-wrapper"], ["class", "processing-indicator", 4, "ngIf"], [3, "valueChange", "textSubmitted", "placeholder", "disabled", "showCharacterCount", "enableMentions", "currentUser", "rows", "value"], [1, "processing-indicator"], [1, "fas", "fa-circle-notch", "fa-spin"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
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: [i10.NgIf, i11.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}"] });
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
- }], initialMessage: [{
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: 27 }); })();
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