The startup splash banner now uses an ASCII-safe border when ASCII
charset mode is active.
---
The splash banner kept Textual's rounded Unicode border even after its
content glyphs switched to ASCII. Apply the same charset-aware border
selection already used by the chat input and cover it with a focused
mounted-widget regression test.
Made by [Open
SWE](https://openswe.vercel.app/agents/7e5df730-093d-507b-b255-30a35d856a55)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.
For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).
---
_Release notes preview: keep this section in sync with the package
`CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`,
not this PR description — keep them aligned anyway so the PR stays an
accurate historical record for reviewers and anyone returning later._
---
##
[0.7.10](https://github.com/langchain-ai/deepagents/compare/deepagents==0.7.9...deepagents==0.7.10)
(2026-08-28)
### Bug Fixes
- Prevent local shell commands from stealing TUI input
([#5873](https://github.com/langchain-ai/deepagents/issues/5873))
- Surface sandbox glob failures instead of reporting no matches
([#5566](https://github.com/langchain-ai/deepagents/issues/5566))
_End release notes preview._
---
> [!NOTE]
> A **community contributors** list and a **Special thanks** section
(crediting the users who filed the issues this release's PRs closed) are
appended to the GitHub release notes automatically at publish time (see
[Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 3).
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com>
The commit hash in `dcode doctor` now links directly to that commit on
GitHub in terminals that support hyperlinks.
---
Render the resolved commit hash with Rich's terminal hyperlink support
while preserving the existing visible and JSON output. Unknown or
invalid hash values remain plain text.
Made by [Open
SWE](https://openswe.vercel.app/agents/25553271-f2f1-5cd8-b89e-1c1ff4e31786)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Launching another `dcode` session no longer makes editors report that
`config.toml` changed when the persisted value was already current.
---
Startup persists the recent agent through `_save_toml_field`, which
previously serialized and atomically replaced the config file on every
call. Even with identical bytes, that replacement changed the file
identity and triggered external-change warnings in editors such as nano.
Return successfully under the existing config lock when the stored
scalar already has the same value and type. Actual changes retain the
crash-safe atomic replacement path, and all saves still refresh cached
config views so external edits become visible in-process.
Tests: `NO_COLOR=1 make format`; `NO_COLOR=1 make lint`; focused
`test_model_config.py` persistence and resolver tests (48 passed).
Made by [Open
SWE](https://openswe.vercel.app/agents/91004cf2-27d6-54fc-a961-3acb33d205cf)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Skill invocations now include `ls_skill_name` in LangSmith trace
metadata across interactive and headless dcode runs.
---
The closed#4826 parsed the persisted `__skill` message envelope
independently in each stream adapter. This keeps the change within
`libs/code` while making trace attribution an explicit value on
`SkillInvocationEnvelope`, propagated through both execution paths into
the centralized `build_stream_config` metadata builder.
Made by [Open
SWE](https://openswe.vercel.app/agents/e3e3c743-7dfd-50b9-8683-268d3ff1be1a)
> [!CAUTION]
> Merging this PR will automatically publish to **PyPI** and create a
**GitHub release**.
For the full release process, see
[`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md).
---
_Release notes preview: keep this section in sync with the package
`CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`,
not this PR description — keep them aligned anyway so the PR stays an
accurate historical record for reviewers and anyone returning later._
---
##
[0.0.11](https://github.com/langchain-ai/deepagents/compare/deepagents-acp==0.0.10...deepagents-acp==0.0.11)
(2026-08-27)
### Features
- Stream visible reasoning as thought chunks.
([#5880](https://github.com/langchain-ai/deepagents/issues/5880))
_End release notes preview._
---
> [!NOTE]
> A **community contributors** list and a **Special thanks** section
(crediting the users who filed the issues this release's PRs closed) are
appended to the GitHub release notes automatically at publish time (see
[Release
Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline),
step 3).
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com>
Raises the LangChain-ecosystem dependency lower bounds (`langchain*`,
`langgraph*`, `langsmith*`, `deepagents*`) for `all` to the latest
compatible stable PyPI release, and regenerates every affected
`uv.lock`. Upper bounds, extras, and markers are preserved; exact `==`
pins are left alone.
Raised 2 minimum(s):
| Manifest | Dependency | Change |
|---|---|---|
| `libs/code/pyproject.toml` | `langgraph-sdk` |
`langgraph-sdk>=0.4.3,<1.0.0` → `langgraph-sdk>=0.4.4,<1.0.0` |
| `libs/code/pyproject.toml` | `langchain-fireworks` |
`langchain-fireworks>=1.6.0,<2.0.0` →
`langchain-fireworks>=1.6.1,<2.0.0` |
Opened automatically by
[`raise_langchain_minimums.yml`](https://github.com/langchain-ai/deepagents/actions/workflows/raise_langchain_minimums.yml),
manually dispatched by @mdrxy.
Review the raised bounds against any compatibility notes in the manifest
comments before merging.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
dcode no longer imposes its own graph step budget, and the configured
budget now actually reaches the graph.
---
## Dropping the product default
dcode replaced the graph's built-in limit with `2000` on every launch.
The unset path now binds nothing, so the runtime's own budget stands.
`--recursion-limit`, `DEEPAGENTS_CODE_RECURSION_LIMIT`,
`[runtime].recursion_limit`, and managed configuration keep their
existing precedence and bounds.
The fallback is the `langgraph dev` server's `10011`
(`langgraph_api/utils/config.py`), not LangGraph core's `10007` and not
the Deep Agents SDK's `9999` — both are shadowed on the path dcode
actually runs. `dcode config` reports it rather than showing an empty
default:
```
runtime.recursion_limit 10011 default
```
## Making the setting take effect
The graph executes inside the `langgraph dev` server, which stamps its
own `recursion_limit` onto every run config it builds. `merge_configs`
only defers to the value bound onto the compiled graph when the incoming
one equals LangGraph core's default:
```python
elif key == "recursion_limit":
if config["recursion_limit"] != DEFAULT_RECURSION_LIMIT: # 10007
base["recursion_limit"] = config["recursion_limit"]
```
`10011 != 10007`, so the server value overrode the binding
`create_cli_agent` applied. Both the TUI and headless runs reach the
graph over `RemoteGraph`, so neither honored a configured limit — the
old hardcoded `2000` was discarded the same way.
`recursion_limit` is in `langgraph_api`'s `CONFIG_KEYS`, so a
client-supplied value replaces the server default. `build_stream_config`
now carries the resolved limit, and omits the key when nothing is
configured:
```
unconfigured -> key absent (server default 10011 stands)
env=3000 -> recursion_limit=3000
```
## Hardening
- `LANGGRAPH_DEFAULT_RECURSION_LIMIT` is denied from project `.env`
files. It sets the upstream default, so a cloned repo could otherwise
bypass the bounded resolver.
- `RECURSION_LIMIT_FLOOR = 25` keeps its rationale in the docstring,
including that rejection *raises* the effective budget: a `config.toml`
value of `20` is discarded and the run falls through to `10011`. Use the
CLI flag, which is exempt and accepts `>= 1`, to bound a run below the
floor.
Made by [Open
SWE](https://openswe.vercel.app/agents/16dfbef1-efaa-512f-9a2d-438912145ead)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Related #5556
Hosts extension tools, middleware, and virtual filesystem backends in
the agent runtime.
---
Layer 3 of 4. Static registrations are applied during graph
construction, late tools remain callable, and late graph-bound
registrations signal that a restart is required. Backend routes are
validated against internal and sandbox boundaries, shell execution
remains on the default backend, and the persistent server lifespan owns
teardown and a loopback-only provenance endpoint. User-facing trust and
inspection UX are deliberately excluded.
## Stack
1. [#5631 — API, registry, and
discovery](https://github.com/langchain-ai/deepagents/pull/5631)
2. [#5632 — configuration, trust, and
loading](https://github.com/langchain-ai/deepagents/pull/5632)
3. [#5633 — agent hosting and
lifecycle](https://github.com/langchain-ai/deepagents/pull/5633)
4. [#5634 — trust and inspection
UX](https://github.com/langchain-ai/deepagents/pull/5634)
Use `Ctrl+G` to open the prompt in an external editor and `Ctrl+T` to
toggle the subagent panel.
---
This aligns external editing with Codex and Claude Code conventions
while preserving `Shift+Tab` for approval-mode cycling. Help text,
contextual hints, startup tips, and focused TUI coverage now reflect the
new bindings.
Made by [Open
SWE](https://openswe.vercel.app/agents/1a571726-3990-588f-a7f7-3dfcc5557092)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Related: #4329
Git commands run through dcode's `execute` tool now fail with an
explicit terminal-prompts-disabled message when credentials are
unavailable.
---
Stacked on #5873.
Starting local shell subprocesses in a new session prevents them from
stealing the Textual TUI's keyboard input, but Git can then surface a
cryptic `/dev/tty` error when it tries to prompt for credentials. Set
`GIT_TERMINAL_PROMPT=0` in dcode's curated local shell environment as
defense in depth so Git skips the prompt attempt and reports the cause
directly.
This is intentionally scoped to dcode's agent `execute` environment. It
does not alter the general SDK backend, remote sandboxes, or the user's
parent environment, and dcode overrides an inherited value to keep
non-interactive execution reliable.
Made by [Open
SWE](https://openswe.vercel.app/agents/000f0c29-ded9-5a80-abaa-daa77e57f972)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
## Problem
Four tests in `TestDispatchModelSwitch`
(`libs/code/tests/unit_tests/test_app.py`) write the process-global
`runtime_state` directly, so `_dispatch_model_switch` sees a model spec
worth warning about, and never restore it:
```python
runtime_state.model_provider = "anthropic"
runtime_state.model_name = "claude-opus-4-5"
```
`test_app.py:24617-24618`, `:24637-24638`, `:24694-24695`,
`:24713-24714`
Everywhere else in that module patches
`deepagents_code.config.runtime_state`, so these are the only writes
that outlive their test.
The leak is not inert. `configurable_model._model_spec_from_model`
prefers `runtime_state` over the model's own `ls_provider` whenever the
names match:
```python
if settings_provider and settings_model and model_name == settings_model:
return f"{settings_provider}:{settings_model}"
```
So any later test whose model happens to be named `claude-opus-4-5`
silently resolves to the leaked `anthropic` provider.
`test_configurable_model.py::TestModelParams::test_reasoning_effort_reaches_model_settings`
is exactly that test — its mock model returns `ls_provider: "openai"`
and it asserts the checkpointed spec is `openai:claude-opus-4-5`.
## Reproduction
```
pytest "tests/unit_tests/test_app.py::TestDispatchModelSwitch" \
"tests/unit_tests/test_configurable_model.py::TestModelParams::test_reasoning_effort_reaches_model_settings" \
-q -p no:randomly
```
**Before:**
```
E AssertionError: assert {'_model_spec...params': None} == {'_model_spec...params': None}
E {'_model_spec': 'anthropic:claude-opus-4-5'} != {'_model_spec': 'openai:claude-opus-4-5'}
FAILED tests/unit_tests/test_configurable_model.py::TestModelParams::test_reasoning_effort_reaches_model_settings
1 failed, 11 passed in 1.72s
```
**After:**
```
12 passed in 8.65s
```
`pytest-randomly` shuffles file order by default, so this fires only
when those two files land in that order — which is why it reads as an
intermittent flake rather than a consistent failure. It is deterministic
under `-p no:randomly`, where alphabetical order puts `test_app.py`
first.
## Fix
A class-scoped autouse fixture that saves and restores the two fields,
matching the pattern `test_config.py:1638-1655` and
`test_model_switch.py:68-84` already use for the same global.
Fixes#5796
Thread timestamps in `dcode threads list` and the thread selector now
render on Windows instead of appearing blank.
---
`sessions.format_timestamp` built the thread list's absolute timestamps
with `strftime("%b %d, %-I:%M%p")`. The `%-I` flag is a glibc/BSD
extension that Microsoft's CRT rejects as an invalid formatting code, so
CPython raised `ValueError` and the helper's `except (ValueError,
TypeError)` swallowed it and returned an empty string. On
`windows-latest` runners across Python 3.12, 3.13 and 3.14 the call
returns `''`; on Linux and macOS it returns `'dec 30, 9:18pm'`. Windows
users running `dcode threads list --no-relative`, or with the thread
selector's relative-time switch off, saw the Created and Updated columns
blank with nothing to explain why.
The hour is now derived with `dt.hour % 12 or 12` and interpolated,
which is what `formatting.format_message_timestamp` already does for the
same 12-hour clock. Substituting another flag would not work: Windows
rejects `%-I` and honours `%#I`, glibc honours `%-I` and ignores `%#I`,
and BSD libc emits `%#I` literally, so the hour has to be computed
rather than formatted. Nothing else changes — comparing the old and new
expressions across every hour of a leap year plus every minute of one
day (8844 timestamps) gives byte-identical output, which the Linux and
macOS runner legs confirm. The two redundant `.replace("am", "am")` /
`.replace("pm", "pm")` calls went away with the rewritten expression;
they were no-ops after `.lower()`. `format_relative_timestamp` and the
parse-failure path are untouched.
The new test stands in a `datetime` subclass whose `strftime` rejects
`%-`, mirroring how `test_non_interactive.py` stands in a `cp1252`
`TextIOWrapper` to cover the legacy-console fix; it fails on `main` and
passes here, so `test-code` gains coverage without needing a Windows
leg.
---------
Co-authored-by: Mason Daugherty <mason@langchain.dev>
Co-authored-by: Mason Daugherty <github@mdrxy.com>
Raises the LangChain-ecosystem dependency lower bounds (`langchain*`,
`langgraph*`, `langsmith*`, `deepagents*`) for `all` to the latest
compatible stable PyPI release, and regenerates every affected
`uv.lock`. Upper bounds, extras, and markers are preserved; exact `==`
pins are left alone.
Raised 2 minimum(s):
| Manifest | Dependency | Change |
|---|---|---|
| `libs/code/pyproject.toml` | `langchain-anthropic` |
`langchain-anthropic>=1.6.1,<2.0.0` →
`langchain-anthropic>=1.7.0,<2.0.0` |
| `libs/deepagents/pyproject.toml` | `langchain-anthropic` |
`langchain-anthropic>=1.6.1,<2.0.0` →
`langchain-anthropic>=1.7.0,<2.0.0` |
Opened automatically by
[`raise_langchain_minimums.yml`](https://github.com/langchain-ai/deepagents/actions/workflows/raise_langchain_minimums.yml),
manually dispatched by @mdrxy.
Review the raised bounds against any compatibility notes in the manifest
comments before merging.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The current model name in the `/model` picker header can now be clicked
to copy its canonical model spec.
---
The picker marks only the current-model span as copyable and reuses the
existing clipboard fallback and notification flow. Custom picker titles
remain unchanged. A focused Textual interaction test covers the click
behavior.
Made by [Open
SWE](https://openswe.vercel.app/agents/b7314bfc-f358-5613-abbe-605583ea26da)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: mdrxy <mdrxy@users.noreply.github.com>
With runtime state, paths, resolver-backed options, and credentials
owned by focused components, `Settings` no longer has a responsibility.
This removes the dataclass, its singleton and module fallback machinery,
and the remaining `settings_field` support. Typed lazy proxies for
credentials, runtime state, and the console preserve deferred startup
behavior while tests target the new owners directly.
Part 5 of 6 in the [`Settings` dissolution
stack](https://github.com/langchain-ai/deepagents/pull/5859?stack=5864).
Credentials and environment-derived project context have a reload
lifecycle separate from tiered configuration. `Credentials` now owns API
keys, provider/project metadata, capability checks, and `project_root`,
including preview and reload behavior. Reloads construct a replacement
before swapping it into use, preserve policy on failure, mask key
changes, retain the bootstrap-owned user project, and keep
`LANGSMITH_PROJECT` synchronized.
Part 4 of 6 in the [`Settings` dissolution
stack](https://github.com/langchain-ai/deepagents/pull/5859?stack=5864).
Interpreter, shell, and extra-skills options are already owned by the
configuration manifest, so retaining copies on `Settings` duplicates
resolver state. Consumers now resolve shell and skills options at use
time, while `InterpreterConfig` provides a coherent snapshot for
middleware construction. The server process builds its own snapshot from
its resolver, and the obsolete `settings_field` mappings are removed.
Part 3 of 6 in the [`Settings` dissolution
stack](https://github.com/langchain-ai/deepagents/pull/5859?stack=5864).
The directory helpers on `Settings` derive paths but do not depend on
configuration state, which makes their current ownership misleading.
This moves them to `_paths` as free functions, passes `project_root`
explicitly where needed, and preserves the existing path resolution and
directory creation behavior.
Part 2 of 6 in the [`Settings` dissolution
stack](https://github.com/langchain-ai/deepagents/pull/5859?stack=5864).
`Settings` currently owns model metadata that is only known after model
creation and changes at runtime, so treating it as configuration
obscures its ownership. This extracts those fields into a small mutable
`RuntimeState`, preserves lazy initialization, and routes
`ModelResult.apply_to_runtime_state()` and readers through that state
without changing model selection behavior.
Part 1 of 6 in the [`Settings` dissolution
stack](https://github.com/langchain-ai/deepagents/pull/5859?stack=5864).
The large-context model-switch warning now points users to `/offload`,
the command that summarizes older messages and frees context.
---
The modal still referenced the obsolete `/compact` spelling. Update the
copy and cover the current command in the existing modal test.
Made by [Open
SWE](https://openswe.vercel.app/agents/af86a6b6-3c48-56e5-ab94-6d4e70672aa2)
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Raises the LangChain-ecosystem dependency lower bounds (`langchain*`,
`langgraph*`, `langsmith*`, `deepagents*`) for `all` to the latest
compatible stable PyPI release, and regenerates every affected
`uv.lock`. Upper bounds, extras, and markers are preserved; exact `==`
pins are left alone.
Raised 2 minimum(s):
| Manifest | Dependency | Change |
|---|---|---|
| `libs/acp/pyproject.toml` | `langchain-baseten` |
`langchain-baseten>=0.2.3` → `langchain-baseten>=0.2.4` |
| `libs/partners/quickjs/pyproject.toml` | `langchain` |
`langchain>=1.3.16,<2.0.0` → `langchain>=1.3.17,<2.0.0` |
Opened automatically by
[`raise_langchain_minimums.yml`](https://github.com/langchain-ai/deepagents/actions/workflows/raise_langchain_minimums.yml)
on its daily schedule.
Review the raised bounds against any compatibility notes in the manifest
comments before merging.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Bare `dcode mcp login` now lists configured OAuth MCP servers that do
not have stored credentials.
---
This makes the login command useful without requiring users to already
know a server name. Discovery uses the existing trust-gated merged
configuration and reads only local URL-scoped token state; `dcode mcp
login <server>` keeps its current behavior.
Made by [Open
SWE](https://openswe.vercel.app/agents/71c1477d-fbb0-5259-b93e-8eea055a8d81)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
When auto-mode policy-denies a tool call (e.g. the credential-access
policy blocking `onepassword_authenticate`), the TUI logged a
false-positive warning:
```
WARNING deepagents_code.tui.textual_adapter ToolMessage tool_call_id=<id> not in _current_tool_messages; no correlated tool.use, sending empty tool_args
```
The warning exists to flag degraded audit fidelity — a tool that
*executed* but whose streamed args never parsed, so no `tool.use` fired
and the audit hook sees a `tool.result` with empty args. A policy denial
instead synthesizes an *error* `ToolMessage` without the tool ever
executing, so no widget mounts — an expected, routine path, not degraded
fidelity. The warning added noise to debug logs and risked training
users to ignore it.
The fix marks the denial at the source rather than string-matching in
the adapter:
- `auto_mode.py`: the synthesized denial `ToolMessage` is stamped with
`additional_kwargs={"deepagents_code_auto_denied": True}` (a new
`AUTO_DENIED_METADATA_KEY` constant). `additional_kwargs` survives the
messages-mode stream, verified by a probe.
- `textual_adapter.py`: the uncorrelated-result branch checks the marker
and skips the warning when present. The `tool.result` hook still fires
exactly as before; only the log line is suppressed. The real warning
case — a tool that executed with unparsed args — still warns.
Manual HITL rejections were checked and do not need the same treatment:
they are synthesized in the base middleware's `after_model` state update
(not streamed) and are consumed through the adapter's
interrupt-resolution path (`completed_tool_result_ids`), so they never
reach the uncorrelated warning branch.
Raises the LangChain-ecosystem dependency lower bounds (`langchain*`,
`langgraph*`, `langsmith*`, `deepagents*`) for `deepagents` to the
latest compatible stable PyPI release, and regenerates every affected
`uv.lock`. Upper bounds, extras, and markers are preserved; exact `==`
pins are left alone.
Raised 2 minimum(s):
| Manifest | Dependency | Change |
|---|---|---|
| `libs/deepagents/pyproject.toml` | `langchain-google-genai` |
`langchain-google-genai>=4.3.5,<5.0.0` →
`langchain-google-genai>=4.3.6,<5.0.0` |
| `libs/deepagents/pyproject.toml` | `langchain-aws` |
`langchain-aws>=1.7.3,<2.0.0` → `langchain-aws>=1.7.4,<2.0.0` |
Opened automatically by
[`raise_langchain_minimums.yml`](https://github.com/langchain-ai/deepagents/actions/workflows/raise_langchain_minimums.yml).
Review the raised bounds against any compatibility notes in the manifest
comments before merging.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
MCP login success messages no longer expose the local token file
location unless debug mode is enabled.
---
The token path is useful for troubleshooting but unnecessarily reveals
local filesystem details in normal output. The success message now
includes it only when `DEEPAGENTS_CODE_DEBUG` is truthy, with focused
coverage for both modes.
Made by [Open
SWE](https://openswe.vercel.app/agents/9d7c98e8-f252-5de1-acfa-08b78bf8eb70)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Editable installs now show their source path in the Debug Console
instead of the startup splash.
---
The splash keeps its compact `(local)` indicator, while the Debug
Console adds a copyable `Install path` field when editable-install
metadata provides a path.
Made by [Open
SWE](https://openswe.vercel.app/agents/793b5cdb-47ee-5c88-9b92-d5f036469dc3)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
`dcode update` now reports when a newly published release is still
propagating instead of falsely claiming that version was installed.
---
The motivating case was the `0.1.63` release: PyPI’s release metadata
advertised `0.1.63`, so `dcode update` offered it, but the first `uv
tool install -U` resolution only upgraded `click`, `langchain-protocol`,
and `openai` while leaving `deepagents-code==0.1.62`. Because uv exited
successfully, dcode printed `Updated to v0.1.63`; the next launch
correctly detected `0.1.62`, repeated the update, and then installed
`0.1.63`.
`perform_upgrade` already reads the uv tool environment after
installation. This change compares that readback with the update target
and returns a concise propagation message when uv resolved an older app
version. The check is uv-only: Homebrew replaces and relinks a Cellar
keg, so the running process’s prefix can still report the old version
after a successful formula upgrade.
Tests cover the stale uv resolution, newer-version and indeterminate
readbacks, and the Homebrew relink case.
<details><summary>Test plan</summary>
- `make -C libs/code format`
- `make -C libs/code lint`
- `uv run --directory libs/code pytest -q --disable-warnings
tests/unit_tests/test_update_check.py -k 'perform_upgrade'
</details>
Made by [Open
SWE](https://openswe.vercel.app/agents/459d7ee6-a016-5fc2-8e03-3d8b2354d23a)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Deep Agents Code now retries transient model request failures
automatically. If a request fails because of a dropped connection, a
rate limit, or a provider server error, dcode waits and tries again
instead of failing the turn. This covers the main agent, subagents,
goal-criteria checks, conversation compaction, auto-mode classification,
and rubric grading even when the grader connection drops mid-response.
How retrying works:
- Retries happen at the individual model call, not the whole turn, so
tool calls that already completed are never replayed.
- If a response started streaming to your terminal before the failure,
that attempt is not retried — this prevents duplicated output.
Rubric-grader messages are the narrow exception: both clients filter
that nested stream, so the failed grader model call can retry without
duplicating visible output.
- You can see retry progress in the terminal, both interactively and in
headless mode.
- Rate-limit responses that carry a valid `Retry-After` header wait as
directed, up to 60 seconds. Other failures use an exponential backoff
(starting at 0.2s, doubling up to a 10s cap, with jitter).
- Permanent failures — authentication errors, permission denials,
invalid requests, context overflow — fail immediately without burning
retries.
- Auto-mode classification runs under a deadline, so its total retry
wait is capped to fit inside it; a rate-limited classifier surfaces the
provider error rather than stalling.
Controlling retries:
- `--max-retries N` (or `[retries] max_retries = N` in `config.toml`)
sets how many retries follow the initial request. The default is 5; `0`
disables retries entirely. Set `[retries.<provider>]` to override per
provider.
- These settings now control dcode's own retry loop. Previously they set
the provider SDK's retry count; that loop is disabled so the two don't
multiply. If dcode can't identify the provider's retry control, it warns
you, since the provider may still be retrying underneath.
- Retries outside the main agent loop (compaction summaries,
classifiers, rubric grading) apply to models dcode builds itself. A
model you supply directly gets the default budget of 5, with a warning
if its own SDK retry loop is also still active.
Rubric grading retains its earlier mid-response reliability. Grader
messages stream under a nested namespace that both interactive and
headless clients filter, and unidentified nested messages are excluded
from hook transcripts. Only the grader's retry middleware marks that
stream as hidden, allowing dropped reads and truncated bodies to retry
the failed model node without replaying completed verification tools.
Main-agent and other visible streams keep the duplicate-output guard.
---
<details>
<summary>Test plan</summary>
- Focused model-retry, rubric-grader, client-rendering, transcript, and
agent-wiring tests: 152 passed
- Ruff checks for all touched files
- `ty` checks for all touched files
- Pre-commit hooks
</details>
Made by [Open
SWE](https://openswe.vercel.app/agents/7fe4aaa6-4f25-5c78-b472-91ae81e8c1b5)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Fixes#5843
---
The `deepagents-code` Python 3.12 unit-test leg failed three
`test_diff.py` assertions that expected the Unicode line-continuation
glyph `…` but rendered the ASCII fallback `.`. The same tests passed on
3.13 and 3.14, and the PR that hit the failure did not touch the diff
renderer.
The diff widget reads `get_glyphs()`, which caches the detected charset
mode in a process-wide module variable. Several tests in
`test_charset.py` patch `UI_CHARSET_MODE` to force ASCII or Unicode and
reset that cache in `setup_method` — before each test — but never reset
it afterward. `TestIsAsciiMode::test_true_in_ascii_mode` therefore
leaves the cache pinned to ASCII. Whether any later test in the same
pytest-xdist worker inherits that state depends entirely on how tests
are distributed across workers, which is why the failure surfaced only
on the 3.12 leg and disappeared under other run orders.
Two changes make the intended behavior deterministic across the matrix:
- `test_charset.py` now uses an autouse fixture that resets the glyph
cache both before and after each test, so a forced charset cannot leak
into unrelated tests.
- `test_diff.py` now sets `UI_CHARSET_MODE=unicode` and resets the cache
around every test, so the rendering expectations no longer depend on
ambient process state.
Adds Z.ai's GLM-5.3-Flash to the dcode model switcher for Baseten, so it
can be picked from `/model` and the onboarding picker instead of typed
in by hand.
---
Z.ai released [GLM-5.3-Flash](https://z.ai/blog/glm-5.3-flash) on
2026-08-26, its first natively multimodal model in the GLM-5 series
(320B total / 18B active, hybrid linear and sparse attention, 1M
context, MIT licensed). Baseten made it available through Model APIs the
same day, per their
[changelog](https://www.baseten.co/resources/changelog/glm-53-fast-available-on-baseten/)
and [model page](https://www.baseten.co/library/glm-53-flash/).
The `baseten` provider is already wired into `PROVIDER_API_KEY_ENV`, and
`_RECOMMENDED_MODELS` already carries `zai-org/GLM-5.2` and
`zai-org/GLM-5.2-Fast`, so this only needs the new spec and its display
name. The model ID `zai-org/GLM-5.3-Flash` is taken verbatim from
Baseten's own model page rather than derived from another provider's
naming scheme. The entry is placed alphabetically within the existing
`baseten:` block, and the display name follows the sibling GLM entries.
Only the Baseten entry is added here. Other providers that may serve
this model are intentionally out of scope for this PR.
`dcode -x` now drains pending LangSmith traces before its child server
exits.
---
The child `langgraph dev` process could terminate before final trace
updates left the SDK queue. The custom HTTP app now flushes existing
tracers during lifespan shutdown on a bounded daemon worker, so a stuck
telemetry call cannot delay exit.
The parent uses graceful process-group signaling on POSIX and Ctrl+Break
for a dedicated Windows process group, with enough shutdown margin for
both the trace flush and LangGraph teardown. No tracing client is
created when tracing is disabled.
<details>
<summary>Test plan</summary>
- Unit coverage for successful, failed, disabled, and timed-out flushes
- Cross-platform server termination unit coverage
- Real `langgraph dev` subprocess shutdown test
- `make lint`
</details>
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
`/clear` now emphasizes starting fresh, while `/force-clear` is framed
as recovery for a stuck session.
---
The previous descriptions focused on implementation details and made the
intended use cases hard to distinguish. The generated command catalog is
updated from the registry.
Made by [Open
SWE](https://openswe.vercel.app/agents/e6814be2-5315-55be-aca4-e8542b57afb0)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Administrators can point the fixed managed-config file at a bounded
HTTPS TOML policy.
---
This adds remote managed configuration while keeping the fixed local
descriptor as the trust anchor. The remote document supplies the
complete managed policy.
Remote loading:
- uses system TLS validation and bypasses proxies
- refuses redirects
- enforces a 5-second timeout and 1 MiB response limit
- fails closed during startup
- preserves the last-known-good policy when a reload fails
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Dynamic subagent model usage now appears in live dcode cost and usage
statistics.
```mermaid
flowchart LR
A[Dynamic subagent request] --> B[Session cost recorder]
B -->|Versioned usage event| C[Live Textual and headless stats]
B -->|Drain raw usage| D[Cost middleware]
D -->|Checkpoint and authoritative total| C
```
Streams completed dynamic-subagent usage into existing provisional
client accounting while preserving checkpointed graph cost as the
durable authority. Events are minimized, thread-validated, deduplicated,
and best-effort.
## References
- Plan:
https://openswe.vercel.app/agents/4f3fc359-7153-5467-8164-33aa496b8a56/plan
Made by [Open
SWE](https://openswe.vercel.app/agents/4f3fc359-7153-5467-8164-33aa496b8a56)
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Closes#5757
`DEEPAGENTS_HOME` now selects the dcode user profile and trust root at
launch while preserving `~/.deepagents` as the default.
---
This makes the configured home an immutable, normalized path captured
before dotenv loading and shared by the client, server, reloads, and
child processes. A central path snapshot separates profile data,
installation-owned resources, and project configuration so cwd changes
and mutable environment state cannot move the trust root. Absolute
profiles also remain usable when the launch user's home cannot be
resolved; optional home-based integrations are skipped in that case.
Profile resolution rejects ambiguous or unsafe roots, including relative
and `~user` forms, filesystem and launch-home aliases, dangling
symlinks, non-directories, and unreadable or unsearchable directories.
The installer applies the same validation as Python and changes
ownership only for exact leaves it creates.
MCP discovery now retains explicit user or project provenance. Only the
exact configured user `.mcp.json` receives user-level trust, and
filesystem aliases or collisions fail closed to project scope. This
prevents project dotenv files, ancestor homes, checkout-contained
profiles, and case or symlink aliases from self-approving project MCP
servers.
Install and update locks and managed ripgrep prefer installation-scoped
locations, with profile-scoped fallbacks when the shared locations are
unusable. A fallback ripgrep is checksum-verified and exposed through a
process-private `PATH` shim so profile-controlled sibling executables
never enter subprocess lookup. Runtime consumers, prompts, bundled
skills, UI messages, diagnostics, and token permission hints use the
effective configured paths, and failed write-probe cleanup is surfaced
without repeated warnings.
<details>
<summary>Test plan</summary>
- Added deterministic path, dotenv, cwd, reload, client/server,
missing-home, and subprocess regressions.
- Added root-validation and installer parity coverage, including
symlink, permission, ownership, and write-probe cases.
- Added MCP provenance, filesystem-identity, trust-classification, and
project self-approval security regressions.
- Added shared-lock, managed-ripgrep fallback, checksum,
private-`PATH`-shim, and optional-ripgrep regressions.
- Added prompt, bundled-skill, diagnostics, and MCP token-path consumer
regressions.
- Current-head validation is covered by the `deepagents-code` lint job
and Python 3.12–3.14 test matrix.
</details>
---------
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>