Expand description
update — bare-naked streaming handler.
Refreshes every shipped binary from the latest GitHub release by
downloading a single per-platform zip
(objectiveai-<version>-<os>-<arch>.zip) and replacing the contents
of the machine-wide bin/ directory wholesale. Emits one
ResponseItem per stage as the run progresses.
Layout on disk (resolved via ctx.filesystem.bin_dir() — every
binary is machine-wide, shared across states):
<bin_dir>/objectiveai{.exe} ← cli
<bin_dir>/objectiveai-api{.exe}
<bin_dir>/objectiveai-viewer{.exe}
<bin_dir>/objectiveai-mcp{.exe}
<bin_dir>/objectiveai-db{.exe}
<bin_dir>/objectiveai-claude-agent-sdk-runner{.exe}
<bin_dir>/objectiveai-codex-sdk-runner{.exe}
<bin_dir>/objectiveai-mcp-laboratory (always musl-linux; no .exe)Flow:
- Resolve the single zip asset for this
(os, arch). A missing zip emitsResponseSkipReason::IncompleteRelease. - Download the zip to a temp path (outside
bin/, so the wipe below can’t clobber it). - Kill the running servers in-process: the machine-wide
api(its lock lives at<bin_dir>/locks) and the per-statedb/vieweracross every state. - Rename the running updater aside (Windows can’t overwrite a
running
.exe; renaming frees the name — the process keeps running from the renamed file). - Wipe
bin/keeping onlyplugins/,tools/, andconfig.json(best-effort — a still-running server/.oldthat won’t delete is skipped).pg-bin/is wiped; postgres re-extracts on nextdbspawn. - Unzip the download into
bin/. Each binary is written via the same rename-aside swap so a still-locked straggler doesn’t fail the extraction.
Caveat: db/viewer are killed across every state, but a server
that comes back (or a binary still locked at unzip time) is left as
a .old; the cli’s own .old is swept on the next invocation.