@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/CHANGELOG.md +40 -0
- package/dist/index.cjs +41 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +41 -10
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +77 -24
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +21 -2
- package/dist/react.d.ts +21 -2
- package/dist/react.js +83 -25
- package/dist/react.js.map +1 -1
- package/package.json +2 -2
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
|
@@ -1211,6 +1211,11 @@ function createMessagingEngine(options) {
|
|
|
1211
1211
|
if (openChannels.has(id) || disposed) return;
|
|
1212
1212
|
const handle = manager.open({
|
|
1213
1213
|
topic: conversationTopic(id),
|
|
1214
|
+
// Presence callbacks are JOIN-TIME in supabase-js. Declare the
|
|
1215
|
+
// read-only room shape on the first holder (the engine) so the
|
|
1216
|
+
// composer/typist/online hooks can attach without forcing a rebuild
|
|
1217
|
+
// after this durable channel has already subscribed.
|
|
1218
|
+
presence: { publish: false, state: {} },
|
|
1214
1219
|
postgresChanges: [
|
|
1215
1220
|
{
|
|
1216
1221
|
event: "*",
|
|
@@ -1956,18 +1961,20 @@ function groupMessages(messages, args = {}) {
|
|
|
1956
1961
|
let current = null;
|
|
1957
1962
|
let previousDay = null;
|
|
1958
1963
|
for (const message of messages) {
|
|
1964
|
+
const actorKey = args.actorKey?.(message) ?? `principal:${message.senderId}`;
|
|
1959
1965
|
const day = message.createdAt.slice(0, 10);
|
|
1960
1966
|
const startsNewDay = day !== previousDay;
|
|
1961
1967
|
previousDay = day;
|
|
1962
1968
|
const last = current?.messages.at(-1);
|
|
1963
1969
|
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) {
|
|
1970
|
+
if (current !== null && current.senderId === message.senderId && current.actorKey === actorKey && withinWindow && !startsNewDay) {
|
|
1965
1971
|
current.messages.push(message);
|
|
1966
1972
|
continue;
|
|
1967
1973
|
}
|
|
1968
1974
|
if (current !== null) groups.push(current);
|
|
1969
1975
|
current = {
|
|
1970
1976
|
senderId: message.senderId,
|
|
1977
|
+
actorKey,
|
|
1971
1978
|
messages: [message],
|
|
1972
1979
|
dateSeparator: startsNewDay ? formatDateSeparator(message.createdAt, now, args.locale) : null
|
|
1973
1980
|
};
|
|
@@ -2285,23 +2292,47 @@ function useMessageAction(message) {
|
|
|
2285
2292
|
}
|
|
2286
2293
|
|
|
2287
2294
|
// src/react/components.tsx
|
|
2288
|
-
import {
|
|
2295
|
+
import {
|
|
2296
|
+
useEffect as useEffect3,
|
|
2297
|
+
useMemo as useMemo3,
|
|
2298
|
+
useRef as useRef3,
|
|
2299
|
+
useState as useState2
|
|
2300
|
+
} from "react";
|
|
2289
2301
|
|
|
2290
2302
|
// src/core/actor.ts
|
|
2291
2303
|
function readActorHint(metadata) {
|
|
2292
|
-
const
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2304
|
+
const envelope = metadata;
|
|
2305
|
+
const raw = envelope["actor"];
|
|
2306
|
+
if (typeof raw === "object" && raw !== null && !Array.isArray(raw)) {
|
|
2307
|
+
const record = raw;
|
|
2308
|
+
const agentId = record["agentId"] ?? record["agent_id"];
|
|
2309
|
+
if (typeof agentId !== "string" || agentId.length === 0) return null;
|
|
2310
|
+
const name2 = record["agentName"] ?? record["agent_name"];
|
|
2311
|
+
const avatar2 = record["agentAvatarUrl"] ?? record["agent_avatar_url"];
|
|
2312
|
+
return {
|
|
2313
|
+
agentId,
|
|
2314
|
+
showPrincipalAttribution: true,
|
|
2315
|
+
...typeof name2 === "string" && name2.length > 0 ? { agentName: name2 } : {},
|
|
2316
|
+
...typeof avatar2 === "string" && avatar2.length > 0 ? { agentAvatarUrl: avatar2 } : {}
|
|
2317
|
+
};
|
|
2318
|
+
}
|
|
2319
|
+
const actorKind = envelope["actor_kind"] ?? envelope["actorKind"];
|
|
2320
|
+
if (actorKind !== "agent") return null;
|
|
2321
|
+
const id = envelope["actor_id"] ?? envelope["actorId"];
|
|
2322
|
+
const name = envelope["actor_label"] ?? envelope["actorLabel"];
|
|
2323
|
+
const avatar = envelope["actor_avatar_url"] ?? envelope["actorAvatarUrl"];
|
|
2299
2324
|
return {
|
|
2300
|
-
|
|
2325
|
+
showPrincipalAttribution: false,
|
|
2326
|
+
...typeof id === "string" && id.length > 0 ? { agentId: id } : {},
|
|
2301
2327
|
...typeof name === "string" && name.length > 0 ? { agentName: name } : {},
|
|
2302
2328
|
...typeof avatar === "string" && avatar.length > 0 ? { agentAvatarUrl: avatar } : {}
|
|
2303
2329
|
};
|
|
2304
2330
|
}
|
|
2331
|
+
function effectiveActorKey(message) {
|
|
2332
|
+
const hint = readActorHint(message.metadata);
|
|
2333
|
+
if (hint === null) return `principal:${message.senderId}`;
|
|
2334
|
+
return `agent:${hint.agentId ?? hint.agentName ?? "anonymous"}`;
|
|
2335
|
+
}
|
|
2305
2336
|
function resolveActor(message, sender) {
|
|
2306
2337
|
const hint = readActorHint(message.metadata);
|
|
2307
2338
|
const humanName = sender?.displayName ?? message.senderId;
|
|
@@ -2313,7 +2344,11 @@ function resolveActor(message, sender) {
|
|
|
2313
2344
|
displayName: hint.agentName ?? "Agent",
|
|
2314
2345
|
avatarUrl: hint.agentAvatarUrl ?? null,
|
|
2315
2346
|
isAgent: true,
|
|
2316
|
-
|
|
2347
|
+
// The nested envelope explicitly models an agent acting on behalf of a
|
|
2348
|
+
// session principal. Platform event rows use the flat actor envelope as
|
|
2349
|
+
// the complete presentation identity; surfacing their audit writer as
|
|
2350
|
+
// "via Human" wrongly re-attaches that person to an automated event.
|
|
2351
|
+
onBehalfOfName: hint.showPrincipalAttribution ? humanName : null,
|
|
2317
2352
|
principalUserId: message.senderId
|
|
2318
2353
|
};
|
|
2319
2354
|
}
|
|
@@ -2697,7 +2732,7 @@ function ConversationView(props) {
|
|
|
2697
2732
|
);
|
|
2698
2733
|
const anyOnline = others.some((participant) => online.has(participant.userId));
|
|
2699
2734
|
return /* @__PURE__ */ jsxs2("div", { className: `mx-msg__thread${props.className !== void 0 ? ` ${props.className}` : ""}`, children: [
|
|
2700
|
-
/* @__PURE__ */ jsxs2("header", { className: "mx-msg__header", children: [
|
|
2735
|
+
props.showHeader !== false ? /* @__PURE__ */ jsxs2("header", { className: "mx-msg__header", children: [
|
|
2701
2736
|
props.onBack !== void 0 ? /* @__PURE__ */ jsx4(
|
|
2702
2737
|
"button",
|
|
2703
2738
|
{
|
|
@@ -2732,8 +2767,8 @@ function ConversationView(props) {
|
|
|
2732
2767
|
children: /* @__PURE__ */ jsx4(UsersIcon, {})
|
|
2733
2768
|
}
|
|
2734
2769
|
) : null })
|
|
2735
|
-
] }),
|
|
2736
|
-
ai.available.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ jsxs2(
|
|
2770
|
+
] }) : null,
|
|
2771
|
+
props.showAi !== false && ai.available.length > 0 ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__ai-bar", children: ai.available.map((capability) => /* @__PURE__ */ jsxs2(
|
|
2737
2772
|
"button",
|
|
2738
2773
|
{
|
|
2739
2774
|
type: "button",
|
|
@@ -2747,7 +2782,7 @@ function ConversationView(props) {
|
|
|
2747
2782
|
},
|
|
2748
2783
|
capability
|
|
2749
2784
|
)) }) : 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: [
|
|
2785
|
+
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
2786
|
/* @__PURE__ */ jsx4("span", { className: "mx-msg__ai-output-label", children: ai.activeCapability !== null ? `${AI_LABELS[ai.activeCapability]}\u2026` : "Working\u2026" }),
|
|
2752
2787
|
/* @__PURE__ */ jsx4(
|
|
2753
2788
|
"span",
|
|
@@ -2756,7 +2791,7 @@ function ConversationView(props) {
|
|
|
2756
2791
|
style: { display: "block", height: 11, width: "72%" }
|
|
2757
2792
|
}
|
|
2758
2793
|
)
|
|
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: [
|
|
2794
|
+
] }) }) : 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
2795
|
ai.result.text,
|
|
2761
2796
|
/* @__PURE__ */ jsx4(
|
|
2762
2797
|
"button",
|
|
@@ -2781,26 +2816,24 @@ function ConversationView(props) {
|
|
|
2781
2816
|
children: "Load earlier messages"
|
|
2782
2817
|
}
|
|
2783
2818
|
) : null,
|
|
2784
|
-
groupMessages(messages).map((group) => {
|
|
2819
|
+
groupMessages(messages, { actorKey: effectiveActorKey }).map((group) => {
|
|
2785
2820
|
const first = group.messages[0];
|
|
2786
2821
|
if (first === void 0) return null;
|
|
2787
|
-
const isMine = group.senderId === selfId;
|
|
2788
2822
|
const sender = conversation.participants.find(
|
|
2789
2823
|
(participant) => participant.userId === group.senderId
|
|
2790
2824
|
) ?? null;
|
|
2825
|
+
const actor = resolveActor(first, sender);
|
|
2826
|
+
const isMine = group.senderId === selfId && !actor.isAgent;
|
|
2791
2827
|
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
2792
2828
|
group.dateSeparator !== null ? /* @__PURE__ */ jsx4("div", { className: "mx-msg__day", children: group.dateSeparator }) : null,
|
|
2793
2829
|
/* @__PURE__ */ jsx4(
|
|
2794
2830
|
MessageGroupView,
|
|
2795
2831
|
{
|
|
2796
2832
|
messages: group.messages,
|
|
2797
|
-
|
|
2833
|
+
actor,
|
|
2798
2834
|
isMine,
|
|
2799
2835
|
onRetry: conversation.retry,
|
|
2800
2836
|
onReply: composer.setReplyTo,
|
|
2801
|
-
pendingIds: new Set(
|
|
2802
|
-
conversation.pending.filter((entry) => entry.state === "failed").map((entry) => entry.clientMessageId)
|
|
2803
|
-
),
|
|
2804
2837
|
failedEntryIdByClientId: new Map(
|
|
2805
2838
|
conversation.pending.map((entry) => [entry.clientMessageId, entry.id])
|
|
2806
2839
|
)
|
|
@@ -2813,13 +2846,20 @@ function ConversationView(props) {
|
|
|
2813
2846
|
/* @__PURE__ */ jsx4(TypingDots, {}),
|
|
2814
2847
|
typists.label
|
|
2815
2848
|
] }) : null }),
|
|
2816
|
-
/* @__PURE__ */ jsx4(
|
|
2849
|
+
/* @__PURE__ */ jsx4(
|
|
2850
|
+
ComposerView,
|
|
2851
|
+
{
|
|
2852
|
+
composer,
|
|
2853
|
+
disabled: false,
|
|
2854
|
+
...props.renderComposerInput !== void 0 ? { renderInput: props.renderComposerInput } : {}
|
|
2855
|
+
}
|
|
2856
|
+
)
|
|
2817
2857
|
] });
|
|
2818
2858
|
}
|
|
2819
2859
|
function MessageGroupView(props) {
|
|
2820
2860
|
const first = props.messages[0];
|
|
2821
2861
|
if (first === void 0) return null;
|
|
2822
|
-
const actor =
|
|
2862
|
+
const actor = props.actor;
|
|
2823
2863
|
return /* @__PURE__ */ jsxs2("div", { className: `mx-msg__group${props.isMine ? " mx-msg__group--mine" : ""}`, children: [
|
|
2824
2864
|
/* @__PURE__ */ jsx4(
|
|
2825
2865
|
Avatar,
|
|
@@ -3006,7 +3046,24 @@ function ComposerView(props) {
|
|
|
3006
3046
|
}
|
|
3007
3047
|
)
|
|
3008
3048
|
] }) : null,
|
|
3009
|
-
|
|
3049
|
+
props.renderInput !== void 0 ? props.renderInput({
|
|
3050
|
+
value: composer.value,
|
|
3051
|
+
disabled: props.disabled,
|
|
3052
|
+
canSend: composer.canSend,
|
|
3053
|
+
placeholder: "Write a reply\u2026",
|
|
3054
|
+
onChange: (value) => {
|
|
3055
|
+
composer.setValue(value);
|
|
3056
|
+
composer.onKeystroke();
|
|
3057
|
+
},
|
|
3058
|
+
onKeyDown: (event) => {
|
|
3059
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
3060
|
+
const isTouch = typeof globalThis.matchMedia === "function" && globalThis.matchMedia("(pointer: coarse)").matches;
|
|
3061
|
+
if (isTouch) return;
|
|
3062
|
+
event.preventDefault();
|
|
3063
|
+
composer.send();
|
|
3064
|
+
},
|
|
3065
|
+
onSubmit: composer.send
|
|
3066
|
+
}) : /* @__PURE__ */ jsxs2("div", { className: "mx-msg__composer-row", children: [
|
|
3010
3067
|
/* @__PURE__ */ jsx4(
|
|
3011
3068
|
"textarea",
|
|
3012
3069
|
{
|
|
@@ -3137,6 +3194,7 @@ export {
|
|
|
3137
3194
|
createOutbox,
|
|
3138
3195
|
createReadCache,
|
|
3139
3196
|
createWebOutboxStorage,
|
|
3197
|
+
effectiveActorKey,
|
|
3140
3198
|
extractReferences,
|
|
3141
3199
|
formatConversationTime,
|
|
3142
3200
|
formatDateSeparator,
|