Commit Graph

1981 Commits

Author SHA1 Message Date
陈大猫 a78c052d86 perf(autocomplete): skip completion queries when nothing is shown (#1088)
fetchSuggestions ran the full completion pipeline (history scan, fig specs, remote path lookups) on the main thread even when both the popup and ghost text were disabled — the results were then discarded. Add a shouldQueryCompletions(settings) gate and bail out early (clearing any stale state) when neither display mode is on.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:39:49 +08:00
陈大猫 e6b0a551e8 perf(terminal): isolate autocomplete re-renders into a child component (#1089)
The autocomplete hook (useState) lived in Terminal, so every suggestion / selection / live-preview update re-rendered the whole ~2775-line Terminal component. Move the hook and its popup into a dedicated <TerminalAutocomplete> component so those frequent state updates re-render only that small subtree.

The hook's handlers are surfaced back to Terminal via refs (the same refs already used to wire the xterm runtime), and the component is mounted unconditionally so the hook keeps recording command history and intercepting completion keys for the session's lifetime. No behavior change intended.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:39:38 +08:00
陈大猫 38775245d2 perf(terminal): bound the connection log with a chunk ring buffer (#1087)
* perf(terminal): bound the connection log with a chunk ring buffer

The connection log kept the last 1,000,000 chars via `log += chunk; log = log.slice(-MAX)`. Once a session emits more than that, the slice flattens a ~1M-char string on every subsequent output chunk — on the render thread, for each echoed keystroke included — on long/busy sessions.

Replace the string with a small chunk-queue ring buffer that trims only the boundary chunk (amortized O(chunk) append) and materializes the full string once on read. Behavior is unchanged: it still retains exactly the last MAX_CONNECTION_LOG_DATA_CHARS characters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* perf(terminal): coalesce connection log into bounded blocks (O(1) trim)

The first cut used one array entry per append and trimmed with chunks.shift(). For interactive output (many tiny chunks) the array grows toward the cap in entries, so once full, shift() reindexes ~N elements on every append — O(appends) per chunk, no better than the slice it replaced.

Coalesce appends into a small, bounded set of fixed-size blocks (~maxChars/blockSize). New data fills an open tail that seals into a block at blockSize; trimming only drops/slices a handful of blocks. Adds segmentCount() and a test asserting the segment count stays bounded across many tiny appends.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:39:02 +08:00
陈大猫 fcb699ffb9 chore(eslint): lint electron/bridges for undefined references (#1086) 2026-05-25 13:53:53 +08:00
陈大猫 e889d8fc20 perf(terminal): flush shell output on the event-loop turn instead of a fixed 8ms timer (#1085)
* perf(terminal): flush shell output on the event-loop turn, not a fixed 8ms timer

SSH/PTY output was coalesced and shipped to the renderer on a fixed 8ms timer. For interactive use that interval is pure added latency: every echoed keystroke waits out the timer before it can paint, so typing feels slightly behind.

Replace the timer with turn-based (setImmediate) coalescing in a single shared ptyOutputBuffer module, used by the SSH, local, telnet, and mosh paths. A single echoed keystroke is now forwarded almost immediately, while data arriving in the same turn still collapses into one IPC send, and a 16KB size cap still forces an immediate flush under heavy output.

Also de-duplicates two copies of the buffering logic (SSH had an inline copy; local/telnet/mosh shared another) and adds unit tests for the buffer.

Related to #1084.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(terminal): drop orphaned flushTimeout reference in SSH close handler

The SSH stream "close" handler still cleared `flushTimeout`, a variable that lived in the inline buffer removed when this path moved to the shared ptyOutputBuffer. Reading it now throws ReferenceError on every channel close, aborting the cleanup and exit signaling. The shared buffer's flush() cancels any pending flush internally, so the timer bookkeeping is removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 13:42:49 +08:00
陈大猫 bf1c95500a feat #826: optional Option+←/→ word jump on macOS (#1082)
* feat #826: optional Option+←/→ word jump on macOS

Adds a Terminal → Keyboard toggle "Option+←/→ jumps by word" (off by default,
synced). When on, a bare Option+Left/Right sends Meta-b / Meta-f instead of
xterm's default ^[[1;3D / ^[[1;3C, so readline/zle moves by word without
per-host bindkey setup (Termius-style).

The key→sequence mapping is a tested pure function; the handler reads the
setting live (no reconnect) and runs after kitty mode + autocomplete so it
doesn't override them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #826: gate Option+←/→ word jump to macOS

The setting is syncable, so without a platform gate, enabling it on a Mac
would also rewrite Alt+←/→ to Meta-b/f on synced Linux/Windows devices,
breaking apps/shells that expect the default ^[[1;3D / ^[[1;3C. Pass
isMacPlatform() into the mapping so it only applies on macOS; add a test
for the non-macOS case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.1.12
2026-05-25 00:10:40 +08:00
陈大猫 f9d00c9d23 fix #1079: preserve remote file mode when rz overwrites a same-named file (#1081)
* fix #1079: preserve remote file mode when rz overwrites a same-named file

#1070's overwrite path rm's the remote file and lets rz re-create it, which
writes with the remote umask and drops the original permission bits — e.g. a
0755 script became 0644 after choosing "replace". (It didn't happen before
because rz used to skip same-named files, leaving the original untouched.)

Capture each conflicting file's mode during the pre-upload probe
(stat -c %a, BSD stat -f %Lp fallback) and chmod it back once the transfer
finishes and the files are on disk. Restore is best-effort: any failure
silently falls back to today's behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1079: probe file mode with `stat -- "$n"` for dash-prefixed names

Without `--`, `stat -c %a "-x.sh"` (and the BSD `-f %Lp` fallback) parse a
leading-dash filename as options, so the mode was never captured and overwrite
fell back to rz defaults — losing permission preservation for a valid filename
class. Mirrors the existing `rm -f --` handling. (chmod left as-is: its path is
always absolute, and BSD chmod doesn't accept `--`.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 23:44:41 +08:00
陈大猫 8fd7ff6475 fix #1078: send macOS Option as Meta (wire altAsMeta to xterm macOptionIsMeta) (#1080)
"Use Option as Meta key" was read into `altIsMeta` but only applied to the
mouse alt-click options (`altClickMovesCursor`). xterm.js's `macOptionIsMeta`
— the option that actually makes Option emit ESC-prefixed (Meta) sequences —
was never set, so on macOS Option kept producing layout characters (ƒ, ∫, …)
and readline/zle word shortcuts (Alt+f, Alt+b, Alt+Backspace) were dead.

Extract the altAsMeta→xterm mapping into one tested helper used by both the
terminal init path (createXTermRuntime) and the live settings sync
(Terminal.tsx) so the two can't drift again.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 23:30:35 +08:00
陈大猫 02c80ae7d2 chore: silence two production build warnings (#1072)
- Drop the manualChunks 'vendor-react' entry: react/react-dom already land
  in another chunk, so it only ever produced an empty chunk + a build
  warning, with no caching benefit.
- Import domain/syncMerge statically in useAutoSync. It's already in the
  eager graph via CloudSyncManager's static import, so the dynamic
  `import()` couldn't be code-split anyway and only emitted a mixed
  static/dynamic-import warning.

No behavior change; production build is warning-free.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.1.11
2026-05-23 13:50:33 +08:00
陈大猫 e5d3d02b17 fix #1063: give each terminal its own WebGL texture atlas (disable cross-terminal sharing) (#1071)
Root cause of the persistent split-view 花屏: xterm's WebGL addon shares
ONE TextureAtlas across terminal instances with equal config (font / size
/ theme / DPR) — acquireTextureAtlas does `if (configEquals) { ownedBy.push;
return atlas }`. Two split panes then share an atlas, so the
clearTextureAtlas calls netcatty makes to recover from glyph corruption
(on resize / DPR / font change / tab show, from #1049 and #1066) clobber
the *other* pane's rendering. That's why the earlier redraw/clear-based
recovery attempts didn't help and only bounced the garble between panes.

Disable the sharing: remove the "reuse a matching atlas" loop so every
terminal creates its own atlas. The published bundle is minified, so this
is done with a small idempotent postinstall script (a patch-package patch
would be a ~550KB unreadable blob of the whole minified line). It
string-replaces the exact loop in the CJS + ESM builds, runs after
patch-package, and warns without failing if @xterm/addon-webgl changes.

Verified: split-view WebGL no longer garbles; script is idempotent
(patched=2 → already=2) and the production build is unaffected.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 13:45:05 +08:00
陈大猫 78186d8d46 feat #1064: prompt to overwrite when rz upload hits a remote filename conflict (#1070)
* feat #1064: add buildUploadPlan for rz overwrite/skip/cancel resolution

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1064: handle remote filename conflicts in rz handleUpload

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1064: SSH exec probe + remove for rz upload conflicts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1064: IPC for rz overwrite-conflict prompt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1064: renderer prompt for rz overwrite conflicts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1064: repair sshBridge test mock (ipcMain.on) and i18n the overwrite dialog

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1064: make upload plan index-based to preserve per-file decisions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 12:20:20 +08:00
陈大猫 c899653621 fix #1065: resolve terminal cwd through su/sudo for the SFTP locate (#1068)
* fix #1065: resolve terminal cwd through su/sudo for the SFTP locate

The SFTP "locate to terminal's current directory" feature kept showing the
login user's home (e.g. /root) after the user switched accounts with su /
sudo -s and cd'd elsewhere.

getSessionPwd walks the remote process tree from a sibling exec channel to
find the interactive shell's cwd, but it only followed children whose comm
is a shell name (bash/zsh/...). su and sudo are named "su"/"sudo", so the
walk stopped at the login shell and read its cwd. The actual shell the user
is typing in lives *under* su/sudo as the controlling tty's foreground
process group.

Rewrite the walk to pick the deepest foreground shell ("+" in stat) within
the login shell's whole process subtree, which transparently follows
through su/sudo to the active shell, falling back to the login shell when
no foreground shell is found.

Verified on a real server (root -> su user -> cd /tmp):
  before: /root   after: /tmp
and confirmed the no-su case is unchanged (cd /var -> /var).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fall back to login shell cwd when the active shell's /proc is unreadable (Codex review)

When an unprivileged user runs `sudo -s` / `su root`, find_active_shell
correctly selects the root-owned foreground shell, but the exec channel
(running as the login user) cannot readlink another uid's /proc/<pid>/cwd
due to ptrace permissions. Without a fallback the script dropped straight
to the home directory, regressing user→root sessions.

Retry readlink on the same-uid login shell before falling back to home.

Verified live (user -> cd /var -> sudo -s -> cd /tmp): the root shell's
cwd is unreadable, and the result is now /var (login shell cwd) instead of
/home/<user>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Select the interactive (tty-bearing) login shell deterministically (Codex review)

find_login_shell picked the first shell child of sshd and exited, but ps
output is unsorted, so when other exec channels (server-stats polls, etc.)
are running on the same connection their transient sh could be chosen,
making find_active_shell walk the wrong subtree.

Prefer the shell child that has a controlling tty: the interactive shell
has a pts, while non-PTY probe exec channels have tty "?". This is
deterministic regardless of ps order, in both the su and no-su cases (the
old "prefer foreground" heuristic was itself nondeterministic under su).
Falls back to any shell child if none has a tty.

Verified live with a concurrent no-tty `sh -c sleep` under the same sshd:
the pts/0 bash is selected and the result is /tmp, not the probe shell.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 11:26:20 +08:00
陈大猫 a91fbcdd68 fix #1062: treat SSH shell TMOUT auto-logout as a timeout, not a normal exit (#1067)
* fix #1062: treat SSH shell TMOUT auto-logout as a timeout, not a normal exit

A shell-level TMOUT idle auto-logout makes bash/csh exit cleanly (numeric
exit code, no signal), which is byte-for-byte indistinguishable from a
user-typed `exit` at the SSH protocol level. PR #1057 keyed the
close-vs-keep decision on `streamExited` (numeric code + no signal), so
TMOUT exits were reported as reason "exited" and the tab was auto-closed —
reintroducing the problem from #977.

Verified against a real server that bash TMOUT exits with code 0 / no
signal and prints "timed out waiting for input: auto-logout" to the
channel before it closes. Since exit code/signal can't distinguish it from
an intentional exit, detect that banner in the session's existing rolling
output tail (_promptTrackTail) and report reason "timeout" instead, which
routes to the existing markDisconnected path (keep tab + reconnect). A
normal `exit`/`logout` (no "auto-" prefix) still auto-closes the tab, so
PR #1057's behavior is preserved.

zsh's TMOUT raises SIGALRM (a signal), so it already took the
keep-tab/reconnect path and is unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Anchor TMOUT auto-logout match to the banner's final line (Codex review)

The detector matched "auto-logout" as an unanchored substring within the
last 256 chars, so command output that merely mentions it (e.g. `grep
auto-logout /etc/profile` while investigating TMOUT) followed by an
intentional `exit` could be misclassified as a timeout and wrongly keep
the tab open. Anchor on the final non-empty line of output instead — the
banner the shell prints right before exiting — which loses no true
positives (verified against the real-server output shape) while rejecting
mid-stream mentions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 10:53:03 +08:00
陈大猫 74b315e285 fix #1063: force WebGL redraw on tab show to recover from garbled multi-tab terminals (#1066)
Hidden tabs stay mounted off-screen (visibility:hidden) so each keeps a
live WebGL context. Creating another terminal's WebGL context — or the GPU
dropping a non-composited off-screen canvas — leaves the hidden terminals'
drawing buffers corrupted ("花屏"). This reproduces on both Windows and
macOS: opening 2 tabs garbles the 1st, opening 3 garbles the 1st and 2nd,
while the just-created (visible) one is always fine. The DOM renderer is
immune because it uses real DOM nodes.

A window resize recovers the display because it triggers a full repaint
(clearTextureAtlas + RenderService._renderRows). A tab switch did not:
the visibility effect only calls safeFit, which early-returns when the
pane's dimensions are unchanged, so no redraw happened.

Perform the same recovery a resize does when a tab becomes visible:
clear the texture atlas (no-op on the DOM renderer) and synchronously
repaint every row. Verified against xterm core that _renderRows draws
unconditionally, independent of dimension changes or dirty-row tracking.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 09:56:30 +08:00
陈大猫 60eeafe7a9 feat #1005: Termius-style live-preview popup autocomplete (free the Tab key) (#1059)
* feat #1005: add live-preview keystroke calculator for popup autocomplete

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1005: live-render the selected popup suggestion on arrow navigation

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1005: free Tab for the shell; Enter runs the rendered line; Esc reverts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1005: show key hint (→ expand / ↵ run) on the selected popup row

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat #1005: live-render full path while navigating sub-directory panels

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test #1005: move live-preview test into the npm test glob

The test runner only scans components/terminal/*.test.ts (not the
autocomplete/ subdir), matching where the other autocomplete-module tests
live (e.g. completionEngine.test.ts). Relocate so it actually runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1005: center and refine the popup key-cap hint

Use inline-flex centering (the ↵ glyph was vertically off with line-height +
padding), softer color-mixed border/background, a system-sans font so the
glyph renders consistently regardless of the terminal font, and the more
balanced ⏎ return symbol.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1005: record the actual executed line on Enter, not the stale suggestion

Codex review (P2): the popup Enter handler recorded selected.text and
suppressed handleInput's recorder, so editing a previewed command (select
docker, type ' ps', Enter before the re-query) logged the stale 'docker'
instead of 'docker ps'. Delegate to handleInput's Enter path, which records
lastAcceptedCommandRef on a clean select and falls back to the live buffer
after an edit (typing nulls that ref).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix #1005: don't revert user edits when Escape closes the popup

Codex review (P2): previewActiveRef stayed true after the user edited a
previewed command, so Escape (before the debounced re-query reset state)
called renderPreviewSelection(-1) and rewrote the line back to the stale
baseline, dropping the edits. Clear previewActiveRef when the user types
(alongside the existing lastAcceptedCommandRef reset), so Escape only reverts
a pristine preview and otherwise just dismisses the popup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.1.9
2026-05-22 23:58:57 +08:00
陈大猫 ee2c21e712 feat #1044: close tabs with the middle mouse button (#1058)
Middle-clicking a tab (mouse wheel click) is a conventional "close tab"
gesture in browsers and editors. Wire it to every closeable tab strip:
the top session / workspace / log-view / editor tabs and the SFTP tab bar.

A small shared helper (lib/tabInteractions.ts) handles the gesture:
onAuxClick closes the tab when button === 1, and onMouseDown calls
preventDefault for the middle button so the Chromium/Electron autoscroll
overlay does not appear. Left-click activation and right-click context
menus are untouched.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 22:58:19 +08:00
陈大猫 e678ad3546 fix terminal exit auto close (#1057) 2026-05-22 22:49:15 +08:00
陈大猫 c47c780b48 fix s3 checksum compatibility (#1056) 2026-05-22 22:41:25 +08:00
陈大猫 88074ac9b3 fix auto sync remote checks (#1055) 2026-05-22 22:26:05 +08:00
陈大猫 59cb0c4b65 fix #1043: skip pwd probe on network devices to keep Huawei VRP sessions alive (#1052) 2026-05-22 22:06:03 +08:00
陈大猫 bf0bd193eb fix #1049: clear WebGL texture atlas to recover from garbled terminal (#1050)
Heavy full-screen TUIs (claude code / gemini cli / opencode), font changes,
and device pixel ratio changes can leave xterm.js's WebGL glyph texture atlas
in a corrupted state that persists for the life of the terminal — users see
persistent "garbled / 花屏" output that only clears when a brand-new terminal
is opened (most often on Windows with display scaling / multi-monitor setups).

Clear the texture atlas so glyphs re-rasterize at the correct scale instead of
forcing users to reopen the terminal:

- Add watchDevicePixelRatio() helper (TDD, unit-tested) that re-registers a
  matchMedia listener across DPI changes and fires a repair callback.
- Wire it into createXTermRuntime: on devicePixelRatio change, clear the atlas
  and refit; also clear the atlas on reflow (term.onResize). Watcher is torn
  down on dispose.
- Expose clearTextureAtlas() on XTermRuntime and call it after font changes in
  Terminal.tsx (xterm.js #3280). All calls are no-ops under the DOM renderer.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 18:25:38 +08:00
陈大猫 7661375925 fix huawei vrp ssh detection (#1046) 2026-05-22 01:05:46 +08:00
陈大猫 308fb45985 fix comware legacy ssh handshake (#1045) 2026-05-22 00:13:59 +08:00
陈大猫 f4aa6ddb46 fix #1013: stop ghost text from drawing over untracked echoed input (#1042)
Inline (ghost-text) suggestions render suggestion.substring(trackedInput.length)
after the cursor, where trackedInput is a client-side reconstruction of the
command line (buffer heuristics + keystroke prediction, to mask SSH echo
latency). On hosts with non-standard echo — hardware bastion hosts / network OS
like `ecOS#` (#1013, previously #756 / #906) — that reconstruction drifts and
the ghost gets painted over characters the user already typed (`int` + ghost
`terface` -> `intterface`).

Add a fail-safe consistency check: on each post-echo render, if the real
terminal line before the cursor contains the tracked input followed by more
untracked, non-whitespace characters (reality is AHEAD of what we tracked),
hide the ghost instead of drawing it over real text. SSH echo latency is the
opposite case (the line is a prefix-behind of the tracked input) and is
deliberately not flagged, so the ghost stays responsive on slow links. The
check is ASCII-only (wide-char column mapping is ambiguous) and fail-open, so
it can only ever suppress a ghost that would otherwise corrupt — never change
correct behaviour.

This converts the recurring "ghost shows already-typed characters" bug into
"ghost simply doesn't show" on devices we can't track reliably.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.1.8
2026-05-21 15:40:35 +08:00
陈大猫 f6cb73fdd6 fix #1040: unique macOS Mach-O LC_UUID for Local Network privacy (#1041)
macOS keys the "Local Network" privacy permission on the main executable's
Mach-O LC_UUID (Apple TN3179). Electron's prebuilt binary is linked with LLD,
which derives the UUID from a content hash, so every app built from the same
Electron version ships the *same* LC_UUID even with a different bundle id. That
collision makes the grant unreliable: a user who enables Local Network for
Netcatty can still hit `connect EHOSTUNREACH` on LAN / VMware host-only
addresses, while loopback-forwarded connections work.

Add an electron-builder afterPack hook that rewrites the packaged macOS
executable's LC_UUID to a value derived deterministically from the appId —
stable across builds (so the grant survives updates) but distinct from every
other app. It runs before code signing, so signature/notarization cover the
patched binary. No-op on Windows/Linux.

Verified the rewrite on a copy of Electron's binary (LC_UUID changes, file
stays a valid Mach-O, deterministic) and added unit tests for the Mach-O
patcher (thin + fat) and the UUID derivation.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 15:11:25 +08:00
陈大猫 3c100b0ae2 fix #1035: support diffie-hellman-group1-sha1 under BoringSSL (#1039)
Electron's BoringSSL dropped several standard MODP groups from the named
crypto.createDiffieHellmanGroup() API — notably the 1024-bit Oakley Group 2
(modp2) that backs SSH's diffie-hellman-group1-sha1. ssh2 calls
createDiffieHellmanGroup('modp2') for that kex, so connecting to legacy
network devices that only speak group1-sha1 failed with "Error: Unknown DH
group".

The underlying DH math still works on BoringSSL via createDiffieHellman()
with an explicit prime, so add a compatibility shim that wraps
createDiffieHellmanGroup and falls back to the well-known prime constants
when (and only when) the runtime can't resolve a group by name. On OpenSSL
builds the original call succeeds and the fallback is never used.

The shim is installed in main.cjs before any ssh2-using bridge loads, since
ssh2 destructures createDiffieHellmanGroup at module load. Once installed,
the existing legacy-group probe detects modp2 as supported again and offers
group1-sha1, so affected devices actually connect (still gated behind the
per-host legacy-algorithms toggle).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:51:50 +08:00
陈大猫 168e42b5fa fix slow first SSH connect from DH group probe under BoringSSL (#1038)
The fixed-DH-group support probe called crypto.createDiffieHellmanGroup()
for each MODP group to feature-detect runtime support. Under Electron's
BoringSSL, instantiating the large groups is pathologically slow
(modp18/8192-bit takes ~20s on first call), and the result is only cached
in-process, so the first connection after every app launch froze for ~24s.

The standard modern groups (modp14/16/18) are universally supported and
always pass the probe anyway, so treat them as supported without probing.
Only groups a runtime may genuinely drop (e.g. BoringSSL removed the weak
1024-bit group1/modp2) are still feature-detected; those fail instantly.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:35:20 +08:00
陈大猫 2ce6bd5ed1 [codex] Reorder legacy SSH group-exchange fallback (#1034)
* reorder legacy ssh kex fallback

* add ssh handshake debug logging
2026-05-21 11:30:24 +08:00
陈大猫 7bd5d6465a fix claude system cli detection (#1033) 2026-05-21 00:11:51 +08:00
陈大猫 65387d4c61 fix legacy group exchange sha1 (#1032) 2026-05-20 23:19:07 +08:00
yuzifu 6084e8e94f fix(terminal): handle forced prompt newline (#1025)
* fix(terminal): handle forced prompt newline

* fix review issue

* fix(terminal): harden prompt newline handling

---------

Co-authored-by: yuzifu <yuzifu@TB16PGen5.Info>
Co-authored-by: bincxz <16399091+binaricat@users.noreply.github.com>
2026-05-20 23:08:42 +08:00
陈大猫 3ccc5c9fc6 Fix broadcast hotkey refresh (#1030) 2026-05-20 16:30:25 +08:00
陈大猫 d07859f604 [codex] Prevent terminal host preference pollution (#1026)
* Prevent terminal host preference pollution

* Preserve terminal host updates while isolating session ports
2026-05-20 11:51:54 +08:00
陈大猫 88a322a03b [codex] Filter terminal cursor replies from broadcast input (#1022)
* Filter terminal CPR from broadcast input

* Handle split cursor reports in broadcast
2026-05-20 11:12:27 +08:00
陈大猫 0e02bbc2fb [codex] Persist vault host sort mode (#1021)
* Persist vault host sort mode

* Harden vault host sort persistence tests
2026-05-20 10:53:20 +08:00
陈大猫 affd9217e2 Fix session log capture after reconnect (#1020) 2026-05-20 10:53:04 +08:00
陈大猫 7b4a349e3f [codex] Guard unsupported legacy SSH groups (#1023)
* Guard legacy SSH DH groups

* Align legacy SFTP algorithms
2026-05-20 10:52:52 +08:00
陈大猫 7dc5ab5035 [codex] Use terminal cwd when opening SFTP (#1024)
* Use terminal cwd when opening SFTP

* Clear stale terminal cwd for SFTP open
2026-05-20 10:52:35 +08:00
yuzifu 3e8965f9a9 Fix pr987 (#1010) 2026-05-19 20:13:16 +08:00
陈大猫 23a27bf544 Handle missing streamed tool call ids (#1007) 2026-05-19 11:29:50 +08:00
陈大猫 86a815ad46 [codex] Optimize terminal tab switching (#1003)
* Optimize terminal tab switching

* Reduce themed tab switch repaint work
v1.1.7
2026-05-18 22:19:54 +08:00
陈大猫 cb4fb091aa [codex] Fix browser loading of shared rule files (#1002)
* Fix local shell browser import

* Fix command blocklist browser import
2026-05-18 21:05:33 +08:00
陈大猫 b30696c98b Clean up dead code and duplicated helpers (#1001) 2026-05-18 20:00:10 +08:00
bincxz 6b8f05c65a Merge branch 'codex/fix-russian-settings-sync-icon' 2026-05-18 19:23:44 +08:00
bincxz 64dd3a4a2f Fix settings sidebar icon clipping 2026-05-18 19:23:36 +08:00
yuzifu 88732040aa fix(terminal): separate prompt after unterminated command output (#987)
* fix(terminal): separate prompt after unterminated command output
Add a display-layer prompt line break handler so recognized shell prompts move to the next visual line when the final command output line is not newline terminated.

Also add a terminal setting to toggle the behavior, sync support, i18n copy, and focused tests for prompt insertion.

* fix review issue

* Fix prompt cache initialization

* Serialize terminal output writes for prompt breaks

* Keep terminal status lines ordered with output

* Fix prompt arming without command callback

* Keep prompt display breaks out of session logs

* Avoid prompt breaks for output suffix matches

---------

Co-authored-by: yuzifu <yuzifu@TB16PGen5.Info>
Co-authored-by: bincxz <16399091+binaricat@users.noreply.github.com>
2026-05-18 18:45:41 +08:00
ウィール スペース b9f3bfa8bb Add i18n russian (#991)
* add i18n russian

* Added the Russian translation

* Complete Russian SFTP transfer translations

* Add Russian reconnect menu translation

---------

Co-authored-by: bincxz <16399091+binaricat@users.noreply.github.com>
2026-05-18 16:55:02 +08:00
陈大猫 b7ec3c12f7 Handle ConPTY controls in Mosh password prompts (#1000) 2026-05-18 15:44:58 +08:00
DeepFal d20a18b862 Fix AI code block rendering fallback (#983) 2026-05-18 13:19:30 +08:00
陈大猫 ff6b4a4625 Broadcast pasted terminal input (#927) (#996)
* Broadcast user paste to terminals

* Use workspace session id for context paste broadcast

* Consume paste broadcast suppression before toggle check
2026-05-18 11:53:14 +08:00