@filigran/chatbot 3.21.0 → 3.22.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/CHANGELOG.md CHANGED
@@ -8,16 +8,105 @@ 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.21.0 — unreleased
11
+ ## 3.22.0 — 2026-11-11
12
12
 
13
13
  ### Added
14
14
 
15
+ - `renderAgentIcon(name, { size })`: the host draws an agent icon given by
16
+ name (an icon library's, such as `brain-circuit`) in the conversation rows,
17
+ the agent switcher and its trigger; `null` keeps the panel's glyph. Image
18
+ URLs and emoji are still drawn by the panel.
19
+
20
+ ### Changed
21
+
22
+ - A row's workspace marker keeps a readable minimum width and shows the whole
23
+ workspace name in the panel's tooltip when it is cut.
24
+ - Error and warning states take the host's design-system tones: `theme.danger`
25
+ and `theme.warning` (`--filigran-chat-danger`, `--filigran-chat-warning`)
26
+ colour the notices, a failed upload, dictation and the stop button; unset, a
27
+ red and an amber per mode (red-700 and amber-800 in the light mode, which
28
+ read at 4.5:1 under a notice's wash). No Tailwind red or amber is left in the
29
+ notice or the composer.
30
+ - A notice's close button shows the panel's tooltip instead of a native title,
31
+ with a 24 px hit area.
32
+ - The agent switcher hands the focus back to its trigger on Escape and when an
33
+ agent is chosen, and the trigger is 32 px high like the other header controls.
34
+
35
+ - Answers render their Markdown at the old chat page's quality and past it.
36
+ Fenced code is coloured by language (Python, TypeScript and JavaScript, JSON,
37
+ shell, SQL, YAML and their usual aliases) in light and dark, with no new
38
+ dependency; an unknown language stays plain. Tables read at the prose's size
39
+ with a filled header row, ruled and striped rows, cells that keep a readable
40
+ width and a frame that scrolls sideways when the table is wider than the
41
+ answer. Nested lists tighten and change bullet by level, task lists show
42
+ read-only boxes, h4 to h6, strikethrough and footnotes are styled.
43
+ - Conversations come first in the list. The workspaces fold into one
44
+ "Workspaces" line above the conversations (with their count and the New
45
+ workspace button), opened on demand and remembered per browser
46
+ (`filigran-chat-workspaces-open`). Below it, every conversation is listed most
47
+ recent first, a filed one naming its workspace on its row. The "Not in a
48
+ workspace" heading becomes "Conversations"; dropping a row there still takes
49
+ it out of its workspace. Creating, opening, renaming and deleting a workspace,
50
+ filing a conversation, the default marker and the counts all work as before
51
+ inside the open line.
52
+
53
+ ### Changed
54
+
55
+ - The new-conversation screen is short: the agent's mark, one greeting line
56
+ naming the agent, and the agent's own suggestions as compact chips. The
57
+ agent's description is no longer shown there (`ChatWelcome`'s
58
+ `agentDescription` is deprecated and ignored), the "Suggestions" heading is
59
+ gone, and the package's four generic fallback suggestions are removed: an
60
+ agent the suggestions route answers nothing for, with no host
61
+ `promptSuggestions`, shows no suggestion.
62
+ - The header's agent control is one switcher: a click anywhere on the icon,
63
+ the name or the chevron opens a searchable list of the agents (always
64
+ searchable, ArrowUp / ArrowDown move, Enter switches, Escape closes, the
65
+ current agent checked). With `agentHref` or `onAgentNameClick`, the agent's
66
+ page moves to an "Open agent page" item of that menu, with the same rules
67
+ (in place, a modifier key left to the browser); the name is no longer a link.
68
+ - Every error, warning and notice of the panel renders through one notice
69
+ block (`ChatNotice`): a tone (error, warning, info) with its icon, a tinted
70
+ container at the panel's radius, and a close button where the notice is not
71
+ tied to a live state. The composer's refused attachment and refused steer
72
+ or Stop notices close on a click; no notice is raw coloured text any more.
73
+ `useChat` returns `dismissNotice` and `dismissFileNotice`, and `ChatInput`
74
+ takes `onDismissNotice` and `onDismissFileNotice`.
75
+ - While the agent thinks or acts, the composer's working glow plays whether the
76
+ field has the focus or not: the focus ring stands aside for the turn (the box
77
+ carries `data-working`) and comes back when the turn ends or is stopped. The
78
+ field keeps the focus after Enter, as before.
79
+
80
+ ### Added
81
+
82
+ - A conversation row shows its agent's own icon (`agent_icon` of the list,
83
+ `ChatConversationSummary.agentIcon`: an image URL or an emoji, as
84
+ `XtmAgent.icon`) in place of the bot glyph, and its last line is the agent as
85
+ a small pill followed by the relative time, the time never cut. A backend
86
+ without `agent_icon`, or one the panel cannot draw, keeps the bot glyph.
15
87
  - `onConversationChange` says why the conversation changed: its second argument
