mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-28 23:15:33 +08:00
dc5d73936a881ffbcae1b95dbdcf13319e4ccafd
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
dc5d73936a |
refactor(projects): identify projects by DB projectId instead of folder-derived name
GET /api/projects used to scan ~/.claude/projects/ on every request, derive each project's identity from the encoded folder name, and re-parse JSONL files to build session lists. Using the folder-derived name as the project identifier leaked the Claude CLI's on-disk encoding into every API route, forced every downstream endpoint to re-resolve a real path via JSONL 'cwd' inspection, and made the project list endpoint O(projects x sessions) on disk I/O. This change switches the entire API surface to identify projects by the stable primary key from the 'projects' table and drives the listing straight from the DB: - Add projectsDb.getProjectPathById as the canonical projectId -> path resolver so routes no longer need to touch the filesystem to figure out where a project lives. - Rewrite getProjects so it reads the project list from the 'projects' table and the per-project session list from the 'sessions' table (one SELECT per project). No filesystem scanning happens for this endpoint anymore, which removes the dependency on ~/.claude/projects existing, on Cursor's MD5-hashed chat folders being discoverable, and on Codex's JSONL history being on disk. Per the migration spec each session now exposes 'summary' sourced from sessions.custom_name, 'messageCount' = 0 (message counting is not implemented), and sessionMeta.hasMore is pinned to false since this endpoint doesn't drive session pagination. - Introduce id-based wrappers (getSessionsById, renameProjectById, deleteSessionById, deleteProjectById, getProjectTaskMasterById) so every caller can pass projectId and resolve the real path through the DB. renameProjectById also writes to projects.custom_project_name so the DB-driven getProjects response reflects renames immediately; it keeps project-config.json in sync for any legacy reader that still consults the JSON file. - Migrate every /api/projects/:projectName route in server/index.js, server/routes/taskmaster.js, and server/routes/messages.js to :projectId, and change server/routes/git.js so the 'project' query/body parameter carries a projectId that is resolved through the DB before any git command runs. TaskMaster WebSocket broadcasts emit 'projectId' for the same reason so the frontend can match notifications against its current selection without another lookup. - Delete helpers that existed only to feed the old getProjects path (getCursorSessions, getGeminiCliSessions, getProjectTaskMaster) along with their unused imports (better-sqlite3's Database, applyCustomSessionNames). The legacy folder-name helpers (getSessions, renameProject, deleteSession, deleteProject, extractProjectDirectory) are kept as internal implementation details of the id-based wrappers and of destructive cleanup / conversation search, but they are no longer re-exported. - searchConversations still walks JSONL to produce match snippets (that data doesn't live in the DB), but it now includes the resolved projectId in each result so the sidebar can cross-reference hits with its already loaded project list without a second round-trip. Frontend migration: - Project.name is replaced by Project.projectId in src/types/app.ts, and ProjectSession.__projectName becomes __projectId so session tagging and sidebar state keys stay aligned with the backend identifier. Settings continues to use SettingsProject.name for legacy consumers, but it is populated from projectId by normalizeProjectForSettings. - All places that previously indexed per-project state by project.name (sidebar expanded/starred/loading/deletingProjects sets, additionalSessions map, projectHasMoreOverrides, starredProjects localStorage, command history and draft-input localStorage, TaskMaster caches) now key on projectId so state survives display-name edits and is consistent across the app. - src/utils/api.js renames every endpoint parameter to projectId, the unified messages endpoint takes projectId in its query string, and useSessionStore forwards projectId on fetchFromServer / fetchMore / refreshFromServer. Git panel, file tree, code editor, PRD editor, plugins context, MCP server flows and TaskMaster hooks are all updated to pass projectId. - DEFAULT_PROJECT_FOR_EMPTY_SHELL is updated to carry a 'default' projectId sentinel so the empty-shell placeholder still satisfies the Project contract. Bug fix bundled in: - sessionsDb.setName no longer bumps updated_at when a row already exists. Renaming is a label change, not activity, so there is no reason for it to reset 'last activity' in the sidebar. It also no longer relies on SQLite's CURRENT_TIMESTAMP, which stores a naive 'YYYY-MM-DD HH:MM:SS' value that JavaScript parses as local time and caused renamed sessions to appear shifted backwards by the client's UTC offset. When an INSERT actually happens it now writes ISO-8601 UTC with a 'Z' suffix. - buildSessionsByProviderFromDb normalizes any legacy naive timestamps in the sessions table to ISO-8601 UTC on the way out so rows written before this change also render correctly on the client. Other cleanup: - Removed the filesystem-first project-discovery comment block at the top of server/projects.js and replaced it with a short note that describes the new DB-driven flow and lists the few remaining filesystem-dependent helpers (message reads, search, destructive delete, manual project registration). - server/modules/providers/index.ts is added as a small barrel so the providers module exposes a stable public surface. Made-with: Cursor |
||
|
|
96463df8da |
Feature/backend ts support andunification of auth settings on frontend (#654)
* fix: remove project dependency from settings controller and onboarding * fix(settings): remove onClose prop from useSettingsController args * chore: tailwind classes order * refactor: move provider auth status management to custom hook * refactor: rename SessionProvider to LLMProvider * feat(frontend): support for @ alias based imports) * fix: replace init.sql with schema.js * fix: refactor database initialization to use schema.js for SQL statements * feat(server): add a real backend TypeScript build and enforce module boundaries The backend had started to grow beyond what the frontend-only tooling setup could support safely. We were still running server code directly from /server, linting mainly the client, and relying on path assumptions such as "../.." that only worked in the source layout. That created three problems: - backend alias imports were hard to resolve consistently in the editor, ESLint, and the runtime - server code had no enforced module boundary rules, so cross-module deep imports could bypass intended public entry points - building the backend into a separate output directory would break repo-level lookups for package.json, .env, dist, and public assets because those paths were derived from source-only relative assumptions This change makes the backend tooling explicit and runtime-safe. A dedicated backend TypeScript config now lives in server/tsconfig.json, with tsconfig.server.json reduced to a compatibility shim. This gives the language service and backend tooling a canonical project rooted in /server while still preserving top-level compatibility for any existing references. The backend alias mapping now resolves relative to /server, which avoids colliding with the frontend's "@/..." -> "src/*" mapping. The package scripts were updated so development runs through tsx with the backend tsconfig, build now produces a compiled backend in dist-server, and typecheck/lint cover both client and server. A new build-server.mjs script runs TypeScript and tsc-alias and cleans dist-server first, which prevents stale compiled files from shadowing current source files after refactors. To make the compiled backend behave the same as the source backend, runtime path resolution was centralized in server/utils/runtime-paths.js. Instead of assuming fixed relative paths from each module, server entry points now resolve the actual app root and server root at runtime. That keeps package.json, .env, dist, public, and default database paths stable whether code is executed from /server or from /dist-server/server. ESLint was expanded from a frontend-only setup into a backend-aware one. The backend now uses import resolution tied to the backend tsconfig so aliased imports resolve correctly in linting, import ordering matches the frontend style, and unused/duplicate imports are surfaced consistently. Most importantly, eslint-plugin-boundaries now enforces server module boundaries. Files under server/modules can no longer import another module's internals directly. Cross-module imports must go through that module's barrel file (index.ts/index.js). boundaries/no-unknown was also enabled so alias-resolution gaps cannot silently bypass the rule. Together, these changes make the backend buildable, keep runtime path resolution stable after compilation, align server tooling with the client where appropriate, and enforce a stricter modular architecture for server code. * fix: update package.json to include dist-server in files and remove tsconfig.server.json * refactor: remove build-server.mjs and inline its logic into package.json scripts * fix: update paths in package.json and bin.js to use dist-server directory * feat(eslint): add backend shared types and enforce compile-time contract for imports * fix(eslint): update shared types pattern --------- Co-authored-by: Haileyesus <something@gmail.com> |
||
|
|
e7d6c40452 |
Refactor WebSocket context + centralize platform flag (#363)
* fix: remove unnecessary websocket.js file and replace its usage directly in `WebSocketContext` * fix: connect() doesn't need to be async * fix: update WebSocket context import to use useWebSocket hook * fix: use `useRef` for WebSocketContext The main issue with using states was, previously the websocket never closed properly on unmount, so multiple connections could be opened. This was because the useEffect cleanup function was closing an old websocket (that was initialized to null) instead of the current one. We could have fixed this by adding `ws` to the useEffect dependency array, but this was unnecessary since `ws` doesn't affect rendering so we shouldn't use a state. * fix: replace `WebSocketContext` default value with null and add type definitions * fix: add type definition for WebSocket URL and remove redundant protocol declaration * fix: Prevent WebSocket reconnection attempts after unmount Right now, when the WebSocketContext component unmounts, there is still a pending reconnection attempt that tries to reconnect the WebSocket after 3 seconds. * refactor: Extract WebSocket URL construction into a separate function * refactor: Centralize platform mode detection using IS_PLATFORM constant; use `token` from Auth context in WebSocket connection * refactor: Use IS_PLATFORM constant for platform detection in authenticatedFetch function (backend) * refactor: move IS_PLATFORM to config file for both frontend and backend The reason we couldn't place it in shared/modelConstants.js is that the frontend uses Vite which requires import.meta.env for environment variables, while the backend uses process.env. Therefore, we created separate config files for the frontend (src/constants/config.ts) and backend (server/constants/config.js). * refactor: update import path for IS_PLATFORM constant to use config file * refactor: replace `messages` with `latestMessage` in WebSocket context and related components Why? Because, messages was only being used to access the latest message in the components it's used in. * refactor: optimize WebSocket connection handling with useCallback and useMemo * refactor: comment out debug log for render count in AppContent component * refactor(backend): update environment variable handling and replace VITE_IS_PLATFORM with IS_PLATFORM constant * refactor: update WebSocket connection effect to depend on token changes for reconnection --------- |