Skip to content

feat(shell): add configurable key sequence callbacks for raw PTY mode#401

Draft
bassmanitram wants to merge 2 commits intostrands-agents:mainfrom
bassmanitram:feature/raw-callbacks
Draft

feat(shell): add configurable key sequence callbacks for raw PTY mode#401
bassmanitram wants to merge 2 commits intostrands-agents:mainfrom
bassmanitram:feature/raw-callbacks

Conversation

@bassmanitram
Copy link

@bassmanitram bassmanitram commented Feb 14, 2026

Description

This PR adds support for configurable key sequence detection during interactive PTY execution. When the shell tool runs in raw mode, callers can now register callbacks for specific key sequences (e.g., Ctrl+C, Alt+C) that will be invoked when those sequences are detected in stdin.

Motivation

When the shell tool executes commands interactively with PTY in raw mode, the terminal is owned by the subprocess. This means the calling application cannot intercept keypresses through normal means. This PR provides a mechanism for callers to register key sequence callbacks via tool_context.invocation_state, enabling features like cancellation to work even during raw PTY execution.

Implementation

New KeySequenceMatcher class:

  • Detects configured byte sequences in stdin during raw PTY mode
  • Uses 50ms timeout to disambiguate between standalone keypresses (e.g., Escape) and multi-character sequences (e.g., Alt+C which sends Escape followed by 'c')
  • Prefers longer sequences over shorter ones when both could match
  • Optimized for minimal allocations in the hot path (uses __slots__, pre-computed lookups, bytearray buffer)

API:

# Pass via tool_context.invocation_state
key_sequence_callbacks = {
    b'\x03': cancel_callback,    # Ctrl+C
    b'\x1bc': cancel_callback,   # Alt+C (Escape + c)
}

Changes

  • src/strands_tools/shell.py: Added KeySequenceMatcher class and integrated key sequence detection into PTY execution loop
  • tests/test_shell_key_sequences.py: 27 new tests covering matcher behavior, timeout handling, and integration

Backward Compatibility

Fully backward compatible. When no key_sequence_callbacks are provided, behavior is identical to before.

Documentation PR

Type of Change

Other (please describe):

Non-breaking enhancement

Testing

  • All 27 new tests pass

  • All 31 existing shell tests pass

  • Tested key scenarios:

    • Single-byte sequences (Ctrl+C)
    • Multi-byte sequences (Alt+C)
    • Timeout disambiguation (Escape alone vs Escape+c)
    • Longest-match preference when sequences overlap
  • I ran hatch run prepare
    Well, no, 'cause there appears to be something wrong upstream - but I did run ruff locally.

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Add KeySequenceMatcher class that detects configured key sequences during
interactive PTY execution, with 50ms timeout to disambiguate between
standalone keypresses (like Escape) and multi-character sequences (like Alt+C).

Key features:
- Pass key_sequence_callbacks via tool_context.invocation_state
- Maps byte sequences (e.g., b'\\x03' for Ctrl+C) to callables
- Longer sequences have priority over shorter ones
- Optimized for minimal allocations in hot path

This enables callers to receive callbacks for specific key sequences
even when the terminal is in raw mode and normal keyboard handling
is unavailable.
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