@ai-matrx/messaging 0.10.1 → 0.10.2

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/react.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { ReactNode, ComponentType, SVGProps } from 'react';
1
+ import { ReactNode, ComponentType, KeyboardEvent, SVGProps } from 'react';
2
2
  import { MatrxJsonObject, MatrxTransport } from '@ai-matrx/agents/matrx';
3
3
  import { RealtimeClientLike, RealtimeManager } from '@ai-matrx/realtime';
4
4
 
@@ -1157,6 +1157,21 @@ interface ConversationViewProps {
1157
1157
  conversationId: ConversationId | null;
1158
1158
  onBack?: () => void;
1159
1159
  className?: string;
1160
+ /** Hide package chrome when a containing workspace already owns the title. */
1161
+ showHeader?: boolean;
1162
+ /** Hide conversation AI controls on a surface that deliberately does not offer them. */
1163
+ showAi?: boolean;
1164
+ /** Let a host inject its canonical textarea chrome without taking composer behavior. */
1165
+ renderComposerInput?: (props: ComposerInputRenderProps) => ReactNode;
1166
+ }
1167
+ interface ComposerInputRenderProps {
1168
+ readonly value: string;
1169
+ readonly disabled: boolean;
1170
+ readonly canSend: boolean;
1171
+ readonly placeholder: string;
1172
+ readonly onChange: (value: string) => void;
1173
+ readonly onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => void;
1174
+ readonly onSubmit: () => void;
1160
1175
  }
1161
1176
  declare function ConversationView(props: ConversationViewProps): ReactNode;
1162
1177
  declare function MessageBubble(props: {
@@ -1285,6 +1300,8 @@ interface ActorPresentation {
1285
1300
  /** The audit principal. Always the row's `sender_id`. Never rewritten. */
1286
1301
  readonly principalUserId: Message["senderId"];
1287
1302
  }
1303
+ /** Stable presentation identity for grouping adjacent messages in the UI. */
1304
+ declare function effectiveActorKey(message: Message): string;
1288
1305
  declare function resolveActor(message: Message, sender: UserSummary | null): ActorPresentation;
1289
1306
 
1290
1307
  /**
@@ -1434,6 +1451,8 @@ declare function groupMessages(messages: readonly Message[], args?: {
1434
1451
  now?: number;
1435
1452
  windowMs?: number;
1436
1453
  locale?: string;
1454
+ /** Split audit-principal rows by their effective actor presentation. */
1455
+ actorKey?: (message: Message) => string;
1437
1456
  }): readonly MessageGroup[];
1438
1457
  /** "Ana is typing…" / "Ana and Bo are typing…" / "3 people are typing…" */
1439
1458
  declare function formatTypists(names: readonly string[]): string | null;
@@ -1519,4 +1538,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1519
1538
  /** Serialize picked references into a fence the platform's other readers accept. */
1520
1539
  declare function composeFence(references: readonly MatrxReference[]): string;
1521
1540
 
