()
| 2827 | this.setTurnPhase(TurnPhase.PREPARING); |
| 2828 | |
| 2829 | const startPreparedStream = async (): Promise<Result<void, SendMessageError>> => { |
| 2830 | try { |
| 2831 | if (preparedTurnAbortController.signal.aborted) { |
| 2832 | return Ok(undefined); |
| 2833 | } |
| 2834 | // If this is a compaction request, terminate background processes first. |
| 2835 | // They won't be included in the summary, so continuing with orphaned processes would be confusing. |
| 2836 | const isCompactionStreamRequest = isCompactionRequest || autoCompactionMessage !== null; |
| 2837 | if (isCompactionStreamRequest && !this.keepBackgroundProcesses) { |
| 2838 | await this.backgroundProcessManager.cleanup(this.workspaceId); |
| 2839 | |
| 2840 | if (this.disposed) { |
| 2841 | return Ok(undefined); |
| 2842 | } |
| 2843 | } |
| 2844 | |
| 2845 | // Note: Follow-up content for compaction is now stored on the summary message |
| 2846 | // and dispatched via dispatchPendingFollowUp() after compaction completes. |
| 2847 | // This provides crash safety - the follow-up survives app restarts. |
| 2848 | |
| 2849 | if (this.disposed || preparedTurnAbortController.signal.aborted) { |
| 2850 | return Ok(undefined); |
| 2851 | } |
| 2852 | |
| 2853 | // Turn-phase transitions for success are driven by stream events. |
| 2854 | return await this.streamWithHistory( |
| 2855 | modelForStream, |
| 2856 | optionsForStream, |
| 2857 | undefined, |
| 2858 | undefined, |
| 2859 | agentInitiated, |
| 2860 | preparedTurnAbortController.signal, |
| 2861 | goalKind |
| 2862 | ); |
| 2863 | } finally { |
| 2864 | // Success should advance via stream events; if startup never emitted any, don't leave the |
| 2865 | // session stuck in PREPARING. Guard by controller identity so an aborted startup cannot |
| 2866 | // mark the replacement edit's new PREPARING turn idle when it unwinds later. |
| 2867 | if (this.activePreparedTurnAbortController === preparedTurnAbortController) { |
| 2868 | this.activePreparedTurnAbortController = null; |
| 2869 | if (this.turnPhase === TurnPhase.PREPARING) { |
| 2870 | this.setTurnPhase(TurnPhase.IDLE); |
| 2871 | } |
| 2872 | } |
| 2873 | } |
| 2874 | }; |
| 2875 | |
| 2876 | if (editMessageId || internal?.startStreamInBackground === true) { |
| 2877 | // The user turn is already persisted + emitted above. Edits and backend |
nothing calls this directly
no test coverage detected