@ai-matrx/messaging 0.10.1 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -291,6 +291,8 @@ interface ActorPresentation {
291
291
  /** The audit principal. Always the row's `sender_id`. Never rewritten. */
292
292
  readonly principalUserId: Message["senderId"];
293
293
  }
294
+ /** Stable presentation identity for grouping adjacent messages in the UI. */
295
+ declare function effectiveActorKey(message: Message): string;
294
296
  declare function resolveActor(message: Message, sender: UserSummary | null): ActorPresentation;
295
297
 
296
298
  /**
@@ -1030,6 +1032,8 @@ declare function groupMessages(messages: readonly Message[], args?: {
1030
1032
  now?: number;
1031
1033
  windowMs?: number;
1032
1034
  locale?: string;
1035
+ /** Split audit-principal rows by their effective actor presentation. */
1036
+ actorKey?: (message: Message) => string;
1033
1037
  }): readonly MessageGroup[];
1034
1038
  /** "Ana is typing…" / "Ana and Bo are typing…" / "3 people are typing…" */
1035
1039
  declare function formatTypists(names: readonly string[]): string | null;
@@ -1115,4 +1119,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1115
1119
  /** Serialize picked references into a fence the platform's other readers accept. */
1116
1120
  declare function composeFence(references: readonly MatrxReference[]): string;
1117
1121
 
1118
- export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, type AiCallArgs, type AiCapability, type AiResult, type Attachment, type ClientMessageId, type Conversation, type ConversationCursor, type ConversationId, type ConversationSummary, type ConversationThread, type ConversationType, type DeliveryState, type DraftMessage, type EngineDiagnostic, type JsonObject, type JsonValue, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingIdentity, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, type Participant, type ParticipantRole, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, type RepositoryOptions, type SchemaLike, type SessionResolver, type SupabaseLike, TABLES, type TextSegment, type UserId, type UserSummary, asClientMessageId, asConversationId, asMessageId, asOrganizationId, asUserId, composeFence, conversationTopic, createActionRegistry, createMemoryOutboxStorage, createMessagingAi, createMessagingEngine, createMessagingRepository, createMessagingStore, createOutbox, createReadCache, createWebOutboxStorage, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, unreadCutoff };
1122
+ export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, type AiCallArgs, type AiCapability, type AiResult, type Attachment, type ClientMessageId, type Conversation, type ConversationCursor, type ConversationId, type ConversationSummary, type ConversationThread, type ConversationType, type DeliveryState, type DraftMessage, type EngineDiagnostic, type JsonObject, type JsonValue, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingIdentity, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, type Participant, type ParticipantRole, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, type RepositoryOptions, type SchemaLike, type SessionResolver, type SupabaseLike, TABLES, type TextSegment, type UserId, type UserSummary, asClientMessageId, asConversationId, asMessageId, asOrganizationId, asUserId, composeFence, conversationTopic, createActionRegistry, createMemoryOutboxStorage, createMessagingAi, createMessagingEngine, createMessagingRepository, createMessagingStore, createOutbox, createReadCache, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, unreadCutoff };
package/dist/index.d.ts CHANGED
@@ -291,6 +291,8 @@ interface ActorPresentation {
291
291
  /** The audit principal. Always the row's `sender_id`. Never rewritten. */
292
292
  readonly principalUserId: Message["senderId"];
293
293
  }
294
+ /** Stable presentation identity for grouping adjacent messages in the UI. */
295
+ declare function effectiveActorKey(message: Message): string;
294
296
  declare function resolveActor(message: Message, sender: UserSummary | null): ActorPresentation;
295
297
 
296
298
  /**
@@ -1030,6 +1032,8 @@ declare function groupMessages(messages: readonly Message[], args?: {
1030
1032
  now?: number;
1031
1033
  windowMs?: number;
1032
1034
  locale?: string;
1035
+ /** Split audit-principal rows by their effective actor presentation. */
1036
+ actorKey?: (message: Message) => string;
1033
1037
  }): readonly MessageGroup[];
1034
1038
  /** "Ana is typing…" / "Ana and Bo are typing…" / "3 people are typing…" */
1035
1039
  declare function formatTypists(names: readonly string[]): string | null;
@@ -1115,4 +1119,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1115
1119
  /** Serialize picked references into a fence the platform's other readers accept. */
1116
1120
  declare function composeFence(references: readonly MatrxReference[]): string;
1117
1121
 
