@memberjunction/ng-conversations 6.2.0-edge.5 → 6.2.0-edge.6

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 (71) hide show
  1. package/dist/lib/components/attachment/image-viewer.component.d.ts +3 -1
  2. package/dist/lib/components/attachment/image-viewer.component.d.ts.map +1 -1
  3. package/dist/lib/components/attachment/image-viewer.component.js +5 -1
  4. package/dist/lib/components/attachment/image-viewer.component.js.map +1 -1
  5. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +13 -6
  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 +74 -28
  8. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  9. package/dist/lib/components/message/message-input.component.d.ts +60 -20
  10. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  11. package/dist/lib/components/message/message-input.component.js +282 -381
  12. package/dist/lib/components/message/message-input.component.js.map +1 -1
  13. package/dist/lib/components/message/message-item.component.d.ts +16 -1
  14. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  15. package/dist/lib/components/message/message-item.component.js +180 -144
  16. package/dist/lib/components/message/message-item.component.js.map +1 -1
  17. package/dist/lib/components/message/message-list.component.d.ts +5 -0
  18. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  19. package/dist/lib/components/message/message-list.component.js +53 -38
  20. package/dist/lib/components/message/message-list.component.js.map +1 -1
  21. package/dist/lib/components/overlay/chat-overlay.component.d.ts +19 -0
  22. package/dist/lib/components/overlay/chat-overlay.component.d.ts.map +1 -1
  23. package/dist/lib/components/overlay/chat-overlay.component.js +125 -13
  24. package/dist/lib/components/overlay/chat-overlay.component.js.map +1 -1
  25. package/dist/lib/components/project/project-form-modal.component.js +2 -2
  26. package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
  27. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts +6 -1
  28. package/dist/lib/components/realtime/realtime-agent-banner.component.d.ts.map +1 -1
  29. package/dist/lib/components/realtime/realtime-agent-banner.component.js +110 -82
  30. package/dist/lib/components/realtime/realtime-agent-banner.component.js.map +1 -1
  31. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts +13 -0
  32. package/dist/lib/components/realtime/realtime-call-failure-notice.d.ts.map +1 -0
  33. package/dist/lib/components/realtime/realtime-call-failure-notice.js +21 -0
  34. package/dist/lib/components/realtime/realtime-call-failure-notice.js.map +1 -0
  35. package/dist/lib/components/realtime/realtime-composer.component.js +114 -102
  36. package/dist/lib/components/realtime/realtime-composer.component.js.map +1 -1
  37. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts +21 -2
  38. package/dist/lib/components/realtime/realtime-session-overlay.component.d.ts.map +1 -1
  39. package/dist/lib/components/realtime/realtime-session-overlay.component.js +113 -76
  40. package/dist/lib/components/realtime/realtime-session-overlay.component.js.map +1 -1
  41. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  42. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +7 -1
  43. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  44. package/dist/lib/services/conversation-agent.service.d.ts +37 -12
  45. package/dist/lib/services/conversation-agent.service.d.ts.map +1 -1
  46. package/dist/lib/services/conversation-agent.service.js +51 -27
  47. package/dist/lib/services/conversation-agent.service.js.map +1 -1
  48. package/dist/lib/services/conversation-detail-window.store.d.ts +5 -0
  49. package/dist/lib/services/conversation-detail-window.store.d.ts.map +1 -1
  50. package/dist/lib/services/conversation-detail-window.store.js +52 -5
  51. package/dist/lib/services/conversation-detail-window.store.js.map +1 -1
  52. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  53. package/dist/lib/services/realtime-session.service.js +2 -1
  54. package/dist/lib/services/realtime-session.service.js.map +1 -1
  55. package/dist/lib/utils/agent-failure-display.d.ts +14 -0
  56. package/dist/lib/utils/agent-failure-display.d.ts.map +1 -0
  57. package/dist/lib/utils/agent-failure-display.js +26 -0
  58. package/dist/lib/utils/agent-failure-display.js.map +1 -0
  59. package/dist/lib/utils/message-list-order.d.ts +13 -0
  60. package/dist/lib/utils/message-list-order.d.ts.map +1 -0
  61. package/dist/lib/utils/message-list-order.js +31 -0
  62. package/dist/lib/utils/message-list-order.js.map +1 -0
  63. package/dist/lib/utils/pin-state.d.ts +11 -0
  64. package/dist/lib/utils/pin-state.d.ts.map +1 -0
  65. package/dist/lib/utils/pin-state.js +9 -0
  66. package/dist/lib/utils/pin-state.js.map +1 -0
  67. package/dist/public-api.d.ts +1 -0
  68. package/dist/public-api.d.ts.map +1 -1
  69. package/dist/public-api.js +1 -0
  70. package/dist/public-api.js.map +1 -1
  71. package/package.json +36 -36
