Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

feat(ai-chat-companion): floating widget + composables + NcAppSidebar#197

Merged
rubenvdlinde merged 1 commit into
betafrom
feature/ai-chat-companion-widget
May 11, 2026
Merged

feat(ai-chat-companion): floating widget + composables + NcAppSidebar#197
rubenvdlinde merged 1 commit into
betafrom
feature/ai-chat-companion-widget

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

Implements the nextcloud-vue side of the ai-chat-companion 3-spec chain (hydra ADR-034).

Consuming apps get a Conduction-Cobalt hex FAB + context-aware chat panel auto-mounted via CnAppRoot — a single line in any app that already wraps in CnAppRoot. No install-time PHP dep on OpenRegister (runtime HTTP only, gracefully no-ops when OR is unreachable).

New components

src/components/CnAiCompanion/

  • CnAiFloatingButton.vueConduction-Cobalt (#4376fc) hex with white AI sparkles icon (Material Design Creation). Pointy-top point-up per the brand rule. Solid colour, no gradients. Hover #2e5ed9. Respects prefers-reduced-motion. Position prop accepts four corners.
  • CnAiCompanion.vue — top-level mount, OR health probe at startup, no-op fallback (renders nothing if OR unreachable, no console warnings above info).
  • CnAiChatPanel.vue — built on NcAppSidebar (proper NC theming + a11y + slide animation) with NcActionButton secondary actions for Start-new-chat and History. Slides in from the right edge.
  • CnAiMessageList.vue — user / assistant / system roles, NcRichText for assistant markdown, plain text for user, tool-call / tool-result inline with collapse-to-summary, isError highlighting.
  • CnAiInput.vue — multi-line textarea + send, Enter to send, Shift+Enter for newline.

src/dialogs/ (per ADR-004 file-isolation rule)

  • CnAiHistoryDialog.vueNcDialog-based history browser, fetches GET /api/chat/conversations?limit=50, empty / loading / error states.

New composables

  • useAiContext() — injects the reactive cnAiContext.
  • useAiChatStream() — owns the SSE lifecycle via @microsoft/fetch-event-source (handles POST bodies, abort signals, auto-reconnect, frame parsing). Falls back to POST /api/chat/send on 404 / 501 with synthetic final event so message-rendering code has one path.

Modified

  • CnAppRoot.vue — provides reactive cnAiContext; auto-mounts <CnAiCompanion /> as the last NcContent child so the embedded NcAppSidebar slides from the right.
  • CnIndexPage / CnDetailPage / CnDashboardPage — push pageKind, registerSlug, schemaSlug, objectUuid into cnAiContext on created() + watch + beforeDestroy.
  • l10n/en.json + l10n/nl.json — 13 keys + Dutch translations.
  • src/index.js + src/types/index.d.ts — exports.

Demo

examples/ai-chat-companion-demo/ ships a standalone harness with mocked OR backend (health, /api/chat/stream, /api/chat/conversations).

Browser-verified

Mounted via file: link in decidesk against the real OR backend: hex FAB renders bottom-right (verified cn-ai-floating-button__hex element + rgb(67, 118, 252) background + creation-icon class). NcAppSidebar slides in from the right with title, subtitle, sparkles empty state, and the message input.

Dependencies

Depends on the hydra ai-chat-companion spec landing first (defines the contracts) and the sibling openregister/ai-chat-companion-orchestrator for the real SSE backend (widget no-ops gracefully without it).

Test plan

  • openspec validate ai-chat-companion-widget --strict passes
  • FAB renders with Conduction Cobalt hex + white sparkles
  • NcAppSidebar slides in from the right
  • OR health probe + no-op fallback works
  • npm run lint clean
  • npm test green
  • npm run build ESM + CJS + extracted CSS no new warnings
  • End-to-end browser test against the live OR change once it ships

Implements the nextcloud-vue side of the ai-chat-companion 3-spec
chain (hydra ADR-034). Adds a single line auto-mount via CnAppRoot —
consuming apps get a Conduction-Cobalt hex FAB and a context-aware
chat panel for free.

NEW components (src/components/CnAiCompanion/):
- CnAiCompanion.vue — top-level mount, OR health probe, no-op fallback
- CnAiFloatingButton.vue — Conduction-Cobalt (#4376fc) hex with white
  AI sparkles icon (Material Design Creation), pointy-top point-up per
  brand rule. Solid colour, no gradients.
- CnAiChatPanel.vue — built on NcAppSidebar (proper NC theming + a11y
  + slide animation) with NcActionButton secondary actions for Start
  new chat and History.
- CnAiMessageList.vue, CnAiInput.vue — message rendering and input.

NEW dialog (src/dialogs/, per ADR-004 file-isolation rule):
- CnAiHistoryDialog.vue — NcDialog overlay listing past conversations.

NEW composables (src/composables/):
- useAiContext() — injects the reactive cnAiContext provided by
  CnAppRoot.
- useAiChatStream() — owns the SSE lifecycle via @microsoft/fetch-
  event-source (handles POST bodies, abort signals, automatic
  reconnect, frame parsing). Falls back to POST /api/chat/send on
  404/501 with synthetic final event.

MODIFIED:
- CnAppRoot.vue — provides reactive cnAiContext; auto-mounts
  <CnAiCompanion /> as the last NcContent child so the embedded
  NcAppSidebar slides in from the right.
- CnIndexPage / CnDetailPage / CnDashboardPage — push pageKind,
  registerSlug, schemaSlug, objectUuid into cnAiContext on created()
  + watch + beforeDestroy.
- l10n/en.json + l10n/nl.json — 13 new keys + Dutch translations.
- src/index.js + src/types/index.d.ts — barrel exports.

Demo: examples/ai-chat-companion-demo/ — standalone harness with
mocked OR backend (health, /api/chat/stream, /api/chat/conversations).

Tests: Vitest mount + behaviour tests for every new component and
composable. tests/__mocks__/fetch-event-source.js mocks the SSE
library so unit tests run without a real OR backend.

Depends on the hydra ai-chat-companion spec.
@rubenvdlinde rubenvdlinde merged commit efefdfc into beta May 11, 2026
1 of 3 checks passed
@rubenvdlinde rubenvdlinde deleted the feature/ai-chat-companion-widget branch May 11, 2026 11:25
rubenvdlinde added a commit that referenced this pull request May 11, 2026
…t spec

The mount-level in-memory manifest tests previously asserted axios.get was
never called. After the AI Chat Companion (#197) was merged onto beta, the
CnAiCompanion child issues an unrelated GET /apps/openregister/api/chat/health
during mount. Filter axios.get calls to /api/manifest endpoints so the
REQ-IMM-002 / REQ-IMM-004 guarantees stay meaningful without colliding with
the new health probe.
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.0.0-beta.31 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant