Skip to content

feat(wave3): missing actions + error visibility#14

Merged
vikranthreddimasu merged 1 commit into
mainfrom
feat/wave3-missing-actions
Apr 18, 2026
Merged

feat(wave3): missing actions + error visibility#14
vikranthreddimasu merged 1 commit into
mainfrom
feat/wave3-missing-actions

Conversation

@vikranthreddimasu

Copy link
Copy Markdown
Owner

Context

Wave 3 of 5 from PLAN.md. Wave 1 (#12) stopped the bleeding; Wave 2 (#13) resurrected the citation layer. This one closes table-stakes gaps: rename, delete-document, empty-notebook creation, error persistence, and Ollama health monitoring.

Actions that didn't exist

  • Rename notebook. Backend `PATCH /notebooks/{id}` + `notebook_store.rename_notebook`. Frontend: context-menu "Rename" → inline edit, same pattern as conversations. New notebook creation now drops you directly into rename mode so "Untitled notebook" doesn't stick around.
  • Delete document. Backend `DELETE /documents?notebook_id=&source_path=` removes chunks from the chroma collection, the summary row, the file on disk (scoped to the notebook's `uploads_dir` with the same `Path.relative_to` guard as preview), and decrements the notebook's counts via a new clamp-at-zero `adjust_counts` helper. Frontend: overflow menu on each document card with confirmation.
  • Create empty notebook. `+ New` now calls `POST /notebooks/` directly instead of forcing an immediate file upload.
  • Zotero is discoverable. Button lives next to `+ Add` in the Documents section — previously only reachable via the command palette.

Error visibility

  • Notification center. Bell icon in the sidebar footer with an unread badge; opens a slide-over panel listing the last 50 errors, successes, and warnings with relative + absolute timestamps. `Toast.tsx` now mirrors non-`info` toasts into this log so a failure at second 3 is still recoverable at second 30.
  • Human error messages. New `utils/errorMessages.ts` translates common failures:
    • `ECONNREFUSED` / `Failed to fetch` → "The backend isn't reachable. Check that the server is running."
    • 413 → "That file is too large. Split it into smaller documents."
    • 415 → "That file type isn't supported. Try a PDF, DOCX, PPTX, TXT, or Markdown file."
    • 422 → "We couldn't process that. The file may be empty, scanned without OCR, or corrupt."
    • 403 → "That file is outside this notebook."
    • Ollama / model-not-found → "The AI model isn't available. Make sure Ollama is running."
    • Unknown errors fall through to the raw message (capped).
  • `role="alert"` on error toasts so screen readers announce immediately.
  • AppShell drop handler no longer aborts the whole batch. Each file has its own try/catch — file 2 failing doesn't swallow the result of file 1, and the error message names which file failed.

Reliability

  • `ConnectionBanner` monitors Ollama too. Three-state: `healthy` / `backend-down` / `ollama-down`. Ollama crash mid-session now shows an amber warn-banner: "AI model (Ollama) isn't reachable. Start Ollama, then try your message again." Previously a dead model surfaced only as a raw error in the chat bubble.
  • Banner runs its check on mount instead of only after the first 30s interval tick. Interval dropped from 30s to 15s.

Verified

  • `cd apps/desktop && npm run build` — clean (272 modules, 847ms)
  • `cd backend && uv run ruff check .` — clean
  • `cd backend && uv run pytest -q` — 33 passed (3 new: rename happy path, rename-missing returns None, `adjust_counts` clamps to zero)

Intentionally not in this PR (punted to Wave 3b or Wave 4)

  • 3.3 duplicate upload detection — needs ingestion-layer change; belongs with Wave 4's other vector_store work
  • 3.4 real upload progress bar — requires an XHR refactor of the upload path; kept separate for review surface
  • 3.6 wizard model selection wiring — needs a backend model-override API; scoped out here

🤖 Generated with Claude Code

Wave 3 of 5 from .gstack/qa-reports/PLAN.md. With Waves 1 and 2 in, the
product no longer corrupts data and its signature feature renders — but
you still can't rename a notebook, can't delete a document, can't see
errors once a toast vanishes, and the AI-model-crashed case is a blank
stare. This wave closes those gaps.

## Actions that didn't exist

- **Rename notebook.** Backend PATCH /notebooks/:id + notebook_store
  rename_notebook(). Frontend: context menu → inline edit (same pattern
  as conversations). New notebook creation drops you directly into
  rename mode so "Untitled notebook" doesn't stick around.
- **Delete document.** Backend DELETE /documents?notebook_id=&source_path=
  removes the chunks from the chroma collection, the summary row, the
  uploaded file (scoped to the notebook's uploads_dir with the same
  Path.relative_to guard as preview), and decrements the notebook's
  source_count/chunk_count via a new clamp-at-zero adjust_counts helper.
  Frontend: overflow menu on each document card with confirmation.
- **Create empty notebook.** "+ New" now calls POST /notebooks/
  directly instead of opening a file picker — users can shape a notebook
  before adding documents. The welcome + upload paths still create a
  notebook implicitly.
- **Zotero is discoverable.** Button lives next to "+ Add" in the
  Documents section. It was previously only reachable via the command
  palette.

## Error visibility

- **Notification center.** Bell icon in the sidebar footer with an unread
  badge; opens a slide-over panel listing the last 50 errors, successes,
  and warnings with relative+absolute timestamps. Toast.tsx now mirrors
  non-info toasts into this log so "Upload failed" at second 3 is still
  recoverable at second 30. role="alert" on error toasts so screen
  readers announce immediately.
- **Human error messages.** New utils/errorMessages.ts translates common
  failure modes — "Request failed with status 422" -> "We couldn't
  process that. The file may be empty, scanned without OCR, or corrupt."
  Network errors, 413 size, 415 MIME, 403 scope, 500 server, Ollama-down
  all get specific copy. Unknown errors fall through to the raw message
  (truncated). Wired into Sidebar upload/delete/rename + AppShell drop.
- **AppShell drop handler no longer aborts the whole batch.** Each file
  upload is now its own try/catch — file 2 failing doesn't swallow the
  report on file 1, and the error message names which file failed.

## Reliability nudges

- **ConnectionBanner monitors Ollama too.** Previously checked only the
  backend, so a model crash mid-session was invisible until the chat
  failed. Now it watches both and shows a distinct amber warn-banner
  when Ollama is unreachable: "AI model (Ollama) isn't reachable. Start
  Ollama, then try your message again."
- **Banner runs its check on mount**, not only after the first 30s
  interval tick. And the interval is 15s now, not 30s.

## Verified

- cd apps/desktop && npm run build — clean (272 modules, 847ms)
- cd backend && uv run ruff check . — clean
- cd backend && uv run pytest -q — 33 passed (3 new: rename happy path,
  rename-missing returns None, adjust_counts clamps to zero)

## Intentionally not in this PR

- 3.3 duplicate upload detection — needs ingestion-layer change; punted
  to Wave 4 alongside other vector_store work
- 3.4 real upload progress bar — requires an XHR refactor of the
  upload path; kept as a separate PR for review surface
- 3.6 wizard model selection wiring — needs a backend-side model
  override API; scoped out for this wave

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vikranthreddimasu vikranthreddimasu merged commit 5c0afd1 into main Apr 18, 2026
2 checks passed
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