proximal-onyx-widget
v0.1.0
Published
Proximal build of the Onyx chat widget: legacy-stream compatible, with built-in diagnostic logging. Embed an AI chat assistant on any site with a single script tag.
Maintainers
Readme
proximal-onyx-widget
Proximal's build of the Onyx chat widget. Adds three things over the stock CDN builds:
- Legacy-stream compatibility — talks to both the legacy line-JSON stream
format and the newer enveloped format, so it works against self-hosted Onyx
backends (like ours) that the stock
cdn.onyx.appbuilds crash on. - Diagnostic logging — every network call, retry, stream packet failure, and empty LLM response is recorded to an in-page ring buffer and (for warnings/errors) the browser console, so "the bot didn't answer" is debuggable in production.
- Link masking — citation badges and URLs inside answers that point at Google Drive/Docs (configurable) render as plain text instead of links, so the widget never hands visitors a link to a source document.
Quick start — embed with one script tag
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/embed.js"
data-backend-url="https://chat.aistudio.proximal.cloud/api"
data-api-key="YOUR_WIDGET_API_KEY"
data-agent-name="Proximal Assistant"
data-mode="launcher"
data-include-citations="true"
></script>Use a plain script tag (no type="module"); the loader injects the widget
bundle (an ES module) itself and mounts <onyx-chat-widget> on document.body
once the DOM is ready.
Supported data-* attributes
| Attribute | Required | Description |
| --- | --- | --- |
| data-backend-url | yes | Onyx API base, e.g. https://host/api |
| data-api-key | yes | Onyx API key (use a widget-scoped, least-privilege key — it is visible to anyone viewing the page source) |
| data-agent-id | no | Persona/agent id to chat with |
| data-agent-name | no | Display name (default Assistant) |
| data-logo | no | Logo URL for the header/avatar |
| data-mode | no | launcher (floating button, default) or inline |
| data-include-citations | no | true to render source citations |
| data-mask-link-hosts | no | Hosts whose links are masked (rendered as text). Default: Google Drive/Docs. Comma-separated hostnames; default expands to the built-in list, * masks every link, none disables. See Link masking |
| data-locale | no | UI language: en, zh-CN, zh-TW, or ja. Defaults to the visitor's browser language (auto-detected), falling back to English |
| data-primary-color | no | Accent color, hex |
| data-background-color | no | Panel background, hex |
| data-text-color | no | Text color, hex |
| data-z-index | no | Stacking override for the host page |
| data-widget-src | no | Override URL of onyx-widget.js (defaults to the file next to embed.js) |
Using the web component directly
If you prefer to control mounting yourself (e.g. inside a React effect):
<script type="module" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/onyx-widget.js"></script>
<onyx-chat-widget
backend-url="https://chat.aistudio.proximal.cloud/api"
api-key="YOUR_WIDGET_API_KEY"
agent-name="Proximal Assistant"
mode="launcher"
></onyx-chat-widget>Note: the bundle is an ES module — loading it cross-origin requires the CDN to
send Access-Control-Allow-Origin (jsDelivr/unpkg do; if you self-host, set
the header yourself).
Localization
The widget UI (placeholders, button titles, disclaimer, streaming status
messages, error messages) is localized in English (en), Simplified Chinese
(zh-CN), Traditional Chinese (zh-TW), and Japanese (ja).
Language is resolved in this order:
?onyx-locale=<code>in the page URL — a test override that beats everything; open any page with?onyx-locale=ja(orzh-CN,zh-TW,en) to preview that language.- The
localeattribute (data-localevia the embed loader). - The visitor's browser language (
navigator.language) —zh-Hans/zh-SGmap tozh-CN;zh-Hant/zh-HK/zh-MOmap tozh-TW. - English.
Note: this localizes the widget chrome. The assistant's answers are generated by the backend LLM, which typically replies in the language the user writes in (or as the agent's prompt instructs).
Translations are authored as one JSON file per language in locales/ and
compiled into the bundle by scripts/onyx-l10n.mjs (run via pnpm onyx:sync),
which also validates key/placeholder parity across locales. To add a
language, add locales/<code>.json with the full key set and re-run the
sync — do not edit the strings inside dist/onyx-widget.js directly.
Link masking
Onyx returns each cited document's title and URL, and the LLM may paste URLs
into its answer. By default the widget masks Google Drive/Docs links
(drive.google.com, docs.google.com, drive.usercontent.google.com, and
their subdomains) everywhere they could surface:
- citation badges for a masked document render as a non-clickable chip
(title still shown, no
href); - Markdown links to a masked host render as their label text; bare URLs (including inside code spans) and autolinks become a localized "[link hidden]" placeholder; images hosted there render as their alt text.
Configure with mask-link-hosts (data-mask-link-hosts via the loader):
| Value | Effect |
| --- | --- |
| (absent) / default | Google Drive/Docs hosts |
| default, sharepoint.com, dropbox.com | built-in list plus your own hosts (parent domains match subdomains) |
| * | mask every link |
| none | disable masking |
Links masked inside answer text are counted in the link.masked debug
event (citation badges are masked silently). This is a presentation-layer
safeguard: the document titles and URLs still travel in
the API response, and the answer is still generated from those documents.
Restrict the agent's document sets in the Onyx admin panel for real access
control; use masking as the belt-and-suspenders layer on top.
Debugging
- Append
?onyx-debug=1to the page URL, or run__ONYX_WIDGET__.enableDebug()in the console, to log every widget event (boot, session create, send, stream progress) — errors and warnings are logged even without debug mode. __ONYX_WIDGET__.logs— array of the last 300 events (with timestamps).__ONYX_WIDGET__.dump()— prints and returns the log buffer as JSON, for attaching to bug reports.
Event reference and troubleshooting guide: docs/onyx-widget-distribution.md
Versioning
dist/onyx-widget.js is built from the Onyx repo's widget/ package at the
tag matching our backend version, plus a local patch — the rebuild procedure
lives in vendor/onyx-widget/README.md in the parent repo. This package's
version tracks our patch revisions, not the Onyx backend version.
