Skip to content

feat: add POST /v1/cancel/{command_id} endpoint#1579

Merged
Evanev7 merged 3 commits intoexo-explore:mainfrom
mlpy0:feature/cancel-command-endpoint
Mar 3, 2026
Merged

feat: add POST /v1/cancel/{command_id} endpoint#1579
Evanev7 merged 3 commits intoexo-explore:mainfrom
mlpy0:feature/cancel-command-endpoint

Conversation

@mlpy0
Copy link
Copy Markdown
Contributor

@mlpy0 mlpy0 commented Feb 20, 2026

Summary

  • Adds explicit POST /v1/cancel/{command_id} REST endpoint to cancel in-flight text and image generation commands by ID
  • Previously, cancellation only worked via HTTP disconnect (client closes SSE connection, triggering anyio.get_cancelled_exc_class()). Non-streaming clients and external consumers had no way to cleanly cancel active generation
  • The endpoint looks up the command in active generation queues, sends TaskCancelled to notify workers, and closes the sender stream. Returns 404 (OpenAI error format) if the command is not found or already completed

Changes

File Change
src/exo/shared/types/api.py Add CancelCommandResponse model
src/exo/master/api.py Import, route registration, cancel_command handler
src/exo/master/tests/test_cancel_command.py 3 test cases (404, text cancel, image cancel)
docs/api.md Document new endpoint + update summary table

Design Decisions

  • Uses self._send() (not raw command_sender.send()) — respects API pause state during elections
  • Uses raise HTTPException — feeds into exo's centralized OpenAI-style error handler
  • Returns typed CancelCommandResponse — consistent with CreateInstanceResponse / DeleteInstanceResponse patterns
  • sender.close() is idempotent so concurrent cancel requests for the same command are harmless

Test Plan

  • test_cancel_nonexistent_command_returns_404 — verifies 404 with OpenAI error format
  • test_cancel_active_text_generation — verifies 200, sender.close() called, TaskCancelled sent with correct cancelled_command_id
  • test_cancel_active_image_generation — same verification for image queue
  • basedpyright — 0 new errors
  • ruff check — all checks passed
  • pytest — 3/3 new tests pass, no regressions

Copy link
Copy Markdown
Member

@Evanev7 Evanev7 left a comment

Choose a reason for hiding this comment

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

looks good, just a tidy

Comment thread src/exo/master/api.py Outdated
Comment on lines +569 to +571
async def cancel_command(self, command_id: str) -> CancelCommandResponse:
"""Cancel an active command by closing its stream and notifying workers."""
cid = CommandId(command_id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
async def cancel_command(self, command_id: str) -> CancelCommandResponse:
"""Cancel an active command by closing its stream and notifying workers."""
cid = CommandId(command_id)
async def cancel_command(self, command_id: CommandId) -> CancelCommandResponse:
"""Cancel an active command by closing its stream and notifying workers."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the CommandId's are just strings anyway, we don't need the extra step here

Copy link
Copy Markdown
Member

@Evanev7 Evanev7 left a comment

Choose a reason for hiding this comment

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

cool, test seems a little redundant imo but lgtm

@Evanev7 Evanev7 force-pushed the feature/cancel-command-endpoint branch from 27884fb to 26dfbf2 Compare February 23, 2026 17:35
@mlpy0
Copy link
Copy Markdown
Contributor Author

mlpy0 commented Feb 23, 2026

What did you do @Evanev7

@Evanev7
Copy link
Copy Markdown
Member

Evanev7 commented Feb 24, 2026

just rebased onto latest main to try and get it merged, though we're feature freezing now before our next release

@mlpy0
Copy link
Copy Markdown
Contributor Author

mlpy0 commented Feb 24, 2026

just rebased onto latest main to try and get it merged, though we're feature freezing now before our next release

Sorry for confusion

@Evanev7
Copy link
Copy Markdown
Member

Evanev7 commented Feb 24, 2026

no worries! it's nice to see regular contributors so let me know if i can do anything to keep things clear

@mlpy0
Copy link
Copy Markdown
Contributor Author

mlpy0 commented Feb 26, 2026

no worries! it's nice to see regular contributors so let me know if i can do anything to keep things clear

Thank you 🙏🙏

mlpy0 added 2 commits March 3, 2026 10:28
…cancellation

Previously, generation cancellation only worked via HTTP disconnect (client
closes SSE connection). This adds an explicit REST endpoint so non-streaming
clients and external consumers can cleanly cancel in-flight text and image
generation commands by ID.
@Evanev7 Evanev7 force-pushed the feature/cancel-command-endpoint branch from 3f7c378 to 35b8b1d Compare March 3, 2026 10:28
@Evanev7 Evanev7 enabled auto-merge (squash) March 3, 2026 10:31
@Evanev7 Evanev7 merged commit f0d4ccb into exo-explore:main Mar 3, 2026
3 checks passed
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