Commit graph

14 commits

Author SHA1 Message Date
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
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
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
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
Luis Novo
1a67f1f912
fix: enhance chat reference links and prevent text overflow (#173)
This commit addresses two related issues in the chat interface:

1. **Fix broken reference links (OSS-310)**
   - Completely rewrote convertReferencesToMarkdownLinks() with greedy pattern matching
   - Now handles all edge cases: references after commas, nested brackets, bold markdown
   - Added visual icon indicators (FileText, Lightbulb, FileEdit) for reference types
   - Implemented proper error handling with toast notifications
   - Added validation for reference types and ID lengths

2. **Fix long URL/text overflow (#172)**
   - Added break-words and overflow-wrap classes to chat messages
   - Long URLs and text now wrap properly within chat bubbles
   - Applied fix consistently across source chat, notebook chat, and search results

**Technical Details:**
- Enhanced reference detection algorithm processes from end to start to preserve indices
- Context analysis (50 chars before/after) determines original formatting
- Icons are 12px, accessible, and themed appropriately
- All changes pass linting and build successfully

**Files Modified:**
- frontend/src/lib/utils/source-references.tsx (core algorithm rewrite)
- frontend/src/components/source/ChatPanel.tsx (error handling + text wrapping)
- frontend/src/components/search/StreamingResponse.tsx (error handling + text wrapping)
- open_notebook/utils/token_utils.py (ruff formatting fix)

fixes #172
2025-10-19 15:38:59 -03:00
Luis Novo
b5666c4d68
Fix/increase fix: increase API client timeouts for transformation operations timeouts (#170)
* fix: increase API client timeouts for transformation operations

- Increase frontend timeout from 30s to 300s (5 minutes)
- Increase Streamlit API client timeout from 30s to 300s
- Add API_CLIENT_TIMEOUT environment variable for configurability
- Add ESPERANTO_LLM_TIMEOUT environment variable documentation
- Update .env.example with comprehensive timeout documentation

Fixes #131 - API timeout errors during transformation generation
Transformations now have sufficient time to complete on slower
hardware (Ollama, LM Studio) without frontend timeout errors.

Users can now configure timeouts for both the API client layer
(API_CLIENT_TIMEOUT) and the LLM provider layer (ESPERANTO_LLM_TIMEOUT)
to accommodate their specific hardware and network conditions.

* docs: add timeout configuration documentation

- Add comprehensive timeout troubleshooting section to common-issues.md
- Add FAQ entry about timeout errors during transformations
- Document API_CLIENT_TIMEOUT and ESPERANTO_LLM_TIMEOUT usage
- Provide specific timeout recommendations for different hardware/network scenarios
- Link to GitHub issue #131 for reference

* chore: bump

* refactor: improve timeout configuration with validation and consistency

Based on PR review feedback, this commit addresses several improvements:

**Timeout Validation:**
- Add validation to ensure timeout values are between 30s and 3600s
- Invalid values fall back to default 300s with warning logs
- Handles edge cases (negative, zero, invalid strings)

**Fix Hard-coded Timeouts:**
- Replace all hard-coded timeout values in api/client.py
- ask_simple: 300s → self.timeout
- execute_transformation: 120s → self.timeout
- embed_content: 120s → self.timeout
- create_source: 300s → self.timeout
- rebuild_embeddings: Uses smart logic (2x timeout, max 3600s)

**Improved Documentation:**
- Add clarifying comments about ms vs seconds (frontend vs backend)
- Document that frontend uses 300000ms = backend 300s
- Add inline documentation for rebuild_embeddings timeout logic

**Development Dependencies:**
- Add pytest>=8.0.0 to dev dependencies for future test coverage

This makes timeout configuration more robust, consistent, and user-friendly
while maintaining backward compatibility.
2025-10-19 11:37:24 -03:00
LUIS NOVO
a73ce8e094 fix: better fix to the backend connectivity problem using the react backend for guessing the API URL 2025-10-19 10:16:58 -03:00
Luis Novo
04b5a9c96a
Implement a serverside fix for reverse proxy users (#169) 2025-10-19 08:02:21 -03:00
Luis Novo
b7e656a319
Version 1 (#160)
New front-end
Launch Chat API
Manage Sources
Enable re-embedding of all contents
Sources can be added without a notebook now
Improved settings
Enable model selector on all chats
Background processing for better experience
Dark mode
Improved Notes

Improved Docs: 
- Remove all Streamlit references from documentation
- Update deployment guides with React frontend setup
- Fix Docker environment variables format (SURREAL_URL, SURREAL_PASSWORD)
- Update docker image tag from :latest to :v1-latest
- Change navigation references (Settings → Models to just Models)
- Update development setup to include frontend npm commands
- Add MIGRATION.md guide for users upgrading from Streamlit
- Update quick-start guide with correct environment variables
- Add port 5055 documentation for API access
- Update project structure to reflect frontend/ directory
- Remove outdated source-chat documentation files
2025-10-18 12:46:22 -03:00