feat(desktop,ipc,ui): chrome title overflow menu — thread actions, reveal, open in editor - #265
feat(desktop,ipc,ui): chrome title overflow menu — thread actions, reveal, open in editor#265AprilNEA wants to merge 6 commits into
Conversation
Greptile SummaryAdds a desktop thread-title overflow menu.
Confidence Score: 5/5The PR appears safe to merge with no blocking failures remaining from the reviewed threads. No blocking failure remains.
What T-Rex did
Important Files Changed
Reviews (3): Last reviewed commit: "test(desktop): let the thread-menu e2e f..." | Re-trigger Greptile |
…ect and launch editors
Adds VSCodium, Trae, Antigravity, and the common JetBrains IDEs. JetBrains carry no windowsExe: their installer nests the binary under a version-stamped directory this model can't address, so Windows stays uncovered rather than guessed.
|
Warning Review limit reached
Next review available in: 8 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAdds a desktop thread title menu with pin, clipboard, reveal, editor, and close actions. Introduces shell/editor IPC capabilities, platform-specific editor detection, localization, desktop integration, and an isolated end-to-end test. ChangesThread title menu
Estimated code review effort: 4 (Complex) | ~45 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant ThreadMenu
participant RendererBridge
participant ElectronIPC
participant DesktopShell
ThreadMenu->>RendererBridge: revealPath or openInEditor
RendererBridge->>ElectronIPC: invoke shell operation
ElectronIPC->>DesktopShell: validate and execute request
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/desktop/e2e/thread-menu.e2e.mts`:
- Around line 35-38: Update fail() to throw an Error with the supplied message
instead of calling process.exit(1), allowing existing catch and finally handling
in main() to capture diagnostics and clean up resources. Preserve the failure
reporting and exit-code behavior already implemented by main().
In `@packages/presentation/ui/src/shell/thread-title-menu.tsx`:
- Around line 29-65: Rename the shared menu module and its ThreadTitleMenu and
ThreadTitleMenuEditor symbols to session-based names, preserving the existing
behavior and UI/i18n terminology. Update the re-export in
packages/presentation/ui/src/shell/index.ts at line 30 and all corresponding
imports, component usages, and type references in
apps/desktop/src/renderer/src/shell/desktop-shell.tsx at lines 2-11; do not
rename wire or other code identifiers outside this UI naming scope.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 46170f41-078f-4b6e-8ba5-5cc958d1e541
📒 Files selected for processing (17)
apps/desktop/e2e/thread-menu.e2e.mtsapps/desktop/package.jsonapps/desktop/src/main/__tests__/editors.test.tsapps/desktop/src/main/editors.tsapps/desktop/src/main/system-context.tsapps/desktop/src/renderer/src/ipc.tsapps/desktop/src/renderer/src/shell/chrome/chrome.tsxapps/desktop/src/renderer/src/shell/desktop-shell.tsxpackages/presentation/i18n/src/locales/en.tspackages/presentation/i18n/src/locales/zh-cn.tspackages/presentation/ui/src/shell/index.tspackages/presentation/ui/src/shell/thread-title-menu.tsxpackages/system-plane/ipc/src/bridge.tspackages/system-plane/ipc/src/context.tspackages/system-plane/ipc/src/electron-main.tspackages/system-plane/ipc/src/electron-renderer.tspackages/system-plane/ipc/src/events.ts
| /** One editor the host detected; `id` is opaque and travels back on open. */ | ||
| export interface ThreadTitleMenuEditor { | ||
| id: string; | ||
| label: string; | ||
| } | ||
|
|
||
| export interface ThreadTitleMenuProps { | ||
| /** Copied verbatim by the copy item. */ | ||
| title: string; | ||
| pinned: boolean; | ||
| fileManager: FileManagerKind; | ||
| /** Detected editors; empty hides the open-in-editor item entirely. */ | ||
| editors: ThreadTitleMenuEditor[]; | ||
| onTogglePin: () => void; | ||
| onReveal: () => void; | ||
| onOpenInEditor: (editorId: string) => void; | ||
| /** Stop the thread if live and drop it from the list. */ | ||
| onClose: () => void; | ||
| } | ||
|
|
||
| const REVEAL_KEY = { | ||
| darwin: 'reveal.darwin', | ||
| win32: 'reveal.win32', | ||
| other: 'reveal.other', | ||
| } as const; | ||
|
|
||
| /** The chrome title's overflow menu: what you can do to the thread you're looking at. */ | ||
| export function ThreadTitleMenu({ | ||
| title, | ||
| pinned, | ||
| fileManager, | ||
| editors, | ||
| onTogglePin, | ||
| onReveal, | ||
| onOpenInEditor, | ||
| onClose, | ||
| }: ThreadTitleMenuProps): React.ReactNode { |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use session consistently for the new menu’s code identifiers. Thread is UI/i18n terminology only; the shared component introduced it into module, type, and component names.
packages/presentation/ui/src/shell/thread-title-menu.tsx#L29-L65: rename the module,ThreadTitleMenu, andThreadTitleMenuEditorto session-based names.packages/presentation/ui/src/shell/index.ts#L30-L30: re-export the renamed session-based module.apps/desktop/src/renderer/src/shell/desktop-shell.tsx#L2-L11: update imports and all corresponding type/component usages.
As per coding guidelines, “Use session as the code and wire term for the UI product concept Thread; the rename is UI/i18n-only and code or wire identifiers must not be renamed.”
📍 Affects 3 files
packages/presentation/ui/src/shell/thread-title-menu.tsx#L29-L65(this comment)packages/presentation/ui/src/shell/index.ts#L30-L30apps/desktop/src/renderer/src/shell/desktop-shell.tsx#L2-L11
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/presentation/ui/src/shell/thread-title-menu.tsx` around lines 29 -
65, Rename the shared menu module and its ThreadTitleMenu and
ThreadTitleMenuEditor symbols to session-based names, preserving the existing
behavior and UI/i18n terminology. Update the re-export in
packages/presentation/ui/src/shell/index.ts at line 30 and all corresponding
imports, component usages, and type references in
apps/desktop/src/renderer/src/shell/desktop-shell.tsx at lines 2-11; do not
rename wire or other code identifiers outside this UI naming scope.
Source: Coding guidelines
…e executable A cached existence-only snapshot let a present-but-non-executable PATH entry outrank a working application bundle, and went stale as soon as an editor moved or was uninstalled.
|
Thanks — three of the four are addressed in Greptile P2 (non-executable target wins) + P1 (cached target goes stale) — fixed togetherBoth had one root cause: a cached, existence-only snapshot. Rather than patch each symptom, the snapshot is gone: export function isLaunchable(target: EditorTarget): boolean {
if (target.kind === 'mac-app') return existsSync(target.bundle);
try { accessSync(target.file, constants.X_OK); return true; } catch { return false; }
}
/** Resolved per call rather than cached: a snapshot goes stale the moment an editor is
* installed, moved, upgraded, or removed. */
function resolveInstall(candidate) { return editorTargets(candidate, process.platform).find(isLaunchable); }
CodeRabbit:
|
shell/sidebar/thread-row.tsx |
ThreadRow, ThreadRowProps |
shell/sidebar/thread-im-menu.tsx |
ThreadImMenuItems, ThreadImMenuComponentType, ThreadImMenuChatView |
shell/sidebar/group-header.tsx |
ThreadGroupHeader, ThreadGroupHeaderProps |
shell/threads-view.tsx |
ThreadsView, ThreadGroupViewModel, ThreadsViewProps |
shell/sidebar/thread-group-actions.ts |
ThreadGroupActions, ThreadGroupState |
thread-groups.ts |
ThreadGroup |
ThreadTitleMenu sits in that same directory next to ThreadImMenu. Renaming only the new one would make it the single inconsistent member. Note the data still travels as session throughout — the component takes SessionInfo-derived props and the desktop wiring calls onToggleSessionPinned / onCloseSession; no wire or data identifier was renamed.
Happy to rename the whole family in a separate sweep if that's the preferred direction, but that's a repo-wide decision, not this PR's.
CI
The Desktop App Entry failure was flaky, not caused by this PR — it's e2e:window-bounds asserting the maximized state survives a relaunch (Linux/xvfb). Re-ran the same commit with no changes: passed. Nothing here touches window state; master@364dd559 hit the same assertion for the same reason.
pnpm check:ci + pnpm test (1920 pass) green, and e2e:thread-menu PASS after the changes.
Closes CODE-379.
Wires the disabled ellipsis placeholder right of the document title into the active thread's overflow menu.
Stacked on #239
Base is
xuan/code-380, not master. This branch needs the renderer-crash fix from #239 to run — without it the desktop app white-screens (that bug is still shipped on master, 0.6.3). Merge #239 first, then retarget this to master. The diff here is only the four feature commits; the fix commit belongs to #239.What's in it
shellsystem capability (packages/system-plane/ipc):revealPath/listEditors/openInEditor, mirrored across the eventa contract + main impl. The renderer half stays zod-free (sandboxed preload).apps/desktop/src/main/editors.ts): probes PATH + macOS app bundles for installed editors. Coverage follows vitejs/launch-editor's editor-info catalog (MIT) — VS Code family (incl. VSCodium/Cursor/Windsurf/Trae/Antigravity), Sublime, Zed, and the common JetBrains IDEs. Terminal editors (vim/emacs) and EOL apps (Atom/Brackets) are excluded — the menu opens a workspace folder in a GUI editor. JetBrains carry nowindowsExe(version-stamped install dir this model can't address), so Windows stays uncovered rather than guessed.packages/presentation/ui/src/shell/thread-title-menu.tsx): pure props-driven coss-uiMenu; the editor item is hidden at 0 detected, a plain item at 1, a submenu at >1. Reveal label varies by platform (Finder / File Explorer / file manager).DesktopChromeProps.titleMenuslot; desktop supplies it reusing existing pin/close/cwd props +systemBridge.shell.*. An untitled thread or the draft page hides the whole title area (and the menu) as before.workbench.threadMenunamespace; the barelabel="More"is gone.Verification
editorTargets(all shapes incl. JetBrains-on-Windows →[]).e2e:thread-menu: seeds a titled session straight into the daemon DB (no agent CLI needed) and drives the menu — pin round-trips through the sidebar's Pinned group, copy lands on the clipboard, reveal reaches main with the thread cwd, close drops the thread. Open-in-editor is presence-only (clicking would launch a real editor). Ran green on this machine (Zed detected); screenshot confirms the menu.pnpm check:ciandpnpm test(1737 tests) pass.Not covered: renaming a thread — there is no
session.renamewire op (would need aWIRE_PROTOCOL_VERSIONbump).Summary by CodeRabbit
New Features
Tests