1522
- export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, AgentTag, type AiCallArgs, type AiCapability, type AiResult, AlertIcon, type Attachment, Avatar, BotIcon, CheckIcon, ChevronLeftIcon, type ClientMessageId, ClockIcon, CloseIcon, Composer, type Conversation, type ConversationCursor, type ConversationId, ConversationList, type ConversationListProps, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, type DeliveryState, DeliveryTick, DoubleCheckIcon, type DraftMessage, EmptyState, type EngineDiagnostic, type IncomingMessageContext, type JsonObject, type JsonValue, LinkIcon, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, MessageActionChips, type MessageActionRenderProps, type MessageActionRenderer, MessageBubble, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessageWrapperProps, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingHost, type MessagingIdentity, MessagingInbox, type MessagingInboxProps, MessagingProvider, type MessagingProviderProps, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, PaperclipIcon, type Participant, type ParticipantRole, PlusIcon, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, ReferenceCard, type ReferenceRenderer, ReplyIcon, type RepositoryOptions, type SchemaLike, SearchIcon, SendIcon, type SessionResolver, SparklesIcon, type SupabaseLike, TABLES, type TextSegment, TypingDots, type UseComposerResult, type UseConversationResult, type UseConversationsResult, type UseMessageActionResult, type UseMessagingAiResult, type UseTypistsResult, type UserId, type UserSummary, UsersIcon, 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, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
1541
+ export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, AgentTag, type AiCallArgs, type AiCapability, type AiResult, AlertIcon, type Attachment, Avatar, BotIcon, CheckIcon, ChevronLeftIcon, type ClientMessageId, ClockIcon, CloseIcon, Composer, type ComposerInputRenderProps, type Conversation, type ConversationCursor, type ConversationId, ConversationList, type ConversationListProps, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, type DeliveryState, DeliveryTick, DoubleCheckIcon, type DraftMessage, EmptyState, type EngineDiagnostic, type IncomingMessageContext, type JsonObject, type JsonValue, LinkIcon, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, MessageActionChips, type MessageActionRenderProps, type MessageActionRenderer, MessageBubble, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessageWrapperProps, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingHost, type MessagingIdentity, MessagingInbox, type MessagingInboxProps, MessagingProvider, type MessagingProviderProps, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, PaperclipIcon, type Participant, type ParticipantRole, PlusIcon, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, ReferenceCard, type ReferenceRenderer, ReplyIcon, type RepositoryOptions, type SchemaLike, SearchIcon, SendIcon, type SessionResolver, SparklesIcon, type SupabaseLike, TABLES, type TextSegment, TypingDots, type UseComposerResult, type UseConversationResult, type UseConversationsResult, type UseMessageActionResult, type UseMessagingAiResult, type UseTypistsResult, type UserId, type UserSummary, UsersIcon, 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, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ReactNode, ComponentType, SVGProps } from 'react';
1
+ import { ReactNode, ComponentType, KeyboardEvent, SVGProps } from 'react';
2
2
  import { MatrxJsonObject, MatrxTransport } from '@ai-matrx/agents/matrx';
3
3
  import { RealtimeClientLike, RealtimeManager } from '@ai-matrx/realtime';
4
4
 
@@ -1157,6 +1157,21 @@ interface ConversationViewProps {
1157
1157
  conversationId: ConversationId | null;
1158
1158
  onBack?: () => void;
1159
1159
  className?: string;
1160
+ /** Hide package chrome when a containing workspace already owns the title. */
1161
+ showHeader?: boolean;
1162
+ /** Hide conversation AI controls on a surface that deliberately does not offer them. */
1163
+ showAi?: boolean;
1164
+ /** Let a host inject its canonical textarea chrome without taking composer behavior. */
1165
+ renderComposerInput?: (props: ComposerInputRenderProps) => ReactNode;
1166
+ }
1167
+ interface ComposerInputRenderProps {
1168
+ readonly value: string;
1169
+ readonly disabled: boolean;
1170
+ readonly canSend: boolean;
1171
+ readonly placeholder: string;
1172
+ readonly onChange: (value: string) => void;
1173
+ readonly onKeyDown: (event: KeyboardEvent<HTMLTextAreaElement>) => void;
1174
+ readonly onSubmit: () => void;
1160
1175
  }
1161
1176
  declare function ConversationView(props: ConversationViewProps): ReactNode;
1162
1177
  declare function MessageBubble(props: {
@@ -1285,6 +1300,8 @@ interface ActorPresentation {
1285
1300
  /** The audit principal. Always the row's `sender_id`. Never rewritten. */
1286
1301
  readonly principalUserId: Message["senderId"];
1287
1302
  }
1303
+ /** Stable presentation identity for grouping adjacent messages in the UI. */
1304
+ declare function effectiveActorKey(message: Message): string;
1288
1305
  declare function resolveActor(message: Message, sender: UserSummary | null): ActorPresentation;
1289
1306
 
1290
1307
  /**
@@ -1434,6 +1451,8 @@ declare function groupMessages(messages: readonly Message[], args?: {
1434
1451
  now?: number;
1435
1452
  windowMs?: number;
1436
1453
  locale?: string;
1454
+ /** Split audit-principal rows by their effective actor presentation. */
1455
+ actorKey?: (message: Message) => string;
1437
1456
  }): readonly MessageGroup[];