16
88
  is `{ created }`, true for a conversation the panel has just created from a
17
89
  new chat (its first message or file), false for one opened from the list, on
18
90
  a reload or in place of a deleted one, and when it is left for a new chat. A
19
91
  host could not tell an opened conversation from a created one, as both came
20
92
  after a new chat.
93
+ - The composer takes the host's field tokens: `theme.inputRadius`,
94
+ `theme.inputMinHeight` and `theme.focusRing` set its corners, its height at
95
+ rest and its focus ring, so a host draws it with its design system and no
96
+ local override.
97
+ - The conversation list of fullscreen and inline modes is resizable: drag its
98
+ right edge between 224 and 480 px, or move it with the arrow keys, Home and
99
+ End once focused; a double-click puts back the 256 px it always had. The
100
+ width is remembered per browser (`filigranChatConversationListWidth`,
101
+ namespaced by `storageKeyPrefix`) and kept while the list is collapsed.
102
+
103
+ ### Changed
104
+
105
+ - The composer opens at two lines instead of one, and still grows with the
106
+ text up to its maximum: at one line it did not read as the place to write.
107
+ - The composer's focus is a 2 px ring around its box instead of an accent
108
+ border, the text-field focus of a design system; the border keeps its colour,
109
+ so dictation's red border still reads.
21
110
 
22
111
  ## 3.20.0 — 2026-11-10
23
112
 
package/README.md CHANGED
@@ -80,6 +80,7 @@ import { ChatPanel } from '@filigran/chatbot';
80
80
  | `t` | `(key: string) => string` | — | The host's translations; a key it returns unchanged falls back to the panel's catalog in `locale` (none without `locale`) — see [Internationalization](#internationalization) |
81
81
  | `accentColor` | `string` | `'#7b5cff'` | Primary accent color (hex) |
82
82
  | `logoIcon` | `React.ReactNode` | default icon | Custom logo/icon for the assistant |
83
+ | `renderAgentIcon` | `(name: string, { size }) => ReactNode` | — | Draws an agent icon given by name (`brain-circuit`) in the conversation rows, the switcher and its trigger; `null` keeps the panel's glyph. Image URLs and emoji are drawn by the panel |
83
84
  | `promptSuggestions` | `string[]` | default list | Prompt suggestions shown on welcome screen |
84
85
  | `draftBorderColor` | `string` | — | Color of the line above the composer (e.g. a draft context) |
85
86
  | `draftLabel` | `string` | — | Accepted, and not shown |
@@ -146,8 +147,8 @@ import { ChatPanel } from '@filigran/chatbot';
146
147
  | `sidebarSearchThreshold` | `number` | `7` | The conversation list's search box shows above this many conversations; `0` shows it from the first |
147
148
  | `channelLabel` | `(channel: string) => string \| null \| undefined` | — | Names the channel a conversation was started in, on its row (`Started in {channel}`) and in the header (`Agent · {channel}`); `null` shows nothing, `undefined` keeps the panel's names (Slack, Teams, WhatsApp, Telegram, Discord, Google Chat) |
148
149
  | `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. Without `headerSubtitle`, the line reads `Agent · {channel}` for a conversation started in a channel its row names |
149
- | `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 |
150
- | `onAgentNameClick` | `(agent: XtmAgent) => void` | — | Takes a plain click on the header's agent name (over `agentHref`); the chevron beside it opens the picker |
150
+ | `agentHref` | `(agent: XtmAgent) => string \| undefined` | — | The agent's page (http(s) or a path of the host's origin), followed in place from the "Open agent page" item of the agent switcher; the header's agent control itself always opens the switcher |
151
+ | `onAgentNameClick` | `(agent: XtmAgent) => void` | — | Takes a plain click on the switcher's "Open agent page" item (over `agentHref`) |
151
152
  | `clearAllAction` | `'delete' \| 'archive'` | `'delete'` | What Clear all does, for its wording (`Archive all conversations`) |
