Previously the regex ^\/(\S*)$ only matched when the entire text before
the cursor was a bare /command. Typing a slash mid-sentence (e.g.
"please run /he") produced no suggestions.
Changed pattern to (?:^|\s)(\/\S*)$ which matches / at the start of
input or after any whitespace. Also compute slashPos from match.index
instead of hardcoding 0, so insertCommandIntoInput replaces the correct
slice of the input when the command is mid-sentence.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
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.
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>
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.
Claude stores some tool failures as errored tool_result rows. The UI either
attached those rows to hidden tool output or dropped them when no matching tool
call was rendered, which made validation failures disappear from chat history.
Render unattached errored tool results, unwrap Claude tool_use_error content,
and keep tool errors visible even for tools whose successful output is hidden.
Also remove the permission-grant recovery controls from rendered error history
so denied tool use stays a plain error message.
Users deploying behind a reverse proxy need a config they can adapt.
The template documents each proxy block and centralizes upstream/subpath values.
It also notes that Nginx location matchers still require literal subpath edits.
* 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>
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.
Add dir="auto" to chat message content and composer textarea so
Persian and Arabic text automatically renders right-to-left
while English and other LTR text remains unaffected.
Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
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>
Plugin WebSocket connections (e.g. the official Terminal plugin) hang
in `npm run dev` because Vite proxies /api, /ws, and /shell but not
/plugin-ws/*. Production is unaffected because the same Express server
serves both the frontend and the WS gateway.
Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
The effect cleanup sets unmountedRef.current = true to prevent reconnects after
the provider unmounts. Without an inverse reset at the start of the effect,
re-running the effect (e.g. when the auth token rotates) leaves the ref true,
and connect() short-circuits at its unmounted guard. The socket then stays
permanently disconnected for the lifetime of the provider.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Haile <118998054+blackmammoth@users.noreply.github.com>
* fix(security)(components): unsanitized svg content injected via `dangerouslys
The plugin icon renderer fetches SVG text from `/api/plugins/.../assets/...` and injects it directly into the DOM using `dangerouslySetInnerHTML` after only checking that the payload starts with `<svg`. This does not remove malicious attributes/elements (e.g., event handlers, scriptable SVG payloads), enabling DOM-based XSS if a plugin asset is malicious or compromised.
Affected files: PluginIcon.tsx
Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com>
* fix: sanitize plugin svg icons
---------
Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com>
Co-authored-by: tuanaiseo <tuanaiseo@gmail.com>
Co-authored-by: Simos Mikelatos <simosmik@gmail.com>
* fix: harden router basename detection
* fix: broaden icon basename detection
* fix: ignore cross-origin basename hints
* fix: keep root deployments from inheriting asset basenames
Router basename detection must support root hosting and path-prefix hosting at runtime.
The icon fallback used /icons/icon-192x192.png as a basename on root deployments.
After login, React Router mounted at /icons while the current URL was /.
That mismatch made authenticated root deployments render a blank page.
Strip known asset directories even when they are the only path segment.
Root icon URLs now keep basename ''. Prefixed /ai/icons/... URLs still resolve to /ai.
---------
Co-authored-by: JohnGenri <myname945@gmail.com>
Co-authored-by: Simos Mikelatos <simosmik@gmail.com>
* 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.
FixesCoderLuii/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>
* fix: refresh Claude auth status after login flow
* fix: rely on refreshed auth status after login
---------
Co-authored-by: HolyCode User <noreply@holycode.local>
PromptInputSubmit already has type="submit" via the parent form, so the
button's click triggers handleSubmit through the form's onSubmit path.
The added onMouseDown/onTouchStart handlers created two extra paths that
both invoked handleSubmit; on iOS Safari a single tap could fire both
touchstart and a synthetic mousedown before isLoading state propagated,
producing two messages and two image-upload roundtrips.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>