@webority/mobile-chat 0.128.0 → 0.134.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/lib/commonjs/AgentByline.js +1 -0
- package/lib/commonjs/ChatComposer.js +1 -0
- package/lib/commonjs/ChatConversationActions.js +1 -0
- package/lib/commonjs/ChatDictationButton.js +1 -0
- package/lib/commonjs/ChatEmbed.js +1 -0
- package/lib/commonjs/ChatEntrance.js +1 -0
- package/lib/commonjs/ChatFooter.js +1 -0
- package/lib/commonjs/ChatFrame.js +1 -0
- package/lib/commonjs/ChatHistory.js +1 -0
- package/lib/commonjs/ChatLiveBar.js +1 -0
- package/lib/commonjs/ChatMessageActions.js +1 -0
- package/lib/commonjs/ChatNudge.js +1 -0
- package/lib/commonjs/ChatOpenTickets.js +1 -0
- package/lib/commonjs/ChatPastChats.js +1 -0
- package/lib/commonjs/ChatScreen.js +1 -0
- package/lib/commonjs/ChatSheet.js +1 -0
- package/lib/commonjs/ChatStarters.js +1 -0
- package/lib/commonjs/ChatThread.js +1 -0
- package/lib/commonjs/ReadAloudButton.js +1 -0
- package/lib/commonjs/chatShared.js +1 -0
- package/lib/commonjs/features.map.json +40 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/loaders/ChatLoader.js +1 -0
- package/lib/commonjs/loaders/OrbLoader.js +1 -0
- package/lib/commonjs/loaders/PhrasesLoader.js +1 -0
- package/lib/commonjs/loaders/SkeletonLoader.js +1 -0
- package/lib/commonjs/loaders/StepsLoader.js +1 -0
- package/lib/commonjs/loaders/TypingPill.js +1 -0
- package/lib/commonjs/pushOpen.js +1 -0
- package/lib/commonjs/renderers/ActionPart.js +1 -0
- package/lib/commonjs/renderers/ChartPart.js +1 -0
- package/lib/commonjs/renderers/FigureText.js +1 -0
- package/lib/commonjs/renderers/FiguresPart.js +1 -0
- package/lib/commonjs/renderers/FilePart.js +1 -0
- package/lib/commonjs/renderers/HandoffPart.js +1 -0
- package/lib/commonjs/renderers/ImagePart.js +1 -0
- package/lib/commonjs/renderers/InputRequestPart.js +1 -0
- package/lib/commonjs/renderers/NoticePart.js +1 -0
- package/lib/commonjs/renderers/QuickRepliesPart.js +1 -0
- package/lib/commonjs/renderers/RecordCardPart.js +1 -0
- package/lib/commonjs/renderers/SourcesPart.js +1 -0
- package/lib/commonjs/renderers/TablePart.js +1 -0
- package/lib/commonjs/renderers/TextPart.js +1 -0
- package/lib/commonjs/renderers/TicketPart.js +1 -0
- package/lib/commonjs/renderers/VoiceClipPart.js +1 -0
- package/lib/commonjs/renderers/index.js +1 -0
- package/lib/commonjs/speech/azureSpeech.js +1 -0
- package/lib/commonjs/speech/expoAudio.js +1 -0
- package/lib/commonjs/speech/phoneSpeech.js +1 -0
- package/lib/commonjs/speech/speechText.js +1 -0
- package/lib/commonjs/types.js +1 -0
- package/lib/commonjs/useChat.js +1 -1
- package/lib/commonjs/useChatHaptics.js +1 -0
- package/lib/commonjs/useChatSound.js +1 -0
- package/lib/commonjs/useChatSpeech.js +1 -0
- package/lib/commonjs/useTranscriptActions.js +1 -0
- package/lib/module/AgentByline.js +1 -0
- package/lib/module/ChatComposer.js +1 -0
- package/lib/module/ChatConversationActions.js +1 -0
- package/lib/module/ChatDictationButton.js +1 -0
- package/lib/module/ChatEmbed.js +1 -0
- package/lib/module/ChatEntrance.js +1 -0
- package/lib/module/ChatFooter.js +1 -0
- package/lib/module/ChatFrame.js +1 -0
- package/lib/module/ChatHistory.js +1 -0
- package/lib/module/ChatLiveBar.js +1 -0
- package/lib/module/ChatMessageActions.js +1 -0
- package/lib/module/ChatNudge.js +1 -0
- package/lib/module/ChatOpenTickets.js +1 -0
- package/lib/module/ChatPastChats.js +1 -0
- package/lib/module/ChatScreen.js +1 -0
- package/lib/module/ChatSheet.js +1 -0
- package/lib/module/ChatStarters.js +1 -0
- package/lib/module/ChatThread.js +1 -0
- package/lib/module/ReadAloudButton.js +1 -0
- package/lib/module/chatShared.js +1 -0
- package/lib/module/features.map.json +40 -0
- package/lib/module/index.js +1 -1
- package/lib/module/loaders/ChatLoader.js +1 -0
- package/lib/module/loaders/OrbLoader.js +1 -0
- package/lib/module/loaders/PhrasesLoader.js +1 -0
- package/lib/module/loaders/SkeletonLoader.js +1 -0
- package/lib/module/loaders/StepsLoader.js +1 -0
- package/lib/module/loaders/TypingPill.js +1 -0
- package/lib/module/pushOpen.js +1 -0
- package/lib/module/renderers/ActionPart.js +1 -0
- package/lib/module/renderers/ChartPart.js +1 -0
- package/lib/module/renderers/FigureText.js +1 -0
- package/lib/module/renderers/FiguresPart.js +1 -0
- package/lib/module/renderers/FilePart.js +1 -0
- package/lib/module/renderers/HandoffPart.js +1 -0
- package/lib/module/renderers/ImagePart.js +1 -0
- package/lib/module/renderers/InputRequestPart.js +1 -0
- package/lib/module/renderers/NoticePart.js +1 -0
- package/lib/module/renderers/QuickRepliesPart.js +1 -0
- package/lib/module/renderers/RecordCardPart.js +1 -0
- package/lib/module/renderers/SourcesPart.js +1 -0
- package/lib/module/renderers/TablePart.js +1 -0
- package/lib/module/renderers/TextPart.js +1 -0
- package/lib/module/renderers/TicketPart.js +1 -0
- package/lib/module/renderers/VoiceClipPart.js +1 -0
- package/lib/module/renderers/index.js +1 -0
- package/lib/module/speech/azureSpeech.js +1 -0
- package/lib/module/speech/expoAudio.js +1 -0
- package/lib/module/speech/phoneSpeech.js +1 -0
- package/lib/module/speech/speechText.js +1 -0
- package/lib/module/types.js +1 -0
- package/lib/module/useChat.js +1 -1
- package/lib/module/useChatHaptics.js +1 -0
- package/lib/module/useChatSound.js +1 -0
- package/lib/module/useChatSpeech.js +1 -0
- package/lib/module/useTranscriptActions.js +1 -0
- package/lib/typescript/commonjs/AgentByline.d.ts +9 -0
- package/lib/typescript/commonjs/ChatComposer.d.ts +15 -0
- package/lib/typescript/commonjs/ChatConversationActions.d.ts +10 -0
- package/lib/typescript/commonjs/ChatDictationButton.d.ts +19 -0
- package/lib/typescript/commonjs/ChatEmbed.d.ts +11 -0
- package/lib/typescript/commonjs/ChatEntrance.d.ts +8 -0
- package/lib/typescript/commonjs/ChatFooter.d.ts +9 -0
- package/lib/typescript/commonjs/ChatFrame.d.ts +45 -0
- package/lib/typescript/commonjs/ChatHistory.d.ts +11 -0
- package/lib/typescript/commonjs/ChatLiveBar.d.ts +11 -0
- package/lib/typescript/commonjs/ChatMessageActions.d.ts +15 -0
- package/lib/typescript/commonjs/ChatNudge.d.ts +14 -0
- package/lib/typescript/commonjs/ChatOpenTickets.d.ts +12 -0
- package/lib/typescript/commonjs/ChatPastChats.d.ts +21 -0
- package/lib/typescript/commonjs/ChatScreen.d.ts +5 -0
- package/lib/typescript/commonjs/ChatSheet.d.ts +21 -0
- package/lib/typescript/commonjs/ChatStarters.d.ts +12 -0
- package/lib/typescript/commonjs/ChatThread.d.ts +36 -0
- package/lib/typescript/commonjs/ReadAloudButton.d.ts +11 -0
- package/lib/typescript/commonjs/chatShared.d.ts +4 -0
- package/lib/typescript/commonjs/index.d.ts +27 -21
- package/lib/typescript/commonjs/loaders/ChatLoader.d.ts +13 -0
- package/lib/typescript/commonjs/loaders/OrbLoader.d.ts +8 -0
- package/lib/typescript/commonjs/loaders/PhrasesLoader.d.ts +8 -0
- package/lib/typescript/commonjs/loaders/SkeletonLoader.d.ts +8 -0
- package/lib/typescript/commonjs/loaders/StepsLoader.d.ts +8 -0
- package/lib/typescript/commonjs/loaders/TypingPill.d.ts +7 -0
- package/lib/typescript/commonjs/pushOpen.d.ts +3 -0
- package/lib/typescript/commonjs/renderers/ActionPart.d.ts +3 -0
- package/lib/typescript/commonjs/renderers/ChartPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/FigureText.d.ts +23 -0
- package/lib/typescript/commonjs/renderers/FiguresPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/FilePart.d.ts +3 -0
- package/lib/typescript/commonjs/renderers/HandoffPart.d.ts +9 -0
- package/lib/typescript/commonjs/renderers/ImagePart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/InputRequestPart.d.ts +3 -0
- package/lib/typescript/commonjs/renderers/NoticePart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/QuickRepliesPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/RecordCardPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/SourcesPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/TablePart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/TextPart.d.ts +8 -0
- package/lib/typescript/commonjs/renderers/TicketPart.d.ts +9 -0
- package/lib/typescript/commonjs/renderers/VoiceClipPart.d.ts +9 -0
- package/lib/typescript/commonjs/renderers/index.d.ts +3 -0
- package/lib/typescript/commonjs/speech/azureSpeech.d.ts +25 -0
- package/lib/typescript/commonjs/speech/expoAudio.d.ts +23 -0
- package/lib/typescript/commonjs/speech/phoneSpeech.d.ts +16 -0
- package/lib/typescript/commonjs/speech/speechText.d.ts +16 -0
- package/lib/typescript/commonjs/types.d.ts +29 -0
- package/lib/typescript/commonjs/useChat.d.ts +40 -10
- package/lib/typescript/commonjs/useChatHaptics.d.ts +3 -0
- package/lib/typescript/commonjs/useChatSound.d.ts +35 -0
- package/lib/typescript/commonjs/useChatSpeech.d.ts +4 -0
- package/lib/typescript/commonjs/useTranscriptActions.d.ts +10 -0
- package/lib/typescript/module/AgentByline.d.ts +9 -0
- package/lib/typescript/module/ChatComposer.d.ts +15 -0
- package/lib/typescript/module/ChatConversationActions.d.ts +10 -0
- package/lib/typescript/module/ChatDictationButton.d.ts +19 -0
- package/lib/typescript/module/ChatEmbed.d.ts +11 -0
- package/lib/typescript/module/ChatEntrance.d.ts +8 -0
- package/lib/typescript/module/ChatFooter.d.ts +9 -0
- package/lib/typescript/module/ChatFrame.d.ts +45 -0
- package/lib/typescript/module/ChatHistory.d.ts +11 -0
- package/lib/typescript/module/ChatLiveBar.d.ts +11 -0
- package/lib/typescript/module/ChatMessageActions.d.ts +15 -0
- package/lib/typescript/module/ChatNudge.d.ts +14 -0
- package/lib/typescript/module/ChatOpenTickets.d.ts +12 -0
- package/lib/typescript/module/ChatPastChats.d.ts +21 -0
- package/lib/typescript/module/ChatScreen.d.ts +5 -0
- package/lib/typescript/module/ChatSheet.d.ts +21 -0
- package/lib/typescript/module/ChatStarters.d.ts +12 -0
- package/lib/typescript/module/ChatThread.d.ts +36 -0
- package/lib/typescript/module/ReadAloudButton.d.ts +11 -0
- package/lib/typescript/module/chatShared.d.ts +4 -0
- package/lib/typescript/module/index.d.ts +27 -21
- package/lib/typescript/module/loaders/ChatLoader.d.ts +13 -0
- package/lib/typescript/module/loaders/OrbLoader.d.ts +8 -0
- package/lib/typescript/module/loaders/PhrasesLoader.d.ts +8 -0
- package/lib/typescript/module/loaders/SkeletonLoader.d.ts +8 -0
- package/lib/typescript/module/loaders/StepsLoader.d.ts +8 -0
- package/lib/typescript/module/loaders/TypingPill.d.ts +7 -0
- package/lib/typescript/module/pushOpen.d.ts +3 -0
- package/lib/typescript/module/renderers/ActionPart.d.ts +3 -0
- package/lib/typescript/module/renderers/ChartPart.d.ts +8 -0
- package/lib/typescript/module/renderers/FigureText.d.ts +23 -0
- package/lib/typescript/module/renderers/FiguresPart.d.ts +8 -0
- package/lib/typescript/module/renderers/FilePart.d.ts +3 -0
- package/lib/typescript/module/renderers/HandoffPart.d.ts +9 -0
- package/lib/typescript/module/renderers/ImagePart.d.ts +8 -0
- package/lib/typescript/module/renderers/InputRequestPart.d.ts +3 -0
- package/lib/typescript/module/renderers/NoticePart.d.ts +8 -0
- package/lib/typescript/module/renderers/QuickRepliesPart.d.ts +8 -0
- package/lib/typescript/module/renderers/RecordCardPart.d.ts +8 -0
- package/lib/typescript/module/renderers/SourcesPart.d.ts +8 -0
- package/lib/typescript/module/renderers/TablePart.d.ts +8 -0
- package/lib/typescript/module/renderers/TextPart.d.ts +8 -0
- package/lib/typescript/module/renderers/TicketPart.d.ts +9 -0
- package/lib/typescript/module/renderers/VoiceClipPart.d.ts +9 -0
- package/lib/typescript/module/renderers/index.d.ts +3 -0
- package/lib/typescript/module/speech/azureSpeech.d.ts +25 -0
- package/lib/typescript/module/speech/expoAudio.d.ts +23 -0
- package/lib/typescript/module/speech/phoneSpeech.d.ts +16 -0
- package/lib/typescript/module/speech/speechText.d.ts +16 -0
- package/lib/typescript/module/types.d.ts +29 -0
- package/lib/typescript/module/useChat.d.ts +40 -10
- package/lib/typescript/module/useChatHaptics.d.ts +3 -0
- package/lib/typescript/module/useChatSound.d.ts +35 -0
- package/lib/typescript/module/useChatSpeech.d.ts +4 -0
- package/lib/typescript/module/useTranscriptActions.d.ts +10 -0
- package/package.json +43 -15
- package/README.md +0 -185
- package/lib/commonjs/components/ActionCard.js +0 -1
- package/lib/commonjs/components/ChatComposer.js +0 -1
- package/lib/commonjs/components/ChatConversationList.js +0 -1
- package/lib/commonjs/components/ChatLauncher.js +0 -1
- package/lib/commonjs/components/ChatMarkdown.js +0 -1
- package/lib/commonjs/components/ChatMessage.js +0 -1
- package/lib/commonjs/components/ChatScreen.js +0 -1
- package/lib/commonjs/components/ChatThread.js +0 -1
- package/lib/commonjs/components/ComposerAttachments.js +0 -1
- package/lib/commonjs/components/ReplyRating.js +0 -1
- package/lib/module/components/ActionCard.js +0 -1
- package/lib/module/components/ChatComposer.js +0 -1
- package/lib/module/components/ChatConversationList.js +0 -1
- package/lib/module/components/ChatLauncher.js +0 -1
- package/lib/module/components/ChatMarkdown.js +0 -1
- package/lib/module/components/ChatMessage.js +0 -1
- package/lib/module/components/ChatScreen.js +0 -1
- package/lib/module/components/ChatThread.js +0 -1
- package/lib/module/components/ComposerAttachments.js +0 -1
- package/lib/module/components/ReplyRating.js +0 -1
- package/lib/typescript/commonjs/components/ActionCard.d.ts +0 -23
- package/lib/typescript/commonjs/components/ChatComposer.d.ts +0 -42
- package/lib/typescript/commonjs/components/ChatConversationList.d.ts +0 -22
- package/lib/typescript/commonjs/components/ChatLauncher.d.ts +0 -22
- package/lib/typescript/commonjs/components/ChatMarkdown.d.ts +0 -24
- package/lib/typescript/commonjs/components/ChatMessage.d.ts +0 -55
- package/lib/typescript/commonjs/components/ChatScreen.d.ts +0 -40
- package/lib/typescript/commonjs/components/ChatThread.d.ts +0 -30
- package/lib/typescript/commonjs/components/ComposerAttachments.d.ts +0 -12
- package/lib/typescript/commonjs/components/ReplyRating.d.ts +0 -19
- package/lib/typescript/module/components/ActionCard.d.ts +0 -23
- package/lib/typescript/module/components/ChatComposer.d.ts +0 -42
- package/lib/typescript/module/components/ChatConversationList.d.ts +0 -22
- package/lib/typescript/module/components/ChatLauncher.d.ts +0 -22
- package/lib/typescript/module/components/ChatMarkdown.d.ts +0 -24
- package/lib/typescript/module/components/ChatMessage.d.ts +0 -55
- package/lib/typescript/module/components/ChatScreen.d.ts +0 -40
- package/lib/typescript/module/components/ChatThread.d.ts +0 -30
- package/lib/typescript/module/components/ComposerAttachments.d.ts +0 -12
- package/lib/typescript/module/components/ReplyRating.d.ts +0 -19
package/README.md
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# @webority/mobile-chat
|
|
2
|
-
|
|
3
|
-
An AI assistant for a Webority React Native app: a client that streams the assistant's reply, a
|
|
4
|
-
chat hook with no store of its own, and the chat screen and its parts (the conversation with
|
|
5
|
-
Markdown replies, the question box, past chats with delete, reply ratings, support action cards,
|
|
6
|
-
the questions left today and an optional floating launcher). It talks to the chat endpoints a
|
|
7
|
-
product hosts with `Webority.Ai.Chat.AspNetCore`, the same contract as the web package
|
|
8
|
-
`@webority/chat-react`, and it is built on `@webority/mobile-ui`, so it follows the app's theme.
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm install @webority/mobile-chat
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Peers
|
|
15
|
-
|
|
16
|
-
| Package | Why |
|
|
17
|
-
|---|---|
|
|
18
|
-
| `@webority/mobile-core`, `@webority/mobile-ui` | the HTTP client the app passes in, dates, theme and components |
|
|
19
|
-
| `react-native-keyboard-controller` | the question box rises with the keyboard (mobile-ui needs it too) |
|
|
20
|
-
| `react-native-safe-area-context` | the question box and the launcher clear the home indicator (mobile-ui needs it too) |
|
|
21
|
-
| `expo-clipboard` | the copy action on a reply; the package reaches it through `@webority/mobile-core/clipboard` |
|
|
22
|
-
|
|
23
|
-
All are required. An app on mobile-ui already has the first three; `expo-clipboard` is the one an app adds.
|
|
24
|
-
|
|
25
|
-
## Wire it up
|
|
26
|
-
|
|
27
|
-
Give the client the app's own signed-in axios instance. It already carries the bearer token, the
|
|
28
|
-
tenant header and the refresh on 401, so chat calls sign in like every other call. The package
|
|
29
|
-
never handles auth.
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
import { userClient } from '@webority/mobile-core';
|
|
33
|
-
import { createChatClient, useChat } from '@webority/mobile-chat';
|
|
34
|
-
import { createSupportClient } from '@webority/mobile-support';
|
|
35
|
-
|
|
36
|
-
const chatClient = createChatClient(userClient, { base: '/api/assistant' });
|
|
37
|
-
const supportClient = createSupportClient(userClient, '/api/support');
|
|
38
|
-
|
|
39
|
-
// Reply links look like [label](scheme:kind/id); map the ones the app knows to a screen.
|
|
40
|
-
const resolveLink = (href: string) => {
|
|
41
|
-
const [scheme, rest] = href.split(':');
|
|
42
|
-
if (scheme === 'ticket') return { screen: 'SupportTicket', params: { id: rest.split('/')[1] } };
|
|
43
|
-
return null;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// Above the navigator, so the conversation survives leaving the chat screen.
|
|
47
|
-
export const AssistantProvider = ({ children }) => {
|
|
48
|
-
const chat = useChat({ client: chatClient, pageContext: { screen: currentRouteName() } });
|
|
49
|
-
return <AssistantContext.Provider value={chat}>{children}</AssistantContext.Provider>;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// A stack screen. pickFiles opens the app's own picker and resolves to { uri, name, type } files.
|
|
53
|
-
export const AssistantScreen = ({ navigation }) => (
|
|
54
|
-
<ChatScreen
|
|
55
|
-
chat={useAssistant()}
|
|
56
|
-
title="Ask the assistant"
|
|
57
|
-
headerActions={<Button label="All chats" size="sm" variant="ghost" onPress={() => navigation.navigate('PastChats')} />}
|
|
58
|
-
resolveLink={resolveLink}
|
|
59
|
-
onLinkPress={(target) => navigation.navigate(target.screen, target.params)}
|
|
60
|
-
confirmAction={supportClient.confirmAction}
|
|
61
|
-
onViewTicket={(ticket) => navigation.navigate('SupportTicket', { id: ticket.id })}
|
|
62
|
-
pickAttachments={pickFiles}
|
|
63
|
-
onOpenAttachment={(attachment) => openAttachment(attachment)}
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Call `chat.reset()` when the person signs out or switches account, so nothing of one person's chat
|
|
69
|
-
shows to the next. Call `chat.refreshAllowance()` when the chat opens if the allowance should show
|
|
70
|
-
before the first question.
|
|
71
|
-
|
|
72
|
-
### Streaming
|
|
73
|
-
|
|
74
|
-
The reply streams through axios's XMLHttpRequest adapter, the React Native default: React
|
|
75
|
-
Native's XMLHttpRequest hands over text as it arrives once a progress listener is attached, and
|
|
76
|
-
the client attaches one through `onDownloadProgress`. Incremental delivery on iOS has not yet been
|
|
77
|
-
confirmed on a device; where it buffers, the reply appears whole when it ends. Give the POST a timeout long enough for a
|
|
78
|
-
whole answer (the app's own client may default to a short one). An instance forced onto axios's
|
|
79
|
-
fetch adapter still works, but the reply then appears whole at the end.
|
|
80
|
-
|
|
81
|
-
## The client
|
|
82
|
-
|
|
83
|
-
`createChatClient(http, { base })` takes an axios instance (`get`, `post`, `put`, `delete`
|
|
84
|
-
resolving to `{ data }`) and the prefix the API maps the chat endpoints under. Every method
|
|
85
|
-
rejects with a `ChatApiError` carrying `code`, `status`, `resetsAtUtc` and a `message` written for
|
|
86
|
-
the person, which the components show as is. `code` is the server's code, `network` when no
|
|
87
|
-
response arrived, `aborted` when the request was cancelled, or `invalid-response`.
|
|
88
|
-
|
|
89
|
-
| Method | Request |
|
|
90
|
-
|---|---|
|
|
91
|
-
| `sendMessage({ message, conversationId, pageContext, replacesMessageId, attachmentIds }, { signal, onEvent })` | `POST {base}/chat`, streamed; resolves with the `done` event, which carries `questionId` |
|
|
92
|
-
| `getSettings()` | `GET {base}/settings`: the attachment limits, `{ attachments: null }` when the server takes none |
|
|
93
|
-
| `uploadAttachment(file, { signal, onProgress })` | `POST {base}/attachments`, multipart |
|
|
94
|
-
| `deleteAttachment(id)` | `DELETE {base}/attachments/{id}` |
|
|
95
|
-
| `getAttachment(id)` | `GET {base}/attachments/{id}`, resolves with the bytes |
|
|
96
|
-
| `getAllowance()` | `GET {base}/allowance` |
|
|
97
|
-
| `listConversations({ page, pageSize })` | `GET {base}/conversations?page=&pageSize=`, one page of `{ items, page, pageSize, totalCount, totalPages }` |
|
|
98
|
-
| `getConversation(id)` | `GET {base}/conversations/{id}` |
|
|
99
|
-
| `renameConversation(id, title)` | `PUT {base}/conversations/{id}/title`, the new title in the body |
|
|
100
|
-
| `deleteConversation(id)` | `DELETE {base}/conversations/{id}` |
|
|
101
|
-
| `rateMessage(conversationId, messageId, { rating, note })` | `PUT {base}/conversations/{conversationId}/messages/{messageId}/rating` |
|
|
102
|
-
|
|
103
|
-
The server must answer `GET {base}/settings`. An older server that does not answers 404, and each
|
|
104
|
-
question then fails with `assistant_outdated` ("The assistant needs an update before it can answer. Please try again later.").
|
|
105
|
-
|
|
106
|
-
`onEvent(name, data)` is called with `delta { text }`, `reset {}`, `tool {}` and `actions { actions }` as they
|
|
107
|
-
arrive. `createSseParser(onEvent)` is exported too, for reading the same stream elsewhere. The
|
|
108
|
-
server contract (refusal codes, the event stream, the read endpoints) is the one
|
|
109
|
-
`@webority/chat-react` documents.
|
|
110
|
-
|
|
111
|
-
## The hook
|
|
112
|
-
|
|
113
|
-
`useChat({ client, pageContext })` returns `turns` (`[{ id, question, answer, streaming, error,
|
|
114
|
-
actions, messageId, rating, ratingNote }]`, oldest first), `conversationId`, `messagesLeftToday`,
|
|
115
|
-
`streaming`, `loading`, `loadError`, `settings`, `settingsError`, `editing`, `attachments`, and
|
|
116
|
-
`submit(message)`, `stop()`, `retry(turnId)`, `regenerate(turnId)`, `startEdit(turnId)`,
|
|
117
|
-
`cancelEdit()`, `attach(files)`, `removeAttachment(key)`, `openConversation(id)`,
|
|
118
|
-
`newConversation()`, `rate(turnId, rating, note?)`, `refreshAllowance()` and `reset()`.
|
|
119
|
-
`pageContext` is read at the moment each question is sent.
|
|
120
|
-
|
|
121
|
-
An answer still arriving is cancelled on `reset`, `newConversation`, `openConversation` and
|
|
122
|
-
unmount. A failed turn keeps the question, drops the half-streamed text and carries `error`
|
|
123
|
-
(`{ code, message, resetsAtUtc }`). After `daily_limit`, `messagesLeftToday` becomes 0; after
|
|
124
|
-
`conversation_not_found`, the next question starts a new conversation. A question asked while an
|
|
125
|
-
answer is arriving is ignored.
|
|
126
|
-
|
|
127
|
-
## Components
|
|
128
|
-
|
|
129
|
-
Every component takes `labels`, any subset of `DEFAULT_CHAT_LABELS`. The keys are the web
|
|
130
|
-
package's, so a product passes one label set to both; `composerHint` is not shown on a phone.
|
|
131
|
-
|
|
132
|
-
- **`ChatScreen`**: the whole chat for one navigator screen. `chat` (the `useChat` result),
|
|
133
|
-
`title` (default "Assistant"), `headerActions` (before New chat, e.g. "All chats"), `empty`
|
|
134
|
-
(shown before the first question), `disclaimer` (null hides it), `maxLength` (default 4000),
|
|
135
|
-
`allowanceThreshold` (show the questions left at this many or fewer, default 10), `rating`
|
|
136
|
-
(default true), `resolveLink`, `onLinkPress`, `confirmAction`, `onViewTicket`, `pickAttachments`,
|
|
137
|
-
`onOpenAttachment`, `onAskSuggestion(text)` (sends a suggested follow-up question under the last
|
|
138
|
-
settled answer), `isCitation(inner)` and `onOpenCitation(citation)` (a run of the reply that
|
|
139
|
-
`isCitation` accepts draws as an inline pressable text run, not a chip, and pressing it calls
|
|
140
|
-
`onOpenCitation`), `renderReply`,
|
|
141
|
-
`keyboardOffset`.
|
|
142
|
-
New chat is disabled until there is something to clear; the question box is disabled with no
|
|
143
|
-
questions left, and the thread follows the newest text while an answer streams.
|
|
144
|
-
The five controls: Stop ends an answer while it streams and marks its turn stopped;
|
|
145
|
-
Try again sends a stopped or failed question again; New answer asks for another reply to the last
|
|
146
|
-
answered turn; Edit puts a question back in the box to change and resend; Attach a file adds files
|
|
147
|
-
to the next question. Attach a file shows only when `pickAttachments` is given and the server's
|
|
148
|
-
settings allow attachments; `pickAttachments` resolves to the files the person picked, and
|
|
149
|
-
`onOpenAttachment(attachment)` opens one shown in a message.
|
|
150
|
-
- **`ChatThread`**, **`ChatMessage`**, **`ChatComposer`**: its parts, built on mobile-ui's
|
|
151
|
-
`MessageList`, `MessageBubble`, `TypingIndicator` and `Composer`, for an app that lays out its
|
|
152
|
-
own chat. The thread and the composer handle the keyboard themselves; pass
|
|
153
|
-
`keyboardAware={false}` to both inside a container that already does, and `keyboardOffset` (the
|
|
154
|
-
tab bar height) above a tab bar. The composer's return key adds a new line; only the send button
|
|
155
|
-
sends.
|
|
156
|
-
- **`ChatMarkdown`**: renders a reply through mobile-ui's `Markdown`, the one Markdown renderer
|
|
157
|
-
the phone uses, so the reply draws the same subset of Markdown as every other surface: paragraphs,
|
|
158
|
-
bold, italics, inline code, bullet and numbered lists, simple tables (scrolling sideways),
|
|
159
|
-
headings, code blocks and rules. A link shows only when its href has the form `scheme:kind/id`
|
|
160
|
-
and `resolveLink(href)` returns something; pressing it calls `onLinkPress(target)`. A web address
|
|
161
|
-
never opens, and shows its label as plain text.
|
|
162
|
-
- **`ReplyRating`**: Helpful and Not helpful under a stored reply; Not helpful then offers an
|
|
163
|
-
optional note (`noteMaxLength`, default 1000).
|
|
164
|
-
- **`ActionCard`**: one support action under a reply, with Confirm and Not now. It moves through
|
|
165
|
-
sending to done (with View ticket when `onViewTicket` is given); an expired action shows
|
|
166
|
-
without a button. `confirmAction(token)` is mobile-support's `supportClient.confirmAction`.
|
|
167
|
-
- **`ChatConversationList`**: past chats, newest first: `client`, `onOpen(conversation)`,
|
|
168
|
-
`onDeleted(id)`, `pageSize` (default 20). Show more, pull to refresh, delete after a confirm,
|
|
169
|
-
and empty and error states with Try again.
|
|
170
|
-
- **`ChatLauncher`**: an optional floating button (`onPress`, `position` `end` or `start`,
|
|
171
|
-
`bottomOffset` to clear a tab bar, `compact`). Most apps open the chat from a header action or a
|
|
172
|
-
Help row instead.
|
|
173
|
-
|
|
174
|
-
The labels the new parts read, all keys of `DEFAULT_CHAT_LABELS`: `copy` and `copied` (the reply's
|
|
175
|
-
Copy action and its confirmation); `toolStep(toolName)` (the waiting line while the assistant runs a
|
|
176
|
-
tool; it receives the server's tool name and defaults to "Looking this up", so the app maps each
|
|
177
|
-
tool to the person's words); `suggestions` (the heading over suggested questions); `renameConversation`, `conversationTitle`,
|
|
178
|
-
`renameSave` and `renameFailed` (the rename dialog in `ChatConversationList`).
|
|
179
|
-
|
|
180
|
-
`ChatConversationList` pages by `page` and `pageSize` (default 20) and renames a chat in place
|
|
181
|
-
through `renameConversation`.
|
|
182
|
-
|
|
183
|
-
`renderReply(turn, { streaming })` on `ChatScreen`, `ChatThread` or `ChatMessage` draws each
|
|
184
|
-
assistant reply your way (charts, maths); the question, thinking state, errors, action cards and
|
|
185
|
-
rating stay the library's.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ActionCard=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const titleOf=(e,i)=>"Reply"===e.kind?i.actionReply(e.ticketNumber??""):"Reopen"===e.kind?i.actionReopen(e.ticketNumber??""):i.actionRaiseTicket,doneText=(e,i,t)=>"Reply"===e.kind?t.actionDoneReply(i):"Reopen"===e.kind?t.actionDoneReopen(i):t.actionDoneRaiseTicket(i),ActionCard=({action:e,confirmAction:i,onViewTicket:t,labels:n,testID:s="chat-action"})=>{const a=(0,_chat.mergeLabels)(n),o=(0,_mobileUi.useTheme)(),[r,c]=(0,_react.useState)("ready"),[l,d]=(0,_react.useState)(null),[m,x]=(0,_react.useState)("");if("dismissed"===r)return(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&l)return(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"success",message:doneText(e,l.number,a),actions:t?[{label:a.viewTicket,onPress:()=>t(l)}]:void 0,testID:s});const u="sending"===r,_=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",testID:s,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",children:titleOf(e,a)}),""!==b&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",children:e.body}):null,_?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionConfirm,size:"sm",loading:u,disabled:u,onPress:()=>{(async()=>{c("sending"),x("");try{d(await i(e.token)),c("done")}catch(e){const i=e?.message;x("string"==typeof i&&i?i:a.actionFailed),c("ready")}})()},testID:`${s}-confirm`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:u,onPress:()=>c("dismissed"),testID:`${s}-dismiss`})]})]})]})})};exports.ActionCard=ActionCard;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatComposer=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_ComposerAttachments=require("./ComposerAttachments.js"),_jsxRuntime=require("react/jsx-runtime");const ChatComposer=({onSubmit:e,busy:t=!1,onStop:s,disabled:a=!1,maxLength:o=4e3,above:n,below:i,keyboardAware:r,keyboardOffset:c,safeArea:l,attachments:m=[],onAttach:d,onRemoveAttachment:b,editing:u,onCancelEdit:h,labels:p,testID:x="chat-composer"})=>{const _=(0,_chat.mergeLabels)(p),j=m.some(e=>"Uploading"===e.status),C=m.some(e=>"Ready"===e.status),[g,v]=(0,_react.useState)("");(0,_react.useEffect)(()=>{v(u?u.text:"")},[u]);const y=u?(0,_jsxRuntime.jsx)(_mobileUi.Banner,{message:_.editing,accessibilityRole:"summary",actions:h?[{label:_.cancel,onPress:h,testID:`${x}-cancel-edit`}]:void 0,testID:`${x}-editing`}):null,R=m.length>0?(0,_jsxRuntime.jsx)(_ComposerAttachments.ComposerAttachments,{attachments:m,onRemove:b,labels:p,testID:`${x}-attachments`}):null,A=y||R||n?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[y,R,n]}):void 0,f=d?(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"paperclip",accessibilityLabel:_.attach,variant:"ghost",tone:"neutral",disabled:a||t,onPress:d,testID:`${x}-attach`}):void 0;return(0,_jsxRuntime.jsx)(_mobileUi.Composer,{onSend:e,value:g,onChangeText:v,loading:t,onStop:s,stopLabel:_.stop,disabled:a,maxLength:o,canSend:!j&&(!!C||void 0),placeholder:_.placeholder,accessibilityLabel:_.composer,labels:{send:_.send},leading:f,above:A,below:i,keyboardAware:r,keyboardOffset:c,safeArea:l,testID:x})};exports.ChatComposer=ChatComposer;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatConversationList=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileCore=require("@webority/mobile-core"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const messageOf=(e,t)=>{const i=e?.message;return"string"==typeof i&&i?i:t},IDLE_STATE={items:[],totalCount:null,loading:!0,error:null,hasMore:!1},IDLE={getState:()=>IDLE_STATE,subscribe:()=>()=>{}},ChatConversationList=({client:e,onOpen:t,onDeleted:i,pageSize:s=20,labels:n,style:a,testID:r="chat-conversations"})=>{const l=(0,_chat.mergeLabels)(n),o=(0,_mobileUi.useTheme)(),[c,m]=(0,_react.useState)(null),u=c??IDLE,{items:d,loading:_,error:b,hasMore:x}=(0,_react.useSyncExternalStore)(u.subscribe,u.getState),[g,j]=(0,_react.useState)(!1),[h,p]=(0,_react.useState)(null),[v,y]=(0,_react.useState)(!1),[S,f]=(0,_react.useState)(""),[I,C]=(0,_react.useState)(null),[R,D]=(0,_react.useState)(""),[U,L]=(0,_react.useState)(!1),[T,w]=(0,_react.useState)(""),[E,$]=(0,_react.useState)(void 0),[P,O]=(0,_react.useState)("");(0,_react.useEffect)(()=>{const t=(0,_chat.createConversationList)({client:e,pageSize:s});return m(t),t.load(),()=>t.dispose()},[e,s]),(0,_react.useEffect)(()=>{let t=!0;return e.getSettings().then(e=>{t&&$(e.titleMaxLength)},e=>{t&&O(messageOf(e,l.renameFailed))}),()=>{t=!1}},[e,l.renameFailed]);const M=R.trim(),save=async()=>{if(I&&""!==M){L(!0),w("");try{await(c?.rename(I.publicId,M)),C(null)}catch(e){w(messageOf(e,l.renameFailed))}finally{L(!1)}}},q=!_&&!b&&0===d.length;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:a,contentContainerStyle:{padding:o.space.md,gap:o.space.sm,flexGrow:1},refreshControl:(0,_jsxRuntime.jsx)(_reactNative.RefreshControl,{refreshing:g,onRefresh:()=>{(async()=>{j(!0),await(c?.load()),j(!1)})()}}),accessibilityLabel:l.conversations,testID:r,children:[b&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:b.message||l.loadFailed,actions:[{label:l.retry,onPress:()=>{c?.load()}}],testID:`${r}-error`}),q&&(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{size:"sm",title:l.conversationsEmptyTitle,description:l.conversationsEmptyText,testID:`${r}-empty`}),d.map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||l.untitled,testID:`${r}-item-${e.publicId}`,children:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:o.space.sm},children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,minWidth:0},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"label",numberOfLines:1,children:e.title||l.untitled}),(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",children:(0,_mobileCore.formatDateTime)(e.lastMessageDateTimeUtc)})]}),(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"edit",variant:"ghost",accessibilityLabel:l.renameConversation,onPress:()=>{w(""),D(e.title??""),C(e)},testID:`${r}-rename-${e.publicId}`}),(0,_jsxRuntime.jsx)(_mobileUi.IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:l.deleteConversation,onPress:()=>{f(""),p(e)},testID:`${r}-delete-${e.publicId}`})]})},e.publicId)),_&&!g&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:o.space.sm},accessibilityElementsHidden:!0,children:[(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56}),(0,_jsxRuntime.jsx)(_mobileUi.Skeleton,{height:56})]}),!_&&x&&(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:l.loadMore,variant:"outline",onPress:()=>{c?.loadMore()},testID:`${r}-more`}),(0,_jsxRuntime.jsxs)(_mobileUi.Dialog,{visible:null!==I,onClose:()=>{U||C(null)},title:l.renameConversation,dismissOnAction:!1,actions:[{label:l.cancel,tone:"neutral",disabled:U,onPress:()=>C(null)},{label:l.renameSave,disabled:""===M||U,loading:U,onPress:()=>{save()}}],testID:`${r}-rename`,children:[(0,_jsxRuntime.jsx)(_mobileUi.Input,{label:l.conversationTitle,value:R,onChangeText:D,maxLength:E,returnKeyType:"done",onSubmitEditing:()=>{save()},testID:`${r}-rename-input`}),""!==(T||P)&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"danger",testID:`${r}-rename-error`,children:T||P})]}),(0,_jsxRuntime.jsx)(_mobileUi.Dialog,{visible:null!==h,onClose:()=>{v||p(null)},tone:"warning",title:l.deleteConfirmTitle,message:S||l.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:l.cancel,tone:"neutral",disabled:v,onPress:()=>p(null)},{label:l.deleteConfirm,tone:"danger",loading:v,onPress:()=>{(async()=>{if(h){y(!0),f("");try{await(c?.remove(h.publicId)),i?.(h.publicId),p(null)}catch(e){f(messageOf(e,l.deleteFailed))}finally{y(!1)}}})()}}],testID:`${r}-confirm`})]})};exports.ChatConversationList=ChatConversationList;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatLauncher=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");const ChatLauncher=({onPress:e,position:t="end",bottomOffset:o,compact:r=!1,labels:i,testID:s="chat-launcher"})=>{const a=(0,_chat.mergeLabels)(i);return(0,_jsxRuntime.jsx)(_mobileUi.FloatingActionButton,{icon:"messages",label:r?void 0:a.launcher,accessibilityLabel:a.launcher,position:"end"===t?"bottomRight":"bottomLeft",bottomOffset:o,onPress:e,testID:s})};exports.ChatLauncher=ChatLauncher;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMarkdown=ChatMarkdown;var _mobileUi=require("@webority/mobile-ui"),_jsxRuntime=require("react/jsx-runtime");function ChatMarkdown({text:e,resolveLink:i,onLinkPress:t,isCitation:n,onOpenCitation:r,testID:o}){return(0,_jsxRuntime.jsx)(_mobileUi.Markdown,{links:"app",headings:"text",resolveLink:i,onAppLinkPress:t,isCitation:n,onOpenCitation:r,testID:o,children:e})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatMessage=void 0;var _markdownCore=require("@webority/markdown-core"),_chat=require("@webority/markdown-core/chat"),_clipboard=require("@webority/mobile-core/clipboard"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_ActionCard=require("./ActionCard.js"),_ChatMarkdown=require("./ChatMarkdown.js"),_ReplyRating=require("./ReplyRating.js"),_jsxRuntime=require("react/jsx-runtime");function ChatMessageView({turn:e,canRegenerate:t=!1,onRetry:i,onRegenerate:s,onEdit:n,onOpenAttachment:a,onRate:r,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m,onAskSuggestion:u,confirmAction:x,onViewTicket:_,renderReply:p,labels:g,testID:d="chat-message"}){const b=(0,_chat.mergeLabels)(g),j=(0,_mobileUi.useTheme)(),[w,R]=(0,_react.useState)(!1),h=(0,_react.useRef)(null);(0,_react.useEffect)(()=>()=>{null!==h.current&&clearTimeout(h.current)},[]);const y=e.streaming&&!e.answer,k=(0,_react.useMemo)(()=>e.streaming?e.answer:(0,_markdownCore.markdownToPlainText)(e.answer),[e.streaming,e.answer]),C=(0,_react.useMemo)(()=>({you:b.you}),[b.you]),v=!e.streaming&&(e.stopped||null!==e.error),I=!e.streaming&&null!==e.questionId,T=e.attachments.length>0||e.stopped||i&&v||n&&I?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:j.space.xs},children:[e.attachments.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:e.attachments.map(e=>(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e.fileName,onPress:a?()=>a(e):void 0,testID:`${d}-attachment-${e.publicId}`},e.publicId))}):null,e.stopped?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"secondary",accessibilityLiveRegion:"polite",testID:`${d}-stopped`,children:b.stopped}):null,i&&v||n&&I?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:[i&&v?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.retry,variant:"link",size:"sm",onPress:()=>i(e.id),testID:`${d}-retry`}):null,n&&I?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.edit,variant:"link",size:"sm",onPress:()=>n(e.id),testID:`${d}-edit`}):null]}):null]}):null;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:j.space.sm},testID:d,children:[""!==e.question&&(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"mine",text:e.question,labels:C,footer:T,testID:`${d}-question`}),y?(0,_jsxRuntime.jsx)(_mobileUi.TypingIndicator,{label:b.thinking,testID:`${d}-thinking`}):null,""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.MessageBubble,{side:"theirs",author:b.assistant,text:k,streaming:e.streaming,onCopy:()=>{(0,_clipboard.copyText)((0,_markdownCore.markdownToPlainText)(e.answer))},testID:`${d}-answer`,children:p?p(e,{streaming:e.streaming}):(0,_jsxRuntime.jsx)(_ChatMarkdown.ChatMarkdown,{text:e.answer,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m})}):null,e.streaming&&e.step?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",testID:`${d}-step`,children:b.toolStep(e.step)}):null,e.streaming||""===e.answer?null:(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:w?b.copied:b.copy,variant:"link",size:"sm",onPress:()=>{(async()=>{await(0,_clipboard.copyText)((0,_markdownCore.markdownToPlainText)(e.answer))&&(R(!0),null!==h.current&&clearTimeout(h.current),h.current=setTimeout(()=>R(!1),2e3))})()},testID:`${d}-copy`}),u&&!e.streaming&&e.suggestions.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{accessibilityRole:"list",accessibilityLabel:b.suggestions,style:{flexDirection:"row",flexWrap:"wrap",gap:j.space.xs},children:e.suggestions.map((e,t)=>(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e,onPress:()=>u(e),testID:`${d}-suggestion-${t}`},e))}):null,t&&s&&!e.streaming&&""!==e.answer?(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:b.regenerate,variant:"link",size:"sm",onPress:()=>s(e.id),testID:`${d}-regenerate`}):null,e.error&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),x&&!e.streaming&&e.actions.map(e=>(0,_jsxRuntime.jsx)(_ActionCard.ActionCard,{action:e,confirmAction:x,onViewTicket:_,labels:g},e.token)),r&&e.messageId&&!e.streaming&&(0,_jsxRuntime.jsx)(_ReplyRating.ReplyRating,{rating:e.rating,onRate:(t,i)=>r(e.id,t,i),labels:g})]})}const ChatMessage=exports.ChatMessage=(0,_react.memo)(ChatMessageView);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatScreen=ChatScreen;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_reactNative=require("react-native"),_ChatComposer=require("./ChatComposer.js"),_ChatThread=require("./ChatThread.js"),_jsxRuntime=require("react/jsx-runtime");function ChatScreen({chat:e,pickAttachments:t,onOpenAttachment:s,title:i,headerActions:a,empty:n,disclaimer:r,maxLength:o=4e3,allowanceThreshold:l=10,rating:m=!0,keyboardOffset:c,testID:d="chat-screen",...h}){const u=(0,_chat.mergeLabels)(h.labels),x=(0,_mobileUi.useTheme)(),b=e.messagesLeftToday,g=void 0===r?u.disclaimer:r,_=t&&e.settings?.attachments?async()=>e.attach(await t()):void 0;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flex:1,backgroundColor:x.colors.bg},testID:d,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",alignItems:"center",gap:x.space.sm,paddingHorizontal:x.space.md,paddingVertical:x.space.sm,borderBottomWidth:1,borderBottomColor:x.colors["border-subtle"]},children:[(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:i??u.panelTitle}),a,(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:u.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${d}-new`})]}),e.loading?(0,_jsxRuntime.jsx)(_reactNative.View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:(0,_jsxRuntime.jsx)(_mobileUi.Spinner,{message:u.loadingConversation,testID:`${d}-loading`})}):(0,_jsxRuntime.jsx)(_ChatThread.ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:c,onRate:m?e.rate:void 0,onRetry:e.retry,onRegenerate:e.regenerate,onEdit:e.startEdit,onOpenAttachment:s,empty:n??(0,_jsxRuntime.jsx)(_mobileUi.EmptyState,{fill:!0,size:"sm",title:u.emptyTitle,description:u.emptyText,testID:`${d}-empty`}),testID:`${d}-thread`,...h,onAskSuggestion:e.submit}),(0,_jsxRuntime.jsx)(_ChatComposer.ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,onStop:e.stop,disabled:0===b||e.loading,maxLength:o,keyboardOffset:c,labels:h.labels,onAttach:_,attachments:e.attachments,onRemoveAttachment:t=>{e.removeAttachment(t)},editing:e.editing,onCancelEdit:e.cancelEdit,testID:`${d}-composer`,above:(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[e.loadError&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:e.loadError.message,testID:`${d}-load-error`}),e.settingsError&&(0,_jsxRuntime.jsx)(_mobileUi.Banner,{tone:"danger",message:e.settingsError.message,testID:`${d}-settings-error`}),null!==b&&b<=l&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:0===b?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${d}-allowance`,children:u.allowance(b)})]}),below:g?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"tertiary",testID:`${d}-disclaimer`,children:g}):null})]})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ChatThread=ChatThread;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_ChatMessage=require("./ChatMessage.js"),_jsxRuntime=require("react/jsx-runtime");const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=(0,_mobileUi.useTheme)();return(0,_jsxRuntime.jsx)(_reactNative.View,{style:{height:e.space.lg}})};function ChatThread({turns:e,empty:t,keyboardAware:r,keyboardOffset:a,onRetry:s,onRegenerate:n,onEdit:i,onOpenAttachment:o,onAskSuggestion:u,style:c,testID:l="chat-thread",...d}){const m=(0,_chat.mergeLabels)(d.labels),h=(0,_react.useMemo)(()=>[...e].reverse(),[e]),g=(0,_react.useMemo)(()=>{const t=e[e.length-1];return t&&null!==t.messageId&&!t.streaming?t.id:null},[e]),y=e[e.length-1]?.id;return(0,_jsxRuntime.jsx)(_mobileUi.MessageList,{messages:h,keyExtractor:turnKey,renderMessage:({item:e})=>(0,_jsxRuntime.jsx)(_ChatMessage.ChatMessage,{turn:e,onRetry:s,canRegenerate:e.id===g,onRegenerate:e.id===g?n:void 0,onEdit:i,onOpenAttachment:o,testID:`${l}-${e.id}`,...d,onAskSuggestion:e.id===y?u:void 0}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:r,keyboardOffset:a,accessibilityLabel:m.thread,style:c,testID:l})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ComposerAttachments=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const ComposerAttachments=({attachments:e,onRemove:t,labels:r,testID:s="composer-attachments"})=>{const a=(0,_mobileUi.useTheme)(),i=(0,_react.useMemo)(()=>buildStyles(a),[a]),o=(0,_chat.mergeLabels)(r),m=(0,_react.useMemo)(()=>({remove:o.removeAttachment}),[o.removeAttachment]);return(0,_jsxRuntime.jsx)(_reactNative.View,{style:i.root,testID:s,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:i.row,children:e.map(e=>(0,_jsxRuntime.jsxs)(_reactNative.View,{style:i.item,children:[(0,_jsxRuntime.jsx)(_mobileUi.Chip,{label:e.fileName,variant:"soft",onRemove:t?()=>t(e.key):void 0,labels:m,removeTestID:`chat-attachment-remove-${e.key}`,testID:`${s}-${e.key}`}),"Uploading"===e.status?(0,_jsxRuntime.jsx)(_mobileUi.ProgressBar,{progress:e.progress??void 0,label:o.attachmentUploading,height:4,containerStyle:i.progress}):null,"Failed"===e.status?(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:o.attachmentFailed}):null]},e.key))})})};exports.ComposerAttachments=ComposerAttachments;const buildStyles=e=>_reactNative.StyleSheet.create({root:{gap:e.space.xs},row:{flexDirection:"row",flexWrap:"wrap",gap:e.space.xs},item:{gap:e.space.xxs,maxWidth:"100%"},progress:{minWidth:120}});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ReplyRating=void 0;var _chat=require("@webority/markdown-core/chat"),_mobileUi=require("@webority/mobile-ui"),_react=require("react"),_reactNative=require("react-native"),_jsxRuntime=require("react/jsx-runtime");const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:i=1e3,labels:a,testID:s="chat-rating"})=>{const n=(0,_chat.mergeLabels)(a),r=(0,_mobileUi.useTheme)(),[l,o]=(0,_react.useState)(!1),[c,d]=(0,_react.useState)(!1),[u,m]=(0,_react.useState)(""),[x,_]=(0,_react.useState)(""),[b,p]=(0,_react.useState)(!1),save=async(e,i)=>{o(!0),_("");try{await t(e,i),d("Down"===e&&void 0===i),p("Up"===e||void 0!==i),void 0!==i&&m("")}catch{_(n.ratingFailed)}finally{o(!1)}};return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:r.space.sm},testID:s,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:r.space.xs},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:l},"aria-selected":"Up"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Up")},testID:`${s}-up`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:l},"aria-selected":"Down"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Down")},testID:`${s}-down`}),b&&!c&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:n.rated})]}),""!==x&&(0,_jsxRuntime.jsx)(_mobileUi.Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:x}),c&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{gap:r.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Input,{label:n.ratingNote,helperText:n.ratingNoteHint,multiline:!0,maxLength:i,value:u,onChangeText:m,testID:`${s}-note`}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:{flexDirection:"row",gap:r.space.sm},children:[(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.ratingNoteSend,size:"sm",loading:l,disabled:l,onPress:()=>{save("Down",u)},testID:`${s}-note-send`}),(0,_jsxRuntime.jsx)(_mobileUi.Button,{label:n.ratingNoteSkip,size:"sm",variant:"outline",disabled:l,onPress:()=>{d(!1),p(!0)},testID:`${s}-note-skip`})]})]})]})};exports.ReplyRating=ReplyRating;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Button,Card,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const titleOf=(e,t)=>"Reply"===e.kind?t.actionReply(e.ticketNumber??""):"Reopen"===e.kind?t.actionReopen(e.ticketNumber??""):t.actionRaiseTicket,doneText=(e,t,i)=>"Reply"===e.kind?i.actionDoneReply(t):"Reopen"===e.kind?i.actionDoneReopen(t):i.actionDoneRaiseTicket(t);export const ActionCard=({action:e,confirmAction:t,onViewTicket:i,labels:n,testID:s="chat-action"})=>{const a=mergeLabels(n),o=useTheme(),[r,c]=useState("ready"),[l,d]=useState(null),[m,x]=useState("");if("dismissed"===r)return _jsx(Text,{variant:"bodySmall",color:"secondary",testID:s,children:a.actionDismissed});if("done"===r&&l)return _jsx(Banner,{tone:"success",message:doneText(e,l.number,a),actions:i?[{label:a.viewTicket,onPress:()=>i(l)}]:void 0,testID:s});const p="sending"===r,y=new Date(e.expiresDateTimeUtc).getTime()<=Date.now(),b="RaiseTicket"===e.kind?[e.category,e.subject].filter(Boolean).join(", "):"";return _jsx(Card,{variant:"outline",padding:"sm",testID:s,children:_jsxs(View,{style:{gap:o.space.sm},children:[_jsx(Text,{variant:"label",children:titleOf(e,a)}),""!==b&&_jsx(Text,{variant:"bodySmall",color:"secondary",children:b}),"Reopen"!==e.kind&&e.body?_jsx(Text,{variant:"bodySmall",children:e.body}):null,y?_jsx(Text,{variant:"bodySmall",color:"secondary",children:a.actionExpired}):_jsxs(_Fragment,{children:[_jsx(Text,{variant:"caption",color:"secondary",children:a.actionNote}),""!==m&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:m}),_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:o.space.sm},children:[_jsx(Button,{label:a.actionConfirm,size:"sm",loading:p,disabled:p,onPress:()=>{(async()=>{c("sending"),x("");try{d(await t(e.token)),c("done")}catch(e){const t=e?.message;x("string"==typeof t&&t?t:a.actionFailed),c("ready")}})()},testID:`${s}-confirm`}),_jsx(Button,{label:a.actionDismiss,size:"sm",variant:"outline",disabled:p,onPress:()=>c("dismissed"),testID:`${s}-dismiss`})]})]})]})})};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Composer,IconButton}from"@webority/mobile-ui";import{useEffect,useState}from"react";import{ComposerAttachments}from"./ComposerAttachments.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";export const ChatComposer=({onSubmit:e,busy:t=!1,onStop:s,disabled:a=!1,maxLength:o=4e3,above:n,below:r,keyboardAware:i,keyboardOffset:c,safeArea:m,attachments:l=[],onAttach:d,onRemoveAttachment:b,editing:p,onCancelEdit:h,labels:u,testID:g="chat-composer"})=>{const f=mergeLabels(u),x=l.some(e=>"Uploading"===e.status),y=l.some(e=>"Ready"===e.status),[j,v]=useState("");useEffect(()=>{v(p?p.text:"")},[p]);const A=p?_jsx(Banner,{message:f.editing,accessibilityRole:"summary",actions:h?[{label:f.cancel,onPress:h,testID:`${g}-cancel-edit`}]:void 0,testID:`${g}-editing`}):null,C=l.length>0?_jsx(ComposerAttachments,{attachments:l,onRemove:b,labels:u,testID:`${g}-attachments`}):null,_=A||C||n?_jsxs(_Fragment,{children:[A,C,n]}):void 0,I=d?_jsx(IconButton,{icon:"paperclip",accessibilityLabel:f.attach,variant:"ghost",tone:"neutral",disabled:a||t,onPress:d,testID:`${g}-attach`}):void 0;return _jsx(Composer,{onSend:e,value:j,onChangeText:v,loading:t,onStop:s,stopLabel:f.stop,disabled:a,maxLength:o,canSend:!x&&(!!y||void 0),placeholder:f.placeholder,accessibilityLabel:f.composer,labels:{send:f.send},leading:I,above:_,below:r,keyboardAware:i,keyboardOffset:c,safeArea:m,testID:g})};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{createConversationList,mergeLabels}from"@webority/markdown-core/chat";import{formatDateTime}from"@webority/mobile-core";import{Banner,Button,Card,Dialog,EmptyState,IconButton,Input,Skeleton,Text,useTheme}from"@webority/mobile-ui";import{useEffect,useState,useSyncExternalStore}from"react";import{RefreshControl,ScrollView,View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const messageOf=(e,t)=>{const s=e?.message;return"string"==typeof s&&s?s:t},IDLE_STATE={items:[],totalCount:null,loading:!0,error:null,hasMore:!1},IDLE={getState:()=>IDLE_STATE,subscribe:()=>()=>{}};export const ChatConversationList=({client:e,onOpen:t,onDeleted:s,pageSize:n=20,labels:a,style:i,testID:l="chat-conversations"})=>{const r=mergeLabels(a),o=useTheme(),[c,m]=useState(null),d=c??IDLE,{items:u,loading:g,error:b,hasMore:p}=useSyncExternalStore(d.subscribe,d.getState),[x,h]=useState(!1),[f,S]=useState(null),[y,I]=useState(!1),[j,v]=useState(""),[D,_]=useState(null),[C,T]=useState(""),[E,w]=useState(!1),[L,$]=useState(""),[P,O]=useState(void 0),[B,M]=useState("");useEffect(()=>{const t=createConversationList({client:e,pageSize:n});return m(t),t.load(),()=>t.dispose()},[e,n]),useEffect(()=>{let t=!0;return e.getSettings().then(e=>{t&&O(e.titleMaxLength)},e=>{t&&M(messageOf(e,r.renameFailed))}),()=>{t=!1}},[e,r.renameFailed]);const V=C.trim(),save=async()=>{if(D&&""!==V){w(!0),$("");try{await(c?.rename(D.publicId,V)),_(null)}catch(e){$(messageOf(e,r.renameFailed))}finally{w(!1)}}},k=!g&&!b&&0===u.length;return _jsxs(ScrollView,{style:i,contentContainerStyle:{padding:o.space.md,gap:o.space.sm,flexGrow:1},refreshControl:_jsx(RefreshControl,{refreshing:x,onRefresh:()=>{(async()=>{h(!0),await(c?.load()),h(!1)})()}}),accessibilityLabel:r.conversations,testID:l,children:[b&&_jsx(Banner,{tone:"danger",message:b.message||r.loadFailed,actions:[{label:r.retry,onPress:()=>{c?.load()}}],testID:`${l}-error`}),k&&_jsx(EmptyState,{size:"sm",title:r.conversationsEmptyTitle,description:r.conversationsEmptyText,testID:`${l}-empty`}),u.map(e=>_jsx(Card,{variant:"outline",padding:"sm",onPress:()=>t(e),accessibilityLabel:e.title||r.untitled,testID:`${l}-item-${e.publicId}`,children:_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:o.space.sm},children:[_jsxs(View,{style:{flex:1,minWidth:0},children:[_jsx(Text,{variant:"label",numberOfLines:1,children:e.title||r.untitled}),_jsx(Text,{variant:"caption",color:"secondary",children:formatDateTime(e.lastMessageDateTimeUtc)})]}),_jsx(IconButton,{icon:"edit",variant:"ghost",accessibilityLabel:r.renameConversation,onPress:()=>{$(""),T(e.title??""),_(e)},testID:`${l}-rename-${e.publicId}`}),_jsx(IconButton,{icon:"trash",tone:"danger",variant:"ghost",accessibilityLabel:r.deleteConversation,onPress:()=>{v(""),S(e)},testID:`${l}-delete-${e.publicId}`})]})},e.publicId)),g&&!x&&_jsxs(View,{style:{gap:o.space.sm},accessibilityElementsHidden:!0,children:[_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56}),_jsx(Skeleton,{height:56})]}),!g&&p&&_jsx(Button,{label:r.loadMore,variant:"outline",onPress:()=>{c?.loadMore()},testID:`${l}-more`}),_jsxs(Dialog,{visible:null!==D,onClose:()=>{E||_(null)},title:r.renameConversation,dismissOnAction:!1,actions:[{label:r.cancel,tone:"neutral",disabled:E,onPress:()=>_(null)},{label:r.renameSave,disabled:""===V||E,loading:E,onPress:()=>{save()}}],testID:`${l}-rename`,children:[_jsx(Input,{label:r.conversationTitle,value:C,onChangeText:T,maxLength:P,returnKeyType:"done",onSubmitEditing:()=>{save()},testID:`${l}-rename-input`}),""!==(L||B)&&_jsx(Text,{variant:"caption",color:"danger",testID:`${l}-rename-error`,children:L||B})]}),_jsx(Dialog,{visible:null!==f,onClose:()=>{y||S(null)},tone:"warning",title:r.deleteConfirmTitle,message:j||r.deleteConfirmMessage,dismissOnAction:!1,actions:[{label:r.cancel,tone:"neutral",disabled:y,onPress:()=>S(null)},{label:r.deleteConfirm,tone:"danger",loading:y,onPress:()=>{(async()=>{if(f){I(!0),v("");try{await(c?.remove(f.publicId)),s?.(f.publicId),S(null)}catch(e){v(messageOf(e,r.deleteFailed))}finally{I(!1)}}})()}}],testID:`${l}-confirm`})]})};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{FloatingActionButton}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export const ChatLauncher=({onPress:t,position:o="end",bottomOffset:e,compact:s=!1,labels:r,testID:i="chat-launcher"})=>{const n=mergeLabels(r);return _jsx(FloatingActionButton,{icon:"messages",label:s?void 0:n.launcher,accessibilityLabel:n.launcher,position:"end"===o?"bottomRight":"bottomLeft",bottomOffset:e,onPress:t,testID:i})};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{Markdown}from"@webority/mobile-ui";import{jsx as _jsx}from"react/jsx-runtime";export function ChatMarkdown({text:t,resolveLink:i,onLinkPress:n,isCitation:e,onOpenCitation:o,testID:r}){return _jsx(Markdown,{links:"app",headings:"text",resolveLink:i,onAppLinkPress:n,isCitation:e,onOpenCitation:o,testID:r,children:t})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{markdownToPlainText}from"@webority/markdown-core";import{mergeLabels}from"@webority/markdown-core/chat";import{copyText}from"@webority/mobile-core/clipboard";import{Button,Chip,MessageBubble,Text,TypingIndicator,useTheme}from"@webority/mobile-ui";import{memo,useEffect,useMemo,useRef,useState}from"react";import{View}from"react-native";import{ActionCard}from"./ActionCard.js";import{ChatMarkdown}from"./ChatMarkdown.js";import{ReplyRating}from"./ReplyRating.js";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function ChatMessageView({turn:e,canRegenerate:t=!1,onRetry:s,onRegenerate:n,onEdit:i,onOpenAttachment:a,onRate:r,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m,onAskSuggestion:p,confirmAction:u,onViewTicket:g,renderReply:d,labels:x,testID:w="chat-message"}){const y=mergeLabels(x),b=useTheme(),[h,j]=useState(!1),f=useRef(null);useEffect(()=>()=>{null!==f.current&&clearTimeout(f.current)},[]);const T=e.streaming&&!e.answer,k=useMemo(()=>e.streaming?e.answer:markdownToPlainText(e.answer),[e.streaming,e.answer]),_=useMemo(()=>({you:y.you}),[y.you]),I=!e.streaming&&(e.stopped||null!==e.error),R=!e.streaming&&null!==e.questionId,C=e.attachments.length>0||e.stopped||s&&I||i&&R?_jsxs(View,{style:{gap:b.space.xs},children:[e.attachments.length>0?_jsx(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:e.attachments.map(e=>_jsx(Chip,{label:e.fileName,onPress:a?()=>a(e):void 0,testID:`${w}-attachment-${e.publicId}`},e.publicId))}):null,e.stopped?_jsx(Text,{variant:"bodySmall",color:"secondary",accessibilityLiveRegion:"polite",testID:`${w}-stopped`,children:y.stopped}):null,s&&I||i&&R?_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:[s&&I?_jsx(Button,{label:y.retry,variant:"link",size:"sm",onPress:()=>s(e.id),testID:`${w}-retry`}):null,i&&R?_jsx(Button,{label:y.edit,variant:"link",size:"sm",onPress:()=>i(e.id),testID:`${w}-edit`}):null]}):null]}):null;return _jsxs(View,{style:{gap:b.space.sm},testID:w,children:[""!==e.question&&_jsx(MessageBubble,{side:"mine",text:e.question,labels:_,footer:C,testID:`${w}-question`}),T?_jsx(TypingIndicator,{label:y.thinking,testID:`${w}-thinking`}):null,""!==e.answer?_jsx(MessageBubble,{side:"theirs",author:y.assistant,text:k,streaming:e.streaming,onCopy:()=>{copyText(markdownToPlainText(e.answer))},testID:`${w}-answer`,children:d?d(e,{streaming:e.streaming}):_jsx(ChatMarkdown,{text:e.answer,resolveLink:o,onLinkPress:l,isCitation:c,onOpenCitation:m})}):null,e.streaming&&e.step?_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",testID:`${w}-step`,children:y.toolStep(e.step)}):null,e.streaming||""===e.answer?null:_jsx(Button,{label:h?y.copied:y.copy,variant:"link",size:"sm",onPress:()=>{(async()=>{await copyText(markdownToPlainText(e.answer))&&(j(!0),null!==f.current&&clearTimeout(f.current),f.current=setTimeout(()=>j(!1),2e3))})()},testID:`${w}-copy`}),p&&!e.streaming&&e.suggestions.length>0?_jsx(View,{accessibilityRole:"list",accessibilityLabel:y.suggestions,style:{flexDirection:"row",flexWrap:"wrap",gap:b.space.xs},children:e.suggestions.map((e,t)=>_jsx(Chip,{label:e,onPress:()=>p(e),testID:`${w}-suggestion-${t}`},e))}):null,t&&n&&!e.streaming&&""!==e.answer?_jsx(Button,{label:y.regenerate,variant:"link",size:"sm",onPress:()=>n(e.id),testID:`${w}-regenerate`}):null,e.error&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:e.error.message}),u&&!e.streaming&&e.actions.map(e=>_jsx(ActionCard,{action:e,confirmAction:u,onViewTicket:g,labels:x},e.token)),r&&e.messageId&&!e.streaming&&_jsx(ReplyRating,{rating:e.rating,onRate:(t,s)=>r(e.id,t,s),labels:x})]})}export const ChatMessage=memo(ChatMessageView);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Banner,Button,EmptyState,Spinner,Text,useTheme}from"@webority/mobile-ui";import{View}from"react-native";import{ChatComposer}from"./ChatComposer.js";import{ChatThread}from"./ChatThread.js";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";export function ChatScreen({chat:e,pickAttachments:t,onOpenAttachment:s,title:a,headerActions:r,empty:n,disclaimer:o,maxLength:i=4e3,allowanceThreshold:l=10,rating:m=!0,keyboardOffset:c,testID:d="chat-screen",...g}){const h=mergeLabels(g.labels),p=useTheme(),x=e.messagesLeftToday,b=void 0===o?h.disclaimer:o,y=t&&e.settings?.attachments?async()=>e.attach(await t()):void 0;return _jsxs(View,{style:{flex:1,backgroundColor:p.colors.bg},testID:d,children:[_jsxs(View,{style:{flexDirection:"row",alignItems:"center",gap:p.space.sm,paddingHorizontal:p.space.md,paddingVertical:p.space.sm,borderBottomWidth:1,borderBottomColor:p.colors["border-subtle"]},children:[_jsx(Text,{variant:"title",accessibilityRole:"header",style:{flex:1},numberOfLines:1,children:a??h.panelTitle}),r,_jsx(Button,{label:h.newChat,size:"sm",variant:"soft",leftIcon:"add",disabled:0===e.turns.length&&!e.loading,onPress:e.newConversation,testID:`${d}-new`})]}),e.loading?_jsx(View,{style:{flex:1,alignItems:"center",justifyContent:"center"},children:_jsx(Spinner,{message:h.loadingConversation,testID:`${d}-loading`})}):_jsx(ChatThread,{turns:e.turns,style:{flex:1},keyboardOffset:c,onRate:m?e.rate:void 0,onRetry:e.retry,onRegenerate:e.regenerate,onEdit:e.startEdit,onOpenAttachment:s,empty:n??_jsx(EmptyState,{fill:!0,size:"sm",title:h.emptyTitle,description:h.emptyText,testID:`${d}-empty`}),testID:`${d}-thread`,...g,onAskSuggestion:e.submit}),_jsx(ChatComposer,{onSubmit:t=>{e.submit(t)},busy:e.streaming,onStop:e.stop,disabled:0===x||e.loading,maxLength:i,keyboardOffset:c,labels:g.labels,onAttach:y,attachments:e.attachments,onRemoveAttachment:t=>{e.removeAttachment(t)},editing:e.editing,onCancelEdit:e.cancelEdit,testID:`${d}-composer`,above:_jsxs(_Fragment,{children:[e.loadError&&_jsx(Banner,{tone:"danger",message:e.loadError.message,testID:`${d}-load-error`}),e.settingsError&&_jsx(Banner,{tone:"danger",message:e.settingsError.message,testID:`${d}-settings-error`}),null!==x&&x<=l&&_jsx(Text,{variant:"caption",color:0===x?"danger":"secondary",accessibilityLiveRegion:"polite",testID:`${d}-allowance`,children:h.allowance(x)})]}),below:b?_jsx(Text,{variant:"caption",color:"tertiary",testID:`${d}-disclaimer`,children:b}):null})]})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{MessageList,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{View}from"react-native";import{ChatMessage}from"./ChatMessage.js";import{jsx as _jsx}from"react/jsx-runtime";const turnKey=e=>e.id,followTurn=()=>!0,TurnGap=()=>{const e=useTheme();return _jsx(View,{style:{height:e.space.lg}})};export function ChatThread({turns:e,empty:t,keyboardAware:r,keyboardOffset:s,onRetry:o,onRegenerate:n,onEdit:a,onOpenAttachment:i,onAskSuggestion:m,style:u,testID:l="chat-thread",...g}){const d=mergeLabels(g.labels),c=useMemo(()=>[...e].reverse(),[e]),h=useMemo(()=>{const t=e[e.length-1];return t&&null!==t.messageId&&!t.streaming?t.id:null},[e]),y=e[e.length-1]?.id;return _jsx(MessageList,{messages:c,keyExtractor:turnKey,renderMessage:({item:e})=>_jsx(ChatMessage,{turn:e,onRetry:o,canRegenerate:e.id===h,onRegenerate:e.id===h?n:void 0,onEdit:a,onOpenAttachment:i,testID:`${l}-${e.id}`,...g,onAskSuggestion:e.id===y?m:void 0}),followNew:followTurn,empty:t,ItemSeparatorComponent:TurnGap,keyboardAware:r,keyboardOffset:s,accessibilityLabel:d.thread,style:u,testID:l})}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Chip,ProgressBar,Text,useTheme}from"@webority/mobile-ui";import{useMemo}from"react";import{StyleSheet,View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const ComposerAttachments=({attachments:e,onRemove:t,labels:s,testID:r="composer-attachments"})=>{const o=useTheme(),a=useMemo(()=>buildStyles(o),[o]),i=mergeLabels(s),m=useMemo(()=>({remove:i.removeAttachment}),[i.removeAttachment]);return _jsx(View,{style:a.root,testID:r,children:_jsx(View,{style:a.row,children:e.map(e=>_jsxs(View,{style:a.item,children:[_jsx(Chip,{label:e.fileName,variant:"soft",onRemove:t?()=>t(e.key):void 0,labels:m,removeTestID:`chat-attachment-remove-${e.key}`,testID:`${r}-${e.key}`}),"Uploading"===e.status?_jsx(ProgressBar,{progress:e.progress??void 0,label:i.attachmentUploading,height:4,containerStyle:a.progress}):null,"Failed"===e.status?_jsx(Text,{variant:"caption",color:"danger",accessibilityLiveRegion:"polite",children:i.attachmentFailed}):null]},e.key))})})};const buildStyles=e=>StyleSheet.create({root:{gap:e.space.xs},row:{flexDirection:"row",flexWrap:"wrap",gap:e.space.xs},item:{gap:e.space.xxs,maxWidth:"100%"},progress:{minWidth:120}});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";import{mergeLabels}from"@webority/markdown-core/chat";import{Button,Input,Text,useTheme}from"@webority/mobile-ui";import{useState}from"react";import{View}from"react-native";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const ReplyRating=({rating:e=null,onRate:t,noteMaxLength:s=1e3,labels:a,testID:i="chat-rating"})=>{const n=mergeLabels(a),o=useTheme(),[l,r]=useState(!1),[c,d]=useState(!1),[p,m]=useState(""),[x,b]=useState(""),[g,u]=useState(!1),save=async(e,s)=>{r(!0),b("");try{await t(e,s),d("Down"===e&&void 0===s),u("Up"===e||void 0!==s),void 0!==s&&m("")}catch{b(n.ratingFailed)}finally{r(!1)}};return _jsxs(View,{style:{gap:o.space.sm},testID:i,children:[_jsxs(View,{style:{flexDirection:"row",flexWrap:"wrap",alignItems:"center",gap:o.space.xs},children:[_jsx(Button,{label:n.rateUp,size:"sm",leftIcon:"like",variant:"Up"===e?"soft":"ghost",accessibilityState:{selected:"Up"===e,disabled:l},"aria-selected":"Up"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Up")},testID:`${i}-up`}),_jsx(Button,{label:n.rateDown,size:"sm",leftIcon:"dislike",variant:"Down"===e?"soft":"ghost",accessibilityState:{selected:"Down"===e,disabled:l},"aria-selected":"Down"===e,"aria-disabled":l,disabled:l,onPress:()=>{save("Down")},testID:`${i}-down`}),g&&!c&&_jsx(Text,{variant:"caption",color:"secondary",accessibilityLiveRegion:"polite",children:n.rated})]}),""!==x&&_jsx(Text,{variant:"bodySmall",color:"danger",accessibilityLiveRegion:"polite",children:x}),c&&_jsxs(View,{style:{gap:o.space.sm},children:[_jsx(Input,{label:n.ratingNote,helperText:n.ratingNoteHint,multiline:!0,maxLength:s,value:p,onChangeText:m,testID:`${i}-note`}),_jsxs(View,{style:{flexDirection:"row",gap:o.space.sm},children:[_jsx(Button,{label:n.ratingNoteSend,size:"sm",loading:l,disabled:l,onPress:()=>{save("Down",p)},testID:`${i}-note-send`}),_jsx(Button,{label:n.ratingNoteSkip,size:"sm",variant:"outline",disabled:l,onPress:()=>{d(!1),u(!0)},testID:`${i}-note-skip`})]})]})]})};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { SupportAction, SupportActionTicket } from "@webority/markdown-core/chat";
|
|
2
|
-
import { type ChatLabels } from "@webority/markdown-core/chat";
|
|
3
|
-
import type React from "react";
|
|
4
|
-
export interface ActionCardProps {
|
|
5
|
-
action: SupportAction;
|
|
6
|
-
/**
|
|
7
|
-
* Sends the person's yes, e.g. mobile-support's `supportClient.confirmAction`; resolves to the
|
|
8
|
-
* ticket raised, replied on or reopened. A rejection's `message` is shown when present.
|
|
9
|
-
*/
|
|
10
|
-
confirmAction: (token: string) => Promise<SupportActionTicket>;
|
|
11
|
-
/** Shows a View ticket button once confirmed. */
|
|
12
|
-
onViewTicket?: (ticket: SupportActionTicket) => void;
|
|
13
|
-
labels?: Partial<ChatLabels>;
|
|
14
|
-
testID?: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* One support action the assistant prepared, shown under its reply. Nothing reaches support until
|
|
18
|
-
* the person confirms. The card moves from ready to sending to done (with View ticket), or to
|
|
19
|
-
* dismissed on Not now. An expired action (a reopened conversation) still shows what was offered,
|
|
20
|
-
* without a button that could only fail.
|
|
21
|
-
*/
|
|
22
|
-
export declare const ActionCard: React.FC<ActionCardProps>;
|
|
23
|
-
//# sourceMappingURL=ActionCard.d.ts.map
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { type ChatEditing, type ChatLabels, type ComposerAttachment } from "@webority/markdown-core/chat";
|
|
2
|
-
import type React from "react";
|
|
3
|
-
export interface ChatComposerProps {
|
|
4
|
-
/** Called with the trimmed question; the box clears once it is handed over. */
|
|
5
|
-
onSubmit: (message: string) => unknown;
|
|
6
|
-
/** An answer is arriving: the question can be typed but not sent. */
|
|
7
|
-
busy?: boolean;
|
|
8
|
-
/** While busy, the send button becomes a stop button that calls this. */
|
|
9
|
-
onStop?: () => void;
|
|
10
|
-
/** No question can be asked, e.g. none left today. */
|
|
11
|
-
disabled?: boolean;
|
|
12
|
-
/** The server's message limit. Default 4000. */
|
|
13
|
-
maxLength?: number;
|
|
14
|
-
/** Inside the bar, above the question box: a banner, the questions left. */
|
|
15
|
-
above?: React.ReactNode;
|
|
16
|
-
/** Inside the bar, below the question box: the disclaimer. */
|
|
17
|
-
below?: React.ReactNode;
|
|
18
|
-
/** Rides the keyboard; see mobile-ui `Composer`. Default true. */
|
|
19
|
-
keyboardAware?: boolean;
|
|
20
|
-
/** See mobile-ui `Composer`. Default: the bottom safe-area inset. */
|
|
21
|
-
keyboardOffset?: number;
|
|
22
|
-
/** Pads for the bottom safe area. Default true. */
|
|
23
|
-
safeArea?: boolean;
|
|
24
|
-
/** The files on the question being written. */
|
|
25
|
-
attachments?: ComposerAttachment[];
|
|
26
|
-
/** Opens the app's file picker. The attach button shows only when this is given. */
|
|
27
|
-
onAttach?: () => void;
|
|
28
|
-
/** Removes one file by its key. */
|
|
29
|
-
onRemoveAttachment?: (key: string) => void;
|
|
30
|
-
/** The question being edited; its banner's Cancel calls `onCancelEdit`. */
|
|
31
|
-
editing?: ChatEditing | null;
|
|
32
|
-
onCancelEdit?: () => void;
|
|
33
|
-
labels?: Partial<ChatLabels>;
|
|
34
|
-
testID?: string;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* The question box and its send button, on mobile-ui's `Composer`. The return
|
|
38
|
-
* key adds a new line, as phone keyboards expect; only the button sends. The
|
|
39
|
-
* bar rides the keyboard and pads for the bottom safe area by default.
|
|
40
|
-
*/
|
|
41
|
-
export declare const ChatComposer: React.FC<ChatComposerProps>;
|
|
42
|
-
//# sourceMappingURL=ChatComposer.d.ts.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ConversationSummary } from "@webority/markdown-core/chat";
|
|
2
|
-
import { type ChatClient, type ChatLabels } from "@webority/markdown-core/chat";
|
|
3
|
-
import type React from "react";
|
|
4
|
-
import { type StyleProp, type ViewStyle } from "react-native";
|
|
5
|
-
export interface ChatConversationListProps {
|
|
6
|
-
client: ChatClient;
|
|
7
|
-
/** E.g. go to the chat and call `chat.openConversation(conversation.publicId)`. */
|
|
8
|
-
onOpen: (conversation: ConversationSummary) => void;
|
|
9
|
-
/** Called after a chat is deleted, e.g. to start a new chat when the open one was deleted. */
|
|
10
|
-
onDeleted?: (id: string) => void;
|
|
11
|
-
/** Default 20. */
|
|
12
|
-
pageSize?: number;
|
|
13
|
-
labels?: Partial<ChatLabels>;
|
|
14
|
-
style?: StyleProp<ViewStyle>;
|
|
15
|
-
testID?: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* The person's past chats, newest first. It pages with Show more, refreshes on pull, opens one
|
|
19
|
-
* through `onOpen`, renames and deletes one after a confirm.
|
|
20
|
-
*/
|
|
21
|
-
export declare const ChatConversationList: React.FC<ChatConversationListProps>;
|
|
22
|
-
//# sourceMappingURL=ChatConversationList.d.ts.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type ChatLabels } from "@webority/markdown-core/chat";
|
|
2
|
-
import type React from "react";
|
|
3
|
-
export interface ChatLauncherProps {
|
|
4
|
-
onPress: () => void;
|
|
5
|
-
/** `end` (the default) or `start`: the bottom corner it sits in. */
|
|
6
|
-
position?: "end" | "start";
|
|
7
|
-
/**
|
|
8
|
-
* Distance above the bottom safe area, so it clears a tab bar or another floating control.
|
|
9
|
-
* Defaults to the theme's floating action button offset.
|
|
10
|
-
*/
|
|
11
|
-
bottomOffset?: number;
|
|
12
|
-
/** Show only the icon, with the label as its accessible name. */
|
|
13
|
-
compact?: boolean;
|
|
14
|
-
labels?: Partial<ChatLabels>;
|
|
15
|
-
testID?: string;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* An optional floating button that opens the chat. A phone app usually opens the chat from a
|
|
19
|
-
* header action or a Help row instead; use this where a floating entry point fits the screen.
|
|
20
|
-
*/
|
|
21
|
-
export declare const ChatLauncher: React.FC<ChatLauncherProps>;
|
|
22
|
-
//# sourceMappingURL=ChatLauncher.d.ts.map
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type React from "react";
|
|
2
|
-
export interface ChatMarkdownProps<T = string> {
|
|
3
|
-
/** The reply text, possibly still arriving. */
|
|
4
|
-
text: string;
|
|
5
|
-
/**
|
|
6
|
-
* Maps a reply link (`scheme:kind/id`, e.g. `app:requirement/R-12`) to what it opens in the
|
|
7
|
-
* app: a route, a screen and its params, anything `onLinkPress` understands. Return null for a
|
|
8
|
-
* link the app does not know; it then shows as plain text. A web address never reaches it.
|
|
9
|
-
*/
|
|
10
|
-
resolveLink?: (href: string) => T | null | undefined;
|
|
11
|
-
/** Opens what `resolveLink` returned. Without it, links show as plain text. */
|
|
12
|
-
onLinkPress?: (target: T) => void;
|
|
13
|
-
/**
|
|
14
|
-
* Tells a citation marker (the bracketed inner text, e.g. `1` for `[1]`) from an ordinary link.
|
|
15
|
-
* A citation draws as a pressable marker and never as a link.
|
|
16
|
-
*/
|
|
17
|
-
isCitation?: (inner: string) => boolean;
|
|
18
|
-
/** Opens the citation a reply marker names. Without it, citation markers show as plain text. */
|
|
19
|
-
onOpenCitation?: (citation: string) => void;
|
|
20
|
-
testID?: string;
|
|
21
|
-
}
|
|
22
|
-
/** A reply never opens a web address, and its headings draw as bold lines, not large type. */
|
|
23
|
-
export declare function ChatMarkdown<T = string>({ text, resolveLink, onLinkPress, isCitation, onOpenCitation, testID, }: ChatMarkdownProps<T>): React.ReactElement;
|
|
24
|
-
//# sourceMappingURL=ChatMarkdown.d.ts.map
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { ChatAttachment, ChatRating, SupportActionTicket } from "@webority/markdown-core/chat";
|
|
2
|
-
import { type ChatLabels } from "@webority/markdown-core/chat";
|
|
3
|
-
import type React from "react";
|
|
4
|
-
import type { ChatTurn } from "../useChat";
|
|
5
|
-
/** The props a thread passes to each of its turns. */
|
|
6
|
-
export interface ChatReplyProps<T = string> {
|
|
7
|
-
/** Shows the rating under a stored reply. */
|
|
8
|
-
onRate?: (turnId: string, rating: ChatRating, note?: string) => Promise<unknown>;
|
|
9
|
-
/** Maps a reply link to what it opens; see `ChatMarkdown`. */
|
|
10
|
-
resolveLink?: (href: string) => T | null | undefined;
|
|
11
|
-
/** Opens what `resolveLink` returned. */
|
|
12
|
-
onLinkPress?: (target: T) => void;
|
|
13
|
-
/** Tells a citation marker in a reply from an ordinary link; see `ChatMarkdown`. */
|
|
14
|
-
isCitation?: (inner: string) => boolean;
|
|
15
|
-
/** Opens the citation a reply marker names; see `ChatMarkdown`. */
|
|
16
|
-
onOpenCitation?: (citation: string) => void;
|
|
17
|
-
/** Sends a suggested follow-up question; shows the suggestions under the last answer. */
|
|
18
|
-
onAskSuggestion?: (text: string) => void;
|
|
19
|
-
/** Shows support action cards; see `ActionCard`. */
|
|
20
|
-
confirmAction?: (token: string) => Promise<SupportActionTicket>;
|
|
21
|
-
onViewTicket?: (ticket: SupportActionTicket) => void;
|
|
22
|
-
/**
|
|
23
|
-
* Draws the assistant's answer in place of `ChatMarkdown` (charts, maths). The question, action
|
|
24
|
-
* cards, rating and layout stay the library's.
|
|
25
|
-
*/
|
|
26
|
-
renderReply?: (turn: ChatTurn, state: {
|
|
27
|
-
streaming: boolean;
|
|
28
|
-
}) => React.ReactNode;
|
|
29
|
-
/** Sends a failed or stopped question again; shows Try again under it. */
|
|
30
|
-
onRetry?: (turnId: string) => void;
|
|
31
|
-
/** Asks for a new answer to this turn; shows New answer under the answer when `canRegenerate` is set. */
|
|
32
|
-
onRegenerate?: (turnId: string) => void;
|
|
33
|
-
/** Puts this question back in the box to edit; shows Edit under the question. */
|
|
34
|
-
onEdit?: (turnId: string) => void;
|
|
35
|
-
/** Opens an attached file from its chip under the question. */
|
|
36
|
-
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
37
|
-
labels?: Partial<ChatLabels>;
|
|
38
|
-
}
|
|
39
|
-
export interface ChatMessageProps<T = string> extends ChatReplyProps<T> {
|
|
40
|
-
turn: ChatTurn;
|
|
41
|
-
/** Set on the one turn a New answer is offered for, normally the last answered turn. */
|
|
42
|
-
canRegenerate?: boolean;
|
|
43
|
-
testID?: string;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* One turn on mobile-ui's chat parts: the person's question in a `MessageBubble` on the trailing
|
|
47
|
-
* side, with its files, a stopped note and Try again or Edit under it; the typing dots and the
|
|
48
|
-
* tool step while the answer has not started, then the answer in a bubble on the leading side.
|
|
49
|
-
* The answer is announced once, when it finishes arriving. Support actions show under the answer,
|
|
50
|
-
* and the rating once the reply is stored.
|
|
51
|
-
*/
|
|
52
|
-
declare function ChatMessageView<T = string>({ turn, canRegenerate, onRetry, onRegenerate, onEdit, onOpenAttachment, onRate, resolveLink, onLinkPress, isCitation, onOpenCitation, onAskSuggestion, confirmAction, onViewTicket, renderReply, labels: labelOverrides, testID, }: ChatMessageProps<T>): React.ReactElement;
|
|
53
|
-
export declare const ChatMessage: typeof ChatMessageView;
|
|
54
|
-
export {};
|
|
55
|
-
//# sourceMappingURL=ChatMessage.d.ts.map
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { type ChatAttachment, type ChatUploadFile } from "@webority/markdown-core/chat";
|
|
2
|
-
import type React from "react";
|
|
3
|
-
import type { UseChatResult } from "../useChat";
|
|
4
|
-
import type { ChatReplyProps } from "./ChatMessage";
|
|
5
|
-
export interface ChatScreenProps<T = string> extends Omit<ChatReplyProps<T>, "onRate" | "onAskSuggestion"> {
|
|
6
|
-
/** The `useChat` result. */
|
|
7
|
-
chat: UseChatResult;
|
|
8
|
-
/** Opens the file picker. The attach button shows only with this and the chat's attachment settings. */
|
|
9
|
-
pickAttachments?: () => Promise<ChatUploadFile[]>;
|
|
10
|
-
/** Opens an attachment shown in a message. */
|
|
11
|
-
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
12
|
-
/** Header title. Defaults to the `panelTitle` label. */
|
|
13
|
-
title?: string;
|
|
14
|
-
/** Extra header controls before New chat, e.g. an "All chats" button. */
|
|
15
|
-
headerActions?: React.ReactNode;
|
|
16
|
-
/** Shown before the first question, in place of the default title and text. */
|
|
17
|
-
empty?: React.ReactNode;
|
|
18
|
-
/** The footnote under the question box. Defaults to the `disclaimer` label; null hides it. */
|
|
19
|
-
disclaimer?: string | null;
|
|
20
|
-
/** The server's message limit. Default 4000. */
|
|
21
|
-
maxLength?: number;
|
|
22
|
-
/** Show the questions left once this many or fewer remain. Default 10. */
|
|
23
|
-
allowanceThreshold?: number;
|
|
24
|
-
/** Offer ratings under stored replies. Default true. */
|
|
25
|
-
rating?: boolean;
|
|
26
|
-
/**
|
|
27
|
-
* How far below the question box the keyboard's top edge starts. Default: the bottom safe-area
|
|
28
|
-
* inset; set it to the tab bar's height when the screen sits above one.
|
|
29
|
-
*/
|
|
30
|
-
keyboardOffset?: number;
|
|
31
|
-
testID?: string;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* The whole chat for one screen of the app's navigator: a header with New chat, the
|
|
35
|
-
* conversation, the questions left today, the question box and the AI disclaimer. The question
|
|
36
|
-
* box rides the keyboard and the newest turn stays above it. Place it in a stack screen and keep
|
|
37
|
-
* the `useChat` call above the navigator, so the conversation survives leaving the screen.
|
|
38
|
-
*/
|
|
39
|
-
export declare function ChatScreen<T = string>({ chat, pickAttachments, onOpenAttachment, title, headerActions, empty, disclaimer, maxLength, allowanceThreshold, rating, keyboardOffset, testID, ...reply }: ChatScreenProps<T>): React.ReactElement;
|
|
40
|
-
//# sourceMappingURL=ChatScreen.d.ts.map
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type ChatAttachment } from "@webority/markdown-core/chat";
|
|
2
|
-
import type React from "react";
|
|
3
|
-
import { type StyleProp, type ViewStyle } from "react-native";
|
|
4
|
-
import type { ChatTurn } from "../useChat";
|
|
5
|
-
import { type ChatReplyProps } from "./ChatMessage";
|
|
6
|
-
export interface ChatThreadProps<T = string> extends ChatReplyProps<T> {
|
|
7
|
-
turns: ChatTurn[];
|
|
8
|
-
/** Shown before the first question. */
|
|
9
|
-
empty?: React.ReactNode;
|
|
10
|
-
/** Lifts the newest turn above the keyboard; see mobile-ui `MessageList`. Default true. */
|
|
11
|
-
keyboardAware?: boolean;
|
|
12
|
-
/** The composer's `keyboardOffset`. Default: the bottom safe-area inset. */
|
|
13
|
-
keyboardOffset?: number;
|
|
14
|
-
/** Asks a failed or stopped turn's question again. */
|
|
15
|
-
onRetry?: (turnId: string) => void;
|
|
16
|
-
/** Asks for a new answer; offered on the last answered turn only. */
|
|
17
|
-
onRegenerate?: (turnId: string) => void;
|
|
18
|
-
/** Puts a question back in the box to be edited. */
|
|
19
|
-
onEdit?: (turnId: string) => void;
|
|
20
|
-
onOpenAttachment?: (attachment: ChatAttachment) => void;
|
|
21
|
-
style?: StyleProp<ViewStyle>;
|
|
22
|
-
testID?: string;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* The conversation on mobile-ui's `MessageList`: newest at the bottom, the
|
|
26
|
-
* streaming answer growing in place, a jump to the latest once scrolled up,
|
|
27
|
-
* and the newest turn kept above the keyboard.
|
|
28
|
-
*/
|
|
29
|
-
export declare function ChatThread<T = string>({ turns, empty, keyboardAware, keyboardOffset, onRetry, onRegenerate, onEdit, onOpenAttachment, onAskSuggestion, style, testID, ...reply }: ChatThreadProps<T>): React.ReactElement;
|
|
30
|
-
//# sourceMappingURL=ChatThread.d.ts.map
|