AI chat assistant widget integrating iMio's Omnia API for Plone
Project description
A floating AI chat assistant for Plone 6, part of the Omnia suite by iMio.
This package adds a draggable, resizable chat widget to every page of the Plone site. The assistant streams responses from an OpenAI-compatible API through a secure server-side proxy, and can automatically inject the current page content as conversation context. It relies on imio.omnia.core for API connectivity, authentication, and the shared Omnia control panel.
Features
Floating or fixed panel — draggable and resizable floating mode, or a fixed sidebar anchored to the page edge.
Real-time streaming — SSE-based chat completions streamed token by token.
Page context injection — current page content (HTML or plain text, configurable via a CSS selector) is sent as a system message so the assistant can answer questions about the page.
Large-context handling — when the page content exceeds the configured limit the assistant prompts the user to select a relevant text excerpt instead.
Keyboard shortcut — Alt+I toggles the panel open/closed.
Secure by design — API credentials never reach the browser; all requests go through @@omnia-assistant-api with an HMAC-signed token.
Configurable — system prompt, disclaimer, model, display dimensions, conversation length, and context extraction are all adjustable from the control panel.
Installation
Add the egg to your buildout:
[buildout]
...
eggs =
imio.omnia.assistant
Then run bin/buildout.
The package is auto-included in Plone via z3c.autoinclude.plugin, so no ZCML slug is needed.
imio.omnia.core must be installed first. Its GenericSetup profile is declared as a dependency in profiles/default/metadata.xml, so installing imio.omnia.assistant via the Plone add-on control panel is sufficient.
Configuration
All settings are editable from the Assistant tab of the Omnia control panel (Site Setup > Omnia > @@omnia-assistant-settings).
Registry settings
Stored under the prefix imio.omnia.assistant.browser.controlpanel.IOmniaAssistantSettings:
Field |
Purpose |
|---|---|
enabled |
Enable or disable the assistant globally (default: True) |
model |
Model name for the OpenAI-compatible API (vocabulary fetched from the API at form load) |
base_prompt |
System prompt prepended server-side to every conversation |
include_page_content |
Include the current page as context (default: True) |
page_content_selector |
CSS selector(s) to extract page content (default: #content) |
page_content_clean |
Use innerText instead of innerHTML for cleaner extraction (default: False) |
max_context_chars |
Maximum characters of page content to send (default: 20000) |
max_messages_per_session |
Maximum number of user messages allowed in a single conversation (default: 0, unlimited) |
mode |
Panel display mode: floating (draggable) or fixed (sidebar, default: floating) |
initial_width |
Initial panel width in pixels (default: 380) |
initial_height |
Initial panel height in pixels (default: 520) |
disclaimer |
Disclaimer text shown at the bottom of the panel |
How it works
Widget loading
Two Plone resource bundles are registered by the default GenericSetup profile:
omnia-assistant-preact — Preact UMD (loaded first as a global).
omnia-assistant — the assistant UI library (depends on the preact bundle).
An OmniaAssistantConfigViewlet registered in plone.htmlhead renders a <script> tag that:
Sets window.omnia_assistant_settings with configuration from the Plone registry (model, selectors, dimensions, etc.).
Waits for the OmniaAssistantUI global to be available (exported by the bundle).
Calls OmniaAssistantUI.mount('omnia-assistant-root', window.omnia_assistant_settings) to mount the Preact widget into a <div id="omnia-assistant-root"> that the viewlet template appends to the page body.
The widget is not rendered when the enabled setting is False. More generally, page-level availability and server-side prompt composition are exposed through the IOmniaAssistantAdapter multi-adapter. The default implementation reads enabled and base_prompt from the registry.
Streaming chat
Chat messages are sent as POST requests to <portal_url>/@@omnia-assistant-api/chat/completions with stream: true. The assistant proxy inherits from the shared imio.omnia.core.browser.proxy.OmniaOpenAIProxyView implementation, keeps the shared auth/streaming behavior, and forwards the request to the configured OpenAI-compatible gateway in real time.
Authentication uses an HMAC Bearer token generated server-side by the viewlet (imio.omnia.core.tokens.generate_token()). Tokens are signed with the Plone site keyring and expire after 2 hours. By default, the caller must also have the imio.omnia.core: Access Omnia OpenAI proxy permission, which imio.omnia.core grants to Authenticated users.
Projects that need anonymous access can override that permission mapping in their own GenericSetup rolemap.xml.
The request payload follows the OpenAI Chat Completions format:
{
"model": "<configured model>",
"messages": [
{ "role": "system", "content": "<page content>" },
{ "role": "user", "content": "<user message>" }
],
"stream": true
}
If base_prompt is configured, the assistant proxy prepends it server-side as the first system message before dispatching upstream. The prompt is no longer exposed in window.omnia_assistant_settings. Projects can override that behavior with a more specific IOmniaAssistantAdapter that changes availability rules or returns a custom system prompt for the current context/request.
Conversation length limit
When max_messages_per_session is greater than 0, the assistant counts user prompts in the current thread. Assistant replies do not consume the limit.
Once the limit is reached:
the composer is disabled for the current thread,
the UI tells the user to start a new conversation,
the backend proxy also rejects any request whose payload contains more user messages than the configured limit.
Starting a new conversation from the panel header resets the counter because the limit is applied per thread, not across the whole browser session.
Page content injection
When include_page_content is True, the widget extracts DOM content using the CSS selector(s) in page_content_selector (a single selector string, or a JSON array of selectors). Each matching element contributes either its innerHTML or innerText (controlled by page_content_clean), joined by blank lines.
If the extracted content exceeds max_context_chars characters, the widget displays a warning banner and invites the user to select a specific text excerpt on the page. The selected text replaces the full page content as context for that turn.
Uninstall
The uninstall handler disables both Plone bundles (omnia-assistant and omnia-assistant-preact) by setting their enabled registry flag to False.
Frontend development
The assistant widget source lives in browser/resources/. Built artifacts are committed to browser/static/ and served via ++plone++imio.omnia.assistant/.
Rebuild after JS changes:
make build-js # npm ci + vite build + copy to static/ make clean-js # remove built artifacts
Tests covering the registry export and proxy enforcement live in src/imio/omnia/assistant/tests/ and should be kept in sync with any setting or frontend behavior changes.
The frontend stack uses Vite (library mode), Preact, @assistant-ui/react (chat runtime), Framer Motion (animations), Mousetrap (keyboard shortcuts), and Tailwind CSS v3.
Translations
This product has been translated into:
English
French
License
The project is licensed under the GPLv2.
Contributors
Antoine Duchêne, antoine.duchene@imio.be
Changelog
1.0a4 (2026-04-03)
Load imio.omnia.core ZCML. [aduchene]
1.0a3 (2026-04-03)
Re-release because ZCML files were lacking (2). [aduchene]
1.0a2 (2026-04-03)
Re-release because ZCML files were lacking. [aduchene]
1.0a1 (2026-04-03)
Initial release. [duchenean]
Added floating/fixed AI chat assistant widget built with Vite + Preact and @assistant-ui/react. [duchenean]
Added real-time SSE streaming of chat completions from the OpenAI-compatible Omnia gateway. [duchenean]
Added server-side API proxy (@@omnia-assistant-api) so upstream credentials are never exposed to the browser. [duchenean]
Added HMAC-signed bearer token authentication (2-hour expiration) for proxy requests, signed with the Plone site keyring. [duchenean]
Added automatic page content injection as conversation context, with configurable CSS selectors, HTML or plain-text mode, and character limit. [duchenean]
Added server-side system prompt (base_prompt) injection — no longer exposed to the frontend. [duchenean]
Added control panel tab (@@omnia-assistant-settings) in the shared Omnia settings UI: enable/disable, model selection, display mode (floating/fixed), dimensions, disclaimer, and conversation limits. [duchenean]
Added IOmniaAssistantAdapter extension point for context-specific availability, system prompt composition, and frontend config overrides. [duchenean]
Added dynamic model vocabulary fetched from the IOmniaOpenAIService. [duchenean]
Added max_messages_per_session enforced both client and server-side. [duchenean]
Added keyboard shortcut (Alt+I) to toggle the assistant panel. [duchenean]
Added i18n support (en, fr). [duchenean]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file imio_omnia_assistant-1.0a4.tar.gz.
File metadata
- Download URL: imio_omnia_assistant-1.0a4.tar.gz
- Upload date:
- Size: 701.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02117463d469d4b36bebecec79c36ac97a7d6ccd1eefb5df381d8634f50cde27
|
|
| MD5 |
3773e3ea4cc44a4661850aa31f7788e7
|
|
| BLAKE2b-256 |
63e8fa05086bdfc1dcf5c28735ce6aa880e8d9ca8b8ab725c0f0b030934864ce
|
File details
Details for the file imio_omnia_assistant-1.0a4-py3-none-any.whl.
File metadata
- Download URL: imio_omnia_assistant-1.0a4-py3-none-any.whl
- Upload date:
- Size: 724.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ca2733cb65e68fd1aaef76c199d2bf4cdd6cea09d79c6aceb5c845af0dfa900
|
|
| MD5 |
67a421786bddcaceb06baf4d9fb1a664
|
|
| BLAKE2b-256 |
8434b068b66326826b6fda5386c68f5954a825a1cce03cf68191e101e6d6a759
|