mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-10-09 15:58:34 +00:00
1d91c8fbf4e22d48fe2ff0130784fadfe2062853
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bd12dc663e |
Polish vault host-details and snippet UI.
Truncate long snippet command tooltips, add drag-resize for inline host/group detail panels, and compact appearance override reset controls. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
6b9b71ac8a |
feat(scripts): terminal script automation, recording, and side panel (#1763)
* feat(scripts): add terminal script automation, recording, and side panel Introduce nct script runtime in the main process with terminal-side recording, execution overlay, Monaco editor, connect-script queues, and scripts side panel integration. Fix recording to wire scriptRecorderRef into xterm, use waitForPrompt for root/user shells, and save recorded scripts through the global editor dialog. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): address Bugbot review findings for recording and side panel Refresh script run state in side panel memo, guard toolbar recording against multi-session conflicts, reset connect scripts on reconnect, resolve focused session via getActiveTerminalSessionId, and avoid wiping host edit form when snippets list updates. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): prevent pending script re-run and improve workspace run feedback Track one-shot pendingScript execution separately from onConnect queue so reconnects do not replay Run-now scripts. Fall back to focused session when running on all tabs outside a workspace, and toast when every tab is still connecting. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): consume connect-script window once and filter serial hosts Mark the onConnect script evaluation as consumed even when the queue is empty so later snippet/host edits do not rerun automation mid-session. Restore serial-host filtering in SelectHostPanel confirm handler. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): grace period before giving up on connect-script queue Only mark onConnect automation as consumed after scripts run or a short post-connect grace window expires, so late-loading snippets still trigger while mid-session Vault edits do not. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): gate connect-script consumption on vault hydration Replace the grace timer with vault-init and unresolved host script binding checks so late-loading snippets still run onConnect automation while mid-session edits stay suppressed. Clear pending script run state on disconnect so reconnect retries workspace pending scripts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): honor run targets and retry failed connect automation Route QuickScriptEditorDialog Run through onRunSnippet for multi-host workspaces. Defer connect/pending script completion markers until each script succeeds and retry the queue after failures. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): stabilize pending runs and global connect queue sync Keep pending script run state across reconnects, run onConnect scripts before one-shot workspace pending scripts, and strip per-host queue entries when an onConnect script targets all hosts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): defer host queue snippet sync and guard connect runs Persist snippet target links only when the host panel is saved, block duplicate connect-script scheduling while a batch is running, and require runnable hosts before showing Run in the snippets editor footer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): retry connect failures and surface output-trigger errors Use a retry tick in connect-script effect deps, toast automation failures from output triggers, and require runnable hosts before QuickScript Run. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): track id-less pending runs and re-arm output triggers Remember anonymous pendingScript objects after first run and allow onOutput triggers to fire again when new terminal output arrives. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): unblock paused connect runs and pass session meta Resolve waitForScriptRun on pause, run workspace scripts per session with hostname context, defer output-trigger arming until runs start, and add noRunnableHosts i18n for QuickScript Run. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): serialize output triggers and defer empty connect finalize Fire at most one onOutput trigger per scan while a run is active, and only finalize an empty connect queue after vault snippets are loaded. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): guard output launch race and script run waits Block overlapping onOutput launches, timeout stuck waitForScriptRun promises, and disable vault Run when no connectable targets exist. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): match output triggers on new chunks only Scan onOutput patterns against recent terminal output instead of buffer length dedupe, and restore overflow-visible on SelectHostPanel new-host flow. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): await sequential workspace runs and output launch Wait for each tab script to finish in sequential workspace mode, and hold output-trigger launch guard until the session run becomes active. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): wait through pause and hold output trigger until done Keep connect and sequential workspace queues blocked until scripts complete or fail, and retain output-trigger guard until the launched run finishes. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): harden output trigger wait helpers Add explicit timeouts to output-trigger wait helpers and stop rescanning the buffer after script completion to avoid sticky-match rerun loops. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): allow empty connect queue and match output in new chunks Treat an empty connectScriptIds array as an explicit cleared queue instead of re-migrating from snippet targets, and only fire onOutput triggers when the latest terminal output contains the pattern. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): require fresh output overlap for onOutput triggers Only fire output-matched scripts when the regex match extends into the latest terminal chunk, preventing reruns from stale buffer text. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): promote manual scripts added to host connect queue Diff connect queue changes from raw connectScriptIds so saving a host updates manual scripts to onConnect when they are newly queued. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): dedupe output triggers by match position Track the buffer end offset of each output trigger match and ignore stale re-scans, with a longer wait for run registration before retry. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): record output trigger matches only after run starts Propagate automation launch failures to output triggers and commit match dedupe only once the session run is registered as active. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): address Codex review on wait cursor and sensitive codegen Track scan offset so waitFor/waitForAny only match output after the previous wait, and emit sendLine after sensitive prompt in recorded scripts. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(scripts): harden onOutput triggers against PTY echo and local input Filter server output before pattern matching so onOutput fires only after Enter on real stdout, not on keystroke/paste echo, OSC/SGR sequences, or alternate-screen apps. Add dev diagnostics and scope triggers to the active session when no explicit host targets are configured. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(scripts): remove onOutput trigger debug logging Drop temporary diagnostics module and console traces now that PTY echo filtering is verified; keep the production trigger pipeline unchanged. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
5e00e998a8 | Add vault drag reorder ordering (#1407) | ||
|
|
36e5779d94 |
perf(terminal): reduce terminal tab-switch and layout jank (#1321)
* perf(terminal): smooth layout drags and faster tab switching Defer xterm refit during split, sidebar, and host-tree drags while keeping pane containers in sync with live layout measurements. Refactor TerminalLayer into focused sections with TabBridge/memo optimizations and add the terminal host tree sidebar. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(terminal): keep side panels alive and guard session attach races Prevent terminal boot unmount from leaking backend sessions, keep SFTP/scripts/theme/AI state when switching side tabs, and defer heavy SFTP UI mount so first entry stays responsive. Co-authored-by: Cursor <cursoragent@cursor.com> * perf(terminal): reduce tab switch jank --------- Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
03cd9bc968 | feat(snippets): implement snippet variable handling and UI prompts (#1159) | ||
|
|
ea5320d94a |
Fix #954: unify Tooltip styling + replace native selects (#961)
* Fix #954: unify Tooltip styling + replace native selects Replace native HTML title= tooltips and native <select> dropdowns with the existing Radix-based Tooltip / Select components so they share the app's rounded styling, theme tokens and i18n pipeline. Adds a global TooltipProvider in AppWithProviders so every descendant Tooltip works without a per-file Provider wrapper. Scope (driven by the issue #954 examples and "全部都处理" follow-up): - TerminalLayer toolbar: Add Terminal / Split View / SFTP / Scripts / Theme / AI Chat / Move panel / Close panel. - TopTabs middle bar: quick switcher, more tabs, AI assistant, theme toggle, settings; window-control buttons (min/max/close), tray close and hotkey reset/disable have their native title dropped per the user's explicit opt-out ("可以不用Tooltip,直接全局禁用 原生title 属性"). - AI panels: AIChatSidePanel session history / new chat / delete, ConversationExport, AgentSelector, ChatInput attach / expand / permission, ModelSelector, ProviderCard, ai-elements/tool-call. - SFTP: SftpSidePanel header, SftpBreadcrumb, SftpFileRow, SftpPaneToolbar, SftpTabBar, SftpTransferQueue. - Settings: SettingsPage close, SettingsAppearanceTab theme/accent swatches, SettingsFileAssociationsTab edit/remove, SettingsSystemTab crash-log paths and global hotkey reset. - Host vault: HostDetailsPanel (clear / suggestions / show-password / key path / browse key), GroupDetailsPanel, KnownHostsManager, ConnectionLogsManager, KeychainManager, SyncStatusButton, CloudSyncSettings, LogView, QuickSwitcher, ScriptsSidePanel, Terminal status bar copy-host + broadcast/focus, ZmodemProgressIndicator. - Terminal subcomponents: HostKeywordHighlightPopover, TerminalComposeBar, TerminalConnectionDialog, TerminalSearchBar. - Editor: TextEditorPane (subtitle, search, wrap, promote-to-tab). - TrayPanel session rows and port-forwarding rows. Native <select> migrated to custom Select component: - SerialConnectModal (data bits, stop bits, parity, flow control) - SerialHostDetailsPanel (same four fields) - HostDetailsPanel backspace behavior - GroupDetailsPanel backspace behavior - SettingsTerminalTab local shell picker - terminal/ThemeSidePanel font weight Hardcoded English strings extracted to i18n. New keys for both en and zh-CN: terminal.layer.*, topTabs.*, ai.chat.* (sessionHistory, attach, collapse, expand, enableAgent), zmodem.*, settings.shortcuts. resetToDefault. Inline help text on SnippetsManager package-name input removed because the same hint is already shown in a visible <p> below the input. Existing per-file <TooltipProvider> wrappers (SnippetsManager, ScriptsSidePanel, SelectHostPanel, RuleCard, HostDetailsPanel proxy section) are left in place — they nest harmlessly under the global provider and stay self-sufficient for component tests. Tests: - tsc clean for changed files (pre-existing repo-wide errors unrelated to this PR). - All 802 tests pass (3 skipped pre-existing). - HostDetailsPanel.proxyProfile.test and TextEditorPane.test updated to wrap with TooltipProvider, matching the runtime context now needed by the migrated components. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Fix #954: wrap Settings + Tray windows with TooltipProvider Settings and the tray panel mount as separate Electron windows with their own React root in index.tsx, so they do not inherit the global TooltipProvider added under AppWithProviders. After the unified Tooltip migration, any settings tab that used a Tooltip (Appearance, Application, FileAssociations, System, Shortcuts, Terminal, AI ProviderCard, AI ModelSelector) — and TrayPanel — threw "Tooltip must be used within TooltipProvider" and rendered nothing. Wrap both branches with TooltipProvider at the same level as ToastProvider in index.tsx. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f38afd8bfc |
Align snippet row icons with package row icons in tree (#802)
Snippet rows used a padding-based offset to account for the chevron column in package rows, but the flex gap between chevron and icon wasn't being compensated so the FileCode icon sat 4-6px to the left of the Package icon above it. Mirror the package row's flex layout literally by rendering an invisible chevron placeholder, so both row types share the same column structure. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c3dabbfef2 |
Render snippets sidebar as an expandable tree (#800) (#801)
* Render snippets sidebar as an expandable tree (#800) The terminal sidebar used breadcrumb navigation, so switching between packages meant clicking out and back in. Replace that with a single tree view where each package row has a chevron to expand/collapse (SFTP-style), so snippets across multiple packages stay visible and reachable without drilling. - All discovered packages default to expanded, so the tree matches the user's expectation of seeing everything at once. - Search flattens to a list of matching snippets regardless of nesting, each annotated with its package path so the origin is still clear. - Implicit ancestor packages (e.g. "a/b/c" implies "a" and "a/b") are materialized so deeply nested snippets aren't orphaned when a parent package isn't explicitly listed. - Depth-based left padding + chevron rotation mirror the SFTP tree view's affordances. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Unify snippet row typography with tree + move command to tooltip Snippet rows were rendered as two-line blocks (label + inline command preview), which made them visually taller and heavier than the single-line package rows in the tree, and long commands overflowed the container. Collapse them to single-line rows that match the package row layout exactly (same text size, same padding, aligned icon column) and surface the full label + command text in a tooltip on hover. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Preserve collapsed packages across snippet refreshes (codex) The auto-expand effect compared prev.size to normalizedPackages.size to decide whether to repopulate, but collapsed rows shrink prev.size, so any later snippet/package change would trip the condition and overwrite the user's collapse state with a bulk re-expand. Track the set of packages ever observed in a ref and only auto-expand paths that are new since the previous render. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
8ca09b1616 |
Add right-click Edit/Delete to sidepanel snippets (#780) (#787)
The terminal-side ScriptsSidePanel was the surface the #780 reporter was actually looking at when they asked for right-click delete/modify on snippets. PR #783 closed the issue by adding a trash icon in the Vault edit panel, but the sidepanel snippet rows were still plain <button>s with no context menu — so the original complaint ("右键可以弹出一个菜单, 可以包含'删除, 修改'等操作") remained unaddressed at the exact spot the screenshot came from. Changes: - ScriptsSidePanel: wrap each snippet row in a ContextMenu with Edit and Delete items. Menu actions dispatch window events instead of threading new callbacks — matches the existing netcatty:snippets:add pattern the + button already uses. - QuickAddSnippetDialog: accept an optional onUpdateSnippet prop and listen for netcatty:snippets:edit. Prefills label/command/package from the dispatched snippet, and on save preserves the snippet's original tags/targets/shortkey/noAutoRun (the dialog only exposes the three quick-edit fields). Title flips to snippets.panel.editTitle in edit mode. - App.tsx: pass onUpdateSnippet wired to updateSnippets(map-replace), and register a window listener for netcatty:snippets:delete that filters the deleted id out of snippets. Delete needs no UI so it doesn't go through a dialog. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
683756324e |
feat: add "new snippet" button in terminal ScriptsSidePanel (#641) (#656)
* feat: add "new snippet" button in terminal ScriptsSidePanel (#641) Previously, adding a new snippet required navigating back to the main Snippets section from the Vault view. This adds a "+" button in the search header of the terminal-side ScriptsSidePanel that jumps directly into the snippet edit flow. Flow: - ScriptsSidePanel "+" → dispatches window event `netcatty:snippets:add` - App.tsx listens → switches activeTab to vault, navigates to Snippets section, and bumps a monotonic `openSnippetAddTrigger` state - VaultView forwards the trigger to SnippetsManager - SnippetsManager watches the trigger and opens its add panel when the value changes (uses a ref to ignore unrelated remounts) Closes #641 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: switch add-snippet flow to one-shot pending flag Codex review pointed out a real bug with the monotonic trigger approach: when SnippetsManager mounts for the first time with openAddTrigger already non-zero (the common "+ clicked from terminal while not on Snippets section" path), the last-seen-trigger ref is initialized to the current value and the useEffect immediately returns early, so the add panel never opens. Switch to a cleaner one-shot pending flag: - App.tsx holds pendingSnippetAdd: boolean + handlePendingSnippetAddHandled - VaultView forwards pendingSnippetAdd + onPendingSnippetAddHandled - SnippetsManager opens the add panel on every transition to pendingAdd=true, then clears the flag via onPendingAddHandled, so subsequent renders and plain remounts are no-ops Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move useCallback above early return in ScriptsSidePanel React's rules-of-hooks require all hooks to be called unconditionally. The new handleAddSnippet useCallback was placed after the `if (!isVisible) return null;` guard, which tripped eslint. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
80fbf0da2f |
feat: add data-section hooks for Custom CSS targeting (#642) (#655)
Custom CSS already exists in Settings → Appearance, but major UI
components use only Tailwind utility classes, making it hard for
users to reliably target regions in their custom styles.
This adds stable `data-section="..."` attributes on the root element
of the most commonly customized UI regions so users can write selectors
like `[data-section="snippets-panel"] { font-size: 14px !important; }`
without depending on implementation details.
Instrumented regions:
- snippets-panel (ScriptsSidePanel)
- host-details-panel (HostDetailsPanel via AsidePanel dataSection prop)
- group-details-panel (GroupDetailsPanel)
- serial-host-details-panel (SerialHostDetailsPanel)
- ai-chat-panel (AIChatSidePanel)
- vault-view / vault-sidebar / vault-main / vault-hosts-header / vault-host-list (VaultView)
- terminal-workspace / terminal-workspace-sidebar (TerminalLayer)
- top-tabs (TopTabs — also keeps existing data-top-tabs-root)
Also updated the Custom CSS description and placeholder in both
English and Chinese to list available hooks and show a working
example (snippet panel font-size override).
Closes #642
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
338ba94d42 |
feat: add paste-only option for snippets (no auto-execute) (#375)
* feat: add "paste only" option for snippets (no auto-execute) Add a noAutoRun flag to snippets that pastes the command into the terminal without appending a carriage return, so users can review and edit before manually pressing Enter. Applies to all snippet execution paths: snippet runner (new session), keyboard shortcut, and startup command. Closes #371 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use clearer wording "仅粘贴" instead of "仅上屏" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: skip onCommandExecuted for paste-only shortcut snippets Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: persist noAutoRun on save and apply to Scripts panel clicks - Include noAutoRun in handleSubmit serialization (was being lost) - Pass noAutoRun through ScriptsSidePanel click handler to TerminalLayer so paste-only snippets work from the Scripts panel too Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
4877c934fa |
feat: move Scripts and Theme to side panel sub-tabs (#333)
* feat: move Scripts and Theme from toolbar popups to side panel sub-tabs Migrate Scripts (snippet library) and Theme customization from toolbar popover/modal dialogs into the left side panel alongside SFTP. The panel header now shows three tab buttons (SFTP / Scripts / Theme) so users can switch between sub-panels without losing SFTP connections. - Add ScriptsSidePanel with package hierarchy, breadcrumb nav and search - Add ThemeSidePanel adapted from ThemeCustomizeModal (no preview pane) - Generalize TerminalLayer state from sftpOpenTabs to sidePanelOpenTabs - Simplify TerminalToolbar by removing inline popover and modal rendering - Clicking the already-active tab button is a no-op; only X closes panel - Theme/font changes apply in real-time to the actual terminal behind Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review findings for side panel migration - Clean up sftpInitialLocationForTab on panel close - Remove unused handleCloseSidePanel from deps array - Re-focus terminal after snippet execution from side panel - Use props directly in ThemeSidePanel instead of mirrored local state - Use ?? instead of || for falsy-safe theme/font/size defaults - Extract isFocusedHostLocal into memoized value Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |