Repository navigation
v2026.10.15
@code-yeongyu/senpi
Breaking Changes
Added
-
Shared RPC hosts publish each session holder's public socket and host instance in validated lease evidence. Clients can pass
open_session.expectedHostInstanceto attach only to that live host generation; a changed owner or released path returns a typed refusal with a rediscovery action instead of creating another writer (#3255, #3257). -
Dual-era MCP client: servers speaking the 2026-07-28 stateless spec revision (no
initialize, per-request_meta,MCP-Protocol-Version/Mcp-Method/Mcp-Nameheaders,server/discover) now connect, while legacy initialize-handshake servers keep working through spec-driven auto-negotiation (HTTP: modern request first with 400-body classification; stdio: discover-first probe; era cached per origin/process). Modern-only servers receive zero legacy handshake traffic through an SDK-compatibility bridge that answers the SDK client'sinitializelocally from the discovery result. Connect diagnostics log the negotiated era and protocol version per server. Modern-only stdio servers work too: the spawned process answersserver/discoverfirst, then every request carries the per-request_meta, with noinitializesent (#3304, reported by @changeroa). -
RPC effect ledger (capability
effect_ledger):abort,set_modelandset_thinking_leveltake an optionaleffectIdand get a durable receipt written before the effect is applied; a retry with the same id replays the receipt instead of acting twice, and a different request under that id is refused witheffect_id_conflict.get_effect_statusanswers any receipt by id, including inputs byclientMessageId, from a loaded session or from a transcript on disk. Input receipts now say how their turn ended (completed, aborted and by whom, error), a reopened session seals receipts its dead process left running, and queued input dropped bynew_session/switch_sessionreadsfailedinstead of vanishing (#3199).
Changed
Fixed
-
senpi host gc, and the cleanup pass that runs after starting a host, now stop a host left behind by an older engine once it holds no session, no reservation and no client and has outlived its own idle window plus 10 minutes. Such hosts used to linger for days after an update, because their old idle logic was the only thing that could end them.senpi host status --allmarks themstale_old_engine. A host with any session or connected client is never stopped (#3268). -
A fallback chain that lists one model at several thinking levels now walks every one of those levels. A rung that hard-errors parks only itself, so
models: [X:high, X:off, X:low, Y]triesX:lowafterX:offfails instead of jumping toY; a rate limit, quota or overload still skips every level of that model, so after one the walk moves on to the next model. This replaces the per-turn limit described in the previous entry. A model you pick by hand gets all its levels back (#3311, reported by @tw-yshuang). -
senpi host sessioncommands now return only after the host has dropped their attachment: on a host that advertises the newdetach_connectioncapability the client asks for the detach and waits for the answer (bounded at 5 s, with one plain line if it never comes), so a listing right afteropenno longer shows the short-lived client as still attached. A connection leaving a session that another client also holds now releases its attachment at once, even while a turn runs; only the last attachment of a non-retained session still waits for the turn to settle. After a request timed out or the connection was lost, the client closes without asking for the detach. Older hosts keep the release on socket close. (#3238) -
A flaky network no longer strands a session on a fallback model. A timeout or connection reset that outlasts the same-model retries may finish that one turn on the next model in the chain, but it no longer puts the primary on a cooldown or opens its circuit, so the next turn goes back to the primary. A rate limit, quota or overload error keeps its existing fallback behavior (#3306, reported in the OmO community).
-
A model that hit a usage limit and fell back now returns when that limit's own reset passes ("resets 3pm",
resets_at, or "resets in 9 minutes"), instead of staying on the fallback for a cooldown that doubled past the window with every failed retry. A short hint such as "retry in 7s", even on a spent quota, and a plain Retry-After still keep the doubling cooldown, so a failing provider is not retried every few seconds (#3314, reported in the OmO community). -
Local extensions keep loading after a runtime update on Bun 1.4.2 and older. Bun's transpile cache had stored the previous runtime's path to
extension-runtime-module.js, so once that runtime was pruned an unchanged extension failed withCannot find module. The cache entry now changes whenever the runtime moves, and a cache that is already broken heals on the next start, with nothing to clear by hand (#3300, reported in the OmO community). -
A credential-pool account blocked for an authentication error is no longer excluded until someone logs in again. The block now lasts 15 minutes, then one request tries the account again (refreshing its saved login first when it can), so accounts whose token was renewed elsewhere come back on their own. A goal whose provider is down no longer fires eight retries within seconds and gives up: retries back off from 15 seconds up to 30 minutes, and when the pool names the time an account frees up, the goal waits until then and continues (#3264).
-
A Claude Pro/Max subscription signed in through the Anthropic provider is moved to the Anthropic Subscription (Claude Agent SDK) lane on startup, together with saved model selections, because Anthropic bills direct-API subscription requests to extra usage and refused them. The rejection now ends the turn once with the reason and what to do, instead of replaying it on every Anthropic model (#3259).
-
A tool named
evalwith its ownpermissionParsercould answer for itself with a narrower class (for exampleread), so a preset that allows reads would run an arbitrary-code cell without asking. Theevalpermission request is now always carried alongside any tool-owned requests, so only a preset that allows everything allows a cell (#3211, requested by @code-yeongyu). -
A provider whose credentials were locked when the store was first read no longer reports "not configured" to
get_auth_providersafter the lock clears, while its models already work. The status now re-reads the store the same way model availability does (#3273, reported from the OmO desktop app). -
A fallback chain can walk to a rung that runs the same model at another thinking level. Such an entry used to disappear twice over: the chain scan consumed it as the entry in flight and then skipped it as a self-reference, and a model's remaining rungs were suppressed once one of them had been taken - so a chain written as
models: [X:high, X:off, Y], which is how the OMO/senpi adapter ships it (the entries[X:off, Y]under the bareXkey), jumped straight toY. Chain validation no longer reportsX:offunder theXkey as referencing the same model. Cooldowns and circuits stay keyed by the model, because a rate-limited or spent account is unhealthy at every level, so one same-model rung remains reachable per turn before the current model's cooldown expires.
Removed
- Removed the Codex
app-servercommand, daemon, generated protocol and compatibility QA harness. Process integrations use Native RPC (senpi --mode rpcorsenpi host); OpenAI API and ChatGPT subscription models remain supported, and historical model-change records remain readable. Extensions that comparedctx.modewith"app-server"must drop that branch:ExtensionModeno longer includes it (#3167, requested by @code-yeongyu).
@code-yeongyu/senpi-ai
Breaking Changes
Added
Changed
- The bundled model catalog is refreshed from models.dev and the providers' model listings (
github-copilot,google,google-vertex,meta,opencode,opencode-go,opengateway,openrouter,vercel-ai-gateway).
Fixed
- OpenCode Go models served over the Google Generative AI API now have a working transport; the refreshed catalog had added one, which broke the typed catalog. Two entries the provider no longer offers are removed from OpenCode Go.
- Venice deepseek models (
deepseek-v4-1-flash,deepseek-v4-pro-0813and the other deepseek-v4 entries) work again: requests no longer carry DeepSeek'sthinkingkey, which Venice rejected with 400 on every call, and thinking runs through Venice'sreasoning_effortinstead (#3308). - Anthropic's "Third-party apps now draw from your extra usage" rejection is classified as terminal account exhaustion with a plain explanation of the billing path, and the
anthropicprovider no longer offers a Claude subscription OAuth login; subscriptions use the Agent SDK lane (#3259).
Removed
@code-yeongyu/senpi-agent-core
Breaking Changes
Added
Changed
Fixed
Removed
@code-yeongyu/senpi-codemode
Breaking Changes
Added
Changed
Fixed
display()of a large object, such as a screenshot result that wraps a multi-MB Buffer, no longer writes megabytes into the session file or breaks the session render. The stored copy is trimmed inside the value instead of dropped: every top-level key is kept, Buffers become a<Buffer N MB>summary, long strings, arrays and keys keep a prefix with a visible marker, and the entry stays within the display budget, emoji included. Older sessions holding such entries render a short summary, and an object whosebufferholds image bytes now displays as the image with its metadata (#3320).