1438
1457
  /** "Ana is typing…" / "Ana and Bo are typing…" / "3 people are typing…" */
1439
1458
  declare function formatTypists(names: readonly string[]): string | null;
@@ -1519,4 +1538,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1519
1538
  /** Serialize picked references into a fence the platform's other readers accept. */
1520
1539
  declare function composeFence(references: readonly MatrxReference[]): string;
1521
1540
 
1522
- export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, AgentTag, type AiCallArgs, type AiCapability, type AiResult, AlertIcon, type Attachment, Avatar, BotIcon, CheckIcon, ChevronLeftIcon, type ClientMessageId, ClockIcon, CloseIcon, Composer, type Conversation, type ConversationCursor, type ConversationId, ConversationList, type ConversationListProps, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, type DeliveryState, DeliveryTick, DoubleCheckIcon, type DraftMessage, EmptyState, type EngineDiagnostic, type IncomingMessageContext, type JsonObject, type JsonValue, LinkIcon, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, MessageActionChips, type MessageActionRenderProps, type MessageActionRenderer, MessageBubble, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessageWrapperProps, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingHost, type MessagingIdentity, MessagingInbox, type MessagingInboxProps, MessagingProvider, type MessagingProviderProps, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, PaperclipIcon, type Participant, type ParticipantRole, PlusIcon, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, ReferenceCard, type ReferenceRenderer, ReplyIcon, type RepositoryOptions, type SchemaLike, SearchIcon, SendIcon, type SessionResolver, SparklesIcon, type SupabaseLike, TABLES, type TextSegment, TypingDots, type UseComposerResult, type UseConversationResult, type UseConversationsResult, type UseMessageActionResult, type UseMessagingAiResult, type UseTypistsResult, type UserId, type UserSummary, UsersIcon, 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, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
1541
+ export { type ActionChoice, type ActionContext, type ActionHandler, type ActionOutcome, type ActionReceipt, type ActionRegistry, type ActorPresentation, AgentTag, type AiCallArgs, type AiCapability, type AiResult, AlertIcon, type Attachment, Avatar, BotIcon, CheckIcon, ChevronLeftIcon, type ClientMessageId, ClockIcon, CloseIcon, Composer, type ComposerInputRenderProps, type Conversation, type ConversationCursor, type ConversationId, ConversationList, type ConversationListProps, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, type DeliveryState, DeliveryTick, DoubleCheckIcon, type DraftMessage, EmptyState, type EngineDiagnostic, type IncomingMessageContext, type JsonObject, type JsonValue, LinkIcon, MESSAGING_EVENTS, MESSAGING_RPC_SCHEMA, MESSAGING_SCHEMA, type MatrxReference, type Message, type MessageAction, MessageActionChips, type MessageActionRenderProps, type MessageActionRenderer, MessageBubble, type MessageCursor, type MessageGroup, type MessageId, type MessageKind, type MessageWrapperProps, type MessagingAgentIdentity, type MessagingAgents, type MessagingAi, type MessagingAiOptions, type MessagingEngine, type MessagingEngineOptions, MessagingError, type MessagingErrorCode, type MessagingHost, type MessagingIdentity, MessagingInbox, type MessagingInboxProps, MessagingProvider, type MessagingProviderProps, type MessagingRepository, type MessagingSnapshot, type MessagingStore, type MessagingSupabaseClient, type MessagingSupabaseInternal, type OrganizationId, type Outbox, type OutboxEntry, type OutboxOptions, type OutboxStorage, type Page, PaperclipIcon, type Participant, type ParticipantRole, PlusIcon, type PostgrestFilterLike, type PostgrestLikeResponse, type PostgrestTableLike, RPCS, type ReadCache, type ReadCacheOptions, ReferenceCard, type ReferenceRenderer, ReplyIcon, type RepositoryOptions, type SchemaLike, SearchIcon, SendIcon, type SessionResolver, SparklesIcon, type SupabaseLike, TABLES, type TextSegment, TypingDots, type UseComposerResult, type UseConversationResult, type UseConversationsResult, type UseMessageActionResult, type UseMessagingAiResult, type UseTypistsResult, type UserId, type UserSummary, UsersIcon, 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, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
package/dist/react.js CHANGED
@@ -1956,18 +1956,20 @@ function groupMessages(messages, args = {}) {
1956
1956
  let current = null;
1957
1957
  let previousDay = null;
1958
1958
  for (const message of messages) {
1959
+ const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
1959
1960
  const day = message.createdAt.slice(0, 10);
1960
1961
  const startsNewDay = day !== previousDay;
1961
1962
  previousDay = day;
1962
1963
  const last = current?.messages.at(-1);
1963
1964
  const withinWindow = last !== void 0 && Math.abs(Date.parse(message.createdAt) - Date.parse(last.createdAt)) <= windowMs;
1964
- if (current !== null && current.senderId === message.senderId && withinWindow && !startsNewDay) {
1965
+ if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
1965
1966
  current.messages.push(message);
1966
1967
  continue;
1967
1968
  }
1968
1969
  if (current !== null) groups.push(current);
1969
1970
  current = {
1970
1971
  senderId: message.senderId,
1972
+ actorKey,
1971
1973
  messages: [message],
1972
1974
  dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
1973
1975
  };
@@ -2285,23 +2287,45 @@ function useMessageAction(message) {
2285
2287
  }
2286
2288
 
2287
2289
  // src/react/components.tsx
2288
- import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState2 } from "react";
2290
+ import {
2291
+ useEffect as useEffect3,
2292
+ useMemo as useMemo3,
2293
+ useRef as useRef3,
2294
+ useState as useState2
2295
+ } from "react";
2289
2296
 
2290
2297
  // src/core/actor.ts
2291
2298
  function readActorHint(metadata) {
2292
- const raw = metadata["actor"];
2293
- if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
2294
- const record = raw;
2295
- const agentId = record["agentId"] ?? record["agent_id"];
2296
- if (typeof agentId !== "string" || agentId.length === 0) return null;
2297
- const name = record["agentName"] ?? record["agent_name"];
2298
- const avatar = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
2299
+ const envelope = metadata;
2300
+ const raw = envelope["actor"];
2301
+ if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
2302
+ const record = raw;
2303
+ const agentId = record["agentId"] ?? record["agent_id"];
2304
+ if (typeof agentId !== "string" || agentId.length === 0) return null;
2305
+ const name2 = record["agentName"] ?? record["agent_name"];
2306
+ const avatar2 = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
2307
+ return {
2308
+ agentId,
2309
+ ...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
2310
+ ...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
2311
+ };
2312
+ }
2313
+ const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
2314
+ if (actorKind !== "agent") return null;
2315
+ const id = envelope["actor_id"] ?? envelope["actorId"];
2316
+ const name = envelope["actor_label"] ?? envelope["actorLabel"];
2317
+ const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
2299
2318
  return {
2300
- agentId,
2319
+ ...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
2301
2320
  ...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
2302
2321
  ...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
2303
2322
  };
2304
2323
  }
2324
+ function effectiveActorKey(message) {
2325
+ const hint = readActorHint(message.metadata);
2326
+ if (hint === null) return `principal:${message.senderId}`;
2327
+ return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
2328
+ }
2305
2329
  function resolveActor(message, sender) {
2306
2330
  const hint = readActorHint(message.metadata);
2307
2331
  const humanName = sender?.displayName ?? message.senderId;
@@ -2697,7 +2721,7 @@ function ConversationView(props) {
2697
2721
  );
2698
2722
  const anyOnline = others.some((participant) => online.has(participant.userId));
2699
2723
  return /* @__PURE__ */ jsxs2("div", { className: `mx-msg__thread${props.className !== void 0 ? ` ${props.className}` : ""}`, children: [
2700
- /* @__PURE__ */ jsxs2("header", { className: "mx-msg__header", children: [
2724
+ props.showHeader !== false ? /* @__PURE__ */ jsxs2("header", { className: "mx-msg__header", children: [
2701
2725
  props.onBack !== void 0 ? /* @__PURE__ */ jsx4(
2702
2726
  "button",
2703
2727
  {
@@ -2732,8 +2756,8 @@ function ConversationView(props) {
2732
2756
  children: /* @__PURE__ */ jsx4(UsersIcon, {})
2733
2757
  }
2734
2758
  ) : null })
2735
- ] }),
2736
- ai.available.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ jsxs2(
2759
+ ] }) : null,
2760
+ props.showAi !== false && ai.available.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ jsxs2(
2737
2761
  "button",
2738
2762
  {
2739
2763
  type: "button",
@@ -2747,7 +2771,7 @@ function ConversationView(props) {
2747
2771
  },
2748
2772
  capability
2749
2773
  )) }) : null,
2750
- ai.isRunning ? /* @__PURE__ */ jsx4("p", { className: "mx-msg__ai-output", "aria-busy": "true", "aria-live": "polite", children: ai.partialText.length > 0 ? ai.partialText : /* @__PURE__ */ jsxs2(Fragment, { children: [
2774
+ props.showAi !== false && ai.isRunning ? /* @__PURE__ */ jsx4("p", { className: "mx-msg__ai-output", "aria-busy": "true", "aria-live": "polite", children: ai.partialText.length > 0 ? ai.partialText : /* @__PURE__ */ jsxs2(Fragment, { children: [
2751
2775
  /* @__PURE__ */ jsx4("span", { className: "mx-msg__ai-output-label", children: ai.activeCapability !== null ? `${AI_LABELS[ai.activeCapability]}\u2026` : "Working\u2026" }),
2752
2776
  /* @__PURE__ */ jsx4(
2753
2777
  "span",
@@ -2756,7 +2780,7 @@ function ConversationView(props) {
2756
2780
  style: { display: "block", height: 11, width: "72%" }
2757
2781
  }
2758
2782
  )
2759
- ] }) }) : ai.error !== null ? /* @__PURE__ */ jsx4("p", { className: "mx-msg__ai-output", style: { color: "var(--mx-msg-danger)" }, children: ai.error }) : ai.result !== null ? /* @__PURE__ */ jsxs2("p", { className: "mx-msg__ai-output", children: [
2783
+ ] }) }) : props.showAi !== false && ai.error !== null ? /* @__PURE__ */ jsx4("p", { className: "mx-msg__ai-output", style: { color: "var(--mx-msg-danger)" }, children: ai.error }) : props.showAi !== false && ai.result !== null ? /* @__PURE__ */ jsxs2("p", { className: "mx-msg__ai-output", children: [
2760
2784
  ai.result.text,
2761
2785
  /* @__PURE__ */ jsx4(
2762
2786
  "button",
@@ -2781,26 +2805,24 @@ function ConversationView(props) {
2781
2805
  children: "Load earlier messages"
2782
2806
  }
2783
2807
  ) : null,
2784
- groupMessages(messages).map((group) => {
2808
+ groupMessages(messages, { actorKey: effectiveActorKey }).map((group) => {
2785
2809
  const first = group.messages[0];
2786
2810
  if (first === void 0) return null;
2787
- const isMine = group.senderId === selfId;
2788
2811
  const sender = conversation.participants.find(
2789
2812
  (participant) => participant.userId === group.senderId
2790
2813
  ) ?? null;
2814
+ const actor = resolveActor(first, sender);
2815
+ const isMine = group.senderId === selfId && !actor.isAgent;
2791
2816
  return /* @__PURE__ */ jsxs2("div", { children: [
2792
2817
  group.dateSeparator !== null ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__day", children: group.dateSeparator }) : null,
2793
2818
  /* @__PURE__ */ jsx4(
2794
2819
  MessageGroupView,
2795
2820
  {
2796
2821
  messages: group.messages,
2797
- sender,
2822
+ actor,
2798
2823
  isMine,
2799
2824
  onRetry: conversation.retry,
2800
2825
  onReply: composer.setReplyTo,
2801
- pendingIds: new Set(
2802
- conversation.pending.filter((entry) => entry.state === "failed").map((entry) => entry.clientMessageId)
2803
- ),
2804
2826
  failedEntryIdByClientId: new Map(
2805
2827
  conversation.pending.map((entry) => [entry.clientMessageId, entry.id])
2806
2828
  )
@@ -2813,13 +2835,20 @@ function ConversationView(props) {
2813
2835
  /* @__PURE__ */ jsx4(TypingDots, {}),
2814
2836
  typists.label
2815
2837
  ] }) : null }),
2816
- /* @__PURE__ */ jsx4(ComposerView, { composer, disabled: false })
2838
+ /* @__PURE__ */ jsx4(
2839
+ ComposerView,
2840
+ {
2841
+ composer,
2842
+ disabled: false,
2843
+ ...props.renderComposerInput !== void 0 ? { renderInput: props.renderComposerInput } : {}
2844
+ }
2845
+ )
2817
2846
  ] });
2818
2847
  }
2819
2848
  function MessageGroupView(props) {
2820
2849
  const first = props.messages[0];
2821
2850
  if (first === void 0) return null;
2822
- const actor = resolveActor(first, props.sender);
2851
+ const actor = props.actor;
2823
2852
  return /* @__PURE__ */ jsxs2("div", { className: `mx-msg__group${props.isMine ? " mx-msg__group--mine" : ""}`, children: [
2824
2853
  /* @__PURE__ */ jsx4(
2825
2854
  Avatar,
@@ -3006,7 +3035,24 @@ function ComposerView(props) {
3006
3035
  }
3007
3036
  )
3008
3037
  ] }) : null,
3009
- /* @__PURE__ */ jsxs2("div", { className: "mx-msg__composer-row", children: [
3038
+ props.renderInput !== void 0 ? props.renderInput({
3039
+ value: composer.value,
3040
+ disabled: props.disabled,
3041
+ canSend: composer.canSend,
3042
+ placeholder: "Write a reply\u2026",
3043
+ onChange: (value) => {
3044
+ composer.setValue(value);
3045
+ composer.onKeystroke();
3046
+ },
3047
+ onKeyDown: (event) => {
3048
+ if (event.key !== "Enter" || event.shiftKey) return;
3049
+ const isTouch = typeof globalThis.matchMedia === "function" && globalThis.matchMedia("(pointer: coarse)").matches;
3050
+ if (isTouch) return;
3051
+ event.preventDefault();
3052
+ composer.send();
3053
+ },
3054
+ onSubmit: composer.send
3055
+ }) : /* @__PURE__ */ jsxs2("div", { className: "mx-msg__composer-row", children: [
3010
3056
  /* @__PURE__ */ jsx4(
3011
3057
  "textarea",
3012
3058
  {
@@ -3137,6 +3183,7 @@ export {
3137
3183
  createOutbox,
3138
3184
  createReadCache,
3139
3185
  createWebOutboxStorage,
3186
+ effectiveActorKey,
3140
3187
  extractReferences,
3141
3188
  formatConversationTime,
3142
3189
  formatDateSeparator,