Commit Graph

234 Commits

Author SHA1 Message Date
Simos Mikelatos
6af4afe6f2 Merge branch 'main' into browser-use 2026-06-16 19:02:36 +02:00
Haileyesus
d7a38a567a chore: move tests to appropriate folder 2026-06-16 17:54:48 +03:00
Haileyesus
c6c153e7f2 chore: move tests to appropriate folder 2026-06-16 17:47:52 +03:00
Simos Mikelatos
9438a365f2 feat: improve browser use session controls 2026-06-15 21:14:10 +00:00
Simos Mikelatos
0426522406 feat: expose browser use to agents via MCP 2026-06-15 19:47:58 +00:00
Simos Mikelatos
6e7e2ff4c1 feat: make browser use opt-in 2026-06-15 18:12:27 +00:00
Simos Mikelatos
e6263dbd1f refactor: store browser use settings in database 2026-06-15 17:57:00 +00:00
Simos Mikelatos
260070bae0 feat: add browser use runtime setup settings 2026-06-15 17:52:27 +00:00
Simos Mikelatos
828d1a2302 Merge remote-tracking branch 'origin/feat/unify-websocket-2' into browser-use-independent 2026-06-15 16:12:10 +00:00
Haileyesus
9fb2d91b26 fix: resolve session provider on backend reads
Session history and token usage reads already have a stable app session id.
Passing provider and project hints from the frontend kept those reads coupled
with provider-specific state that the backend can resolve from the session row.

Resolve token usage provider server-side and narrow the session store read API
to session id plus pagination. This keeps provider-specific storage decisions
behind the backend boundary and makes reconnect, pagination, and load-all use
the same session-owned contract.
2026-06-15 14:04:50 +03:00
Haileyesus
d0adddbbda fix: normalize project session payloads
The sidebar had to understand cursorSessions, codexSessions,
and other provider buckets because /api/projects exposed
provider-shaped arrays.

That leaked backend adapter storage into project state and made
frontend behavior drift each time a provider needed another bucket
or exception.

Return one sessions list with provider metadata instead. Project
state, search, and running-session filtering now share one contract,
while provider-specific storage remains behind the backend boundary.
2026-06-15 13:43:18 +03:00
Simos Mikelatos
243e6cecd5 Add browser use workspace panel 2026-06-14 20:34:16 +00:00
Haileyesus
5b9adbbdee fix(opencode): bind watcher sessions to app rows early 2026-06-12 23:22:11 +03:00
Haileyesus
416a737d76 fix(opencode): pass workspace dir explicitly
The remote environment could start OpenCode runs under /opt/claudecodeui.

That happened even when the selected project path was correct.

The integration relied on child-process cwd alone.

OpenCode run resolves its workspace through the explicit --dir contract.

Pass --dir with the resolved working directory.

Assert in the CLI test that launch args include the workspace dir.
2026-06-12 22:45:22 +03:00
Haileyesus
3bbb42c233 fix(sessions): canonicalize sidebar ids and timestamps
The sidebar could keep a provider-native id after backend remapping.

That left a duplicate non-working session visible until refresh.

Fresh sessions could also appear hours old.

SQLite CURRENT_TIMESTAMP is UTC without a timezone suffix.

Browser parsing then treated those values like local time.

Broadcast a canonical session_upserted event when the provider id is mapped.

Collapse provider-id aliases onto the stable app session id in the client.

Normalize session-row timestamps to ISO UTC when reading from the repository.
2026-06-12 20:52:18 +03:00
Haileyesus
89f05247ed fix(shell): use correct session id 2026-06-11 21:04:31 +03:00
Haileyesus
591b18e9e3 feat(sidebar): improve running session state tracking
Add a running-session view to the sidebar, including header controls, running counts, empty states, and row-level processing indicators so active provider work is visible outside the current chat.

Hydrate running state after refresh through a status-only /api/providers/sessions/running endpoint backed by chatRunRegistry.listRunningRuns, then sync and poll the frontend processingSessions map from AppContent without attaching to chat streams or replaying messages.

Preserve fresh local processing entries during sync so newly sent messages are not cleared before the backend registry catches up, and clear completed sessions once the status endpoint no longer reports them.