@@ -22,6 +22,8 @@ import { RealtimeSessionReviewService } from '../../services/realtime-session-re
22
22
  import { GenerateAndApplyConversationName, GenerateAndApplyForkName, SaveForkName } from '../../services/conversation-naming';
23
23
  import { CollectRealtimeSessionIDs, MapRealtimeSessionMeta, REALTIME_SESSION_META_FIELDS } from '../../utils/realtime-session-timeline';
24
24
  import { ResolveDateJumpTarget, CombineDateJumpOutcome, DescribeDateJumpOutcome, DATE_JUMP_MAX_PAGES } from '../../utils/date-jump';
25
+ import { CompareMessagesByCreatedAt, UpsertMessageById } from '../../utils/message-list-order';
26
+ import { SavePinState } from '../../utils/pin-state';
25
27
  import { InjectFrameZone } from '../../util/frame-zone';
26
28
  import { MessageListComponent } from '../message/message-list.component';
27
29
  import { IsForkPointOrEarlier } from '../../utils/conversation-branching';
@@ -31,6 +33,7 @@ import { NormalizeUUID, UUIDsEqual, UUIDSet, IndexByUUID, IsValidUUID } from '@m
31
33
  // PR 2c — Widget extension surface
32
34
  import { ChatSlotDirective } from '../../directives/chat-slot.directive';
33
35
  import { ConversationCallStartOptions } from '../realtime/capture/realtime-capture-channel';
36
+ import { DescribeCallFailureNotice } from '../realtime/realtime-call-failure-notice';
34
37
  import { BeforeToolInvokedEventArgs, AfterToolInvokedEventArgs, BeforeStopClickedEventArgs, AfterStopClickedEventArgs, SessionStartedEventArgs, SessionChannelStateChangedEventArgs, SessionEndedEventArgs, } from '../../events/chat-events';
35
38
  import * as i0 from "@angular/core";
36
39
  import * as i1 from "../../services/agent-state.service";
@@ -2803,6 +2806,8 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
2803
2806
  this.syncSendSlot();
2804
2807
  }
2805
2808
  _inProgressMessageIds = [];
2809
+ /** Tracks the ID each in-progress reply entity was last registered under so adopting the server's row ID drops the local placeholder UUID. */
2810
+ inProgressIdByEntity;
2806
2811
  // ── The composer's send slot as the stop control ──────────────────────────────────────
2807
2812
  // While replies are in flight the composer's send slot is the stop control (one run: "Stop
2808
2813
  // {agent}"; several: "Stop all N", and each reply shows its own pill as well). The slot's mode,
@@ -3631,6 +3636,16 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
3631
3636
  namedThisSession = false;
3632
3637
  this.onRealtimeSessionStarted();
3633
3638
  });
3639
+ // A call that ends over a failure (a failed start, a dropped connection, a time limit) is ended by the
3640
+ // runtime itself, which closes the call surface with it: say why, or the call just vanishes.
3641
+ this.RealtimeSession.SessionEnded$
3642
+ .pipe(takeUntil(this.destroy$))
3643
+ .subscribe((ended) => {
3644
+ if (ended.reason === 'error') {
3645
+ const notice = DescribeCallFailureNotice(this.RealtimeSession.LastStartError, this.RealtimeSession.LastSessionError);
3646
+ MJNotificationService.Instance.CreateSimpleNotification(notice, 'error', 6000);
3647
+ }
3648
+ });
3634
3649
  let voiceWasActive = false;
3635
3650
  this.RealtimeSession.Active$
3636
3651
  .pipe(takeUntil(this.destroy$))
@@ -4112,13 +4127,27 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
4112
4127
  this.conversationLoadEnded$?.next();
4113
4128
  }
4114
4129
  }
4130
+ _cachedInputsArray = [];
4131
+ _cachedInputsKey = '';
4115
4132
  /**
4116
- * Returns array of cached message-input metadata for rendering
4133
+ * Returns array of cached message-input metadata for rendering.
4117
4134
  * This allows multiple message-input components to exist simultaneously (hidden)
4118
- * preserving their state when switching conversations
4135
+ * preserving their state when switching conversations.
4136
+ * Memoized on cache contents so template `@for` loops receive a stable array reference across CD ticks.
4119
4137
  */
