Skip to content

tooltip for delete tab + kill processes when delete workspace#254

Merged
AviPeltz merged 4 commits intomainfrom
jade-river-7
Dec 4, 2025
Merged

tooltip for delete tab + kill processes when delete workspace#254
AviPeltz merged 4 commits intomainfrom
jade-river-7

Conversation

@AviPeltz
Copy link
Copy Markdown
Collaborator

@AviPeltz AviPeltz commented Dec 4, 2025

Description

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes

Summary by CodeRabbit

  • New Features

    • Tooltip added to the workspace delete button ("Delete workspace").
    • Delete confirmation now shows live count of active terminals and refreshes while open.
  • Accessibility

    • Button aria-label changed from "Close workspace" to "Delete workspace" for clearer intent.
  • Bug Fixes / Reliability

    • Deleting a workspace now terminates associated terminal processes and returns a terminal warning if needed.
  • Tests

    • New tests covering terminal termination and per-workspace session counts.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 4, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
website Ready Ready Preview Comment Dec 4, 2025 6:45pm

@AviPeltz AviPeltz marked this pull request as draft December 4, 2025 07:57
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 4, 2025

Walkthrough

Adds terminal-aware workspace deletion: UI tooltip on the delete button, dialog polling revealing active terminal counts, TerminalManager methods to count and kill sessions by workspace, and TRPC canDelete/delete integration to surface counts, warnings, and to terminate terminals before workspace removal.

Changes

Cohort / File(s) Summary
UI — Tooltip & accessibility
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
Wrapped the delete button with Tooltip, TooltipTrigger, and TooltipContent; updated aria-label from "Close workspace" to "Delete workspace".
UI — Delete dialog polling & terminal info
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
canDelete query now uses refetchInterval: 2000 while open; reads activeTerminalCount and renders a warning when >0; shows toast warnings for teardownError and terminalWarning.
Backend — TRPC router changes
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
Imported terminalManager; canDelete now returns activeTerminalCount (via getSessionCountByWorkspaceId); delete calls terminalManager.killByWorkspaceId and returns terminalWarning alongside teardown results.
Main — Terminal manager API & tests
apps/desktop/src/main/lib/terminal-manager.ts, apps/desktop/src/main/lib/terminal-manager.test.ts
Added getSessionCountByWorkspaceId(workspaceId: string): number and killByWorkspaceId(workspaceId: string): Promise<{ killed:number; failed:number }>; added tests covering per-workspace counting, killing, history cleanup, and exit handling scenarios.

Sequence Diagram(s)

sequenceDiagram
  actor User
  participant Renderer as Renderer (React)
  participant TRPC as TRPC Router
  participant Main as TerminalManager
  participant DB as Database

  User->>Renderer: open DeleteWorkspaceDialog
  Renderer->>TRPC: canDelete(workspaceId) [polled every 2s]
  TRPC->>Main: getSessionCountByWorkspaceId(workspaceId)
  Main-->>TRPC: activeTerminalCount
  TRPC-->>Renderer: { canDelete, reason, activeTerminalCount }

  alt User confirms delete
    Renderer->>TRPC: delete(workspaceId)
    TRPC->>Main: killByWorkspaceId(workspaceId)
    Main-->>TRPC: {killed, failed}
    TRPC->>DB: remove workspace/worktree records
    DB-->>TRPC: deletion result
    TRPC-->>Renderer: delete result (includes terminalWarning/teardownError)
    Renderer->>User: show success/warnings
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay attention to:
    • terminal-manager.killByWorkspaceId concurrency, timeouts, SIGTERM→SIGKILL sequence, and per-session cleanup.
    • TRPC delete ordering, error handling, and propagation of terminalWarning/teardownError.
    • Type/interface updates for canDelete and delete responses to keep client/server in sync.
    • Delete dialog polling lifecycle (refetchInterval) to ensure it stops when dialog closes.
    • New tests in terminal-manager.test.ts for flakiness and accurate PTY hook simulation.

Possibly related PRs

Poem

🐇
I counted shells where terminals hum,
I nudged "Delete" — the tooltip strum.
I asked the sessions, "Time to go?"
SIGTERM first, then a final show.
Hop-hop — tidy desks, soft bunny toe.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is mostly unfilled, with only the Type of Change checkbox completed (marked as Bug fix). All other required sections lack any substantive content. Fill in Description section explaining why processes need to be killed and tooltip added. Add Related Issues, Testing steps, and any Additional Notes to complete the template.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes both main changes: adding a tooltip for the delete tab and killing processes when deleting a workspace.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jade-river-7

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (1)

176-198: Tooltip‑wrapped delete button looks good; consider more descriptive labels

Wrapping the delete icon button in a tooltip preserves the existing click behavior and improves discoverability. For better accessibility and clarity (especially for screen readers and when multiple tabs are present), consider including the workspace title in both the aria label and tooltip text:

-        <Button
+        <Button
           type="button"
           variant="ghost"
           size="icon"
@@
-          aria-label="Delete workspace"
+          aria-label={`Delete workspace ${title}`}
         >
           <HiMiniXMark />
         </Button>
       </TooltipTrigger>
-      <TooltipContent side="bottom" showArrow={false}>
-        Delete workspace
-      </TooltipContent>
+      <TooltipContent side="bottom" showArrow={false}>
+        {`Delete workspace "${title}"`}
+      </TooltipContent>

This keeps behavior the same while making the control’s target more explicit.

Please verify that interpolating title here doesn’t conflict with any existing i18n strategy and that the tooltip renders as expected for long workspace names.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bf23b2 and c0d617d.

📒 Files selected for processing (1)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
**/components/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/components/**/*.tsx: Create one folder per component with structure: ComponentName/ComponentName.tsx + index.ts for barrel export
Co-locate tests next to the component file they test (e.g., ComponentName.test.tsx)
Co-locate dependencies (utils, hooks, constants, config, stories) next to the file using them
Use nested components/ subdirectory within a parent component only if a sub-component is used 2+ times within that parent; otherwise keep it in the parent's components/ folder
One component per file - avoid multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
apps/desktop/src/renderer/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Call IPC methods using window.ipcRenderer.invoke() with object parameters - TypeScript will infer the exact response type automatically

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/WorkspaceItem.tsx (1)

3-3: Tooltip import is minimal and consistent with new usage

The added Tooltip, TooltipTrigger, and TooltipContent import is used directly below and keeps the diff tight with no unused symbols or style violations.

Please sanity‑check against other @superset/ui/tooltip usages in the repo to ensure pattern consistency (e.g., TooltipTooltipTrigger asChildTooltipContent).

@AviPeltz AviPeltz marked this pull request as ready for review December 4, 2025 08:55
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
apps/desktop/src/main/lib/terminal-manager.test.ts (1)

637-638: Avoid hardcoded timeouts in tests for better reliability.

The use of setTimeout(resolve, 100) introduces timing dependencies that can make tests flaky on slower CI systems or under load. Consider using event-driven approaches or mocking time.

For instance, at lines 637-638, the 100ms wait is used to ensure cleanup completes. Instead of waiting, you could:

  • Listen for specific cleanup events if the API supports it
  • Use mock timers (e.g., jest.useFakeTimers() or bun's equivalent)
  • Make the test await the actual cleanup promise if exposed

As per learnings, tests should be repeatable and reliable across different environments.

Also applies to: 668-668, 730-731

apps/desktop/src/main/lib/terminal-manager.ts (1)

351-360: Document the forced cleanup behavior.

When a process doesn't respond to SIGKILL within 500ms (line 348-361), the code forcibly marks isAlive = false and deletes the session, but logs that "Process may still be running." This is the correct defensive approach, but the implications should be clearly documented.

Consider adding a JSDoc comment above killByWorkspaceId explaining:

  • The termination stages and timeouts
  • What happens if a process can't be killed
  • Potential for orphaned processes
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)

354-356: Consider more informative terminal warning message.

The current warning only reports failed kills: "${terminalResult.failed} terminal process(es) may still be running".

If killed=5 and failed=2, users might benefit from knowing that 5 terminals were successfully terminated, and 2 may still be running. This provides better context for the warning.

Consider:

 const terminalWarning =
   terminalResult.failed > 0
-    ? `${terminalResult.failed} terminal process(es) may still be running`
+    ? `Terminated ${terminalResult.killed} terminal(s); ${terminalResult.failed} process(es) may still be running`
     : undefined;

Also applies to: 433-438

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx (1)

35-36: Consider extracting polling interval as a named constant.

The 2000 ms refetch interval is a magic number that appears only once but represents a UX decision about terminal count freshness.

For better maintainability:

+const TERMINAL_COUNT_POLL_INTERVAL_MS = 2000;
+
 const { data: canDeleteData, isLoading } = trpc.workspaces.canDelete.useQuery(
   { id: workspaceId },
   {
     enabled: open,
-    refetchInterval: open ? 2000 : false,
+    refetchInterval: open ? TERMINAL_COUNT_POLL_INTERVAL_MS : false,
   },
 );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 518c4d6 and 910f5ef.

📒 Files selected for processing (4)
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (7 hunks)
  • apps/desktop/src/main/lib/terminal-manager.test.ts (1 hunks)
  • apps/desktop/src/main/lib/terminal-manager.ts (1 hunks)
  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
  • apps/desktop/src/main/lib/terminal-manager.test.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
  • apps/desktop/src/main/lib/terminal-manager.test.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
  • apps/desktop/src/main/lib/terminal-manager.test.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
**/components/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

**/components/**/*.tsx: Create one folder per component with structure: ComponentName/ComponentName.tsx + index.ts for barrel export
Co-locate tests next to the component file they test (e.g., ComponentName.test.tsx)
Co-locate dependencies (utils, hooks, constants, config, stories) next to the file using them
Use nested components/ subdirectory within a parent component only if a sub-component is used 2+ times within that parent; otherwise keep it in the parent's components/ folder
One component per file - avoid multi-component files

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
apps/desktop/src/renderer/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules (fs, path, os, net, etc.) in renderer process code - browser environment only

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
apps/desktop/src/renderer/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Call IPC methods using window.ipcRenderer.invoke() with object parameters - TypeScript will infer the exact response type automatically

Files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
apps/desktop/**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.test.{ts,tsx,js,jsx}: Tests should have one assert per test
Tests should be readable
Tests should be fast
Tests should be independent
Tests should be repeatable

Files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
apps/desktop/src/main/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js modules (fs, path, os, net, etc.) can be used in main process code only

Files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
  • apps/desktop/src/main/lib/terminal-manager.ts
apps/desktop/src/lib/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in shared code like src/lib/electron-router-dom.ts - this code runs in both main and renderer processes

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
🧠 Learnings (3)
📚 Learning: 2025-11-28T01:03:47.963Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-28T01:03:47.963Z
Learning: Applies to **/*.{ts,tsx} : Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications

Applied to files:

  • apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be independent

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
📚 Learning: 2025-11-24T21:33:13.267Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-11-24T21:33:13.267Z
Learning: Applies to apps/desktop/**/*.test.{ts,tsx,js,jsx} : Tests should be repeatable

Applied to files:

  • apps/desktop/src/main/lib/terminal-manager.test.ts
🧬 Code graph analysis (2)
apps/desktop/src/main/lib/terminal-manager.ts (1)
apps/desktop/src/main/lib/terminal-history.ts (1)
  • cleanup (131-138)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)
apps/desktop/src/main/lib/terminal-manager.ts (1)
  • terminalManager (506-506)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (8)
apps/desktop/src/main/lib/terminal-manager.test.ts (1)

583-735: Comprehensive test coverage for new terminal management features.

The test suites for killByWorkspaceId and getSessionCountByWorkspaceId cover the key scenarios effectively:

  • Workspace isolation
  • Non-existent workspace handling
  • History cleanup
  • Dead session handling
  • Active session counting

The tests follow the coding guidelines with clear, independent test cases.

apps/desktop/src/main/lib/terminal-manager.ts (2)

399-403: Simple and correct implementation.

The getSessionCountByWorkspaceId method is straightforward and correctly filters for both workspace ID and alive status.


300-397: Test the actual SIGTERM→SIGKILL→force cleanup timeout behavior.

The staged termination logic is well-structured with defensive cleanup guards (resolved flag, idempotent closeHistory, safe event handler removal). However, the test suite uses mocked PTY that exits via setImmediate, so the actual 2000ms SIGTERM→SIGKILL and 500ms SIGKILL→force cleanup timeouts are never exercised. Consider adding tests that verify the timeout progression works correctly with real delays.

apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (2)

287-342: Consistent terminal count integration across all branches.

The activeTerminalCount is properly added to all return paths of canDelete:

  • Workspace not found (line 287)
  • Worktree exists check (lines 315, 324)
  • No worktree error (line 331)
  • No associated worktree (line 341)

This ensures the UI can always display the terminal count regardless of the workspace state.


354-356: Proper sequencing of terminal cleanup before workspace deletion.

Invoking terminalManager.killByWorkspaceId(input.id) before the teardown and worktree removal ensures terminals are properly terminated first. This prevents potential issues with file locks or running processes during deletion.

apps/desktop/src/renderer/screens/main/components/TopBar/WorkspaceTabs/DeleteWorkspaceDialog.tsx (3)

31-37: Good refetch pattern for keeping terminal count fresh.

The refetchInterval tied to the open state ensures the terminal count updates while the dialog is visible, without unnecessary polling when closed. The 2-second interval strikes a good balance between freshness and network/CPU usage.


46-58: Clear separation of teardown and terminal warnings.

The separate toast warnings for teardownError and terminalWarning provide clear, specific feedback to users about different failure modes during workspace deletion. The 100ms delay allows the success toast to appear first.


94-99: Clear terminal count messaging with proper pluralization.

The conditional rendering and pluralization correctly handles single/multiple terminals, providing clear expectations to users about what will happen during deletion.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@AviPeltz AviPeltz merged commit 596e97c into main Dec 4, 2025
6 of 7 checks passed
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)

354-358: Consider handling killByWorkspaceId failures so deletion isn’t blocked by terminal errors

Right now, if terminalManager.killByWorkspaceId throws for any reason, the mutation will abort before worktree removal and DB cleanup, which can leave the user unable to delete a problematic workspace even though orphaned terminals are often non‑critical. You already model partial failure via terminalWarning, so it would be more robust to treat terminal-kill failures as a warning rather than a hard failure.

You can centralize both the kill and terminalWarning computation in a small try/catch block:

-				// Kill all terminal processes in this workspace first
-				const terminalResult = await terminalManager.killByWorkspaceId(
-					input.id,
-				);
+				// Kill all terminal processes in this workspace first
+				let terminalWarning: string | undefined;
+				try {
+					const terminalResult = await terminalManager.killByWorkspaceId(
+						input.id,
+					);
+					if (terminalResult.failed > 0) {
+						terminalWarning = `${terminalResult.failed} terminal process(es) may still be running`;
+					}
+				} catch (error) {
+					console.error(
+						"Failed to kill terminal processes for workspace",
+						input.id,
+						error,
+					);
+					terminalWarning = "Terminal processes may still be running";
+				}
@@
-				const terminalWarning =
-					terminalResult.failed > 0
-						? `${terminalResult.failed} terminal process(es) may still be running`
-						: undefined;
-
-				return { success: true, teardownError, terminalWarning };
+				return { success: true, teardownError, terminalWarning };

This way, workspace deletion proceeds even if process termination is imperfect, and callers still get a clear signal that there may be lingering terminals.

Also applies to: 435-441

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 910f5ef and 46ede62.

📒 Files selected for processing (1)
  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
apps/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

For Electron interprocess communication, ALWAYS use tRPC as defined in src/lib/trpc

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
apps/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)

apps/desktop/**/*.{ts,tsx}: Please use alias as defined in tsconfig.json when possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid using any type - use explicit types instead for type safety
Use camelCase for variable and function names following existing codebase patterns
Keep diffs minimal with targeted edits only - avoid unnecessary changes when making modifications
Follow existing patterns and match the codebase style when writing new code

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
apps/desktop/src/lib/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Never import Node.js modules in shared code like src/lib/electron-router-dom.ts - this code runs in both main and renderer processes

Files:

  • apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts
🧬 Code graph analysis (1)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (1)
apps/desktop/src/main/lib/terminal-manager.ts (1)
  • terminalManager (506-506)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (2)
apps/desktop/src/lib/trpc/routers/workspaces/workspaces.ts (2)

4-4: Terminal manager import looks appropriate for TRPC router usage

Bringing terminalManager in at the router layer is a good place to centralize workspace/terminal coordination and keeps IPC flowing through tRPC as per the guidelines. No changes needed here.


277-343: activeTerminalCount plumbing in canDelete is consistent and useful

The way activeTerminalCount is computed once and then returned on every code path (including error and “workspace not found” cases) is clean and keeps the tRPC output shape consistent. This should make it straightforward for the UI to display terminal activity state alongside delete affordances.

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