Commit Graph

13 Commits

Author SHA1 Message Date
Ryanisgood
52bc48f73a 为主机添加可自定义图标和颜色 (#1504) 2026-06-17 23:32:36 +08:00
陈大猫
f5c3302329 feat: terminal rename, closeSession shortcut, and pane zoom (#1459)
* feat: auto-poll Docker capabilities while Docker tab is active

When the Docker tab is visible and hasDocker is not yet true,
poll refreshCapabilities() at the process refresh interval.
Stop polling once hasDocker becomes true, or when switching
to a different tab.

* fix: use resolvedTab instead of activeTab for Docker auto-poll condition

The auto-poll useEffect condition used activeTab, which stays stale
when Docker becomes unavailable. Changed to resolvedTab which reflects
the actual displayed tab. Also updated the dep array.

* fix: replace setInterval with setTimeout recursion in Docker tab probe

Replace setInterval-based polling with setTimeout recursion in the Docker
tab capability probe effect. This ensures the next probe only starts after
the previous one finishes, avoiding overlapping probes when SSH timeout
exceeds the polling interval.

- Add dockerPollTimerRef to track the timeout handle
- Use async pollOnce() that awaits refreshCapabilities() before scheduling next
- Use cancelled flag in cleanup to prevent scheduling after unmount
- Keep same dependency array for correctness

* fix: stabilize docker poll timer by using useRef for refreshCapabilities

refreshCapabilities() can return a new reference on every render, causing
the useEffect to re-run on every render — cleanup cancels the polling timer,
then the effect immediately calls pollOnce(), effectively bypassing the
configured timeout interval.

Fix: store refreshCapabilities in a useRef (refreshRef), use
refreshRef.current() inside pollOnce(), and replace refreshCapabilities
with refreshRef in the useEffect dependency array.

Closes #PR1456 Codex P2 review item.

* fix: delay auto-poll first probe by one interval to avoid overlap with tab-switch probe

When switching to the Docker tab, two mechanisms were triggering probes:
1. tab-switch effect (line 67-76): immediate probe via refreshCapabilities()
2. auto-poll effect: pollOnce() executing immediately on mount

This caused duplicate probes that waste SSH channel resources.

Fix: pollOnce() no longer fires on mount. Instead, the effect schedules the
first probe with setTimeout(pollOnce, capabilitiesTtlMs), so the first probe
happens after one full interval. Subsequent probes continue at interval pace
via the setTimeout recursion in pollOnce itself.

The tab-switch effect still fires the immediate probe (the correct one),
so responsiveness on tab switch is preserved.

* fix: reset cancelledRef in effect body to prevent permanent stalling of Docker polling

The cancelledRef was set to true in the cleanup function when dependencies
changed, but never reset when the effect re-ran. This caused pollOnce to
always early-return on subsequent timer ticks, permanently halting
Docker capability probing after the first dependency change.

* fix(system-manager): replace cancelledRef with closure variables for per-effect cancellation

Each effect generation now has its own  and  closure
variables instead of shared  / . This
prevents stale probes from surviving cleanup when the panel hides and
re-shows (Codex P2 review).

* fix: wrap refreshCapabilities in try/catch to keep polling on exception

If refreshCapabilities throws (instead of returning {success: false}),
the await would exit pollOnce without scheduling the next setTimeout,
silently killing Docker auto-detection polling.

* fix: add in-flight probe guard to prevent tab-switch and auto-poll concurrent probes

Add probingRef to track whether a capabilities probe is already in-flight.
- Tab-switch effect for Docker branch checks probingRef before starting a new probe
- Auto-poll pollOnce checks probingRef at entry and sets/clears it around the actual probe
- Tmux branch left unchanged as it has no auto-poll overlap risk

* fix: re-schedule next poll timer when probe is in-flight

When probingRef.current is true (tab-switch probe still running),
pollOnce was returning early without scheduling the next timer,
causing auto-poll to stop permanently afterward.

Now it schedules the next poll within the interval and returns,
so the polling loop keeps running until a slot where no probe is
active.

* fix: convert comments to ASCII-only English

- Line 105: translate Chinese comment to 'probe is in-flight, reschedule for next cycle'
- Line 113: replace em dash (U+2014) with ASCII dash

* feat: session inline rename, closeSession shortcut, pane zoom

* fix: sidebar inline rename with local state

* fix: add sessionDisplayName to terminalPropsAreEqual comparator

The Terminal component is wrapped with React.memo(…, terminalPropsAreEqual),
but the comparator was missing a check for sessionDisplayName. After renaming
a session, the pane title bar would show the old name until some other prop
changed and triggered a re-render.

Add prev.sessionDisplayName === next.sessionDisplayName to the comparator
so that display name changes cause the Terminal to re-render immediately.

* fix: add onStartSessionRename to TerminalLayerWorkspaceSection ctx destructuring and TerminalPanesHost props

* fix: add toggleWorkspaceViewMode to executeHotkeyActionImpl destructuring

The togglePaneZoom handler calls toggleWorkspaceViewMode() but it
wasn't destructured from getCtx(), causing a ReferenceError at runtime.

* fix: restore truncated ctx object in TerminalView render call

The TerminalView ctx object literal on line 1265 was truncated to
'showSele...' due to an editing tool truncation bug, causing
Parsing error: ',' expected on npm run lint / tsc --noEmit.

Restored the missing fields from the base commit:
showSelectionAIAction, snippets, status, statusDotTone, sudoHintRef,
sudoHintText: t("terminal.sudoHint.pressEnter"), t, termRef,
terminalBackend, terminalContextActions, terminalCwdTracker,
terminalPreviewVars, terminalSettings, timeLeft, toast, zmodem

Kept the PR's new additions (isVisible, onRename, sessionDisplayName)
intact.

* fix: add toggleWorkspaceViewMode to executeHotkeyAction context and add terminal.menu.rename translations

- Add toggleWorkspaceViewMode to the context getter in executeHotkeyAction (App.tsx)
- Add terminal.menu.rename translation for en (Rename), zh-CN (重命名), ru (Переименовать)

* fix: validate focusedSessionId before closing in closeSession hotkey

When closeSession hotkey fires, workspace.focusedSessionId may reference
a session that was already closed by another trigger (e.g., mouse click
on tab close button). Collect alive session IDs from the workspace root
and fall back to the first living pane if the stored focusedSessionId
is stale.

* fix(auto-poll): check useSessionCapabilities probing state in pollOnce

When auto-poll timer fires before the initial probe (from
useSessionCapabilities) completes, probingRef.current is still false
because the initial probe doesn't set it — causing a second overlapping
probe.

Add  check so that any in-flight probe from any path
(initial/auto-poll/tab-switch) prevents auto-poll overlap.

PR #1459

* fix: address remaining Codex review issues

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat: add detach session from workspace with toolbar button and context menu

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: use customName in pane header display name for renamed sessions

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: refine workspace terminal detach interactions

* fix: preserve workspace detach tab ordering

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 01:30:44 +08:00
陈大猫
a5b0efba75 fix(hotkeys): toggle quick switcher with the same shortcut (#1384)
Allow the quick switch shortcut to close the panel when pressed again,
including while the search input is focused, so users are not limited to
clicking outside to dismiss it.

Closes #1355

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 23:00:13 +08:00
bincxz
14fe1e3ecb feat(shortcuts): add option to skip pinned tabs for number keys
Fixes #1375 by letting Cmd/Ctrl+[1...9] target only work tabs when enabled, while keeping the existing Terminus-style default.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 19:15:15 +08:00
bincxz
555c00406e Polish vault and log icons 2026-06-10 10:41:42 +08:00
陈大猫
29a6172120 Add duplicate tab to new window
Adds a tab context menu action to duplicate a terminal into an independent peer window, with per-window active-tab titles and multi-window lifecycle safeguards.
2026-06-06 22:13:47 +08:00
bincxz
2867262e4d Add per-host sudo password autofill 2026-06-06 20:47:16 +08:00
bincxz
9d0f6a9cea Merge origin/main into feat/et 2026-06-04 18:12:54 +08:00
陈大猫
008890a688 feat(terminal): 自定义本地 Shell 支持启动参数 (#1221) (#1225)
* feat(terminal): 支持为自定义本地 Shell 配置启动参数 (#1221)

自定义本地 Shell 此前只能填可执行文件路径,无法指定启动参数,
导致接入 msys2 bash 时缺少 `--login -i`,shell 不经 profile 初始化、
环境变量缺失而无法使用。

- TerminalSettings 新增 localShellArgs(string[],默认 []),随设置自动迁移
- 新增 domain/shellArgs:引号感知的命令行分词/回显格式化
- resolveShellSetting 透传自定义参数;参数为空时回退到 bridge 默认参数,
  命中已发现 shell(WSL/Git Bash)时忽略自定义参数,避免串味
- 自定义 Shell 弹窗新增「启动参数」输入,设置行展示完整命令(en/zh-CN/ru)

参数复用已有管线 session.localShellArgs → startLocalSession → pty.spawn,
不涉及云同步(与机器相关的 localShell 一致,均不同步)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(terminal): 修复自定义 Shell 参数的两处 review 问题

- 切换到默认/已发现 shell 时清空 localShellArgs:自定义参数仅对自定义
  路径有意义,清空可避免在发现列表尚未加载(启动竞态)或所选 shell ID
  在本机不可用时,旧参数被当作该 shell 的启动参数而泄漏导致启动失败
- formatShellArgs 对含双引号的参数改用单引号包裹,修复 `-c "..."`
  这类参数重新打开弹窗保存时被破坏的往返问题

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(terminal): shellArgs 量化处理含两种引号的参数往返

采用单引号优先的引号策略:单引号内全字面(Windows 路径、双引号原样保留,
无需转义);仅当 token 自身含单引号时改用双引号包裹并转义 \ 与 "。
解析端仅在双引号区内将 \" / \\ 视为转义,其余反斜杠保持字面,
确保未加引号的 Windows 路径不被破坏。修复 `echo "it's ok"` 这类同时含
单双引号的参数在弹窗重新保存时被破坏的问题。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(terminal): 自定义 Shell 已选中后可重新打开编辑参数

自定义 shell 选中时下拉框值已是 __custom__,再次点选「自定义…」不会触发
onValueChange,导致无法重新打开弹窗修改参数/路径。改为把自定义 shell 概要
做成可点击的编辑入口(铅笔图标),点击即重新填充草稿并打开弹窗;
打开逻辑抽到 openCustomShellModal 复用。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(terminal): shellArgs 改用 POSIX 单引号方案,修复尾部反斜杠与空参数

- 解析:两种引号区内均全字面(双引号不再把 \" 当转义),保留 Windows
  路径尾部反斜杠等手输入;引号外仅 \' 转义为字面单引号(支撑 '\'' 习语),
  其余反斜杠保持字面,未加引号的 Windows 路径不受影响
- 格式化:统一单引号包裹(内容全字面),内嵌单引号用 POSIX '\'' 习语;
  显式空参数输出为 '' 以免重新保存时被丢弃

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(terminal): customArgs take precedence over discovered shell defaults when user explicitly sets them

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 11:07:13 +08:00
lateautumn233
816e274dfc Route ET protocol through application session state and backend
Resolve 'et' protocol in tray panel and host connection handlers with
priority over mosh. Propagate etEnabled through session factories and
useSessionState. Expose etAvailable guard and startEtSession wrapper
in useTerminalBackend.
2026-06-03 01:45:28 +08:00
陈大猫
63b95bb68e [codex] add terminal font size shortcuts 2026-06-01 15:25:31 +08:00
陈大猫
94b8f298ae feat(vault): connect with the host's default protocol, prompt only for Telnet (#1163)
Issue #1099: a Telnet host shows the protocol picker on every connect. Connect resolution is now explicit, and the picker only appears when it's genuinely a choice:

- Telnet set as default (protocol = telnet) -> connect Telnet (single-click and batch)
- Telnet enabled but not the default -> show the picker (unchanged)
- Mosh enabled -> connect Mosh
- otherwise -> connect SSH

A "Connect with Telnet by default" switch in the Telnet card sets the host's primary protocol. SSH+Mosh hosts now connect Mosh directly instead of prompting every time. Addresses part 1 of #1099.

Refs #1099

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 12:38:14 +08:00
陈大猫
1fec5925eb Refactor large modules and fix runtime errors (#1136) 2026-05-28 15:12:19 +08:00