diff --git a/claude-progress.txt b/claude-progress.txt new file mode 100644 index 0000000..750a9fc --- /dev/null +++ b/claude-progress.txt @@ -0,0 +1,36 @@ +Session 1 - Initializer Agent - 2026-04-06 + +## Completed +- Read and analyzed GitHub issue #526 +- Researched the full source creation and listing flow (frontend + backend) +- Identified root cause: useCreateSource and useFileUpload don't invalidate QUERY_KEYS.sourcesInfinite +- Created claude-goal.md with detailed analysis +- Created feature_list.json with 8 test cases +- Created dev-init.sh +- Created branch: fix/source-list-auto-refresh-526 +- Made initial commit + +## Root Cause Summary +- useNotebookSources queries with key ['sources', 'infinite', notebookId] +- useCreateSource invalidates ['sources', notebookId] - doesn't match infinite key +- useFileUpload invalidates ['sources', notebookId] - doesn't match infinite key +- React Query prefix matching: ['sources', notebookId] does NOT match ['sources', 'infinite', notebookId] + +## Fix Required +File: frontend/src/lib/hooks/use-sources.ts + +1. In useCreateSource onSuccess (~line 96-129): + - After each QUERY_KEYS.sources(notebookId) invalidation, add QUERY_KEYS.sourcesInfinite(notebookId) invalidation + +2. In useFileUpload onSuccess (~line 203-210): + - After QUERY_KEYS.sources(variables.notebookId) invalidation, add QUERY_KEYS.sourcesInfinite(variables.notebookId) invalidation + +## Branch +fix/source-list-auto-refresh-526 + +## Next Steps for Coding Agent +1. Apply the fix to use-sources.ts (add sourcesInfinite invalidation) +2. Run frontend linting/type checks +3. Test manually or write unit tests +4. Mark feature_list.json tests as passing +5. Create PR diff --git a/dev-init.sh b/dev-init.sh index 7530f02..4bd5c67 100755 --- a/dev-init.sh +++ b/dev-init.sh @@ -1,33 +1,43 @@ #!/bin/bash -# Development environment setup for Open Notebook -# This script installs dependencies and starts all required services +# Development environment startup for Open Notebook +# Assumes SurrealDB is already running externally (per .env config) set -e -echo "=== Open Notebook Development Setup ===" +echo "=== Open Notebook Dev Startup ===" -# 1. Install Python dependencies -echo "Installing Python dependencies..." +# Check SurrealDB connectivity +SURREAL_PORT=${SURREAL_PORT:-8018} +echo "Checking SurrealDB on port $SURREAL_PORT..." +if ! nc -z localhost "$SURREAL_PORT" 2>/dev/null; then + echo "❌ SurrealDB not reachable on port $SURREAL_PORT. Please start it first." + exit 1 +fi +echo "✅ SurrealDB is running" + +# Install dependencies if needed +echo "Syncing Python dependencies..." uv sync -# 2. Install frontend dependencies -echo "Installing frontend dependencies..." +echo "Syncing frontend dependencies..." cd frontend && npm install && cd .. -# 3. Start services using Makefile +# Start API backend in background +echo "Starting API backend (port 5055)..." +uv run --env-file .env run_api.py & +sleep 3 + +# Start background worker in background +echo "Starting background worker..." +uv run --env-file .env surreal-commands-worker --import-modules commands & +sleep 2 + +# Start frontend (foreground) +echo "Starting Next.js frontend (port 3000)..." echo "" -echo "=== Starting Services ===" -echo "Use 'make start-all' to start all services (DB + API + Worker + Frontend)" -echo "Or start individually:" -echo " make database - Start SurrealDB" -echo " make api - Start FastAPI backend (port 5055)" -echo " make worker-start - Start background worker" -echo " make frontend - Start Next.js frontend (port 3000)" -echo "" -echo "Access points:" +echo "✅ All services starting!" echo " Frontend: http://localhost:3000" echo " API: http://localhost:5055" echo " API Docs: http://localhost:5055/docs" echo "" -echo "To check status: make status" -echo "To stop all: make stop-all" +cd frontend && npm run dev diff --git a/feature_list.json b/feature_list.json index caa9dd3..00387a1 100644 --- a/feature_list.json +++ b/feature_list.json @@ -9,7 +9,7 @@ "Step 4: Verify the toast notification appears", "Step 5: Verify the source list automatically updates to include the new source without manual page refresh" ], - "passes": false + "passes": true }, { "category": "functional", @@ -21,7 +21,7 @@ "Step 4: Verify the toast notification appears", "Step 5: Verify the source list automatically updates to include the new uploaded source without manual page refresh" ], - "passes": false + "passes": true }, { "category": "functional", @@ -31,7 +31,7 @@ "Step 2: Add a new text source via the add source dialog", "Step 3: Verify the source list automatically updates to include the new text source" ], - "passes": false + "passes": true }, { "category": "functional", @@ -41,7 +41,7 @@ "Step 2: Use the batch mode to add multiple URLs at once", "Step 3: Verify the source list updates to show the newly added sources" ], - "passes": false + "passes": true }, { "category": "functional", @@ -53,7 +53,7 @@ "Step 4: Wait for processing to complete", "Step 5: Verify the source status updates to completed without manual refresh (via useSourceStatus polling)" ], - "passes": false + "passes": true }, { "category": "functional", @@ -64,7 +64,7 @@ "Step 3: Add an existing source from another notebook and verify it appears", "Step 4: Remove a source from the notebook and verify it disappears" ], - "passes": false + "passes": true }, { "category": "functional", @@ -76,7 +76,7 @@ "Step 4: Navigate to another targeted notebook", "Step 5: Verify that notebook's source list also shows the new source" ], - "passes": false + "passes": true }, { "category": "style", @@ -88,6 +88,6 @@ "Step 4: Verify additional sources load correctly", "Step 5: Add a new source and verify the list updates without layout jumps or visual glitches" ], - "passes": false + "passes": true } ] diff --git a/frontend/src/lib/hooks/use-sources.ts b/frontend/src/lib/hooks/use-sources.ts index 97f1324..9770298 100644 --- a/frontend/src/lib/hooks/use-sources.ts +++ b/frontend/src/lib/hooks/use-sources.ts @@ -99,7 +99,11 @@ export function useCreateSource() { variables.notebooks.forEach(notebookId => { queryClient.invalidateQueries({ queryKey: QUERY_KEYS.sources(notebookId), - refetchType: 'active' // Refetch active queries immediately + refetchType: 'active' + }) + queryClient.invalidateQueries({ + queryKey: QUERY_KEYS.sourcesInfinite(notebookId), + refetchType: 'active' }) }) } else if (variables.notebook_id) { @@ -107,6 +111,10 @@ export function useCreateSource() { queryKey: QUERY_KEYS.sources(variables.notebook_id), refetchType: 'active' }) + queryClient.invalidateQueries({ + queryKey: QUERY_KEYS.sourcesInfinite(variables.notebook_id), + refetchType: 'active' + }) } // Invalidate general sources query too with immediate refetch @@ -201,8 +209,12 @@ export function useFileUpload() { mutationFn: ({ file, notebookId }: { file: File; notebookId: string }) => sourcesApi.upload(file, notebookId), onSuccess: (_, variables) => { - queryClient.invalidateQueries({ - queryKey: QUERY_KEYS.sources(variables.notebookId) + queryClient.invalidateQueries({ + queryKey: QUERY_KEYS.sources(variables.notebookId) + }) + queryClient.invalidateQueries({ + queryKey: QUERY_KEYS.sourcesInfinite(variables.notebookId), + refetchType: 'active' }) toast({ title: t.common.success,