Thread active session state through sidebar project/session components, show rotating loaders for processing sessions, and keep the running search mode expanded and filterable.

Fix optimistic local user-message dedupe so repeated prompts are only collapsed when a matching server echo appears from the same send window, preventing sent messages from disappearing until assistant completion.

Add registry test coverage for listing currently running app sessions.

Tests: npx eslint on changed files; npx tsc --noEmit -p tsconfig.json; npx tsc --noEmit -p server/tsconfig.json; npx tsx --tsconfig server/tsconfig.json --test server/modules/websocket/tests/chat-run-registry.test.ts.
2026-06-11 20:04:38 +03:00
Haileyesus
881e72d4a0 fix: correct notification session id 2026-06-11 19:31:13 +03:00
Haileyesus
f5eac2ec12 feat(chat): unify session gateway with stable IDs and a single WS protocol
The frontend previously juggled placeholder IDs, provider-native IDs, and session_created handoffs, which caused race conditions and provider-specific branching. This introduces app-allocated session IDs, a chat run registry with event replay, delta sidebar updates, and one kind-based websocket contract so the UI can treat every provider the same while JSONL remains the source of truth.
2026-06-11 18:47:19 +03:00
Haileyesus
3d948217ef chore: upgrade gemini models 2026-06-11 18:38:02 +03:00
Haileyesus
afc717e69e feat(chat): derive activity indicator from per-session state and unify provider lifecycle events
Replace the chat processing banner with a minimal activity indicator and
rebuild the state model underneath it. The old banner was driven by five
overlapping pieces of state (isLoading, canAbortSession, claudeStatus in the
chat, plus two app-level Sets updated in lockstep through four callbacks)
that had to be kept in sync imperatively. Because completion and status
events mutated the *viewed* session's flags regardless of which session they
belonged to, a background session finishing could hide the indicator for a
still-running session, returning to a finished session could briefly show a
stale banner, and a late status reply could override a newer request.

