Commit graph

55 commits

Author SHA1 Message Date
Luis Novo
6dc9a3db50
feat: detect HTML content in clipboard for text sources (#475)
* chore: bump content-core to support html to markdown

* feat: detect HTML content in clipboard for text sources

- Add paste handler to detect text/html format in clipboard
- Use HTML content instead of plain text when available
- Display info message when HTML is detected
- Add translations for all supported languages (en-US, pt-BR, ja-JP, zh-CN, zh-TW)

* fix: reset HTML detection banner on plain text paste

Clear the hasHtmlContent flag when pasting plain text (no HTML in
clipboard) so the banner doesn't persist incorrectly after replacing
HTML content with plain text.
2026-01-25 21:36:58 -03:00
Luis Novo
4e411e0488
feat: add cascade deletion for notebooks with delete preview (#471)
* feat: decrease chunking size for maximum ollama compatibility

* docs: improve i18n info on Claude.md

* feat: add cascade deletion for notebooks with delete preview

- Add Notebook.get_delete_preview() to show counts of affected items
- Add Notebook.delete(delete_exclusive_sources) for cascade deletion
- Always delete notes when notebook is deleted
- Allow user to choose: delete or keep exclusive sources
- Shared sources are always unlinked but never deleted
- Add NotebookDeleteDialog component with radio button options
- Add delete-preview API endpoint
- Update delete endpoint with delete_exclusive_sources param
- Add i18n support for all 5 locales

Closes #77

* docs: remove harcoded config settings
2026-01-25 14:56:14 -03:00
Jun Endo
0436a851da
feat(i18n): add Japanese (ja-JP) language support (#450) 2026-01-21 23:49:44 -03:00
Luis Novo
d8006ff5cb
feat: content-type aware chunking and unified embedding (#444)
* feat: content-type aware chunking and unified embedding

- Add chunking.py with HTML, Markdown, and plain text detection
- Add embedding.py with mean pooling for large content
- Create dedicated commands: embed_note, embed_insight, embed_source
- Use fire-and-forget pattern for embedding via submit_command()
- Refactor rebuild_embeddings_command to delegate to individual commands
- Remove legacy commands and needs_embedding() methods
- Reduce chunk size to 1500 chars for Ollama compatibility
- Update CLAUDE.md documentation for new architecture

Fixes #350, #142

* fix: address code review issues

- Note.save() now returns command_id for tracking embedding jobs
- Add length check after generate_embeddings() to fail fast on mismatch
- Add numpy as explicit dependency (was transitive)
- Remove hardcoded chunk sizes from docstrings

* docs: address code review comments

- Rename "SYNC PATH" to "DOMAIN MODEL PATH" in embedding router
- Add test_chunking.py and test_embedding.py to Testing Strategy
- Clarify auto-embedding behavior for each domain model

* fix: clean thinking tags from prompt graph output

Adds clean_thinking_content() to prompt.py to handle extended thinking
models that return <think>...</think> tags. This fixes empty titles
when saving notes from chat.

* chore: remove local docker-compose from git

* fix(frontend): handle null parent_id in search results

Add defensive check for null parent_id in search results to prevent
"Cannot read properties of null (reading 'split')" error. This can
happen with orphaned records in the database.

* fix: cascade delete embeddings and insights when source is deleted

When deleting a Source, now also deletes associated:
- source_embedding records
- source_insight records

This prevents orphaned records that cause null parent_id errors
in vector search results.

* fix: add cleanup for orphan embedding/insight records in migration 10

Deletes source_embedding and source_insight records where the
linked source no longer exists (source.id = NONE).

* chore: bump esperanto to 2.16

Increases ctx_num for Ollama models to accommodate larger notebook
context windows. See: https://github.com/lfnovo/esperanto/pull/69
2026-01-21 23:49:08 -03:00
Luis Novo
c6ec1fcddf
fix(i18n): resolve podcast dialog translation infinite loop and profile issues (#435)
* fix(i18n): resolve podcast dialog translation infinite loop and profile issues

- Remove incorrect translation keys for user-defined episode profiles
- Cache translation strings in ContentSelectionPanel to avoid repeated
  Proxy accesses that triggered infinite loop detection
- Stabilize useEffect dependencies with dataKey pattern to prevent
  re-initialization on every keystroke
- Replace unstable sourcesQueries prop with stable fetchingNotebookIds set
- Clean up unused getSourceModes function and TranslationKeys import

* chore: bump lock

* chore: bump version to 1.5.1 and update CHANGELOG

* fix: guard .join() call in dataKey when query data is undefined
2026-01-15 21:50:27 -03:00
Luis Novo
de0d3977b7
feat(i18n): add Brazilian Portuguese (pt-BR) translation (#434)
- Add complete pt-BR locale with 750+ translated strings
- Register pt-BR in locale registry and language selector
- Add date-fns ptBR locale for date formatting
- Update README and CLAUDE.md documentation
2026-01-15 18:55:55 -03:00
Luis Novo
b7ff0ccfe9
chore: post-i18n cleanup and version bump to 1.5.0 (#433)
* chore: post-i18n cleanup and version bump to 1.5.0

- Restore missing .dockerignore entries (notebook_data, surreal_data, docs, etc.)
- Fix lint command for Next.js 16 (use eslint directly instead of next lint)
- Remove aria-describedby={undefined} causing Radix UI warnings
- Bump version to 1.5.0
- Update CHANGELOG with i18n features
- Add multi-language UI mention to README
- Add i18n contribution guide to README.dev
- Document i18n system in CLAUDE.md files

Closes #344, #349, #360

* docs: fix provider order in CLAUDE.md to match layout.tsx
2026-01-15 14:20:13 -03:00
MisonL
67dd85c928
Feat/localization tests docker (#371)
* feat(i18n): complete 100% internationalization and fix Next.js 15 compatibility

* feat(i18n): complete 100% internationalization coverage

* chore(test): finalize component tests and project cleanup

* test(logic): add unit tests for useModalManager hook

* fix(test): resolve timeout in AppSidebar tests by mocking TooltipProvider

* feat(i18n): comprehensive i18n audit, fixes for hardcoded strings, and complete zh-TW support

* fix(i18n): resolve TypeScript warnings and improve translation hook stability

- Remove unused useTranslation import from ConnectionGuard
- Add ref-based checking state to prevent dependency cycles
- Fix useTranslation hook to return empty string for undefined translations
- Add comment for backward compatibility on ExtractedReference interface
- Ensure .replace() string methods work safely with nested translation keys

* feat(i18n): complete internationalization implementation with Docker deployment

- Add LanguageLoadingOverlay component for smooth language transitions
- Update all translation files (en-US, zh-CN, zh-TW) with improved terminology
- Optimize Docker configuration for better performance
- Update version check and config handling for i18n support
- Fix route handling for language-specific content
- Add comprehensive task documentation

* fix(i18n): resolve localization errors, duplicates, and type issues

* chore(i18n): finalize 100% internationalization coverage

* chore(test): supplement i18n test cases and cleanup redundant files

* fix(test): resolve lint type errors and finalize delivery documents

* feat(i18n): finalize full internationalization and zh-TW localization

* fix(frontend): add missing devDependency and fix build tsconfig

* feat(ui): enhance sidebar hover effects with better visual feedback

* fix(frontend): resolve accessibility, i18n, and lint issues

- fix: add missing id, name, autocomplete attributes to dialog inputs
- fix: add aria labels and DialogDescription for accessibility
- fix: resolve uncontrolled component warning in SettingsForm
- fix: correct duplicate 'Traditional Chinese' label in zh-TW locale
- feat: add i18n support for podcast template names
- chore: fix lint errors in Dialogs

* fix: address all 21 PR feedback items from cubic-dev-ai bot

Configuration:
- Remove ignoreDuringBuilds flags from next.config.ts

Testing:
- Fix AppSidebar.test.tsx regex pattern and add missing assertion

Logic:
- Fix ConnectionGuard.tsx re-entry prevention logic

Internationalization (I18n) - Translations:
- Add missing keys: notebooks.archived, common.note/insight, accessibility keys
- Add specific keys: sources.allSourcesDescShort, transformations.selectModel
- Add singular/plural keys: podcasts.usedByCount_one/other, common.note/notes
- Add common.created/updated with {time} placeholder

Internationalization (I18n) - Usage:
- SourcesPage: use allSourcesDescShort instead of string splitting
- TransformationPlayground: use navigation.transformation and selectModel
- CommandPalette: use dedicated keys instead of string concatenation
- GeneratePodcastDialog: fix zh-TW date locale handling
- NotebookHeader: correctly interpolate {time} placeholder
- TransformationCard: use common.description instead of undefined key
- ChatPanel/SpeakerProfilesPanel: implement proper pluralization
- SystemInfo: correctly interpolate {version} placeholder
- LanguageLoadingOverlay: use t.common.loading instead of hardcoded string
- MessageActions: use specific error key cannotSaveNoteNoNotebook

Other:
- Fix SessionManager.tsx exhaustive-deps warning

* fix: remove duplicate locale keys and add missing zh-CN translations

- en-US: remove duplicate loading key (line 59) and addNew key (sources)
- zh-CN: remove duplicate common keys (loading, note, insight, newSource, newNotebook, newPodcast)
- zh-CN: remove duplicate accessibility.searchNotebooks key
- zh-CN: remove duplicate sources.addNew key
- zh-CN: remove duplicate navigation.transformation key
- zh-CN: add missing usedByCount_one and usedByCount_other keys in podcasts
- zh-TW: remove duplicate common keys (loading, note, insight, newSource, newNotebook, newPodcast)
- zh-TW: remove duplicate accessibility.searchNotebooks key
- zh-TW: remove duplicate sources.addNew key

* docs: remove info.md

* fix: remove duplicate notebook keys and unused ts-expect-error

- zh-CN: remove duplicate notebooks keys (archived, archive, unarchive, deleteNotebook, deleteNotebookDesc)
- zh-TW: remove duplicate notebooks keys (archived, archive, unarchive, deleteNotebook, deleteNotebookDesc)
- GeneratePodcastDialog: remove unused @ts-expect-error directive

* fix(a11y): fix unassociated labels in search page

- Replace <Label> with role='group' + aria-labelledby for search type section
- Replace <Label> with role='group' + aria-labelledby for search in section
- Follows WAI-ARIA best practices for labeling form field groups

* fix(a11y): fix unassociated labels across multiple components

- search/page.tsx: use role='group' + aria-labelledby for search type and search in sections
- RebuildEmbeddings.tsx: use role='group' + aria-labelledby for include checkboxes
- TransformationPlayground.tsx: replace Label with span for non-form output label

* chore: revert to npm stack and ensure i18n compatibility

* chore: polish zh-TW translations for better idiomatic usage

* fix: resolve linter errors (ruff import sort, mypy config duplicate)

* style: apply ruff formatting

* fix: finalize upstream compliance (Dockerfile.single, i18n hooks, docker-compose)

* style: polish strings, fix timeout cleanup, and improve test mocks

* fix: use relative imports in test setup to resolve IDE path errors

* perf(docker): optimize build speed by removing apt-get upgrade and build tools

- Remove apt-get upgrade from both builder and runtime stages (saves 10-15 min each)
- Remove gcc/g++/make/git from builder (uv downloads pre-built wheels)
- Add --no-install-recommends to minimize package footprint
- Keep npm mirror (npmmirror.com) for faster frontend deps
- Add npm registry config for reliable China network access

Also includes:
- fix(a11y): add missing labels and aria attributes to form fields
- fix(i18n): add 2s safety timeout to LanguageLoadingOverlay
- fix(i18n): add robustness checks to use-translation proxy

Build time reduced from 2+ hours to ~34 minutes (~70% improvement)

* fix(a11y): resolve 16 form field accessibility warnings in notebook and podcast pages

* fix(a11y): resolve 4 button and 1 select field accessibility warnings in models page

* fix(a11y): resolve redundant attributes and residual warnings in transformations and podcast forms

* fix(i18n): deep fix for language switch hang using proxy protection and safer access

* fix(a11y): add name attributes to ModelSelector, TransformationPlayground, and SourceDetailContent

* fix: add missing Label import to SourceDetailContent

* fix(i18n): use native react-i18next in LanguageLoadingOverlay to prevent hang during language switch

* fix(i18n): rewrite use-translation Proxy with strict depth limit and expanded blocked props to prevent language switch hang

* fix: add type assertion to fix TypeScript comparison error

* fix(i18n): disable useSuspense to prevent thread hang during language resource loading

* fix(i18n): add infinite loop detection circuit breaker to useTranslation hook

* fix(i18n): update traditional chinese label to native script in en-US

* feat: add new localization strings for notebook and note management.

* fix: resolve config priority, docker build deps, and ui glitches

* refactor: improve ui details and test coverage based on feedback

* refactor: improve ui details (version check/lang toggle) and test coverage

* fix: polish language matching and test cleanup

* fix(test): update mocks to resolve timeouts and proxy errors

* fix(frontend): restore tsconfig.json structure and enable IDE support for tests

* fix: address PR review findings and resolve CI OIDC failure

* fix: merge exception headers in custom handler

* fix: comprehensive PR review remediations and async performance fixes

* refactor: address all PR #371 review feedback

- Docker: consolidate SURREAL_URL to docker.env, add single-container override
- Security: restore apt-get upgrade in Dockerfile and Dockerfile.single
- Create centralized getDateLocale helper (lib/utils/date-locale.ts)
- Refactor 7 files to use getDateLocale helper
- Revert config/route.ts to origin/main version
- Move test files to co-located pattern (3 files)
- Remove local useTranslation mock from ConfirmDialog.test.tsx
- Simplify use-version-check to single useEffect pattern
- Fix test import paths after moving to co-located pattern

* fix: add jest-dom types for test files

* fix: address remaining review issues

- Add apt-get upgrade -y to Dockerfile.single backend-builder stage
- Refactor ChatColumn.test.tsx: use 'as unknown as ReturnType<typeof hook>' instead of 'as any'
- Use toBeInTheDocument() assertions instead of toBeDefined()
2026-01-15 13:51:05 -03:00
LUIS NOVO
4fe36be43c docs: update CLAUDE.md files for Next.js 16 upgrade
- Update root CLAUDE.md: Next.js 15 → 16
- Update frontend/src/CLAUDE.md: middleware.ts → proxy.ts
2026-01-14 13:02:33 -03:00
LUIS NOVO
136698864e feat: upgrade Next.js 15 → 16 to fix large file uploads
- Upgrade Next.js from 15.4.10 to 16.1.1
- Upgrade React from 19.1.0 to 19.2.3
- Rename middleware.ts → proxy.ts (Next.js 16 requirement)
- Update function name: middleware → proxy
- Enable proxyClientMaxBodySize configuration (now supported in Next.js 16)
- Update documentation to reference Next.js 16 requirement
- Fix upload size limit issue for files >10MB

This upgrade fixes GitHub issue #361 where users cannot upload files
larger than 10MB. The proxyClientMaxBodySize configuration option was
introduced in Next.js 16.1+ and allows configuring the proxy body size
limit to 100MB.

Fixes #361
Related to PR #405
2026-01-14 10:33:19 -03:00
LUIS NOVO
7717e0f9f6 fix: update broken documentation links to ai-providers.md
Updated all references from non-existent docs/features/ai-models.md
to the correct path docs/5-CONFIGURATION/ai-providers.md

Fixes #412
2026-01-13 20:34:04 -03:00
Luis Novo
dd4e47a127
Merge pull request #418 from lfnovo/fix/remove-zip-support-indication
fix: remove zip support indication
2026-01-13 20:01:58 -03:00
LUIS NOVO
3d696b0ab0 fix: remove zip support indication fixes #415 2026-01-13 19:56:09 -03:00
Fauzira Alpiandi
a1fb7a750f feat: add CTA button to empty state list 2026-01-10 04:08:42 +00:00
LUIS NOVO
a41703fbac chore: remove unused AddButton component
The AddButton component was never imported or used anywhere in the
application. Notebook creation is already implemented and working via:
- "New Notebook" button on the notebooks page
- "Create" button in the sidebar
- "Create Notebook" command in the command palette

Closes #390
2026-01-08 15:56:26 -03:00
LUIS NOVO
71b8d13b24 docs: generate comprehensive CLAUDE.md reference documentation across codebase
Create a hierarchical CLAUDE.md documentation system for the entire Open Notebook
codebase with focus on concise, pattern-driven reference cards rather than
comprehensive tutorials.

## Changes

### Core Documentation System
- Updated `.claude/commands/build-claude-md.md` to distinguish between leaf and
  parent modules, with special handling for prompt/template modules
- Established clear patterns:
  * Leaf modules (40-70 lines): Components, hooks, API clients
  * Parent modules (50-150 lines): Architecture, cross-layer patterns, data flows
  * Template modules: Pattern focus, not catalog listings

### Generated Documentation
Created 15 CLAUDE.md reference files across the project:

**Frontend (React/Next.js)**
- frontend/src/CLAUDE.md: Architecture overview, data flow, three-tier design
- frontend/src/lib/hooks/CLAUDE.md: React Query patterns, state management
- frontend/src/lib/api/CLAUDE.md: Axios client, FormData handling, interceptors
- frontend/src/lib/stores/CLAUDE.md: Zustand state persistence, auth patterns
- frontend/src/components/ui/CLAUDE.md: Radix UI primitives, CVA styling

**Backend (Python/FastAPI)**
- open_notebook/CLAUDE.md: System architecture, layer interactions
- open_notebook/ai/CLAUDE.md: Model provisioning, Esperanto integration
- open_notebook/domain/CLAUDE.md: Data models, ObjectModel/RecordModel patterns
- open_notebook/database/CLAUDE.md: Repository pattern, async migrations
- open_notebook/graphs/CLAUDE.md: LangGraph workflows, async orchestration
- open_notebook/utils/CLAUDE.md: Cross-cutting utilities, context building
- open_notebook/podcasts/CLAUDE.md: Episode/speaker profiles, job tracking

**API & Other**
- api/CLAUDE.md: REST layer, service architecture
- commands/CLAUDE.md: Async command handlers, job queue patterns
- prompts/CLAUDE.md: Jinja2 templates, prompt engineering patterns (refactored)

**Project Root**
- CLAUDE.md: Project overview, three-tier architecture, tech stack, getting started

### Key Features
- Zero duplication: Parent modules reference child CLAUDE.md files, don't repeat them
- Pattern-focused: Emphasizes how components work together, not component catalogs
- Scannable: Short bullets, code examples only when necessary (1-2 per file)
- Practical: "How to extend" guides, quirks/gotchas for each module
- Navigation: Root CLAUDE.md acts as hub pointing to specialized documentation

### Cleanup
- Removed unused `batch_fix_services.py`
- Removed deprecated `open_notebook/plugins/podcasts.py`
- Updated .gitignore for documentation consistency

## Impact
New contributors can now:
1. Read root CLAUDE.md for system architecture (5 min)
2. Jump to specific layer documentation (frontend, api, open_notebook)
3. Dive into module-specific patterns in child CLAUDE.md files (1 min per module)
All documentation is lean, reference-focused, and avoids duplication.
2026-01-03 16:27:52 -03:00
Luis Novo
93cda6c42a
Merge pull request #304 from xeader/fix/issue-271.2-ui-not-responsive
feat(notebooks): improve layout responsiveness
2025-12-20 10:18:22 -03:00
LUIS NOVO
2a4d98772b fix(ui): optimize MutationObserver in NoteEditorDialog
Only observe DOM mutations when dialog is open, preventing
unnecessary observer activity when the dialog is closed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 10:13:49 -03:00
Luis Novo
a8bb88e10f
Merge pull request #305 from xeader/fix/issue-271.1-note-editor-not-full-screen
feat(notebooks): Enhance dialog content styling for fullscreen mode
2025-12-20 10:12:29 -03:00
Antonio Gatta
cdb074193f feat: support fullscreen mode in NoteEditorDialog
- Added `isEditorFullscreen` state to track fullscreen mode for the Markdown editor.
- Integrated `MutationObserver` to detect changes related to the `.w-md-editor-fullscreen` class.
- Adjusted dialog and editor styles dynamically based on fullscreen state using `cn`.
- Enhanced UX by resetting fullscreen state on dialog close.
2025-12-20 11:38:31 +01:00
LUIS NOVO
79f4d5ea6a fix: resolve merge conflict in SourceInsightDialog
Add missing state variables and handlers for delete functionality
that were lost during merge of PRs #334 and #340
2025-12-19 23:10:49 -03:00
Luis Novo
c41cc074b5
Merge branch 'main' into feat/delete-insight 2025-12-19 22:50:53 -03:00
Luis Novo
8fdb0f0539
Update frontend/src/components/source/SourceDetailContent.tsx
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-19 22:48:09 -03:00
Justin Florentine
c7de8ecd86
fix: address PR feedback for delete insight feature
- Fix AlertDialogAction closing before async delete completes by using
  asChild with Button and event.preventDefault()
- Add delete button to SourceInsightDialog header for consistent UX
- Add confirmation dialog in SourceInsightDialog
- Pass onDelete callback from SourceDetailContent to SourceInsightDialog

Addresses PR #334 feedback from lfnovo and cubic-dev-ai.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 20:45:11 -05:00
LUIS NOVO
7f19c916ae feat: add View Source button to insight modal
- Add button to navigate from insight popup to its parent source
- Uses existing modal manager to open source detail view
- Shows button only when source_id is available
2025-12-19 17:10:55 -03:00
LUIS NOVO
a1d0a3a666 fix: allow model override before chat session exists
- Add pendingModelOverride state to useNotebookChat hook
- Store model selection when no session exists yet
- Apply pending model override when session is auto-created on first message
- Simplify ChatColumn by using new setModelOverride function
2025-12-19 16:55:26 -03:00
LUIS NOVO
e11f0a4db8 fix: resolve chat model selection and session display issues
- Add nullable_fields support to ObjectModel base class
- Configure ChatSession to allow model_override to be cleared to null
- Fix JSX conditional that rendered "0" when message_count was 0
- Display model name instead of raw ID in session manager

Fixes issues:
1. Switching to default model now persists correctly
2. Session list shows human-readable model names
3. Sessions with 0 messages no longer show "0" badge
2025-12-19 16:47:34 -03:00
Justin Florentine
8644f1923c
feat: add delete insight functionality
Add ability to delete insights from sources with a confirmation dialog.
Uses AlertDialog component for a native React experience instead of
browser confirm().

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 18:04:41 -05:00
LUIS NOVO
26e989fdbb fix: query key consistency and timeout configuration
- Use QUERY_KEYS.sourcesInfinite for infinite scroll query key
  Starting with ['sources', ...] ensures mutations that invalidate
  ['sources'] will also invalidate the infinite scroll cache

- Use httpx.Timeout for chat service with short connect (10s) and
  long read (600s) timeouts. Prevents 10 min wait on connection errors
2025-12-14 21:55:38 -03:00
LUIS NOVO
6e8f46420a feat(ui): add markdown table rendering support
Added remark-gfm plugin to enable GitHub Flavored Markdown support,
which includes proper table rendering. Updated all ReactMarkdown
usages with table styling components:

- ChatPanel (source and notebook chat)
- StreamingResponse (search/ask results)
- SourceInsightDialog
- SourceDetailContent
- TransformationPlayground

Tables now render with proper borders, headers with background,
and horizontal scroll for wide tables.
2025-12-14 12:01:28 -03:00
LUIS NOVO
3001537aa7 fix: increase timeout for Ollama and local LLM operations
Users with Ollama reported timeout errors on notebook chat while the
backend was still processing. The answer would appear after refresh.

- Frontend axios timeout: 5 min → 10 min
- Backend chat service timeout: 2 min → 10 min

Local LLMs can take several minutes for complex questions with large
contexts, especially on slower hardware.
2025-12-14 11:31:03 -03:00
LUIS NOVO
e5eeb90341 feat(ui): add infinite scroll for notebook sources
Previously, notebook sources were limited to 50 items due to API default.
This adds pagination with infinite scroll to the sources column:

- Add useNotebookSources hook with useInfiniteQuery for paginated fetching
- Update SourcesColumn with scroll detection to load more sources
- Fetch 30 sources per page, loading more as user scrolls near bottom
2025-12-14 10:56:38 -03:00
Antonio Gatta
45ac425484 feat: enhance dialog content for fullscreen mode
- Added styles to ensure `.w-md-editor-fullscreen` behaves statically and adjusts height dynamically with `!static` and `!h-[calc(90vh-(var(--spacing)*41))]`.
2025-12-08 02:18:07 +01:00
Antonio Gatta
eb67e33965 feat: improve dialog content responsive styling
- Added support for `.w-md-editor-fullscreen` class to dynamically adjust height and width for fullscreen mode.
2025-12-08 01:41:05 +01:00
Antonio Gatta
47db332d17 feat(notebooks): improve layout responsiveness
- Adjusted `div` class styles to add horizontal scrolling in smaller viewports (`overflow-x-auto`).
- Updated chat column element with additional padding and margin adjustments for better desktop layout.
2025-12-08 00:24:37 +01:00
LUIS NOVO
d8e61c6b5b fix(ui): address review feedback for URL param handling
- Fix race condition: only set hasAutoTriggeredRef after successful execution
- Add URL mode validation: ensure mode is either 'search' or 'ask'
2025-12-01 20:52:35 -03:00
LUIS NOVO
33be80ab7c fix(ui): handle URL params in search page for command palette navigation
The search page now reads `q` and `mode` query parameters from the URL,
enabling proper integration with the command palette's search/ask actions.

Changes:
- Read URL params using useSearchParams hook
- Initialize form fields and active tab from URL params
- Auto-trigger search/ask when arriving with URL params
- Handle subsequent navigations while on the search page
2025-12-01 20:46:49 -03:00
Luis Novo
5d5b6bd035
feat(ui): add command palette for quick navigation and search (#288)
* feat(ui): add command palette for quick navigation and search

Replace top bar search with a command palette (⌘K / Ctrl+K) that provides:
- Quick navigation to all app sections
- Create shortcuts for sources, notebooks, and podcasts
- Theme switching (light/dark/system)
- Search and Ask functionality for non-matching queries

This approach saves screen real estate while providing faster access
to common actions through keyboard shortcuts.

Co-authored-by: EmbroiderSnow <1497411439@qq.com>

* chore: bump to 1.2.3

* feat(command-palette): add notebook quick navigation

Users can now type a notebook name in the command palette (⌘K) to
navigate directly to that notebook. Shows up to 8 most recent
notebooks, with cmdk filtering all notebooks when typing.

* fix(command-palette): address code review issues

- Skip ⌘K/Ctrl+K shortcut when focus is inside input, textarea, select,
  or contentEditable elements to preserve native keyboard handling
- Remove 8-item limit on notebooks so all notebooks are searchable
  via cmdk filtering

* perf(command-palette): memoize command matching and add platform shortcuts

- Memoize hasCommandMatch computation with useMemo to avoid
  recalculating on every render
- Show platform-specific keyboard shortcut in sidebar hint:
  ⌘K on macOS, Ctrl+K on Windows/Linux

* fix(command-palette): add spinner to notebooks loading state

Show a spinning Loader2 icon alongside the "Loading notebooks..." text
for clearer visual feedback when the command palette is fetching data.

---------

Co-authored-by: EmbroiderSnow <1497411439@qq.com>
2025-12-01 14:59:17 -03:00
Luis Novo
45a99831a9
Hide sources notes (#273)
* fix: add missing overflow wrapper to notebooks list page

Adds flex-1 overflow-y-auto wrapper to enable proper scrolling
when notebook list exceeds viewport height. Matches the layout
pattern used by all other dashboard pages.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: reorder transformation routes to prevent dynamic route interception

Moved static routes (/transformations/execute and /transformations/default-prompt)
before dynamic routes (/transformations/{transformation_id}) to ensure FastAPI
matches them correctly. Previously, requests to static routes were incorrectly
captured by the dynamic route handler.

Fixes #250

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: bump to 1.2.1

* hide source and notes panel - fixes #193

* feat: improve layout for mobile views

* bump version to 1.2.2

* fix: address PR review feedback for collapsible columns

- Remove unused CollapseButton component from CollapsibleColumn.tsx
- Rename useCollapseButton to createCollapseButton (not a React hook)
- Move dialogs outside Card in SourcesColumn.tsx for consistency
- Add useMemo for collapseButton in both columns to prevent re-renders

* feat: support multiple sources

* fix: prevent ChatColumn double mounting on desktop

Add useIsDesktop hook to conditionally render mobile view only on
mobile screens. Previously, the mobile ChatColumn was hidden via CSS
on desktop but still mounted, causing duplicate hooks initialization
and redundant network requests.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-25 16:59:26 -03:00
Luis Novo
b42cc06e65
fix: UI scrolling and API route ordering issues (#253)
* fix: add missing overflow wrapper to notebooks list page

Adds flex-1 overflow-y-auto wrapper to enable proper scrolling
when notebook list exceeds viewport height. Matches the layout
pattern used by all other dashboard pages.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: reorder transformation routes to prevent dynamic route interception

Moved static routes (/transformations/execute and /transformations/default-prompt)
before dynamic routes (/transformations/{transformation_id}) to ensure FastAPI
matches them correctly. Previously, requests to static routes were incorrectly
captured by the dynamic route handler.

Fixes #250

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: bump to 1.2.1

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-04 21:15:00 -03:00
Luis Novo
f79a9040ae
Release 1.2 (#242)
* chore: improve podcast transcripts

* fix: remove date from insight - fixes #241

* fix: improve scrolling on source and insights - fixes #237

* chore: update esperanto to fix: #234

* chore: update esperanto to fix #226

* fix: process vectorization as subcommands to handle larger documents more gracefully - fix: #229

* feat: enable background job retry capabilities

* feat: reenable content types that were disabled during alpha version

* fix: remove unnecessary model caching causing many issues.

* feat: support multiple azure endpoints and keys just like openai compatible. Fixes #215

* docs: update azure variables

* chore: bump and update dependencies
2025-11-01 14:40:00 -03:00
Luis Novo
933de75b73
feat: implement compact chat references with numbered citations (#220)
Transform verbose inline references to compact footnote-style format:
- Replace [source:abc123] with numbered citations [1], [2], etc.
- Add "References:" section at bottom of messages
- Deduplicate references (same ID gets same number)
- Remove icons from citations for cleaner appearance
- Maintain click-to-open functionality for all reference types

Changes:
- Add convertReferencesToCompactMarkdown() function
- Add createCompactReferenceLinkComponent() function
- Update ChatPanel to use new compact reference functions
- Add ReferenceData interface for type safety

Improves readability by reducing visual clutter while preserving
all existing functionality. References restart numbering at 1 for
each message.
2025-10-25 10:26:21 -03:00
Luis Novo
a287d3b248
refactor: optimize duplicate model validation and improve error handling (#219)
* feat: prevent duplicate model names under same provider

Implement case-insensitive validation to prevent users from creating
duplicate model names under the same provider. This validation is
implemented both in the backend API and the frontend UI.

Changes:
- Backend: Add duplicate check in create_model endpoint (case-insensitive)
- Frontend: Add client-side validation in AddModelForm
- Frontend: Improve error message display from backend
- Tests: Add unit tests for duplicate model validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: optimize duplicate model validation and improve error handling

- Replace O(n) model iteration with efficient SurrealDB query for duplicate check
- Improve error message to include model name and provider for better UX
- Remove frontend duplicate validation (backend-only enforcement)
- Fix test authentication by setting OPEN_NOTEBOOK_PASSWORD before imports
- Update test mocking to use repo_query instead of Model.get_all()
- Add pytest fixture for TestClient to ensure proper test isolation

All 11 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* remove unnecessary package

* fix: replace any with unknown type in error handler

- Change error type from 'any' to 'unknown' to satisfy ESLint
- Add proper type assertion for error object structure
- Maintains same runtime behavior with better type safety

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-25 08:48:18 -03:00
Luis Novo
a0a2282bfa
Delete note functionality (#216)
* feat: Enable note deletion.

* enable dismissing the upgrade button

* delete notes

* fix chat session dialog error

* chore: bump

* chore: bump correctly
2025-10-24 18:27:02 -03:00
Luis Novo
9bdfd99f1b
feat: simplify reverse proxy configuration with Next.js rewrites (#213)
* feat: simplify reverse proxy configuration with Next.js rewrites

Add Next.js API rewrites to proxy /api/* requests internally from port 8502
to the FastAPI backend on port 5055. This eliminates the need for complex
reverse proxy configurations with multiple upstreams and location blocks.

Changes:
- Add rewrites to next.config.ts proxying /api/* to INTERNAL_API_URL
- Introduce INTERNAL_API_URL env var (defaults to http://localhost:5055)
- Update supervisord configs to pass INTERNAL_API_URL to Next.js
- Document INTERNAL_API_URL in .env.example with usage examples
- Add simplified reverse proxy examples for nginx, Traefik, Caddy, Coolify
- Update README architecture diagram to show internal proxying
- Add explanatory comments to _config route handler

Benefits:
- Reduces reverse proxy config from 12 lines to 3 (75% reduction)
- Single-port deployment (8502 only) for 95% of use cases
- Zero breaking changes - backward compatible with existing setups
- Zero performance overhead (validated through testing)
- Preserves proxy headers (X-Forwarded-*) for rate limiting/SSL

Resolves: #179
Related: OSS-321

* fix: rename _config to config to fix production routing

CRITICAL BUG FIX: The /_config endpoint has never worked in production builds
because Next.js treats folders starting with underscore as "private folders"
and excludes them from routing entirely.

This endpoint is critical for:
- Providing API_URL to the browser at runtime
- Enabling zero-config deployments with auto-detection
- Supporting reverse proxy scenarios where API URL differs from frontend URL

Changes:
- Rename frontend/src/app/_config/ → frontend/src/app/config/
- Update client code references (/_config → /config)
- Update documentation with correct endpoint path
- Bump version to 1.1.0 (minor version for new rewrites feature + bug fix)

Impact:
- Runtime configuration now works in production builds
- /config returns {"apiUrl":"http://localhost:5055"} correctly
- Auto-detection for reverse proxy deployments now functional

Related: #179, OSS-321

* fix: resolve React hook exhaustive-deps warning in AddExistingSourceDialog

Wrap performSearch function in useCallback to properly memoize it and satisfy
React Hook exhaustive-deps rule. This prevents unnecessary re-renders and
ensures the useEffect dependency array is correctly specified.

Changes:
- Import useCallback from React
- Wrap performSearch with useCallback([debouncedSearchQuery, allSources])
- Add performSearch to useEffect dependency array

* final fixes
2025-10-24 11:24:14 -03:00
Luis Novo
d680a0affc
docs: update model help links to point to ai-models documentation (#212)
Updated help links in DefaultModelsSection and ProviderStatus components
to point to the new AI models documentation location at
docs/features/ai-models.md instead of docs/models.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-23 18:14:24 -03:00
Luis Novo
fc8a4a0c64
fix: resolve API_URL config routing conflict with reverse proxies (#191)
Move runtime configuration endpoint from /api/runtime-config to /_config to avoid
conflicts with reverse proxies that route all /api/* requests to the FastAPI backend.

This fixes an issue where users with reverse proxies would see port 5055 incorrectly
appended to their API_URL even when explicitly set via environment variable.

Changes:
- Move frontend/src/app/api/runtime-config/route.ts to frontend/src/app/_config/route.ts
- Update config.ts to fetch from /_config instead of /api/runtime-config
- Add troubleshooting documentation for reverse proxy users
- Update all reverse proxy examples to show correct routing (catch-all handles /_config)
- Bump version to 1.0.11

The new /_config endpoint is automatically handled by standard reverse proxy catch-all
rules (location / { proxy_pass http://frontend; }), requiring no additional configuration
for most users.

Fixes issue where API_URL environment variable was being ignored in reverse proxy setups,
causing CORS errors with "Status code: (null)" and incorrect port 5055 being added.
2025-10-21 12:06:24 -03:00
LUIS NOVO
a9af195485 fix: set version cache to 24hrs 2025-10-19 18:05:04 -03:00
Luis Novo
992442150e
feat: add ability to link existing sources to notebooks (OSS-311) (#177)
* fix: small issue where users cant change podcast segments

* chore: remove playwright mcp from gut

* feat: add ability to link existing sources to notebooks (OSS-311)

Implemented bidirectional source-notebook linking functionality:

Backend changes:
- Add POST endpoint to link sources to notebooks
- Include notebook associations in source detail response
- Implement idempotent linking with proper RecordID handling

Frontend changes:
- Add AddExistingSourceDialog with search and multi-select
- Add NotebookAssociations component for source detail view
- Add dropdown menu to "Add Source" button (new/existing)
- Implement useAddSourcesToNotebook hook with graceful error handling
- Fix dialog pointer-events during close animation
- Add loading states and disable checkboxes for linked sources
- Optimize dialog width with proper responsive breakpoints

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: address PR review feedback

- Fix sources.py query to use correct reference direction (OUT where IN)
- Remove debug console.log statements
- Add truncation warning for 100+ source lists

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 17:52:14 -03:00
Luis Novo
df0986cee0
Feature/oss 312 notebook item counts (#175)
* fix: small issue where users cant change podcast segments

* feat: display source and note counts on notebook cards (OSS-312)

Add item counters to notebook listing page showing the number of sources
and notes in each notebook. Counts are displayed in a footer section with
FileText and StickyNote icons for visual consistency with ContextIndicator.

Backend changes:
- Add source_count and note_count to NotebookResponse model
- Update /notebooks endpoint to use SurrealDB graph traversal query
- Query: count(<-reference.in) for sources, count(<-artifact.in) for notes
- Update all notebook endpoints to include counts

Frontend changes:
- Add source_count and note_count to TypeScript NotebookResponse interface
- Add footer section to NotebookCard component
- Display counts with FileText and StickyNote icons (h-3 w-3)
- Use border-top separator and muted-foreground styling

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* style: use colorful badges for notebook counts matching ContextIndicator

Update notebook card counts to use Badge components with primary color
styling instead of plain text, matching the visual style of the
ContextIndicator component in the chat window.

Changes:
- Replace plain text divs with Badge components
- Apply text-primary and border-primary/50 styling
- Use same spacing (gap-1.5, px-1.5, py-0.5) as ContextIndicator
- Remove bullet separator (not needed with badge layout)

Visual result matches the colorful badges shown in chat context.

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-10-19 16:03:36 -03:00