@filigran/chatbot 3.12.1 → 3.13.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 ADDED
@@ -0,0 +1,108 @@
1
+ # Changelog
2
+
3
+ Notable changes to `@filigran/chatbot`, so a host can see what an upgrade brings
4
+ before taking it.
5
+
6
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
7
+ the versions follow [semantic versioning](https://semver.org/spec/v2.0.0.html).
8
+ This file starts at 3.10.0; earlier releases are on the
9
+ [releases page](https://github.com/FiligranHQ/filigran-ui/releases).
10
+
11
+ ## 3.13.0 — unreleased
12
+
13
+ ### Added
14
+
15
+ - The assistant can act on the page the panel is mounted in (#441). The agent
16
+ asks for one step at a time — take a snapshot, click, open a menu, type, or
17
+ navigate — and the panel answers each with a fresh reading of the page.
18
+ - The reading lists one line per control a user could act on, with its role,
19
+ accessible name, state and in-app destination, so the agent can name the one
20
+ it means.
21
+ - `Acting on the page…` shows on the status line while a step runs.
22
+
23
+ ### Host opt-in
24
+
25
+ - The panel offers the capability only when the host sets `apiEndpoints.approve`
26
+ **and** passes `onRelativeLinkClick`, because its proxy has to forward the
27
+ answer whole. A host that offers neither is unaffected, and a step arriving
28
+ without that opt-in is refused without the page being read or touched.
29
+
30
+ ### Security
31
+
32
+ - A reading never carries a secret: a password, a one-time code or a card field
33
+ is masked by `type` and by `autocomplete`, and its contents cannot surface
34
+ through an enclosing control's name or value, nor through a heading above it.
35
+ Hidden, `aria-hidden`, `inert` and closed `<details>` content stays out, as
36
+ does the panel's own.
37
+ - A step that would leave the page is refused rather than performed: another
38
+ origin, a link that opens a tab, a path that resolves off-site. A click or a
39
+ form submission that would load a page is cancelled while the host's own
40
+ handlers still run.
41
+ - A step is refused on a control the user could not use either: disabled,
42
+ read-only, a masked field, a file chooser, or one no longer visible when the
43
+ step runs.
44
+ - A step ends with the turn that asked for it. Stop, New chat, switching
45
+ conversation and closing the panel all end it, and one arriving afterwards is
46
+ answered rather than left to time out.
47
+
48
+ ## 3.12.2 — 2026-10-02
49
+
50
+ ### Fixed
51
+
52
+ - The panel keeps its own styles inside a host that ships its Tailwind utilities
53
+ outside any cascade layer: the message action icons were invisible and the
54
+ header hover backgrounds round instead of square (#431).
55
+
56
+ ## 3.12.1 — 2026-10-01
57
+
58
+ ### Fixed
59
+
60
+ - The reader can scroll up while the agent reasons or streams. The transcript
61
+ follows the end only while the reader is there; scrolling up stops the follow,
62
+ and returning to the bottom or sending a message resumes it (#429).
63
+
64
+ ## 3.12.0 — 2026-09-30
65
+
66
+ ### Added
67
+
68
+ - Every message ends with a footer: an answer shows its time, reasoning details,
69
+ Copy response, thumbs up / down and Read aloud; a user message shows Copy and
70
+ its time.
71
+ - Message times follow the new `locale` prop, and an answer is dated when it
72
+ completes, so the live time matches the time after a reload.
73
+ - Persisted feedback through the new `apiEndpoints.feedback`, optimistic and
74
+ rolled back on error; a rating restored with the conversation is locked (#419).
75
+
76
+ ## 3.11.1 — 2026-09-29
77
+
78
+ ### Changed
79
+
80
+ - The dictation button sits inside the composer, before Send, so its toolbar row
81
+ no longer appears alone in hosts with nothing else to put there.
82
+ - Listening is visible on the field itself, and the composer height no longer
83
+ shifts.
84
+ - Every send cancels dictation and drops the phrase still being recognised, so
85
+ no words land in a composer that was just emptied.
86
+
87
+ ## 3.11.0 — 2026-09-29
88
+
89
+ ### Changed
90
+
91
+ - A streamed answer is rendered block by block: a chunk re-parses only the blocks
92
+ it can still change.
93
+ - Streamed text and reasoning are applied once per animation frame rather than
94
+ once per network read.
95
+ - The markdown renderers keep their identity, so the live answer's DOM, a
96
+ selection in it and its images are no longer rebuilt per chunk.
97
+
98
+ ## 3.10.0 — 2026-09-26
99
+
100
+ ### Changed
101
+
102
+ - The waiting game is a link to the XTM One arcade rather than an embedded game
103
+ (#411).
104
+
105
+ ### Fixed
106
+
107
+ - The agent's reasoning stays on screen instead of being replaced by the waiting
108
+ game (#409).
package/README.md CHANGED
@@ -507,6 +507,58 @@ chat must forward the request body whole (a proxy rebuilding it from a fixed
507
507
  field list silently drops `supports_tool_approval`), never time out the
508
508
  streaming turn, and pass SSE keepalives through untouched.
509
509
 
510
+ #### Acting on the host page
511
+
512
+ The same path answers `act_on_page` (XTM One #5559): with `apiEndpoints.approve`
513
+ set **and** `onRelativeLinkClick` passed — the host's opt-in, since it hands the
514
+ panel its navigation — the panel also sends `supports_page_actions: true`, and the
515
+ agent may act on the page the panel is mounted in. The host's proxy must forward
516
+ the approve route's body whole (a `page_action` answer carries no `decisions`).
517
+ Without that opt-in a frame is answered `page_actions_not_supported`, with the
518
+ page neither read nor acted on. Each step arrives on the stream as a
519
+ `status` frame with `event: "page_action_required"`; the panel performs it
520
+ (`click`, `open` — a hover, or a click when hovering opens nothing —, `type`, then
521
+ Enter only in a field that says it is a search - `type="search"`,
522
+ `role="searchbox"`, inside `role="search"`, or named like one (a `name`, `id`,
523
+ `placeholder`, `aria-label` or `title` whose whole words include "search",
524
+ "query", "filter" or "find", and only when it is the form's sole field) - never
525
+ in a form of one unnamed field, which is as likely a create or
526
+ rename dialog,
527
+ or `navigate` through `onRelativeLinkClick` — never
528
+ a page load, which would end the turn) and POSTs
529
+ `{ conversation_id, page_action: { action_id, ok, error, url, title, snapshot } }`.
530
+ `ok` is the action's own outcome, so a step is never retried because reading the
531
+ page back failed; when that read throws, `ok` stands and `error` carries
532
+ `snapshot_failed: …` with an empty snapshot. A stopped turn (Stop, New chat,
533
+ switching conversation) abandons the action instead of acting on the page.
534
+
535
+ The snapshot (`utils/pageSnapshot.ts`) lists one line per element a user could
536
+ act on — `[e1] link "Reports" -> /dashboard/analyses/reports`, with states such as
537
+ `(selected)`, `(pressed)`, `(menu)` for a closed menu or `(collapsed)` for a closed
538
+ group
539
+ — and leaves out the panel itself, hidden and inert content, and every secret
540
+ value: a `type="password"` field, and anything whose `autocomplete` marks it as a
541
+ password, a one-time code or a card field, so a revealed password is masked too.
542
+ A list cut off at the size cap ends with `[truncated]`. A state the host shows by
543
+ styling alone is invisible to it: mark toggles
544
+ with `aria-pressed`, the current item with `aria-current`, and a clickable card
545
+ with `role="button"`. A `409` means the
546
+ turn no longer waits for that action, and the panel drops it.
547
+
548
+ Actions that would leave the page are refused rather than performed, each
549
+ answered with `ok: false` and a reason: a `navigate` off-site, a `click` on a
550
+ link to another origin or one opening a new tab, a `type` on anything that is
551
+ not a text field, a read-only field, a masked one (a password, one-time code
552
+ or card field), a file input (whose chooser is an operating-system window), a
553
+ target that is disabled - including one disabled by its `<fieldset>` - and one
554
+ no longer visible when the action runs. A click never completes a native default that
555
+ would leave the page: an anchor's navigation and a form's submission are
556
+ cancelled while the host's own handlers still run. Clicking an in-host link is
557
+ routed through `onRelativeLinkClick` rather than clicked, for the same reason a
558
+ `navigate` is. An action this version does not know is answered as
559
+ `unsupported_action` instead of being dropped, so a backend running ahead of the
560
+ panel is not left waiting out its timeout.
561
+
510
562
  #### Recovering a prompt after a page reload
511
563
 
512
564
  `approval_required` is a single event on a stream, so a reload loses it —
@@ -900,6 +952,15 @@ import '@filigran/chatbot/styles.css';
900
952
 
901
953
  The component uses Tailwind CSS classes and CSS custom properties for theming. The accent color is applied via `--chat-accent` CSS variable.
902
954
 
955
+ The stylesheet is isolated from the host page in both directions. Every utility
956
+ is scoped to the panel (`.filigran-chatbot` and its descendants) and declared
957
+ outside any cascade layer, and the theme variables (`--radius-*`, `--spacing`,
958
+ ...) are declared on the panel root. The host's own utilities and `:root`
959
+ tokens - a Tailwind build shipped without layers, such as the Filigran design
960
+ system's - therefore never restyle the panel, and the panel's utilities never
961
+ style the host page. Panel overlays (menus, dialogs, tooltips) render inside
962
+ the panel root, so they keep its styles.
963
+
903
964
  ### Composer toolbar
904
965
 
905
966
  Two toolbar items are **data-driven rather than mode-driven**: they appear only