@memberjunction/ng-conversations 5.47.0 → 5.49.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 (44) hide show
  1. package/README.md +37 -0
  2. package/dist/lib/components/composer/ai-composer.component.d.ts +8 -2
  3. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  4. package/dist/lib/components/composer/ai-composer.component.js +16 -3
  5. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  6. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +90 -1
  7. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  8. package/dist/lib/components/conversation/conversation-chat-area.component.js +322 -99
  9. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  10. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +16 -1
  11. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  12. package/dist/lib/components/conversation/conversation-empty-state.component.js +62 -24
  13. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  14. package/dist/lib/components/message/message-input.component.d.ts +48 -1
  15. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  16. package/dist/lib/components/message/message-input.component.js +146 -6
  17. package/dist/lib/components/message/message-input.component.js.map +1 -1
  18. package/dist/lib/components/message/message-item.component.d.ts +13 -1
  19. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  20. package/dist/lib/components/message/message-item.component.js +307 -235
  21. package/dist/lib/components/message/message-item.component.js.map +1 -1
  22. package/dist/lib/components/message/message-list.component.d.ts +18 -1
  23. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  24. package/dist/lib/components/message/message-list.component.js +48 -4
  25. package/dist/lib/components/message/message-list.component.js.map +1 -1
  26. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js +2 -2
  27. package/dist/lib/components/realtime/evidence-playback/realtime-evidence-playback.component.js.map +1 -1
  28. package/dist/lib/components/realtime/media/realtime-media-surface.component.js +2 -2
  29. package/dist/lib/components/realtime/media/realtime-media-surface.component.js.map +1 -1
  30. package/dist/lib/services/composer-draft-store.d.ts +52 -0
  31. package/dist/lib/services/composer-draft-store.d.ts.map +1 -0
  32. package/dist/lib/services/composer-draft-store.js +123 -0
  33. package/dist/lib/services/composer-draft-store.js.map +1 -0
  34. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  35. package/dist/lib/services/mention-autocomplete.service.js +5 -1
  36. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  37. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  38. package/dist/lib/services/realtime-session.service.js +2 -1
  39. package/dist/lib/services/realtime-session.service.js.map +1 -1
  40. package/dist/public-api.d.ts +1 -0
  41. package/dist/public-api.d.ts.map +1 -1
  42. package/dist/public-api.js +1 -0
  43. package/dist/public-api.js.map +1 -1
  44. package/package.json +29 -29
