Skip to content

feat(ui): add floating help chat widget powered by Docs Q&A (#391) - #392

Merged
vybe merged 1 commit into
mainfrom
feature/391-help-chat-widget
Apr 18, 2026
Merged

feat(ui): add floating help chat widget powered by Docs Q&A (#391)#392
vybe merged 1 commit into
mainfrom
feature/391-help-chat-widget

Conversation

@vybe

@vybe vybe commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add floating help chat button in bottom-right corner of Trinity UI
  • Chat panel connects to existing ask-trinity Cloud Function (Vertex AI Search)
  • Multi-turn conversations with localStorage session persistence
  • Markdown rendering, loading states, error handling with retry

Changes

  • src/frontend/src/components/HelpChatWidget.vue — New floating widget component
  • src/frontend/src/App.vue — Mount widget for authenticated users
  • docs/memory/feature-flows/trinity-docs-qa.md — Document the UI integration

Test Plan

  • Widget button appears on authenticated pages only
  • Panel opens/closes with button click and Escape key
  • Messages sent to Cloud Function and responses rendered with markdown
  • Session persists across page navigations (localStorage)
  • New conversation button clears history and session
  • Error handling shows retry button

Closes #391

🤖 Generated with Claude Code

Add a floating help chat button in the bottom-right corner that opens
an expandable chat panel. Users can ask questions about Trinity and
get instant answers from the Vertex AI Search-powered documentation.

Features:
- Floating button (authenticated pages only)
- Multi-turn conversations with session persistence
- Markdown rendering with DOMPurify sanitization
- Loading indicator and error handling with retry
- Keyboard navigation and ARIA accessibility
- New conversation button to reset session

Closes #391

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vybe
vybe force-pushed the feature/391-help-chat-widget branch from b08b540 to 431e012 Compare April 18, 2026 12:35
@vybe
vybe merged commit ef1148a into main Apr 18, 2026
dolho added a commit that referenced this pull request Aug 28, 2026
…ee latent desyncs (ent#451)

Blocker 1 was real and I had not seen it. `resolveAgentQuery` passed `forceNew`
to `resolveAgentLanding` and set `pendingSession = null`, but never raised
`startingNewChat` — so `/workspace?agent=X&new=1` rendered an empty conversation
and then sent `new_thread: false`, resuming the thread the user asked to leave.
The reported bug, intact on the documented `?new=1` contract, in the PR that
exists to fix it.

The cause is the one this PR is about, one level up: `route.query.new` was read
in two places for two different decisions — WHICH THREAD to land on and WHAT THE
FIRST SEND ASKS FOR — and only the first honoured it. Now read ONCE into a local
that feeds both, so they cannot drift again. AND-ed with the landing result, so
a `?new=1` that still resolved a thread never claims a fresh start.

Blocker 2: a frontend test, which the change genuinely had none of — the
`1497 passed` in the body was the pre-existing suite, as the review says.
`workspaceNewChat.spec.js` (9 tests) covers the deep link, the watcher branch
ORDER, the first-paint guard, both send conjunctions, and the settle-everywhere
rule, using the two established patterns (pure function + source assertion in
the `portalLeaveSpecificRoute.spec.js` shape) since vitest runs
`environment: 'node'` with no mount harness. Mutation-checked, and M1 is the
reviewer's own blocker: reverting it turns the suite red.

Blocker 3: `test_history_without_a_session_is_unchanged` cited "the spec in
tests/unit/... frontend suite" — a dangling reference asserting coverage that
did not exist. It now names the real file.

Comments addressed:

* Three more sites nulled `pendingSession` without settling the intent — the
  deep-link watcher (the commonest way in), `openRoom`, `openAgentPage`, plus
  the unreachable-agent branch. Latent because both consumers AND on "no session
  yet", but a flag that is only correct because of a second variable is one
  refactor from being wrong, and the declaration claims it is cleared the moment
  a real thread exists. Now true.
* `test_both_turn_entry_points_forward_it` was `getsource` + a substring, so a
  comment or a misspelled kwarg satisfied it. It now BINDS the keyword against
  each service signature and asserts the routes forward `body.new_thread`
  through a comment-stripped source — verified by mutation.
* `workspace-absorbs-session.md` updated at both seams the change touches
  (`resolveAgentLanding`'s landing rule and `_resolve_session_id`'s three
  states), and `architecture.md`'s Workspace section documents the new public
  `new_thread` field on the ent#83 headless surface.
* Gating stated rather than inferred: "OSS-core by decision (ent#451)", matching
  the ent#326/#384/#392 convention.

ONE CORRECTION, offered with evidence rather than silently applied. The review
says "`test_ent457_portal_turn_kwargs.py` doesn't exist on `dev`, #2427
introduces it". It does exist on `dev` — added by d6a4bc1 (ent#457) — and #2427
modifies it. `git cat-file -e origin/dev:tests/unit/test_ent457_portal_turn_kwargs.py`
succeeds, and `backend-unit-test` is failing on `dev` independently of any PR.
So the body's "fails on dev today" stands. Everything else in the review is
accepted as written.

Verification: frontend 1497 -> 1506 (+9). Backend 392 passed on the portal
selection, the same 2 pre-existing dev failures unchanged.

Related to ent#451

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

Add floating help chat widget powered by Docs Q&A

1 participant