152
153
 
153
154
  Plain-data props (`requestHeaders`, `apiEndpoints`, `pageContext`, `promptSuggestions`) are compared by content and callback props are called
@@ -1287,6 +1288,11 @@ both. The same variables may be set in CSS on an ancestor instead.
1287
1288
  | `surfaceSubtle` | `--filigran-chat-surface-subtle` | Cards, search boxes, a table's or a code block's header |
1288
1289
  | `surfaceHover` | `--filigran-chat-surface-hover` | A row or a button under the pointer |
1289
1290
  | `inputSurface` | `--filigran-chat-input-surface` | A text field: the composer (no fill unless set), a rename field, the feedback and approval comments |
1291
+ | `inputRadius` | `--filigran-chat-input-radius` | The composer's corners (0.75rem unset) |
1292
+ | `inputMinHeight` | `--filigran-chat-input-min-height` | The composer field's height at rest, before it grows with the text (two lines unset) |
1293
+ | `focusRing` | `--filigran-chat-focus-ring` | The 2 px ring around the composer while it has the focus (the accent unset) |
1294
+ | `danger` | `--filigran-chat-danger` | The tone of every error state: error notices, a failed upload, dictation, stop (a red unset, e.g. `var(--color-error)`) |
1295
+ | `warning` | `--filigran-chat-warning` | The tone of every warning notice (an amber unset, e.g. `var(--color-warning)`) |
1290
1296
  | `headerBackground` | `--filigran-chat-header-background` | The header's background, a colour or an image (`none` for the surface alone) |
1291
1297
  | `text` | `--filigran-chat-text` | Text |
1292
1298
  | `textMuted` | `--filigran-chat-text-muted` | Times, labels, hints and placeholders |
@@ -1440,11 +1446,14 @@ A host behind its own proxy points the routes at it, relative to its
1440
1446
  `{ prompts: '/prompts', quota: '/quota', feedback: '/conversations' }`
1441
1447
  (`feedback`: see [Message feedback](#message-feedback)).
1442
1448
 
1443
- The welcome screen names the selected agent and shows its own suggestions —
1444
- which is also how switching agent is confirmed: the thread resets to that
1445
- screen, so without it nothing tells you who the next message will reach. When
1446
- the suggestions route is unavailable the host's `promptSuggestions` prop is used
1447
- instead, so the section is never empty.
1449
+ The welcome screen is short: the agent's mark, one greeting line naming the
1450
+ selected agent (which is also how switching agent is confirmed: the thread
1451
+ resets to that screen, so without it nothing tells you who the next message
1452
+ will reach), and the agent's own suggestions as compact chips. The agent's
1453
+ description is never shown there (it is picker and agent-page prose). When the
1454
+ suggestions route is unavailable the host's `promptSuggestions` prop is used
1455
+ instead; with neither, no suggestion is shown: the package carries no generic
1456
+ list of its own.
1448
1457
 
1449
1458
  Dictation needs no configuration at all: it uses the browser's own Web Speech
1450
1459
  API, so the mic button appears inside the text field, next to Send, wherever
package/dist/index.d.ts CHANGED
@@ -392,6 +392,20 @@ interface ChatPanelTheme {
392
392
  surfaceHover?: string;
393
393
  /** A text field: the composer (no fill unless set), a rename field, the feedback and approval comments (`--filigran-chat-input-surface`). */
394
394
  inputSurface?: string;
395
+ /** The composer's corners, as the host's text fields draw theirs (`--filigran-chat-input-radius`, `radiusMd` unset). */
396
+ inputRadius?: string;
397
+ /** The small corner of every control, chip and avatar tile, the design system's `--radius-sm` (`--filigran-chat-radius-sm`, 4px unset). */
398
+ radiusSm?: string;
399
+ /** The card corner of every card, bubble, status indicator, menu and dialog, the design system's `--radius-md` (`--filigran-chat-radius-md`, 12px unset). */
400
+ radiusMd?: string;
401
+ /** The composer field's height at rest, before it grows with the text (`--filigran-chat-input-min-height`, two lines unset). */
402
+ inputMinHeight?: string;
403
+ /** The 2 px ring drawn around the composer while it has the focus (`--filigran-chat-focus-ring`, the accent unset). */
404
+ focusRing?: string;
405
+ /** The danger tone of every error state: notices, a failed upload, dictation, stop (`--filigran-chat-danger`, a red unset). */
406
+ danger?: string;
407
+ /** The warning tone of every warning notice (`--filigran-chat-warning`, an amber unset). */
408
+ warning?: string;
395
409
  /** The header's background, a colour or an image; `none` for the surface alone (`--filigran-chat-header-background`). */
396
410
  headerBackground?: string;
397
411
  /** Text (`--filigran-chat-text`). */
@@ -415,6 +429,10 @@ interface ChatPanelTheme {
415
429
  codeSize?: string;
416
430
  codeSurface?: string;
417
431
  }
432
+ /** Draws an agent icon given by name at `size` pixels; `null` when the host has no such icon. */
433
+ type ChatAgentIconRenderer = (name: string, options: {
434
+ size: number;
435
+ }) => React.ReactNode;
418
436
  interface ChatPanelProps {
419
437
  mode: ChatPanelMode;
420
438
  /** Shows the close button; inline mode has none. */
@@ -449,6 +467,13 @@ interface ChatPanelProps {
449
467
  t?: Translate;
450
468
  accentColor?: string;
451
469
  logoIcon?: React.ReactNode;
470
+ /**
471
+ * Draws an agent icon given by name (`XtmAgent.icon`,
472
+ * `ChatConversationSummary.agentIcon`, e.g. `brain-circuit`), which the
473
+ * panel cannot draw itself: in the conversation rows and the agent switcher.
474
+ * `null` keeps the panel's glyph. Image URLs and emoji are drawn by the panel.
475
+ */
476
+ renderAgentIcon?: ChatAgentIconRenderer;
452
477
  promptSuggestions?: string[];
453
478
  /** Accepted, and not shown. */
454
479
  draftLabel?: string;
@@ -1362,6 +1387,12 @@ interface ChatConversationSummary {
1362
1387
  * genuinely have no agent.
1363
1388
  */
1364
1389
  agentName?: string;
1390
+ /**
1391
+ * The conversation agent's icon (`agent_icon`), an image URL or an emoji as
1392
+ * `XtmAgent.icon`, when the backend reports one: the row draws it in place of
1393
+ * the panel's generic glyph.
1394
+ */
1395
+ agentIcon?: string;
1365
1396
  /**
1366
1397
  * The workspace the conversation is filed in (`null`: none), when the
1367
1398
  * backend reports it. Undefined on backends that do not.
@@ -1407,7 +1438,7 @@ interface XtmAgent {
1407
1438
  id: string;
1408
1439
  name: string;
1409
1440
  slug: string | null;
1410
- /** An image URL or an emoji; anything else shows the panel's logo. */
1441
+ /** An image URL, an emoji, or a name drawn by `ChatPanelProps.renderAgentIcon`; else the panel's logo. */
1411
1442
  icon: string | null;
1412
1443
  description: string | null;
1413
1444
  /** The heading the agent picker lists it under; ungrouped agents come first. */
@@ -1440,4 +1471,4 @@ interface TransferredAgent {
1440
1471
  declare const voiceCallSupported: () => boolean;
1441
1472
 
1442
1473
  export { ChatPanel, ChatToggleButton, voiceCallSupported };
1443
- export type { AgentStatusState, ApiEndpoints, BackendType, ChatAnsweredBy, ChatArtifact, ChatArtifactKind, ChatAttachment, ChatCodeBlockContext, ChatCodeBlockRenderer, ChatContextBreakdown, ChatContextUsage, ChatConversationAction, ChatConversationChange, 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 };
1474
+ export type { AgentStatusState, ApiEndpoints, BackendType, ChatAgentIconRenderer, ChatAnsweredBy, ChatArtifact, ChatArtifactKind, ChatAttachment, ChatCodeBlockContext, ChatCodeBlockRenderer, ChatContextBreakdown, ChatContextUsage, ChatConversationAction, ChatConversationChange, 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 };