Commit Graph

123 Commits

Author SHA1 Message Date
Haileyesus
f891316ec0 Refactor/app content main content and chat interface (#374)
* feat: improve version comparison logic in useVersionCheck hook

* refactor: useVersionCheck.js to typescript

* refactor: move VersionUpgradeModal component to its own file and remove it from AppContent component

* refactor: improve VersionUpgradeModal props and extract ReleaseInfo type

Using useVersionCheck hook in 2 places caused github requests to be made twice, which is not ideal.

* refactor: handleUpdateNow function with useCallback and error display in VersionUpgradeModal

* refactor: move isOpen check to the correct position in VersionUpgradeModal

* refactor: move VersionUpgradeModal and collapsed sidebar to Sidebar component from App.jsx

* refactor: remove unused SettingsIcon import from App.jsx

* refactor: move formatTimeAgo function to dateUtils.ts

* refactor: replace useLocalStorage with useUiPreferences for better state management in AppContent

* refactor: use shared props for Sidebar props in AppContent

* refactor: remove showQuickSettings state and toggle from AppContent, manage isOpen state directly in QuickSettingsPanel

* refactor: move preference props directly to QuickSettingsPanel and MainContent

* refactor: remove unused isPWA prop

* refactor: remove unused isPWA prop from AppContent

* refactor: remove unused generatingSummary state from Sidebar component

* refactor: remove unused isPWA prop from MainContent component

* refactor: use usePrefrences for sidebar visibility in Sidebar component

* refactor: extract device detection into hook and localize PWA handling to Sidebar

- Add new `useDeviceSettings` hook (`src/hooks/useDeviceSettings.ts`) to centralize
  device-related state:
  - exposes `isMobile` and `isPWA`
  - supports options: `mobileBreakpoint`, `trackMobile`, `trackPWA`
  - listens to window resize for mobile updates
  - listens to `display-mode: standalone` changes for PWA updates
  - includes `matchMedia.addListener/removeListener` fallback for older environments

- Update `AppContent` (`src/App.jsx`) to consume `isMobile` from
  `useDeviceSettings({ trackPWA: false })`:
  - remove local `isMobile` state/effect
  - remove local `isPWA` state/effect
  - keep existing `isMobile` behavior for layout and mobile sidebar flow
  - stop passing `isPWA` into `Sidebar` props

- Update `Sidebar` (`src/components/Sidebar.jsx`) to own PWA detection:
  - consume `isPWA` from `useDeviceSettings({ trackMobile: false })`
  - add effect to toggle `pwa-mode` class on `document.documentElement` and `document.body`
  - retain use of `isMobile` prop from `App` for sidebar/mobile rendering decisions

Why:
- removes duplicated device-detection logic from `AppContent`
- makes device-state logic reusable and easier to maintain
- keeps PWA-specific behavior where it is actually used (`Sidebar`)

* chore(to-remove): comment todo's

* refactor: remove unused createNewProject and cancelNewProject functions from Sidebar component

* refactor(sidebar): extract typed app/sidebar architecture and split Sidebar into modular components

- Replace `src/App.jsx` with `src/App.tsx` and move route-level UI orchestration into `src/components/app/AppContent.tsx`.
  This separates provider/bootstrap concerns from runtime app layout logic, keeps route definitions minimal, and improves readability of the root app entry.

- Introduce `src/hooks/useProjectsState.ts` to centralize project/session/sidebar state management previously embedded in `App.jsx`.
  This keeps the existing behavior for:
  project loading,
  Cursor session hydration,
  WebSocket `loading_progress` handling,
  additive-update protection for active sessions,
  URL-based session selection,
  sidebar refresh/delete/new-session flows.
  The hook now exposes a typed `sidebarSharedProps` contract and typed handlers used by `AppContent`.

- Introduce `src/hooks/useSessionProtection.ts` for active/processing session lifecycle logic.
  This preserves session-protection behavior while isolating `activeSessions`, `processingSessions`, and temporary-session replacement into a dedicated reusable hook.

- Replace monolithic `src/components/Sidebar.jsx` with typed `src/components/Sidebar.tsx` as a thin orchestrator.
  `Sidebar.tsx` now focuses on wiring controller state/actions, modal visibility, collapsed mode, and version modal behavior instead of rendering every UI branch inline.

- Add `src/hooks/useSidebarController.ts` to encapsulate sidebar interaction/state logic.
  This includes expand/collapse state, inline project/session editing state, project starring/sorting/filtering, lazy session pagination, delete confirmations, rename/delete actions, refresh state, and mobile touch click handling.

- Add strongly typed sidebar domain models in `src/components/sidebar/types.ts` and move sidebar-derived helpers into `src/components/sidebar/utils.ts`.
  Utility coverage now includes:
  session provider normalization,
  session view-model creation (name/time/activity/message count),
  project sorting/filtering,
  task indicator status derivation,
  starred-project persistence and readbacks.

- Split sidebar rendering into focused components under `src/components/sidebar/`:
  `SidebarContent.tsx` for top-level sidebar layout composition.
  `SidebarProjectList.tsx` for project-state branching and project iteration.
  `SidebarProjectsState.tsx` for loading/empty/no-search-result placeholders.
  `SidebarProjectItem.tsx` for per-project desktop/mobile header rendering and actions.
  `SidebarProjectSessions.tsx` for expanded session area, skeletons, pagination, and new-session controls.
  `SidebarSessionItem.tsx` for per-session desktop/mobile item rendering and session actions.
  `SessionProviderIcon.tsx` for provider icon normalization.
  `SidebarHeader.tsx`, `SidebarFooter.tsx`, `SidebarCollapsed.tsx`, and `SidebarModals.tsx` as dedicated typed UI surfaces.
  This keeps rendering responsibilities local and significantly improves traceability.

- Convert shared UI primitives from JSX to TSX:
  `src/components/ui/button.tsx`,
  `src/components/ui/input.tsx`,
  `src/components/ui/badge.tsx`,
  `src/components/ui/scroll-area.tsx`.
  These now provide typed props/variants (`forwardRef` where appropriate) while preserving existing class/behavior.

- Add shared app typings in `src/types/app.ts` for projects/sessions/websocket/loading contracts used by new hooks/components.

- Add global window declarations in `src/types/global.d.ts` for `__ROUTER_BASENAME__`, `refreshProjects`, and `openSettings`, removing implicit `any` usage for global integration points.

- Update `src/main.jsx` to import `App.tsx` and keep app bootstrap consistent with the TS migration.

- Update `src/components/QuickSettingsPanel.jsx` to self-resolve mobile state via `useDeviceSettings` (remove `isMobile` prop dependency), and update `src/components/ChatInterface.jsx` to render `QuickSettingsPanel` directly.
  This reduces prop drilling and keeps quick settings colocated with chat UI concerns.

* refactor(sidebar): integrate settings modal into SidebarModals and update props

* fix(mobile): prevent menu tap from triggering unintended dashboard navigation

The mobile sidebar menu button redirects users to `cloudcli.ai/dashboard` when a
session was active. The redirect happened because
the menu was opened on `touchstart`, which mounted the sidebar before the touch
sequence completed; the follow-up tap/click then landed on the sidebar header
anchor.

This change rewrites mobile menu interaction handling in `MainContent.jsx` to
eliminate touch/click event leakage and ghost-click behavior.

Key changes:
- Added `suppressNextMenuClickRef` to guard against synthetic click events that
  fire after a touch interaction.
- Added `openMobileMenu(event)` helper to centralize `preventDefault`,
  `stopPropagation`, and `onMenuClick()` invocation.
- Added `handleMobileMenuTouchEnd(event)`:
  - opens the menu on `touchend` instead of `touchstart`
  - sets a short suppression window (350ms) for the next click.
- Added `handleMobileMenuClick(event)`:
  - ignores/suppresses click events during the suppression window
  - otherwise opens the menu normally.
- Updated all mobile menu button instances in `MainContent.jsx` (loading state,
  no-project state, active header state) to use:
  - `onTouchEnd={handleMobileMenuTouchEnd}`
  - `onClick={handleMobileMenuClick}`
- Removed the previous `onTouchStart` path that caused premature DOM mutation.

Behavioral impact:
- Mobile sidebar still opens reliably with one tap.
- Tap no longer leaks to newly-mounted sidebar header links.
- Prevents accidental redirects while preserving existing menu UX.

* refactor(main-content): migrate MainContent to TypeScript and modularize UI/state boundaries

Replace the previous monolithic MainContent.jsx with a typed one and
extract focused subcomponents/hooks to improve readability, local state ownership,
and maintainability while keeping runtime behavior unchanged.

Key changes:
- Replace `src/components/MainContent.jsx` with `src/components/MainContent.tsx`.
- Add typed contracts for main-content domain in `src/components/main-content/types.ts`.
- Extract header composition into:
  - `MainContentHeader.tsx`
  - `MainContentTitle.tsx`
  - `MainContentTabSwitcher.tsx`
  - `MobileMenuButton.tsx`
- Extract loading/empty project views into `MainContentStateView.tsx`.
- Extract editor presentation into `EditorSidebar.tsx`.
- Move editor file-open + resize behavior into `useEditorSidebar.ts`.
- Move mobile menu touch/click suppression logic into `useMobileMenuHandlers.ts`.
- Extract TaskMaster-specific concerns into `TaskMasterPanel.tsx`:
  - task detail modal state
  - PRD editor modal state
  - PRD list loading/refresh
  - PRD save notification lifecycle

Behavior/compatibility notes:
- Preserve existing tab behavior, session passthrough props, and Chat/Git/File flows.
- Keep interop with existing JS components via boundary `as any` casts where needed.
- No intentional functional changes; this commit is structural/type-oriented refactor.

Validation:
- `npm run typecheck` passes.
- `npm run build` passes (existing unrelated CSS minify warnings remain).

* refactor(chat): split monolithic chat interface into typed modules and hooks

Replace the legacy monolithic ChatInterface.jsx implementation with a modular TypeScript architecture centered around a small orchestration component (ChatInterface.tsx).

Core architecture changes:
- Remove src/components/ChatInterface.jsx and add src/components/ChatInterface.tsx as a thin coordinator that wires provider state, session state, realtime WebSocket handlers, and composer behavior via dedicated hooks.
- Update src/components/MainContent.tsx to use typed ChatInterface directly (remove AnyChatInterface cast).

State ownership and hook extraction:
- Add src/hooks/chat/useChatProviderState.ts to centralize provider/model/permission-mode state, provider/session synchronization, cursor model bootstrap from backend config, and pending permission request scoping.
- Add src/hooks/chat/useChatSessionState.ts to own chat/session lifecycle state: session loading, cursor/claude/codex history loading, pagination, scroll restoration, visible-window slicing, token budget loading, persisted chat hydration, and processing-state restoration.
- Add src/hooks/chat/useChatRealtimeHandlers.ts to isolate WebSocket event processing for Claude/Cursor/Codex, including session filtering, streaming chunk buffering, session-created/pending-session transitions, permission request queueing/cancellation, completion/error handling, and session status updates.
- Add src/hooks/chat/useChatComposerState.ts to own composer-local state and interactions: input/draft persistence, textarea sizing and keyboard behavior, slash command execution, file mentions, image attachment/drop/paste workflow, submit/abort flows, permission decision responses, and transcript insertion.

UI modularization under src/components/chat:
- Add view/ChatMessagesPane.tsx for message list rendering, loading/empty states, pagination affordances, and thinking indicator.
- Add view/ChatComposer.tsx for composer shell layout and input area composition.
- Add view/ChatInputControls.tsx for mode toggles, token display, command launcher, clear-input, and scroll-to-bottom controls.
- Add view/PermissionRequestsBanner.tsx for explicit tool-permission review actions (allow once / allow & remember / deny).
- Add view/ProviderSelectionEmptyState.tsx for provider and model selection UX plus task starter integration.
- Add messages/MessageComponent.tsx and markdown/Markdown.tsx to isolate message rendering concerns, markdown/code rendering, and rich tool-output presentation.
- Add input/ImageAttachment.tsx for attachment previews/removal/progress/error overlay rendering.

Shared chat typing and utilities:
- Add src/components/chat/types.ts with shared types for providers, permission mode, message/tool payloads, pending permission requests, and ChatInterfaceProps.
- Add src/components/chat/utils/chatFormatting.ts for html decoding, code fence normalization, regex escaping, math-safe unescaping, and usage-limit text formatting.
- Add src/components/chat/utils/chatPermissions.ts for permission rule derivation, suggestion generation, and grant flow.
- Add src/components/chat/utils/chatStorage.ts for resilient localStorage access, quota handling, and normalized Claude settings retrieval.
- Add src/components/chat/utils/messageTransforms.ts for session message normalization (Claude/Codex/Cursor) and cached diff computation utilities.

Command/file input ergonomics:
- Add src/hooks/chat/useSlashCommands.ts for slash command fetching, usage-based ranking, fuzzy filtering, keyboard navigation, and command history persistence.
- Add src/hooks/chat/useFileMentions.tsx for project file flattening, @mention suggestions, mention highlighting, and keyboard/file insertion behavior.

TypeScript support additions:
- Add src/types/react-syntax-highlighter.d.ts module declarations to type-check markdown code highlighting imports.

Behavioral intent:
- Preserve existing chat behavior and provider flows while improving readability, separation of concerns, and future refactorability.
- Move state closer to the components/hooks that own it, reducing cross-cutting concerns in the top-level chat component.

* perf(project-loading): eliminate repeated Codex session rescans and duplicate cursor fetches

The staged changes remove the main source of project-load latency by avoiding repeated full scans of ~/.codex/sessions for every project and by removing redundant client-side cursor session refetches.

Server changes (server/projects.js):\n- Add a per-request Codex index reference in getProjects so Codex metadata is built once and reused across all projects, including manually added ones.\n- Introduce normalizeComparablePath() to canonicalize project paths (including Windows long-path prefixes and case-insensitive matching on Windows).\n- Introduce findCodexJsonlFiles() + buildCodexSessionsIndex() to perform a single recursive Codex scan and group sessions by normalized cwd.\n- Update getCodexSessions() to accept indexRef and read from the prebuilt index, with fallback index construction when no ref is provided.\n- Preserve existing session limiting behavior (limit=5 default, limit=0 returns all).

Client changes (src/hooks/useProjectsState.ts):\n- Remove loadCursorSessionsForProjects(), which previously triggered one extra /api/cursor/sessions request per project after /api/projects.\n- Use /api/projects response directly during initial load and refresh.\n- Expand projectsHaveChanges() to treat both cursorSessions and codexSessions as external session deltas.\n- Keep refresh comparison aligned with external session updates by using includeExternalSessions=true in sidebar refresh path.

Impact:\n- Reduces backend work from roughly O(projects * codex_session_files) to O(codex_session_files + projects) for Codex discovery during a project load cycle.\n- Removes an additional client-side O(projects) network fan-out for Cursor session fetches.\n- Improves perceived and actual sidebar project-loading time, especially in large session datasets.

* fix(chat): make Stop and Esc reliably abort active sessions

Problem

Stop requests were unreliable because aborting depended on currentSessionId being set, Esc had no actual global abort binding, stale pending session ids could be reused, and abort failures were surfaced as successful interruptions. Codex sessions also used a soft abort flag without wiring SDK cancellation.

Changes

- Add global Escape key handler in chat while a run is loading/cancellable to trigger the same abort path as the Stop button.

- Harden abort session target selection in composer by resolving from multiple active session id sources (current, pending view, pending storage, cursor storage, selected session) and ignoring temporary new-session-* ids.

- Clear stale pendingSessionId when launching a brand-new session to prevent aborting an old run.

- Update realtime abort handling to respect backend success=false responses: keep loading state when abort fails and emit an explicit failure message instead of pretending interruption succeeded.

- Improve websocket send reliability by checking socket.readyState === WebSocket.OPEN directly before send.

- Implement real Codex cancellation via AbortController + runStreamed(..., { signal }), propagate aborted status, and suppress expected abort-error noise.

Impact

This makes both UI Stop and Esc-to-stop materially more reliable across Claude/Cursor/Codex flows, especially during early-session windows before currentSessionId is finalized, and prevents false-positive interrupted states when backend cancellation fails.

Validation

- npm run -s typecheck

- npm run -s build

- node --check server/openai-codex.js

* refactor: tool components

* refactor: tool components

* fix: remove  one-line logic from messagecomponent

* refactor(design): change the design of bash

* refactor(design): fix bash design and config

* refactor(design): change the design of tools and introduce todo list and task list.

* refactor(improvement):add memo on diffviewer, cleanup messsagecomponent

* refactor: update readme and remove unusedfiles.

* refactor(sidebar): remove duplicate loading message in SidebarProjectsState

* refactor(sidebar): move VersionUpgradeModal into SidebarModals

* refactor: replace individual provider logos with a unified SessionProviderLogo component

* fix(commands): restore /cost slash command and improve command execution errors

The /cost command was listed as built-in but had no handler, causing execution to
fall through to custom command logic and return 400 ("command path is required").

- Add a built-in /cost handler in server/routes/commands.js
- Return the expected payload shape for the chat UI (`action: "cost"`, token usage,
  estimated cost, model)
- Normalize token usage inputs and compute usage percentage
- Add provider-based default pricing for cost estimation
- Fix model selection in command execution context so codex uses `codexModel`
  instead of `claudeModel`
- Improve frontend command error handling by parsing backend error responses and
  showing meaningful error messages instead of a generic failure

* fix(command-menu): correct slash command selection with frequent commands

When the “Frequently Used” section is visible, command clicks/hover could use a
UI-local index instead of the canonical `filteredCommands` index, causing the
wrong command to execute (e.g. clicking `/help` running `/clear`).

- map rendered menu items back to canonical command indices using a stable key
  (`name + namespace/type + path`)
- use canonical index for hover/click selection callbacks
- deduplicate frequent commands from other grouped sections to avoid duplicate
  rows and selection ambiguity
- keep and restore original inline comments, with clarifications where needed

* refactor(sidebar): update sessionMeta handling for session loading logic

- This fixes an issue where the sidebar was showing 6+ even when there were only 5 sessions, due to the hasMore logic not accounting for the case where there are exactly 6 sessions.
It was also showing "Show more sessions" even where there were no more sessions to load.

- This was because `hasMore` was sometimes `undefined` and the logic checked for hasMore !== false, which treated undefined as true.
Now we explicitly check for hasMore === true to determine if there are more sessions to load.

* refactor(project-watcher): add codex and cursor file watchers

* fix: chat session scroll to bottom error even when scrolled up

* fix(chat): clear stuck loading state across realtime lifecycle events

The chat UI could remain in a stale "Thinking/Processing" state when session IDs
did not line up exactly between view state (`currentSessionId`), selected route
session, pending session IDs, and provider lifecycle events. This was most visible
with Codex completion/abort flows, but the same mismatch risk existed in shared
handlers.

Unify lifecycle cleanup behavior in realtime handlers and make processing tracking
key off the active viewed session identity.

Changes:
- src/hooks/chat/useChatRealtimeHandlers.ts
- src/components/ChatInterface.tsx
- src/hooks/chat/useChatSessionState.ts

What changed:
- Added shared helpers in realtime handling:
  - `collectSessionIds(...)` to normalize and dedupe candidate session IDs.
  - `clearLoadingIndicators()` to consistently clear `isLoading`, abort UI, and status.
  - `markSessionsAsCompleted(...)` to consistently notify inactive/not-processing state.
- Updated lifecycle branches to use shared cleanup logic:
  - `cursor-result`
  - `claude-complete`
  - `codex-response` (`turn_complete` and `turn_failed`)
  - `codex-complete`
  - `session-aborted`
- Expanded completion/abort cleanup to include all relevant session IDs
  (`latestMessage.sessionId`, `currentSessionId`, `selectedSession?.id`,
  `pendingSessionId`, and Codex `actualSessionId` when present).
- Switched processing-session marking in `ChatInterface` to use
  `selectedSession?.id || currentSessionId` instead of `currentSessionId` alone.
- Switched processing-session rehydration in `useChatSessionState` to use
  the same active-view session identity fallback.

Result:
- Prevents stale loading indicators after completion/abort when IDs differ.
- Keeps processing session bookkeeping aligned with the currently viewed session.
- Reduces provider-specific drift by using one lifecycle cleanup pattern.

* fix(chat): stabilize long-history scroll-up pagination behavior

- fix top-pagination lockups by only locking when older messages are actually fetched
- make fetched older messages visible immediately by increasing `visibleMessageCount` on prepend
- prevent unintended auto-scroll-to-bottom during older-message loading and scroll restore
- replace state-based pagination offset with a ref to avoid stale offset/reload side effects
- ensure initial auto-scroll runs only after initial session load completes
- reset top-load lock/restore state and visible window when switching sessions
- loosen top-lock release near the top to avoid requiring a full down/up cycle

* refactor: Restructure files and folders to better mimic feature-based architecture

* refactor: reorganize chat view components and types

* feat(chat): move thinking modes, token usage pie, and related logic into chat folder

* refactor(tools): add agent category for Task tool

Add visual distinction for the Task tool (subagent invocation) by
introducing a new 'agent' category with purple border styling. This
separates subagent tasks from regular task management tools
(TaskCreate, TaskUpdate, etc.) for clearer user feedback.

Also refactor terminal command layout in OneLineDisplay to properly
nest flex containers, fixing copy button alignment issues.

* refactor(tools): improve Task tool display formatting

Update Task tool config to show cleaner subagent information in the UI.
Simplifies the input display by showing only the prompt when no
optional fields are present, reducing visual clutter. Updates title
format to "Subagent / {type}" for better categorization. Enhances
result display to better handle complex agent response structures with
array content types, extracting text blocks for cleaner presentation.

* fix: show auth url panel in shell only on mobile

- use static url: https://auth.openai.com/codex/device, for codex login.
- add an option for hiding the panel

* fix(chat): escape command name in regex to prevent unintended matches

* fix(chat): handle JSON parsing errors for saved chat messages

* refactor(chat): replace localStorage provider retrieval with prop usage in MessageComponent

* fix(chat): handle potential null content in message before splitting lines

* refactor(todo): update TodoListContentProps to include optional id and priority fields that are used in TodoList.jsx

* fix(watcher): ensure provider folders exist before creating watchers to maintain active watching

* refactor(chat): improve message handling by cloning state updates and improving structured message parsing

* refactor(chat): exclude currentSessionId from dependency array to prevent unnecessary reloading of messages

* refactor(useFileMentions): implement abort controller for fetch requests

* refactor(MessageComponent): add types

* refactor(calculateDiff): optimize LCS algorithm for improved diff calculation

* refactor(createCachedDiffCalculator): use both newStr and oldStr as cache keys

* refactor(useSidebarController): manage project session overrides in local state

* refactor(ScrollArea): adjust ref placement and className order

* fix: type annotations

* refactor(ChatInputControls): update import statement for ThinkingModeSelector

* refactor(dateUtils): update type annotation for formatTimeAgo function

* refactor(ToolRenderer): ensure stable hook order

* refactor(useProjectsState): normalize refreshed session metadata to maintain provider stability; use getProjectSessions helper for session retrieval.

* refactor(useChatComposerState): improve input handling and command execution flow

* refactor(useChatRealtimeHandlers): normalize interactive prompt content to string for consistent ChatMessage shape

* refactor(OneLineDisplay):  improve clipboard functionality with fallback for unsupported environments

* refactor(QuickSettingsPanel): simplify state management by removing localIsOpen and using isOpen directly

* refactor(ChatMessagesPane): use stable message key

* refactor:: move AssistantThinkingIndicator component to its own file

* refactor(ChatMessagesPane): extract message key generation logic to a utility function

* refactor(SidebarModals): move normalizeProjectForSettings into utils file

* refactor(ToolConfigs): use optional chaining for content retrieval

* fix(chat): stabilize provider/message handling and complete chat i18n coverage

Unify provider typing, harden realtime message effects, normalize tool input
serialization, and finish i18n/a11y updates across chat UI components.

- tighten provider contracts from `Provider | string` to `SessionProvider` in:
  - `useChatProviderState`
  - `useChatComposerState`
  - `useChatRealtimeHandlers`
  - `ChatMessagesPane`
  - `ProviderSelectionEmptyState`
- refactor `AssistantThinkingIndicator` to accept `selectedProvider` via props
  instead of reading provider from local storage during render
- fix stale-closure risk in `useChatRealtimeHandlers` by:
  - adding missing effect dependencies
  - introducing `lastProcessedMessageRef` to prevent duplicate processing when
    dependencies change without a new message object

- standardize `toolInput` shape in `messageTransforms`:
  - add `normalizeToolInput(...)`
  - ensure all conversion paths produce consistent string output
  - remove mixed `null`/raw/stringified variants across cursor/session branches

- harden tool display fallback in `CollapsibleDisplay`:
  - default border class now falls back safely for unknown categories

- improve chat i18n consistency:
  - localize hardcoded strings in `MessageComponent`
    (`permissions.*`, `interactive.*`, `thinking.emoji`, `json.response`,
    `messageTypes.error`)
  - localize button titles in `ChatInputControls`
    (`input.clearInput`, `input.scrollToBottom`)
  - localize provider-specific empty-project prompt in `ChatInterface`
    (`projectSelection.startChatWithProvider`)
  - localize repeated “Start the next task” prompt in
    `ProviderSelectionEmptyState` (`tasks.nextTaskPrompt`)

- add missing translation keys in all supported chat locales:
  - `src/i18n/locales/en/chat.json`
  - `src/i18n/locales/ko/chat.json`
  - `src/i18n/locales/zh-CN/chat.json`
  - new keys:
    - `input.clearInput`
    - `input.scrollToBottom`
    - `projectSelection.startChatWithProvider`
    - `tasks.nextTaskPrompt`

- improve attachment remove-button accessibility in `ImageAttachment`:
  - add `type="button"` and `aria-label`
  - make control visible on touch/small screens and focusable states
  - preserve hover behavior on larger screens

Validation:
- `npm run typecheck`

* fix(chat): sync quick settings state and stabilize thinking toggle

Synchronize useUiPreferences instances via custom sync events and storage listeners so Quick Settings updates apply across UI consumers immediately.

Also hide standalone thinking messages when showThinking is disabled, while preserving hook order to avoid Rendered fewer hooks runtime errors.

* refactor(validateGitRepository): improve directory validation for git work tree

* refactor(GitPanel): clear stale state on project change and improve error handling

* refactor(git): use spawnAsync for command execution and improve commit log retrieval

* fix: iOS pwa bottom margin

* fix: pass diff information to code editor

* refactor(sidebar): remove touch event handlers from project and session items

* bumping node to v22

* Release 1.17.0

---------

Co-authored-by: Haileyesus <something@gmail.com>
Co-authored-by: simosmik <simosmik@gmail.com>
2026-02-13 20:26:47 +01:00
Haileyesus
c1e025b665 fix: claude code login issues (#375)
* fix: claude code login issues

1. Now, the browser opens in a new tab automatically
2. Clicking "C" to copy works
3. I have removed the "x-term" link selector since it didn't select the whole link

* fix: remove unnecessary terminal hyperlink for auth URL

* fix(shell): resolve clipboard handling for copy and paste events

* feat(shell): add authentication URL display and copy functionality - allows copy for mobile users

* revert: Update login command for unauthenticated users to use '/exit'

---------

Co-authored-by: Haileyesus <something@gmail.com>
2026-02-11 12:05:28 +01:00
Haileyesus
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

---------
2026-02-03 10:05:15 +01:00
Haileyesus
bbb51dbf99 fix: enforce WORKSPACES_ROOT in folder browser and folder creation 2026-01-28 22:12:20 +03:00
Eric Blanquer​
ede56ad81b fix: simplify project wizard labels for clarity 2026-01-26 03:25:43 +01:00
Eric Blanquer
36094fb73f fix: encode Windows paths correctly in addProjectManually
The regex only replaced forward slashes, causing Windows paths like
C:\Users\Eric\my_project to remain unchanged instead of being encoded
to C--Users-Eric-my-project. This caused API routes to fail.
2026-01-26 03:09:22 +01:00
Eric Blanquer​
57828653bf fix: handle EEXIST race and prevent data loss on clone 2026-01-26 03:09:22 +01:00
Eric Blanquer​
ab50c5c1a8 fix: address CodeRabbit review comments
- Add path validation to /api/create-folder endpoint (forbidden system dirs)
- Fix repo name extraction to handle trailing slashes in URLs
- Add cleanup of partial clone directory on SSE clone failure
- Remove dead code branch (unreachable message)
- Fix Windows path separator detection in createNewFolder
- Replace alert() with setError() for consistent error handling
- Detect ssh:// URLs in addition to git@ for SSH key display
- Show create folder button for both workspace types
2026-01-26 03:09:22 +01:00
Eric Blanquer​
6726e8f44e feat: enhance project creation wizard with folder creation and git clone progress
- Add "+" button to create new folders directly from folder browser
- Add SSE endpoint for git clone with real-time progress display
- Show clone progress (receiving objects, resolving deltas) in UI
- Detect SSH URLs and display "SSH Key" instead of "No authentication"
- Hide token section for SSH URLs (tokens only work with HTTPS)
- Fix auto-advance behavior: only auto-advance for "Existing Workspace"
- Fix various misleading UI messages
- Support auth token via query param for SSE endpoints
2026-01-26 03:09:22 +01:00
viper151
b2c69d6ea8 Merge branch 'main' into main 2026-01-25 23:17:29 +01:00
viper151
8825baf5b4 Update codex.js 2026-01-25 23:17:08 +01:00
viper151
80732923b5 Merge branch 'main' into fix/session-streamed-to-another-chat 2026-01-25 23:15:23 +01:00
Tim Smith
dab089b29f fix: prevent codex spawn error when codex CLI is not installed
Return success with empty servers array from the config read endpoint
when no config file exists, so the frontend doesn't fall through to
the CLI list endpoint which attempts to spawn the codex binary.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 11:21:43 -08:00
Eric Blanquer​
74640a7f31 feat: allow deleting projects with sessions and add styled confirmation modal
- Add force delete option to delete projects with existing sessions
- Add styled confirmation modal with session count warning
- Add deletingProjects state to show loading indicator during deletion
- Delete associated Codex sessions when deleting a project (with limit: 0)
- Delete associated Cursor sessions directory when deleting a project
- Add fallback to extractProjectDirectory when projectPath undefined
- Use finally block for deletingProjects cleanup
- Add fallback name in delete modal
2026-01-21 22:05:00 +01:00
Haileyesus Dessie
396f058b46 Merge pull request #311 from EricBlanquer/local/loading-progress
Add loading progress indicator
2026-01-21 17:08:30 +03:00
Eric Blanquer​
9e03acb0db Add loading progress indicator
Adds real-time progress feedback when loading projects:
- Server broadcasts progress updates via WebSocket
- Sidebar shows current project being loaded with progress bar
- Fixed progress counter to show correct current/total
- Completion event now fires after all projects (including manual) are processed
- Race condition fix for timeout cleanup using ref
- Added cleanup function to prevent state update on unmounted component
2026-01-21 00:21:01 +01:00
viper151
9cd1b5811a Merge branch 'main' into fix/session-streamed-to-another-chat 2026-01-20 12:59:42 +01:00
Eric Blanquer​
e1f2af1a34 feat: add folder browser to ProjectCreationWizard
- Add folder browser modal to navigate and select project folders
- Sort folders alphabetically (case-insensitive)
- Add toggle to show/hide hidden folders (hidden by default)
- Auto-advance to confirmation step when selecting a folder
- Place "Use this folder" button next to Cancel
2026-01-18 06:05:34 +01:00
Haileyesus Dessie
b3c6e95971 fix: don't stream response to another session 2026-01-16 14:04:12 +03:00
amacsmith
66e85fb2c1 fix: filter VCS directories from file autocomplete
Excludes .git, .svn, and .hg directories from the file tree returned
by getFileTree(). This prevents VCS internal files from appearing
in the @ file autocomplete dropdown.

The fix is applied server-side which:
- Reduces data transferred to the client
- Benefits all features using getFileTree()
- Provides consistent filtering across the application

Fixes #290

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 18:43:58 -05:00
Haileyesus Dessie
35e140b941 add a clarification comment about crypto.randomUUID() 2026-01-10 15:00:46 +03:00
Haileyesus Dessie
64ebbaf387 feat: setup canUseTool for claude messages 2026-01-10 14:35:51 +03:00
Haileyesus Dessie
4c40a33255 fix: improve error handling and response structure in MCP CLI routes for codex 2026-01-05 20:54:26 +03:00
Haileyesus Dessie
9efe433d99 fix: get codex sessions in windows; improve message counting logic; fix session navigation in ChatInterface 2026-01-05 16:35:20 +03:00
simosmik
8af982e706 feat: add update command to CLI for checking and installing the latest version 2025-12-31 07:59:13 +00:00
viper151
9b217ada0d Merge branch 'main' into main 2025-12-31 08:48:30 +01:00
simosmik
04efaa41f6 feat: add custom port and database path options to CLI commands 2025-12-31 07:42:01 +00:00
simosmik
b315360f8a fix: replace HOME env variable with os.homedir() to support windows 2025-12-30 18:07:04 +00:00
simosmik
babe96eedd fix: API would be stringified twice. That is now fixed. 2025-12-29 23:18:38 +00:00
simosmik
60c8bda755 fix: pass model parameter to Claude and Codex SDKs
Previously, the model parameter was accepted by the /api/agent endpoint
and extracted from requests, but was never passed through to the Claude
SDK or Codex SDK, causing all requests to use default models regardless
of user selection.

Changes:
- Add model parameter to queryClaudeSDK() options in routes/agent.js
- Add model to threadOptions in openai-codex.js
- Remove unused /cost slash command and PRICING constants
- Centralize all model definitions in shared/modelConstants.js
- Update API documentation to dynamically load models from constants
2025-12-29 16:19:09 +00:00
simosmik
8186c4039f fix: path improvement of projects added via config. 2025-12-29 11:32:41 +00:00
simosmik
fbbf7465fb feat: Introducing Codex to the Claude code UI project. Improve the Settings and Onboarding UX to accomodate more agents. 2025-12-27 22:30:32 +00:00
simosmik
7a173071f1 fix: added webfetch and websearch to plan mode tools 2025-12-17 12:25:47 +00:00
simosmik
6bf3696991 fix: fixing claude and cursor login defaulting to the previously opened shell 2025-12-17 12:18:40 +00:00
simosmik
d822a96818 feat(chat): add model selection for Claude and update to latest versinos of claude agent sdk and cursor cli 2025-12-16 17:22:33 +00:00
Ivan Pantic
19bb741af0 Fix issue: Broken pasted image upload 2025-12-12 00:27:09 +01:00
simos
1f4cd16b89 fix: change agent mode for platform 2025-12-10 00:29:53 +01:00
simos
18d0874142 feat: auto-populate git config from system 2025-11-17 18:05:49 +01:00
simos
544c72434a fix: initial commit error 2025-11-17 15:54:08 +01:00
simos
8c629a1a05 feat: onboarding page & adding git settings 2025-11-17 15:26:46 +01:00
simos
2df8c8e786 fix:identify claude login status 2025-11-17 14:20:10 +01:00
simos
f91f9f702d fix: settings api calls that would fail. 2025-11-17 13:58:58 +01:00
simos
33834d808b feature:show auth status on settings 2025-11-17 08:48:15 +01:00
simos
521fce32d0 refactor: improve shell performance, fix bugs on the git tab and promote login to a standalone component
Implement PTY session persistence with 30-minute timeout for shell reconnection. Sessions are now keyed by project path and session ID, preserving terminal state across UI disconnections with buffered output replay.
Refactor Shell component to use refs for stable prop access, removing unnecessary isActive prop and improving WebSocket connection lifecycle management. Replace conditional rendering with early returns in MainContent for better performance.
Add directory handling in git operations: support discarding, diffing, and viewing directories in untracked files. Prevent errors when staging or generating commit messages for directories.
Extract LoginModal into reusable component for Claude and Cursor CLI authentication. Add minimal mode to StandaloneShell for embedded use cases. Update Settings to use new LoginModal component.
Improve terminal dimensions handling by passing client-provided cols and rows to PTY spawn. Add comprehensive logging for session lifecycle and API operations.
2025-11-14 23:44:29 +00:00
simos
2815e206dc refactor: Remove unecessary websocket calls for taskmaster 2025-11-14 16:31:33 +01:00
simos
ed65399dfb refactor: remove unused /api/config endpoint and update WebSocket connection logic 2025-11-12 23:23:01 +01:00
simos
23de8c7863 feature: is_platform changes 2025-11-05 00:25:47 +01:00
simos
7ab14750de Merge remote-tracking branch 'origin/feature/new-project-creation' into feature/new-project-creation 2025-11-04 09:32:42 +00:00
simos
255aed0b01 feat(projects): add workspace path security validation and align github credentials implementation across components 2025-11-04 09:29:21 +00:00
viper151
b416e542c7 Apply suggestion from @coderabbitai[bot]
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-04 09:39:37 +01:00