Skip to content

merge: upstream/main 14コミットを取り込み#3004

Closed
MocA-Love wants to merge 94 commits intosuperset-sh:mainfrom
MocA-Love:merge/upstream-main-2026-03-30
Closed

merge: upstream/main 14コミットを取り込み#3004
MocA-Love wants to merge 94 commits intosuperset-sh:mainfrom
MocA-Love:merge/upstream-main-2026-03-30

Conversation

@MocA-Love
Copy link
Copy Markdown

@MocA-Love MocA-Love commented Mar 30, 2026

Summary

  • upstream/main の14コミットを取り込み(behind 0 に)
  • ターミナル安定性修正(PTYバッチ処理、バックプレッシャー警告削除、バージョンピン留め)
  • 画像data URLバリデーション強化
  • ワークスペース検索リグレッション修正
  • worktree右クリック「Open in Editor」追加
  • PR検索のサーバー側移行
  • 破壊的ダイアログのEnter対応
  • 設定検索バナー表示
  • チャットカーソル位置保持
  • ReviewサイドバーUIクリーンアップ
  • Mastra upstream パッケージ切り替え
  • タスク詳細簡素化
  • MCP list_devices スキーマ修正

コンフリクト解消

  • page.tsx: フォーク独自の keywordSearch + upstream の hotkeyOptions 変更を統合
  • file-types.ts: フォーク独自の SPREADSHEET_EXTENSIONS + upstream の IMAGE_MIME_TYPE_EXTENSIONS を両方保持
  • bun.lock: upstream 採用後に bun install で再生成

Summary by cubic

Merged upstream/main (14 commits) and shipped major desktop upgrades: spreadsheet viewing/diff, persistent browser tabs, pane pop‑out, terminal history suggestions, Chrome extension support, and a fork-aware updater.

  • New Features

    • Spreadsheet viewer and diff for .xlsx/.xls/.xlsm/.xlsb/.ods with formatting, shapes, merged cells; side-by-side diff with per-cell highlights. Uses exceljs, jszip, and diff. Large text diffs use @codemirror/merge.
    • Browser upgrades: keep webviews alive across tab/workspace switches, open target=_blank in a new tab, zoom controls with live sync, copy URL button, mouse back/forward, and Inspect Element.
    • Pop out any pane to a separate window; tabs return to the main window on close. Includes a lightweight tear‑off window UI.
    • Terminal history suggestions: dropdown from shell history with keyboard navigation; enable/disable in Settings.
    • Chrome extensions: install from the Web Store, enable/disable/uninstall in Settings, toolbar icons, and popup windows. Includes CRX download/extract, a compatibility checker, and a custom icon protocol.
    • Commit message generation from staged/unstaged changes via the configured provider; appears as a sparkle action in the commit input.
    • Ports and Files UX: resizable ports list with min/max bounds, filter to ports.json entries, always show static ports, improved workspace labels, and optional file path tooltips.
  • Bug Fixes

    • Crash recovery and stability: handle clipboard write failures, recover from renderer crashes, and improve browser/terminal robustness.
    • Fork updater: disable in-app install and use GitHub Releases polling for this fork; toast now opens the releases page.
    • Workspace keep-alive: fix wrong-context reads and hotkey conflicts by threading workspaceId via context and gating hotkeys.
    • GitHub PR data: allow branch-type workspaces to fall back to the project’s main repo path.

Written for commit aabe193. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added Chrome extension installation and management with compatibility checking
    • Added tab tear-off functionality to open tabs in separate windows
    • Added spreadsheet/Excel file preview with cell-level diffs
    • Added AI-powered commit message generation
    • Added shell command history suggestions in terminal
    • Added browser zoom controls and inspect element feature
    • Added tab color customization
    • Added ports list resizing and visibility filtering
    • Added file explorer tooltips
  • Documentation

    • Updated README with fork-specific features and macOS build instructions

MocA-Love and others added 30 commits March 28, 2026 02:09
Add the ability to view .xlsx, .xls, .xlsm, .xlsb, and .ods files
natively instead of showing "Binary file preview not supported".

Features:
- Full spreadsheet rendering with ExcelJS (formatting, borders, merged
  cells, fonts, colors, theme colors with tint, rich text, row heights,
  text wrapping, vertical text)