1118
- export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, type AiCallArgs, type AiCapability, type AiResult, type Attachment, type ClientMessageId, type Conversation, type ConversationCursor, type ConversationId, type ConversationSummary, type ConversationThread, type ConversationType, type DeliveryState, type DraftMessage, type EngineDiagnostic, type JsonObject, type JsonValue, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingIdentity, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, type Participant, type ParticipantRole, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, type RepositoryOptions, type SchemaLike, type SessionResolver, type SupabaseLike, TABLES, type TextSegment, type UserId, type UserSummary, asClientMessageId, asConversationId, asMessageId, asOrganizationId, asUserId, composeFence, conversationTopic, createActionRegistry, createMemoryOutboxStorage, createMessagingAi, createMessagingEngine, createMessagingRepository, createMessagingStore, createOutbox, createReadCache, createWebOutboxStorage, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, unreadCutoff };
1122
+ export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, type AiCallArgs, type AiCapability, type AiResult, type Attachment, type ClientMessageId, type Conversation, type ConversationCursor, type ConversationId, type ConversationSummary, type ConversationThread, type ConversationType, type DeliveryState, type DraftMessage, type EngineDiagnostic, type JsonObject, type JsonValue, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingIdentity, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, type Participant, type ParticipantRole, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, type RepositoryOptions, type SchemaLike, type SessionResolver, type SupabaseLike, TABLES, type TextSegment, type UserId, type UserSummary, asClientMessageId, asConversationId, asMessageId, asOrganizationId, asUserId, composeFence, conversationTopic, createActionRegistry, createMemoryOutboxStorage, createMessagingAi, createMessagingEngine, createMessagingRepository, createMessagingStore, createOutbox, createReadCache, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, unreadCutoff };
package/dist/index.js CHANGED
@@ -71,19 +71,38 @@ function createActionRegistry() {
71
71
 
72
72
  // src/core/actor.ts
73
73
  function readActorHint(metadata) {
74
- const raw = metadata["actor"];
75
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
76
- const record = raw;
77
- const agentId = record["agentId"] ?? record["agent_id"];
78
- if (typeof agentId !== "string" || agentId.length === 0) return null;
79
- const name = record["agentName"] ?? record["agent_name"];
80
- const avatar = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
74
+ const envelope = metadata;
75
+ const raw = envelope["actor"];
76
+ if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
77
+ const record = raw;
78
+ const agentId = record["agentId"] ?? record["agent_id"];
79
+ if (typeof agentId !== "string" || agentId.length === 0) return null;
80
+ const name2 = record["agentName"] ?? record["agent_name"];
81
+ const avatar2 = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
82
+ return {
83
+ agentId,
84
+ showPrincipalAttribution: true,
85
+ ...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
86
+ ...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
87
+ };
88
+ }
89
+ const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
90
+ if (actorKind !== "agent") return null;
91
+ const id = envelope["actor_id"] ?? envelope["actorId"];
92
+ const name = envelope["actor_label"] ?? envelope["actorLabel"];
93
+ const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
81
94
  return {
82
- agentId,
95
+ showPrincipalAttribution: false,
96
+ ...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
83
97
  ...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
84
98
  ...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
85
99
  };
86
100
  }
101
+ function effectiveActorKey(message) {
102
+ const hint = readActorHint(message.metadata);
103
+ if (hint === null) return `principal:${message.senderId}`;
104
+ return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
105
+ }
87
106
  function resolveActor(message, sender) {
88
107
  const hint = readActorHint(message.metadata);
89
108
  const humanName = sender?.displayName ?? message.senderId;
@@ -95,7 +114,11 @@ function resolveActor(message, sender) {
95
114
  displayName: hint.agentName ?? "Agent",
96
115
  avatarUrl: hint.agentAvatarUrl ?? null,
97
116
  isAgent: true,
98
- onBehalfOfName: humanName,
117
+ // The nested envelope explicitly models an agent acting on behalf of a
118
+ // session principal. Platform event rows use the flat actor envelope as
119
+ // the complete presentation identity; surfacing their audit writer as
120
+ // "via Human" wrongly re-attaches that person to an automated event.
121
+ onBehalfOfName: hint.showPrincipalAttribution ? humanName : null,
99
122
  principalUserId: message.senderId
100
123
  };
101
124
  }
@@ -1287,6 +1310,11 @@ function createMessagingEngine(options) {
1287
1310
  if (openChannels.has(id) || disposed) return;
1288
1311
  const handle = manager.open({
1289
1312
  topic: conversationTopic(id),
1313
+ // Presence callbacks are JOIN-TIME in supabase-js. Declare the
1314
+ // read-only room shape on the first holder (the engine) so the
1315
+ // composer/typist/online hooks can attach without forcing a rebuild
1316
+ // after this durable channel has already subscribed.
1317
+ presence: { publish: false, state: {} },
1290
1318
  postgresChanges: [
1291
1319
  {
1292
1320
  event: "*",
@@ -1452,18 +1480,20 @@ function groupMessages(messages, args = {}) {
1452
1480
  let current = null;
1453
1481
  let previousDay = null;
1454
1482
  for (const message of messages) {
1483
+ const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
1455
1484
  const day = message.createdAt.slice(0, 10);
1456
1485
  const startsNewDay = day !== previousDay;
1457
1486
  previousDay = day;
1458
1487
  const last = current?.messages.at(-1);
1459
1488
  const withinWindow = last !== void 0 && Math.abs(Date.parse(message.createdAt) - Date.parse(last.createdAt)) <= windowMs;
1460
- if (current !== null && current.senderId === message.senderId && withinWindow && !startsNewDay) {
1489
+ if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
1461
1490
  current.messages.push(message);
1462
1491
  continue;
1463
1492
  }
1464
1493
  if (current !== null) groups.push(current);
1465
1494
  current = {
1466
1495
  senderId: message.senderId,
1496
+ actorKey,
1467
1497
  messages: [message],
1468
1498
  dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
1469
1499
  };
@@ -1862,6 +1892,7 @@ export {
1862
1892
  createOutbox,
1863
1893
  createReadCache,
1864
1894
  createWebOutboxStorage,
1895
+ effectiveActorKey,
1865
1896
  extractReferences,
1866
1897
  formatConversationTime,
1867
1898
  formatDateSeparator,