Skip to content

[codex] Always enable agent prose streaming - #7066

Merged
azooz2003-bit merged 3 commits into
mainfrom
codex/always-enable-agent-prose-streaming
Jun 29, 2026
Merged

azooz2003-bit merged 3 commits into
mainfrom
codex/always-enable-agent-prose-streaming

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jun 29, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Remove the CMUXAgentChatProseStreaming UserDefaults feature flag and its app-target wrapper.
  • Start live agent prose previews from hook turn lifecycle events whenever the session has a live surface.
  • Keep runtime safety gates for active turns and subscribed chat clients, so idle sessions are not polled.
  • Add a regression test proving streaming still emits when the legacy defaults key is explicitly false.

Why

The partial-response work shipped behind a default-off flag, so users did not see partial agent responses unless they manually enabled a hidden default. The intended behavior is for streaming previews to be always available.

Validation

  • python3 scripts/normalize-pbxproj.py --check
  • ./scripts/check-pbxproj.sh
  • ./scripts/lint-pbxproj-test-wiring.sh
  • xcodebuild test -project cmux.xcodeproj -scheme cmux-unit -configuration Debug -destination 'platform=macOS' -derivedDataPath /tmp/cmux-always-enable-agent-prose-streaming-test -only-testing:cmuxTests/AgentChatProseStreamerTests
  • ./scripts/reload.sh --tag always-enable-agent-prose-streaming

Localization

No user-facing strings were added or changed.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Always enable live agent prose streaming. Adds a regression test to ensure streaming emits when the legacy defaults key is false, and refreshes the Swift file length budget guard.

  • Refactors
    • Removed AgentChatProseStreamingFlag and related wiring.
    • Drive previews from hook lifecycle events (userPromptSubmit starts; turn end stops).
    • Keep idle-session protections: only poll with an active turn and subscribed clients.
    • Refreshed Swift file length budget guard entries.

Written for commit 619e30a. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Live agent chat “streaming prose” previews now start based on active session activity and available listeners, instead of being blocked by the legacy streaming setting.
    • Ending/stop behavior for prose previews continues to follow session state to improve reliability.
  • Tests

    • Added an XCTest that verifies the initial “streaming prose” preview frame is emitted correctly when the prior user setting is disabled.

@vercel

vercel Bot commented Jun 29, 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 Jun 29, 2026 11:07pm
cmux-staging Building Building Preview, Comment Jun 29, 2026 11:07pm

@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bbf91f79-7f78-464d-9caa-adf74e7c13c6

📥 Commits

Reviewing files that changed from the base of the PR and between e2adf48 and 619e30a.

📒 Files selected for processing (1)
  • cmux.xcodeproj/project.pbxproj

📝 Walkthrough

Walkthrough

Removes AgentChatProseStreamingFlag and updates prose streaming to run without the legacy flag check. AgentChatProseStreamer now gates on subscribers only, AgentChatTranscriptService starts turns without the flag, and a new test verifies the legacy flag being false still allows streaming.

Changes

Remove prose streaming feature flag

Layer / File(s) Summary
Remove isEnabled gating from streamer and transcript service
Sources/Mobile/AgentChat/AgentChatProseStreamer.swift, Sources/Mobile/AgentChat/AgentChatProseStreamingFlag.swift, Sources/Mobile/AgentChat/AgentChatTranscriptService.swift
AgentChatProseStreamingFlag is deleted; AgentChatProseStreamer removes the isEnabled dependency and now returns early from emitPreviewIfChanged only when there are no subscribers; AgentChatTranscriptService removes the AgentChatProseStreamingFlag.isEnabled check before calling proseStreamer.turnStarted.
Add AgentChatProseStreamerTests and update Xcode project
cmuxTests/AgentChatProseStreamerTests.swift, cmux.xcodeproj/project.pbxproj
A new XCTest case uses a SleepGate actor and legacy UserDefaults override to verify an emitted streaming prose frame; the Xcode project removes the flag source from the app target and adds the test file to the test target.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • manaflow-ai/cmux#6731: Introduced the AgentChatProseStreamingFlag path and the original gating that this PR removes.

Poem

🐇 Hop, hop — the flag has flown away,
Subscribers now decide the play.
A stream of prose twinkles bright and free,
No old gatekeeper in sight for me.
The rabbit wiggles its nose with glee.


Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Blocking Runtime ❌ Error Production AgentChatProseStreamer still polls with await sleep(pollInterval), and this PR removes the feature-flag gate so it runs for all subscribed sessions. Use a real terminal-update signal/callback to drive previews, or keep polling confined to test scaffolding instead of shipped Swift code.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: always enabling agent prose streaming.
Description check ✅ Passed The description covers summary, motivation, validation, and localization, with only a few non-critical template sections omitted.
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 Changed Swift types are intentionally @MainActor UI/service coordinators, and the new test stays on MainActor; no new protocol, Sendable, or background UI-access isolation debt was introduced.
Cmux Browser Automation Off-Main ✅ Passed Rule targets browser socket automation in TerminalController/ControlCommandExecutionPolicy; this PR only changes AgentChat streaming/test wiring, so it doesn't apply.
Cmux Expensive Synchronous Load ✅ Passed PASS: The PR only shifts prose preview start/stop logic; the streamer still polls terminal snapshots behind hasSubscribers, with no new RestorableAgentSessionIndex.load()/JSON file loads.
Cmux Cache Substitution Correctness ✅ Passed The diff only gates a live preview on subscribers and active turns; it still reads fresh surface rows and never feeds persistence/history/undo/snapshot.
Cmux No Hacky Sleeps ✅ Passed No non-Swift runtime/script changes add sleeps; the only timing seam is test-only Swift scaffolding, and the non-Swift edit is just the Xcode project.
Cmux Algorithmic Complexity ✅ Passed Production edits only remove a flag gate and keep O(n) teardown; no new nested scans, rescans, or hot-path sorting/filtering were introduced.
Cmux Swift Concurrency ✅ Passed PASS: The diff only removes flag gates and updates event routing; it adds no DispatchQueue/Combine/completion-handler code, and the remaining Task is stored/cancelled.
Cmux Swift @Concurrent ✅ Passed All changed async work stays @MainActor; no new nonisolated async helpers or invalid @concurrent annotations were introduced.
Cmux Swift File And Package Boundaries ✅ Passed The new streamer is small app-specific glue with injected seams; the only oversized production file got a tiny incidental edit, and the new code is test-only.
Cmux Swiftpm Lockfiles ✅ Passed PR diff only touches cmux.xcodeproj/project.pbxproj for test wiring; no Package.resolved or .gitignore edits, so swiftpm lockfile rules aren’t implicated.
Cmux Swift Logging ✅ Passed No added print/debugPrint/dump/NSLog/Logger in the touched Swift files; the only dump hit is a structured debugSessionDump return, not logging.
Cmux User-Facing Error Privacy ✅ Passed No production user-facing error/alert/recovery text was added; changes are internal logic, docs, and a test-only defaults key.
Cmux Full Internationalization ✅ Passed The PR only changes Swift logic, comments, a test, and project wiring; no user-facing text or locale/catalog files were added or edited.
Cmux Swiftui State Layout ✅ Passed Touched files are service/test/project code only; no new SwiftUI state/layout patterns or view boundary changes appear in the diff.
Cmux Architecture Rethink ✅ Passed The PR keeps one clear MainActor owner/state machine and only adds test-only synchronization; it removes a flag instead of introducing new timing or side-channel ownership.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR only changes AgentChat prose streaming code and a test; no user-visible NSWindow/NSPanel/WindowGroup or cmuxAuxiliaryWindowIdentifiers changes appear.
Cmux Source Artifacts ✅ Passed Changed paths are source/test/config files and a removed source file; no logs, temp dirs, caches, build outputs, or artifact dirs appear.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Changed production files add no new debug/test-only accessors or seam names; the regression test lives under cmuxTests/ and the Sources changes only remove the flag gate.
Cmux No Ambient Global State ✅ Passed PASS: The PR removes the feature-flag enum and injects hasSubscribers into AgentChatProseStreamer; no new file-scope funcs, globals, or singleton state were introduced.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/always-enable-agent-prose-streaming

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.

@greptile-apps

greptile-apps Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes the CMUXAgentChatProseStreaming UserDefaults feature flag and its AgentChatProseStreamingFlag static-namespace type, making live agent prose previews always active for sessions with an active turn and subscribed chat clients.

  • Flag removal: AgentChatProseStreamingFlag (a caseless-enum static namespace) and its isEnabled dependency in AgentChatProseStreamer are deleted; the userPromptSubmit branch in AgentChatTranscriptService drops the corresponding guard, so streaming begins on every qualifying userPromptSubmit event without an explicit opt-in.
  • Safety gates preserved: hasSubscribers(), the settled-turn flag, and the nil-snapshot early-exit remain, so idle sessions with no listeners are never polled.
  • Regression test: AgentChatProseStreamerTests verifies that a streaming prose frame is emitted even when the legacy defaults key is explicitly false, using a SleepGate actor to drive the poll loop deterministically without timing-based synchronization.

Confidence Score: 5/5

Safe to merge — the change is a straightforward flag removal with all existing idle-session and subscriber guards intact.

The diff removes dead opt-in machinery without touching any of the correctness-critical guards: hasSubscribers(), the settled-turn flag, the record.state != .ended check, and the nil-snapshot early-exit are all preserved. The poll loop and turn lifecycle wiring are unchanged. The new regression test exercises the formerly-gated path with a deterministic actor-based sleep seam, covering the main risk introduced by the removal.

No files require special attention.

Important Files Changed

Filename Overview
Sources/Mobile/AgentChat/AgentChatProseStreamer.swift Removes the isEnabled closure and its guard in emitPreviewIfChanged; retains the hasSubscribers, settled-turn, and snapshot guards so idle sessions are never polled.
Sources/Mobile/AgentChat/AgentChatProseStreamingFlag.swift Deleted. Was a caseless-enum static namespace wrapping a UserDefaults read. Removal is correct.
Sources/Mobile/AgentChat/AgentChatTranscriptService.swift Drops the AgentChatProseStreamingFlag.isEnabled guard from the userPromptSubmit branch; turn lifecycle wiring is otherwise unchanged and all existing safety checks remain.
cmuxTests/AgentChatProseStreamerTests.swift New regression test verifying that a streaming prose frame is emitted even when the legacy UserDefaults key is explicitly false; uses a SleepGate actor to control the poll loop without timing-based synchronization.
cmux.xcodeproj/project.pbxproj Removes AgentChatProseStreamingFlag.swift from the app target and wires AgentChatProseStreamerTests.swift into the test target; no other structural changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant H as Hook Event
    participant TS as AgentChatTranscriptService
    participant PS as AgentChatProseStreamer
    participant S as Surface snapshot
    participant C as Chat Clients

    H->>TS: noteHookEvent(.userPromptSubmit)
    TS->>PS: turnStarted(sessionID, surfaceID, agentKind)
    Note over PS: spawns poll Task at 150ms cadence

    loop Every 150ms while turn active and hasSubscribers
        PS->>S: snapshot(surfaceID)
        S-->>PS: screen rows
        PS->>PS: extract prose
        PS->>C: emit .streamingProse(previewMessage)
    end

    alt Authoritative prose lands in JSONL
        TS->>PS: authoritativeProseArrived(sessionID)
        Note over PS: settled=true, preview cleared
    else stop or sessionEnd hook fires
        H->>TS: noteHookEvent(.stop / .sessionEnd)
        TS->>PS: turnEnded(sessionID)
        Note over PS: Task cancelled, preview cleared
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant H as Hook Event
    participant TS as AgentChatTranscriptService
    participant PS as AgentChatProseStreamer
    participant S as Surface snapshot
    participant C as Chat Clients

    H->>TS: noteHookEvent(.userPromptSubmit)
    TS->>PS: turnStarted(sessionID, surfaceID, agentKind)
    Note over PS: spawns poll Task at 150ms cadence

    loop Every 150ms while turn active and hasSubscribers
        PS->>S: snapshot(surfaceID)
        S-->>PS: screen rows
        PS->>PS: extract prose
        PS->>C: emit .streamingProse(previewMessage)
    end

    alt Authoritative prose lands in JSONL
        TS->>PS: authoritativeProseArrived(sessionID)
        Note over PS: settled=true, preview cleared
    else stop or sessionEnd hook fires
        H->>TS: noteHookEvent(.stop / .sessionEnd)
        TS->>PS: turnEnded(sessionID)
        Note over PS: Task cancelled, preview cleared
    end
Loading

Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

…gent-prose-streaming

# Conflicts:
#	.github/swift-file-length-budget.tsv
@azooz2003-bit
azooz2003-bit merged commit 1e9025f into main Jun 29, 2026
36 checks passed
@azooz2003-bit
azooz2003-bit deleted the codex/always-enable-agent-prose-streaming branch June 29, 2026 23:26

This branch was successfully deployed

1 active deployment
Preview – cmux — 619e30a2 Deployed Jun 29, 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