The fix is structural rather than patch-by-patch: a single
Map<sessionId, {statusText, canInterrupt, startedAt}> in useSessionProtection
is now the only source of truth for "this session is working". The indicator,
stop button, composer streaming state, and session protection are all derived
from the viewed session's entry on render, so there is no stale local copy to
restore or reset when switching sessions. A PENDING_SESSION_ID sentinel
covers the window before a new conversation receives its real session id.
Terminal events delete the entry atomically, which is why the indicator
disappears the instant the final chunk arrives. Stale check-session-status
replies are discarded via an ifStartedBefore guard (an idle reply older than
the entry's startedAt describes a previous request, not the current one).

The second half unifies the provider lifecycle contract, because the frontend
could not be made race-free while each provider terminated differently:

- cursor emitted complete twice per run (result line + process close), which
  double-played the completion sound and let a late close-complete clear a
  newer request's indicator
- aborts produced two completes (the abort-session reply plus the provider's
  own non-aborted one), so cancelling a run played the celebration sound
- codex omitted exitCode; others attached ad-hoc fields (resultText, isError,
  isNewSession) the client had to know about
- claude/codex failures ended with only an error event while gemini/cursor
  also emit kind:'error' for mid-run stderr noise, so 'error' was ambiguous
  between "the run died" and "a process wrote to stderr"

Every run now ends with exactly one complete built by createCompleteMessage()
({sessionId, actualSessionId, exitCode, success, aborted}); abort-session
sends it on behalf of cancelled runs and providers detect the abort and skip
their own. error is demoted to an informational row, so stderr noise no
longer kills the indicator mid-run, and the client celebrates only
success: true completes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:39:04 +03:00
Simos Mikelatos
92de0ed613 chore: remove unused modelConstants from the project 2026-06-09 20:51:19 +00:00
Simos Mikelatos
ce327b6fa9 feat: adding Fable 5 in claude code 2026-06-09 20:33:00 +00:00
Simos Mikelatos
029d159592 Merge branch 'main' into feature/chat-completion-notifications 2026-06-09 18:13:42 +02:00
Simos Mikelatos
f439a8a3d5 Merge branch 'main' into chore/add-prism-plugin 2026-06-09 17:46:47 +02:00
Simos Mikelatos
23210bc40e Merge branch 'main' into feature/chat-completion-notifications 2026-06-09 17:39:56 +02:00
Simos Mikelatos
b7e6bca2e3 Merge pull request #851 from jakeefr/fix/windows-plugin-env
Pass Windows-essential env vars to plugin subprocesses
2026-06-09 14:41:27 +02:00
Simos Mikelatos
231ed04002 Merge branch 'main' into feature/file-tree-upload-ux 2026-06-09 14:25:57 +02:00
Haileyesus
d70dc077bf feat: signal when chat runs complete
Users can miss chat completions while the app is in the background.

They can also miss completions when their attention is elsewhere.

Add opt-out sound notifications and a temporary title marker.

This makes completion noticeable without external audio assets or persistent browser notifications.
2026-06-09 13:51:51 +03:00
Jakob Michael Werner
1faa1a6a00 Pass Windows-essential env vars to plugin subprocesses
Plugin servers are started with a deliberately minimal env (PATH, HOME,
NODE_ENV, PLUGIN_NAME). On Windows that drops system variables that child
processes need to bootstrap. The one that bit me: without APPDATA, CPython
cannot find the per-user site-packages, so a plugin that shells out to a
pip install --user CLI launches the tool but it dies with ModuleNotFoundError.
SystemRoot, PATHEXT and TEMP cause similar failures for other tools.

On win32, pass through a small allowlist of non-secret system variables
(SystemRoot, windir, SystemDrive, USERPROFILE, APPDATA, LOCALAPPDATA, TEMP,
TMP, PATHEXT) when they are set. No change off Windows, and no host secrets
are exposed.
2026-06-08 17:13:10 -05:00
Haileyesus
01dbe2a8bf chore: add prism plugin 2026-06-08 15:55:40 +03:00
Noah
f4a1614a0a fix(sandbox): prevent server SIGHUP on sbx exec exit (#792)
Replace bare background operator with nohup+disown so the cloudcli
server process survives after the sbx exec session terminates.
Also redirects stdout/stderr to /tmp/cloudcli-ui.log for debugging
via `cloudcli sandbox logs`.

Fixes #791

Co-authored-by: NoahHahm <noah@naverz-corp.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
2026-06-08 15:28:35 +03:00
Haileyesus
c235b05e1d feat: add file tree upload progress
Users need a visible upload path from the explorer itself, not only drag and
 drop behavior with no progress feedback. Routing picker and drop uploads
 through one XHR-backed hook keeps progress, validation, refresh, and success
 counts consistent for every upload source.

The 200MB limit is mirrored in the client, multer, and nginx template so large
 uploads fail predictably instead of being blocked by whichever layer sees the
 request first. The server also returns explicit requested and uploaded counts
 so partial or multi-file batches can render accurate status text.
2026-06-08 14:52:09 +03:00
Simos Mikelatos
af3a28abc7 Remove fast project display names option 2026-06-07 08:55:16 +00:00
Simos Mikelatos
371ff034e4 Add fast project display names option 2026-06-07 08:46:31 +00:00
Simos Mikelatos
3b4d6885aa Add lightweight projects query options 2026-06-07 08:10:28 +00:00
Simos Mikelatos
bc9d2dd830 Merge pull request #839 from siteboon/fix/claude-token-cache-usage 2026-06-05 21:48:44 +02:00
Haileyesus
ed9cdf0114 fix: include Claude cache tokens in usage 2026-06-05 21:38:05 +03:00
Haile
b3d0f9037d Merge branch 'main' into chore/update-claude-fallback-models 2026-06-05 15:58:05 +03:00
Haile
14ddbc7c57 fix: redact websocket auth token in logs (#827) 2026-06-05 14:23:27 +02:00
Haile
ebb0e59e80 fix: file tree concurrency (#828)
* perf(file-tree): parallelize directory traversal and widen default ignore list

The project file-tree endpoint walked children sequentially with
`await fsPromises.stat()` inside a for-loop plus a separate
`fsPromises.access()` probe before recursing. On high-latency
filesystems (NFS/SMB) every one of those round-trips was serialized,
so a 120k-file SMB-mounted project took ~2 minutes to load.

This change:
* Runs stat() and recursive getFileTree() calls in parallel via
  `Promise.all` — pipelines round-trips and lets subtree traversals
  overlap.
* Drops the redundant access() probe; any EACCES now surfaces from
  readdir's own try/catch in the recursive call, saving one RTT per
  directory.
* Extracts the hardcoded skip list into an IGNORED_DIRS Set and
  extends it to cover common Python / Rust / JVM / IDE build
  artefacts (.next, __pycache__, .pytest_cache, .tox, .venv,
  target, .gradle, .idea, coverage, etc).

No API shape change; existing consumers get the same tree structure,
only much faster on large or remote-mounted projects.

* fix(file-tree): bound filesystem traversal concurrency

Prevent large file-tree scans from launching unbounded stat and readdir work.

Keep the parallel traversal benefit on high-latency mounts with a bounded queue.

Ignore skipped names only for directories so same-named files stay visible.

* fix(file-tree): inspect entries with lstat

Use lstat for file-tree metadata so symlink entries are identified without following targets.

---------

Co-authored-by: leonkong via Claude <leonkong.claude@users.noreply.github.com>
2026-06-05 14:21:30 +02:00
Haile
957f53fb99 Merge branch 'main' into chore/update-claude-fallback-models 2026-06-05 15:19:13 +03:00
Haile
ef2fd48b46 fix(shell): disconnect and restart buttons (#831)
Co-authored-by: Simos Mikelatos <simosmik@gmail.com>
2026-06-05 14:17:20 +02:00
Haileyesus
cdcac182d4 fix: load claude models directly from provider
Claude's model catalog changes quickly enough that a shared three-day cache can
leave users selecting stale defaults or missing newly available model aliases.
Route Claude model lookups through the provider every time so the UI and slash
commands reflect the current provider result instead of an old disk snapshot.

Keep the static fallback catalog aligned with the latest Claude defaults so the
provider still has a sensible response when live discovery is unavailable.
2026-06-05 15:14:32 +03:00
Haileyesus
94785bfa57 chore: update Claude fallback models 2026-06-05 15:02:25 +03:00
Vojtech
2edfef2e3f fix(websocket): add 30s server-side heartbeat to prevent proxy idle disconnects (#770)
The WebSocket gateway never sent ping frames, so any reverse proxy with
an idle timeout (Cloudflare Tunnel ~100s, AWS ALB 60s, nginx 60s, etc.)
would silently tear down /shell, /ws and /plugin-ws/* connections after
the idle window. The UI reconnects automatically but users see a
"Connecting to shell" toast every 1–3 minutes during normal use and any
in-flight PTY/chat traffic can race the reconnect.

Schedule a 30s ws.ping() per connection at the gateway level, cleared on
close/error. ping/pong counts as protocol activity for all proxies that
implement WebSocket correctly, so this single change covers every
deployment topology without per-proxy tuning.

Fixes #769

Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
2026-06-04 22:07:59 +03:00
Haile
43c33d5cb1 fix: recognize claude auth token env (#818) 2026-06-02 13:23:30 +02:00
CoderLuii
36b860e322 fix: preserve WebSocket frame type in plugin proxy (#594)
* fix: preserve WebSocket frame type in plugin proxy

The plugin WebSocket proxy relays all messages as binary frames
regardless of the original frame type. This causes text-based ready
messages to be forwarded as binary, so the browser never processes
them and plugin UIs (like web-terminal) show a spinner indefinitely.

Pass the isBinary flag through in both relay directions so the
original frame type is preserved.

Fixes CoderLuii/HolyClaude#11

* fix(plugins): preserve websocket frame type in proxy

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 20:56:51 +03:00
CoderLuii
1e125f3db5 fix: refresh Claude auth status after login flow (#617)
* fix: refresh Claude auth status after login flow

* fix: rely on refreshed auth status after login

---------

Co-authored-by: HolyCode User <noreply@holycode.local>
2026-05-31 14:17:27 +03:00
Haile
38bf21ddf5 fix: refine token usage reporting (#807) 2026-05-30 10:09:27 +02:00