Pressing `ESC` to interrupt the agent now returns the interrupted prompt
to the chat input when the input is empty.
---
When `ESC` interrupts a running agent turn, the prompt that was being
processed is now moved back into the chat input if the input is empty,
so it can be edited and resubmitted. This mirrors the existing
queued-message pop behavior. A non-empty draft in the input is left
untouched so typed text is never clobbered.
Made by [Open
SWE](https://openswe.vercel.app/agents/4708dd80-b2c2-8688-8b1c-ab77cb51228f)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
- Display-only `[image N]`/`[video N]` placeholders no longer appear in
the model-facing message text or LangSmith trace; only the structured
media block is sent.
- Manually typing `[image N]`/`[video N]` text that looks like a
placeholder no longer triggers atomic deletion on backspace — it edits
character by character like ordinary text.
---
When a user attaches an image or video in the Deep Agents Code TUI, a
display-only `[image N]` or `[video N]` placeholder appears in the input
area. The placeholder is purely visual — the actual media travels as a
structured content block alongside the text. Two bugs caused that
display convention to leak into model-facing behavior:
1. **Tracing/model leak:** `create_multimodal_content` copied the raw
input text verbatim into the message text block, so the canonical
`HumanMessage` sent to the model and serialized to LangSmith contained
the display-only `[image 1]` as if the user had typed it. It now strips
only the exact placeholder tokens bound to media actually attached to
that message (via `strip_media_placeholders`), leaving look-alike
literal text intact and requiring no escaping mechanism.
2. **Editing false positive:** `ChatTextArea._find_placeholder_span`
treated any text matching the placeholder regex as an atomic token, so
manually typing `[image 2]` meant a single backspace deleted the whole
token. It now validates each regex match against real state — the media
tracker for image/video placeholders and `_pasted_contents` for paste
placeholders — so only tokens bound to real attachments delete
atomically while typed look-alikes edit character by character.
Disambiguating a display token from a user-typed duplicate of the same
string (e.g. attaching an image that gets `[image 1]`, then the user
also types `[image 1]` in the same message) requires tracking the exact
character span of each display token, not just its text. `ImageData` and
`VideoData` now carry a `placeholder_span` that the tracker updates
through edits via `sync_to_text` (using a diff-based span mapper) and
re-maps at submit time through text transforms — whitespace trimming,
paste expansion, prefix prepending — that shift offsets. `add_media`
also skips placeholder IDs already present in the draft so a literal
`[image 1]` in the text doesn't cause a newly attached image to reuse
the same ID.
Made by [Open
SWE](https://openswe.vercel.app/agents/0fc423a2-7100-74d7-2a83-4ea855c9d4bb)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Removes four small helper functions/methods that are defined but never
called:
- `_get_available_sandbox_types` (`integrations/sandbox_factory.py`)
- `MCPServerInfo.is_loaded` (`mcp_tools.py`)
- `MessageStore.get_message_at_index` (`widgets/message_store.py`)
- `InputState.get_media` (`input.py`)
How we know it's dead: each one has exactly one match in the whole
package, tests, and examples — its own definition. Their sibling helpers
that are actually used (e.g. `needs_attention`,
`get_images`/`get_videos`) are left in place.
Made by [Open SWE](https://openswe.vercel.app)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Dependency floors are refreshed across the monorepo for newer
LangChain/LangSmith releases, provider integrations, pytest tooling,
`ruff`, and `ty`. The code changes are the compatibility work needed for
those newer lint and type checks, with small structural cleanups where
the tools needed clearer narrowing or less complex functions.
## Changes
- Raised runtime and test dependency minimums across SDK, CLI, Code,
ACP, evals, examples, and partner packages, including updated
LangChain/LangSmith/provider pins and current lint/test tooling
baselines.
- Reworked backend factory typing around `BACKEND_TYPES` with
`_resolve_backend`, widened file transfer error fields to support
backend-specific strings, and updated filesystem/summarization
middleware to use the shared resolver.
- Tightened `deepagents-code` typing for middleware stacks, MCP tool
filtering, update checks, and Textual compatibility patches, replacing
stale suppressions with `ty`-specific ignores where runtime behavior is
intentionally narrower than static types.
- Split large CLI command handlers into focused helpers such as
`_dispatch_command`, `_execute_agents_command`, and the MCP server
subcommand helpers while preserving existing command behavior.
- Updated Harbor LangSmith sandbox handling to rely on explicit
`NetworkPolicy` and `capabilities` instead of legacy property overrides,
with tests adjusted around the new capability checks.
- Applied lint/format/type-check cleanups across tests and examples so
the staged code passes the refreshed tooling expectations.
Holding a key in the chat input floods the text area with a long run of
characters, which the dropped-path detector speculatively resolves
against the cwd. The resulting path component exceeds the filesystem
name limit, so `os.stat` raises `OSError [Errno 63] ENAMETOOLONG` — and
on Python ≤3.13 `pathlib` lets it propagate out of
`.exists()`/`.is_file()`, crashing the Textual app. The resolution
helpers wrapped `.resolve()` in a `try/except` but left the subsequent
filesystem probes unguarded.