Skip to content

Add frontend client for musing-ai-service - #94

Merged
danibsheehan merged 1 commit into
mainfrom
feat/ai-notes-frontend-client
Aug 30, 2026
Merged

Add frontend client for musing-ai-service#94
danibsheehan merged 1 commit into
mainfrom
feat/ai-notes-frontend-client

Conversation

@danibsheehan

Copy link
Copy Markdown
Owner

Summary

Wires musing's frontend up to the now-live `musing-ai-service` backend: search, summarize, related pages, background indexing, and a usage indicator.

  • `src/lib/aiClient.ts`: `isAiServiceConfigured()` (mirrors `isSupabaseConfigured()`'s pattern, plus requires Supabase configured since every endpoint needs a session JWT), an `AiServiceError` class, typed wrappers for all five backend endpoints. Cross-origin, per the earlier architecture correction (no same-origin proxy — see Add CORS to musing-ai-service; drop the same-origin proxy plan #93).
  • `src/lib/blockPlainText.ts`: strips HTML from block content before anything goes to the AI service — mirrors `blockEditorCommands.ts`'s `isBlockHtmlVisuallyEmpty()` DOM approach.
  • `src/hooks/usePageIndexing.ts`: debounces `embed-page` ~2s after a page's blocks stop changing (document pages only), mirroring `WorkspaceContext`'s 800ms remote-save debounce but longer since this costs money. Failures are logged, never surfaced.
  • UI wiring, per the earlier placement discussion:
    • `PageChrome.tsx`: a Summarize button as a sibling to Export, not a third item inside it — Export's whole model is "click, download, no persistent UI," Summarize needs to show text, so it gets its own busy-state + dismissible result panel.
    • `RelatedPagesSection.tsx`: collapsed-by-default disclosure under the page header.
    • `SidebarSearch.tsx`: debounced (300ms) search input above the page tree, deduped to one result per page.
    • `AppLayout.tsx`: a compact `AiUsageBadge` pill next to the existing `RemoteSyncBadge`.
  • `VITE_AI_SERVICE_URL` wired into `.env.example`, `vite-env.d.ts`, and `deploy-pages.yml`'s build env (mirrors the `VITE_SUPABASE_*` pattern exactly).

Found and fixed via `/code-review` (6 parallel finders): the three new components referenced CSS classes that were never defined anywhere in the repo (confirmed by grep) — the search dropdown would have rendered as broken inline content instead of an overlay. Added the missing `App.css` rules. Also fixed `RelatedPagesSection` swallowing fetch errors into the same empty state as "no related pages" — now shows a real error, matching how `PageChrome` already handles the same failure class for summarize/export.

Documented, not fixed: `usePageIndexing`'s debounce can reset without a real edit when `WorkspaceContext` replaces the whole snapshot (cross-tab sync, or the initial remote-fetch race) — delays indexing, never skips or corrupts it; not worth the complexity of a content-hash key for a delay-only edge case.

Coverage: thresholds hold without new component-level tests, consistent with this codebase's existing convention (`PageChrome`/`PageView`/`Sidebar`/`AppLayout` have none; only lib/hook logic is unit-tested here). `aiClient.ts` (82%) and `usePageIndexing.ts` (93%) — the actual new logic — are well covered.

Cannot verify in a browser — no browser automation tool is available in this environment. Verified instead: typecheck, lint, full test suite, production build, and that every referenced CSS class now resolves (grep-checked). A real manual click-through is still needed before merging.

Test plan

  • `npx tsc -b --noEmit`, `npm run lint`, `npm run format:check` — all pass
  • `npx vitest run` — 161/161 passing; coverage above thresholds
  • `npm run build` — succeeds
  • Manual, needs a real browser: with `VITE_AI_SERVICE_URL` unset, confirm zero AI UI renders and no console errors; with it set, confirm Summarize/Related/Search/usage badge actually work against the live service

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

PR guide

Auto-generated from changed paths. Fill in Summary and How to verify in the PR description above.

Touches: app shell / routes, tests, CI / GitHub, other

Diff: 15 files changed, 908 insertions(+)

Suggested verify

  • npm run lint
  • npm run format:check
  • npm run test:run or targeted Vitest files for the changed area
  • npm run build
  • Review workflow syntax and required permissions in GitHub Actions

Checklist (applies to this PR)

  • No unintended secrets or local-only config committed
  • Routes work with import.meta.env.BASE_URL for GitHub Pages subpath hosting
  • Workflow permissions are scoped to the PR-guide behavior

Reviewer focus

  • Routing, layout state, and Pages BASE_URL behavior
  • Workflow event triggers, token permissions, and label/comment behavior on same-repo vs fork PRs
  • Test assertions cover the behavior under review rather than only implementation details

Commits

  • c91963b Add frontend client for musing-ai-service

Files by area

Area Files
app shell / routes 6
tests 2
CI / GitHub 1
other 6

CI

Primary check: CI runs lint, Prettier format check, Vitest coverage, and build for every PR. Coverage tables are posted separately.


Template: pull_request_template.md

@github-actions github-actions Bot added area: app App shell, layout, or routing area: tests Test files or test tooling area: ci GitHub Actions or PR automation labels Aug 30, 2026
@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

Unit tests (Vitest)

File Coverage Lines Branches
All files 55% 62% 48%
src/components/DatabaseEmbedNodeView.tsx 0% 0% 0%
src/components/DatabaseTableView.tsx 0% 0% 0%
src/components/SlashMenu.tsx 72% 85% 60%
src/context/WorkspaceContext.tsx 25% 35% 14%
src/extensions/blockIdOnBlocks.ts 75% 100% 50%
src/extensions/musingDatabaseEmbed.ts 70% 90% 50%
src/extensions/singleTopLevelBlock.ts 80% 100% 60%
src/hooks/usePageIndexing.ts 95% 90% 100%
src/lib/aiClient.ts 81% 86% 76%
src/lib/blockEditorCommands.ts 42% 50% 35%
src/lib/blockPlainText.ts 55% 60% 50%
src/lib/editorBlockText.ts 13% 13% 14%
src/lib/emojiSuggestionItems.ts 93% 100% 87%
src/lib/htmlToDocx.ts 24% 31% 18%
src/lib/pageToExportHtml.ts 97% 100% 94%
src/lib/resolveWikiPage.ts 91% 100% 83%
src/lib/slashMenuOptions.ts 57% 57% 0%
src/lib/themePreference.ts 32% 25% 40%
src/lib/workspaceStorage.ts 80% 81% 80%
src/lib/pageDocument/blockGutterOps.ts 92% 100% 84%
src/lib/pageDocument/blockIdAtSelection.ts 83% 100% 66%
src/lib/pageDocument/lastBlockNeedsBelowHit.ts 91% 100% 83%
src/lib/pageDocument/serializeDocToBlocks.ts 58% 69% 47%
src/lib/pageDocument/slashMenuDeleteRange.ts 82% 95% 70%
src/lib/pageDocument/tryDeleteEmptyTopLevelBlock.ts 87% 94% 81%

Minimum allowed coverage is 0%

Generated by 🐒 cobertura-action against c91963b

- src/lib/aiClient.ts: isAiServiceConfigured() (mirrors
  isSupabaseConfigured()'s pattern, plus requires Supabase configured
  since every endpoint needs a session JWT), an AiServiceError class,
  and typed wrappers for all five backend endpoints. Cross-origin per
  the earlier architecture correction (no same-origin proxy).
- src/lib/blockPlainText.ts: strips HTML from block content before
  sending anything to the AI service or Anthropic/Voyage — mirrors
  blockEditorCommands.ts's isBlockHtmlVisuallyEmpty() DOM approach.
- src/hooks/usePageIndexing.ts: debounces embed-page ~2s after a
  page's blocks stop changing (document pages only), mirroring
  WorkspaceContext's 800ms remote-save debounce but longer, since this
  costs money. Failures are logged, never surfaced — a background
  enhancement must never disrupt writing.
- UI wiring, per the earlier placement decisions:
  - PageChrome.tsx: a "Summarize" button as a sibling to Export (not
    a third item inside it — Export's whole interaction model is
    "click, download, no persistent UI"; Summarize needs to show
    text, so it gets its own busy-state + dismissible result panel).
  - RelatedPagesSection.tsx: collapsed-by-default <details> under the
    page header, only for document pages when configured.
  - SidebarSearch.tsx: debounced (300ms) search input above the page
    tree, results deduped to one entry per page (highest-similarity
    block), each with a snippet.
  - AppLayout.tsx: a compact AiUsageBadge pill next to the existing
    RemoteSyncBadge, showing the higher of the two providers'
    token-usage percentage with a full breakdown in the tooltip.
- VITE_AI_SERVICE_URL: added to .env.example, vite-env.d.ts, and
  deploy-pages.yml's build env (mirrors the VITE_SUPABASE_* pattern
  exactly). Set directly in .env.local for local dev against the live
  Cloud Run service.

