Skip to content

Honor iMessage workspace ordering and previews - #4062

Merged
lawrencecchen merged 5 commits into
mainfrom
task-imessage-new-workspace-top
May 13, 2026
Merged

lawrencecchen merged 5 commits into
mainfrom
task-imessage-new-workspace-top

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

Task: iMessage mode workspace ordering and sidebar previews.

Changes:

  • Insert new workspaces at the top of the unpinned segment when iMessage mode is enabled, while pinned workspaces remain first.
  • Show the latest conversation message in the sidebar, including human prompt submits and agent final responses.
  • Handle stop and subagent stop feed events as assistant final messages.

Testing:

  • xcodebuild -project GhosttyTabs.xcodeproj -scheme cmux-unit -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/cmux-imtop-test -only-testing:cmuxTests/WorkspaceCreationPlacementTests -only-testing:cmuxTests/WorkspacePromptSubmitTests test
  • ./scripts/reload.sh --tag imtop

Note

Medium Risk
Changes workspace insertion/reordering behavior and feed-event side effects in iMessage mode, which can impact tab ordering, selection, and sidebar rendering. Risk is limited to UI/state updates (no auth/data persistence changes) but touches central TabManager and event-handling paths.

Overview
Improves iMessage mode workspace behavior and sidebar previews. New workspaces now insert at the top of the unpinned segment when iMessage mode is enabled (via WorkspacePlacementSettings.effectivePlacement), keeping pinned workspaces grouped first.

Sidebar preview text is renamed and expanded from latestSubmittedMessage to latestConversationMessage, and is now updated from both user prompt submits and assistant final responses; .stop/.subagentStop feed events trigger these assistant-final side effects.

Global search browse hits now treat .rightSidebarTool panels like title-only panels (previously excluded from the switch).

Reviewed by Cursor Bugbot for commit 705d7ec. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Makes iMessage mode feel like Messages: new workspaces go to the top of unpinned tabs, and the sidebar shows the latest conversation message (user prompt or assistant final). Stop events now count as assistant finals for previews and ordering, and repeated finals still bump the thread.

  • New Features

    • Insert new workspaces at the top of the unpinned segment when iMessage mode is on; pinned stay first and selection is preserved.
    • Sidebar preview now uses latestConversationMessage, showing user submits and assistant finals from .stop/.subagentStop; extracts text from event JSON/context and trims whitespace.
    • On prompt submit or a non-blank assistant final, record the preview and move the workspace to the top in iMessage mode.
  • Bug Fixes

    • Include the right sidebar tool panel in global search.
    • Reorder on repeated assistant finals even if the preview text doesn’t change; ignore blank finals.

Written for commit 705d7ec. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • New workspace insertion: when iMessage mode is enabled, new workspaces are placed at the top of the unpinned segment.
  • Improvements

    • Sidebar now shows conversation-based message previews with better de-duplication and trimming.
    • Assistant event handling expanded to record final messages (including stop events) and update workspace ordering.
    • Search mapping improved for right-sidebar results.
  • Tests

    • Updated/added tests for iMessage placement, conversation-message behavior, and assistant final-message scenarios.

Review Change Stack

@vercel

vercel Bot commented May 13, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 13, 2026 8:52am
cmux-staging Building Building Preview, Comment May 13, 2026 8:52am

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented May 13, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Renames workspace preview tracking from latestSubmittedMessage to latestConversationMessage, wires it through snapshots/UI and terminal feed, refactors WorkstreamEvent message extraction to key-driven helpers, adds assistant-final handling and conditional tab reordering, and forces top insertion when iMessage mode is enabled.

Changes

iMessage Conversation Message Flow

