@filigran/chatbot 3.9.0 → 3.9.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/README.md CHANGED
@@ -121,13 +121,14 @@ import { ChatToggleButton } from '@filigran/chatbot';
121
121
 
122
122
  #### Props
123
123
 
124
- | Prop | Type | Default | Description |
125
- | ------------- | ----------------- | ------------ | ------------------------------ |
126
- | `isOpen` | `boolean` | **required** | Whether the chat panel is open |
127
- | `onToggle` | `() => void` | **required** | Called when button is clicked |
128
- | `label` | `string` | `'Chat'` | Tooltip/aria label |
129
- | `accentColor` | `string` | `'#7b5cff'` | Button background color |
130
- | `icon` | `React.ReactNode` | default icon | Custom icon |
124
+ | Prop | Type | Default | Description |
125
+ | ------------- | ------------------------- | ------------ | -------------------------------------------------------------------------- |
126
+ | `isOpen` | `boolean` | **required** | Whether the chat panel is open |
127
+ | `onToggle` | `() => void` | **required** | Called when button is clicked |
128
+ | `label` | `string` | built-in | Button text, already translated by the host; omit for `t('Ask Assistant')` |
129
+ | `t` | `(key: string) => string` | identity | Translation function, used for the default label |
130
+ | `accentColor` | `string` | `'#7b5cff'` | Button background color |
131
+ | `icon` | `React.ReactNode` | default icon | Custom icon |
131
132
 
132
133
  ## API Contract
133
134
 
@@ -571,59 +572,230 @@ function App() {
571
572
  }
572
573
  ```
573
574
 
574
- **Translation keys used:**
575
+ `t` is only ever asked for a lookup — key in, translated string out — so any
576
+ i18n library works and the package never carries a dictionary of its own.
577
+ Untranslated hosts can omit it: the default is the identity function, so every
578
+ key is its own English text.
575
579
 
576
- - `'Thinking...'`
577
- - `'Using tools…'`
578
- - `'Analyzing results…'`
579
- - `'Composing answer…'`
580
- - `'Incorporating your message…'`
581
- - `'Ask a question...'`
582
- - `'Stop generating'`
583
- - `'Send now'`
584
- - `'Enter to send now · Esc to stop'`
585
- - `'Attachments wait for the current response'`
586
- - `'New chat'`
580
+ #### Values inside sentences
581
+
582
+ A key is always a **whole sentence**, with `{placeholder}` slots for the values.
583
+ The panel fills the slots in _after_ the lookup, so a locale is free to move the
584
+ value, and a translator sees the sentence rather than a fragment of one:
585
+
586
+ | Key | Renders as |
587
+ | --- | --- |
588
+ | `'Waiting for {count} background tasks…'` | Waiting for 3 background tasks… |
589
+ | `'Transferred from {agent}'` | Transferred from Threat Analyst |
590
+ | `'{percent}% full'` | 84% full |
591
+ | `'How can {agent} help you, {name}?'` | How can **Threat Analyst** help you, John? |
592
+
593
+ Two consequences worth knowing when writing the locale files:
594
+
595
+ - **Plurals are separate keys** — `'1 tool call'` and `'{count} tool calls'`,
596
+ `'Delegating one task…'` and `'Delegating {count} tasks…'`. A lookup cannot
597
+ select a plural form, so the panel picks the sentence and the locale
598
+ translates it whole; a language with more plural forms than English can route
599
+ the plural key through its own rules.
600
+ - **A missing slot is not fatal** — a translation that drops a `{placeholder}`
601
+ renders the rest of the sentence as it is, and the value is simply absent.
602
+ That includes the greeting, where the agent's name is markup: a locale that
603
+ rewords the sentence without `{agent}` gets the sentence, not a name dangling
604
+ off the end of it.
605
+
606
+ `promptSuggestions` (and any suggestions the backend serves) also go through
607
+ `t`, so a host may pass either keys or final text.
608
+
609
+ #### Translation keys used
610
+
611
+ Every key the package can ask for, grouped by where it appears:
612
+
613
+ **Toggle button**
614
+
615
+ - `'Ask Assistant'`
616
+
617
+ **Header, agent menu and history**
618
+
619
+ - `'Agent switching is not available here'`
620
+ - `'Browse agents'`
621
+ - `'Close'`
587
622
  - `'Conversation history'`
588
- - `'No conversations yet'`
589
- - `'Untitled conversation'`
590
- - `'New conversation'`
623
+ - `'Could not reach the assistant service. Check the connection and try again.'`
624
+ - `'Create agent'`
591
625
  - `'Delete conversation'`
592
- - `'just now'` / `'m ago'` / `'h ago'` / `'d ago'`
593
- - `'Switch view'`
594
- - `'Close'`
626
+ - `'Floating'`
627
+ - `'Full screen'`
628
+ - `'New chat'`
629
+ - `'New conversation'`
630
+ - `'No agent matches'`
631
+ - `'No conversations yet'`
632
+ - `'Search agents...'`
633
+ - `'Sidebar'`
634
+ - `'Switch to'`
595
635
  - `'Switch to another agent'`
596
- - `'Browse agents'`
597
- - `'Create agent'`
636
+ - `'Switch view'`
637
+ - `'Transferred from {agent}'`
638
+ - `'Untitled conversation'`
639
+
640
+ **Conversation sidebar**
641
+
642
+ - `'Conversation title'`
643
+ - `'Hide conversations'`
644
+ - `'No conversation matches'`
645
+ - `'Rename conversation'`
646
+ - `'Search conversations...'`
647
+ - `'Show conversations'`
648
+
649
+ **Welcome screen**
650
+
651
+ - `'Assistant'`
652
+ - `'Help me create a new simulation scenario'`
653
+ - `'How can I help you, {name}?'`
654
+ - `'How can {agent} help you, {name}?'`
655
+ - `'How do I configure detection rules?'`
656
+ - `'Suggestions'`
657
+ - `'Summarize my recent findings'`
658
+ - `'What are the latest attack patterns?'`
659
+
660
+ **Composer**
661
+
662
+ - `'Ask a question...'`
663
+ - `'Attachments wait for the current response'`
664
+ - `'Dictate a message'`
665
+ - `'Enter to send now · Esc to stop'`
666
+ - `'Files uploading...'`
667
+ - `'Insert prompt template'`
668
+ - `'No prompt matches'`
669
+ - `'Search prompts...'`
670
+ - `'Send now'`
671
+ - `'Stop dictation'`
672
+ - `'Stop generating'`
673
+ - `'Uses AI. Verify results.'`
674
+
675
+ **Messages, markdown and files**
676
+
677
+ - `'Bad response'`
678
+ - `'Copied'`
679
+ - `'Copied!'`
680
+ - `'Copy code'`
681
+ - `'Copy response'`
682
+ - `'Download'`
683
+ - `'Expand image'`
684
+ - `'Good response'`
685
+ - `'Image could not be loaded'`
686
+ - `'Image preview'`
687
+ - `'Load earlier messages'`
688
+ - `'Loading image…'`
598
689
  - `'Reasoning details'`
599
690
  - `'Reasoning details — turn limit reached'`
691
+
692
+ **Agent status**
693
+
694
+ - `'Analyzing results…'`
695
+ - `'Collecting results from one task…'`
696
+ - `'Collecting results from {count} tasks…'`
697
+ - `'Composing answer…'`
698
+ - `'Consulting {agent}…'`
699
+ - `'Delegating one task…'`
700
+ - `'Delegating {count} tasks…'`
701
+ - `'Incorporating your message…'`
702
+ - `'Thinking...'`
703
+ - `'Transferring to {agent}…'`
704
+ - `'Using tools…'`
705
+ - `'Waiting for one background task…'`
706
+ - `'Waiting for your approval…'`
707
+ - `'Waiting for {count} background tasks…'`
708
+ - `'the agent'`
709
+ - `'{tool} (+{count} more)…'`
710
+
711
+ **Waiting mini-game**
712
+
713
+ - `'Almost there'`
714
+ - `'Analyzing the details'`
715
+ - `'Connecting the dots'`
716
+ - `'Consulting the sources'`
717
+ - `'Crunching the data'`
718
+ - `'Polishing the answer'`
719
+ - `'Putting it together'`
720
+ - `'Reticulating splines'`
721
+ - `'Thinking it through'`
722
+ - `'Turn off the waiting mini-game'`
723
+ - `'Turn on the waiting mini-game'`
724
+ - `'Wrapping things up'`
725
+
726
+ **Reasoning details**
727
+
728
+ - `'(no output)'`
729
+ - `'1 tool call'`
730
+ - `'1 transfer'`
731
+ - `'Input'`
600
732
  - `'Model reasoning'`
601
- - `'iterations'`
602
- - `'transfer'` / `'transfers'`
733
+ - `'Output'`
734
+ - `"The agent's iteration budget was exhausted - execution stopped before completing all planned steps. The final response is a best-effort summary of work done so far."`
603
735
  - `'Transfer chain'`
604
736
  - `'Turn limit reached.'`
605
- - `"The agent's iteration budget was exhausted - execution stopped before completing all planned steps. The final response is a best-effort summary of work done so far."`
606
- - `'Input'` / `'Output'` / `'(no output)'`
607
- - `'Download'`
608
- - `'tool call'` / `'tool calls'`
609
- - `'Uses AI. Verify results.'`
610
- - `'How can I help you, '`
611
- - `'Suggestions'`
612
- - `'Waiting for your approval…'`
613
- - `'The agent needs your approval to run a tool:'` / `'The agent needs your approval to run these tools:'`
614
- - `'Yes'` / `'No'` / `'Yes, always'` / `'Back'` / `'Confirm'` / `'Sending…'` / `'decided'`
615
- - `'Approved'` / `'Declined'` / `'Always allowed'`
737
+ - `'{count} iterations'`
738
+ - `'{count} tool calls'`
739
+ - `'{count} transfers'`
740
+
741
+ **Tool approval**
742
+
743
+ - `'Also applies to your scheduled runs, until you revoke it'`
744
+ - `'Always allowed'`
745
+ - `'Approved'`
746
+ - `'Back'`
747
+ - `'Confirm'`
616
748
  - `'Decline this call'`
749
+ - `'Declined'`
750
+ - `'No'`
751
+ - `'Sending…'`
752
+ - `'The agent needs your approval to run a tool:'`
753
+ - `'The agent needs your approval to run these tools:'`
617
754
  - `'Why not? The agent sees this and can adapt (optional)'`
755
+ - `'Yes'`
756
+ - `'Yes, always'`
618
757
  - `'e.g. wrong environment — use staging instead'`
619
- - `'Also applies to your scheduled runs, until you revoke it'`
758
+ - `'unknown tool'`
759
+ - `'{decided}/{total} decided'`
620
760
  - `'“Yes, always” saves a preference for you. That tool will then run without asking — including on scheduled runs nobody is watching — until you revoke it.'`
621
- - `'This turn is no longer waiting for a decision.'`
761
+
762
+ **Context gauge**
763
+
764
+ - `'Context full — older turns are being dropped'`
765
+ - `'Context nearly full — older turns are being summarized'`
766
+ - `'Context used'`
767
+ - `'Conversation'`
768
+ - `'MCP & dynamic tools'`
769
+ - `'Summarized conversation'`
770
+ - `'System prompt'`
771
+ - `'Tool definitions'`
772
+ - `'Tool results'`
773
+ - `'{counts} tokens'`
774
+ - `'{percent}% full'`
775
+ - `'{summary} — click for details'`
776
+
777
+ **Quota**
778
+
779
+ - `'Quota'`
780
+ - `'Quota reached'`
781
+ - `'Usage'`
782
+ - `'Usage · {period}'`
783
+
784
+ **Notices, errors and timestamps**
785
+
622
786
  - `'Could not send your decision. Please try again.'`
787
+ - `'No response.'`
788
+ - `'Response ready'`
789
+ - `'Sorry, an error occurred. Please try again.'`
623
790
  - `'This decision could not be sent. Reload the chat and try again.'`
624
- - `'Floating'`
625
- - `'Sidebar'`
626
- - `'Full screen'`
791
+ - `'This turn is no longer waiting for a decision.'`
792
+ - `'Unable to connect. Please check the configuration.'`
793
+ - `'Your answer is ready'`
794
+ - `'just now'`
795
+ - `'{agent} has finished'`
796
+ - `'{count}d ago'`
797
+ - `'{count}h ago'`
798
+ - `'{count}m ago'`
627
799
 
628
800
  ## Styling
629
801
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,14 @@
1
1
  import { FunctionComponent } from 'react';
2
2
 
3
3
  type ChatMode = 'sidebar' | 'floating' | 'fullscreen';
4
+ /**
5
+ * The host's translation lookup, passed down to every component that renders
6
+ * text. Key in, translated string out — the package never owns a dictionary of
7
+ * its own, and never asks the host's `t` for more than a lookup: values are
8
+ * spliced into the *translated* sentence by `translate()` in `utils`, so a key
9
+ * is always a whole sentence and a locale stays free to reorder it.
10
+ */
11
+ type Translate = (key: string) => string;
4
12
  type BackendType = 'legacy' | 'rest' | 'ag-ui';
5
13
  /** A user's rating of one assistant answer. */
6
14
  type MessageFeedback = 'up' | 'down';
@@ -156,6 +164,7 @@ interface ToolApprovalProposal {
156
164
  * different arguments.
157
165
  */
158
166
  toolCallId: string;
167
+ /** Empty when the backend named no tool; the UI labels that case itself. */
159
168
  toolName: string;
160
169
  toolDescription?: string;
161
170
  arguments: Record<string, unknown>;
@@ -240,7 +249,7 @@ interface ChatPanelProps {
240
249
  user: {
241
250
  firstName: string;
242
251
  };
243
- t?: (key: string) => string;
252
+ t?: Translate;
244
253
  accentColor?: string;
245
254
  logoIcon?: React.ReactNode;
246
255
  promptSuggestions?: string[];
@@ -365,7 +374,9 @@ interface ChatPanelProps {
365
374
  interface ChatToggleButtonProps {
366
375
  isOpen: boolean;
367
376
  onToggle: () => void;
377
+ /** Overrides the built-in label; already translated by the host. */
368
378
  label?: string;
379
+ t?: Translate;
369
380
  accentColor?: string;
370
381
  icon?: React.ReactNode;
371
382
  }
@@ -495,4 +506,4 @@ interface TransferredAgent {
495
506
  }
496
507
 
497
508
  export { ChatPanel, ChatToggleButton };
498
- export type { ApiEndpoints, BackendType, ChatAttachment, ChatContextBreakdown, ChatContextUsage, ChatConversationSummary, ChatFile, ChatMessage, ChatMode, ChatPanelProps, ChatPromptTemplate, ChatQuotaStatus, ChatToggleButtonProps, MessageFeedback, ToolApprovalDecision, ToolApprovalProposal, ToolApprovalVerdict, TransferredAgent, XtmAgent };
509
+ export type { ApiEndpoints, BackendType, ChatAttachment, ChatContextBreakdown, ChatContextUsage, ChatConversationSummary, ChatFile, ChatMessage, ChatMode, ChatPanelProps, ChatPromptTemplate, ChatQuotaStatus, ChatToggleButtonProps, MessageFeedback, ToolApprovalDecision, ToolApprovalProposal, ToolApprovalVerdict, TransferredAgent, Translate, XtmAgent };