fix(code): correct editable SDK detection to scan and correlate - #5199
Merged
Mason Daugherty (mdrxy) merged 1 commit intoJul 30, 2026
Merged
Conversation
`_editable_sdk_source_root` used a single `distribution("deepagents")` lookup
with no correlation against the running package, so it disagreed with the SDK's
own `lc_versions.deepagents` trace entry in both directions: a source-tree
`deepagents.egg-info/` (which carries no `direct_url.json`) shadowed a real
editable install and read "not editable", while an unrelated editable record
could be credited to a published wheel install.
Port the SDK's scan-and-correlate approach into dcode: scan every installed
`deepagents` distribution for a PEP 610 editable record, and credit it only
when its source root contains the package `find_spec` would import. The probe
locates the package without importing it, preserving the "version lookup must
not import the SDK" invariant. Per-distribution metadata failures are
contained so one unreadable record cannot abort the scan, and the
`distributions()` backstop now also swallows `RecursionError` so pathological
metadata cannot make the answer iteration-order-dependent.
dcode keeps its own copy rather than importing the SDK helper: the SDK's
version is a private symbol that only exists in releases newer than dcode's
exact `deepagents` pin, so delegating would gate the fix on an SDK release and
a pin bump.
Mason Daugherty (mdrxy)
deleted the
mdrxy/code/fix-editable-sdk-detection
branch
July 30, 2026 17:59
Mason Daugherty (mdrxy)
added a commit
that referenced
this pull request
Jul 30, 2026
`dcode` now detects an editable `deepagents` SDK install the same way
the SDK itself does, so the two stop disagreeing about the same
installation. A trace that previously showed `lc_versions.deepagents =
"0.7.0+editable"` alongside `dcode_client_deepagents_version = "0.7.0"`
for one install now reports the editable source version on both.
---
## Why
`_editable_sdk_source_root` answered "is the installed `deepagents`
editable, and where is its source?" with a single
`importlib.metadata.distribution("deepagents")` lookup and no
correlation against the running package. The SDK's
`_is_editable_install` does more, and both extra steps guard real
errors:
- **Scan every matching distribution instead of one lookup.**
`setuptools` leaves a gitignored `deepagents.egg-info/` in the source
tree after any local build, and the cwd is on `sys.path` for `-c`, `-m`,
and the REPL — so from a checkout that directory is found *first* and
carries no `direct_url.json`. The single-lookup form concluded "not
editable" and never consulted the real editable install in
site-packages. In that scenario dcode fell back to package metadata for
the version while the SDK stamped `+editable`; after this change dcode
correctly reads the version from the checkout's `_version.py`.
- **Correlate the record with the running package.** An environment can
hold several `deepagents` records — a wheel earlier on `sys.path` plus
an unrelated editable checkout later on it. Crediting the wrong one
labels a published install as a workspace build.
## What changed
dcode's `_editable_sdk_source_root` now scans every installed
`deepagents` distribution for a PEP 610 `dir_info.editable: true` record
and credits it only when its source root contains the package
`find_spec` would import, mirroring the SDK's logic. The correlation
anchor is located with `importlib.util.find_spec` rather than an
`import`, so the existing "SDK version lookup must not import the SDK"
invariant (`test_dcode_client_deepagents_version_does_not_import_sdk`)
still holds. Per-distribution metadata failures are contained so one
unreadable record cannot abort the scan early; the `distributions()`
backstop also swallows `RecursionError` so pathological metadata cannot
make the answer depend on iteration order.
**dcode keeps its own copy rather than importing the SDK helper.** The
SDK's scan lives in the private `_is_editable_install`, which only
exists in releases newer than dcode's exact `deepagents==0.7.0` pin —
delegating would gate this fix on an SDK release and a pin bump, and add
another private-SDK coupling. The mirrored tests in
`test_extras_info.py` keep the two implementations honest.
The editability tests were reworked to patch the new seams
(`distributions`, `_running_sdk_package_root`) instead of handing a
fabricated `direct_url.json` payload to a `distribution()` mock. Some
expectations changed for correctness reasons, not just mocking reasons:
the egg-info-shadowing case now resolves the editable source version
instead of falling back to metadata.
## Behavior change to call out
This is not pure cleanup. In the egg-info-shadowing scenario dcode
previously concluded "not editable" and reported the metadata version;
it now concludes "editable" and reports the checkout's source version.
That is the intended fix — developer environments will see their SDK
version reported as the live source version (matching the SDK's own
trace entry) rather than stale install metadata.
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 31, 2026
> [!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.1.51](deepagents-code==0.1.50...deepagents-code==0.1.51) (2026-07-31) ### Features - The status bar and usage view now show the running session cost. ([#5036](#5036)) - Removed redundant `shell` and `web_search` prompt guidance. ([#5213](#5213)) - After switching threads, Deep Agents now points back to the previous thread. ([#5172](#5172)) - Leaving `/mcp` with pending toggles now prompts you to reconnect. ([#5211](#5211)) - `dcode config get` now accepts configuration sections. ([#5134](#5134)) ### Fixes - Kept the `/goal` criteria prompt responsive. ([#5142](#5142)) - Improved goal handling so underspecified objectives can be resolved from conversation context. ([#5201](#5201)) - Released the turn when an interrupted worker never starts. ([#5196](#5196)) - Hid timestamp footers together with their associated rows. ([#5167](#5167)) - Fixed editable SDK detection by scanning and correlating SDK locations more accurately. ([#5199](#5199)) - Improved `doctor` output to explain why it may not have a latest-version answer. ([#5209](#5209)) _End release notes preview._ --- > [!NOTE] > A **New Contributors** section is 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 2). --------- 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>
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.
dcodenow detects an editabledeepagentsSDK install the same way the SDK itself does, so the two stop disagreeing about the same installation. A trace that previously showedlc_versions.deepagents = "0.7.0+editable"alongsidedcode_client_deepagents_version = "0.7.0"for one install now reports the editable source version on both.Why
_editable_sdk_source_rootanswered "is the installeddeepagentseditable, and where is its source?" with a singleimportlib.metadata.distribution("deepagents")lookup and no correlation against the running package. The SDK's_is_editable_installdoes more, and both extra steps guard real errors:setuptoolsleaves a gitignoreddeepagents.egg-info/in the source tree after any local build, and the cwd is onsys.pathfor-c,-m, and the REPL — so from a checkout that directory is found first and carries nodirect_url.json. The single-lookup form concluded "not editable" and never consulted the real editable install in site-packages. In that scenario dcode fell back to package metadata for the version while the SDK stamped+editable; after this change dcode correctly reads the version from the checkout's_version.py.deepagentsrecords — a wheel earlier onsys.pathplus an unrelated editable checkout later on it. Crediting the wrong one labels a published install as a workspace build.What changed
dcode's
_editable_sdk_source_rootnow scans every installeddeepagentsdistribution for a PEP 610dir_info.editable: truerecord and credits it only when its source root contains the packagefind_specwould import, mirroring the SDK's logic. The correlation anchor is located withimportlib.util.find_specrather than animport, so the existing "SDK version lookup must not import the SDK" invariant (test_dcode_client_deepagents_version_does_not_import_sdk) still holds. Per-distribution metadata failures are contained so one unreadable record cannot abort the scan early; thedistributions()backstop also swallowsRecursionErrorso pathological metadata cannot make the answer depend on iteration order.dcode keeps its own copy rather than importing the SDK helper. The SDK's scan lives in the private
_is_editable_install, which only exists in releases newer than dcode's exactdeepagents==0.7.0pin — delegating would gate this fix on an SDK release and a pin bump, and add another private-SDK coupling. The mirrored tests intest_extras_info.pykeep the two implementations honest.The editability tests were reworked to patch the new seams (
distributions,_running_sdk_package_root) instead of handing a fabricateddirect_url.jsonpayload to adistribution()mock. Some expectations changed for correctness reasons, not just mocking reasons: the egg-info-shadowing case now resolves the editable source version instead of falling back to metadata.Behavior change to call out
This is not pure cleanup. In the egg-info-shadowing scenario dcode previously concluded "not editable" and reported the metadata version; it now concludes "editable" and reports the checkout's source version. That is the intended fix — developer environments will see their SDK version reported as the live source version (matching the SDK's own trace entry) rather than stale install metadata.