Layer / File(s) Summary
Workspace model refactoring
Sources/Workspace.swift
Workspace replaces latestSubmittedMessage with latestConversationMessage (@Published), adds recordConversationMessage(_:), updates observation/reset, and delegates recordSubmittedMessage(_:) to the new helper.
Snapshot structure and sidebar rendering
Sources/ContentView.swift, Sources/Sidebar/SidebarWorkspaceSnapshotRefreshPolicy.swift
SidebarWorkspaceSnapshotBuilder.Snapshot field renamed to latestConversationMessage; TabItemView computes conversationMessageSubtitle and uses it as fallback for effectiveSubtitle; makeWorkspaceSnapshot() and context-menu immediate-field copying populate/copy latestConversationMessage.
Message extraction and handler refactor
Sources/WorkspacePromptSubmit.swift
Refactor WorkstreamEvent parsing to messageText(from:keys:) with promptMessageKeys/assistantMessageKeys; add TabManager.handleAssistantFinalMessage(...); factor handleConversationMessage(...) to record conversation previews and conditionally reorder tabs; rename preview helper to conversationMessagePreview.
Feed event processing
Sources/TerminalController.swift
v2WorkspacePromptSubmit uses latestConversationMessage for preview; v2FeedPush now uses v2ApplyIMessageModeSideEffects(for:), which routes .userPromptSubmit to handlePromptSubmit(...) and .stop/.subagentStop to handleAssistantFinalMessage(...).
Workspace placement in iMessage mode
Sources/TabManager.swift
Add WorkspacePlacementSettings.effectivePlacement(...) that respects override, forces .top when iMessage mode is enabled, otherwise returns persisted placement; newTabInsertIndex uses this helper.
Search mapping tweak
Sources/Search/GlobalSearchDocuments.swift
Treat .rightSidebarTool the same as .terminal / .filePreview and assign .browser search kind.
Tests
cmuxTests/SidebarWorkspaceSnapshotRefreshPolicyTests.swift, cmuxTests/WorkspacePromptSubmitTests.swift, cmuxTests/WorkspaceUnitTests.swift
Update snapshot tests to use latestConversationMessage; expand prompt/assistant final and .stop feed tests; add regression test verifying iMessage-mode insertion at top of unpinned segment.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant TerminalController
  participant TabManager
  participant Workspace
  participant SidebarUI
  Client->>TerminalController: incoming feed event (userPromptSubmit / stop)
  TerminalController->>TabManager: v2ApplyIMessageModeSideEffects -> dispatch handler
  TabManager->>Workspace: handleConversationMessage / recordConversationMessage(message)
  Workspace-->>TabManager: messageRecorded / preview
  TabManager->>SidebarUI: update snapshot (latestConversationMessage) / reorder tabs
  SidebarUI-->>Client: render updated subtitle
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • manaflow-ai/cmux#3252: Directly related to iMessage-mode prompt-submit/message-preview plumbing and earlier latestSubmittedMessage behavior.
  • manaflow-ai/cmux#2023: Also modifies TabManager.newTabInsertIndex(snapshot:placementOverride:) insertion logic; overlapping area with placement changes.
  • manaflow-ai/cmux#2133: Changes in TabManager insertion/placement computation related to this PR's placement adjustments.

"I nibble code and hop through threads,
I stitch the messages where the sidebar treads,
Stops and assists, I tuck them in view,
Snapshots renamed, and tabs hop anew." 🐰✨


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description lacks key required sections from the template: no 'Demo Video' section, incomplete 'Testing' details, and no 'Review Trigger' block or checklist. Add a Demo Video URL/link for the UI changes, expand the Testing section with manual verification details, include the Review Trigger comment block, and complete the pre-merge checklist.
Cmux Swiftui State Layout ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title "Honor iMessage workspace ordering and previews" directly and clearly summarizes the main changes: iMessage mode workspace insertion behavior and sidebar conversation message previews.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed All new declarations maintain Swift 6 actor isolation. @MainActor classes properly isolated; value structs use Sendable types; nonisolated functions establish MainActor boundaries correctly.
Cmux Swift Blocking Runtime ✅ Passed PR introduces no blocking or timing-based synchronization primitives. All changes are refactoring/feature additions using proper async patterns.
Cmux No Hacky Sleeps ✅ Passed PR adds 1737 existing files. Sleeps match allowed cases: timeout abstractions, presentation timing, or tests. Rule restricts "introduced" sleeps; importing existing code doesn't apply.
Cmux Swift Concurrency ✅ Passed PR introduces mostly synchronous APIs for conversation messaging. One fire-and-forget Task in TerminalController is at an allowed external API boundary (workstream) and requires MainActor dispatch.
Cmux Swift @Concurrent ✅ Passed No new nonisolated async functions or @concurrent violations. All new methods are synchronous on @MainActor classes. Proper actor hops with v2MainSync and Task @MainActor patterns used.
Cmux Swift File And Package Boundaries ✅ Passed New file (154 lines) under 400-line threshold with single responsibility. Large file additions all <250 lines. No responsibility mixing or package boundary violations.
Cmux Swift Logging ✅ Passed No logging violations found. The PR introduces no new print, debugPrint, dump, NSLog, or improperly-declared Logger statements in production code.
Cmux Architecture Rethink ✅ Passed No violations. Single state owner, shared handlers, no new timing patterns, no duplicate wiring, clear invariants with test coverage.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR does not add or materially change standalone cmux-owned windows. Changes are to sidebar/preview logic, workspace placement, and message extraction only.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task-imessage-new-workspace-top

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.

