mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-14 20:55:15 +02:00
update
This commit is contained in:
parent
8bc092e40e
commit
f60ba3d01f
5 changed files with 885 additions and 0 deletions
|
|
@ -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)
|
||||
|
||||
328
_bmad-output/implementation-artifacts/1-6-settings-sync.md
Normal file
328
_bmad-output/implementation-artifacts/1-6-settings-sync.md
Normal file
|
|
@ -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<SearchSpace[]> {
|
||||
return apiClient.get('/api/v1/searchspaces');
|
||||
},
|
||||
|
||||
async fetchLLMPreferences(spaceId: number): Promise<LLMPreferences> {
|
||||
return apiClient.get(`/api/v1/search-spaces/${spaceId}/llm-preferences`);
|
||||
},
|
||||
|
||||
async fetchGlobalLLMConfigs(): Promise<LLMConfig[]> {
|
||||
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<SearchSpace[] | null> {
|
||||
return storage.get('searchSpaces');
|
||||
},
|
||||
|
||||
async saveSelectedSpaceId(id: number) {
|
||||
await storage.set('selectedSearchSpaceId', id);
|
||||
},
|
||||
|
||||
async getSelectedSpaceId(): Promise<number | null> {
|
||||
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)
|
||||
|
||||
88
_bmad-output/implementation-artifacts/sprint-status.yaml
Normal file
88
_bmad-output/implementation-artifacts/sprint-status.yaml
Normal file
|
|
@ -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"
|
||||
|
||||
143
surfsense_backend/nohup.out
Normal file
143
surfsense_backend/nohup.out
Normal file
|
|
@ -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]
|
||||
97
surfsense_web/nohup.out
Normal file
97
surfsense_web/nohup.out
Normal file
|
|
@ -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<string | null>(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 <DEA08FB5-0F64-35DA-947E-EADD3218E146> '/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 <DEA08FB5-0F64-35DA-947E-EADD3218E146> '/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
|
||||
Loading…
Add table
Add a link
Reference in a new issue