imio.omnia.assistant
A floating AI chat assistant for Plone 6, part of the Omnia suite by iMio.
This package adds a chat widget (a floating panel or a right sidebar) to every page of the Plone site. The assistant streams responses from an OpenAI-compatible API through a secure server-side proxy, and can read the current page when a question needs it. It relies on imio.omnia.core for API connectivity, authentication, and the shared Omnia control panel.
Features
Floating panel or sidebar — a panel opening from a round button in the bottom-right corner, or docked on the right and pushing the page. The visitor can switch between both from the panel header.
Real-time streaming — SSE-based chat completions streamed token by token.
Page reading — the model calls a read_page tool, run in the browser, that returns the page content (HTML or plain text, selected by a CSS selector).
Large-context handling — when the page content exceeds the configured limit, the model asks the visitor to quote the relevant passage: selecting text shows a « Demander à Omnia » button under it.
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, guarded by a Plone permission, an Origin check and Plone’s CSRF 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 read_page returns (default: 20000) |
max_messages_per_session |
Maximum number of user messages allowed in a single conversation (default: 0, unlimited) |
layout |
floating (round button + popover) or sidebar (docked right, 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
The default GenericSetup profile registers one Plone resource bundle, omnia-assistant: the self-contained UMD build of @imiobe/omnia-assistant-ui (React and styles bundled inside, rendered in a shadow root).
An OmniaAssistantConfigViewlet registered in plone.htmlhead sets window.omnia_assistant_settings from the Plone registry (model, selectors, layout, dimensions, etc.). The bundle reads it and mounts itself into a <div id="omnia-assistant-root"> it 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.
The widget sends no Authorization header. The caller must have the imio.omnia.core: Access Omnia OpenAI proxy permission, which imio.omnia.core grants to Authenticated users: the same-origin fetch() carries the session cookie. Requests whose Origin host differs from the portal’s are rejected.
Every request must also carry plone.protect’s CSRF token in an X-CSRF-TOKEN header, otherwise the proxy answers 403. The viewlet puts it in request_headers of window.omnia_assistant_settings, for anonymous visitors too, and the widget (2.9.0 or later) adds those headers to its chat and MCP requests.
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": "user", "content": "<user message>" }
],
"tools": [{ "type": "function", "function": { "name": "read_page" } }],
"stream": true
}
When the model calls read_page, the widget runs it and calls the model again with the result as a tool message.
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 proxy rejects (HTTP 400) any request whose payload contains more user messages than the configured limit; the widget shows the error in the reply. Assistant replies and tool results do not consume the limit. Starting a new conversation from the panel header (“Nouveau”) resets the counter.
Page reading
When include_page_content is True, the widget offers the model a read_page tool. It returns the DOM content matched by page_content_selector, as innerHTML or innerText (controlled by page_content_clean). The page is never sent up front, so:
the configured model must support tool calling (mistral-* and zai-glm-5-2 on the Omnia gateway do);
base_prompt should tell the model to call read_page before answering a question about the page, otherwise it answers without reading it.
If the content exceeds max_context_chars characters, read_page tells the model to ask the visitor to quote the relevant passage.
Uninstall
The uninstall profile removes the assistant settings and the omnia-assistant bundle from the registry.
Frontend development
The widget is developed in its own repository and published to npm as @imiobe/omnia-assistant-ui. browser/resources/package.json pins the version; the built file is committed to browser/static/ and served via ++plone++imio.omnia.assistant/.
After bumping the version:
make build-js # npm ci + copy the UMD bundle to static/ make clean-js # remove the built artifact
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), React, @assistant-ui/react (chat runtime), Mousetrap (keyboard shortcuts), and Tailwind CSS v4.
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.1 (2026-10-09)
Bump @imiobe/omnia-assistant-ui from 0.3.2 to 2.9.0 and replace the HMAC token by Plone’s CSRF token (X-CSRF-TOKEN header). [chris-adam]
Replace the mode setting by layout (floating / sidebar), migrated by upgrade step 1003. [chris-adam]
Require imio.omnia.core 1.3: its proxy checks the CSRF token the widget sends. [duchenean]
1.0 (2026-08-03)
OIA-241: Follow imio.omnia.core’s httpx -> httpx2 migration in test mocks; drop unused httpx dependency. [duchenean]
OIA-241: Bundle the UI from the published npm package @imiobe/omnia-assistant-ui (0.3.2) instead of a git submodule. [duchenean]
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]
Metadata
Release files for imio.omnia.assistant 1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| imio_omnia_assistant-1.1.tar.gz | 426.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| imio_omnia_assistant-1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 855.7 kB
Release files / imio_omnia_assistant-1.1.tar.gz
| Download URL | imio_omnia_assistant-1.1.tar.gz |
|---|---|
| Size | 426.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c28d9629d04680b8f27a530dbd885229f46989eeed4e3d8f026fc8b498a62acd
|
|
BLAKE2b-256 checksum How to use checksums |
b356e483a62d9ffb6306664d1f367a8dc2ee4466ff8dca61db44a715c5e50b91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / imio_omnia_assistant-1.1-py3-none-any.whl
| Download URL | imio_omnia_assistant-1.1-py3-none-any.whl |
|---|---|
| Size | 429.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6eaff804e00e7b5a3780d344c0b9780dc4f89383bcda634d75eab7aabff8813e
|
|
BLAKE2b-256 checksum How to use checksums |
2270b81d43d13e38823647c7e822f4e143338018eb8f10c6320a6fc6ccc68940
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|