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.
Directory for persisted update command logs.
Delete update logs older than this many days.
Keep at most this many newest update logs.
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 pip command for unrecognized install methods.
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 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.