4120
4138
  GetCachedInputs() {
4121
- return Array.from(this.messageInputMetadataCache.values());
4139
+ if (this.messageInputMetadataCache.size === 0) {
4140
+ return this._cachedInputsArray.length === 0 ? this._cachedInputsArray : (this._cachedInputsArray = []);
4141
+ }
4142
+ let key = '';
4143
+ for (const [id, meta] of this.messageInputMetadataCache.entries()) {
4144
+ key += `${id}:${meta.conversationName ?? ''}|`;
4145
+ }
4146
+ if (key !== this._cachedInputsKey) {
4147
+ this._cachedInputsKey = key;
4148
+ this._cachedInputsArray = Array.from(this.messageInputMetadataCache.values());
4149
+ }
4150
+ return this._cachedInputsArray;
4122
4151
  }
4123
4152
  /** @deprecated Use {@link GetCachedInputs}. */
4124
4153
  getCachedInputs() {
@@ -4655,18 +4684,11 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
4655
4684
  this.windowStore.ApplyLocalDetail(message);
4656
4685
  // Check if message already exists in the array (by ID) to prevent duplicates
4657
4686
  // Messages can be emitted multiple times as they're updated (e.g., status changes)
4658
- const existingIndex = this.messages.findIndex(m => UUIDsEqual(m.ID, message.ID));
4659
- if (existingIndex >= 0) {
4660
- // Update existing message in place (replace with updated version)
4661
- this.messages = [
4662
- ...this.messages.slice(0, existingIndex),
4663
- message,
4664
- ...this.messages.slice(existingIndex + 1)
4665
- ];
4666
- }
4667
- else {
4668
- // Add new message to the list
4669
- this.messages = [...this.messages, message];
4687
+ // An agent reply's placeholder takes the server row's ID when the run is acknowledged; a refresh may already have
4688
+ // brought that row in, so other copies of the ID are dropped.
4689
+ const upsert = UpsertMessageById(this.messages, message);
4690
+ this.messages = upsert.Messages;
4691
+ if (!upsert.Existed) {
4670
4692
  // Ensure current user is in the avatar map for new messages
4671
4693
  this.ensureCurrentUserInAvatarMap();
4672
4694
  // Invalidate cache when new message is added.
@@ -4687,8 +4709,17 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
4687
4709
  // row does not stay In-Progress until the conversation is opened again. Register the row
4688
4710
  // for the live callback either way — an update of an existing In-Progress row included.
4689
4711
  if (message.Status === 'In-Progress' && message.ID) {
4690
- if (!this.InProgressMessageIds.some((id) => UUIDsEqual(id, message.ID))) {
4691
- this.InProgressMessageIds = [...this.InProgressMessageIds, message.ID];
4712
+ const entityMap = (this.inProgressIdByEntity ??= new WeakMap());
4713
+ const previousId = entityMap.get(message);
4714
+ entityMap.set(message, message.ID);
4715
+ const withoutPrevious = previousId && !UUIDsEqual(previousId, message.ID)
4716
+ ? this.InProgressMessageIds.filter((id) => !UUIDsEqual(id, previousId))
4717
+ : this.InProgressMessageIds;
4718
+ if (!withoutPrevious.some((id) => UUIDsEqual(id, message.ID))) {
4719
+ this.InProgressMessageIds = [...withoutPrevious, message.ID];
4720
+ }
4721
+ else if (withoutPrevious !== this.InProgressMessageIds) {
4722
+ this.InProgressMessageIds = withoutPrevious;
4692
4723
  }
4693
4724
  const recentCompletion = this.streamingService.GetRecentCompletion(message.ID);
4694
4725
  if (recentCompletion) {
@@ -4700,7 +4731,7 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
4700
4731
  }
4701
4732
  // Where the viewport goes: a fresh send follows — an in-place update of a message that
4702
4733
  // is already on screen must not re-run the send path's scroll.
4703
- this.followTranscript(existingIndex >= 0 ? 'update' : 'new', message);
4734
+ this.followTranscript(upsert.Existed ? 'update' : 'new', message);
4704
4735
  // Force change detection — zone.js 0.15 no longer patches graphql-ws WebSocket callbacks,
4705
4736
  // so progress updates that arrive via PubSub run outside Angular's zone. Without this,
4706
4737
  // the UI does not update when the messages array is modified from a streaming callback.
@@ -4931,8 +4962,7 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
4931
4962
  merged.set(msg.ID, msg);
4932
4963
  }
4933
4964
  }
4934
- this.messages = Array.from(merged.values())
4935
- .sort((a, b) => (a.__mj_CreatedAt?.getTime() || 0) - (b.__mj_CreatedAt?.getTime() || 0));
4965
+ this.messages = Array.from(merged.values()).sort(CompareMessagesByCreatedAt);
4936
4966
  // Find newly discovered messages (delegated agents)
4937
4967
  const newMessages = engineDetails.filter(m => !existingMessageIds.has(m.ID));
4938
4968
  // Check engine cache for agent runs on new messages
@@ -6680,17 +6710,30 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
6680
6710
  get hasSystemArtifacts() {
6681
6711
  return this.HasSystemArtifacts;
6682
6712
  }
6713
+ _artifactsArrayCache = [];
6714
+ _artifactsArrayKey = '';
6683
6715
  /**
6684
- * Get unique artifacts grouped by artifact ID (not by conversation detail)
6685
- * Returns the latest version info for each unique artifact with all versions
6686
- * Works with LazyArtifactInfo - uses display data without loading full entities
6687
- * Respects showSystemArtifacts toggle
6716
+ * Get unique artifacts grouped by artifact ID (not by conversation detail).
6717
+ * Returns the latest version info for each unique artifact with all versions.
6718
+ * Works with LazyArtifactInfo - uses display data without loading full entities.
6719
+ * Respects showSystemArtifacts toggle and memoizes the result across CD passes.
6688
6720
  */
6689
6721
  GetArtifactsArray() {
6722
+ const effectiveMap = this.EffectiveArtifactsMap;
6723
+ let sig = `${this.ShowSystemArtifacts ? 1 : 0}|${effectiveMap.size}|`;
6724
+ for (const artifactList of effectiveMap.values()) {
6725
+ for (const info of artifactList) {
6726
+ sig += `${info.artifactVersionId}:${info.artifactName ?? ''};`;
6727
+ }
6728
+ }
6729
+ if (sig === this._artifactsArrayKey) {
6730
+ return this._artifactsArrayCache;
6731
+ }
6732
+ this._artifactsArrayKey = sig;
6690
6733
  const artifactMap = new Map();
6691
6734
  // Group by artifactId, collecting all version details
6692
6735
  // Use effectiveArtifactsMap to respect showSystemArtifacts toggle
6693
- for (const artifactList of this.EffectiveArtifactsMap.values()) {
6736
+ for (const artifactList of effectiveMap.values()) {
6694
6737
  for (const info of artifactList) {
6695
6738
  const artifactId = info.artifactId;
6696
6739
  const versionId = info.artifactVersionId;
@@ -6717,7 +6760,7 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
6717
6760
  }
6718
6761
  }
6719
6762
  // Convert to array with version count, sorted by version number descending
6720
- return Array.from(artifactMap.values()).map(item => ({
6763
+ this._artifactsArrayCache = Array.from(artifactMap.values()).map(item => ({
6721
6764
  artifactId: item.artifactId,
6722
6765
  versionId: item.versionId,
6723
6766
  name: item.name,
@@ -6725,6 +6768,7 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
6725
6768
  versionCount: item.versions.length,
6726
6769
  versions: item.versions.sort((a, b) => b.versionNumber - a.versionNumber)
6727
6770
  }));
6771
+ return this._artifactsArrayCache;
6728
6772
  }
6729
6773
  /** @deprecated Use {@link GetArtifactsArray}. */
6730
6774
  getArtifactsArray() {
@@ -7111,7 +7155,9 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
7111
7155
  message.IsPinned = false;
7112
7156
  this.cdr.detectChanges();
7113
7157
  try {
7114
- await message.Save();
7158
+ if (!(await SavePinState(this.ProviderToUse, message.ID, false))) {
7159
+ throw new Error(`the pin on message ${message.ID} could not be saved`);
7160
+ }
7115
7161
  this.OnMessagePinToggled(message);
7116
7162
  }
7117
7163
  catch (err) {
@@ -9698,5 +9744,5 @@ export class ConversationChatAreaComponent extends BaseAngularComponent {
9698
9744
  type: ViewChild,
9699
9745
  args: ['forksButton', { read: ElementRef }]
9700
9746
  }] }); })();
9701
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationChatAreaComponent, { className: "ConversationChatAreaComponent", filePath: "src/lib/components/conversation/conversation-chat-area.component.ts", lineNumber: 201 }); })();
9747
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationChatAreaComponent, { className: "ConversationChatAreaComponent", filePath: "src/lib/components/conversation/conversation-chat-area.component.ts", lineNumber: 204 }); })();
9702
9748
  //# sourceMappingURL=conversation-chat-area.component.js.map