Skip to content

feat(ai): assistant answers from the OpenAEC AI server - #324

Open
mojtabakarimi wants to merge 1 commit into
mainfrom
feat/ai-assistant-openaec-server
Open

feat(ai): assistant answers from the OpenAEC AI server#324
mojtabakarimi wants to merge 1 commit into
mainfrom
feat/ai-assistant-openaec-server

Conversation

@mojtabakarimi

Copy link
Copy Markdown
Collaborator

Connects the assistant to the user's own AI server, restores the sign-in UI and the AI ribbon tab, and moves the login code into a shared crate.

Verified end to end against production: a real sign-in, then a summary of a 7-page drawing set, with authorize → vLLM → settle confirmed in the sidecar logs.

Assistant

The panel gains a third provider ahead of the MCP relay: POST /v1/chat on the AI sidecar, billed against the user's credits. js/services/ai-client.js speaks the wire contract; document-text.js extracts page text via the existing extract_page_text command, capped at 40k characters.

This fixes a real bug. "Vat samen" only ever sent the file name — it relied on an MCP brain reading the document itself, so against the server there was nothing to summarise.

Other changes here:

  • Answers follow the app's language (response_language), so a Dutch UI gets a Dutch answer even from an English document.
  • Every visible string now comes from i18n. They were hardcoded Dutch — including the skill chips, which lived as literals in assistant-skills.js and ignored the language setting entirely. That module now holds only what is language-independent: id, icon, routing.
  • The Claude API key field is gone. The server handles this now, metered against credits, and the key box invited pasting a personal Anthropic key into a text field. app_ai_complete follows the same path instead of calling api.anthropic.com.
  • Failure states are explicit. Signed out shows a sign-in prompt in place of the chips and input; out-of-credits, rate-limited, offline, timed-out and service-down each get their own message. Previously a signed-out click queued to the MCP relay and sat on a 600-second timeout showing "Thinking…".

AI ribbon tab

Restored after c0ab9e7f removed it, wired to the same path as the panel's chips rather than carrying its own copy of the AI logic.

Not restored: the old tab's hover-translate group. It depended on hover-translate-tool.js, deleted in the same commit, and needs its own tool plus dispatcher wiring.

Sign-in

The account widget, store and styling are back after e650d832 parked them. Recovered from history and brought forward, with three defects fixed on the way:

  • a dead i18n fallback that would have displayed a raw key on screen
  • a leaking click listener
  • a hardcoded localhost portal URL that pointed nowhere in production — now taken from config

accounts.rs moves out to openaec-accounts-client (pinned v0.1.0) so the other Impertio desktop apps share one implementation instead of copying it. Nothing app-specific remains in the crate — keyring namespace, config env var, app name and default URLs are passed via init().

Two fixes were needed to make the server reachable at all:

  • accounts_fetch hardcodes the Accounts host, so /v1/chat went to the wrong server. ai_fetch targets the sidecar.
  • The HTTP client had no timeout, so a server that accepted a connection and went quiet hung the caller forever.

Notes for the reviewer

  • New i18n keys are en and nl only; the other 37 locales fall back to English until translated.
  • The app only reaches production when launched with OPENAEC_ACCOUNTS_CONFIG pointing at a config file. The compiled defaults still target the local dev issuer, so shipping a build will want those changed.
  • Deliberately excluded from this branch: package-lock.json churn, the locally rebuilt pdfium-worker binary, and an unrelated untracked plan document.

Connects the assistant to the user's own AI server, restores the sign-in
UI and the AI ribbon tab, and moves the login code into a shared crate.

Assistant
---------
The panel gains a third provider ahead of the MCP relay: POST /v1/chat on
the AI sidecar, billed against the user's credits. Two new modules do the
work -- js/services/ai-client.js speaks the wire contract, and
document-text.js extracts the page text via the existing extract_page_text
command, capped at 40k characters.

This also fixes a real bug: "Vat samen" only ever sent the FILE NAME. It
relied on an MCP brain reading the document itself, so with the server
there was nothing to summarise.

Answers are requested in the app's language (response_language), so a
Dutch UI gets a Dutch answer even from an English document.

Every visible string now comes from i18n. They were hardcoded Dutch --
including the skill chips, which lived as literals in assistant-skills.js
and so ignored the language setting entirely. The skills module now holds
only what is language-independent: id, icon, routing.

The Claude API key field is gone. The server handles this now, metered
against the user's credits, and the key box invited pasting a personal
Anthropic key into a text field. app_ai_complete follows the same path
instead of calling api.anthropic.com directly.

Failure states are explicit rather than a spinner: signed out shows a
sign-in prompt in place of the chips and input, and out-of-credits,
rate-limited, offline, timed-out and service-down each get their own
message. Previously a signed-out click queued to the MCP relay and sat on
a 600-second timeout showing "Thinking...".

AI ribbon tab
-------------
Restored after c0ab9e7 removed it, wired to the same path as the panel's
chips rather than carrying its own copy of the AI logic. The old tab's
hover-translate group is NOT restored: it depended on
hover-translate-tool.js, deleted in the same commit, and needs its own
tool plus dispatcher wiring.

Sign-in
-------
The account widget, store and styling are back after e650d83 parked them.
Recovered from history and brought forward, with three defects fixed on
the way: a dead i18n fallback that would have displayed a raw key, a
leaking click listener, and a hardcoded localhost portal URL that pointed
nowhere in production -- it now comes from config.

accounts.rs moves out to openaec-accounts-client, so the other Impertio
desktop apps share one implementation instead of copying it. Nothing
app-specific remains in the crate: keyring namespace, config env var, app
name and default URLs are passed via init().

Two fixes were needed to make the server reachable at all. accounts_fetch
hardcodes the Accounts host, so /v1/chat went to the wrong server; ai_fetch
targets the sidecar. And the HTTP client had no timeout, so a server that
accepted a connection and went quiet hung the caller forever.

Verified end to end against production: a real sign-in, then a summary of
a 7-page drawing set, with authorize -> vLLM -> settle confirmed in the
sidecar logs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant