mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-11 08:42:45 +00:00
* refactor: migrate architecture-debt hooks into application/state Move SFTP Wave A stores/hooks and related vault/AI/terminal/systemManager hooks out of components into application/state, update importers, and keep thin deprecated re-exports at the old paths. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * refactor(sftp): align local bookmarks store API with global bookmarks Export subscribe/get/set/rehydrate helpers from localSftpBookmarks to match the globalSftpBookmarks external-store pattern. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(electron): reduce baseline memory via spellcheck/GPU/prewarm guards Disable spellcheck on BrowserWindows and the default session, drop spare renderers, gate aggressive GPU switches behind NETCATTY_COMPAT_GPU, and make settings prewarm opt-in via NETCATTY_PREWARM_SETTINGS. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * Isolate notes and customAccent from TerminalLayer hot props Route vault notes through notesStore (shellHistoryStore pattern) and app accent through appearanceChromeStore so note edits and accent-drag ticks no longer rebuild TerminalLayer. Notes/AI slots and Terminal leaves subscribe locally; VaultView and open-note callbacks stay unchanged. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(ui): cut unnecessary AppView/VaultView/settings re-renders Stabilize TopTabs close handler, memo AppHostTreeLayer, exclude accent from settingsVersion, ignore connectionLogs off the logs section, share lastConnected host refs, and keep rename dialog drafts local so chrome domain stays stable. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * chore: package size, dead code, and consolidation cleanup Remove unused direct deps, exclude Vite-bundled renderer packages from electron-builder, delete high-confidence dead code/no-op transfer warm wiring, consolidate cloud provider IDs and KnownHost/SFTP helpers, and land UI/AGENTS quick wins (rAF text batching, notes draft debounce, streaming plain text, tempDirBridge, diagnostics adapter, External MCP setters). Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: stabilize rAF text batching and diagnostics tests Polyfill requestAnimationFrame for Node, flush pending text before steer buffering, bypass rAF while steer is in flight, and stub global localStorage for AI panel diagnostics adapter tests. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: correct import paths after application/state hook migrations Migrated vault/AI/system hooks still used components/-relative imports; point them at repo-root domain/components/types/lib instead. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: address Bugbot/Codex regressions from perf cleanup - Keep blank Enter from closing RenameDraftDialog; only reset rename state after a non-empty submit - Flush note drafts before vault mutations so pending title/body edits are not overwritten - Re-apply appearanceChromeStore accent on appearanceTheme in Terminal, and keep layer themes unaccented Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(notes): flush draft before markdown export paths Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: keep editor-close hotkey ref fresh during render Assign handleRequestCloseEditorTabRef in render instead of useEffect so Cmd/Ctrl+W never hits the App stub before the effect runs. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: keep accent in chrome themes without TerminalLayer thrash Restore accent in globalAppearance for chrome/injection consumers. Keep resolveFocusedAppearance identity stable across accent drag via accent ref, while Terminal leaf still re-applies appearanceChromeStore. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: keep compose chrome accent live and merge note renames Subscribe theme-panel focusedAppearance to appearanceChromeStore so compose-bar chrome updates during color-picker drag even when resolveFocusedAppearance identity stays stable. Tree renames now merge title into the post-flush note instead of replacing from a stale row. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: clear terminal accent when switching back to theme mode Re-resolve appearanceTheme by catalog id before applyCustomAccent so a stale baked custom cursor/selection cannot stick after accentMode returns to theme while TerminalLayer memo ignores accent props. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: register unsaved prompt singleton during render AppView close handlers call promptUnsavedChanges outside the old render-prop. Assign the singleton during render so Cmd/Ctrl+W and tab close never hit the pre-effect null window that auto-cancels. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: keep vault import hooks UI-free and flush notes on teardown Move ImportOptions into application/state and inject a notifier so useVaultImportHandlers no longer imports components. Notes drafts also flush on pagehide/beforeunload when Electron tears down without React unmount. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: move AI terminal session context builders into domain buildAITerminalSessionInfo and AIPanelContext now live under domain/ so application hooks no longer import TerminalLayerSupport and create a UI → application → UI cycle. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: drop duplicate AIPanelContext type from TerminalLayerSupport The type is re-exported from domain; the local definition conflicted. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: keep migrated state hooks free of UI-layer imports Move aiChatStreamingSupport into infrastructure/ai and poll list helpers into domain/systemManager so useAIChatStreaming / useSystemManager no longer import from components. Leave thin re-exports at the old paths. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: move remaining migrated-hook deps out of components Host-key verification types/helpers now live in domain/, and SFTP column layout types live in application/state/sftp/columnLayout. Application hooks no longer import those definitions from the UI layer. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix: clear lint blockers and flush notes when panels hide Move AI panel diagnostics persistence into application/state so components stop importing localStorageAdapter. Flush note drafts when retained NotesManager mounts become inactive, and silence related lint warnings in theme/host-key helpers. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> * fix(notes): publish notesStore sync on vault note updates updateNotes/updateNoteGroups now publishNotesSnapshot immediately so AI/notes consumers do not briefly read a stale catalog after a hide flush. Flush inactive drafts in useLayoutEffect before paint. Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>
308 lines
13 KiB
JavaScript
308 lines
13 KiB
JavaScript
const { moshExtraResources } = require('./scripts/mosh-extra-resources.cjs');
|
|
const { etExtraResources } = require('./scripts/et-extra-resources.cjs');
|
|
|
|
/**
|
|
* @type {import('electron-builder').Configuration}
|
|
*/
|
|
module.exports = {
|
|
appId: 'com.netcatty.app',
|
|
productName: 'Netcatty',
|
|
artifactName: '${productName}-${version}-${os}-${arch}.${ext}',
|
|
protocols: [
|
|
{
|
|
name: 'SSH URL',
|
|
schemes: ['ssh']
|
|
},
|
|
{
|
|
name: 'Telnet URL',
|
|
schemes: ['telnet']
|
|
},
|
|
{
|
|
name: 'JumpServer URL',
|
|
schemes: ['jms']
|
|
}
|
|
],
|
|
electronLanguages: ['en', 'en-US', 'zh_CN', 'zh-CN', 'zh_TW', 'zh-TW', 'ru'],
|
|
// Give the macOS build a unique Mach-O LC_UUID before signing, so macOS
|
|
// Local Network privacy treats Netcatty distinctly from every other
|
|
// Electron app (which all share Electron's prebuilt LC_UUID) — see #1040
|
|
// and scripts/afterPackMacUuid.cjs. No-op on Windows/Linux.
|
|
beforePack: './scripts/beforePackCursorSdk.cjs',
|
|
afterPack: './scripts/afterPackMacUuid.cjs',
|
|
// Platform-split icons (#813):
|
|
// - public/icon.png keeps Apple's HIG grid margin so the rendered
|
|
// squircle sits at ~88% of the PNG canvas. macOS needs this —
|
|
// the dock renders icons with its own rounding/shadow and most
|
|
// third-party apps (#803) leave that grid margin alone so the
|
|
// squircle lines up with neighbors.
|
|
// - public/icon-win.png uses a tight-crop viewBox so the squircle
|
|
// fills 100% of the PNG. Windows / Linux taskbars render icons
|
|
// full-bleed, so the Apple margin showed up as visible padding,
|
|
// making the app icon look smaller than other apps in taskbar /
|
|
// Start menu / desktop shortcuts.
|
|
icon: 'public/icon.png',
|
|
// npmRebuild must stay enabled for macOS and Windows builds — without it,
|
|
// node-pty's native module is not recompiled for the Electron ABI, causing
|
|
// "posix_spawnp failed" on macOS. Linux builds set npm_config_arch in CI
|
|
// and run ensure-node-pty-linux.sh before packaging, so the rebuild is
|
|
// redundant but harmless there.
|
|
npmRebuild: true,
|
|
directories: {
|
|
buildResources: 'build',
|
|
output: 'release'
|
|
},
|
|
files: [
|
|
'dist/**/*',
|
|
'electron/**/*',
|
|
// Runtime smoke fixtures are built test packages, not host resources.
|
|
// Keep them out of production ASARs so no example plugin can be
|
|
// mistaken for an installed or host-trusted package.
|
|
'!electron/plugins/fixtures/**/*',
|
|
// Main-process terminal flow control reads shared thresholds from here
|
|
// (terminalFlowAck.cjs). Must ship beside electron/ in app.asar.
|
|
'infrastructure/config/terminalFlowConstants.cjs',
|
|
'infrastructure/config/terminalFlowConstants.json',
|
|
'lib/**/*.cjs',
|
|
'lib/**/*.json',
|
|
'skills/**/*',
|
|
'!public/**/*',
|
|
'!**/*.map',
|
|
'!**/*.d.ts',
|
|
'!**/*.d.mts',
|
|
'!**/*.d.cts',
|
|
'!**/*.ts',
|
|
'!**/*.tsx',
|
|
'!**/*.test.*',
|
|
'!**/*.spec.*',
|
|
'!**/__tests__/**/*',
|
|
'!**/test/**/*',
|
|
'!**/tests/**/*',
|
|
'!**/example/**/*',
|
|
'!**/examples/**/*',
|
|
'!node_modules/**/docs/**/*',
|
|
'!node_modules/**/doc/**/*',
|
|
'!node_modules/**/benchmark/**/*',
|
|
'!node_modules/**/benchmarks/**/*',
|
|
// Renderer-only packages are compiled into dist by Vite. Keep them
|
|
// installed for npm run dev/build, but do not ship the duplicate source
|
|
// packages in release artifacts.
|
|
'!node_modules/@fontsource/**/*',
|
|
'!node_modules/@monaco-editor/**/*',
|
|
'!node_modules/@radix-ui/**/*',
|
|
'!node_modules/@xterm/**/*',
|
|
'!node_modules/lucide-react/**/*',
|
|
'!node_modules/monaco-editor/**/*',
|
|
'!node_modules/react/**/*',
|
|
'!node_modules/react-dom/**/*',
|
|
'!node_modules/ai/**/*',
|
|
'!node_modules/@ai-sdk/**/*',
|
|
'!node_modules/@mdxeditor/**/*',
|
|
'!node_modules/streamdown/**/*',
|
|
'!node_modules/@streamdown/**/*',
|
|
'!node_modules/@tanstack/react-virtual/**/*',
|
|
'!node_modules/pinyin-pro/**/*',
|
|
'!node_modules/re2js/**/*',
|
|
'!node_modules/@eslint-community/regexpp/**/*',
|
|
'!node_modules/clsx/**/*',
|
|
'!node_modules/tailwind-merge/**/*',
|
|
'!node_modules/use-stick-to-bottom/**/*',
|
|
'!node_modules/lexical/**/*',
|
|
'!node_modules/@lexical/**/*',
|
|
'!node_modules/@codemirror/**/*',
|
|
'!node_modules/shiki/**/*',
|
|
'!node_modules/@shiki/**/*',
|
|
// Heavy cloud completion specs are intentionally not bundled. The main
|
|
// process filters the same prefixes so dev and packaged builds behave
|
|
// consistently.
|
|
'!node_modules/@withfig/autocomplete/build/aws.js',
|
|
'!node_modules/@withfig/autocomplete/build/aws/**/*',
|
|
'!node_modules/@withfig/autocomplete/build/gcloud.js',
|
|
'!node_modules/@withfig/autocomplete/build/gcloud/**/*',
|
|
'!node_modules/@withfig/autocomplete/build/az/**/*',
|
|
// Fig specs are already compiled JavaScript; TypeScript is only pulled
|
|
// in by Fig helper packages as build tooling and is not needed at app
|
|
// runtime.
|
|
'!node_modules/typescript/**/*',
|
|
// ── Exclude per-platform native agent binaries (~100s of MB each). ──
|
|
// Netcatty is "bring your own CLI": each SDK is pointed at the user's
|
|
// system-installed CLI via an absolute path override (claude
|
|
// pathToClaudeCodeExecutable / codex codexPathOverride / copilot cliPath).
|
|
// Only the SDKs' JS is bundled; the heavy per-arch binaries are dropped.
|
|
// NOTE: claude-agent-sdk vendors the `claude` binary as a NESTED package
|
|
// (claude-agent-sdk/node_modules/@anthropic-ai/claude-agent-sdk-<arch>),
|
|
// so this exclusion must match at any depth (**/), not just top-level.
|
|
// The codex/copilot exclusions target only the per-arch binary packages
|
|
// (codex-<arch> / copilot-<arch>) — NOT @openai/codex-sdk / copilot-sdk,
|
|
// whose JS we DO bundle. @github/copilot is the full ~288MB CLI (with
|
|
// per-platform prebuilds); netcatty uses the user's copilot via cliPath,
|
|
// so it is excluded entirely.
|
|
'!**/@anthropic-ai/claude-agent-sdk-*/**/*',
|
|
'!node_modules/@anthropic-ai/claude-code-*/**/*',
|
|
'!node_modules/@openai/codex-{darwin,linux,linuxmusl,win32}-*/**/*',
|
|
'!node_modules/@github/copilot-{darwin,linux,linuxmusl,win32}-*/**/*',
|
|
'!node_modules/@github/copilot/**/*',
|
|
'!node_modules/opencode-{darwin,linux,linuxmusl,windows}-*/**/*',
|
|
'!node_modules/opencode-ai/**/*',
|
|
// CodeBuddy follows the same first-party integration model as the
|
|
// other coding agents: Netcatty discovers and passes the user's
|
|
// installed CLI path to the SDK. Keep the small SDK wrapper, but do not
|
|
// bundle the full CodeBuddy CLI payload (rg vendors + web UI).
|
|
'!node_modules/@tencent-ai/agent-sdk/cli/**/*',
|
|
// Netcatty loads Cursor SDK through ESM dynamic import, so the duplicate
|
|
// CommonJS build and type metadata are not needed at runtime.
|
|
'!node_modules/@cursor/sdk/dist/cjs/**/*',
|
|
'!node_modules/@cursor/sdk/dist/**/*.d.ts',
|
|
'!node_modules/@cursor/sdk/dist/**/*.d.ts.map',
|
|
// sqlite3 rebuilds a native module for Electron; its upstream source
|
|
// tarball is build-time payload only.
|
|
'!node_modules/sqlite3/deps/**/*'
|
|
],
|
|
asarUnpack: [
|
|
'node_modules/node-pty/**/*',
|
|
'node_modules/ssh2/**/*',
|
|
'node_modules/cpu-features/**/*',
|
|
'node_modules/@vscode/windows-process-tree/**/*',
|
|
'node_modules/@anthropic-ai/claude-agent-sdk/**/*',
|
|
'node_modules/@cursor/sdk-*/**/*',
|
|
'node_modules/sqlite3/**/*',
|
|
'node_modules/@modelcontextprotocol/sdk/**/*',
|
|
'lib/**/*.cjs',
|
|
'lib/**/*.json',
|
|
'node_modules/zod/**/*',
|
|
'node_modules/zod-to-json-schema/**/*',
|
|
'node_modules/@netcatty/plugin-cli/**/*',
|
|
'node_modules/@netcatty/plugin-contract/**/*',
|
|
'node_modules/@netcatty/plugin-sdk/**/*',
|
|
'electron/plugins/runtime/**/*',
|
|
'node_modules/ajv/**/*',
|
|
'node_modules/ajv-formats/**/*',
|
|
'node_modules/fast-deep-equal/**/*',
|
|
'node_modules/fast-uri/**/*',
|
|
'node_modules/json-schema-traverse/**/*',
|
|
'electron/cli/**/*',
|
|
'electron/capabilities/**/*',
|
|
'electron/shared/**/*',
|
|
'electron/mcp/**/*',
|
|
'skills/**/*'
|
|
],
|
|
mac: {
|
|
target: [
|
|
{
|
|
target: 'dmg',
|
|
arch: ['arm64', 'x64']
|
|
},
|
|
{
|
|
target: 'zip',
|
|
arch: ['arm64', 'x64']
|
|
}
|
|
],
|
|
category: 'public.app-category.developer-tools',
|
|
hardenedRuntime: true,
|
|
notarize: true,
|
|
entitlements: 'electron/entitlements.mac.plist',
|
|
entitlementsInherit: 'electron/entitlements.mac.plist',
|
|
extendInfo: {
|
|
NSCameraUsageDescription: 'Netcatty may use the camera for video calls',
|
|
NSMicrophoneUsageDescription: 'Netcatty may use the microphone for audio',
|
|
NSLocalNetworkUsageDescription: 'Netcatty needs local network access for SSH connections',
|
|
CFBundleDocumentTypes: [
|
|
{
|
|
CFBundleTypeName: 'Folder',
|
|
CFBundleTypeRole: 'Viewer',
|
|
LSHandlerRank: 'Alternate',
|
|
LSItemContentTypes: ['public.folder']
|
|
}
|
|
]
|
|
},
|
|
extraResources: [...moshExtraResources('darwin'), ...etExtraResources('darwin')]
|
|
},
|
|
dmg: {
|
|
title: '${productName}',
|
|
iconSize: 100,
|
|
iconTextSize: 12,
|
|
window: {
|
|
width: 540,
|
|
height: 380
|
|
},
|
|
contents: [
|
|
{ x: 140, y: 158 },
|
|
{ x: 400, y: 158, type: 'link', path: '/Applications' }
|
|
]
|
|
},
|
|
win: {
|
|
icon: 'public/icon-win.png',
|
|
// Do not hard-code arch here. pack:win-x64 / pack:win pass --x64/--arm64,
|
|
// and electron-builder unions config arch with the CLI set. Hard-coding
|
|
// ['x64', 'arm64'] made the official x64 CI job also emit win-arm64 and
|
|
// a universal win.exe whose 32-bit NSIS stub can mis-detect on ARM
|
|
// Windows, install to Program Files (x86), and leave Netcatty.exe
|
|
// missing (#2570). Keep official releases on pack:win-x64 until win32
|
|
// arm64 bundled mosh/et + native rebuilds are ready.
|
|
target: ['nsis', 'portable', 'zip'],
|
|
extraResources: [...moshExtraResources('win32'), ...etExtraResources('win32')]
|
|
},
|
|
portable: {
|
|
artifactName: '${productName}-${version}-portable-${os}-${arch}.${ext}',
|
|
},
|
|
nsis: {
|
|
include: 'build/installer.nsh',
|
|
oneClick: false,
|
|
perMachine: false,
|
|
allowElevation: true,
|
|
allowToChangeInstallationDirectory: true,
|
|
createDesktopShortcut: true,
|
|
createStartMenuShortcut: true,
|
|
shortcutName: 'Netcatty'
|
|
},
|
|
linux: {
|
|
// Linux .deb/.rpm/AppImage icons come from build/icons/* (see
|
|
// scripts/generate-linux-icons.sh). Point at the icons directory
|
|
// under buildResources — electron-builder still falls back to the
|
|
// top-level icon (public/icon.png) when linux.icon is unset, which
|
|
// installs only hicolor/1024x1024 and launchers miss the icon (#274,
|
|
// #1340). Do NOT set linux.icon to a single 1024px PNG either.
|
|
icon: 'icons',
|
|
target: ['AppImage', 'deb', 'rpm', 'pacman'],
|
|
category: 'Development',
|
|
extraResources: [...moshExtraResources('linux'), ...etExtraResources('linux')]
|
|
},
|
|
deb: {
|
|
// Use gzip instead of default xz(lzma) for better compatibility with
|
|
// Deepin OS and other distros that have issues with lzma decompression
|
|
compression: 'gz',
|
|
afterInstall: 'scripts/linux/after-install.tpl'
|
|
},
|
|
rpm: {
|
|
// Default fpm/electron-builder RPM compression is "xzmt" (multi-threaded
|
|
// xz). AlmaLinux/RHEL 8 images provide `xz` but not the `xzmt` shim, so
|
|
// rpmbuild fails with exit 127 during packaging. gzip is portable and
|
|
// matches our deb preference for older distros.
|
|
compression: 'gzip',
|
|
afterInstall: 'scripts/linux/after-install.tpl',
|
|
fpm: [
|
|
// Avoid rpm's generated /usr/lib/.build-id symlinks. Those hashes
|
|
// are global on the host, so owning them can conflict with other RPMs.
|
|
'--rpm-rpmbuild-define', '_build_id_links none',
|
|
// Electron ships prebuilt binaries. RHEL/Alma brp post-install
|
|
// scripts (strip/compress/etc.) can exit 127 when a helper is
|
|
// missing or a gcc-toolset `strip` is on PATH; skip them.
|
|
'--rpm-rpmbuild-define', '__os_install_post %{nil}',
|
|
]
|
|
},
|
|
pacman: {
|
|
// FPM-generated .pacman packages bypass Arch's alpm hooks that
|
|
// normally refresh the hicolor icon cache. Without this, KDE cannot
|
|
// resolve Icon=netcatty and shows a generic placeholder (#1358).
|
|
afterInstall: 'scripts/linux/after-install.tpl',
|
|
afterRemove: 'scripts/linux/after-remove.tpl',
|
|
},
|
|
publish: [
|
|
{
|
|
provider: 'github',
|
|
owner: 'binaricat',
|
|
repo: 'Netcatty',
|
|
releaseType: 'release'
|
|
}
|
|
]
|
|
};
|