@stigmer/react 3.7.0 → 3.9.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/attachment/AttachmentChipList.d.ts.map +1 -1
- package/attachment/AttachmentChipList.js +30 -1
- package/attachment/AttachmentChipList.js.map +1 -1
- package/attachment/attachment-utils.d.ts +11 -0
- package/attachment/attachment-utils.d.ts.map +1 -1
- package/attachment/attachment-utils.js +23 -0
- package/attachment/attachment-utils.js.map +1 -1
- package/attachment/clipboard.d.ts +51 -0
- package/attachment/clipboard.d.ts.map +1 -0
- package/attachment/clipboard.js +89 -0
- package/attachment/clipboard.js.map +1 -0
- package/attachment/index.d.ts +6 -1
- package/attachment/index.d.ts.map +1 -1
- package/attachment/index.js +4 -1
- package/attachment/index.js.map +1 -1
- package/attachment/prepare-image.d.ts +43 -0
- package/attachment/prepare-image.d.ts.map +1 -0
- package/attachment/prepare-image.js +162 -0
- package/attachment/prepare-image.js.map +1 -0
- package/attachment/useAttachments.d.ts.map +1 -1
- package/attachment/useAttachments.js +23 -3
- package/attachment/useAttachments.js.map +1 -1
- package/attachment/vision-fit.d.ts +50 -0
- package/attachment/vision-fit.d.ts.map +1 -0
- package/attachment/vision-fit.js +76 -0
- package/attachment/vision-fit.js.map +1 -0
- package/channel/AgentChannelsPanel.d.ts.map +1 -1
- package/channel/AgentChannelsPanel.js +21 -2
- package/channel/AgentChannelsPanel.js.map +1 -1
- package/channel/ChannelConversationsDialog.d.ts +12 -4
- package/channel/ChannelConversationsDialog.d.ts.map +1 -1
- package/channel/ChannelConversationsDialog.js +18 -24
- package/channel/ChannelConversationsDialog.js.map +1 -1
- package/channel/providers.d.ts +23 -0
- package/channel/providers.d.ts.map +1 -1
- package/channel/providers.js +4 -0
- package/channel/providers.js.map +1 -1
- package/channel/useSaveAgentChannel.d.ts +5 -4
- package/channel/useSaveAgentChannel.d.ts.map +1 -1
- package/channel/useSaveAgentChannel.js +18 -4
- package/channel/useSaveAgentChannel.js.map +1 -1
- package/composer/ComposerToolbar.d.ts +1 -1
- package/composer/ComposerToolbar.d.ts.map +1 -1
- package/composer/SessionComposer.d.ts +4 -2
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +51 -5
- package/composer/SessionComposer.js.map +1 -1
- package/conversation/ConversationAttentionBanner.d.ts +22 -0
- package/conversation/ConversationAttentionBanner.d.ts.map +1 -0
- package/conversation/ConversationAttentionBanner.js +25 -0
- package/conversation/ConversationAttentionBanner.js.map +1 -0
- package/conversation/ConversationComposer.d.ts +41 -0
- package/conversation/ConversationComposer.d.ts.map +1 -0
- package/conversation/ConversationComposer.js +57 -0
- package/conversation/ConversationComposer.js.map +1 -0
- package/conversation/ConversationControlBanner.d.ts +52 -0
- package/conversation/ConversationControlBanner.d.ts.map +1 -0
- package/conversation/ConversationControlBanner.js +59 -0
- package/conversation/ConversationControlBanner.js.map +1 -0
- package/conversation/ConversationListPane.d.ts +68 -0
- package/conversation/ConversationListPane.d.ts.map +1 -0
- package/conversation/ConversationListPane.js +120 -0
- package/conversation/ConversationListPane.js.map +1 -0
- package/conversation/ConversationTimelineView.d.ts +46 -0
- package/conversation/ConversationTimelineView.d.ts.map +1 -0
- package/conversation/ConversationTimelineView.js +166 -0
- package/conversation/ConversationTimelineView.js.map +1 -0
- package/conversation/ConversationsWorkbench.d.ts +63 -0
- package/conversation/ConversationsWorkbench.d.ts.map +1 -0
- package/conversation/ConversationsWorkbench.js +165 -0
- package/conversation/ConversationsWorkbench.js.map +1 -0
- package/conversation/conversationPresentation.d.ts +137 -0
- package/conversation/conversationPresentation.d.ts.map +1 -0
- package/conversation/conversationPresentation.js +230 -0
- package/conversation/conversationPresentation.js.map +1 -0
- package/conversation/index.d.ts +26 -0
- package/conversation/index.d.ts.map +1 -0
- package/conversation/index.js +14 -0
- package/conversation/index.js.map +1 -0
- package/conversation/polling.d.ts +39 -0
- package/conversation/polling.d.ts.map +1 -0
- package/conversation/polling.js +39 -0
- package/conversation/polling.js.map +1 -0
- package/conversation/useConversation.d.ts +61 -0
- package/conversation/useConversation.d.ts.map +1 -0
- package/conversation/useConversation.js +153 -0
- package/conversation/useConversation.js.map +1 -0
- package/conversation/useConversationList.d.ts +98 -0
- package/conversation/useConversationList.d.ts.map +1 -0
- package/conversation/useConversationList.js +200 -0
- package/conversation/useConversationList.js.map +1 -0
- package/conversation/useConversationParticipation.d.ts +63 -0
- package/conversation/useConversationParticipation.d.ts.map +1 -0
- package/conversation/useConversationParticipation.js +84 -0
- package/conversation/useConversationParticipation.js.map +1 -0
- package/conversation/useConversationTimeline.d.ts +71 -0
- package/conversation/useConversationTimeline.d.ts.map +1 -0
- package/conversation/useConversationTimeline.js +152 -0
- package/conversation/useConversationTimeline.js.map +1 -0
- package/conversation/useConversationsWantsHumanCount.d.ts +42 -0
- package/conversation/useConversationsWantsHumanCount.d.ts.map +1 -0
- package/conversation/useConversationsWantsHumanCount.js +40 -0
- package/conversation/useConversationsWantsHumanCount.js.map +1 -0
- package/index.d.ts +6 -2
- package/index.d.ts.map +1 -1
- package/index.js +11 -2
- package/index.js.map +1 -1
- package/internal/tooltip.d.ts.map +1 -1
- package/internal/tooltip.js +7 -1
- package/internal/tooltip.js.map +1 -1
- package/internal/useAutoScroll.d.ts +25 -4
- package/internal/useAutoScroll.d.ts.map +1 -1
- package/internal/useAutoScroll.js +55 -15
- package/internal/useAutoScroll.js.map +1 -1
- package/internal/useFetch.d.ts.map +1 -1
- package/internal/useFetch.js +14 -4
- package/internal/useFetch.js.map +1 -1
- package/models/ModelSelector.d.ts +24 -5
- package/models/ModelSelector.d.ts.map +1 -1
- package/models/ModelSelector.js +31 -9
- package/models/ModelSelector.js.map +1 -1
- package/models/registry.d.ts +3 -2
- package/models/registry.d.ts.map +1 -1
- package/models/registry.js.map +1 -1
- package/models/service-tier.d.ts +1 -1
- package/models/service-tier.d.ts.map +1 -1
- package/models/service-tier.js +1 -1
- package/models/service-tier.js.map +1 -1
- package/package.json +4 -4
- package/schedule/ScheduleDetailView.js +1 -1
- package/schedule/ScheduleDetailView.js.map +1 -1
- package/schedule/ScheduleForm.d.ts.map +1 -1
- package/schedule/ScheduleForm.js +7 -6
- package/schedule/ScheduleForm.js.map +1 -1
- package/sharing/useSaveAgentShare.d.ts +10 -1
- package/sharing/useSaveAgentShare.d.ts.map +1 -1
- package/sharing/useSaveAgentShare.js +9 -0
- package/sharing/useSaveAgentShare.js.map +1 -1
- package/sidebar/WorkspaceSidebar.d.ts +12 -4
- package/sidebar/WorkspaceSidebar.d.ts.map +1 -1
- package/sidebar/WorkspaceSidebar.js +19 -7
- package/sidebar/WorkspaceSidebar.js.map +1 -1
- package/src/attachment/AttachmentChipList.tsx +45 -1
- package/src/attachment/__tests__/AttachmentChipList.test.tsx +103 -0
- package/src/attachment/__tests__/attachment-utils.test.ts +54 -0
- package/src/attachment/__tests__/clipboard.test.ts +110 -0
- package/src/attachment/__tests__/prepare-image.browser.test.ts +166 -0
- package/src/attachment/__tests__/prepare-image.test.ts +32 -0
- package/src/attachment/__tests__/vision-fit.test.ts +93 -0
- package/src/attachment/attachment-utils.ts +27 -0
- package/src/attachment/clipboard.ts +102 -0
- package/src/attachment/index.ts +13 -0
- package/src/attachment/prepare-image.ts +179 -0
- package/src/attachment/useAttachments.ts +26 -2
- package/src/attachment/vision-fit.ts +90 -0
- package/src/channel/AgentChannelsPanel.tsx +33 -2
- package/src/channel/ChannelConversationsDialog.tsx +22 -25
- package/src/channel/__tests__/AgentChannelsPanel.test.tsx +36 -5
- package/src/channel/__tests__/ChannelConversationsDialog.test.tsx +38 -1
- package/src/channel/__tests__/useSaveAgentChannel.test.tsx +26 -0
- package/src/channel/providers.ts +27 -0
- package/src/channel/useSaveAgentChannel.ts +18 -4
- package/src/composer/ComposerToolbar.tsx +1 -1
- package/src/composer/SessionComposer.tsx +75 -6
- package/src/composer/__tests__/SessionComposer-paste.test.tsx +263 -0
- package/src/composer/__tests__/SessionComposer-serviceTier.test.tsx +4 -3
- package/src/composer/__tests__/SessionComposer-uploadGate.test.tsx +239 -0
- package/src/conversation/ConversationAttentionBanner.tsx +77 -0
- package/src/conversation/ConversationComposer.tsx +156 -0
- package/src/conversation/ConversationControlBanner.tsx +193 -0
- package/src/conversation/ConversationListPane.tsx +459 -0
- package/src/conversation/ConversationTimelineView.tsx +435 -0
- package/src/conversation/ConversationsWorkbench.tsx +378 -0
- package/src/conversation/__tests__/ConversationAttentionBanner.test.tsx +82 -0
- package/src/conversation/__tests__/ConversationComposer.test.tsx +160 -0
- package/src/conversation/__tests__/ConversationControlBanner.test.tsx +190 -0
- package/src/conversation/__tests__/ConversationListPane.test.tsx +372 -0
- package/src/conversation/__tests__/ConversationTimelineView.layout.test.tsx +160 -0
- package/src/conversation/__tests__/ConversationTimelineView.test.tsx +405 -0
- package/src/conversation/__tests__/ConversationsWorkbench.test.tsx +860 -0
- package/src/conversation/__tests__/a11y/conversation-surfaces.a11y.test.tsx +235 -0
- package/src/conversation/__tests__/a11y/harness.tsx +100 -0
- package/src/conversation/__tests__/conversation-tooltips.layout.test.tsx +167 -0
- package/src/conversation/__tests__/conversationPollingComposition.test.tsx +138 -0
- package/src/conversation/__tests__/conversationPresentation.test.ts +289 -0
- package/src/conversation/__tests__/useConversation.test.tsx +243 -0
- package/src/conversation/__tests__/useConversationList.test.tsx +492 -0
- package/src/conversation/__tests__/useConversationParticipation.test.tsx +190 -0
- package/src/conversation/__tests__/useConversationTimeline.test.tsx +258 -0
- package/src/conversation/__tests__/useConversationsWantsHumanCount.test.tsx +102 -0
- package/src/conversation/conversationPresentation.ts +305 -0
- package/src/conversation/index.ts +80 -0
- package/src/conversation/polling.ts +41 -0
- package/src/conversation/useConversation.ts +221 -0
- package/src/conversation/useConversationList.ts +328 -0
- package/src/conversation/useConversationParticipation.ts +178 -0
- package/src/conversation/useConversationTimeline.ts +244 -0
- package/src/conversation/useConversationsWantsHumanCount.ts +86 -0
- package/src/index.ts +78 -1
- package/src/internal/__tests__/fake-timer-slices.ts +29 -0
- package/src/internal/__tests__/useAutoScroll.layout.test.tsx +143 -0
- package/src/internal/__tests__/useAutoScroll.test.tsx +62 -5
- package/src/internal/__tests__/useFetch-poll-under-render-pressure.test.tsx +79 -0
- package/src/internal/tooltip.tsx +6 -1
- package/src/internal/useAutoScroll.ts +66 -20
- package/src/internal/useFetch.ts +15 -4
- package/src/models/ModelSelector.tsx +81 -49
- package/src/models/__tests__/ModelSelector-serviceTier.test.tsx +105 -21
- package/src/models/registry.ts +3 -2
- package/src/models/service-tier.ts +1 -1
- package/src/schedule/ScheduleDetailView.tsx +1 -1
- package/src/schedule/ScheduleForm.tsx +7 -6
- package/src/schedule/__tests__/scheduleCreation.test.tsx +2 -2
- package/src/sharing/__tests__/useSaveAgentShare.test.tsx +55 -1
- package/src/sharing/__tests__/useShareToolReadiness.test.tsx +1 -0
- package/src/sharing/useSaveAgentShare.ts +19 -1
- package/src/sidebar/WorkspaceSidebar.tsx +62 -3
- package/src/sidebar/__tests__/WorkspaceSidebar.test.tsx +56 -1
- package/styles.css +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AgentChannel } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/api_pb";
|
|
2
|
+
import { ChannelConversationListFilter, type ChannelConversation } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/conversation_io_pb";
|
|
3
|
+
/** The (channel, key) pair identifying one conversation. */
|
|
4
|
+
export interface ConversationIdentity {
|
|
5
|
+
readonly agentChannelId: string;
|
|
6
|
+
readonly conversationKey: string;
|
|
7
|
+
}
|
|
8
|
+
/** Props for {@link ConversationListPane}. */
|
|
9
|
+
export interface ConversationListPaneProps {
|
|
10
|
+
/** Conversations, newest activity first (from `useConversationList`). */
|
|
11
|
+
readonly conversations: readonly ChannelConversation[];
|
|
12
|
+
/** `true` only during the first load. */
|
|
13
|
+
readonly isLoading: boolean;
|
|
14
|
+
/** Error from the list read, or `null`. */
|
|
15
|
+
readonly error: Error | null;
|
|
16
|
+
/** `true` while more conversations exist beyond what is loaded. */
|
|
17
|
+
readonly hasMore: boolean;
|
|
18
|
+
/** Load the next page. */
|
|
19
|
+
readonly loadMore: () => void;
|
|
20
|
+
/** `true` while the next page is in flight. */
|
|
21
|
+
readonly isLoadingMore: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The org's channels the caller can view (from
|
|
24
|
+
* `useOrgAgentChannelList`) — the channel filter's options, each
|
|
25
|
+
* row's provider identity, and the honest empty-state distinction
|
|
26
|
+
* (no channel access vs no conversations yet).
|
|
27
|
+
*/
|
|
28
|
+
readonly channels: readonly AgentChannel[];
|
|
29
|
+
/** Current channel filter; empty string means all channels. */
|
|
30
|
+
readonly channelFilter: string;
|
|
31
|
+
/** Called when the user picks a channel filter. */
|
|
32
|
+
readonly onChannelFilterChange: (agentChannelId: string) => void;
|
|
33
|
+
/**
|
|
34
|
+
* The server-evaluated predicate filter currently applied to the list
|
|
35
|
+
* (DD-011 D-g — the same predicate the nav badge counts, so the
|
|
36
|
+
* filtered list always matches the number that opened it). Defaults
|
|
37
|
+
* to unspecified (all conversations).
|
|
38
|
+
*/
|
|
39
|
+
readonly filter?: ChannelConversationListFilter;
|
|
40
|
+
/**
|
|
41
|
+
* Called when the user picks a predicate filter. The control renders
|
|
42
|
+
* only when this is wired — a dead toggle over an unfiltered list
|
|
43
|
+
* would lie.
|
|
44
|
+
*/
|
|
45
|
+
readonly onFilterChange?: (filter: ChannelConversationListFilter) => void;
|
|
46
|
+
/** The open conversation, for row highlighting. `null` when none. */
|
|
47
|
+
readonly selected: ConversationIdentity | null;
|
|
48
|
+
/** Called when the user opens a conversation. */
|
|
49
|
+
readonly onSelect: (conversation: ChannelConversation) => void;
|
|
50
|
+
/** Frozen instant for deterministic hosts (tests, documentation tours). */
|
|
51
|
+
readonly now?: Date;
|
|
52
|
+
/** Additional classes for the pane container. */
|
|
53
|
+
readonly className?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The conversation inbox pane (channel-conversations T04): every
|
|
57
|
+
* conversation across the org's channels, newest activity first, with
|
|
58
|
+
* control, attention, and awaiting-reply indicators.
|
|
59
|
+
*
|
|
60
|
+
* Presentational — pair with `useConversationList` and
|
|
61
|
+
* `useOrgAgentChannelList`, or compose via `ConversationsWorkbench`.
|
|
62
|
+
* The wants-human filter is SERVER-evaluated (DD-011 D-g closed the API
|
|
63
|
+
* gap that T04 D1 cited): a client-side tab over one fetched page would
|
|
64
|
+
* silently lie across pages, so the pane only reports the choice and the
|
|
65
|
+
* list hook sends it to the server.
|
|
66
|
+
*/
|
|
67
|
+
export declare function ConversationListPane({ conversations, isLoading, error, hasMore, loadMore, isLoadingMore, channels, channelFilter, onChannelFilterChange, filter, onFilterChange, selected, onSelect, now, className, }: ConversationListPaneProps): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
//# sourceMappingURL=ConversationListPane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationListPane.d.ts","sourceRoot":"","sources":["../../src/conversation/ConversationListPane.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAC9F,OAAO,EACL,6BAA6B,EAE7B,KAAK,mBAAmB,EACzB,MAAM,uEAAuE,CAAC;AAiB/E,4DAA4D;AAC5D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,yBAAyB;IACxC,yEAAyE;IACzE,QAAQ,CAAC,aAAa,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACvD,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,qBAAqB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,6BAA6B,CAAC;IAChD;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,6BAA6B,KAAK,IAAI,CAAC;IAC1E,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC/C,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/D,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,aAAa,EACb,SAAS,EACT,KAAK,EACL,OAAO,EACP,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,aAAa,EACb,qBAAqB,EACrB,MAAmF,EACnF,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,SAAS,GACV,EAAE,yBAAyB,2CA2H3B"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useCallback, useRef } from "react";
|
|
4
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
5
|
+
import { MessageSquare, TriangleAlert, User } from "lucide-react";
|
|
6
|
+
import { cn } from "@stigmer/theme";
|
|
7
|
+
import { getUserMessage } from "@stigmer/sdk";
|
|
8
|
+
import { ChannelConversationListFilter, ConversationControl, } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/conversation_io_pb";
|
|
9
|
+
import { formatRelativeTime } from "../activity/format-relative-time.js";
|
|
10
|
+
import { channelProviderOf } from "../channel/providers.js";
|
|
11
|
+
import { Button } from "../button/Button.js";
|
|
12
|
+
import { EmptyState } from "../empty-state/EmptyState.js";
|
|
13
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../internal/tooltip.js";
|
|
14
|
+
import { awaitingIndicatorOf, conversationContactOf, conversationLabelOf, } from "./conversationPresentation.js";
|
|
15
|
+
/**
|
|
16
|
+
* The conversation inbox pane (channel-conversations T04): every
|
|
17
|
+
* conversation across the org's channels, newest activity first, with
|
|
18
|
+
* control, attention, and awaiting-reply indicators.
|
|
19
|
+
*
|
|
20
|
+
* Presentational — pair with `useConversationList` and
|
|
21
|
+
* `useOrgAgentChannelList`, or compose via `ConversationsWorkbench`.
|
|
22
|
+
* The wants-human filter is SERVER-evaluated (DD-011 D-g closed the API
|
|
23
|
+
* gap that T04 D1 cited): a client-side tab over one fetched page would
|
|
24
|
+
* silently lie across pages, so the pane only reports the choice and the
|
|
25
|
+
* list hook sends it to the server.
|
|
26
|
+
*/
|
|
27
|
+
export function ConversationListPane({ conversations, isLoading, error, hasMore, loadMore, isLoadingMore, channels, channelFilter, onChannelFilterChange, filter = ChannelConversationListFilter.channel_conversation_list_filter_unspecified, onFilterChange, selected, onSelect, now, className, }) {
|
|
28
|
+
const providerById = new Map(channels.map((channel) => [
|
|
29
|
+
channel.metadata?.id ?? "",
|
|
30
|
+
channelProviderOf(channel.spec?.providerConfig?.case),
|
|
31
|
+
]));
|
|
32
|
+
return (_jsxs("div", { "aria-label": "Conversation list", className: cn("flex min-h-0 flex-col", className), children: [(onFilterChange !== undefined || channels.length > 1) && (_jsxs("div", { className: "flex flex-col gap-2 border-b border-border px-3 py-2", children: [onFilterChange !== undefined && (_jsx(ConversationFilterToggle, { value: filter, onChange: onFilterChange })), channels.length > 1 && (_jsxs(_Fragment, { children: [_jsx("label", { className: "sr-only", htmlFor: "stgm-conversation-channel-filter", children: "Filter by channel" }), _jsxs("select", { id: "stgm-conversation-channel-filter", value: channelFilter, onChange: (e) => onChannelFilterChange(e.target.value), className: cn("w-full rounded-md border border-border bg-background px-2 py-1.5", "text-sm text-foreground", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"), children: [_jsx("option", { value: "", children: "All channels" }), channels.map((channel) => (_jsx("option", { value: channel.metadata?.id, children: channel.metadata?.name || channel.metadata?.slug }, channel.metadata?.id)))] })] }))] })), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto p-2", children: isLoading ? (_jsx(ListSkeleton, {})) : error ? (_jsx("p", { className: "px-2 py-6 text-center text-sm text-destructive", children: getUserMessage(error) })) : conversations.length === 0 ? (channels.length === 0 ? (_jsx(EmptyState, { variant: "first-use", icon: _jsx(MessageSquare, { className: "size-8" }), title: "No channels to watch", description: "Conversations arrive through an agent's channels. Connect a channel \u2014 or ask a channel owner for access \u2014 and customer conversations appear here." })) : filter === ChannelConversationListFilter.filter_wants_human ? (
|
|
33
|
+
// Its own empty state on purpose: under the filter, "No
|
|
34
|
+
// conversations yet — when a customer messages…" would lie
|
|
35
|
+
// to an org with a full inbox and nothing needing a person.
|
|
36
|
+
_jsx(EmptyState, { variant: "first-use", icon: _jsx(MessageSquare, { className: "size-8" }), title: "Nothing needs a human right now", description: "Conversations appear here when the agent asks for attention, or when a human-held conversation has a customer message awaiting a reply." })) : (_jsx(EmptyState, { variant: "first-use", icon: _jsx(MessageSquare, { className: "size-8" }), title: "No conversations yet", description: "When a customer messages one of your channels, their conversation appears here." }))) : (_jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsx("ul", { className: "space-y-0.5", children: conversations.map((conversation) => (_jsx(ConversationRow, { conversation: conversation, label: conversationLabelOf(conversation, providerById.get(conversation.agentChannelId)?.id ?? null), contact: conversationContactOf(conversation, providerById.get(conversation.agentChannelId)?.id ?? null), isSelected: selected?.agentChannelId === conversation.agentChannelId &&
|
|
37
|
+
selected?.conversationKey === conversation.conversationKey, onSelect: onSelect, now: now }, `${conversation.agentChannelId}:${conversation.conversationKey}`))) }) }), hasMore && (_jsx("div", { className: "flex justify-center py-2", children: _jsx(Button, { variant: "ghost", size: "xs", onClick: loadMore, disabled: isLoadingMore, children: isLoadingMore ? "Loading…" : "Show more" }) }))] })) })] }));
|
|
38
|
+
}
|
|
39
|
+
const FILTER_OPTIONS = [
|
|
40
|
+
{
|
|
41
|
+
value: ChannelConversationListFilter.channel_conversation_list_filter_unspecified,
|
|
42
|
+
label: "All",
|
|
43
|
+
ariaLabel: "All conversations",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
value: ChannelConversationListFilter.filter_wants_human,
|
|
47
|
+
label: "Needs human",
|
|
48
|
+
ariaLabel: "Conversations where a human action is wanted",
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* Segmented control for the server-evaluated list filter. Renders as a
|
|
53
|
+
* WAI-ARIA Radio Group with roving tabindex and arrow-key navigation —
|
|
54
|
+
* the `ScopeToggle` pattern (its second sighting; extract a shared
|
|
55
|
+
* primitive if a third segmented control appears).
|
|
56
|
+
*
|
|
57
|
+
* "Needs human" is exactly the nav badge's predicate (DD-011 D-f/D-g),
|
|
58
|
+
* so the number on the badge and the list this control opens can never
|
|
59
|
+
* disagree.
|
|
60
|
+
*/
|
|
61
|
+
function ConversationFilterToggle({ value, onChange, }) {
|
|
62
|
+
const optionRefs = useRef([]);
|
|
63
|
+
const handleSelect = useCallback((next) => {
|
|
64
|
+
if (next !== value)
|
|
65
|
+
onChange(next);
|
|
66
|
+
}, [value, onChange]);
|
|
67
|
+
const handleKeyDown = useCallback((e, index) => {
|
|
68
|
+
let nextIndex = null;
|
|
69
|
+
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
nextIndex = (index + 1) % FILTER_OPTIONS.length;
|
|
72
|
+
}
|
|
73
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
nextIndex = (index - 1 + FILTER_OPTIONS.length) % FILTER_OPTIONS.length;
|
|
76
|
+
}
|
|
77
|
+
if (nextIndex !== null) {
|
|
78
|
+
optionRefs.current[nextIndex]?.focus();
|
|
79
|
+
handleSelect(FILTER_OPTIONS[nextIndex].value);
|
|
80
|
+
}
|
|
81
|
+
}, [handleSelect]);
|
|
82
|
+
return (_jsx("div", { role: "radiogroup", "aria-label": "Conversation filter", className: "inline-flex self-start rounded-md bg-muted p-0.5", children: FILTER_OPTIONS.map((option, index) => {
|
|
83
|
+
const isSelected = value === option.value;
|
|
84
|
+
return (_jsx("button", { ref: (el) => {
|
|
85
|
+
optionRefs.current[index] = el;
|
|
86
|
+
}, type: "button", role: "radio", "aria-checked": isSelected, "aria-label": option.ariaLabel, tabIndex: isSelected ? 0 : -1, onClick: () => handleSelect(option.value), onKeyDown: (e) => handleKeyDown(e, index), className: cn("inline-flex cursor-pointer items-center rounded-sm px-2 py-1 text-xs font-medium transition-colors", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", isSelected
|
|
87
|
+
? "bg-background text-foreground shadow-sm"
|
|
88
|
+
: "text-muted-foreground hover:text-foreground"), children: option.label }, option.value));
|
|
89
|
+
}) }));
|
|
90
|
+
}
|
|
91
|
+
const ConversationRow = memo(function ConversationRow({ conversation, label, contact, isSelected, onSelect, now, }) {
|
|
92
|
+
const humanHeld = conversation.control === ConversationControl.control_human;
|
|
93
|
+
const awaiting = awaitingIndicatorOf(conversation);
|
|
94
|
+
const lastActivity = conversation.lastActivityAt
|
|
95
|
+
? timestampDate(conversation.lastActivityAt)
|
|
96
|
+
: null;
|
|
97
|
+
return (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onSelect(conversation), "aria-current": isSelected ? "true" : undefined, className: cn("flex w-full items-center gap-2.5 rounded-md px-2.5 py-2 text-left", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", isSelected ? "bg-primary-subtle" : "hover:bg-accent"), children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("p", { className: "truncate text-sm font-medium text-foreground", children: label }), conversation.needsAttention && (
|
|
98
|
+
// The reason rides the house tooltip (F-18). The trigger
|
|
99
|
+
// renders as a span — it sits INSIDE the row button, so a
|
|
100
|
+
// default (button) trigger would nest buttons — and stays
|
|
101
|
+
// out of the tab order; the sr-only text remains the
|
|
102
|
+
// accessible name. The full reason is also always visible
|
|
103
|
+
// in the open conversation's attention banner.
|
|
104
|
+
_jsxs(Tooltip, { children: [_jsxs(TooltipTrigger, { render: _jsx("span", { className: "shrink-0" }), children: [_jsx(TriangleAlert, { "aria-hidden": "true", className: "size-3.5 text-destructive" }), _jsx("span", { className: "sr-only", children: conversation.attentionReason
|
|
105
|
+
? `Needs attention: ${conversation.attentionReason}`
|
|
106
|
+
: "Needs attention" })] }), _jsx(TooltipContent, { side: "top", children: conversation.attentionReason || "Needs attention" })] }))] }), contact !== null && (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground-faint", children: contact })), humanHeld && (_jsxs("p", { className: "mt-0.5 flex items-center gap-1 text-xs text-muted-foreground", children: [_jsx(User, { "aria-hidden": "true", className: "size-3" }), "Human has the conversation"] }))] }), (lastActivity !== null || awaiting !== null) && (_jsxs("span", { className: "flex shrink-0 flex-col items-end gap-1", children: [lastActivity && (_jsx("span", { className: "text-xs text-muted-foreground-faint", children: formatRelativeTime(lastActivity, now) })), awaiting && (
|
|
107
|
+
// The WhatsApp inbox convention: an awaiting conversation
|
|
108
|
+
// carries a dot under its timestamp. Strength maps the
|
|
109
|
+
// holder (DD-011 D-a): strong when a human holds it — the
|
|
110
|
+
// agent will not answer, a person must — muted when the
|
|
111
|
+
// agent does. No tooltip and no tab stop (the F-18
|
|
112
|
+
// discipline); the sr-only text is the accessible meaning.
|
|
113
|
+
_jsxs("span", { className: "flex", children: [_jsx("span", { "aria-hidden": "true", className: cn("size-2 rounded-full", awaiting === "strong" ? "bg-primary" : "bg-muted-foreground") }), _jsx("span", { className: "sr-only", children: awaiting === "strong"
|
|
114
|
+
? "Customer awaiting reply — the conversation is human-held"
|
|
115
|
+
: "Customer awaiting reply" })] }))] }))] }) }));
|
|
116
|
+
});
|
|
117
|
+
function ListSkeleton() {
|
|
118
|
+
return (_jsx("div", { className: "space-y-1 p-1", "aria-hidden": "true", children: [1, 2, 3, 4].map((i) => (_jsx("div", { className: "h-11 animate-pulse rounded-md bg-muted-faint" }, i))) }));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=ConversationListPane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationListPane.js","sourceRoot":"","sources":["../../src/conversation/ConversationListPane.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ConversationTimelineItem } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/conversation_io_pb";
|
|
2
|
+
import { type ChannelProviderId } from "../channel/providers.js";
|
|
3
|
+
/** Props for {@link ConversationTimelineView}. */
|
|
4
|
+
export interface ConversationTimelineViewProps {
|
|
5
|
+
/** Timeline items in chronological order (from `useConversationTimeline`). */
|
|
6
|
+
readonly items: readonly ConversationTimelineItem[];
|
|
7
|
+
/** `true` only during the first load. */
|
|
8
|
+
readonly isLoading: boolean;
|
|
9
|
+
/** Error from the timeline read, or `null`. */
|
|
10
|
+
readonly error: Error | null;
|
|
11
|
+
/** `true` while older history exists beyond what is loaded. */
|
|
12
|
+
readonly hasOlder: boolean;
|
|
13
|
+
/** Load the next older page. */
|
|
14
|
+
readonly loadOlder: () => void;
|
|
15
|
+
/** `true` while an older page is in flight. */
|
|
16
|
+
readonly isLoadingOlder: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The channel's provider, for the honest-timeline notice: providers
|
|
19
|
+
* whose inbound lane has no timeline source (Slack) render an
|
|
20
|
+
* explicit "customer messages aren't shown" notice instead of a
|
|
21
|
+
* silently one-sided thread. `null` renders no notice.
|
|
22
|
+
*/
|
|
23
|
+
readonly provider: ChannelProviderId | null;
|
|
24
|
+
/** Frozen instant for deterministic hosts (tests, documentation tours). */
|
|
25
|
+
readonly now?: Date;
|
|
26
|
+
/** Additional classes for the view container. */
|
|
27
|
+
readonly className?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* One conversation's customer-visible thread, WhatsApp-style: customer
|
|
31
|
+
* on the left, the business (agent, teammate, platform copy) on the
|
|
32
|
+
* right, internal-lane events (escalations, attention clears) as inline
|
|
33
|
+
* system rows the customer never saw.
|
|
34
|
+
*
|
|
35
|
+
* Honesty rules, enforced here rather than hoped for: outbound items
|
|
36
|
+
* carry their send attempt AND the provider's receipt as two independent
|
|
37
|
+
* facts (DD-004 D-d — an item can be handed to the provider yet fail on
|
|
38
|
+
* the customer's side), failed and suppressed sends render as exactly
|
|
39
|
+
* that, and non-text inbound renders a typed placeholder instead of
|
|
40
|
+
* disappearing.
|
|
41
|
+
*
|
|
42
|
+
* Presentational — pair with `useConversationTimeline`, or compose via
|
|
43
|
+
* `ConversationsWorkbench`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function ConversationTimelineView({ items, isLoading, error, hasOlder, loadOlder, isLoadingOlder, provider, now, className, }: ConversationTimelineViewProps): import("react/jsx-runtime").JSX.Element;
|
|
46
|
+
//# sourceMappingURL=ConversationTimelineView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationTimelineView.d.ts","sourceRoot":"","sources":["../../src/conversation/ConversationTimelineView.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uEAAuE,CAAC;AACtH,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAoBpF,kDAAkD;AAClD,MAAM,WAAW,6BAA6B;IAC5C,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACpD,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,gCAAgC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB,iDAAiD;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,SAAS,EACT,KAAK,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,QAAQ,EACR,GAAG,EACH,SAAS,GACV,EAAE,6BAA6B,2CAgF/B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { memo, useMemo } from "react";
|
|
4
|
+
import { timestampDate } from "@bufbuild/protobuf/wkt";
|
|
5
|
+
import { Ban, Check, CheckCheck, Clock, Info, MessageSquare, TriangleAlert } from "lucide-react";
|
|
6
|
+
import { cn } from "@stigmer/theme";
|
|
7
|
+
import { getUserMessage } from "@stigmer/sdk";
|
|
8
|
+
import { channelProviderOf } from "../channel/providers.js";
|
|
9
|
+
import { Button } from "../button/Button.js";
|
|
10
|
+
import { EmptyState } from "../empty-state/EmptyState.js";
|
|
11
|
+
import { JumpToLatestButton } from "../internal/JumpToLatestButton.js";
|
|
12
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../internal/tooltip.js";
|
|
13
|
+
import { useAutoScroll } from "../internal/useAutoScroll.js";
|
|
14
|
+
import { authorKindOf, inboundPlaceholderOf, isInternalItem, receiptOf, sendAttemptOf, } from "./conversationPresentation.js";
|
|
15
|
+
/**
|
|
16
|
+
* One conversation's customer-visible thread, WhatsApp-style: customer
|
|
17
|
+
* on the left, the business (agent, teammate, platform copy) on the
|
|
18
|
+
* right, internal-lane events (escalations, attention clears) as inline
|
|
19
|
+
* system rows the customer never saw.
|
|
20
|
+
*
|
|
21
|
+
* Honesty rules, enforced here rather than hoped for: outbound items
|
|
22
|
+
* carry their send attempt AND the provider's receipt as two independent
|
|
23
|
+
* facts (DD-004 D-d — an item can be handed to the provider yet fail on
|
|
24
|
+
* the customer's side), failed and suppressed sends render as exactly
|
|
25
|
+
* that, and non-text inbound renders a typed placeholder instead of
|
|
26
|
+
* disappearing.
|
|
27
|
+
*
|
|
28
|
+
* Presentational — pair with `useConversationTimeline`, or compose via
|
|
29
|
+
* `ConversationsWorkbench`.
|
|
30
|
+
*/
|
|
31
|
+
export function ConversationTimelineView({ items, isLoading, error, hasOlder, loadOlder, isLoadingOlder, provider, now, className, }) {
|
|
32
|
+
const { scrollRef, sentinelRef, contentRef, isFollowing, jumpToLatest } = useAutoScroll();
|
|
33
|
+
const days = useMemo(() => groupByDay(items, now), [items, now]);
|
|
34
|
+
const descriptor = channelProviderOf(provider ?? undefined);
|
|
35
|
+
const showsCustomerMessages = descriptor?.timelineIncludesCustomerMessages ?? true;
|
|
36
|
+
return (
|
|
37
|
+
// The provider is context-only (no DOM node); one per view arms
|
|
38
|
+
// every status-glyph tooltip below (the WorkspaceSidebar precedent).
|
|
39
|
+
_jsx(TooltipProvider, { children: _jsxs("div", { "aria-label": "Conversation timeline", className: cn("relative flex min-h-0 flex-1 flex-col", className), children: [_jsxs("div", { ref: scrollRef, className: "min-h-0 flex-1 overflow-y-auto [overflow-anchor:none] px-4 py-3", children: [!showsCustomerMessages && descriptor && (_jsxs("div", { className: "mb-3 flex items-start gap-2 rounded-md border border-border bg-muted-faint px-3 py-2 text-xs text-muted-foreground", children: [_jsx(Info, { "aria-hidden": "true", className: "mt-0.5 size-3.5 shrink-0" }), _jsxs("p", { children: ["Customer messages on ", descriptor.label, " channels aren't shown here yet \u2014 this thread has replies, sends, and internal events only."] })] })), isLoading ? (_jsx(TimelineSkeleton, {})) : error ? (_jsx("p", { className: "px-2 py-6 text-center text-sm text-destructive", children: getUserMessage(error) })) : items.length === 0 ? (_jsx(EmptyState, { variant: "first-use", icon: _jsx(MessageSquare, { className: "size-8" }), title: "No messages yet", description: "The conversation's messages appear here as they happen." })) : (_jsxs("div", { ref: contentRef, children: [hasOlder && (_jsx("div", { className: "flex justify-center pb-2", children: _jsx(Button, { variant: "ghost", size: "xs", onClick: loadOlder, disabled: isLoadingOlder, children: isLoadingOlder ? "Loading…" : "Load earlier messages" }) })), days.map((day) => (_jsxs("div", { children: [_jsx("div", { className: "my-2 text-center text-xs text-muted-foreground-faint", role: "separator", children: day.label }), _jsx("ul", { className: "space-y-1.5", children: day.items.map((item) => (_jsx(TimelineItemRow, { item: item }, item.itemId))) })] }, day.label)))] })), _jsx("div", { ref: sentinelRef, "aria-hidden": "true" })] }), _jsx(JumpToLatestButton, { visible: !isFollowing, onClick: jumpToLatest })] }) }));
|
|
40
|
+
}
|
|
41
|
+
const BUSINESS_CAPTION = {
|
|
42
|
+
agent: "Agent",
|
|
43
|
+
teammate: "Teammate",
|
|
44
|
+
platform: "Automated",
|
|
45
|
+
unknown: "Unknown sender",
|
|
46
|
+
};
|
|
47
|
+
const TimelineItemRow = memo(function TimelineItemRow({ item, }) {
|
|
48
|
+
if (isInternalItem(item)) {
|
|
49
|
+
return _jsx(InternalEventRow, { item: item });
|
|
50
|
+
}
|
|
51
|
+
const author = authorKindOf(item);
|
|
52
|
+
const isCustomer = author === "customer";
|
|
53
|
+
const body = item.text || inboundPlaceholderOf(item);
|
|
54
|
+
// DD-014 D-c (amended at the Sitting 2 gate, R-1): the provider's
|
|
55
|
+
// failure explanation is decision-bearing — window closed vs bad
|
|
56
|
+
// number changes what the operator does next — so it renders as
|
|
57
|
+
// VISIBLE text, not hover-only (the footer glyphs are deliberately
|
|
58
|
+
// non-focusable per F-18, which makes a tooltip mouse-only). Verbatim
|
|
59
|
+
// relay, never pattern-matched; the numeric twin (receipt_error_code)
|
|
60
|
+
// stays off the surface as machine vocabulary. Gated exactly like
|
|
61
|
+
// ReceiptTicks' failed arm — attempt delivered AND receipt failed —
|
|
62
|
+
// so the attempt-axis explanation (last_error, F-25's slice) can
|
|
63
|
+
// structurally never leak in here.
|
|
64
|
+
const receiptExplanation = sendAttemptOf(item) === "delivered" &&
|
|
65
|
+
receiptOf(item) === "failed" &&
|
|
66
|
+
item.receiptDetail !== ""
|
|
67
|
+
? item.receiptDetail
|
|
68
|
+
: null;
|
|
69
|
+
return (_jsx("li", { className: cn("flex", isCustomer ? "justify-start" : "justify-end"), children: _jsxs("div", { className: cn("max-w-[80%] rounded-lg px-3 py-2", isCustomer ? "bg-muted-subtle" : "bg-primary-subtle"), children: [!isCustomer && (_jsx("p", { className: "text-xs font-medium text-muted-foreground", children: BUSINESS_CAPTION[author] })), _jsx("p", { className: cn("whitespace-pre-wrap break-words text-sm text-foreground", !item.text && "italic text-muted-foreground"), children: body || "Message content unavailable" }), receiptExplanation !== null && (_jsx("p", { className: "mt-1 break-words text-xs text-destructive", children: receiptExplanation })), _jsx(ItemFooter, { item: item })] }) }));
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* A footer status glyph with its explanation on the house tooltip
|
|
73
|
+
* (F-18, replacing native `title` — OS-delayed, imprecise, invisible to
|
|
74
|
+
* keyboard and touch). The trigger renders as a plain `<span>` and is
|
|
75
|
+
* deliberately NOT focusable: these sit inside every bubble's footer,
|
|
76
|
+
* so focusable triggers would add several tab stops per message. Their
|
|
77
|
+
* accessible name stays the visible or `sr-only` text; the tooltip is
|
|
78
|
+
* the visual description only.
|
|
79
|
+
*/
|
|
80
|
+
function StatusHint({ hint, className, children, }) {
|
|
81
|
+
return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx("span", { className: className }), children: children }), _jsx(TooltipContent, { side: "top", children: hint })] }));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The bubble footer: the item's instant plus, for outbound items, the
|
|
85
|
+
* two status axes — our attempt and the provider's receipt, never
|
|
86
|
+
* collapsed into one glyph.
|
|
87
|
+
*/
|
|
88
|
+
function ItemFooter({ item }) {
|
|
89
|
+
const attempt = sendAttemptOf(item);
|
|
90
|
+
const time = item.at
|
|
91
|
+
? timestampDate(item.at).toLocaleTimeString(undefined, {
|
|
92
|
+
hour: "2-digit",
|
|
93
|
+
minute: "2-digit",
|
|
94
|
+
})
|
|
95
|
+
: "";
|
|
96
|
+
return (_jsxs("p", { className: "mt-1 flex items-center justify-end gap-1 text-xs text-muted-foreground-faint", children: [_jsx("span", { children: time }), attempt === "failed" && (_jsxs(StatusHint, { hint: "The platform could not deliver this message", className: "flex items-center gap-0.5 text-destructive", children: [_jsx(TriangleAlert, { "aria-hidden": "true", className: "size-3" }), "Not delivered"] })), attempt === "suppressed" && (_jsxs(StatusHint, { hint: "Withheld because a human had the conversation when it came due", className: "flex items-center gap-0.5", children: [_jsx(Ban, { "aria-hidden": "true", className: "size-3" }), "Held"] })), (attempt === "pending" || attempt === "delivering") && (_jsxs(StatusHint, { hint: "Sending", className: "flex items-center gap-0.5", children: [_jsx(Clock, { "aria-hidden": "true", className: "size-3" }), _jsx("span", { className: "sr-only", children: "Sending" })] })), attempt === "delivered" && _jsx(ReceiptTicks, { item: item })] }));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The provider's receipt report, WhatsApp-tick style. Renders only on
|
|
100
|
+
* items the platform successfully handed to the provider; the receipt
|
|
101
|
+
* can still be `failed` — the "we sent it, it never arrived" case a
|
|
102
|
+
* collapsed status hides.
|
|
103
|
+
*/
|
|
104
|
+
function ReceiptTicks({ item }) {
|
|
105
|
+
const receipt = receiptOf(item);
|
|
106
|
+
if (receipt === "failed") {
|
|
107
|
+
return (_jsxs(StatusHint, { hint: "The provider accepted this message but could not deliver it", className: "flex items-center gap-0.5 text-destructive", children: [_jsx(TriangleAlert, { "aria-hidden": "true", className: "size-3" }), "Delivery failed"] }));
|
|
108
|
+
}
|
|
109
|
+
if (receipt === "read") {
|
|
110
|
+
return (_jsxs(StatusHint, { hint: "Read by the customer", className: "text-primary", children: [_jsx(CheckCheck, { "aria-hidden": "true", className: "size-3.5" }), _jsx("span", { className: "sr-only", children: "Read" })] }));
|
|
111
|
+
}
|
|
112
|
+
if (receipt === "delivered") {
|
|
113
|
+
return (_jsxs(StatusHint, { hint: "Delivered to the customer's device", children: [_jsx(CheckCheck, { "aria-hidden": "true", className: "size-3.5" }), _jsx("span", { className: "sr-only", children: "Delivered" })] }));
|
|
114
|
+
}
|
|
115
|
+
// Handed to the provider; no (further) receipt yet.
|
|
116
|
+
return (_jsxs(StatusHint, { hint: "Sent", children: [_jsx(Check, { "aria-hidden": "true", className: "size-3.5" }), _jsx("span", { className: "sr-only", children: "Sent" })] }));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Internal-lane rows — org-internal events the customer never saw,
|
|
120
|
+
* rendered as centered system copy so they can never be misread as
|
|
121
|
+
* messages: the agent's escalation (its reason verbatim) and a
|
|
122
|
+
* teammate's attention clear.
|
|
123
|
+
*/
|
|
124
|
+
function InternalEventRow({ item }) {
|
|
125
|
+
const author = authorKindOf(item);
|
|
126
|
+
const isEscalation = author === "agent" && item.text !== "";
|
|
127
|
+
return (_jsx("li", { className: "flex justify-center", children: _jsx("div", { className: cn("flex max-w-[90%] items-start gap-1.5 rounded-md px-3 py-1.5 text-center text-xs", isEscalation
|
|
128
|
+
? "bg-destructive-subtle text-destructive"
|
|
129
|
+
: "bg-muted-faint text-muted-foreground"), children: isEscalation ? (_jsxs(_Fragment, { children: [_jsx(TriangleAlert, { "aria-hidden": "true", className: "mt-0.5 size-3.5 shrink-0" }), _jsxs("span", { className: "min-w-0 break-words", children: ["Agent escalated to a human \u2014 \u201C", item.text, "\u201D"] })] })) : item.text !== "" ? (
|
|
130
|
+
// A future internal note flows through with zero code change.
|
|
131
|
+
_jsx("span", { className: "min-w-0 break-words", children: item.text })) : (_jsx("span", { children: "A teammate resolved the attention flag" })) }) }));
|
|
132
|
+
}
|
|
133
|
+
function TimelineSkeleton() {
|
|
134
|
+
return (_jsxs("div", { className: "space-y-2", "aria-hidden": "true", children: [_jsx("div", { className: "h-10 w-3/5 animate-pulse rounded-lg bg-muted-faint" }), _jsx("div", { className: "ml-auto h-10 w-3/5 animate-pulse rounded-lg bg-muted-faint" }), _jsx("div", { className: "h-10 w-2/5 animate-pulse rounded-lg bg-muted-faint" })] }));
|
|
135
|
+
}
|
|
136
|
+
/** Group chronological items under day separators. */
|
|
137
|
+
function groupByDay(items, now) {
|
|
138
|
+
const ref = now ?? new Date();
|
|
139
|
+
const groups = [];
|
|
140
|
+
let currentKey = "";
|
|
141
|
+
for (const item of items) {
|
|
142
|
+
const date = item.at ? timestampDate(item.at) : null;
|
|
143
|
+
const key = date ? date.toDateString() : "undated";
|
|
144
|
+
if (key !== currentKey) {
|
|
145
|
+
currentKey = key;
|
|
146
|
+
groups.push({ label: date ? dayLabel(date, ref) : "Earlier", items: [] });
|
|
147
|
+
}
|
|
148
|
+
groups[groups.length - 1].items.push(item);
|
|
149
|
+
}
|
|
150
|
+
return groups;
|
|
151
|
+
}
|
|
152
|
+
function dayLabel(date, ref) {
|
|
153
|
+
if (date.toDateString() === ref.toDateString())
|
|
154
|
+
return "Today";
|
|
155
|
+
const yesterday = new Date(ref);
|
|
156
|
+
yesterday.setDate(ref.getDate() - 1);
|
|
157
|
+
if (date.toDateString() === yesterday.toDateString())
|
|
158
|
+
return "Yesterday";
|
|
159
|
+
return date.toLocaleDateString(undefined, {
|
|
160
|
+
weekday: "short",
|
|
161
|
+
month: "short",
|
|
162
|
+
day: "numeric",
|
|
163
|
+
...(date.getFullYear() === ref.getFullYear() ? {} : { year: "numeric" }),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=ConversationTimelineView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationTimelineView.js","sourceRoot":"","sources":["../../src/conversation/ConversationTimelineView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { AgentChannel } from "@stigmer/protos/ai/stigmer/agentic/agentchannel/v1/api_pb";
|
|
2
|
+
import { type ConversationIdentity } from "./ConversationListPane.js";
|
|
3
|
+
/**
|
|
4
|
+
* Context handed to a function-form
|
|
5
|
+
* {@link ConversationsWorkbenchProps.headerAccessory}.
|
|
6
|
+
*/
|
|
7
|
+
export interface ConversationHeaderContext {
|
|
8
|
+
/**
|
|
9
|
+
* The open conversation's channel, once the org's channel list
|
|
10
|
+
* answers — `null` while it loads. Carries the channel's name (for
|
|
11
|
+
* scope-explicit accessories like the "Channel access" trigger) and
|
|
12
|
+
* `spec.agent_ref` (for navigation), so hosts never re-fetch what the
|
|
13
|
+
* workbench already holds.
|
|
14
|
+
*/
|
|
15
|
+
readonly channel: AgentChannel | null;
|
|
16
|
+
}
|
|
17
|
+
/** Props for {@link ConversationsWorkbench}. */
|
|
18
|
+
export interface ConversationsWorkbenchProps {
|
|
19
|
+
/** Organization whose conversations to show. */
|
|
20
|
+
readonly org: string;
|
|
21
|
+
/**
|
|
22
|
+
* The open conversation. Controlled by the host so selection can live
|
|
23
|
+
* in the URL (deep links, reloads, back button).
|
|
24
|
+
*/
|
|
25
|
+
readonly selected: ConversationIdentity | null;
|
|
26
|
+
/** Called when the user opens or leaves a conversation. */
|
|
27
|
+
readonly onSelectionChange: (selection: ConversationIdentity | null) => void;
|
|
28
|
+
/**
|
|
29
|
+
* The signed-in staff member's identity account id, when the host
|
|
30
|
+
* knows it — used only for "You have this conversation" copy.
|
|
31
|
+
*/
|
|
32
|
+
readonly currentIdentityAccountId?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Rendered in the open conversation's header (the host's seam for
|
|
35
|
+
* page-level actions — e.g. the channel access panel trigger). The
|
|
36
|
+
* function form receives {@link ConversationHeaderContext} so the
|
|
37
|
+
* accessory can name the channel it acts on.
|
|
38
|
+
*/
|
|
39
|
+
readonly headerAccessory?: React.ReactNode | ((context: ConversationHeaderContext) => React.ReactNode);
|
|
40
|
+
/**
|
|
41
|
+
* Maps the open conversation's channel to the host's channel surface
|
|
42
|
+
* — the owning agent's Channels tab (channels have no standalone
|
|
43
|
+
* page). When provided, the header's channel name renders as a link;
|
|
44
|
+
* `null` for a specific channel keeps it plain text. The SDK never
|
|
45
|
+
* assumes a routing scheme (DD-004).
|
|
46
|
+
*/
|
|
47
|
+
readonly channelHref?: (channel: AgentChannel) => string | null;
|
|
48
|
+
/** Frozen instant for deterministic hosts (tests, documentation tours). */
|
|
49
|
+
readonly now?: Date;
|
|
50
|
+
/** Additional classes for the workbench container. */
|
|
51
|
+
readonly className?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The Conversations console surface (channel-conversations T04), fully
|
|
55
|
+
* composed: the org-wide inbox on the left; the open conversation's
|
|
56
|
+
* timeline, participation banners, and staff composer on the right.
|
|
57
|
+
*
|
|
58
|
+
* Everything under it is independently importable — hosts that need a
|
|
59
|
+
* different layout compose `ConversationListPane`,
|
|
60
|
+
* `ConversationTimelineView`, the banners, and the hooks directly.
|
|
61
|
+
*/
|
|
62
|
+
export declare function ConversationsWorkbench({ org, selected, onSelectionChange, currentIdentityAccountId, headerAccessory, channelHref, now, className, }: ConversationsWorkbenchProps): import("react/jsx-runtime").JSX.Element;
|
|
63
|
+
//# sourceMappingURL=ConversationsWorkbench.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationsWorkbench.d.ts","sourceRoot":"","sources":["../../src/conversation/ConversationsWorkbench.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAY9F,OAAO,EAAwB,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAa5F;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;CACvC;AAED,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC1C,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC/C,2DAA2D;IAC3D,QAAQ,CAAC,iBAAiB,EAAE,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7E;;;OAGG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EACrB,KAAK,CAAC,SAAS,GACf,CAAC,CAAC,OAAO,EAAE,yBAAyB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9D;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,MAAM,GAAG,IAAI,CAAC;IAChE,2EAA2E;IAC3E,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB,sDAAsD;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,WAAW,EACX,GAAG,EACH,SAAS,GACV,EAAE,2BAA2B,2CAmR7B"}
|