@imiobe/omnia-assistant-ui
v1.0.1
Published
AI chat assistant widget for iMio's Omnia API
Downloads
25
Readme
@imiobe/omnia-assistant-ui
AI chat assistant widget that integrates iMio's Omnia API for conversational AI interactions. Features a draggable/resizable chat panel, streaming responses via SSE, page content injection, and keyboard shortcuts.
Installation
npm install @imiobe/omnia-assistant-ui preactPreact (>=10) is a peer dependency and must be installed separately.
Quick start
import { mount } from '@imiobe/omnia-assistant-ui';
import '@imiobe/omnia-assistant-ui/dist/omnia-assistant-ui.css';
// Configure via window global
window.omnia_assistant_settings = {
api_service_url: 'https://example.be/api',
model: 'your-model-name',
base_prompt: 'You are a helpful assistant.',
};
mount('app'); // mount into element with id="app"Or pass configuration directly:
import { mount } from '@imiobe/omnia-assistant-ui';
import '@imiobe/omnia-assistant-ui/dist/omnia-assistant-ui.css';
mount('app', {
apiServiceUrl: 'https://example.be/api',
model: 'your-model-name',
basePrompt: 'You are a helpful assistant.',
mode: 'floating',
initialWidth: 380,
initialHeight: 520,
});Or let the widget mount itself by setting window.omnia_assistant_settings before the bundle loads (useful for server-side integrations):
<script>
window.omnia_assistant_settings = {
api_service_url: 'https://example.be/api',
model: 'your-model-name',
base_prompt: 'You are a helpful assistant.',
};
</script>
<!-- Bundle then auto-mounts into a <div id="omnia-assistant-root"> it creates -->
<script src="omnia-assistant-ui.umd.cjs"></script>Or import the Preact component directly:
import { AIAssistant } from '@imiobe/omnia-assistant-ui';
import '@imiobe/omnia-assistant-ui/dist/omnia-assistant-ui.css';
function App() {
return <AIAssistant config={{ apiServiceUrl: '...', model: '...' }} />;
}Configuration
Settings can be provided via the config prop / mount() argument (camelCase) or via window.omnia_assistant_settings (snake_case). The config prop takes precedence.
API settings
| config prop | window.omnia_assistant_settings | Default | Description |
|---|---|---|---|
| apiServiceUrl | api_service_url | — | Required. Base URL of the OpenAI-compatible chat API. |
| model | model | — | Required. Model name sent in the completions request. |
| basePrompt | base_prompt | — | System prompt prepended to every conversation. |
The widget sends no Authorization header. Authentication is always a
Keycloak JWT (sso-apps realm) minted and injected server-side by the
gateway/proxy apiServiceUrl points at — never in the browser. This also
covers the MCP tool-server calls, which go through the same gateway.
For the Plone integration in imio.omnia.assistant, base_prompt is
typically injected server-side by @@omnia-assistant-api and is therefore not
included in window.omnia_assistant_settings. The frontend option remains
available for direct JS consumers and other integrations.
Page context settings
| config prop | window.omnia_assistant_settings | Default | Description |
|---|---|---|---|
| includePageContent | include_page_content | true | Inject the host page content as a system message. |
| pageContentSelector | page_content_selector | '#content' | CSS selector(s) to extract page content from. Can be a string or array of strings. |
| pageContentClean | page_content_clean | false | Use innerText instead of innerHTML for cleaner extraction. |
| maxContextChars | — | 20000 | Max characters for page context. When exceeded, the user can select text on the page to provide a smaller context. |
UI settings
| config prop | Default | Description |
|---|---|---|
| mode | 'floating' | 'floating' for a draggable/resizable panel, 'fixed' for a stationary panel. |
| initialWidth | 380 | Initial panel width in pixels. |
| initialHeight | 520 | Initial panel height in pixels. |
| disclaimer | French AI disclaimer | Disclaimer text shown at the bottom of the panel. Set to null to hide. |
API endpoint
The API endpoint must serve OpenAI-compatible SSE streaming responses at {apiServiceUrl}/chat/completions.
Request:
{
"model": "model-name",
"messages": [
{ "role": "system", "content": "System prompt..." },
{ "role": "system", "content": "Page content..." },
{ "role": "user", "content": "User message" }
],
"stream": true
}Response: SSE stream in OpenAI chat completions format:
data: {"choices":[{"delta":{"content":"Hello "}}]}
data: {"choices":[{"delta":{"content":"world."}}]}
data: [DONE]Keyboard shortcuts
| Shortcut | Action |
|----------|--------|
| Alt+I | Toggle the chat panel open/closed |
Development
make install # npm install
make dev # Storybook on port 6006
make build # Build to dist/
make lint # ESLintCopy .env.example to .env for the Storybook live API stories. When
VITE_OMNIA_BASE_URL is a full URL, Storybook proxies requests through the dev
server (/omnia-proxy) to avoid CORS.
JWT-gated LLM gateway (apims-omnia-llm-gateway, staging sso-apps). The dev
server mints a Keycloak JWT server-side, caches it, refreshes it on expiry,
and injects it as the Bearer on every proxied request. Secrets are read from
non-VITE_ variables so Vite never inlines them into the browser bundle.
VITE_OMNIA_BASE_URL=https://<apims-staging-host>/imio/omnia/llm/gateway/v1
VITE_OMNIA_MODEL=mistral-small-2603
OMNIA_TOKEN_URL=https://keycloak-apps.cloud.imio-test.be/realms/sso-apps/protocol/openid-connect/token
OMNIA_CLIENT_ID=imio-apims-omnia-llm-gateway
OMNIA_CLIENT_SECRET=… # see Passbolt link below
# OMNIA_USERNAME=… # set BOTH to switch to the password grant
# OMNIA_PASSWORD=… # (user token with real groups)Two grants, selected by whether OMNIA_USERNAME/OMNIA_PASSWORD are set:
| Grant | Needs | Token represents | Reachable models |
|-------|-------|------------------|------------------|
| client_credentials (default) | OMNIA_CLIENT_SECRET | the client's service account (group access_imio-apims-omnia-llm-gateway) | mistral-small-2603, mistral-large-2512 |
| password | OMNIA_USERNAME + OMNIA_PASSWORD (+ secret) | a real user with their groups | iA.* models (Mistral Small, Claude Sonnet 4.5, …) per the user's groups |
Credentials (iMio Passbolt, pwmg.imio-app.be):
- Client secret (
imio-apims-omnia-llm-gateway): https://pwmg.imio-app.be/app/passwords/view/8f8e5a85-9c60-4f90-964f-33c318dad7eb - User (for the password grant): https://pwmg.imio-app.be/app/passwords/view/6dca1f35-14ea-4718-9b84-d2a1e5a0e05a
Leave OMNIA_TOKEN_URL empty to disable minting (only the mock-API stories work then).
A 403 from the gateway means the token is valid but the requested model isn't
allowed for its groups — pick a model from the table above.
Available commands
| Command | Description |
|---------|-------------|
| make install | Install dependencies |
| make dev | Start Storybook dev server (port 6006) |
| make build | Build library to dist/ (ES + UMD + CSS) |
| make build-storybook | Build static Storybook site |
| make lint | Run ESLint |
| make lint-fix | Run ESLint with auto-fix |
| make clean | Remove dist/ and storybook-static/ |
| make publish | Build and publish to npm |
Build output
The library builds to dist/ in two formats:
omnia-assistant-ui.js-- ES moduleomnia-assistant-ui.umd.cjs-- UMD (global:OmniaAssistantUI)omnia-assistant-ui.css-- Styles (Tailwind + @assistant-ui + theme)
Preact is not bundled -- it must be provided by the host application.
Stack
- Preact for UI (with
preact/compataliasing for React libraries) - @assistant-ui/react for chat thread, composer, and markdown rendering
- Vite for builds (library mode)
- Tailwind CSS v3 with @assistant-ui plugins
- Framer Motion for panel animations (drag, resize, open/close)
- Mousetrap for keyboard shortcuts (Alt+I)
- Storybook 10 for component development
License
Proprietary -- (c) iMio
