Update lifecycle for deepagents-code.
Handles version checking against PyPI (with caching), install-method detection, auto-upgrade execution, config-driven opt-in/out, notification throttling, and "what's new" tracking.
Most public entry points absorb errors and return sentinel values.
set_auto_update raises on write failures so callers can surface
actionable feedback.
PyPI JSON API endpoint for version checks.
PyPI JSON API endpoint for reading deepagents SDK release metadata.
The CLI only reads release-age metadata from this endpoint; it never performs SDK update checks.
User-Agent header sent with PyPI requests.
Path to the user's model configuration file (~/.deepagents/config.toml).
Directory for app-managed internal state (~/.deepagents/.state).
Holds files the app writes for its own bookkeeping — OAuth tokens, the
sessions database, version-check caches, input history. Kept separate from
top-level user-facing config and agent directories so listing/iterating
~/.deepagents doesn't conflate state with agents.
On-disk cache of the latest published dcode/SDK versions and SDK release times.
Populated by get_latest_version; reads short-circuit on the cached payload
when it is younger than CACHE_TTL. SDK upload timestamps are stored under
_SDK_RELEASE_TIMES_KEY.
Persistent flags for the update-notification UX.
Tracks which version the user has been notified about (notified_version,
notified_at) and the most recent version they've seen the splash for
(seen_version, seen_at). Read by should_notify_update and friends
to suppress repeat notifications across invocations. Auto-update opt-outs
live in config.toml, not here.
Maximum age in seconds before CACHE_FILE entries are considered stale.
A cached latest_version.json younger than this is reused without an HTTP
call to PyPI; older payloads trigger a fresh fetch. Set conservatively at
24h since release cadence is on the order of days, not minutes.
Minimum installed-version age before update notices call it out explicitly.
Generic upgrade hint used when install-method detection fails.
Callers that surface an upgrade command in user-facing text should prefer
upgrade_command(); this constant exists so those callers have something
to render when detection raises unexpectedly. The documented install path
is uv tool install (see scripts/install.sh), so the uv command is the
right display fallback. Execution paths still refuse unrecognized installs
instead of updating a separate environment.
Directory for persisted update command logs.
Delete update logs older than this many days.
Keep at most this many newest update logs.
Check for updates using only a fresh local cache entry.
This is the startup fast path: it never contacts PyPI. Stale, missing, corrupt, or unparsable cache data is treated as "no cached update answer" so callers can launch immediately and let a background update check refresh the cache later.
Fetch the latest deepagents-code version from PyPI, with caching.
Results are cached to CACHE_FILE to avoid repeated network calls.
The cache stores both the latest stable and pre-release versions so a
single PyPI request serves both code paths.
Return the cached ISO-8601 upload time for version, or None.
Only versions captured during a prior get_latest_version call are
available; unknown versions, or a None input, return None.
Return a human-readable age for version (e.g., 'released 3d ago').
Returns an empty string when the upload time is unknown (cache entry
lacks release_times for this version, or a None version) so callers
can concatenate unconditionally.
Return ", released Nd ago" for version, or "" when unknown.
The ", " separator is included so callers can splice the age into a
parenthetical unconditionally — if the age is unknown, the empty
string collapses cleanly into the surrounding text.
Return " (released Nd ago)" for version, or "" when unknown.
Return " (N days old)" for installed versions at least a week old.
Return the ISO-8601 upload time for deepagents SDK version.
Reads from CACHE_FILE under sdk_release_times, falling back to a
single PyPI fetch on cache miss and writing the result back so
subsequent calls stay local.
Return a human-readable age for SDK version (e.g., 'released 3d ago').
May trigger a single PyPI fetch on cache miss (3s timeout). Returns an empty string on any failure so callers can concatenate unconditionally.
Return ", released Nd ago" for SDK version, or "" when unknown.
The ", " separator is included so callers can splice the age into a
line unconditionally — if the age is unknown, the empty string
collapses cleanly into the surrounding text. May trigger a single
PyPI fetch on cache miss.
Return whether the user should be notified about version latest.
Throttles notifications to at most once per CACHE_TTL period for a
given version, preventing repeated banners every session.
Record that the user was notified about version latest.
Writes into the shared update state file so a subsequent
should_notify_update call can suppress duplicate banners.
Clear the "already notified" marker so the update modal re-opens next launch.
Removes both notified_at and notified_version from the shared
update state file.
Check whether a newer version of deepagents-code is available.
When the installed version is a pre-release (e.g. 0.0.35a1),
pre-release versions on PyPI are included in the comparison so alpha
testers are notified of newer alphas and the eventual stable release.
Stable installs only compare against stable PyPI releases.
Detect how deepagents-code was installed.
Checks sys.prefix against known paths for uv and Homebrew.
Return the shell command to upgrade deepagents-code.
Falls back to the documented uv command for display-only guidance.
Remove old update logs while preserving the newest recent logs.
Return a new timestamped update log path and clean stale logs.
Attempt to upgrade deepagents-code using the detected install method.
Only tries the detected method — does not fall back to other package managers to avoid cross-environment contamination.
Return whether extra is safe to embed in package-extra syntax.
Return whether package is safe to embed in a --with install command.
Return the shell command that adds a package to the dcode tool env.
The result is built for execution (via perform_install_package), not for
display — surfacing raw uv tool invocations to the user is intentionally
avoided. package is validated and then shlex.quote-d: the validation
already blocks shell metacharacters, so the quoting is defense in depth that
keeps the command safe even if the pattern is later loosened.
Already-installed extras are folded into the deepagents-code[...]
requirement via the shared _dcode_extras_requirement helper, the same way
install_extras_command builds its requirement. Without this the reinstall
would replace the tool with a plain deepagents-code, silently dropping any
extras the user added through /install <extra>.
Return the uv command that installs the exact set of dcode extras.
Return the shell command that adds extra to the installed dcode tool.
The documented install path is uv tool install (see
scripts/install.sh), so extras must be preserved across reinstalls.
Single-quoting the bracket form keeps zsh from globbing it.
Return the canonical action hint for editable installs missing an extra.
Shared by every site that detects an editable install and points the user
at the correct uv tool install --editable invocation, so wording stays
consistent and the literal [<extra>] bracket fragment is centrally
defined (callers that print through Rich markup must still escape it).
Return the canonical action hint for editable installs needing a package.
Editable installs can't have packages added automatically, so this points
the user at adding it to their own development environment. Phrased without
a raw install command, since surfacing uv tool invocations to the user is
intentionally avoided.
Add extra to the installed dcode tool environment.
Runs uv tool install -U 'deepagents-code[<extras>]', preserving any
extras that are already installed. Editable installs are refused — the
caller should rerun their uv tool install --editable command with --with 'deepagents-code[<extra>]' added so the extra is resolved against the
editable source.
Add an arbitrary package to the installed dcode tool environment.
Runs uv tool install -U 'deepagents-code[<extras>]' --with <package>, the
escape hatch for a provider whose package is not a deepagents-code extra
(e.g. a custom or in-house class_path model). Already-installed extras are
preserved so the reinstall does not drop them. Editable installs are refused
— the caller should rerun their uv tool install --editable command with
--with <package> added so it resolves against the editable source.
Return whether update checks are enabled.
Checks DEEPAGENTS_CODE_NO_UPDATE_CHECK env var and the [update].check key
in config.toml.
Defaults to enabled.
Return whether auto-update is enabled.
Opt-in via DEEPAGENTS_CODE_AUTO_UPDATE=1 env var or
[update].auto_update = true in config.toml.
Defaults to False.
Always disabled for editable installs.
Persist the auto-update preference to config.toml.
Writes [update].auto_update so the setting survives across sessions.
Return the last version the user saw the "what's new" banner for.
Record that the user has seen the "what's new" banner for version.
Return True if this is the first launch on a newer version.