@ai-matrx/messaging 0.12.5 → 0.13.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.
package/dist/react.d.cts CHANGED
@@ -943,6 +943,24 @@ declare function createMessagingRepository(options: RepositoryOptions): Messagin
943
943
  * place here.
944
944
  */
945
945
 
946
+ /**
947
+ * Why a conversation could not be read — held PER conversation so a screen can
948
+ * tell "still loading" from "this will never load".
949
+ *
950
+ * Without it a refused read left the thread absent forever (an endless
951
+ * spinner), and a zero-row read of a conversation the caller cannot see
952
+ * rendered "No messages yet" — a confident lie about a conversation they may
953
+ * not even be allowed to know exists.
954
+ */
955
+ interface ConversationReadFailure {
956
+ readonly error: MessagingError;
957
+ /**
958
+ * True when the conversation does not exist or this user may not read it
959
+ * (`not-found` / `forbidden`) — an ACCESS question the host answers with its
960
+ * access surface, never a retryable fault.
961
+ */
962
+ readonly unavailable: boolean;
963
+ }
946
964
  interface ConversationThread {
947
965
  readonly conversationId: ConversationId;
948
966
  readonly messages: readonly Message[];
@@ -984,6 +1002,8 @@ interface MessagingSnapshot {
984
1002
  readonly count: number;
985
1003
  readonly exact: boolean;
986
1004
  } | null;
1005
+ /** Conversations whose last open failed, keyed by id. Cleared on the next open. */
1006
+ readonly conversationReadFailures: ReadonlyMap<ConversationId, ConversationReadFailure>;
987
1007
  }