@@ -67,6 +67,8 @@ export class MessageInputComponent extends BaseAngularComponent {
67
67
  parentMessageId; // Optional: for replying in threads
68
68
  enableAttachments = true; // Whether to show attachment button (based on agent modality support)
69
69
  enableMentions = true; // Whether to enable @-mention autocomplete (agents/users). Hosts addressing a single fixed agent (e.g. Form Builder cockpit) typically set false.
70
+ enablePlanMode = true; // Whether the composer shows the Plan Mode toggle. Hosts that don't expose plan-mode workflows set false.
71
+ enableRealtime = true; // Whether the composer shows the realtime voice-call launcher/options. Hosts without a voice experience set false.
70
72
  maxAttachments = 10; // Maximum number of attachments per message
71
73
  maxAttachmentSizeBytes = 20 * 1024 * 1024; // Maximum size per attachment (20MB default)
72
74
  acceptedFileTypes = 'image/*'; // Accepted MIME types pattern
@@ -252,6 +254,125 @@ export class MessageInputComponent extends BaseAngularComponent {
252
254
  uploadStateChanged = new EventEmitter(); // Emits when attachment upload state changes
253
255
  inputBox;
254
256
  messageText = '';
257
+ /**
258
+ * Prefills the composer with draft text WITHOUT sending (unlike pendingMessage,
259
+ * which auto-sends) and focuses the input — e.g. the omnibar's '@agent' flow
260
+ * lands in chat with '@AgentName ' staged so the user just types their ask.
261
+ */
262
+ /**
263
+ * Draft text to stage in the composer when this input mounts (NOT sent — unlike
264
+ * pendingMessage). Applied once per distinct value, view-readiness-proof: if the
265
+ * view isn't up yet, ngAfterViewInit applies it. Emits initialDraftApplied so the
266
+ * host can clear its pending state.
267
+ */
268
+ set initialDraft(value) {
269
+ if (value && value !== this.appliedInitialDraft) {
270
+ this.appliedInitialDraft = value;
271
+ if (this.inputBox) {
272
+ this.SetDraft(value, true);
273
+ this.initialDraftApplied.emit();
274
+ }
275
+ else {
276
+ this.pendingInitialDraft = value;
277
+ }
278
+ }
279
+ }
280
+ get initialDraft() {
281
+ return this.appliedInitialDraft;
282
+ }
283
+ appliedInitialDraft = null;
284
+ pendingInitialDraft = null;
285
+ initialDraftApplied = new EventEmitter();
286
+ /**
287
+ * Live draft-state signal: fires on every composer value change with the
288
+ * SERIALIZED content (mention pills encoded via getPlainTextWithJsonMentions,
289
+ * so hosts can persist drafts losslessly). Empty string = draft cleared.
290
+ */
291
+ DraftStateChanged = new EventEmitter();
292
+ /** The composer lost focus — hosts flush persisted drafts on this. */
293
+ ComposerBlurred = new EventEmitter();
294
+ /** Handles the composer's value stream: keeps messageText in sync + emits draft state. */
295
+ OnComposerValueChanged(value) {
296
+ this.messageText = value;
297
+ this.DraftStateChanged.emit(this.GetSerializedDraft());
298
+ }
299
+ /** Current composer content in the lossless serialized form ('' when empty). */
300
+ GetSerializedDraft() {
301
+ const serialized = this.inputBox?.getPlainTextWithJsonMentions() ?? this.messageText ?? '';
302
+ return serialized.trim().length === 0 ? '' : serialized;
303
+ }
304
+ /**
305
+ * Pre-addresses the composer to an agent as a RESOLVED mention pill (+ trailing
306
+ * space, caret after, focused) — identical to the user typing '@agent' and picking
307
+ * it from the dropdown. Resolves the agent through MentionAutocompleteService so
308
+ * the chip carries the agent's real id/icon/presets; falls back to a plain-text
309
+ * '@Name ' draft when the agent can't be resolved (e.g. name mismatch).
310
+ *
311
+ * @returns false while the composer view isn't mounted yet — callers may retry.
312
+ */
313
+ async InsertAgentMention(agentName, focus = true, clearExisting = true) {
314
+ if (!this.inputBox) {
315
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): input box not mounted yet — caller will retry`);
316
+ return false;
317
+ }
318
+ if (clearExisting) {
319
+ // Pre-addressing REPLACES any un-sent draft (tagging agent B after agent A
320
+ // must not stack pills).
321
+ this.inputBox.mentionEditor?.clear();
322
+ this.messageText = '';
323
+ }
324
+ try {
325
+ if (!this.mentionAutocomplete.IsInitialized && this.currentUser) {
326
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): initializing mention autocomplete…`);
327
+ await this.mentionAutocomplete.initialize(this.currentUser);
328
+ }
329
+ const wanted = agentName.trim().toLowerCase();
330
+ const suggestion = this.mentionAutocomplete
331
+ .getSuggestions(agentName, false, '@')
332
+ .find(s => s.type === 'agent' && s.name.trim().toLowerCase() === wanted);
333
+ if (suggestion) {
334
+ const inserted = this.inputBox.InsertMention(suggestion, focus);
335
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): resolved to pill (id=${suggestion.id}) — insert ${inserted ? 'OK' : 'FAILED (editor view not ready)'}`);
336
+ if (inserted) {
337
+ if (focus) {
338
+ this.scheduleFocusReassert(agentName);
339
+ }
340
+ return true;
341
+ }
342
+ return false; // editor view not mounted — caller retries
343
+ }
344
+ console.warn(`[Omnibar→Chat] InsertAgentMention('${agentName}'): agent NOT found in autocomplete (initialized=${this.mentionAutocomplete.IsInitialized}) — falling back to plain text`);
345
+ }
346
+ catch (e) {
347
+ console.warn(`[Omnibar→Chat] InsertAgentMention('${agentName}'): resolution error — falling back to plain text`, e);
348
+ }
349
+ const mention = agentName.includes(' ') ? `@"${agentName}" ` : `@${agentName} `;
350
+ this.SetDraft(mention, focus);
351
+ return true;
352
+ }
353
+ /**
354
+ * The insert happens mid-tab-mount; late-arriving chat UI (lists, empty-state
355
+ * autofocus, tab chrome) can steal focus AFTER we set it. Re-assert at settle
356
+ * points — only when focus genuinely left the editor, so we never fight the user.
357
+ */
358
+ scheduleFocusReassert(context) {
359
+ for (const delay of [300, 900, 1800]) {
360
+ setTimeout(() => {
361
+ const editor = this.inputBox?.mentionEditor;
362
+ if (editor && !editor.HasFocus) {
363
+ const ok = editor.FocusCaretAtEnd();
364
+ console.log(`[Omnibar→Chat] focus re-assert (+${delay}ms) for '${context}': ${ok ? 'refocused' : 'editor gone'}`);
365
+ }
366
+ }, delay);
367
+ }
368
+ }
369
+ SetDraft(text, focus = true) {
370
+ this.messageText = text;
371
+ if (focus) {
372
+ // The composer mounts/binds on the next tick after messageText flows down.
373
+ setTimeout(() => this.inputBox?.focus(), 50);
374
+ }
375
+ }
255
376
  isSending = false;
256
377
  isProcessing = false; // True when waiting for agent/naming response
257
378
  processingMessage = 'AI is responding...'; // Message shown during processing
@@ -313,6 +434,15 @@ export class MessageInputComponent extends BaseAngularComponent {
313
434
  // Note: initialMessage/initialAttachments handled by setters, inProgressMessageIds handled by setter
314
435
  }
315
436
  ngAfterViewInit() {
437
+ if (this.pendingInitialDraft) {
438
+ const draft = this.pendingInitialDraft;
439
+ this.pendingInitialDraft = null;
440
+ // next tick — the composer's own view finishes mounting first
441
+ setTimeout(() => {
442
+ this.SetDraft(draft, true);
443
+ this.initialDraftApplied.emit();
444
+ }, 50);
445
+ }
316
446
  // Focus input on initial load
317
447
  this.focusInput();
318
448
  // Mark component as ready
@@ -2362,13 +2492,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2362
2492
  } if (rf & 2) {
2363
2493
  let _t;
2364
2494
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.inputBox = _t.first);
2365
- } }, inputs: { conversationId: "conversationId", conversationName: "conversationName", currentUser: "currentUser", disabled: "disabled", placeholder: "placeholder", parentMessageId: "parentMessageId", enableAttachments: "enableAttachments", enableMentions: "enableMentions", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", artifactsByDetailId: "artifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", emptyStateMode: "emptyStateMode", appContext: "appContext", defaultAgentId: "defaultAgentId", conversationDefaultAgentId: "conversationDefaultAgentId", agentConfigurationPresetId: "agentConfigurationPresetId", initialMessage: "initialMessage", initialAttachments: "initialAttachments", conversationHistory: "conversationHistory", inProgressMessageIds: "inProgressMessageIds", applicationId: "applicationId" }, outputs: { messageSent: "messageSent", agentResponse: "agentResponse", beforeAgentTurn: "beforeAgentTurn", afterAgentTurn: "afterAgentTurn", agentRunDetected: "agentRunDetected", agentRunUpdate: "agentRunUpdate", messageComplete: "messageComplete", artifactCreated: "artifactCreated", conversationRenamed: "conversationRenamed", intentCheckStarted: "intentCheckStarted", intentCheckCompleted: "intentCheckCompleted", initialMessageAutoSendStarted: "initialMessageAutoSendStarted", initialMessageAutoSendFailed: "initialMessageAutoSendFailed", emptyStateSubmit: "emptyStateSubmit", uploadStateChanged: "uploadStateChanged" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 23, consts: [["pickerOrigin", "cdkOverlayOrigin"], ["inputBox", ""], ["cdkOverlayOrigin", "", 1, "message-input-wrapper"], [1, "processing-indicator"], [3, "valueChange", "textSubmitted", "attachmentsChanged", "attachmentError", "voiceRequested", "voiceOptionsRequested", "planModeToggle", "placeholder", "disabled", "showCharacterCount", "enableMentions", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "currentUser", "Provider", "rows", "enableRealtime", "voiceActive", "canStartRealtime", "enablePlanMode", "planModeActive", "value"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPush", "cdkConnectedOverlayHasBackdrop"], [1, "fas", "fa-circle-notch", "fa-spin"], [3, "AgentPicked", "Cancelled", "Provider", "Agents", "DefaultAgentId", "CoAgents", "DefaultCoAgentId"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
2495
+ } }, inputs: { conversationId: "conversationId", conversationName: "conversationName", currentUser: "currentUser", disabled: "disabled", placeholder: "placeholder", parentMessageId: "parentMessageId", enableAttachments: "enableAttachments", enableMentions: "enableMentions", enablePlanMode: "enablePlanMode", enableRealtime: "enableRealtime", maxAttachments: "maxAttachments", maxAttachmentSizeBytes: "maxAttachmentSizeBytes", acceptedFileTypes: "acceptedFileTypes", artifactsByDetailId: "artifactsByDetailId", systemArtifactsByDetailId: "systemArtifactsByDetailId", agentRunsByDetailId: "agentRunsByDetailId", emptyStateMode: "emptyStateMode", appContext: "appContext", defaultAgentId: "defaultAgentId", conversationDefaultAgentId: "conversationDefaultAgentId", agentConfigurationPresetId: "agentConfigurationPresetId", initialMessage: "initialMessage", initialAttachments: "initialAttachments", conversationHistory: "conversationHistory", inProgressMessageIds: "inProgressMessageIds", applicationId: "applicationId", initialDraft: "initialDraft" }, outputs: { messageSent: "messageSent", agentResponse: "agentResponse", beforeAgentTurn: "beforeAgentTurn", afterAgentTurn: "afterAgentTurn", agentRunDetected: "agentRunDetected", agentRunUpdate: "agentRunUpdate", messageComplete: "messageComplete", artifactCreated: "artifactCreated", conversationRenamed: "conversationRenamed", intentCheckStarted: "intentCheckStarted", intentCheckCompleted: "intentCheckCompleted", initialMessageAutoSendStarted: "initialMessageAutoSendStarted", initialMessageAutoSendFailed: "initialMessageAutoSendFailed", emptyStateSubmit: "emptyStateSubmit", uploadStateChanged: "uploadStateChanged", initialDraftApplied: "initialDraftApplied", DraftStateChanged: "DraftStateChanged", ComposerBlurred: "ComposerBlurred" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], decls: 6, vars: 23, consts: [["pickerOrigin", "cdkOverlayOrigin"], ["inputBox", ""], ["cdkOverlayOrigin", "", 1, "message-input-wrapper"], [1, "processing-indicator"], [3, "valueChange", "blurred", "textSubmitted", "attachmentsChanged", "attachmentError", "voiceRequested", "voiceOptionsRequested", "planModeToggle", "placeholder", "disabled", "showCharacterCount", "enableMentions", "enableAttachments", "maxAttachments", "maxAttachmentSizeBytes", "acceptedFileTypes", "currentUser", "Provider", "rows", "enableRealtime", "voiceActive", "canStartRealtime", "enablePlanMode", "planModeActive", "value"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "cdk-overlay-transparent-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPush", "cdkConnectedOverlayHasBackdrop"], [1, "fas", "fa-circle-notch", "fa-spin"], [3, "AgentPicked", "Cancelled", "Provider", "Agents", "DefaultAgentId", "CoAgents", "DefaultCoAgentId"]], template: function MessageInputComponent_Template(rf, ctx) { if (rf & 1) {
2366
2496
  const _r1 = i0.ɵɵgetCurrentView();
2367
2497
  i0.ɵɵelementStart(0, "div", 2, 0);
2368
2498
  i0.ɵɵconditionalCreate(2, MessageInputComponent_Conditional_2_Template, 4, 1, "div", 3);
2369
2499
  i0.ɵɵelementStart(3, "mj-ai-composer", 4, 1);
2370
- i0.ɵɵtwoWayListener("valueChange", function MessageInputComponent_Template_mj_ai_composer_valueChange_3_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.messageText, $event) || (ctx.messageText = $event); return i0.ɵɵresetView($event); });
2371
- i0.ɵɵlistener("textSubmitted", function MessageInputComponent_Template_mj_ai_composer_textSubmitted_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onTextSubmitted($event)); })("attachmentsChanged", function MessageInputComponent_Template_mj_ai_composer_attachmentsChanged_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentsChanged($event)); })("attachmentError", function MessageInputComponent_Template_mj_ai_composer_attachmentError_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentError($event)); })("voiceRequested", function MessageInputComponent_Template_mj_ai_composer_voiceRequested_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onStartRealtime()); })("voiceOptionsRequested", function MessageInputComponent_Template_mj_ai_composer_voiceOptionsRequested_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRealtimeOptions()); })("planModeToggle", function MessageInputComponent_Template_mj_ai_composer_planModeToggle_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.TogglePlanMode()); });
2500
+ i0.ɵɵlistener("valueChange", function MessageInputComponent_Template_mj_ai_composer_valueChange_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.OnComposerValueChanged($event)); })("blurred", function MessageInputComponent_Template_mj_ai_composer_blurred_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.ComposerBlurred.emit()); })("textSubmitted", function MessageInputComponent_Template_mj_ai_composer_textSubmitted_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onTextSubmitted($event)); })("attachmentsChanged", function MessageInputComponent_Template_mj_ai_composer_attachmentsChanged_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentsChanged($event)); })("attachmentError", function MessageInputComponent_Template_mj_ai_composer_attachmentError_3_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onAttachmentError($event)); })("voiceRequested", function MessageInputComponent_Template_mj_ai_composer_voiceRequested_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onStartRealtime()); })("voiceOptionsRequested", function MessageInputComponent_Template_mj_ai_composer_voiceOptionsRequested_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRealtimeOptions()); })("planModeToggle", function MessageInputComponent_Template_mj_ai_composer_planModeToggle_3_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.TogglePlanMode()); });
2372
2501
  i0.ɵɵelementEnd();
2373
2502
  i0.ɵɵtemplate(5, MessageInputComponent_ng_template_5_Template, 1, 5, "ng-template", 5);
2374
2503
  i0.ɵɵlistener("backdropClick", function MessageInputComponent_Template_ng_template_backdropClick_5_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRealtimeAgentPickerCancelled()); })("detach", function MessageInputComponent_Template_ng_template_detach_5_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onRealtimeAgentPickerCancelled()); });
@@ -2378,15 +2507,14 @@ export class MessageInputComponent extends BaseAngularComponent {
2378
2507
  i0.ɵɵadvance(2);
2379
2508
  i0.ɵɵconditional(ctx.isProcessing ? 2 : -1);
2380
2509
  i0.ɵɵadvance();
2381
- i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", ctx.enableMentions)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes)("currentUser", ctx.currentUser)("Provider", ctx.Provider)("rows", 3)("enableRealtime", true)("voiceActive", ctx.voiceActive)("canStartRealtime", ctx.canStartRealtime)("enablePlanMode", true)("planModeActive", ctx.PlanModeEnabled);
2382
- i0.ɵɵtwoWayProperty("value", ctx.messageText);
2510
+ i0.ɵɵproperty("placeholder", ctx.placeholder)("disabled", ctx.disabled || ctx.isProcessing)("showCharacterCount", false)("enableMentions", ctx.enableMentions)("enableAttachments", ctx.enableAttachments)("maxAttachments", ctx.maxAttachments)("maxAttachmentSizeBytes", ctx.maxAttachmentSizeBytes)("acceptedFileTypes", ctx.acceptedFileTypes)("currentUser", ctx.currentUser)("Provider", ctx.Provider)("rows", 3)("enableRealtime", ctx.enableRealtime)("voiceActive", ctx.voiceActive)("canStartRealtime", ctx.canStartRealtime)("enablePlanMode", ctx.enablePlanMode)("planModeActive", ctx.PlanModeEnabled)("value", ctx.messageText);
2383
2511
  i0.ɵɵadvance(2);
2384
2512
  i0.ɵɵproperty("cdkConnectedOverlayOrigin", pickerOrigin_r4)("cdkConnectedOverlayOpen", ctx.showRealtimeAgentPicker)("cdkConnectedOverlayPositions", ctx.pickerOverlayPositions)("cdkConnectedOverlayPush", true)("cdkConnectedOverlayHasBackdrop", true);
2385
2513
  } }, dependencies: [i11.CdkConnectedOverlay, i11.CdkOverlayOrigin, i12.RealtimeAgentPickerComponent, i13.AiComposerComponent], styles: [".message-input-wrapper[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n}\n\n\n\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: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n}\n.processing-indicator[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}"] });
2386
2514
  }
2387
2515
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputComponent, [{
2388
2516
  type: Component,
2389
- args: [{ standalone: false, selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\" cdkOverlayOrigin #pickerOrigin=\"cdkOverlayOrigin\">\n <!-- Processing Indicator Overlay -->\n @if (isProcessing) {\n <div class=\"processing-indicator\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n }\n\n <!-- AI composer (mic + Plan Mode buttons live in its in-composer toolbar): wraps the\n generic mj-message-input-box with the '@' agent / '#' record / '/' skill trigger\n plugins built in \u2014 all three on by default, preserving the standard chat behavior. -->\n <mj-ai-composer\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [currentUser]=\"currentUser\"\n [Provider]=\"Provider\"\n [rows]=\"3\"\n [enableRealtime]=\"true\"\n [voiceActive]=\"voiceActive\"\n [canStartRealtime]=\"canStartRealtime\"\n [enablePlanMode]=\"true\"\n [planModeActive]=\"PlanModeEnabled\"\n [(value)]=\"messageText\"\n (textSubmitted)=\"onTextSubmitted($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (voiceRequested)=\"onStartRealtime()\"\n (voiceOptionsRequested)=\"onRealtimeOptions()\"\n (planModeToggle)=\"TogglePlanMode()\">\n </mj-ai-composer>\n\n <!-- Voice agent/co-agent/model picker \u2014 shown when starting a call on a conversation\n with NO prior agent participation, or on demand via the caret next to the phone\n button (any conversation). Rendered in a body-level CDK overlay anchored above the\n composer so it POPS OUT of the chat overlay's clipping border instead of being cut\n off at the top of a narrow (~390px) overlay. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"pickerOrigin\"\n [cdkConnectedOverlayOpen]=\"showRealtimeAgentPicker\"\n [cdkConnectedOverlayPositions]=\"pickerOverlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onRealtimeAgentPickerCancelled()\"\n (detach)=\"onRealtimeAgentPickerCancelled()\">\n <mj-realtime-agent-picker\n [Provider]=\"Provider\"\n [Agents]=\"voicePickerAgents\"\n [DefaultAgentId]=\"voicePickerDefaultAgentId\"\n [CoAgents]=\"voicePickerCoAgents\"\n [DefaultCoAgentId]=\"voicePickerDefaultCoAgentId\"\n (AgentPicked)=\"onRealtimeAgentPicked($event)\"\n (Cancelled)=\"onRealtimeAgentPickerCancelled()\">\n </mj-realtime-agent-picker>\n </ng-template>\n</div>\n\n<!-- The voice \"call mode\" overlay is hosted by <mj-conversation-chat-area> (it fills the\n whole conversation panel in place); this component only owns the trigger wiring. -->\n", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n/* Plan Mode moved into the in-composer toolbar (message-input-box) as a toggle icon button\n next to the attachment/voice buttons \u2014 see .plan-mode-button-icon there. */\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: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--mj-brand-primary);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n"] }]
2517
+ args: [{ standalone: false, selector: 'mj-message-input', template: "<div class=\"message-input-wrapper\" cdkOverlayOrigin #pickerOrigin=\"cdkOverlayOrigin\">\n <!-- Processing Indicator Overlay -->\n @if (isProcessing) {\n <div class=\"processing-indicator\">\n <i class=\"fas fa-circle-notch fa-spin\"></i>\n <span>{{ processingMessage }}</span>\n </div>\n }\n\n <!-- AI composer (mic + Plan Mode buttons live in its in-composer toolbar): wraps the\n generic mj-message-input-box with the '@' agent / '#' record / '/' skill trigger\n plugins built in \u2014 all three on by default, preserving the standard chat behavior. -->\n <mj-ai-composer\n #inputBox\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled || isProcessing\"\n [showCharacterCount]=\"false\"\n [enableMentions]=\"enableMentions\"\n [enableAttachments]=\"enableAttachments\"\n [maxAttachments]=\"maxAttachments\"\n [maxAttachmentSizeBytes]=\"maxAttachmentSizeBytes\"\n [acceptedFileTypes]=\"acceptedFileTypes\"\n [currentUser]=\"currentUser\"\n [Provider]=\"Provider\"\n [rows]=\"3\"\n [enableRealtime]=\"enableRealtime\"\n [voiceActive]=\"voiceActive\"\n [canStartRealtime]=\"canStartRealtime\"\n [enablePlanMode]=\"enablePlanMode\"\n [planModeActive]=\"PlanModeEnabled\"\n [value]=\"messageText\"\n (valueChange)=\"OnComposerValueChanged($event)\"\n (blurred)=\"ComposerBlurred.emit()\"\n (textSubmitted)=\"onTextSubmitted($event)\"\n (attachmentsChanged)=\"onAttachmentsChanged($event)\"\n (attachmentError)=\"onAttachmentError($event)\"\n (voiceRequested)=\"onStartRealtime()\"\n (voiceOptionsRequested)=\"onRealtimeOptions()\"\n (planModeToggle)=\"TogglePlanMode()\">\n </mj-ai-composer>\n\n <!-- Voice agent/co-agent/model picker \u2014 shown when starting a call on a conversation\n with NO prior agent participation, or on demand via the caret next to the phone\n button (any conversation). Rendered in a body-level CDK overlay anchored above the\n composer so it POPS OUT of the chat overlay's clipping border instead of being cut\n off at the top of a narrow (~390px) overlay. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"pickerOrigin\"\n [cdkConnectedOverlayOpen]=\"showRealtimeAgentPicker\"\n [cdkConnectedOverlayPositions]=\"pickerOverlayPositions\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n (backdropClick)=\"onRealtimeAgentPickerCancelled()\"\n (detach)=\"onRealtimeAgentPickerCancelled()\">\n <mj-realtime-agent-picker\n [Provider]=\"Provider\"\n [Agents]=\"voicePickerAgents\"\n [DefaultAgentId]=\"voicePickerDefaultAgentId\"\n [CoAgents]=\"voicePickerCoAgents\"\n [DefaultCoAgentId]=\"voicePickerDefaultCoAgentId\"\n (AgentPicked)=\"onRealtimeAgentPicked($event)\"\n (Cancelled)=\"onRealtimeAgentPickerCancelled()\">\n </mj-realtime-agent-picker>\n </ng-template>\n</div>\n\n<!-- The voice \"call mode\" overlay is hosted by <mj-conversation-chat-area> (it fills the\n whole conversation panel in place); this component only owns the trigger wiring. -->\n", styles: [".message-input-wrapper {\n position: relative;\n width: 100%;\n}\n\n/* Plan Mode moved into the in-composer toolbar (message-input-box) as a toggle icon button\n next to the attachment/voice buttons \u2014 see .plan-mode-button-icon there. */\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: color-mix(in srgb, var(--mj-bg-surface-card) 95%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n z-index: 10;\n pointer-events: none;\n}\n.processing-indicator i {\n color: var(--mj-brand-primary);\n}\n.processing-indicator span {\n font-size: 0.9rem;\n color: var(--mj-text-primary);\n}\n"] }]
2390
2518
  }], () => [{ type: i1.DialogService }, { type: i2.ToastService }, { type: i3.ConversationAgentService }, { type: i4.DataCacheService }, { type: i5.ActiveTasksService }, { type: i6.ConversationStreamingService }, { type: i7.MentionParserService }, { type: i8.ConversationAttachmentService }, { type: i9.ConversationBridgeService }, { type: i10.RealtimeSessionService }], { conversationId: [{
2391
2519
  type: Input
2392
2520
  }], conversationName: [{
@@ -2403,6 +2531,10 @@ export class MessageInputComponent extends BaseAngularComponent {
2403
2531
  type: Input
2404
2532
  }], enableMentions: [{
2405
2533
  type: Input
2534
+ }], enablePlanMode: [{
2535
+ type: Input
2536
+ }], enableRealtime: [{
2537
+ type: Input
2406
2538
  }], maxAttachments: [{
2407
2539
  type: Input
2408
2540
  }], maxAttachmentSizeBytes: [{
@@ -2468,6 +2600,14 @@ export class MessageInputComponent extends BaseAngularComponent {
2468
2600
  }], inputBox: [{
2469
2601
  type: ViewChild,
2470
2602
  args: ['inputBox']
2603
+ }], initialDraft: [{
2604
+ type: Input
2605
+ }], initialDraftApplied: [{
2606
+ type: Output
2607
+ }], DraftStateChanged: [{
2608
+ type: Output
2609
+ }], ComposerBlurred: [{
2610
+ type: Output
2471
2611
  }] }); })();
2472
2612
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 45 }); })();
2473
2613
  //# sourceMappingURL=message-input.component.js.map