Fixed via /code-review (6 parallel finders): the three new components
referenced CSS classes that were never defined anywhere (confirmed by
grep) — the search dropdown would have rendered as broken inline
content instead of an overlay. Added the missing App.css rules for
sidebar-search-*, related-pages-*, and ai-usage-badge. Also fixed
RelatedPagesSection swallowing fetch errors into the same empty state
as "no related pages" — now shows a real error, matching how
PageChrome already surfaces the same class of failure for
summarize/export.

Documented, not fixed: usePageIndexing's debounce can reset without a
real edit when WorkspaceContext replaces the whole snapshot (cross-tab
sync, or the initial remote-fetch race) — delays indexing, never
skips or corrupts it, so not worth the complexity of keying off a
content hash instead of array identity for a delay-only edge case.

Coverage thresholds hold without new component-level tests (existing
convention: PageChrome/PageView/Sidebar/AppLayout have none; only
lib/hook logic is unit-tested here) — aiClient.ts and
usePageIndexing.ts, the actual new logic, are covered at 82%/93%.

Cannot verify in a browser: no browser automation tool is available
in this environment. Verified instead: typecheck, lint, full test
suite (161 passing), production build, and that every referenced CSS
class now resolves. A real manual click-through is still needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@danibsheehan
danibsheehan force-pushed the feat/ai-notes-frontend-client branch from 7281470 to c91963b Compare August 30, 2026 22:07
@danibsheehan
danibsheehan merged commit 545289e into main Aug 30, 2026
8 checks passed
@danibsheehan
danibsheehan deleted the feat/ai-notes-frontend-client branch August 30, 2026 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: app App shell, layout, or routing area: ci GitHub Actions or PR automation area: tests Test files or test tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant