@filigran/chatbot 3.18.1 → 3.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +182 -0
- package/README.md +58 -17
- package/dist/index.d.ts +153 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/markdown.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/workspaces.d.ts +4 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,188 @@ the versions follow [semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
8
8
|
This file starts at 3.10.0; earlier releases are on the
|
|
9
9
|
[releases page](https://github.com/FiligranHQ/filigran-ui/releases).
|
|
10
10
|
|
|
11
|
+
## 3.19.1 — unreleased
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- The panel speaks German, Italian, Korean, Russian and Simplified Chinese on
|
|
16
|
+
its own: a catalog for each, picked from `locale` by its language whatever
|
|
17
|
+
the region (`de-de`, `it-it`, `ko-kr`, `ru-ru`, `zh-cn`). Those languages
|
|
18
|
+
showed in English unless the host translated every key through `t`.
|
|
19
|
+
Traditional Chinese tags (`zh-TW`, `zh-HK`, `zh-Hant`) keep falling back.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- A refusal whose body has no `detail` shows its `error` when that is a
|
|
24
|
+
sentence, as the products' proxies answer (`{ "error": "..." }`, beside a
|
|
25
|
+
`status` or not), never a code (`invalid_token`, `Unauthorized`) nor a
|
|
26
|
+
status's reason phrase (`Not Found`, `Too Many Requests`). It shows above
|
|
27
|
+
the composer, in place of the answer, on a failed upload's chip, under the
|
|
28
|
+
conversation list and on a conversation that could not be loaded. The panel
|
|
29
|
+
showed its generic message instead.
|
|
30
|
+
- The status line has its own wording when it has no agent's name (`The agent
|
|
31
|
+
is answering…`, `Consulting an agent…`, `Transferring to another agent…`),
|
|
32
|
+
where it filled the name with a lowercase `the agent`: `the agent is
|
|
33
|
+
answering…` started without a capital. A host translating through `t` in a
|
|
34
|
+
language the panel has no catalog for translates these three keys; it
|
|
35
|
+
translated `the agent` before, and shows them in English until it does.
|
|
36
|
+
|
|
37
|
+
## 3.19.0 — unreleased
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- `collapseUnnamedFiles`: the files a reply carries but whose markers it does
|
|
42
|
+
not name go behind one collapsed `Working files ({count})` line, all of them
|
|
43
|
+
(`true`) or those a predicate picks, instead of one card each. Opened, each
|
|
44
|
+
is listed with its card, after a thumbnail for a picture (fetched only once
|
|
45
|
+
the list opens; the picture icon when there is no URL, the fetch fails or
|
|
46
|
+
the bytes do not decode), and from 8 files a `Show less` closes it from its
|
|
47
|
+
end. Opened while following the end, it stops following once it pushes the
|
|
48
|
+
end out of view, so the list stays in view. Off unless the host asks.
|
|
49
|
+
- `renderReasoningAction`: a host's action in the corner of the reasoning
|
|
50
|
+
window, shown while the window is and gone with it.
|
|
51
|
+
- An image's lightbox has a Download action when the panel can download the
|
|
52
|
+
file, so a user's uploaded picture, which replaces its download card, can be
|
|
53
|
+
downloaded.
|
|
54
|
+
- A `Scroll to bottom` button shows once the reader has scrolled up, and
|
|
55
|
+
brings the view back to the end, following it again.
|
|
56
|
+
- Older messages load as the reader scrolling up nears the top, a second at
|
|
57
|
+
least after the last load ended, never while the view follows the end, and
|
|
58
|
+
only where the button would load them. A load that brings nothing (the
|
|
59
|
+
backend failing) stops them until the conversation is opened again; the
|
|
60
|
+
button still tries again. The button reads `Loading earlier messages…` while they load.
|
|
61
|
+
- `maxFileSize` limits each attached file, next to `maxTotalSize` (none by
|
|
62
|
+
default). A file refused, whichever limit it went past (`maxFileSize`,
|
|
63
|
+
`maxTotalSize`, `maxFileCount`), is named above the text field with why; it
|
|
64
|
+
was dropped without a word. `onFileRefused(file, reason)` tells the host too
|
|
65
|
+
(`ChatFileRefusal`).
|
|
66
|
+
- `acceptFileTypes` sets the file picker's `accept`, and refuses a pasted or
|
|
67
|
+
dropped file of another type (`'file-type'`). A file the browser gives no
|
|
68
|
+
MIME type (Chrome on Windows for `.md`, `.yaml`) is judged by the type its
|
|
69
|
+
extension stands for, and refused by a MIME token when it stands for none.
|
|
70
|
+
- `placeholder` replaces "Ask a question...": a text, or a function of the
|
|
71
|
+
agent selected.
|
|
72
|
+
- `onBeforeSend`'s draft says how many files the message carries
|
|
73
|
+
(`fileCount`).
|
|
74
|
+
- The composer takes the focus after a send from it and after a switch to
|
|
75
|
+
another conversation or a new one, unless the focus is in a field, a dialog
|
|
76
|
+
or the host's page; opening the panel takes none.
|
|
77
|
+
- `onBeforeMove(conversation, workspace)` is asked before a drag or a row's
|
|
78
|
+
Move menu files a conversation into a workspace (`workspace` is `null` when
|
|
79
|
+
taking it out of one): `false`, or a promise of it, leaves the conversation
|
|
80
|
+
where it was, e.g. once the user declined to share it with a workspace's
|
|
81
|
+
members. One that throws or rejects refuses the move.
|
|
82
|
+
- `onConversationActionFailed(action, conversation, error)` is told when
|
|
83
|
+
deleting, renaming, moving or clearing conversations fails (`'delete'`,
|
|
84
|
+
`'rename'`, `'move'`, `'clearAll'`), with the backend's `detail` when it
|
|
85
|
+
gave one; returning `true` keeps the panel's own notice from showing.
|
|
86
|
+
- A row of the conversation list shows the last message
|
|
87
|
+
(`last_message_preview`) under its title, and a small icon for a
|
|
88
|
+
conversation started in a messaging channel (`channel`), named `Started in
|
|
89
|
+
{channel}`: Slack, Teams, WhatsApp, Telegram, Discord and Google Chat out
|
|
90
|
+
of the box; `channelLabel(channel)` names another, or hides one (`null`).
|
|
91
|
+
`ChatConversationSummary` gains the optional `lastMessagePreview` and
|
|
92
|
+
`channel`.
|
|
93
|
+
- `sidebarSearchThreshold` sets how many conversations the list holds before
|
|
94
|
+
its search box shows (default 7, as before; `0` shows it from the first).
|
|
95
|
+
- `headerTitle` and `headerSubtitle`, a node or a function of what is on
|
|
96
|
+
screen (`ChatHeaderContext`: the conversation as the list holds it, and the
|
|
97
|
+
agent), show a title beside the header's agent name and a line under it.
|
|
98
|
+
- `agentHref(agent)` makes the header's agent name a link, followed in place
|
|
99
|
+
(an http(s) URL or a path of the host's origin), and `onAgentNameClick(agent)`
|
|
100
|
+
takes a plain click on it; the chevron beside the name opens the agent
|
|
101
|
+
picker then.
|
|
102
|
+
- `clearAllAction: 'archive'` words Clear all as an archive (`Archive all
|
|
103
|
+
conversations`).
|
|
104
|
+
- `XtmAgent.badges`: short labels the agents list may send (`badges`, strings
|
|
105
|
+
only), shown after the agent's name in the agent picker.
|
|
106
|
+
- `toolLabels`: the host's names for its tools, by raw name or as a function
|
|
107
|
+
of it, in the status line (a consult's tools too) and the reasoning details.
|
|
108
|
+
A name it does not give keeps the built-in one.
|
|
109
|
+
- `sidebarSections` also takes a function of the conversation list's search,
|
|
110
|
+
`(search: ChatSidebarSearch) => ReactNode`, given what the search box holds,
|
|
111
|
+
trimmed (`''` when empty). It is drawn again when the search or the function
|
|
112
|
+
changes, so a host passes a stable one, and puts hooks in a component the
|
|
113
|
+
function returns. With it the search box shows whatever the number of
|
|
114
|
+
conversations, and a search no conversation of the user's own matches says
|
|
115
|
+
"None of your conversations matches". Sections given as an element show as
|
|
116
|
+
they are.
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- The view keeps the last line in view when the thread's own box shrinks
|
|
121
|
+
while following the end (the composer growing to several lines, a tray
|
|
122
|
+
opening); only growth inside the thread was followed.
|
|
123
|
+
- Earlier messages already loaded, shown by the button, leave the reader
|
|
124
|
+
where they were in every browser, as older messages fetched do.
|
|
125
|
+
- A failed upload's chip says why: the upload's `detail`
|
|
126
|
+
(`ChatFile.uploadError`), or "Upload failed". It showed a bare ✕.
|
|
127
|
+
- A message holding a file that failed to upload is not sent until the user
|
|
128
|
+
removes the file, turn or no turn; with no turn running it went without the
|
|
129
|
+
file, and nothing said so.
|
|
130
|
+
- Files attached before a host turns `disableFileManagement` on stay shown
|
|
131
|
+
and removable; they were hidden, yet still sent, or a failed one held every
|
|
132
|
+
send without a word.
|
|
133
|
+
- Deleting, renaming or clearing conversations failed silently: the panel now
|
|
134
|
+
says it under the conversation list, or under the header when the list is
|
|
135
|
+
not shown, in the backend's words when it gives some. A refused rename
|
|
136
|
+
still keeps the old title, and now undoes only that row: other changes to
|
|
137
|
+
the list made meanwhile stay.
|
|
138
|
+
- The conversation list's search matches a conversation's last message and
|
|
139
|
+
its agent's name too, not its title alone.
|
|
140
|
+
- A message sent in a conversation moves it to the top of its section at
|
|
141
|
+
once, with the time and its text as the preview; it stayed where it was
|
|
142
|
+
until the turn ended and the list was read again.
|
|
143
|
+
- A read-only panel showed the welcome screen's "Suggestions" heading over no
|
|
144
|
+
suggestions: nothing can be sent there, so the section is left out.
|
|
145
|
+
- The status line says what the turn does where it said `Thinking...`:
|
|
146
|
+
`{agent} is answering…` for each mentioned agent of a turn, with that
|
|
147
|
+
agent's name before the statuses of its run, in the voice call too
|
|
148
|
+
(`AgentStatusState.answeringAgentName`);
|
|
149
|
+
`Transferring to {agent}…` on `transfer_start`; the setup step of
|
|
150
|
+
`preparing` by its `phase` (`Loading conversation history…`, `Summarizing
|
|
151
|
+
earlier conversation…`, `Recalling memory…`, `Connecting integrations…`,
|
|
152
|
+
`Preparing tools…`, else `Preparing…`); `Compacting conversation context…`;
|
|
153
|
+
`Saving response…` on `persisting`; and `Analyzing results (step {step})…`
|
|
154
|
+
from the frame's `iteration` after the first step. A host's `statusLabel`
|
|
155
|
+
reads them as `AgentStatusState.agentName`, `phase` and `iteration`.
|
|
156
|
+
- While mentioned agents answer, a message does not steer: it would reach
|
|
157
|
+
whichever of them runs. It waits for the turn, held with
|
|
158
|
+
`holdSendsDuringTurn`, as a message that cannot steer does.
|
|
159
|
+
- A stored answer the server's restart cut short (`interrupted: true`,
|
|
160
|
+
`ChatMessage.interrupted`) is marked as a truncated one is, and its reasoning
|
|
161
|
+
details say why.
|
|
162
|
+
- A finished answer with no text and no files says `No response was
|
|
163
|
+
generated. Please try again.`; it showed `...`.
|
|
164
|
+
- A paste from an office suite or a spreadsheet (Excel, Word, PowerPoint,
|
|
165
|
+
OneNote, LibreOffice, Numbers) puts the copied text in the composer. These
|
|
166
|
+
apps copy a selection as its text, its HTML and a picture of it, and the
|
|
167
|
+
panel attached the picture and dropped the text. A paste whose files are all
|
|
168
|
+
images, with plain text and an HTML fragment that shows text, attaches
|
|
169
|
+
nothing and reaches the text box; a screenshot, a browser's "Copy image" and
|
|
170
|
+
a file copied in a file manager still attach. A picture copied together with
|
|
171
|
+
text around it (an image and its caption in Word or Outlook) is read the same
|
|
172
|
+
way: the text is pasted, the picture is not attached; copy the picture alone
|
|
173
|
+
to attach it.
|
|
174
|
+
- Enter while an input method composes a word (Chinese, Japanese, Korean)
|
|
175
|
+
confirms the word instead of sending the half-typed message, renaming a
|
|
176
|
+
conversation or naming a workspace, and Escape then cancels the composition
|
|
177
|
+
without stopping the turn, closing the field or clearing a search.
|
|
178
|
+
- A file dropped on the panel where it attaches none (a `readOnly` panel, one
|
|
179
|
+
with `disableFileManagement` or no upload route, or the header and the
|
|
180
|
+
conversation list of any panel) leaves the page where it is; the browser
|
|
181
|
+
opened it in the tab, away from the chat. A host's own drop zone around the
|
|
182
|
+
panel still receives the drop, and a picture or link dragged from a page
|
|
183
|
+
still goes into a text field as its address.
|
|
184
|
+
- The composer's draft is written when the page goes away (`pagehide`) or is
|
|
185
|
+
hidden, so a reload right after typing keeps it; a keystroke within the
|
|
186
|
+
300 ms the draft waits before being written was lost. Two panels on one
|
|
187
|
+
conversation write only the draft typed in them, so neither erases the
|
|
188
|
+
other's.
|
|
189
|
+
- A search box hidden as the list shrinks below its threshold clears its
|
|
190
|
+
query: the list stayed filtered by a search the user could neither see nor
|
|
191
|
+
clear.
|
|
192
|
+
|
|
11
193
|
## 3.18.1 — unreleased
|
|
12
194
|
|
|
13
195
|
### Fixed
|
package/README.md
CHANGED
|
@@ -92,6 +92,10 @@ import { ChatPanel } from '@filigran/chatbot';
|
|
|
92
92
|
| `disableFileManagement` | `boolean` | `false` | No attaching or pasting files in the composer |
|
|
93
93
|
| `maxFileCount` | `number` | `10` | Most files attached to one message |
|
|
94
94
|
| `maxTotalSize` | `number` | 50 MB | Most bytes the files attached to one message add up to |
|
|
95
|
+
| `maxFileSize` | `number` | — | Most bytes one attached file may hold; none of its own by default, only `maxTotalSize` |
|
|
96
|
+
| `acceptFileTypes` | `string` | — | The file types the composer takes, in the file input's `accept` form (`'.pdf,image/*'`): the picker offers only these, and a pasted or dropped file of another type is refused. A file the browser gives no MIME type (Chrome on Windows for `.md`, `.yaml`) is judged by the type its extension stands for (`.md`, `.markdown`, `.yaml`, `.yml`, `.csv`, `.tsv`, `.txt`, `.log`, `.json`), and refused by a MIME token when it stands for none. Any type by default |
|
|
97
|
+
| `onFileRefused` | `(file: File, reason: ChatFileRefusal) => void` | — | A file the composer refused: `'file-size'` (over `maxFileSize`), `'total-size'` (past `maxTotalSize`), `'file-count'` (past `maxFileCount`) or `'file-type'` (not of `acceptFileTypes`). The composer names the file and says why above the text field either way |
|
|
98
|
+
| `placeholder` | `string \| ((agent: XtmAgent \| null) => string)` | `'Ask a question...'` | The composer's placeholder, or one for the agent selected (`null` until the agents load); used as given, so the host translates it |
|
|
95
99
|
| `onMessageFeedback` | `(id, feedback, message) => void` | — | Receives each rating of an answer (`null` clears it); `id` is the message's persisted id when the backend reported one (`done.message_id`, a restored entry's `id`), else the panel's own. On its own it enables 👍/👎 and the panel stores nothing; with `apiEndpoints.feedback` set it is called once the backend has stored the rating. With neither, no thumbs. |
|
|
96
100
|
| `locale` | `string` | browser's | BCP 47 language tag of the platform's language (e.g. `'fr-FR'`): the language of the panel's catalog for what `t` does not translate, of its message times and of read-aloud. Unset, the browser's — except that a host passing `t` gets no catalog then |
|
|
97
101
|
| `disableImagePreviews` | `boolean` | `false` | Render image attachments as download cards instead of inline previews |
|
|
@@ -116,10 +120,14 @@ import { ChatPanel } from '@filigran/chatbot';
|
|
|
116
120
|
| `headerActions` / `banner` / `composerHeader` / `transcriptFooter` / `welcome` | `React.ReactNode` | — | The host's content in the header, above the thread, above the composer, after the last message, or in place of the welcome screen |
|
|
117
121
|
| `renderMessageExtras` / `messageFooterActions` | `(message, { streaming }) => React.ReactNode` | — | The host's content under a message, and controls in a finished answer's footer; `streaming` while the message is the answer still being written. `message.raw` holds the backend's own fields — see [Host extensions](#host-extensions) |
|
|
118
122
|
| `sidebarRowActions` | `(conversation) => React.ReactNode` | — | The host's controls on a row of the conversation list |
|
|
119
|
-
| `sidebarHeaderActions`
|
|
123
|
+
| `sidebarHeaderActions` | `React.ReactNode` | — | The host's controls beside New conversation |
|
|
124
|
+
| `sidebarSections` | `React.ReactNode \| ((search: ChatSidebarSearch) => React.ReactNode)` | — | Sections under the list; a function draws them from the list's search (`query`, trimmed), again when the search or the function changes (pass a stable one, and put hooks in a component it returns), and offers the search box whatever the number of conversations |
|
|
120
125
|
| `statusLabel` | `(status: AgentStatusState) => string \| undefined` | — | The status line's text for a status, over the built-in one |
|
|
126
|
+
| `toolLabels` | `Record<string, string> \| ((toolName: string) => string \| undefined)` | — | Tool names as the status line and the reasoning details show them, by the tool's raw name; a name it does not give keeps the built-in one (`search_iocs` → `Search Iocs`). A new function redraws every message: keep one across renders unless its labels change |
|
|
121
127
|
| `waitingMessages` | `string[]` | built-in | The waiting panel's rotating messages, already translated |
|
|
122
128
|
| `renderWaitingPanel` | `() => React.ReactNode` | — | Replaces the waiting panel's content (its messages and the invitation to play) |
|
|
129
|
+
| `renderReasoningAction` | `() => React.ReactNode` | — | An action in the reasoning window's corner (a game to play while the agent works), shown while the window is |
|
|
130
|
+
| `collapseUnnamedFiles` | `boolean \| (attachment, message) => boolean` | `false` | Puts the files a reply does not name behind one collapsed `Working files (N)` line, with a thumbnail for each picture once opened: all of them, or those the predicate picks |
|
|
123
131
|
| `fontFamily` | `string` | — | Font of the panel's text |
|
|
124
132
|
| `theme` | `ChatPanelTheme` | — | The host's colours, type and shapes; see [Custom Theme](#custom-theme) |
|
|
125
133
|
| `agentMentions` | `boolean` | `false` | `@` also mentions agents of the agent list; the message carries their ids as `mentioned_agent_ids` |
|
|
@@ -130,6 +138,14 @@ import { ChatPanel } from '@filigran/chatbot';
|
|
|
130
138
|
| `onBeforeSend` | `(draft) => false \| { text?, displayText?, extras? } \| void` | — | Sees every non-empty send first and takes it over (`false`), rewords it, shows the user's bubble other words or adds body fields (a message with fields of its own is held with `holdSendsDuringTurn`) — see [Host extensions](#host-extensions) |
|
|
131
139
|
| `hideConversationList` | `boolean` | `false` | Hides the conversation list of fullscreen and inline modes, for a rail or a task pane (usable from 320 px wide); the header's history menu stands in for it — see [Host extensions](#host-extensions) |
|
|
132
140
|
| `holdSendsDuringTurn` | `boolean` | `false` | A message that cannot steer is held and sent when the turn ends, instead of waiting in the composer. A turn winding down after a provisional end (until its stored end or its stream's close, at most 5 s) holds sends with or without it |
|
|
141
|
+
| `onBeforeMove` | `(conversation, workspace \| null) => boolean \| Promise<boolean>` | — | Asked before a drag or a row's Move menu files a conversation into a workspace (`null`: out of one); `false` leaves it where it was |
|
|
142
|
+
| `onConversationActionFailed` | `(action, conversation \| null, error \| null) => boolean \| void` | — | A failed `'delete'`, `'rename'`, `'move'` or `'clearAll'`, with the backend's reason; return `true` when the host told the user itself, and the panel says nothing |
|
|
143
|
+
| `sidebarSearchThreshold` | `number` | `7` | The conversation list's search box shows above this many conversations; `0` shows it from the first |
|
|
144
|
+
| `channelLabel` | `(channel: string) => string \| null \| undefined` | — | Names the channel a row's conversation was started in (`Started in {channel}`); `null` shows nothing, `undefined` keeps the panel's names (Slack, Teams, WhatsApp, Telegram, Discord, Google Chat) |
|
|
145
|
+
| `headerTitle` / `headerSubtitle` | `React.ReactNode \| ((context: ChatHeaderContext) => React.ReactNode)` | — | A title beside the header's agent name and a line under it, or functions of the conversation on screen (as the list holds it) and the agent |
|
|
146
|
+
| `agentHref` | `(agent: XtmAgent) => string \| undefined` | — | Links the header's agent name to this address (http(s) or a path of the host's origin), in place; the chevron beside it opens the picker |
|
|
147
|
+
| `onAgentNameClick` | `(agent: XtmAgent) => void` | — | Takes a plain click on the header's agent name (over `agentHref`); the chevron beside it opens the picker |
|
|
148
|
+
| `clearAllAction` | `'delete' \| 'archive'` | `'delete'` | What Clear all does, for its wording (`Archive all conversations`) |
|
|
133
149
|
|
|
134
150
|
Plain-data props (`requestHeaders`, `apiEndpoints`, `pageContext`, `promptSuggestions`) are compared by content and callback props are called
|
|
135
151
|
through a stable wrapper, so building them inline is fine. `t` and `logoIcon` are used as given: keep them stable (`useCallback` / `useMemo`),
|
|
@@ -224,8 +240,9 @@ them stable, and a new one re-renders every message, which is also how to
|
|
|
224
240
|
refresh what they render.
|
|
225
241
|
|
|
226
242
|
`onBeforeSend(draft)` sees every non-empty send first, synchronously:
|
|
227
|
-
`draft.text`, `draft.source` (`'composer'`, `'host'` or `'voice'`)
|
|
228
|
-
`draft.turnRunning` (a turn is running)
|
|
243
|
+
`draft.text`, `draft.source` (`'composer'`, `'host'` or `'voice'`),
|
|
244
|
+
`draft.turnRunning` (a turn is running) and `draft.fileCount` (the files the
|
|
245
|
+
message carries), e.g. to refuse a send whose files the host cannot use. It returns `false` to take the send
|
|
229
246
|
over (the composer keeps its draft), or an object: `text` rewords what the
|
|
230
247
|
backend receives, `displayText` is what the user's bubble shows, and `extras`
|
|
231
248
|
adds body fields. The panel's own fields cannot be set this way, and a message
|
|
@@ -439,11 +456,15 @@ Returns available AI agents.
|
|
|
439
456
|
"name": "General Assistant",
|
|
440
457
|
"slug": "general",
|
|
441
458
|
"icon": null,
|
|
442
|
-
"description": "A helpful general-purpose assistant"
|
|
459
|
+
"description": "A helpful general-purpose assistant",
|
|
460
|
+
"badges": ["Company"]
|
|
443
461
|
}
|
|
444
462
|
]
|
|
445
463
|
```
|
|
446
464
|
|
|
465
|
+
`badges` is optional: short labels, already translated, shown after the
|
|
466
|
+
agent's name in the agent picker. Anything but strings is ignored.
|
|
467
|
+
|
|
447
468
|
### `POST {apiBaseUrl}/chat/sessions`
|
|
448
469
|
|
|
449
470
|
Restores conversation history (and, implicitly, resolves the session).
|
|
@@ -499,8 +520,8 @@ conversation. If the endpoint responds with a non-2xx status, the component
|
|
|
499
520
|
silently resets the stored id and starts fresh on the next message, except
|
|
500
521
|
when it says nothing of the conversation: a `502`, `503` or `504` (or no
|
|
501
522
|
answer at all) keeps the id and reads it back once the backend answers, and a
|
|
502
|
-
`401` or `403` (expired credentials) keeps it, shows the response's
|
|
503
|
-
(or "This conversation could not be loaded.") with a Retry button, and reads
|
|
523
|
+
`401` or `403` (expired credentials) keeps it, shows the response's
|
|
524
|
+
[reason](#a-refusals-reason) (or "This conversation could not be loaded.") with a Retry button, and reads
|
|
504
525
|
it back as soon as `requestHeaders` change.
|
|
505
526
|
|
|
506
527
|
Assistant history messages **should echo the same `attachments[]` array** that
|
|
@@ -535,11 +556,17 @@ Lists the user's past conversations for the history menu in the chat header.
|
|
|
535
556
|
"conversation_id": "uuid-here",
|
|
536
557
|
"title": "What is the weather?",
|
|
537
558
|
"updated_at": "2026-06-10T08:30:00Z",
|
|
538
|
-
"message_count": 12
|
|
559
|
+
"message_count": 12,
|
|
560
|
+
"last_message_preview": "It is sunny in Paris.",
|
|
561
|
+
"channel": "slack"
|
|
539
562
|
}
|
|
540
563
|
]
|
|
541
564
|
```
|
|
542
565
|
|
|
566
|
+
`last_message_preview` and `channel` are optional: a row shows the preview
|
|
567
|
+
under its title, and names a messaging channel the conversation was started
|
|
568
|
+
in (see `channelLabel`).
|
|
569
|
+
|
|
543
570
|
Selecting a conversation restores it through the existing
|
|
544
571
|
`POST /chat/sessions` contract above. The endpoint is fetched lazily when the
|
|
545
572
|
history menu opens; a backend that doesn't implement it yet (404/405) simply
|
|
@@ -556,7 +583,7 @@ the row reverts to its previous title.
|
|
|
556
583
|
|
|
557
584
|
With [workspaces](#workspaces) on, the same route files a conversation:
|
|
558
585
|
`{ "workspace_id": "uuid" }`, or `{ "workspace_id": null }` to take it out of
|
|
559
|
-
its workspace. A refusal's
|
|
586
|
+
its workspace. A refusal's [reason](#a-refusals-reason) is shown under the list.
|
|
560
587
|
|
|
561
588
|
### Workspaces
|
|
562
589
|
|
|
@@ -632,6 +659,17 @@ Deletes a conversation from the history menu. Any 2xx response counts as
|
|
|
632
659
|
success; deleting the active conversation resets the panel to a fresh chat so
|
|
633
660
|
the next message never targets a dead conversation id.
|
|
634
661
|
|
|
662
|
+
### A refusal's reason
|
|
663
|
+
|
|
664
|
+
Where the panel shows why the backend refused a request, it reads the JSON body
|
|
665
|
+
of the non-2xx answer: its `detail` when a string, or the `message` (or
|
|
666
|
+
`detail`) of a `detail` object, as XTM One answers; else its `error` when that
|
|
667
|
+
is a sentence, as the products' proxies answer (`{ "error": "..." }`, beside a
|
|
668
|
+
`status` or not). A code (`invalid_token`, `Unauthorized`), a status's reason
|
|
669
|
+
phrase (`Not Found`, `Too Many Requests`), anything else in the body (a
|
|
670
|
+
top-level `message` included), a string over 500 characters or a body that is
|
|
671
|
+
not JSON shows the panel's own, translated message.
|
|
672
|
+
|
|
635
673
|
### `POST {apiBaseUrl}/chat/messages`
|
|
636
674
|
|
|
637
675
|
Sends a message and streams the response via SSE.
|
|
@@ -659,7 +697,7 @@ It must be JSON-serializable — a non-serializable value (circular reference,
|
|
|
659
697
|
|
|
660
698
|
A refusal before the stream (a non-2xx answer: a rate limit, a refused
|
|
661
699
|
option, an unknown conversation) shows the response's `detail` in place of the
|
|
662
|
-
answer
|
|
700
|
+
answer ([its reason](#a-refusals-reason)), and
|
|
663
701
|
"Unable to connect. Please check the configuration." when it has none; the
|
|
664
702
|
handle's `send` resolves `'failed'`.
|
|
665
703
|
|
|
@@ -793,7 +831,7 @@ until the next send. On a non-2xx
|
|
|
793
831
|
response or a network error nothing was stored: the optimistic user bubble is
|
|
794
832
|
rolled back, the text is restored into the composer (prepended on its own line
|
|
795
833
|
if the user already typed something new), the send resolves `'failed'` and the
|
|
796
|
-
refusal's
|
|
834
|
+
refusal's [reason](#a-refusals-reason), when there is one, shows above the composer — so a backend
|
|
797
835
|
without steering support degrades gracefully and the message is never silently
|
|
798
836
|
lost. A `409` means no turn is running any more, an ordinary race: no notice
|
|
799
837
|
shows, and with `holdSendsDuringTurn` the message is held and sent as the next
|
|
@@ -808,9 +846,9 @@ mentions or body fields of its own (`send`'s `extras`, `onBeforeSend`'s
|
|
|
808
846
|
`extras`) never steers, since a steer reaches the agent as text alone: it waits
|
|
809
847
|
for the turn to end (`holdSendsDuringTurn`), and `onBeforeSend` is asked again,
|
|
810
848
|
with `turnRunning: false`, before it goes out. A file that failed to upload
|
|
811
|
-
neither steers nor waits
|
|
812
|
-
|
|
813
|
-
|
|
849
|
+
neither steers nor waits, nor goes without that file: its chip says why (the
|
|
850
|
+
upload's [reason](#a-refusals-reason)), and the composer offers no send, and says why, until the
|
|
851
|
+
user removes it. `send` and a voice
|
|
814
852
|
call attach no files, so this never holds them. Esc stops generating.
|
|
815
853
|
|
|
816
854
|
#### Multi-segment responses
|
|
@@ -1017,7 +1055,7 @@ chat) opts into six more routes, none with a default:
|
|
|
1017
1055
|
|
|
1018
1056
|
| `apiEndpoints` key | Request | What it does |
|
|
1019
1057
|
| --- | --- | --- |
|
|
1020
|
-
| `cancel` | `POST {cancel}` with `{ conversation_id }` | Stop asks the backend to end the turn; the panel keeps reading until the stream's `cancelled` frame (or lets go after 10 s, or at once on a network error or an answer of `{ "turn": "none" }`, reading the conversation back for an end it had not read yet). A Stop pressed before the panel's own send started its turn (its stream delivered nothing yet) carries `"awaiting_send": true`, and its `none` says nothing of that turn: the Stop stays pending and is sent again, without the flag, as the turn starts (or as the answer comes, the turn started meanwhile); any other answer reached a turn, and nothing goes again. A backend may keep a Stop with that flag for the send's turn, and must then take a second cancel of one turn; a Stop without it says nothing of a later send. A refusal (non-2xx) keeps the turn running and shows its
|
|
1058
|
+
| `cancel` | `POST {cancel}` with `{ conversation_id }` | Stop asks the backend to end the turn; the panel keeps reading until the stream's `cancelled` frame (or lets go after 10 s, or at once on a network error or an answer of `{ "turn": "none" }`, reading the conversation back for an end it had not read yet). A Stop pressed before the panel's own send started its turn (its stream delivered nothing yet) carries `"awaiting_send": true`, and its `none` says nothing of that turn: the Stop stays pending and is sent again, without the flag, as the turn starts (or as the answer comes, the turn started meanwhile); any other answer reached a turn, and nothing goes again. A backend may keep a Stop with that flag for the send's turn, and must then take a second cancel of one turn; a Stop without it says nothing of a later send. A refusal (non-2xx) keeps the turn running and shows its [reason](#a-refusals-reason) above the composer |
|
|
1021
1059
|
| `skipWait` | `POST {skipWait}` with `{ conversation_id }` | `Continue now` on `status: wait_start` (`{ seconds, reason }`), for as long as the pause lasts (see the status values) |
|
|
1022
1060
|
| `events` | `GET {events}/{conversation_id}/events?client_id=<id>` → SSE | Turns this panel did not start (another tab, a reload mid-turn), `user_message`, `conversation_title`, `approval_resolved`; every frame of a turn names it (`turn_id`, below) |
|
|
1023
1061
|
| `messagesPage` | `GET {messagesPage}/{conversation_id}/messages?before=<message id>&limit=50&supports_artifacts=true` → `{ messages, has_more }` | "Load earlier messages" past the restored ones, offered when the restore answers `has_more: true` |
|
|
@@ -1263,9 +1301,12 @@ both. The same variables may be set in CSS on an ancestor instead.
|
|
|
1263
1301
|
|
|
1264
1302
|
### Internationalization
|
|
1265
1303
|
|
|
1266
|
-
The panel speaks English, French, Spanish
|
|
1267
|
-
|
|
1268
|
-
|
|
1304
|
+
The panel speaks English, French, German, Italian, Spanish, Japanese, Korean,
|
|
1305
|
+
Russian and Simplified Chinese on its own: it ships a catalog for each and
|
|
1306
|
+
picks one from `locale` by its language, whatever the region (`fr-FR` reads
|
|
1307
|
+
French, `zh-cn` Chinese; English, or a language it lacks, is its own keys).
|
|
1308
|
+
Traditional Chinese (`zh-TW`, `zh-HK`, `zh-Hant`) has no catalog: it reads
|
|
1309
|
+
English unless the host translates it through `t`. A host in another language translates
|
|
1269
1310
|
through `t`. A host with nothing to add only passes `locale`:
|
|
1270
1311
|
|
|
1271
1312
|
```tsx
|
package/dist/index.d.ts
CHANGED
|
@@ -473,6 +473,30 @@ interface ChatPanelProps {
|
|
|
473
473
|
maxFileCount?: number;
|
|
474
474
|
/** Maximum total size in bytes for attached files. Default: 50 * 1024 * 1024 (50 MB). */
|
|
475
475
|
maxTotalSize?: number;
|
|
476
|
+
/** Maximum size in bytes of one attached file. Default: none (only `maxTotalSize`). */
|
|
477
|
+
maxFileSize?: number;
|
|
478
|
+
/**
|
|
479
|
+
* The file types the composer takes, in the file input's `accept` form
|
|
480
|
+
* (`'.pdf,image/*'`): the picker offers only these, and a pasted or dropped
|
|
481
|
+
* file of another type is refused. A file the browser gives no MIME type
|
|
482
|
+
* (Chrome on Windows for `.md`, `.yaml`) is judged by the type its extension
|
|
483
|
+
* stands for (`.md`, `.markdown`, `.yaml`, `.yml`, `.csv`, `.tsv`, `.txt`,
|
|
484
|
+
* `.log`, `.json`), and refused by a MIME token when it stands for none.
|
|
485
|
+
* Default: any type.
|
|
486
|
+
*/
|
|
487
|
+
acceptFileTypes?: string;
|
|
488
|
+
/**
|
|
489
|
+
* A file the user attached that the composer refused, and why. The composer
|
|
490
|
+
* names it and says why above the text field, whether or not the host
|
|
491
|
+
* listens.
|
|
492
|
+
*/
|
|
493
|
+
onFileRefused?: (file: File, reason: ChatFileRefusal) => void;
|
|
494
|
+
/**
|
|
495
|
+
* The composer's placeholder, over "Ask a question...": a text, or one for
|
|
496
|
+
* the agent selected (`null` until the agents load). Used as given, so the
|
|
497
|
+
* host translates it.
|
|
498
|
+
*/
|
|
499
|
+
placeholder?: string | ((agent: XtmAgent | null) => string);
|
|
476
500
|
/** Additional HTTP headers added to chatbot API requests (messages, sessions, agents, uploads). */
|
|
477
501
|
requestHeaders?: Record<string, string>;
|
|
478
502
|
/**
|
|
@@ -546,7 +570,7 @@ interface ChatPanelProps {
|
|
|
546
570
|
onMessageFeedback?: (messageId: string, feedback: MessageFeedback | null, message: ChatMessage) => void;
|
|
547
571
|
/**
|
|
548
572
|
* The user's language as a BCP 47 tag (`'fr'`, `'en-US'`): the language the
|
|
549
|
-
* panel speaks (its own catalog: en, es, fr, ja) where `t` does not
|
|
573
|
+
* panel speaks (its own catalog: en, de, es, fr, it, ja, ko, ru, zh-Hans) where `t` does not
|
|
550
574
|
* translate a key, formats the time under each message and is the language
|
|
551
575
|
* answers are read aloud in. Default: the browser's own, except that a host
|
|
552
576
|
* passing `t` and no `locale` gets no catalog.
|
|
@@ -664,14 +688,42 @@ interface ChatPanelProps {
|
|
|
664
688
|
sidebarRowActions?: (conversation: ChatConversationSummary) => React.ReactNode;
|
|
665
689
|
/** Controls added beside New conversation, atop the conversation list. */
|
|
666
690
|
sidebarHeaderActions?: React.ReactNode;
|
|
667
|
-
/**
|
|
668
|
-
|
|
691
|
+
/**
|
|
692
|
+
* Sections added under the conversation list (conversations shared with the
|
|
693
|
+
* user). A function draws them from the list's search, so they filter on
|
|
694
|
+
* what is typed, as the list does. It is drawn again only when the search or
|
|
695
|
+
* the function changes: pass a stable one (`useCallback`). Hooks go in a
|
|
696
|
+
* component it returns (`({ query }) => <Shared query={query} />`): hook
|
|
697
|
+
* calls in the function itself break once it draws another branch. With it,
|
|
698
|
+
* the search box shows whatever the number of conversations, and a search
|
|
699
|
+
* with no match among the user's own says so ("None of your conversations
|
|
700
|
+
* matches").
|
|
701
|
+
*/
|
|
702
|
+
sidebarSections?: React.ReactNode | ((search: ChatSidebarSearch) => React.ReactNode);
|
|
669
703
|
/** The status line's text for a status, over the built-in one; `undefined` keeps it. */
|
|
670
704
|
statusLabel?: (status: AgentStatusState) => string | undefined;
|
|
705
|
+
/**
|
|
706
|
+
* Tool names as the status line and the reasoning details show them, over
|
|
707
|
+
* the raw name: by name, or a function of it (`undefined` keeps the raw name).
|
|
708
|
+
* A new function redraws every message: keep one across renders unless its
|
|
709
|
+
* labels change.
|
|
710
|
+
*/
|
|
711
|
+
toolLabels?: ChatToolLabels;
|
|
671
712
|
/** The rotating messages of the waiting panel, already translated. */
|
|
672
713
|
waitingMessages?: string[];
|
|
673
714
|
/** Replaces the waiting panel's content (its messages and the invitation to play). */
|
|
674
715
|
renderWaitingPanel?: () => React.ReactNode;
|
|
716
|
+
/**
|
|
717
|
+
* An action in the corner of the reasoning window (a game to play while the
|
|
718
|
+
* agent works), shown while the window is and gone with it.
|
|
719
|
+
*/
|
|
720
|
+
renderReasoningAction?: () => React.ReactNode;
|
|
721
|
+
/**
|
|
722
|
+
* Files a reply carries but whose markers it does not name go behind one
|
|
723
|
+
* collapsed "Working files (N)" line instead of one card each: all of them
|
|
724
|
+
* (`true`), or those the predicate picks. Default: one card each.
|
|
725
|
+
*/
|
|
726
|
+
collapseUnnamedFiles?: boolean | ((attachment: ChatAttachment, message: ChatMessage) => boolean);
|
|
675
727
|
/** Font of the panel's text; the package's own otherwise. */
|
|
676
728
|
fontFamily?: string;
|
|
677
729
|
/**
|
|
@@ -753,6 +805,63 @@ interface ChatPanelProps {
|
|
|
753
805
|
* `sidebar*` slots render nothing meanwhile. Default: false.
|
|
754
806
|
*/
|
|
755
807
|
hideConversationList?: boolean;
|
|
808
|
+
/**
|
|
809
|
+
* Asked before a conversation is filed into a workspace (`null`: taken out
|
|
810
|
+
* of its workspace), by a drag or the row's Move menu: `false` (or a promise
|
|
811
|
+
* of it) leaves it where it is, e.g. once the user declined to share it with
|
|
812
|
+
* a workspace's members. One that throws or rejects refuses the move.
|
|
813
|
+
*/
|
|
814
|
+
onBeforeMove?: (conversation: ChatConversationSummary, workspace: ChatWorkspace | null) => boolean | Promise<boolean>;
|
|
815
|
+
/**
|
|
816
|
+
* Told when deleting, renaming, moving or clearing conversations fails, with
|
|
817
|
+
* the backend's reason when it gave one (`conversation` is `null` for
|
|
818
|
+
* `clearAll`). The panel says it under the conversation list (or the
|
|
819
|
+
* header) unless this returns `true`: the host told the user itself.
|
|
820
|
+
*/
|
|
821
|
+
onConversationActionFailed?: (action: ChatConversationAction, conversation: ChatConversationSummary | null, error: string | null) => boolean | void;
|
|
822
|
+
/**
|
|
823
|
+
* The conversation list's search box shows once the list holds more than
|
|
824
|
+
* this many conversations; `0` shows it from the first one. Default: 7.
|
|
825
|
+
*/
|
|
826
|
+
sidebarSearchThreshold?: number;
|
|
827
|
+
/**
|
|
828
|
+
* Names the channel a conversation was started in, on its row (`Started in
|
|
829
|
+
* {channel}`): a string names it, `null` shows nothing, `undefined` keeps
|
|
830
|
+
* the panel's own name (Slack, Teams, WhatsApp, Telegram, Discord, Google
|
|
831
|
+
* Chat; no other channel is shown).
|
|
832
|
+
*/
|
|
833
|
+
channelLabel?: (channel: string) => string | null | undefined;
|
|
834
|
+
/** A title beside the agent's name in the header (the conversation's, say), or a function of what is on screen. */
|
|
835
|
+
headerTitle?: React.ReactNode | ((context: ChatHeaderContext) => React.ReactNode);
|
|
836
|
+
/** A line under the agent's name in the header (`Agent · Slack`, say), or a function of what is on screen. */
|
|
837
|
+
headerSubtitle?: React.ReactNode | ((context: ChatHeaderContext) => React.ReactNode);
|
|
838
|
+
/**
|
|
839
|
+
* Links the header's agent name to this address (an http(s) URL or a path
|
|
840
|
+
* of the host's own origin), opened in place; the chevron beside the name
|
|
841
|
+
* opens the agent picker then. `undefined` links nothing.
|
|
842
|
+
*/
|
|
843
|
+
agentHref?: (agent: XtmAgent) => string | undefined;
|
|
844
|
+
/**
|
|
845
|
+
* Called on a click of the header's agent name, over following `agentHref`
|
|
846
|
+
* (a click with a modifier key still follows it): a host routes to the
|
|
847
|
+
* agent's page itself. The chevron beside the name opens the agent picker then.
|
|
848
|
+
*/
|
|
849
|
+
onAgentNameClick?: (agent: XtmAgent) => void;
|
|
850
|
+
/**
|
|
851
|
+
* What Clear all does to the conversations, for its wording: `'archive'`
|
|
852
|
+
* says "Archive all conversations". Default: `'delete'`. A host words it
|
|
853
|
+
* otherwise through `t`.
|
|
854
|
+
*/
|
|
855
|
+
clearAllAction?: 'delete' | 'archive';
|
|
856
|
+
}
|
|
857
|
+
/** A conversation action of the list, as `onConversationActionFailed` names it. */
|
|
858
|
+
type ChatConversationAction = 'delete' | 'rename' | 'move' | 'clearAll';
|
|
859
|
+
/** What the header's `headerTitle` and `headerSubtitle` functions are given. */
|
|
860
|
+
interface ChatHeaderContext {
|
|
861
|
+
/** The conversation on screen as the conversation list holds it; `null` for a new chat, or before the list is read. */
|
|
862
|
+
conversation: ChatConversationSummary | null;
|
|
863
|
+
/** The agent the header names, when the agent list holds it. */
|
|
864
|
+
agent: XtmAgent | null;
|
|
756
865
|
}
|
|
757
866
|
/** What a marker card is drawn from. */
|
|
758
867
|
interface ChatMarkerContext {
|
|
@@ -774,6 +883,8 @@ interface ChatCodeBlockContext {
|
|
|
774
883
|
/** The answer is still streaming: the block may not be complete yet. */
|
|
775
884
|
streaming: boolean;
|
|
776
885
|
}
|
|
886
|
+
/** Tool names as a person reads them, by the tool's raw name (see `ChatPanelProps.toolLabels`). */
|
|
887
|
+
type ChatToolLabels = Readonly<Record<string, string>> | ((toolName: string) => string | undefined);
|
|
777
888
|
/** Renders one fenced code block of a language (see `ChatPanelProps.codeBlockRenderers`); *code* is the block's text. `null` keeps the block as code. */
|
|
778
889
|
type ChatCodeBlockRenderer = (code: string, context: ChatCodeBlockContext) => React.ReactNode;
|
|
779
890
|
/** What a message slot (`renderMessageExtras`, `messageFooterActions`) is drawn with. */
|
|
@@ -844,6 +955,8 @@ interface ChatSendDraft {
|
|
|
844
955
|
source: 'composer' | 'host' | 'voice';
|
|
845
956
|
/** A turn is running. */
|
|
846
957
|
turnRunning: boolean;
|
|
958
|
+
/** How many files the message carries (only the composer attaches files); always set by the panel. */
|
|
959
|
+
fileCount?: number;
|
|
847
960
|
/**
|
|
848
961
|
* A message held while a turn ran, asked about again as it leaves, the turn
|
|
849
962
|
* over (`turnRunning: false`), each send held with it on its own. `false`
|
|
@@ -998,6 +1111,12 @@ interface ChatMessage {
|
|
|
998
1111
|
* reasoning-details affordance, mirroring the XTM One web chat.
|
|
999
1112
|
*/
|
|
1000
1113
|
isTruncated?: boolean;
|
|
1114
|
+
/**
|
|
1115
|
+
* True when the server restarted while the turn ran, so the answer stopped
|
|
1116
|
+
* before it could finish (`interrupted` on the stored message): marked as a
|
|
1117
|
+
* truncated answer is.
|
|
1118
|
+
*/
|
|
1119
|
+
interrupted?: boolean;
|
|
1001
1120
|
/**
|
|
1002
1121
|
* The backend's own fields for the message, as it sent them: the restored
|
|
1003
1122
|
* (or paged, or relayed) entry, or the `done` frame - or the stored end -
|
|
@@ -1105,6 +1224,17 @@ interface AgentStatusState {
|
|
|
1105
1224
|
waitStartMs?: number;
|
|
1106
1225
|
/** `consulting`: the consult the agent is waiting on. */
|
|
1107
1226
|
consult?: ConsultStatus;
|
|
1227
|
+
/** `preparing`: the setup step running (`history`, `compaction`, `memory`, `integrations`, `tools`). */
|
|
1228
|
+
phase?: string;
|
|
1229
|
+
/** `analyzing`: the agent's step, from 1. */
|
|
1230
|
+
iteration?: number;
|
|
1231
|
+
/** `transferring`: the agent the conversation goes to; `mention_answering`: the mentioned agent answering. */
|
|
1232
|
+
agentName?: string;
|
|
1233
|
+
/**
|
|
1234
|
+
* The mentioned agent answering now, on every status of its run: a turn
|
|
1235
|
+
* that answers several mentioned agents runs one after the other.
|
|
1236
|
+
*/
|
|
1237
|
+
answeringAgentName?: string;
|
|
1108
1238
|
}
|
|
1109
1239
|
/**
|
|
1110
1240
|
* A consult the agent is waiting on, as the status line shows it. A consulted
|
|
@@ -1134,7 +1264,20 @@ interface ChatFile {
|
|
|
1134
1264
|
fileId?: string;
|
|
1135
1265
|
/** Upload status: 'pending' while uploading, 'done' when uploaded, 'error' on failure. */
|
|
1136
1266
|
uploadStatus?: 'pending' | 'done' | 'error';
|
|
1267
|
+
/** Why the upload failed, as the backend said, when it said: its reason (README, "A refusal's reason"). */
|
|
1268
|
+
uploadError?: string;
|
|
1269
|
+
}
|
|
1270
|
+
/** The conversation list's search, as a host's sections read it (`sidebarSections`). */
|
|
1271
|
+
interface ChatSidebarSearch {
|
|
1272
|
+
/** What the search box holds, trimmed; `''` when it holds nothing. */
|
|
1273
|
+
query: string;
|
|
1137
1274
|
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Why the composer refused a file (see `onFileRefused`): larger than
|
|
1277
|
+
* `maxFileSize`, past `maxTotalSize` with the files attached, past
|
|
1278
|
+
* `maxFileCount`, or not of `acceptFileTypes`.
|
|
1279
|
+
*/
|
|
1280
|
+
type ChatFileRefusal = 'file-size' | 'total-size' | 'file-count' | 'file-type';
|
|
1138
1281
|
/**
|
|
1139
1282
|
* A past conversation surfaced in the history menu (REST backend only).
|
|
1140
1283
|
* Listed via `GET {apiBaseUrl}{apiEndpoints.history ?? apiEndpoints.sessions ?? '/chat/sessions'}`
|
|
@@ -1159,6 +1302,10 @@ interface ChatConversationSummary {
|
|
|
1159
1302
|
* backend reports it. Undefined on backends that do not.
|
|
1160
1303
|
*/
|
|
1161
1304
|
workspaceId?: string | null;
|
|
1305
|
+
/** The last message's text, shortened by the backend (`last_message_preview`), when it sends one. */
|
|
1306
|
+
lastMessagePreview?: string;
|
|
1307
|
+
/** Where the conversation was started (`channel`: `slack`, `teams`, `web`, …), when the backend reports it. */
|
|
1308
|
+
channel?: string;
|
|
1162
1309
|
}
|
|
1163
1310
|
/**
|
|
1164
1311
|
* A conversation the composer's `@` menu offers (see
|
|
@@ -1200,6 +1347,8 @@ interface XtmAgent {
|
|
|
1200
1347
|
description: string | null;
|
|
1201
1348
|
/** The heading the agent picker lists it under; ungrouped agents come first. */
|
|
1202
1349
|
group?: string;
|
|
1350
|
+
/** Short labels shown after its name in the agent picker (`Company`), already translated. */
|
|
1351
|
+
badges?: string[];
|
|
1203
1352
|
}
|
|
1204
1353
|
|
|
1205
1354
|
/**
|
|
@@ -1220,4 +1369,4 @@ interface TransferredAgent {
|
|
|
1220
1369
|
declare const voiceCallSupported: () => boolean;
|
|
1221
1370
|
|
|
1222
1371
|
export { ChatPanel, ChatToggleButton, voiceCallSupported };
|
|
1223
|
-
export type { AgentStatusState, ApiEndpoints, BackendType, ChatAnsweredBy, ChatArtifact, ChatArtifactKind, ChatAttachment, ChatCodeBlockContext, ChatCodeBlockRenderer, ChatContextBreakdown, ChatContextUsage, ChatConversationRef, ChatConversationReferenceCandidate, ChatConversationSummary, ChatFile, ChatHeldOutcome, ChatMarkerContext, ChatMarkerRenderer, ChatMessage, ChatMessagePersistedFeedback, ChatMessageSlotContext, ChatMode, ChatPanelHandle, ChatPanelMode, ChatPanelProps, ChatPanelTheme, ChatPromptTemplate, ChatQuotaStatus, ChatSendDecision, ChatSendDraft, ChatSendOptions, ChatSendOutcome, ChatStreamEventInfo, ChatToggleButtonProps, ChatTurnEnd, ChatTurnOutcome, ChatWorkspace, ConsultStatus, MessageFeedback, ToolApprovalDecision, ToolApprovalProposal, ToolApprovalVerdict, TransferredAgent, Translate, XtmAgent };
|
|
1372
|
+
export type { AgentStatusState, ApiEndpoints, BackendType, ChatAnsweredBy, ChatArtifact, ChatArtifactKind, ChatAttachment, ChatCodeBlockContext, ChatCodeBlockRenderer, ChatContextBreakdown, ChatContextUsage, ChatConversationAction, ChatConversationRef, ChatConversationReferenceCandidate, ChatConversationSummary, ChatFile, ChatFileRefusal, ChatHeaderContext, ChatHeldOutcome, ChatMarkerContext, ChatMarkerRenderer, ChatMessage, ChatMessagePersistedFeedback, ChatMessageSlotContext, ChatMode, ChatPanelHandle, ChatPanelMode, ChatPanelProps, ChatPanelTheme, ChatPromptTemplate, ChatQuotaStatus, ChatSendDecision, ChatSendDraft, ChatSendOptions, ChatSendOutcome, ChatSidebarSearch, ChatStreamEventInfo, ChatToggleButtonProps, ChatToolLabels, ChatTurnEnd, ChatTurnOutcome, ChatWorkspace, ConsultStatus, MessageFeedback, ToolApprovalDecision, ToolApprovalProposal, ToolApprovalVerdict, TransferredAgent, Translate, XtmAgent };
|