feat(channel): add /stop command to cancel in-flight tasks#3891
Merged
theonlyhennygod merged 1 commit intozeroclaw-labs:masterfrom Mar 19, 2026
Merged
feat(channel): add /stop command to cancel in-flight tasks#3891theonlyhennygod merged 1 commit intozeroclaw-labs:masterfrom
theonlyhennygod merged 1 commit intozeroclaw-labs:masterfrom
Conversation
theredspoon
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 18, 2026
Wires Matrix into the auto-cancel-on-new-message mechanism that was already in place for Telegram and Slack. Changes: - MatrixConfig: adds interrupt_on_new_message: bool (serde default false, backward-compatible — existing configs without the field continue to work unchanged) - InterruptOnNewMessageConfig: adds matrix: bool field; enabled_for_channel adds "matrix" => self.matrix arm; runtime init reads the Matrix config flag and passes it into the struct at startup - All test struct literals updated (30 sites) to include matrix: false - Two new schema tests: matrix_config_deserializes_interrupt_on_new_message_true, matrix_config_defaults_interrupt_on_new_message_to_false - MatrixRecordingChannel helper + integration test message_dispatch_interrupts_in_flight_matrix_request_and_preserves_context, mirroring the equivalent Telegram and Slack dispatch tests Depends on zeroclaw-labs#3891 Tests: all new tests pass; pre-existing openai_codex failure is unrelated and present on the base branch.
Adds an explicit /stop slash command that allows users on any non-CLI channel (Matrix, Telegram, Discord, Slack, etc.) to cancel an agent task that is currently running. Changes: - is_stop_command(): new helper that detects /stop (case-insensitive, optional @botName suffix), not gated on channel type - /stop fast path in run_message_dispatch_loop: intercepts /stop before semaphore acquisition so the target task is never replaced in the store; fires CancellationToken on the running task; sends reply via tokio::spawn using the established two-step channel lookup pattern - register_in_flight separated from interrupt_enabled: all non-CLI tasks now enter the in_flight_by_sender store, enabling /stop to reach them; auto-cancel-on-new-message remains gated on interrupt_enabled (Telegram/ Slack only) — this is a deliberate broadening, not a side effect Deferred to follow-up (feat/matrix-interrupt-on-new-message): - interrupt_on_new_message config field for Matrix - thread-aware interruption_scope_key (requires per-channel thread_ts semantics analysis; Slack always sets thread_ts, Matrix only for replies) Supersedes zeroclaw-labs#2855 Tests: 7 new unit tests for is_stop_command; all 4075 tests pass.
2e6e7b4 to
ad8a209
Compare
theredspoon
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 18, 2026
Wires Matrix into the auto-cancel-on-new-message mechanism that was already in place for Telegram and Slack. Changes: - MatrixConfig: adds interrupt_on_new_message: bool (serde default false, backward-compatible — existing configs without the field continue to work unchanged) - InterruptOnNewMessageConfig: adds matrix: bool field; enabled_for_channel adds "matrix" => self.matrix arm; runtime init reads the Matrix config flag and passes it into the struct at startup - All test struct literals updated (30 sites) to include matrix: false - Two new schema tests: matrix_config_deserializes_interrupt_on_new_message_true, matrix_config_defaults_interrupt_on_new_message_to_false - MatrixRecordingChannel helper + integration test message_dispatch_interrupts_in_flight_matrix_request_and_preserves_context, mirroring the equivalent Telegram and Slack dispatch tests Depends on zeroclaw-labs#3891 Tests: all new tests pass; pre-existing openai_codex failure is unrelated and present on the base branch.
theredspoon
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 18, 2026
Wires Matrix into the auto-cancel-on-new-message mechanism that was already in place for Telegram and Slack. Changes: - MatrixConfig: adds interrupt_on_new_message: bool (serde default false, backward-compatible — existing configs without the field continue to work unchanged) - InterruptOnNewMessageConfig: adds matrix: bool field; enabled_for_channel adds "matrix" => self.matrix arm; runtime init reads the Matrix config flag and passes it into the struct at startup - All test struct literals updated (30 sites) to include matrix: false - Two new schema tests: matrix_config_deserializes_interrupt_on_new_message_true, matrix_config_defaults_interrupt_on_new_message_to_false - MatrixRecordingChannel helper + integration test message_dispatch_interrupts_in_flight_matrix_request_and_preserves_context, mirroring the equivalent Telegram and Slack dispatch tests Depends on zeroclaw-labs#3891 Tests: all new tests pass; pre-existing openai_codex failure is unrelated and present on the base branch.
This was referenced Mar 18, 2026
theredspoon
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 18, 2026
The echo_provider() test helper used a shared temp file created via OnceLock. While this avoided recreating the file, it introduced race conditions when parallel tests executed the same script simultaneously: - ETXTBSY (errno 26): 'Text file busy' when spawning the script - EPIPE (errno 32): 'Broken pipe' when the script process died early This commit replaces the shared file with unique per-invocation temp files using thread ID + nanosecond timestamp. Each test now gets its own isolated script, eliminating all parallelization races. Changes: - Remove OnceLock-based shared script - Generate unique script path per echo_provider() call - Add f.sync_all() to ensure file is fully written before chmod - Use 'exec cat' instead of 'cat' to avoid extra shell process Testing: - 5 consecutive runs with --test-threads=20 all pass - Addresses intermittent CI failures in PRs zeroclaw-labs#3891, zeroclaw-labs#3895 Fixes zeroclaw-labs#3902
This was referenced Mar 18, 2026
theredspoon
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 18, 2026
Wires Matrix into the auto-cancel-on-new-message mechanism that was already in place for Telegram and Slack. Changes: - MatrixConfig: adds interrupt_on_new_message: bool (serde default false, backward-compatible — existing configs without the field continue to work unchanged) - InterruptOnNewMessageConfig: adds matrix: bool field; enabled_for_channel adds "matrix" => self.matrix arm; runtime init reads the Matrix config flag and passes it into the struct at startup - All test struct literals updated (30 sites) to include matrix: false - Two new schema tests: matrix_config_deserializes_interrupt_on_new_message_true, matrix_config_defaults_interrupt_on_new_message_to_false - MatrixRecordingChannel helper + integration test message_dispatch_interrupts_in_flight_matrix_request_and_preserves_context, mirroring the equivalent Telegram and Slack dispatch tests Depends on zeroclaw-labs#3891 Tests: all new tests pass; pre-existing openai_codex failure is unrelated and present on the base branch.
theonlyhennygod
approved these changes
Mar 19, 2026
Collaborator
theonlyhennygod
left a comment
There was a problem hiding this comment.
LGTM — cancellation logic is sound, race condition from #2855 eliminated by fast-path before semaphore. Scope key prevents cross-user cancellation. CI green, no conflicts.
theonlyhennygod
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 19, 2026
Keep both the PR's Mattermost interrupt_on_new_message additions and master's new fields (pending_new_sessions, prompt_config, autonomy_level) from the /stop command PR (zeroclaw-labs#3891).
theonlyhennygod
added a commit
to theredspoon/zeroclaw
that referenced
this pull request
Mar 19, 2026
Keep Discord interrupt additions while incorporating master's consolidated test structure and new fields (pending_new_sessions, prompt_config, autonomy_level).
5 tasks
joe2643
added a commit
to joe2643/zeroclaw
that referenced
this pull request
Mar 20, 2026
Resolve 28 merge conflicts from master. Main changes from upstream: - interruption_scope_id for thread-aware cancellation (zeroclaw-labs#4017) - autonomy_level in channel prompts (zeroclaw-labs#3952) - /stop command (zeroclaw-labs#3891) - Various provider and tool fixes All conflicts resolved by keeping both sides: - observe_group + interruption_scope_id in ChannelMessage - All new ChannelRuntimeContext fields in tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
webhive
pushed a commit
to webhive/zeroclaw
that referenced
this pull request
Mar 24, 2026
… scoping (zeroclaw-labs#4017) Add interruption_scope_id to ChannelMessage for thread-aware cancellation. Slack genuine thread replies and Matrix threads get scoped keys, preventing cross-thread cancellation. All other channels preserve existing behavior. Supersedes zeroclaw-labs#3900. Depends on zeroclaw-labs#3891.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
master/stophandler cancelled itself rather than the in-flight task/stopslash command intercepted before semaphore acquisition; separatedregister_in_flightfrominterrupt_enabledso all non-CLI tasks are reachableinterrupt_enabledfor Telegram/Slack only); CLI behavior; any channel implementation fileLabel Snapshot (required)
risk: mediumsize: Schannelchannel: dispatchChange Metadata
featurechannelLinked Issue
Supersede Attribution (required when
Supersedes #is used)#2855 by @theredspoon/stopcommand concept; the race condition in channels: add /reasoning and /stop runtime commands #2855 is the root cause this PR resolves with a different implementation approachCo-authored-bytrailers added for materially incorporated contributors? NoNo, explain why: Same author; no external code carried forwardValidation Evidence (required)
Security Impact (required)
Privacy and Data Hygiene (required)
passCompatibility / Migration
i18n Follow-Through (required when docs or user-facing wording changes)
Human Verification (required)
/stopfires cancellation token for in-flight Slack and Matrix tasks in local testing; "No in-flight task" reply returns correctly when no task is running; CLI channel correctly excluded/stopwith@botnamesuffix; case-insensitive input;/stoparriving after task completes (no crash)Side Effects / Blast Radius (required)
src/channels/mod.rs— all non-CLI channelssender, so Bob's/stopin the same room produces a different key than Alice's in-flight task and cannot cancel itToolLoopCancelledreturn value is observable in logsAgent Collaboration Notes (recommended)
Rollback Plan (required)
git revert <commit>— single commit/stopis always available on non-CLI channels; no opt-out config/stopmessages processed as normal agent input rather than cancellation signalsRisks and Mitigations
/stopfast path runs before semaphore acquisition — ifin_flight_by_senderlookup has a bug, it silently sends "No in-flight task" rather than crashingremoveoperation is atomic under the mutex; the reply is sent viatokio::spawnso it cannot block the dispatch loop