@greptile-apps

greptile-apps Bot commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR wires up iMessage-mode workspace ordering and sidebar previews. New workspaces now insert at the top of the unpinned segment (pinned tabs remain first), and the sidebar preview tracks both user prompt submits and assistant final messages from .stop/.subagentStop feed events.

  • Workspace placement: WorkspacePlacementSettings.effectivePlacement returns .top when iMessage mode is on and no explicit placementOverride is given; explicit overrides are still respected.
  • Preview rename + expansion: latestSubmittedMessage becomes latestConversationMessage; recordSubmittedMessage is kept as a delegating wrapper; assistantFinalMessage extracts text from context.assistantPreamble, extraFieldsJSON, and toolInputJSON using a dedicated key list.
  • Reorder guard fix: handleConversationMessage now uses a hasMessage check alongside messageRecorded, so a workspace bubbles to the top even when the assistant completes twice with the same final text.

Confidence Score: 5/5

Safe to merge; changes are well-scoped to iMessage mode and do not affect non-iMessage workspace behavior.

The stop/subagentStop path now uses a non-blocking Task { @mainactor } instead of the synchronous main-thread hop, which is an improvement over the pre-existing userPromptSubmit pattern. The reorder guard correctly handles both new and duplicate assistant messages. The effectivePlacement helper cleanly centralizes iMessage placement logic without touching non-iMessage paths. Tests cover the key scenarios including duplicate-message reordering and blank-message suppression.

No files require special attention.

Important Files Changed

Filename Overview
Sources/WorkspacePromptSubmit.swift Adds assistantFinalMessage extraction from .stop/.subagentStop events; factors common JSON parsing into messageText(fromJSON:keys:); handleConversationMessage guard uses hasMessage to allow reorder even when preview text is unchanged
Sources/TerminalController.swift Routes .stop/.subagentStop through Task { @mainactor } instead of the blocking v2MainSync; userPromptSubmit keeps the pre-existing v2MainSync path
Sources/TabManager.swift effectivePlacement() returns .top in iMessage mode when no explicit override is given; test coverage validates pinned-tab and selection-preservation invariants
Sources/Workspace.swift Renames latestSubmittedMessage to latestConversationMessage; recordSubmittedMessage is kept as a backward-compat wrapper delegating to recordConversationMessage
Sources/ContentView.swift Renames latestSubmittedMessage to latestConversationMessage in SidebarWorkspaceSnapshotBuilder.Snapshot and TabItemView; no behavioral change to the subtitle logic
Sources/Search/GlobalSearchDocuments.swift Adds .rightSidebarTool to the .title kind mapping; small correctness fix for right-sidebar search results
Sources/Sidebar/SidebarWorkspaceSnapshotRefreshPolicy.swift Mechanical rename latestSubmittedMessage to latestConversationMessage to track the Snapshot field change
cmuxTests/WorkspacePromptSubmitTests.swift Adds tests for assistant final message recording, workspace reordering on duplicate message text, blank message suppression, and stop/subagentStop event JSON extraction
cmuxTests/WorkspaceUnitTests.swift Adds testAddWorkspaceInIMessageModeInsertsAtTopOfUnpinnedSegment; uses defer-based UserDefaults save/restore to avoid polluting other tests

Reviews (3): Last reviewed commit: "fix: handle repeated assistant imessage ..." | Re-trigger Greptile

Comment thread Sources/WorkspacePromptSubmit.swift Outdated
Comment thread Sources/TerminalController.swift

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 705d7ec. Configure here.

message: assistantFinalMessage,
iMessageModeEnabled: iMessageModeEnabled
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Async stop handling races with synchronous prompt handling

Low Severity

The .stop/.subagentStop branch dispatches sidebar updates via a fire-and-forget Task { @MainActor }, while .userPromptSubmit uses the synchronous v2MainSync. Because the Task is not awaited and ingestBlocking proceeds immediately, a prompt-submit event arriving shortly after a stop event can have its synchronous v2MainSync handler execute before the stop event's Task, causing moveTabToTop calls to run in reverse chronological order. This could make the sidebar workspace ordering briefly inconsistent with the actual event timeline.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 705d7ec. Configure here.

@lawrencecchen
lawrencecchen merged commit 70c4e6e into main May 13, 2026
30 checks passed
@lawrencecchen
lawrencecchen deleted the task-imessage-new-workspace-top branch May 13, 2026 08:58

This branch was successfully deployed

1 active deployment
Preview – cmux — 705d7ec2 Deployed May 13, 2026 by vercel[bot]
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