diff --git a/_bmad-output/implementation-artifacts/1-0-authentication-system.md b/_bmad-output/implementation-artifacts/1-0-authentication-system.md new file mode 100644 index 000000000..34e9addbc --- /dev/null +++ b/_bmad-output/implementation-artifacts/1-0-authentication-system.md @@ -0,0 +1,229 @@ +# Story 1.0: Hệ thống Xác thực (Authentication System) + +Status: ready-for-dev + +## Story + +**Là một** SurfSense user, +**Tôi muốn** đăng nhập vào extension với tài khoản SurfSense của tôi, +**Để** extension có thể đồng bộ settings, lịch sử chat, và truy cập backend APIs. + +## Acceptance Criteria + +### AC 1.0.1: User Login Flow +- **Given** user chưa đăng nhập vào extension +- **When** user click nút "Login" trong side panel header +- **Then** Chrome Identity API popup mở ra với tùy chọn Google OAuth +- **And** user hoàn tất quy trình OAuth +- **Then** extension nhận JWT token từ backend +- **And** extension chuyển hướng về side panel +- **And** avatar/email của user hiển thị trong header + +**Error Scenario:** +- **Given** user đang trong quy trình OAuth +- **When** OAuth thất bại (user hủy hoặc lỗi mạng) +- **Then** extension hiển thị error toast "Login failed. Please try again." +- **And** user vẫn ở trạng thái chưa xác thực + +### AC 1.0.2: JWT Token Management +- **Given** backend trả về JWT token (hết hạn sau 24 giờ - theo config hiện tại) +- **When** extension nhận được token +- **Then** extension lưu encrypted JWT trong Plasmo Storage +- **And** thời gian hết hạn của token được lưu + +**Auto-Refresh:** +- **Given** JWT token còn < 1 giờ là hết hạn +- **When** extension kiểm tra token expiry (mỗi 30 phút) +- **Then** extension gọi API `/auth/jwt/refresh` +- **And** extension cập nhật token đã lưu + +**Logout:** +- **Given** user click "Logout" trong settings dropdown +- **When** hành động logout được kích hoạt +- **Then** extension xóa JWT khỏi Plasmo Storage +- **And** user chuyển hướng về màn hình welcome/login + +### AC 1.0.3: Authenticated API Requests +- **Given** user đã đăng nhập (JWT đã lưu) +- **When** extension thực hiện API request +- **Then** request bao gồm header `Authorization: Bearer {JWT}` +- **And** backend xác thực JWT +- **And** request thành công với status 200 + +**Expired Token:** +- **Given** JWT token đã hết hạn +- **When** extension thực hiện API request +- **Then** backend trả về lỗi 401 Unauthorized +- **And** extension cố gắng auto-refresh +- **And** nếu refresh thành công, thử lại request ban đầu +- **And** nếu refresh thất bại, chuyển hướng user đến trang login + +### AC 1.0.4: Offline Handling +- **Given** user đã đăng nhập trước đó +- **And** user mất kết nối internet +- **When** extension cố gắng kết nối backend +- **Then** extension hiển thị chỉ báo "Offline" trong header +- **And** extension cache trạng thái auth gần nhất + +## Tasks / Subtasks + +- [ ] Task 1: Chrome Identity API Integration (AC: 1.0.1) + - [ ] 1.1 Tạo `lib/auth/chrome-identity.ts` - wrapper cho Chrome Identity API + - [ ] 1.2 Implement `launchWebAuthFlow` với backend OAuth URL + - [ ] 1.3 Handle OAuth callback và extract JWT từ redirect URL + - [ ] 1.4 Xử lý các error cases (user cancel, network error) + +- [ ] Task 2: JWT Token Manager (AC: 1.0.2) + - [ ] 2.1 Tạo `lib/auth/jwt-manager.ts` - quản lý JWT storage + - [ ] 2.2 Implement token encryption/decryption với Plasmo Storage + - [ ] 2.3 Implement token expiry checking và auto-refresh logic + - [ ] 2.4 Implement logout và clear token + +- [ ] Task 3: Authenticated API Client (AC: 1.0.3) + - [ ] 3.1 Tạo `lib/auth/api-client.ts` - HTTP client với auth headers + - [ ] 3.2 Implement request interceptor để inject Bearer token + - [ ] 3.3 Implement 401 response handler với auto-retry + - [ ] 3.4 Implement offline detection và caching + +- [ ] Task 4: Auth UI Components (AC: 1.0.1, 1.0.4) + - [ ] 4.1 Tạo `sidepanel/auth/LoginButton.tsx` - nút đăng nhập + - [ ] 4.2 Tạo `sidepanel/auth/UserProfile.tsx` - hiển thị avatar/email + - [ ] 4.3 Tạo `sidepanel/auth/AuthProvider.tsx` - React context cho auth state + - [ ] 4.4 Update `sidepanel/chat/ChatHeader.tsx` để integrate auth UI + +- [ ] Task 5: Integration Testing + - [ ] 5.1 Test OAuth flow end-to-end + - [ ] 5.2 Test token refresh mechanism + - [ ] 5.3 Test offline mode behavior + - [ ] 5.4 Test logout flow + +## Dev Notes + +### Backend Authentication (ALREADY EXISTS) +Backend đã có đầy đủ authentication system sử dụng `fastapi-users`: + +**Existing Endpoints:** +``` +POST /auth/jwt/login - Email/password login +POST /auth/jwt/logout - Logout +GET /auth/google/authorize - Google OAuth initiation +GET /auth/google/callback - Google OAuth callback +POST /auth/register - User registration +GET /verify-token - Verify JWT validity +GET /users/me - Get current user info +``` + +**JWT Configuration (từ `surfsense_backend/app/users.py`):** +- Secret: `config.SECRET_KEY` +- Lifetime: 24 giờ (`3600 * 24` seconds) +- Transport: Bearer token +- OAuth redirect: `{NEXT_FRONTEND_URL}/auth/callback?token={token}` + +### Extension Architecture Pattern + +**Plasmo Storage (đã có trong project):** +```typescript +import { Storage } from "@plasmohq/storage"; +const storage = new Storage({ area: "local" }); +``` + +**Chrome Identity API:** +```typescript +chrome.identity.launchWebAuthFlow({ + url: `${BACKEND_URL}/auth/google/authorize`, + interactive: true, +}, (redirectUrl) => { + // Extract JWT from redirect URL + const url = new URL(redirectUrl); + const token = url.searchParams.get('token'); +}); +``` + +### Critical Implementation Details + +**1. OAuth Flow cho Extension:** +- Backend hiện redirect về `{NEXT_FRONTEND_URL}/auth/callback?token={token}` +- Extension cần sử dụng Chrome Identity API với custom redirect +- Có thể cần thêm endpoint mới hoặc config cho extension redirect + +**2. Token Storage Security:** +- KHÔNG lưu plaintext JWT +- Sử dụng encryption trước khi lưu vào Plasmo Storage +- Xem xét sử dụng `chrome.storage.session` cho sensitive data + +**3. CORS Configuration:** +Backend đã có CORS cho localhost, cần thêm extension origin: +```python +# surfsense_backend/app/app.py - line 74-81 +allowed_origins.extend([ + "chrome-extension://*", # Cần thêm +]) +``` + +### Project Structure Notes + +**Files cần tạo mới:** +``` +surfsense_browser_extension/ +├── lib/ +│ └── auth/ +│ ├── chrome-identity.ts # Chrome Identity API wrapper +│ ├── jwt-manager.ts # JWT storage & refresh +│ └── api-client.ts # Authenticated HTTP client +└── sidepanel/ + └── auth/ + ├── LoginButton.tsx # Login UI component + ├── UserProfile.tsx # User avatar/menu + └── AuthProvider.tsx # Auth context provider +``` + +**Files cần modify:** +- `sidepanel/chat/ChatHeader.tsx` - Thêm auth UI +- `sidepanel/index.tsx` - Wrap với AuthProvider +- `background/index.ts` - Handle auth messages (nếu cần) + +### Dependencies + +**Existing (không cần cài thêm):** +- `@plasmohq/storage` - Đã có +- `react`, `react-dom` - Đã có +- `lucide-react` - Đã có (cho icons) + +**Backend Dependencies (đã có):** +- `fastapi-users` - Authentication framework +- `httpx-oauth` - Google OAuth client +- `python-jose` - JWT handling + +### Security Considerations + +1. **KHÔNG** lưu API keys trong extension code +2. Mã hóa JWT trước khi lưu vào storage +3. Sử dụng HTTPS cho tất cả API calls +4. Validate JWT signature trên backend (đã có) +5. Implement CSRF protection cho OAuth flow + +### References + +- [Source: surfsense_backend/app/users.py] - JWT strategy, OAuth config +- [Source: surfsense_backend/app/app.py#L91-160] - Auth routes registration +- [Source: _bmad-epics/epic-1-ai-powered-crypto-assistant.md#Story-1.0] - Full requirements +- [Source: _bmad-output/architecture-extension.md] - Extension architecture +- [Source: _bmad-output/architecture-backend.md] - Backend auth flow + +## Dev Agent Record + +### Agent Model Used +{{agent_model_name_version}} + +### Completion Notes List +- Story created: 2026-02-04 +- Backend auth system already exists and is fully functional +- Extension needs new auth layer to integrate with existing backend +- P0 BLOCKER - This story blocks all sync features (Settings, Chat, Capture) + +### Debug Log References +(To be filled during implementation) + +### File List +(To be filled during implementation) + diff --git a/_bmad-output/implementation-artifacts/1-6-settings-sync.md b/_bmad-output/implementation-artifacts/1-6-settings-sync.md new file mode 100644 index 000000000..bd58de494 --- /dev/null +++ b/_bmad-output/implementation-artifacts/1-6-settings-sync.md @@ -0,0 +1,328 @@ +# Story 1.6: Đồng bộ Cài đặt (Settings Sync) với Frontend + +Status: ready-for-dev + +## Story + +**Là một** SurfSense user, +**Tôi muốn** extension sử dụng cùng model và search space như web dashboard, +**Để** tôi không phải cấu hình lại. + +## Dependencies + +- **REQUIRES:** Story 1.0 (Authentication System) - Must be completed first +- Extension must have valid JWT token to call backend APIs + +## Acceptance Criteria + +### AC 1.6.1: Hiển thị Dropdown Cài đặt +- **Given** user đã đăng nhập +- **When** user click icon ⚙️ trong header +- **Then** settings dropdown mở ra +- **And** dropdown hiển thị: + - Current model: "GPT-4 Turbo" (chỉ xem, bị mờ) + - Current search space: "Crypto Research" (chỉ xem, bị mờ) + - Links đến web dashboard: + - "🔗 Manage Connectors" + - "💬 View All Chats" + - "⚙️ Full Settings" + - Nút "🚪 Logout" + +### AC 1.6.2: Đồng bộ Cài đặt khi Đăng nhập +- **Given** user hoàn tất đăng nhập +- **When** nhận được JWT token +- **Then** extension gọi `GET /api/v1/searchspaces` để lấy danh sách search spaces +- **And** extension gọi `GET /api/v1/search-spaces/{id}/llm-preferences` để lấy LLM config +- **And** settings được lưu trong Plasmo Storage +- **And** settings hiển thị trong dropdown + +**Response Format (từ backend):** +```json +// GET /api/v1/searchspaces +[ + { + "id": 1, + "name": "Crypto Research", + "description": "...", + "agent_llm_id": 0, + "document_summary_llm_id": 0 + } +] + +// GET /api/v1/search-spaces/{id}/llm-preferences +{ + "agent_llm_id": 0, + "document_summary_llm_id": 0, + "agent_llm": { + "id": 0, + "name": "Auto (Load Balanced)", + "provider": "AUTO", + "model_name": "auto" + } +} +``` + +### AC 1.6.3: Tự động cập nhật Cài đặt +- **Given** user thay đổi model trên web dashboard +- **When** extension phát hiện thay đổi (qua polling) +- **Then** extension lấy settings đã cập nhật +- **And** dropdown phản ánh model mới +- **And** các cuộc chat tiếp theo sử dụng model mới + +**Polling:** +- **Given** extension đang hoạt động +- **When** mỗi 5 phút +- **Then** extension polls `GET /api/v1/searchspaces` và LLM preferences + +### AC 1.6.4: Search Space Selector +- **Given** user có nhiều search spaces +- **When** user click vào search space selector trong header +- **Then** dropdown hiển thị tất cả search spaces của user +- **And** user có thể chọn search space khác +- **And** extension lưu selection vào Plasmo Storage +- **And** các API calls tiếp theo sử dụng search_space_id mới + +### AC 1.6.5: Offline Handling +- **Given** user đã đăng nhập và có settings đã cache +- **When** user mất kết nối internet +- **Then** extension sử dụng settings đã cache +- **And** hiển thị indicator "Using cached settings" +- **When** kết nối được khôi phục +- **Then** extension sync settings mới từ backend + +## Tasks / Subtasks + +- [ ] Task 1: Settings Service (AC: 1.6.2, 1.6.3) + - [ ] 1.1 Tạo `lib/settings/settings-service.ts` - API calls cho settings + - [ ] 1.2 Implement `fetchSearchSpaces()` - GET /api/v1/searchspaces + - [ ] 1.3 Implement `fetchLLMPreferences(spaceId)` - GET LLM config + - [ ] 1.4 Implement polling mechanism (5 phút interval) + - [ ] 1.5 Implement settings caching trong Plasmo Storage + +- [ ] Task 2: Settings State Management (AC: 1.6.1, 1.6.4) + - [ ] 2.1 Tạo `lib/settings/settings-store.ts` - Zustand/Context store + - [ ] 2.2 Define settings types và interfaces + - [ ] 2.3 Implement search space selection logic + - [ ] 2.4 Implement settings sync on login + +- [ ] Task 3: Settings UI Components (AC: 1.6.1, 1.6.4) + - [ ] 3.1 Update `sidepanel/chat/ChatHeader.tsx` - Integrate real settings + - [ ] 3.2 Tạo `sidepanel/settings/SettingsDropdown.tsx` - Enhanced dropdown + - [ ] 3.3 Tạo `sidepanel/settings/SearchSpaceSelector.tsx` - Space picker + - [ ] 3.4 Tạo `sidepanel/settings/ModelDisplay.tsx` - Read-only model info + +- [ ] Task 4: Integration với Auth (AC: 1.6.2, 1.6.5) + - [ ] 4.1 Hook settings fetch vào auth flow (sau login thành công) + - [ ] 4.2 Implement offline detection và fallback + - [ ] 4.3 Clear settings on logout + - [ ] 4.4 Handle 401 errors (redirect to login) + +- [ ] Task 5: Testing + - [ ] 5.1 Test settings sync sau login + - [ ] 5.2 Test polling mechanism + - [ ] 5.3 Test search space switching + - [ ] 5.4 Test offline mode với cached settings + +## Dev Notes + +### Backend APIs (ALREADY EXISTS) + +Backend đã có đầy đủ APIs cho settings: + +**Search Spaces:** +``` +GET /api/v1/searchspaces - List all user's search spaces +POST /api/v1/searchspaces - Create new search space +GET /api/v1/searchspaces/{id} - Get single search space +PUT /api/v1/searchspaces/{id} - Update search space +DELETE /api/v1/searchspaces/{id} - Delete search space +``` + +**LLM Preferences:** +``` +GET /api/v1/search-spaces/{id}/llm-preferences - Get LLM config for space +PUT /api/v1/search-spaces/{id}/llm-preferences - Update LLM config +``` + +**Global LLM Configs:** +``` +GET /api/v1/global-new-llm-configs - List available LLM models +``` + +### Existing Extension Code + +**ChatHeader.tsx (đã có UI cơ bản):** +- Search space selector dropdown (hardcoded data) +- Settings dropdown với menu items +- User avatar với logout +- Token search bar + +**Cần update:** +- Replace hardcoded search spaces với real data từ API +- Add model display trong settings dropdown +- Connect logout button với auth service + +### Data Types + +**SearchSpace (từ backend):** +```typescript +interface SearchSpace { + id: number; + name: string; + description?: string; + user_id: string; + agent_llm_id: number; + document_summary_llm_id: number; + created_at: string; +} +``` + +**LLMPreferences (từ backend):** +```typescript +interface LLMPreferences { + agent_llm_id: number; + document_summary_llm_id: number; + agent_llm?: LLMConfig; + document_summary_llm?: LLMConfig; +} + +interface LLMConfig { + id: number; + name: string; + provider: string; + model_name: string; + is_global?: boolean; + is_auto_mode?: boolean; +} +``` + +### Project Structure Notes + +**Files cần tạo mới:** +``` +surfsense_browser_extension/ +├── lib/ +│ └── settings/ +│ ├── settings-service.ts # API calls +│ ├── settings-store.ts # State management +│ └── types.ts # TypeScript interfaces +└── sidepanel/ + └── settings/ + ├── SettingsDropdown.tsx # Enhanced dropdown + ├── SearchSpaceSelector.tsx # Space picker + └── ModelDisplay.tsx # Read-only model info +``` + +**Files cần modify:** +- `sidepanel/chat/ChatHeader.tsx` - Integrate real settings data +- `sidepanel/index.tsx` - Add SettingsProvider +- `lib/auth/api-client.ts` - Add settings endpoints (từ Story 1.0) + +### Implementation Pattern + +**Settings Service:** +```typescript +// lib/settings/settings-service.ts +import { apiClient } from '../auth/api-client'; + +export const settingsService = { + async fetchSearchSpaces(): Promise { + return apiClient.get('/api/v1/searchspaces'); + }, + + async fetchLLMPreferences(spaceId: number): Promise { + return apiClient.get(`/api/v1/search-spaces/${spaceId}/llm-preferences`); + }, + + async fetchGlobalLLMConfigs(): Promise { + return apiClient.get('/api/v1/global-new-llm-configs'); + } +}; +``` + +**Settings Store (Plasmo Storage):** +```typescript +// lib/settings/settings-store.ts +import { Storage } from "@plasmohq/storage"; + +const storage = new Storage({ area: "local" }); + +export const settingsStore = { + async saveSearchSpaces(spaces: SearchSpace[]) { + await storage.set('searchSpaces', spaces); + }, + + async getSearchSpaces(): Promise { + return storage.get('searchSpaces'); + }, + + async saveSelectedSpaceId(id: number) { + await storage.set('selectedSearchSpaceId', id); + }, + + async getSelectedSpaceId(): Promise { + return storage.get('selectedSearchSpaceId'); + } +}; +``` + +### Polling Implementation + +```typescript +// Polling every 5 minutes +const POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes + +useEffect(() => { + const pollSettings = async () => { + try { + const spaces = await settingsService.fetchSearchSpaces(); + await settingsStore.saveSearchSpaces(spaces); + + const selectedId = await settingsStore.getSelectedSpaceId(); + if (selectedId) { + const prefs = await settingsService.fetchLLMPreferences(selectedId); + await settingsStore.saveLLMPreferences(prefs); + } + } catch (error) { + console.error('Settings poll failed:', error); + } + }; + + const interval = setInterval(pollSettings, POLLING_INTERVAL); + return () => clearInterval(interval); +}, []); +``` + +### Security Considerations + +1. Settings API calls require valid JWT (handled by api-client) +2. Cache settings locally for offline access +3. Clear cached settings on logout +4. Handle 401 errors gracefully (redirect to login) + +### References + +- [Source: surfsense_backend/app/routes/search_spaces_routes.py] - Search space APIs +- [Source: surfsense_backend/app/routes/new_llm_config_routes.py] - LLM config APIs +- [Source: surfsense_browser_extension/sidepanel/chat/ChatHeader.tsx] - Existing UI +- [Source: _bmad-epics/epic-1-ai-powered-crypto-assistant.md#Story-1.6] - Full requirements +- [Source: _bmad-output/implementation-artifacts/1-0-authentication-system.md] - Auth dependency + +## Dev Agent Record + +### Agent Model Used +{{agent_model_name_version}} + +### Completion Notes List +- Story created: 2026-02-04 +- Backend APIs already exist and are fully functional +- Extension UI partially exists (ChatHeader.tsx has basic structure) +- DEPENDS ON Story 1.0 (Authentication) - must complete auth first +- Settings are read-only in extension (changes made via web dashboard) + +### Debug Log References +(To be filled during implementation) + +### File List +(To be filled during implementation) + diff --git a/_bmad-output/implementation-artifacts/sprint-status.yaml b/_bmad-output/implementation-artifacts/sprint-status.yaml new file mode 100644 index 000000000..0722f5c3d --- /dev/null +++ b/_bmad-output/implementation-artifacts/sprint-status.yaml @@ -0,0 +1,88 @@ +# Sprint Status - SurfSense Crypto Co-Pilot +# Generated: 2026-02-04 +# +# STATUS DEFINITIONS: +# - backlog: Story not yet started, waiting in queue +# - ready-for-dev: Story file created with full context, ready for development +# - in-progress: Development actively underway +# - review: Code complete, awaiting review +# - done: Story completed and verified +# +# EPIC STATUS: +# - backlog: Epic not started +# - in-progress: At least one story in progress +# - done: All stories completed + +project: SurfSense 2.0 - Crypto Co-Pilot +sprint: Sprint 1 - Core Infrastructure +start_date: 2026-02-04 + +development_status: + # Epic 1: AI-Powered Crypto Assistant (Phase 1) + epic-1: in-progress + + # Story 1.0 - Authentication System (P0 BLOCKER) + 1-0-authentication-system: in-progress + + # Stories 1.1-1.9 - Already completed (frontend only) + # These are marked done for frontend, but need backend integration + 1-1-side-panel-architecture: done + 1-2-ai-chat-interface: done + 1-3-page-context-detection: done + 1-4-dexscreener-integration: done + 1-5-quick-capture: done + 1-6-settings-sync: ready-for-dev # Depends on 1-0-authentication-system + 1-7-universal-token-search: done + 1-8-multi-page-token-detection: done + 1-9-floating-quick-action: done + + # Epic 1 Retrospective + epic-1-retrospective: backlog + + # Epic 2: Smart Monitoring & Alerts (Phase 2) + epic-2: backlog + 2-1-realtime-price-alerts: backlog + 2-2-whale-activity-tracker: backlog + 2-3-rug-pull-warning: backlog + epic-2-retrospective: backlog + + # Epic 3: Trading Intelligence (Phase 3) + epic-3: backlog + 3-1-one-click-token-analysis: backlog + 3-2-smart-entry-exit: backlog + 3-3-portfolio-tracker: backlog + epic-3-retrospective: backlog + + # Epic 4: Content Creation & Productivity (Phase 4) + epic-4: backlog + 4-1-chart-screenshot: backlog + 4-2-ai-thread-generator: backlog + 4-3-quick-actions-context-menu: done + 4-4-smart-notifications: backlog + 4-5-keyboard-shortcuts: done + epic-4-retrospective: backlog + +# Priority Queue (next stories to work on) +priority_queue: + - 1-0-authentication-system # P0 BLOCKER - Must complete first + - 1-6-settings-sync # Depends on 1-0 + - 2-1-realtime-price-alerts # Phase 2 start + +# Blockers +blockers: + - id: BLOCK-001 + description: "Backend authentication APIs need extension-specific OAuth redirect" + affects: ["1-0-authentication-system"] + status: open + + - id: BLOCK-002 + description: "DexScreener API integration needed for real data" + affects: ["2-1-realtime-price-alerts", "2-2-whale-activity-tracker"] + status: open + +# Notes +notes: + - "Frontend UI for all epics is 100% complete" + - "Backend APIs are the main blocker" + - "Story 1.0 (Auth) is critical path - blocks all sync features" + diff --git a/surfsense_backend/nohup.out b/surfsense_backend/nohup.out new file mode 100644 index 000000000..fd098598f --- /dev/null +++ b/surfsense_backend/nohup.out @@ -0,0 +1,143 @@ +INFO: Will watch for changes in these directories: ['/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend'] +INFO: Uvicorn running on http://0.0.0.0:3998 (Press CTRL+C to quit) +INFO: Started reloader process [6491] using WatchFiles +/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/chonkie/chunker/code.py:82: UserWarning: The language is set to `auto`. This would adversely affect the performance of the chunker. Consider setting the `language` parameter to a specific language to improve performance. + warnings.warn("The language is set to `auto`. This would adversely affect the performance of the chunker. " + +INFO: Started server process [6495] +INFO: Waiting for application startup. +ERROR: Traceback (most recent call last): + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/starlette/routing.py", line 694, in lifespan + async with self.lifespan_context(app) as maybe_state: + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 153, in merged_lifespan + async with original_context(app) as maybe_original_state: + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/app/app.py", line 23, in lifespan + await create_db_and_tables() + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/app/db.py", line 1386, in create_db_and_tables + async with engine.begin() as conn: + ^^^^^^^^^^^^^^ + File "/Users/mac_1/.local/share/uv/python/cpython-3.12.9-macos-aarch64-none/lib/python3.12/contextlib.py", line 210, in __aenter__ + return await anext(self.gen) + ^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 1066, in begin + async with conn: + ^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/base.py", line 121, in __aenter__ + return await self.start(is_ctxmanager=True) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 274, in start + await greenlet_spawn(self.sync_engine.connect) + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 201, in greenlet_spawn + result = context.throw(*sys.exc_info()) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3273, in connect + return self._connection_cls(self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 145, in __init__ + self._dbapi_connection = engine.raw_connection() + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3297, in raw_connection + return self.pool.connect() + ^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 449, in connect + return _ConnectionFairy._checkout(self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 1264, in _checkout + fairy = _ConnectionRecord.checkout(pool) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 713, in checkout + rec = pool._do_get() + ^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 179, in _do_get + with util.safe_reraise(): + ^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 177, in _do_get + return self._create_connection() + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 390, in _create_connection + return _ConnectionRecord(self) + ^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 675, in __init__ + self.__connect() + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 901, in __connect + with util.safe_reraise(): + ^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__ + raise exc_value.with_traceback(exc_tb) + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 897, in __connect + self.dbapi_connection = connection = pool._invoke_creator(self) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/create.py", line 646, in connect + return dialect.connect(*cargs, **cparams) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 625, in connect + return self.loaded_dbapi.connect(*cargs, **cparams) # type: ignore[no-any-return] # NOQA: E501 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 961, in connect + await_only(creator_fn(*arg, **kw)), + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only + return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn + value = await result + ^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connection.py", line 2421, in connect + return await connect_utils._connect( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1075, in _connect + raise last_error or exceptions.TargetServerAttributeNotMatched( + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1049, in _connect + conn = await _connect_addr( + ^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 882, in _connect_addr + return await __connect_addr(params, False, *args) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/Users/mac_1/Documents/GitHub/SurfSense/surfsense_backend/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 931, in __connect_addr + tr, pr = await connector + ^^^^^^^^^^^^^^^ + File "uvloop/loop.pyx", line 2043, in create_connection + File "uvloop/loop.pyx", line 2020, in uvloop.loop.Loop.create_connection +ConnectionRefusedError: [Errno 61] Connection refused + +ERROR: Application startup failed. Exiting. +INFO: Stopping reloader process [6491] diff --git a/surfsense_web/nohup.out b/surfsense_web/nohup.out new file mode 100644 index 000000000..66f54e83b --- /dev/null +++ b/surfsense_web/nohup.out @@ -0,0 +1,97 @@ + +> surfsense_web@0.0.12 dev /Users/mac_1/Documents/GitHub/SurfSense/surfsense_web +> next dev --turbopack -p 3999 + +▲ Next.js 16.1.0 (Turbopack) +- Local: http://localhost:3999 +- Network: http://10.56.57.248:3999 +- Environments: .env + +✓ Starting... +[MDX] generated files in 21.16537500000004ms +[MDX] started dev server +✓ Ready in 2.3s + GET / 200 in 1750ms (compile: 1438ms, render: 313ms) + GET / 200 in 71ms (compile: 5ms, render: 66ms) + GET /dashboard/%7Bid%7D/new-chat 200 in 1979ms (compile: 1630ms, render: 349ms) +Error: ENVIRONMENT_FALLBACK: There is no `timeZone` configured, this can lead to markup mismatches caused by environment differences. Consider adding a global default: https://next-intl.dev/docs/configuration#time-zone + at LoginContent (app/(home)/login/page.tsx:17:27) + 15 | + 16 | function LoginContent() { +> 17 | const t = useTranslations("auth"); + | ^ + 18 | const tCommon = useTranslations("common"); + 19 | const [authType, setAuthType] = useState(null); + 20 | const [isLoading, setIsLoading] = useState(true); { + code: 'ENVIRONMENT_FALLBACK', + originalMessage: 'There is no `timeZone` configured, this can lead to markup mismatches caused by environment differences. Consider adding a global default: https://next-intl.dev/docs/configuration#time-zone' +} + GET /login 200 in 196ms (compile: 77ms, render: 119ms) + GET / 200 in 83ms (compile: 7ms, render: 76ms) + GET / 200 in 61ms (compile: 6ms, render: 55ms) + GET /login 200 in 56ms (compile: 8ms, render: 48ms) + GET / 200 in 90ms (compile: 21ms, render: 69ms) + GET /login 200 in 53ms (compile: 20ms, render: 34ms) + GET /login 200 in 79ms (compile: 8ms, render: 71ms) + GET /auth/callback?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxOTUxYzAxMC00MzZmLTQ2MzYtODljYS01ZDg2ZjU3OTUxZGYiLCJhdWQiOlsiZmFzdGFwaS11c2VyczphdXRoIl0sImV4cCI6MTc3MDg3MDY3M30.O28yYMtWQuLeYdjEn2SpHGBSEzp8gzhyCnNTY4deQF4 200 in 59ms (compile: 32ms, render: 27ms) + GET /dashboard/%7Bid%7D/new-chat 200 in 64ms (compile: 11ms, render: 53ms) + GET /dashboard/%7Bid%7D/new-chat 200 in 60ms (compile: 11ms, render: 49ms) + GET /dashboard/%7Bid%7D/crypto 200 in 568ms (compile: 544ms, render: 24ms) + GET /dashboard/%7Bid%7D/new-chat 200 in 33ms (compile: 11ms, render: 23ms) + GET /dashboard/%7Bid%7D/new-chat?query=Analyze+BULLA 200 in 25ms (compile: 7ms, render: 18ms) + GET / 200 in 75ms (compile: 5ms, render: 70ms) + GET /login 200 in 53ms (compile: 6ms, render: 47ms) + GET /auth/callback?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxOTUxYzAxMC00MzZmLTQ2MzYtODljYS01ZDg2ZjU3OTUxZGYiLCJhdWQiOlsiZmFzdGFwaS11c2VyczphdXRoIl0sImV4cCI6MTc3MDg3MTQxMn0.HscRbBjnqK86Bppg8IFq5OMgxOJppOosPXKtFJjQ2X0 200 in 28ms (compile: 6ms, render: 22ms) + GET /dashboard 200 in 233ms (compile: 28ms, render: 205ms) + GET /dashboard/7/new-chat 200 in 33ms (compile: 9ms, render: 24ms) + GET /dashboard/7/documents 200 in 784ms (compile: 757ms, render: 27ms) + GET /dashboard/7/documents 200 in 21ms (compile: 7ms, render: 15ms) + GET /dashboard/7/new-chat 200 in 61ms (compile: 11ms, render: 50ms) + GET /dashboard/7/new-chat 200 in 32ms (compile: 10ms, render: 22ms) + GET /dashboard/7/new-chat/19 200 in 29ms (compile: 8ms, render: 22ms) + GET /dashboard/7/new-chat/19 200 in 42ms (compile: 16ms, render: 27ms) + GET /dashboard/7/crypto 200 in 26ms (compile: 8ms, render: 18ms) + GET /dashboard/7/crypto 200 in 31ms (compile: 13ms, render: 18ms) + GET /dashboard/7/crypto 200 in 20ms (compile: 5ms, render: 14ms) + GET /dashboard/7/crypto 200 in 16ms (compile: 3ms, render: 13ms) + GET /dashboard/7/crypto 200 in 20ms (compile: 3ms, render: 17ms) + GET /dashboard/7/new-chat/19 200 in 65ms (compile: 13ms, render: 52ms) + GET /dashboard/7/documents 200 in 31ms (compile: 9ms, render: 22ms) + GET /dashboard/7/documents 200 in 40ms (compile: 19ms, render: 21ms) + GET /dashboard/7/crypto 200 in 28ms (compile: 8ms, render: 20ms) + GET /dashboard/7/new-chat/19 200 in 32ms (compile: 10ms, render: 21ms) + GET /dashboard/7/documents 200 in 28ms (compile: 10ms, render: 17ms) + GET /dashboard/7/crypto 200 in 35ms (compile: 12ms, render: 22ms) + GET /dashboard/7/logs 200 in 490ms (compile: 470ms, render: 20ms) + GET /dashboard/7 200 in 458ms (compile: 412ms, render: 46ms) + GET /dashboard/7/new-chat 200 in 35ms (compile: 8ms, render: 27ms) + GET /dashboard/%7Bid%7D/new-chat?query=Analyze+BULLA 200 in 115ms (compile: 33ms, render: 82ms) + GET / 200 in 76ms (compile: 7ms, render: 70ms) + GET /dashboard/7/new-chat/19 200 in 104ms (compile: 13ms, render: 91ms) + GET /login 200 in 55ms (compile: 6ms, render: 49ms) + GET /dashboard/7/new-chat 200 in 57ms (compile: 18ms, render: 39ms) + GET /login 200 in 51ms (compile: 4ms, render: 48ms) + GET /login 200 in 87ms (compile: 34ms, render: 54ms) +[MDX] closing dev server + Downloading swc package @next/swc-wasm-nodejs... to /Users/mac_1/Library/Caches/next-swc +npm warn Unknown env config "network-timeout". This will stop working in the next major version of npm. +npm warn Unknown env config "allow-build-scripts". This will stop working in the next major version of npm. +npm warn Unknown env config "verify-deps-before-run". This will stop working in the next major version of npm. +npm warn Unknown env config "_jsr-registry". This will stop working in the next major version of npm. +npm warn Unknown env config "_windsurf-registry". This will stop working in the next major version of npm. +npm warn Unknown env config "enable-pre-post-scripts". This will stop working in the next major version of npm. +npm warn Unknown env config "store-dir". This will stop working in the next major version of npm. +npm warn Unknown env config "cache-dir". This will stop working in the next major version of npm. +⚠ Attempted to load @next/swc-darwin-arm64, but an error occurred: dlopen(/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node, 0x0001): tried: '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (code signature in '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' not valid for use in process: library load denied by system policy), '/System/Volumes/Preboot/Cryptexes/OS/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (no such file), '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' (code signature in '/Users/mac_1/Documents/GitHub/SurfSense/surfsense_web/node_modules/.pnpm/@next+swc-darwin-arm64@16.1.0/node_modules/@next/swc-darwin-arm64/next-swc.darwin-arm64.node' not valid for use in process: library load denied by system policy) +⚠ TypeError: fetch failed + at ignore-listed frames { + [cause]: Error: getaddrinfo ENOTFOUND registry.npmjs.org + at ignore-listed frames { + errno: -3008, + code: 'ENOTFOUND', + syscall: 'getaddrinfo', + hostname: 'registry.npmjs.org' + } +} +⨯ Failed to load SWC binary for darwin/arm64, see more info here: https://nextjs.org/docs/messages/failed-loading-swc +[?25h