@memberjunction/ng-conversations 5.47.0 → 5.48.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 (31) hide show
  1. package/dist/lib/components/composer/ai-composer.component.d.ts +8 -2
  2. package/dist/lib/components/composer/ai-composer.component.d.ts.map +1 -1
  3. package/dist/lib/components/composer/ai-composer.component.js +16 -3
  4. package/dist/lib/components/composer/ai-composer.component.js.map +1 -1
  5. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +45 -1
  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 +289 -151
  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 +14 -1
  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 +30 -4
  12. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  13. package/dist/lib/components/message/message-input.component.d.ts +46 -1
  14. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  15. package/dist/lib/components/message/message-input.component.js +140 -6
  16. package/dist/lib/components/message/message-input.component.js.map +1 -1
  17. package/dist/lib/services/composer-draft-store.d.ts +52 -0
  18. package/dist/lib/services/composer-draft-store.d.ts.map +1 -0
  19. package/dist/lib/services/composer-draft-store.js +123 -0
  20. package/dist/lib/services/composer-draft-store.js.map +1 -0
  21. package/dist/lib/services/mention-autocomplete.service.d.ts.map +1 -1
  22. package/dist/lib/services/mention-autocomplete.service.js +5 -1
  23. package/dist/lib/services/mention-autocomplete.service.js.map +1 -1
  24. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  25. package/dist/lib/services/realtime-session.service.js +2 -1
  26. package/dist/lib/services/realtime-session.service.js.map +1 -1
  27. package/dist/public-api.d.ts +1 -0
  28. package/dist/public-api.d.ts.map +1 -1
  29. package/dist/public-api.js +1 -0
  30. package/dist/public-api.js.map +1 -1
  31. package/package.json +29 -29
@@ -252,6 +252,125 @@ export class MessageInputComponent extends BaseAngularComponent {
252
252
  uploadStateChanged = new EventEmitter(); // Emits when attachment upload state changes
253
253
  inputBox;
254
254
  messageText = '';
255
+ /**
256
+ * Prefills the composer with draft text WITHOUT sending (unlike pendingMessage,
257
+ * which auto-sends) and focuses the input — e.g. the omnibar's '@agent' flow
258
+ * lands in chat with '@AgentName ' staged so the user just types their ask.
259
+ */
260
+ /**
261
+ * Draft text to stage in the composer when this input mounts (NOT sent — unlike
262
+ * pendingMessage). Applied once per distinct value, view-readiness-proof: if the
263
+ * view isn't up yet, ngAfterViewInit applies it. Emits initialDraftApplied so the
264
+ * host can clear its pending state.
265
+ */
266
+ set initialDraft(value) {
267
+ if (value && value !== this.appliedInitialDraft) {
268
+ this.appliedInitialDraft = value;
269
+ if (this.inputBox) {
270
+ this.SetDraft(value, true);
271
+ this.initialDraftApplied.emit();
272
+ }
273
+ else {
274
+ this.pendingInitialDraft = value;
275
+ }
276
+ }
277
+ }
278
+ get initialDraft() {
279
+ return this.appliedInitialDraft;
280
+ }
281
+ appliedInitialDraft = null;
282
+ pendingInitialDraft = null;
283
+ initialDraftApplied = new EventEmitter();
284
+ /**
285
+ * Live draft-state signal: fires on every composer value change with the
286
+ * SERIALIZED content (mention pills encoded via getPlainTextWithJsonMentions,
287
+ * so hosts can persist drafts losslessly). Empty string = draft cleared.
288
+ */
289
+ DraftStateChanged = new EventEmitter();
290
+ /** The composer lost focus — hosts flush persisted drafts on this. */
291
+ ComposerBlurred = new EventEmitter();
292
+ /** Handles the composer's value stream: keeps messageText in sync + emits draft state. */
293
+ OnComposerValueChanged(value) {
294
+ this.messageText = value;
295
+ this.DraftStateChanged.emit(this.GetSerializedDraft());
296
+ }
297
+ /** Current composer content in the lossless serialized form ('' when empty). */
298
+ GetSerializedDraft() {
299
+ const serialized = this.inputBox?.getPlainTextWithJsonMentions() ?? this.messageText ?? '';
300
+ return serialized.trim().length === 0 ? '' : serialized;
301
+ }
302
+ /**
303
+ * Pre-addresses the composer to an agent as a RESOLVED mention pill (+ trailing
304
+ * space, caret after, focused) — identical to the user typing '@agent' and picking
305
+ * it from the dropdown. Resolves the agent through MentionAutocompleteService so
306
+ * the chip carries the agent's real id/icon/presets; falls back to a plain-text
307
+ * '@Name ' draft when the agent can't be resolved (e.g. name mismatch).
308
+ *
309
+ * @returns false while the composer view isn't mounted yet — callers may retry.
310
+ */
311
+ async InsertAgentMention(agentName, focus = true, clearExisting = true) {
312
+ if (!this.inputBox) {
313
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): input box not mounted yet — caller will retry`);
314
+ return false;
315
+ }
316
+ if (clearExisting) {
317
+ // Pre-addressing REPLACES any un-sent draft (tagging agent B after agent A
318
+ // must not stack pills).
319
+ this.inputBox.mentionEditor?.clear();
320
+ this.messageText = '';
321
+ }
322
+ try {
323
+ if (!this.mentionAutocomplete.IsInitialized && this.currentUser) {
324
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): initializing mention autocomplete…`);
325
+ await this.mentionAutocomplete.initialize(this.currentUser);
326
+ }
327
+ const wanted = agentName.trim().toLowerCase();
328
+ const suggestion = this.mentionAutocomplete
329
+ .getSuggestions(agentName, false, '@')
330
+ .find(s => s.type === 'agent' && s.name.trim().toLowerCase() === wanted);
331
+ if (suggestion) {
332
+ const inserted = this.inputBox.InsertMention(suggestion, focus);
333
+ console.log(`[Omnibar→Chat] InsertAgentMention('${agentName}'): resolved to pill (id=${suggestion.id}) — insert ${inserted ? 'OK' : 'FAILED (editor view not ready)'}`);
334
+ if (inserted) {
335
+ if (focus) {
336
+ this.scheduleFocusReassert(agentName);
337
+ }
338
+ return true;
339
+ }
340
+ return false; // editor view not mounted — caller retries
341
+ }
342
+ console.warn(`[Omnibar→Chat] InsertAgentMention('${agentName}'): agent NOT found in autocomplete (initialized=${this.mentionAutocomplete.IsInitialized}) — falling back to plain text`);
343
+ }
344
+ catch (e) {
345
+ console.warn(`[Omnibar→Chat] InsertAgentMention('${agentName}'): resolution error — falling back to plain text`, e);
346
+ }
347
+ const mention = agentName.includes(' ') ? `@"${agentName}" ` : `@${agentName} `;
348
+ this.SetDraft(mention, focus);
349
+ return true;
350
+ }
351
+ /**
352
+ * The insert happens mid-tab-mount; late-arriving chat UI (lists, empty-state
353
+ * autofocus, tab chrome) can steal focus AFTER we set it. Re-assert at settle
354
+ * points — only when focus genuinely left the editor, so we never fight the user.
355
+ */
356
+ scheduleFocusReassert(context) {
357
+ for (const delay of [300, 900, 1800]) {
358
+ setTimeout(() => {
359
+ const editor = this.inputBox?.mentionEditor;
360
+ if (editor && !editor.HasFocus) {
361
+ const ok = editor.FocusCaretAtEnd();
362
+ console.log(`[Omnibar→Chat] focus re-assert (+${delay}ms) for '${context}': ${ok ? 'refocused' : 'editor gone'}`);
363
+ }
364
+ }, delay);
365
+ }
366
+ }
367
+ SetDraft(text, focus = true) {
368
+ this.messageText = text;
369
+ if (focus) {
370
+ // The composer mounts/binds on the next tick after messageText flows down.
371
+ setTimeout(() => this.inputBox?.focus(), 50);
372
+ }
373
+ }
255
374
  isSending = false;
256
375
  isProcessing = false; // True when waiting for agent/naming response
257
376
  processingMessage = 'AI is responding...'; // Message shown during processing
@@ -313,6 +432,15 @@ export class MessageInputComponent extends BaseAngularComponent {
313
432
  // Note: initialMessage/initialAttachments handled by setters, inProgressMessageIds handled by setter
314
433
  }
315
434
  ngAfterViewInit() {
435
+ if (this.pendingInitialDraft) {
436
+ const draft = this.pendingInitialDraft;
437
+ this.pendingInitialDraft = null;
438
+ // next tick — the composer's own view finishes mounting first
439
+ setTimeout(() => {
440
+ this.SetDraft(draft, true);
441
+ this.initialDraftApplied.emit();
442
+ }, 50);
443
+ }
316
444
  // Focus input on initial load
317
445
  this.focusInput();
318
446
  // Mark component as ready
@@ -2362,13 +2490,12 @@ export class MessageInputComponent extends BaseAngularComponent {
2362
2490
  } if (rf & 2) {
2363
2491
  let _t;
2364
2492
  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) {
2493
+ } }, 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", 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
2494
  const _r1 = i0.ɵɵgetCurrentView();
2367
2495
  i0.ɵɵelementStart(0, "div", 2, 0);
2368
2496
  i0.ɵɵconditionalCreate(2, MessageInputComponent_Conditional_2_Template, 4, 1, "div", 3);
2369
2497
  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()); });
2498
+ 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
2499
  i0.ɵɵelementEnd();
2373
2500
  i0.ɵɵtemplate(5, MessageInputComponent_ng_template_5_Template, 1, 5, "ng-template", 5);
2374
2501
  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 +2505,14 @@ export class MessageInputComponent extends BaseAngularComponent {
2378
2505
  i0.ɵɵadvance(2);
2379
2506
  i0.ɵɵconditional(ctx.isProcessing ? 2 : -1);
2380
2507
  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);
2508
+ 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)("value", ctx.messageText);
2383
2509
  i0.ɵɵadvance(2);
2384
2510
  i0.ɵɵproperty("cdkConnectedOverlayOrigin", pickerOrigin_r4)("cdkConnectedOverlayOpen", ctx.showRealtimeAgentPicker)("cdkConnectedOverlayPositions", ctx.pickerOverlayPositions)("cdkConnectedOverlayPush", true)("cdkConnectedOverlayHasBackdrop", true);
2385
2511
  } }, 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
2512
  }
2387
2513
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MessageInputComponent, [{
2388
2514
  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"] }]
2515
+ 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 (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
2516
  }], () => [{ 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
2517
  type: Input
2392
2518
  }], conversationName: [{
@@ -2468,6 +2594,14 @@ export class MessageInputComponent extends BaseAngularComponent {
2468
2594
  }], inputBox: [{
2469
2595
  type: ViewChild,
2470
2596
  args: ['inputBox']
2597
+ }], initialDraft: [{
2598
+ type: Input
2599
+ }], initialDraftApplied: [{
2600
+ type: Output
2601
+ }], DraftStateChanged: [{
2602
+ type: Output
2603
+ }], ComposerBlurred: [{
2604
+ type: Output
2471
2605
  }] }); })();
2472
2606
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MessageInputComponent, { className: "MessageInputComponent", filePath: "src/lib/components/message/message-input.component.ts", lineNumber: 45 }); })();
2473
2607
  //# sourceMappingURL=message-input.component.js.map