Skip to main content

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 shortcutAlt+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:

  1. Sets window.omnia_assistant_settings with configuration from the Plone registry (model, selectors, dimensions, etc.).

  2. Waits for the OmniaAssistantUI global to be available (exported by the bundle).

  3. 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

Authors

License

The project is licensed under the GPLv2.

Contributors

Changelog

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]

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

imio_omnia_assistant-1.0.tar.gz (272.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

imio_omnia_assistant-1.0-py3-none-any.whl (275.1 kB view details)

Uploaded Python 3

File details

Details for the file imio_omnia_assistant-1.0.tar.gz.

File metadata

  • Download URL: imio_omnia_assistant-1.0.tar.gz
  • Upload date:
  • Size: 272.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.12

File hashes

Hashes for imio_omnia_assistant-1.0.tar.gz
Algorithm Hash digest
SHA256 08bfa1ffa7d1c5acd1dffd4d4ee050ec32fa5f6e7bd269e1d4b7f7e2f2670db8
MD5 20ab290cf33aded9a6ca01a2e2d2aa58
BLAKE2b-256 9d295a8cd7f52a7410acfe6f28cbce33cb7b5bcd2704f8d1d23428927cb50304

See more details on using hashes here.

File details

Details for the file imio_omnia_assistant-1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for imio_omnia_assistant-1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5013f6954e08de076fff41a180410c7407e7a1b3bfd124a74dabbbc0a72aa3f6
MD5 07ea5ebe9bf94eca2914cecd2755d1c7
BLAKE2b-256 0c256c0b1a396193cca0eca8955872bddedef44d0e3750575cc776fbfb71d2e0

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page