- Print area aware column/row range detection
- Auto fit-to-width column scaling
- Multiple sheet tab navigation
- Side-by-side diff viewer with cell-level change highlighting
- Diff navigation (Prev/Next) with synchronized scrolling
- Git binary file read via new readGitFileBinary tRPC procedure
feat(desktop): add Excel/spreadsheet viewer with diff support
Electron's <webview> tag reloads its content whenever the element is
reparented in the DOM. The previous approach rendered only the active
tab, causing BrowserPane to unmount on every tab switch and park the
webview in a hidden container (DOM reparent) — triggering a hard reload.

- Add PersistentTabRenderer that keeps all workspace tabs mounted and
  hides inactive ones via off-screen positioning (not display:none, which
  stops Electron's compositor)
- Wrap each webview in a persistent wrapper div so the webview's
  parentNode never changes during park/reclaim cycles
- Use unique Mosaic IDs per tab to prevent drag-drop conflicts between
  simultaneously mounted Mosaic instances
Keep workspace pages mounted across workspace switches so that webview
elements are never removed from the DOM.

- Add KeepAliveWorkspaces component that replaces <Outlet /> for
  workspace routes, rendering all visited workspaces simultaneously and
  hiding inactive ones off-screen
- Make WorkspacePage accept workspaceId as a prop override so it works
  outside the router's matched-route context
- Thread workspaceId through WorkspaceLayout → ContentView → TabsContent
  via props instead of useParams(), preventing hidden workspaces from
  reading the wrong workspace ID from the active route
…p-alive

When multiple WorkspacePage instances are mounted simultaneously
(KeepAliveWorkspaces), several issues occurred:

1. Components using useParams() read the ACTIVE workspace's ID instead
   of their own — causing wrong files, wrong sidebar data, and wrong
   tab lists. Fixed by introducing WorkspaceIdContext and replacing
   useParams() with useWorkspaceId() in 9 affected components.

2. Mosaic drag-drop was broken because GroupItem used a static mosaicId
   that no longer matched the per-tab dynamic ID. Fixed by computing
   the active tab's mosaicId dynamically.

3. All workspace hotkeys fired for every mounted workspace. Fixed by
   passing `enabled: isActive` to all useAppHotkey calls so only the
   active workspace responds to keyboard shortcuts.
Electron's <webview> tags consume mouse events in their guest process,
so mouse back/forward buttons (button 3/4) never reach the host
renderer's event listeners. Handle the `app-command` event on the main
BrowserWindow to intercept `browser-backward` and `browser-forward`
commands, forwarding them to the focused webview's navigation history.

Also update usePresetHotkeys to accept an options parameter for
consistency with the enabled-flag pattern used across workspace hotkeys.
The `app-command` event is Windows/Linux only — it never fires on macOS.
Instead, inject a mouse event listener into the webview guest page via
executeJavaScript on every `dom-ready`. The injected script calls
`history.back()` / `history.forward()` directly inside the guest when
mouse buttons 3/4 are pressed.

The existing `app-command` handler in the main process is kept as a
fallback for Windows/Linux.
…spaces

PersistentTabRenderer now only keeps tabs mounted when they contain a
webview pane. Tabs with only terminals, chat, or file viewers unmount
normally on tab switch, reducing memory usage.

KeepAliveWorkspaces now watches the workspace list from the database
and automatically removes deleted workspaces from the keep-alive set,
preventing stale WorkspacePage instances from lingering in memory.
Keep both our useWorkspaceId import and main's new githubQueryPolicy
imports. The useParams import was already removed by our branch.
Auto-update pointed to the upstream repo (superset-sh/superset),
which would overwrite fork-specific changes on install.

- Disable autoDownload and autoInstallOnAppQuit
- Replace "Install" button with "Open releases" that opens the fork's
  GitHub releases page (MocA-Love/superset)
- Update toast copy to say "available upstream" instead of "ready to install"
fix(desktop): 自動更新を無効化しフォークのリリースページへ誘導
- Remove redundant `genericNavigate` declaration; reuse existing
  `navigate` from useNavigate()
- Gate mouse-nav shim injection to macOS only (PLATFORM.IS_MAC);
  Windows/Linux already handle side buttons via `app-command`
fix(desktop): prevent browser webview reload on tab/workspace switch
Add a sparkle button to the commit message input that generates a
conventional commit message using the configured AI provider (OpenAI or
Anthropic). Uses the existing callSmallModel infrastructure with
automatic provider fallback.

- Gathers staged, unstaged, and untracked file changes for context
- Supports both OAuth and API key authentication for OpenAI
- Generates messages in Japanese with conventional commit format
- Logs detailed provider diagnostics on failure
…generation

Replace the simple truncated-diff approach with a gptcommit-style
two-phase strategy for the highest accuracy on large diffs:

Phase 1: Summarize each changed file independently in parallel via LLM.
  - Lock files, binaries, and other low-value files are skipped
    (file names only passed to Phase 2)
  - Small diffs (<300 chars) are passed directly without an LLM call
  - Large per-file diffs are truncated at 4000 chars before summarizing

Phase 2: Combine all file summaries + diff stats into a single prompt
  and generate the final conventional commit message.

This avoids token-limit truncation that loses important context and
produces significantly better messages for multi-file changes.
feat(desktop): AIコミットメッセージ自動生成
The existing @pierre/diffs diff viewer renders all lines at once,
causing severe lag on files with 2000+ lines (~180k+ DOM nodes).

Add CodeMirrorDiffViewer using @codemirror/merge which provides
virtualized rendering (only visible lines in DOM). Files with
>2000 total lines automatically use this viewer instead.

- Reuses existing CodeMirror theme, fonts, and syntax highlighting
- Unchanged regions are collapsed (margin: 3, minSize: 4)
- Read-only side-by-side view with line numbers
- No changes to LightDiffViewer (small files use it as before)
The default scanLimit (500) causes the diff algorithm to fall back
to an imprecise mode for large files, marking everything as changed.
Increase to 50000 with a 5s timeout.
Keep context menu actions (split, move, close, edit at location)
available for large file diffs. Also conditionally skip
MarkdownSearch and DiffScrollbarDecorations for CodeMirror path
since they are @pierre/diffs specific.
feat(desktop): 大規模ファイル向け CodeMirror diff ビューア
- Add drag-to-resize handle on the ports section border, allowing users
  to adjust the height (80–600px, persisted to localStorage)
- Add filter toggle button (funnel icon) to show only ports defined in
  ports.json, hiding auto-detected ports
- Fix layout so ports list can expand by using shrink-0 and explicit
  height instead of max-height
MocA-Love and others added 27 commits March 29, 2026 18:15
feat(desktop): Excelセルのインラインdiff表示
- ExtensionPopupManager: フレームレスBrowserWindowでpopup.htmlを表示
  - chrome-extension:// URLでロード、同一session partitionで通信自動対応
  - enablePreferredSizeModeによる自動サイズ調整
  - blurイベントで自動クローズ、同時1つのみ排他制御
  - アイコン直下に配置、画面端クランプ対応
- extension-icon-protocol: superset-ext-icon:// プロトコルでアイコン画像配信
- ExtensionToolbar/ExtensionIcon: BrowserPaneツールバーに拡張アイコン表示
- tRPC: listToolbarExtensions/openPopup/closePopup エンドポイント追加
- 互換性チェッカーからpopup "unsupported" 警告を削除
- sandbox: true が chrome-extension:// プロトコルをブロックしていた問題を修正
- chrome-extension:// ロード失敗時に file:// からの直接ロードにフォールバック
- 未使用変数を削除
ダークモード時に白文字が白背景で見えなくなる問題を修正。
nativeTheme.shouldUseDarkColors に合わせて背景色を設定。
CRX展開時にmanifestのkeyフィールドが失われるため、Electronが
Chrome Web Store IDとは異なるIDを割り当てる。loadExtension()の
戻り値からelectronIdを取得・永続化し、popup URLに使用するよう修正。
feat(desktop): Chrome Web Store拡張機能インストール + ツールバーUI
# Conflicts:
#	apps/desktop/src/lib/trpc/routers/changes/git-operations.ts
#	bun.lock
ツールバーにトグルボタンを追加し、ONにするとファイル/フォルダ名に
相対パスのツールチップを表示。設定はZustandで永続化。
Closes #21
feat(desktop): Filesタブにファイル名ツールチップ
webviewのコンテキストメニューにDevTools検証機能を追加し、
右クリック位置の要素を直接インスペクトできるようにした。
feat(desktop): ブラウザペインに Inspect Element を追加
~/.zsh_history から入力中のプレフィックスに一致するコマンドを候補表示。
ゴーストテキスト+ドロップダウンリストで候補を表示し、↑↓で選択、→で確定、
Escで破棄。設定画面からON/OFF切り替え可能(デフォルトON)。
末尾到達時に追加候補を自動読み込み。
getGitHubStatus / getGitHubPRComments が worktree レコード必須だった
制限を解消し、type=branch のワークスペースでは mainRepoPath に
フォールバックして gh CLI を実行するように変更
候補が8件を超える場合、リストが固定高さ内でスクロールするように変更。
選択中の項目は自動スクロールで追従。フッターは常に表示。
- ゴーストテキストを廃止し候補1件でもドロップダウンを表示
- シェルのzsh-autosuggestions との視覚的衝突を解消
- .zshrc wrapper でユーザーの zshrc source 後に
  ZSH_AUTOSUGGEST_STRATEGY を空にして無効化
- README にシェル履歴サジェスト機能を追記
Supersetターミナル内でzsh-autosuggestionsのサジェスト関数をno-op化し、
ビルトインサジェストとの視覚的な衝突を防止。SUPERSET_DISABLE_ZSH_AUTOSUGGEST
環境変数で制御し、ユーザーの.zshrcは変更しない。
関数のno-opではなくプラグイン公式の_zsh_autosuggest_disable()を使用。
これによりZLEウィジェットバインドが正しく復元され、self-insert
ウィジェットチェーンの破損による入力重複を防止。
- ゴーストテキストを完全に廃止し、ドロップダウンUIのみに統一
- 選択中コマンドのフルプレビューを上部に表示(補完部分を緑色で強調)
- 候補1件でもドロップダウンを表示
- ↑キーのループを廃止(先頭で止まる)
- zsh-autosuggestions無効化を削除(共存可能)
- README更新
feat(desktop): シェル履歴サジェスト & Branch PR表示対応
コンフリクト解消:
- page.tsx: フォーク独自のkeywordSearch + upstreamのhotkeyOptions変更を統合
- file-types.ts: フォーク独自のSPREADSHEET_EXTENSIONS + upstreamのIMAGE_MIME_TYPE_EXTENSIONSを両方保持
- bun.lock: upstream採用後にbun installで再生成
@MocA-Love MocA-Love closed this Mar 30, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 30, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e4bd801b-1910-421e-8508-0bac210634bd

📥 Commits

Reviewing files that changed from the base of the PR and between 5839970 and aabe193.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (109)
  • README.md
  • apps/desktop/package.json
  • apps/desktop/src/lib/trpc/routers/browser/browser.ts
  • apps/desktop/src/lib/trpc/routers/changes/file-contents.ts
  • apps/desktop/src/lib/trpc/routers/changes/git-operations.ts
  • apps/desktop/src/lib/trpc/routers/extensions/index.ts
  • apps/desktop/src/lib/trpc/routers/index.ts
  • apps/desktop/src/lib/trpc/routers/ports/ports.ts
  • apps/desktop/src/lib/trpc/routers/tab-tearoff.ts
  • apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts
  • apps/desktop/src/lib/window-loader.ts
  • apps/desktop/src/main/index.ts
  • apps/desktop/src/main/lib/agent-setup/shell-wrappers.ts
  • apps/desktop/src/main/lib/auto-updater.ts
  • apps/desktop/src/main/lib/browser/browser-manager.ts
  • apps/desktop/src/main/lib/extensions/compatibility-checker.ts
  • apps/desktop/src/main/lib/extensions/crx-downloader.ts
  • apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts
  • apps/desktop/src/main/lib/extensions/extension-manager.ts
  • apps/desktop/src/main/lib/extensions/extension-popup-manager.ts
  • apps/desktop/src/main/lib/shell-history.ts
  • apps/desktop/src/main/lib/window-manager/index.ts
  • apps/desktop/src/main/windows/main.ts
  • apps/desktop/src/preload/index.ts
  • apps/desktop/src/renderer/components/UpdateToast/UpdateToast.tsx
  • apps/desktop/src/renderer/hooks/useBrowserNewWindowHandler.ts
  • apps/desktop/src/renderer/hooks/useTearoffInit/index.ts
  • apps/desktop/src/renderer/hooks/useTearoffInit/useTearoffInit.ts
  • apps/desktop/src/renderer/lib/trpc-storage.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/KeepAliveWorkspaces.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/v2-workspace/$workspaceId/components/WorkspaceFiles/components/WorkspaceFilePreview/components/WorkspaceFilePreviewContent/WorkspaceFilePreviewContent.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/hooks/usePresetHotkeys.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/components/SettingsSidebar/GeneralSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/extensions/components/ExtensionsSettings/ExtensionsSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/extensions/components/ExtensionsSettings/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/extensions/page.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/layout.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/TerminalSettings.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/components/SuggestionsSetting/SuggestionsSetting.tsx
  • apps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/components/SuggestionsSetting/index.ts
  • apps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/components/MergedPortBadge/MergedPortBadge.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/components/WorkspacePortGroup/WorkspacePortGroup.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/useKillPort.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/components/FileDiffSection/FileDiffSection.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/ContentHeader/ContentHeader.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/EmptyTabView.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupStrip.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/PersistentTabRenderer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/BrowserPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/BrowserToolbar/BrowserToolbar.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/ExtensionToolbar/ExtensionToolbar.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/ExtensionToolbar/components/ExtensionIcon/ExtensionIcon.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/ExtensionToolbar/components/ExtensionIcon/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/ExtensionToolbar/components/ExtensionIcon/types.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/components/ExtensionToolbar/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/ChatPane/ChatPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/DevToolsPane/DevToolsPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/FileViewerPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerContent/FileViewerContent.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/FileViewerToolbar/FileViewerToolbar.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetDiffViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetViewer.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/useSpreadsheetData.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/useSpreadsheetDiff.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/TabPane.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/BasePaneWindow/BasePaneWindow.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/components/PaneToolbarActions/PaneToolbarActions.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/Terminal.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/TerminalSuggestion.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/TerminalSuggestion/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/helpers.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/index.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalLifecycle.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/hooks/useTerminalSuggestion.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/pane-guards.ts
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/components/PresetsBar/PresetsBar.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/CommitInput/CommitInput.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/FilesView.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/components/FileTreeItem/FileTreeItem.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/FilesView/components/FileTreeToolbar/FileTreeToolbar.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/index.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceIdContext.tsx
  • apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceLayout/WorkspaceLayout.tsx
  • apps/desktop/src/renderer/stores/file-explorer.ts
  • apps/desktop/src/renderer/stores/ports/store.ts
  • apps/desktop/src/renderer/stores/settings-state.ts
  • apps/desktop/src/renderer/stores/tabs/store.ts
  • apps/desktop/src/renderer/stores/tabs/types.ts
  • apps/desktop/src/renderer/stores/terminal-suggestions.ts
  • apps/desktop/src/shared/file-types.ts
  • apps/desktop/src/shared/tabs-types.ts
  • apps/desktop/src/shared/types/ports.ts

📝 Walkthrough

Walkthrough

This PR introduces comprehensive desktop application enhancements including a Chrome extension system with installation/compatibility checking, tab tear-off functionality enabling popup windows, Excel spreadsheet preview with visual diff support, terminal shell history auto-suggestions, AI-generated commit messages, and various UI improvements including tab coloring, zoom controls, file tooltips, and resizable ports list.

Changes

Cohort / File(s) Summary
Chrome Extension System
apps/desktop/src/main/lib/extensions/*, apps/desktop/src/lib/trpc/routers/extensions/index.ts, apps/desktop/src/renderer/routes/_authenticated/settings/extensions/*, apps/desktop/src/renderer/screens/.../ExtensionToolbar/*
New extension management system with CRX download/extraction, compatibility checker, manager, popup UI, and settings interface for install/enable/disable operations.
Tab Tear-off Window System
apps/desktop/src/main/lib/window-manager/index.ts, apps/desktop/src/lib/trpc/routers/tab-tearoff.ts, apps/desktop/src/preload/index.ts, apps/desktop/src/renderer/hooks/useTearoffInit/*, apps/desktop/src/renderer/routes/.../TabView/index.tsx
Complete tear-off implementation with WindowManager, TRPC mutations for window creation, preload sync IPC, tearoff initialization hooks, and pane pop-out UI in tab views.
Spreadsheet File Preview & Diff
apps/desktop/src/renderer/screens/.../SpreadsheetViewer/*, apps/desktop/src/renderer/screens/.../CodeMirrorDiffViewer/*, apps/desktop/src/shared/file-types.ts
XLSX rendering with workbook parsing, cell styling, shapes/borders, diff visualization with side-by-side comparison, and cell-level diff highlighting.
Terminal Shell Suggestions
apps/desktop/src/main/lib/shell-history.ts, apps/desktop/src/renderer/screens/.../Terminal/TerminalSuggestion/*, apps/desktop/src/renderer/stores/terminal-suggestions.ts, apps/desktop/src/renderer/screens/.../Terminal/hooks/useTerminalSuggestion.ts
Shell history caching with deduplication, suggestion polling/pagination, keyboard navigation, and terminal UI overlay rendering.
TRPC API & Git Operations
apps/desktop/src/lib/trpc/routers/browser/browser.ts, apps/desktop/src/lib/trpc/routers/changes/file-contents.ts, apps/desktop/src/lib/trpc/routers/changes/git-operations.ts, apps/desktop/src/lib/trpc/routers/terminal/terminal.ts
New subscriptions/mutations for zoom control, binary file reading, AI commit message generation, and shell history suggestions.
Browser Pane & UI Enhancements
apps/desktop/src/main/lib/browser/browser-manager.ts, apps/desktop/src/renderer/screens/.../BrowserPane/*, apps/desktop/src/renderer/screens/.../BrowserToolbar/BrowserToolbar.tsx
Browser window events, zoom level control, clipboard operations with error handling, Inspect Element support, and URL copy action.
Port Management & Display
apps/desktop/src/renderer/screens/.../PortsList/*, apps/desktop/src/lib/trpc/routers/ports/ports.ts, apps/desktop/src/renderer/stores/ports/store.ts
Detected vs configured port distinction, resizable list height, show-configured-only filter, and updated EnrichedPort nullability for undetected ports.
Workspace & Context Updates
apps/desktop/src/renderer/screens/main/components/WorkspaceView/WorkspaceIdContext.tsx, apps/desktop/src/renderer/routes/.../KeepAliveWorkspaces.tsx, apps/desktop/src/renderer/screens/.../PersistentTabRenderer.tsx
Context-based workspace ID routing, keep-alive workspace caching, and persistent webview mounting for background tabs.
Settings & State
apps/desktop/src/renderer/stores/tabs/store.ts, apps/desktop/src/renderer/stores/settings-state.ts, apps/desktop/src/renderer/stores/file-explorer.ts, apps/desktop/src/shared/tabs-types.ts
Tab color support, tearoff hydration operations, terminal suggestions store, file tooltip toggle, and extensions settings section.
Auto-Updater & Startup
apps/desktop/src/main/lib/auto-updater.ts, apps/desktop/src/main/index.ts, apps/desktop/src/main/windows/main.ts, apps/desktop/src/main/lib/agent-setup/shell-wrappers.ts
Fork-specific GitHub Releases-based update flow, extension icon protocol registration, window manager integration, and zsh autosuggest disable support.
Configuration & Dependencies
README.md, apps/desktop/package.json
Added build documentation and dependencies (@codemirror/merge, diff, exceljs, jszip, @types/diff).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related issues

  • fix(desktop): GitHub status unavailable for branch workspaces #2592: The changes to apps/desktop/src/lib/trpc/routers/workspaces/procedures/git-status.ts (fallback to project.mainRepoPath when worktree is missing for "branch" workspaces) directly address the issue's described limitation for branch workspace types without corresponding worktree records.

Possibly related PRs

Poem

🐰 Whiskers twitching with delight

Spreadsheets bloom in rainbow light,
Extensions hop from Web Store's keep,
Windows tear off, tabs run deep,
Shell suggestions whisper low—hop hop—here we go! 🌟

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

18 issues found across 110 files

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/main/lib/extensions/crx-downloader.ts">

<violation number="1" location="apps/desktop/src/main/lib/extensions/crx-downloader.ts:148">
P1: ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside `targetDir`.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx:51">
P2: Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.</violation>
</file>

<file name="apps/desktop/src/main/lib/auto-updater.ts">

<violation number="1" location="apps/desktop/src/main/lib/auto-updater.ts:102">
P2: Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts:592">
P2: Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by `sheetN.xml` file index, which can misassociate shapes when sheet order and file numbering differ.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx:95">
P2: `loadLanguageSupport(...)` is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/hooks/usePortsData.ts:36">
P2: Workspace basename extraction uses `split("/")`, which breaks on Windows paths and can render full paths instead of directory names. Use a cross-platform basename helper (e.g., `path.basename`) instead of manual splitting.</violation>
</file>

<file name="apps/desktop/src/lib/trpc/routers/changes/git-operations.ts">

<violation number="1" location="apps/desktop/src/lib/trpc/routers/changes/git-operations.ts:385">
P2: Diff errors are swallowed into null and later treated as new files, which hides failures and can mislabel files in generated summaries. At minimum, log the error and distinguish diff failures from true untracked files.</violation>
</file>

<file name="apps/desktop/src/lib/trpc/routers/changes/file-contents.ts">

<violation number="1" location="apps/desktop/src/lib/trpc/routers/changes/file-contents.ts:81">
P2: Empty catch blocks in readGitFileBinary swallow git/process errors and always return null, which removes diagnostic visibility for unexpected failures.</violation>
</file>

<file name="apps/desktop/src/main/lib/shell-history.ts">

<violation number="1" location="apps/desktop/src/main/lib/shell-history.ts:1">
P3: Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/BrowserPane/hooks/usePersistentWebview/usePersistentWebview.ts:249">
P2: Empty catch swallows `executeJavaScript` failures, hiding injection errors and making mouse-nav feature failures non-observable.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetViewer.tsx">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/SpreadsheetViewer.tsx:434">
P2: Row headers use the array index instead of the actual Excel row number, which will display incorrect row labels when rows are skipped/hidden/truncated.</violation>
</file>

<file name="apps/desktop/src/main/lib/extensions/compatibility-checker.ts">

<violation number="1" location="apps/desktop/src/main/lib/extensions/compatibility-checker.ts:197">
P2: Empty catch silently skips unreadable JS files, which can hide scan failures and under-report compatibility issues.</violation>
</file>

<file name="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx">

<violation number="1" location="apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/GroupStrip/GroupItem.tsx:237">
P2: Inline tab background color overrides the drop-hover background class, so colored tabs won’t show drag-over feedback.</violation>
</file>

<file name="apps/desktop/src/main/lib/browser/browser-manager.ts">

<violation number="1" location="apps/desktop/src/main/lib/browser/browser-manager.ts:149">
P2: Clipboard write errors in context-menu actions are silently swallowed by empty catch blocks, hiding user-visible failures and hindering diagnostics.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx:231">
P2: `QUICK_OPEN` is not gated by `isActive`, so hidden keep-alive workspace pages can still react to the global hotkey.</violation>
</file>

<file name="apps/desktop/src/lib/trpc/routers/tab-tearoff.ts">

<violation number="1" location="apps/desktop/src/lib/trpc/routers/tab-tearoff.ts:18">
P2: `windowId` uses only `Date.now()` (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.</violation>
</file>

<file name="apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts">

<violation number="1" location="apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts:85">
P2: Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.</violation>
</file>

<file name="apps/desktop/src/main/lib/extensions/extension-manager.ts">

<violation number="1" location="apps/desktop/src/main/lib/extensions/extension-manager.ts:42">
P2: Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


const entries = Object.entries(zip.files);
for (const [relativePath, file] of entries) {
const fullPath = path.join(targetDir, relativePath);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside targetDir.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/crx-downloader.ts, line 148:

<comment>ZIP extraction writes files using unvalidated entry paths, enabling path traversal (Zip Slip) outside `targetDir`.</comment>

<file context>
@@ -0,0 +1,261 @@
+
+	const entries = Object.entries(zip.files);
+	for (const [relativePath, file] of entries) {
+		const fullPath = path.join(targetDir, relativePath);
+
+		if (file.dir) {
</file context>
Fix with Cubic

document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
document.addEventListener("mousemove", handleMouseMove);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/PortsList/PortsList.tsx, line 51:

<comment>Global drag listeners are only cleaned up on mouseup, with no unmount/failure-path cleanup, which can leave stale document listeners active.</comment>

<file context>
@@ -11,10 +18,43 @@ const PORTS_DOCS_URL = `${COMPANY.DOCS_URL}/ports`;
+				document.removeEventListener("mousemove", handleMouseMove);
+				document.removeEventListener("mouseup", handleMouseUp);
+			};
+			document.addEventListener("mousemove", handleMouseMove);
+			document.addEventListener("mouseup", handleMouseUp);
+		},
</file context>
Fix with Cubic

if (IS_FORK) {
import("electron")
.then(({ shell }) => shell.openExternal(FORK_RELEASES_URL))
.catch(() => {});
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/auto-updater.ts, line 102:

<comment>Empty catch swallows fork install/open failure, hiding errors and reducing update-flow observability.</comment>

<file context>
@@ -86,13 +96,13 @@ export function getUpdateStatus(): AutoUpdateStatusEvent {
+	if (IS_FORK) {
+		import("electron")
+			.then(({ shell }) => shell.openExternal(FORK_RELEASES_URL))
+			.catch(() => {});
 		emitStatus(AUTO_UPDATE_STATUS.IDLE);
 		return;
</file context>
Suggested change
.catch(() => {});
.catch((error) => {
console.warn("[auto-updater:fork] Failed to open releases page:", error);
});
Fix with Cubic

sheetIndex++;
const dims = getSheetDimensions(worksheet);
const mergeMap = buildMergeMap(worksheet);
const shapes = drawingsMap.get(sheetIndex) || [];
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by sheetN.xml file index, which can misassociate shapes when sheet order and file numbering differ.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/SpreadsheetViewer/parseWorkbook.ts, line 592:

<comment>Shapes are looked up with a sequential sheet counter even though the drawing map is keyed by `sheetN.xml` file index, which can misassociate shapes when sheet order and file numbering differ.</comment>

<file context>
@@ -0,0 +1,685 @@
+		sheetIndex++;
+		const dims = getSheetDimensions(worksheet);
+		const mergeMap = buildMergeMap(worksheet);
+		const shapes = drawingsMap.get(sheetIndex) || [];
+		const colCount = dims.maxC - dims.minC + 1;
+		const columnWidths: number[] = [];
</file context>
Fix with Cubic


mergeViewRef.current = mergeView;

void loadLanguageSupport(language).then((ext) => {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: loadLanguageSupport(...) is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/TabView/FileViewerPane/components/CodeMirrorDiffViewer/CodeMirrorDiffViewer.tsx, line 95:

<comment>`loadLanguageSupport(...)` is used without rejection handling, which can cause unhandled promise rejections when dynamic language imports fail.</comment>

<file context>
@@ -0,0 +1,132 @@
+
+		mergeViewRef.current = mergeView;
+
+		void loadLanguageSupport(language).then((ext) => {
+			if (!ext || !mergeViewRef.current) return;
+			const mv = mergeViewRef.current;
</file context>
Fix with Cubic

@@ -1,5 +1,11 @@
import type { ExternalApp } from "@superset/local-db";
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: QUICK_OPEN is not gated by isActive, so hidden keep-alive workspace pages can still react to the global hotkey.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx, line 231:

<comment>`QUICK_OPEN` is not gated by `isActive`, so hidden keep-alive workspace pages can still react to the global hotkey.</comment>

<file context>
@@ -209,11 +228,12 @@ function WorkspacePage() {
 	);
 
-	useAppHotkey("NEW_GROUP", () => addTab(workspaceId), undefined, [
+	const hotkeyOptions = { enabled: isActive };
+	useAppHotkey("NEW_GROUP", () => addTab(workspaceId), hotkeyOptions, [
 		workspaceId,
</file context>
Fix with Cubic

}),
)
.mutation(({ input }) => {
const windowId = `tearoff-${Date.now()}`;
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: windowId uses only Date.now() (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/lib/trpc/routers/tab-tearoff.ts, line 18:

<comment>`windowId` uses only `Date.now()` (ms precision), so concurrent tearoff requests in the same millisecond can collide and overwrite pending tearoff data stored in the Map.</comment>

<file context>
@@ -0,0 +1,36 @@
+				}),
+			)
+			.mutation(({ input }) => {
+				const windowId = `tearoff-${Date.now()}`;
+
+				// Store data FIRST so it's available when preload requests it
</file context>
Fix with Cubic

}

return net.fetch(pathToFileURL(iconPath).toString());
} catch {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/extension-icon-protocol.ts, line 85:

<comment>Empty catch block swallows errors in the protocol handler, eliminating diagnostics for real failures (manifest parse, IO, etc.). Log the error at least at warning level before returning a 500.</comment>

<file context>
@@ -0,0 +1,89 @@
+			}
+
+			return net.fetch(pathToFileURL(iconPath).toString());
+		} catch {
+			return new Response("Internal error", { status: 500 });
+		}
</file context>
Fix with Cubic

try {
const data = await readFile(storePath, "utf-8");
return JSON.parse(data) as ExtensionStore;
} catch {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/extensions/extension-manager.ts, line 42:

<comment>Unload errors are silently swallowed during uninstall/disable, so unexpected removeExtension failures have no diagnostics while the store is still updated, risking runtime/store state drift.</comment>

<file context>
@@ -0,0 +1,339 @@
+	try {
+		const data = await readFile(storePath, "utf-8");
+		return JSON.parse(data) as ExtensionStore;
+	} catch {
+		return { extensions: [] };
+	}
</file context>
Fix with Cubic

@@ -0,0 +1,105 @@
import { constants } from "node:fs";
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/main/lib/shell-history.ts:

<comment>Empty catch blocks swallow real history read failures, making I/O errors indistinguishable from missing history and hurting observability. Log at least a warning (or otherwise surface the error) in these catch blocks.</comment>

<file context>
@@ -0,0 +1,105 @@
+import { constants } from "node:fs";
+import { access, readFile } from "node:fs/promises";
+import { homedir } from "node:os";
+
+let cachedHistory: string[] | null = null;
+let lastReadTime = 0;
+const CACHE_TTL_MS = 30_000;
+
+function parseZshHistory(content: string): string[] {
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant