Skip to content

🤖 fix: allow interrupt during stream startup#1536

Merged
ammario merged 9 commits intomainfrom
fix/interrupt-stream-startup
Jan 13, 2026
Merged

🤖 fix: allow interrupt during stream startup#1536
ammario merged 9 commits intomainfrom
fix/interrupt-stream-startup

Conversation

@ammar-agent
Copy link
Copy Markdown
Collaborator

@ammar-agent ammar-agent commented Jan 9, 2026

What

Allow interrupt (Esc / Ctrl+C) to cancel a message while the UI is still in "Starting..." (i.e., before stream-start).

Why

Previously, interrupts were gated on canInterrupt / StreamManager.isStreaming() (active StreamManager stream). If a send was blocked during init/runtime setup, there was no active stream to stop, so the UI could get stuck in "Starting..." with no way to cancel.

Also, cancelling during this pre-start window could leave an empty assistant placeholder persisted in chat.jsonl.

How

  • Frontend:

    • Treat pendingStreamStartTime as interruptible for keybind interception.
    • Show cancel hint during the starting barrier.
    • Clear pendingStreamStartTime on stream-abort (abort can arrive before stream-start).
    • Command palette interrupt disables auto-retry (matches keybind behavior).
  • Backend:

    • Add a shared linkAbortSignal() helper for consistent abort-signal bridging.
    • Track per-workspace pending stream starts in AIService and allow stopStream() to abort startup work before StreamManager registers a stream.
    • Emit a synthetic stream-abort when cancelling during pending-start so the renderer can exit the "Starting..." UI immediately.
    • Ensure startup aborts don’t leave empty assistant placeholders behind:
      • New HistoryService.deleteMessage() removes the placeholder without truncating subsequent history.
      • Used in both real streaming and mock mode abort paths.
    • Refactor StreamManager.startStream() to use a derived AbortController + structured cleanup (temp dir, unlink abort listener).
    • Guard against a narrow “late abort before processing begins” race so we never emit stream-start after an interrupt without a corresponding abort/end.

Tests

  • make static-check
  • Added/updated tests:
    • tests/ipc/interruptStream.starting.test.ts (requires TEST_INTEGRATION=1 + ANTHROPIC_API_KEY)
    • src/node/services/historyService.test.ts (deleteMessage)
    • src/node/services/mock/mockAiStreamPlayer.test.ts (placeholder cleanup on abort)

Generated with mux • Model: openai:gpt-5.2 • Thinking: xhigh • Cost: $46.85

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: df524048ba

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/aiService.ts
@ammar-agent ammar-agent force-pushed the fix/interrupt-stream-startup branch from df52404 to 22cac8f Compare January 9, 2026 19:40
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Addressed the startup-interrupt race by honoring already-aborted signals before atomic stream creation, plus a unit test that aborts during temp-dir creation to ensure we never emit stream-start / start streaming.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bfe9be15f0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/streamManager.ts Outdated
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Refactored stream startup abort handling to be race-free by construction:

  • Link abort signals via shared helper (linkAbortSignal)
  • startStream now cleans up runtimeTempDir if abort happens before stream registration
  • Added unit coverage asserting the pre-start temp-dir cleanup path

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0fe42157f1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/mock/mockAiStreamPlayer.ts
@ammar-agent ammar-agent force-pushed the fix/interrupt-stream-startup branch from 0fe4215 to 85620d8 Compare January 13, 2026 17:22
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Addressed the mock-mode startup abort edge case:

  • Added HistoryService.deleteMessage(workspaceId, messageId) to remove a single placeholder without truncating subsequent messages.
  • MockAiStreamPlayer.play now deletes the assistant placeholder if abort happens after appendToHistory but before scheduling events.
  • Added a unit test covering abort-after-append cleanup.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e08c9e76c9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/aiService.ts
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Also addressed the real-stream pre-start abort case in AIService:

  • When combinedAbortSignal.aborted triggers the early-return before calling StreamManager, we now delete the assistant placeholder from chat.jsonl via HistoryService.deleteMessage.
  • Added HistoryService.deleteMessage unit tests.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3395287fc8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/streamManager.ts
@ammar-agent
Copy link
Copy Markdown
Collaborator Author

@codex review

Handled the "abort during StreamManager startup" case:

  • After startStream() returns, if the abort signal is set and StreamManager never registered a stream (!isStreaming(workspaceId)), AIService now deletes the assistant placeholder via HistoryService.deleteMessage.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 302889138e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/node/services/streamManager.ts
@ammario ammario merged commit 4b94330 into main Jan 13, 2026
21 checks passed
@ammario ammario deleted the fix/interrupt-stream-startup branch January 13, 2026 19:07
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.

2 participants