988
1008
  interface MessagingStore {
989
1009
  snapshot(): MessagingSnapshot;
@@ -1003,6 +1023,8 @@ interface MessagingStore {
1003
1023
  upsertConversation(item: ConversationSummary): void;
1004
1024
  removeConversation(id: ConversationId): void;
1005
1025
  setActiveConversation(id: ConversationId | null): void;
1026
+ /** Record (or clear, with `null`) why a conversation could not be read. */
1027
+ setConversationReadFailure(id: ConversationId, failure: ConversationReadFailure | null): void;
1006
1028
  setThread(id: ConversationId, messages: readonly Message[], args?: {
1007
1029
  hasMoreOlder?: boolean;
1008
1030
  }): void;
@@ -1362,7 +1384,18 @@ interface UseConversationResult {
1362
1384
  thread: ConversationThread | null;
1363
1385
  messages: readonly Message[];
1364
1386
  participants: readonly UserSummary[];
1387
+ /** True only while the first read is in flight — false once it failed. */
1365
1388
  isLoading: boolean;
1389
+ /**
1390
+ * Why the conversation could not be read, or `null`. `error.cause` is the
1391
+ * raw database error, for hosts that classify access failures themselves.
1392
+ */
1393
+ error: MessagingError | null;
1394
+ /**
1395
+ * True when the conversation does not exist or this user may not read it.
1396
+ * Render the host's access surface — never "No messages yet".
1397
+ */
1398
+ unavailable: boolean;
1366
1399
  hasMoreOlder: boolean;
1367
1400
  loadOlder: () => void;
1368
1401
  pending: readonly OutboxEntry[];
@@ -1805,4 +1838,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1805
1838
  /** Serialize picked references into a fence the platform's other readers accept. */
1806
1839
  declare function composeFence(references: readonly MatrxReference[]): string;
1807
1840
 
1808
- 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, DEFAULT_MESSAGING_ARCHIVE_FILTER, 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 MessagingArchiveFilter, 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, SERVER_SESSION_IDENTITY, type SchemaLike, SearchIcon, SendIcon, type SessionIdentity, type SessionIdentitySnapshot, 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, createSessionIdentity, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, toMessagingArchiveFilter, unreadCutoff, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
1841
+ 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 ConversationReadFailure, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, DEFAULT_MESSAGING_ARCHIVE_FILTER, 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 MessagingArchiveFilter, 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, SERVER_SESSION_IDENTITY, type SchemaLike, SearchIcon, SendIcon, type SessionIdentity, type SessionIdentitySnapshot, 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, createSessionIdentity, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, toMessagingArchiveFilter, unreadCutoff, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
package/dist/react.d.ts CHANGED
@@ -943,6 +943,24 @@ declare function createMessagingRepository(options: RepositoryOptions): Messagin
943
943
  * place here.
944
944
  */
945
945
 
946
+ /**
947
+ * Why a conversation could not be read — held PER conversation so a screen can
948
+ * tell "still loading" from "this will never load".
949
+ *
950
+ * Without it a refused read left the thread absent forever (an endless
951
+ * spinner), and a zero-row read of a conversation the caller cannot see
952
+ * rendered "No messages yet" — a confident lie about a conversation they may
953
+ * not even be allowed to know exists.
954
+ */
955
+ interface ConversationReadFailure {
956
+ readonly error: MessagingError;
957
+ /**
958
+ * True when the conversation does not exist or this user may not read it
959
+ * (`not-found` / `forbidden`) — an ACCESS question the host answers with its
960
+ * access surface, never a retryable fault.
961
+ */
962
+ readonly unavailable: boolean;
963
+ }
946
964
  interface ConversationThread {
947
965
  readonly conversationId: ConversationId;
948
966
  readonly messages: readonly Message[];
@@ -984,6 +1002,8 @@ interface MessagingSnapshot {
984
1002
  readonly count: number;
985
1003
  readonly exact: boolean;
986
1004
  } | null;
1005
+ /** Conversations whose last open failed, keyed by id. Cleared on the next open. */
1006
+ readonly conversationReadFailures: ReadonlyMap<ConversationId, ConversationReadFailure>;
987
1007
  }
988
1008
  interface MessagingStore {
989
1009
  snapshot(): MessagingSnapshot;
@@ -1003,6 +1023,8 @@ interface MessagingStore {
1003
1023
  upsertConversation(item: ConversationSummary): void;
1004
1024
  removeConversation(id: ConversationId): void;
1005
1025
  setActiveConversation(id: ConversationId | null): void;
1026
+ /** Record (or clear, with `null`) why a conversation could not be read. */
1027
+ setConversationReadFailure(id: ConversationId, failure: ConversationReadFailure | null): void;
1006
1028
  setThread(id: ConversationId, messages: readonly Message[], args?: {
1007
1029
  hasMoreOlder?: boolean;
1008
1030
  }): void;
@@ -1362,7 +1384,18 @@ interface UseConversationResult {
1362
1384
  thread: ConversationThread | null;
1363
1385
  messages: readonly Message[];
1364
1386
  participants: readonly UserSummary[];
1387
+ /** True only while the first read is in flight — false once it failed. */
1365
1388
  isLoading: boolean;
1389
+ /**
1390
+ * Why the conversation could not be read, or `null`. `error.cause` is the
1391
+ * raw database error, for hosts that classify access failures themselves.
1392
+ */
1393
+ error: MessagingError | null;
1394
+ /**
1395
+ * True when the conversation does not exist or this user may not read it.
1396
+ * Render the host's access surface — never "No messages yet".
1397
+ */
1398
+ unavailable: boolean;
1366
1399
  hasMoreOlder: boolean;
1367
1400
  loadOlder: () => void;
1368
1401
  pending: readonly OutboxEntry[];
@@ -1805,4 +1838,4 @@ declare function summarizeText(content: string, maxLength?: number): string;
1805
1838
  /** Serialize picked references into a fence the platform's other readers accept. */
1806
1839
  declare function composeFence(references: readonly MatrxReference[]): string;
1807
1840
 
1808
- 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, DEFAULT_MESSAGING_ARCHIVE_FILTER, 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 MessagingArchiveFilter, 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, SERVER_SESSION_IDENTITY, type SchemaLike, SearchIcon, SendIcon, type SessionIdentity, type SessionIdentitySnapshot, 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, createSessionIdentity, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, toMessagingArchiveFilter, unreadCutoff, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
1841
+ 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 ConversationReadFailure, type ConversationRowWrapperProps, ConversationSkeleton, type ConversationSummary, type ConversationThread, type ConversationType, ConversationView, type ConversationViewProps, DEFAULT_MESSAGING_ARCHIVE_FILTER, 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 MessagingArchiveFilter, 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, SERVER_SESSION_IDENTITY, type SchemaLike, SearchIcon, SendIcon, type SessionIdentity, type SessionIdentitySnapshot, 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, createSessionIdentity, createWebOutboxStorage, effectiveActorKey, extractReferences, formatConversationTime, formatDateSeparator, formatLastSeen, formatMessageTime, formatTypists, groupMessages, inboxTopic, invalidResponse, isSameDay, messagingClientId, normalizeMessagingError, optimisticMessage, participantNames, projectConversationSummary, projectMessage, projectMessageAction, projectParticipantRole, projectUserSummary, resolveActor, splitText, summarizeText, toMessagingArchiveFilter, unreadCutoff, useComposer, useConversation, useConversations, useMessageAction, useMessagingAi, useMessagingHost, useMessagingSnapshot, useOnlineUserIds, useRequiredMessagingHost, useTypists };
package/dist/react.js CHANGED
@@ -875,6 +875,7 @@ function createMessagingStore() {
875
875
  let archivedCount = null;
876
876
  let threads = /* @__PURE__ */ new Map();
877
877
  let activeConversationId = null;
878
+ let conversationReadFailures = /* @__PURE__ */ new Map();
878
879
  const listeners = /* @__PURE__ */ new Set();
879
880
  let cached = null;
880
881
  function snapshot() {
@@ -887,7 +888,8 @@ function createMessagingStore() {
887
888
  activeConversationId,
888
889
  totalUnreadConversations: conversations.filter((item) => item.unreadCount > 0).length,
889
890
  archiveFilter,
890
- archivedCount
891
+ archivedCount,
892
+ conversationReadFailures
891
893
  };
892
894
  return cached;
893
895
  }
@@ -971,6 +973,14 @@ function createMessagingStore() {
971
973
  conversations = normalizeConversations(conversations);
972
974
  emit();
973
975
  },
976
+ setConversationReadFailure(id, failure) {
977
+ if (failure === null && !conversationReadFailures.has(id)) return;
978
+ const next = new Map(conversationReadFailures);
979
+ if (failure === null) next.delete(id);
980
+ else next.set(id, failure);
981
+ conversationReadFailures = next;
982
+ emit();
983
+ },
974
984
  setThread(id, messages, args = {}) {
975
985
  writeThread({
976
986
  conversationId: id,
@@ -1276,11 +1286,26 @@ function createMessagingEngine(options) {
1276
1286
  },
1277
1287
  async openConversation(id) {
1278
1288
  store.setActiveConversation(id);
1289
+ store.setConversationReadFailure(id, null);
1279
1290
  try {
1280
1291
  const page = await repository.listMessages(id, { limit: messagePageSize });
1292
+ if (page.items.length === 0) {
1293
+ await repository.getConversation(id);
1294
+ }
1281
1295
  store.setThread(id, page.items, { hasMoreOlder: page.hasMore });
1282
1296
  } catch (error) {
1283
- reportError(error, "openConversation");
1297
+ const normalized = normalizeMessagingError(error, "openConversation");
1298
+ const unavailable = normalized.code === "not-found" || normalized.code === "forbidden";
1299
+ store.setConversationReadFailure(id, { error: normalized, unavailable });
1300
+ if (unavailable) {
1301
+ report({
1302
+ level: "warn",
1303
+ message: normalized.message,
1304
+ remedy: normalized.remedy
1305
+ });
1306
+ return;
1307
+ }
1308
+ reportError(normalized, "openConversation");
1284
1309
  }
1285
1310
  if (openChannels.has(id) || disposed) return;
1286
1311
  const handle = manager.open({
@@ -2393,6 +2418,7 @@ function useConversation(id) {
2393
2418
  }, []);
2394
2419
  const thread = id === null ? null : snapshot?.threads.get(id) ?? null;
2395
2420
  const summary = id === null ? null : snapshot?.conversations.find((item) => item.conversation.id === id) ?? null;
2421
+ const failure = id === null ? null : snapshot?.conversationReadFailures.get(id) ?? null;
2396
2422
  const pending = useMemo2(() => {
2397
2423
  void outboxTick;
2398
2424
  return id === null ? [] : host?.engine.outbox.pendingFor(id) ?? [];
@@ -2402,7 +2428,9 @@ function useConversation(id) {
2402
2428
  thread,
2403
2429
  messages: thread?.messages ?? [],
2404
2430
  participants: summary?.participants ?? [],
2405
- isLoading: id !== null && thread === null,
2431
+ isLoading: id !== null && thread === null && failure === null,
2432
+ error: failure?.error ?? null,
2433
+ unavailable: failure?.unavailable ?? false,
2406
2434
  hasMoreOlder: thread?.hasMoreOlder ?? false,
2407
2435
  loadOlder: () => {
2408
2436
  if (id !== null) void host?.engine.loadOlderMessages(id);
@@ -3189,7 +3217,19 @@ function ConversationView(props) {
3189
3217
  }
3190
3218
  )
3191
3219
  ] }) : null,
3192
- /* @__PURE__ */ jsx4("div", { className: "mx-msg__scroll", ref: scrollRef, children: conversation.isLoading ? /* @__PURE__ */ jsx4(ConversationSkeleton, { rows: 4 }) : messages.length === 0 ? /* @__PURE__ */ jsx4(EmptyState, { title: "No messages yet", body: "Say something to get started." }) : /* @__PURE__ */ jsxs2("div", { className: "mx-msg__messages", children: [
3220
+ /* @__PURE__ */ jsx4("div", { className: "mx-msg__scroll", ref: scrollRef, children: conversation.isLoading ? /* @__PURE__ */ jsx4(ConversationSkeleton, { rows: 4 }) : conversation.unavailable ? /* @__PURE__ */ jsx4(
3221
+ EmptyState,
3222
+ {
3223
+ title: "Conversation unavailable",
3224
+ body: "It doesn't exist, or you aren't a member of it."
3225
+ }
3226
+ ) : conversation.error !== null && messages.length === 0 ? /* @__PURE__ */ jsx4(
3227
+ EmptyState,
3228
+ {
3229
+ title: "Couldn't load this conversation",
3230
+ body: "Check your connection, then open it again."
3231
+ }
3232
+ ) : messages.length === 0 ? /* @__PURE__ */ jsx4(EmptyState, { title: "No messages yet", body: "Say something to get started." }) : /* @__PURE__ */ jsxs2("div", { className: "mx-msg__messages", children: [
3193
3233
  conversation.hasMoreOlder ? /* @__PURE__ */ jsx4(
3194
3234
  "button",
3195
3235
  {