Repository navigation
Preserve the published FStack runtime baseline alongside inherited PATH policies - #187
Closed
CoreyShupe wants to merge 28 commits into
Closed
CoreyShupe wants to merge 28 commits into
CoreyShupe wants to merge 28 commits into
Conversation
A broker that serves many machines from one sign-in, such as the FStack dashboard, can now supply Claude and ChatGPT access tokens through SetProviderAccountCredential with kind oauth_brokered. Providers rotate refresh tokens, so the broker must be the only refresher: a brokered credential carries no refresh token, Nakode never refreshes it, and once it expires commands fail with a message beginning credential_refresh_required. Each adapter validates its own brokered shape. Replacement credentials now reach running Claude sessions in place through UpdateCredential, as they already did for ChatGPT, so a periodic token replacement never interrupts work. cargo fmt and clippy (pedantic, -D warnings) are clean. The all-target suite passes except tools::tests::bash_skips_unchanged_successful_validation_until_ reason_or_state_change, which fails identically on origin/main.
With several eligible accounts and none in automatic routing, session creation refused outright even though one account was the owner's default. A machine holding its own sign-in beside a brokered account could not start a Claude session at all. The eligible default is now the choice; without one the owner must still pick.
A session no longer belongs to a provider account. Where a turn begins the runtime keeps the session's last or requested account while it is eligible and otherwise routes to any eligible one; commands inside a running turn stay on the account running it. Codex, Claude, Kimi and GLM take the new account's credential into the live handle, and a start or resume loads into a fresh handle on it. sessions.account_id records where a session last ran and is no longer enforced: the affinity conflicts, the historical-session refusal and the in-use account refusal are gone, and removing an account frees its sessions. Codex reasoning is tagged with the ChatGPT account that produced it and replayed only to that account, since its encrypted content opens for no other.
…g agents' .tmp-gallery screenshots
…nts, not only its children
… as an explicit open would
Every backend event of an ordinary session logged "durable inbound replay deferred" because the missing bridge record surfaced as an error.
The Claude SDK owns Claude history, so after a restart a read of a session that is not loaded had nothing to project and failed until the session was reopened. The bridge now leaves its history after every turn and resume, and the retained read projects it.
Account variables such as GH_TOKEN and the GitHub credential helper reached only Nakode's own shell tools; Claude's Bash ran with the bridge's environment, so gh and git push could not authenticate.
One short-lived bridge reads each snapshot-less Claude session's transcript without resuming it, so sessions from before snapshots existed read back too. An unreadable transcript keeps no snapshot rather than an empty one.
Every mutation, including each streamed chunk, cleared the prefix proofs, and the next page read serialized and hashed every entry again. Entry digests are now kept beside the exact entry they came from and reused while it is unchanged; each proof chains the previous one with the next entry's digest. A rebuilt unloaded session reuses its last digests. Proof values change once (v2 tag); clients only compare them.
History rebuilt from the Claude SDK kept a call's input and output only in its body, so resumed and unloaded transcripts showed raw JSON instead of the command, edit and search rows live calls get.
History rebuilt from the Claude SDK had no provider, so restored thinking fell back to a generic notice instead of the thinking trace a live turn shows. Owner messages stay unattributed.
Where the machine gives agents a desktop (DISPLAY, xdotool, ffmpeg), three tools appear: desktop_screenshot, desktop_action (click, drag, scroll, type, keys) and screen_record. Recordings drop repeated frames, hold the last one, and compress to H.264 within 8 MiB into the stack Gallery with a poster frame. Claude sees each screenshot, including one after every action; native tools save it for the vision tool.
The bridge always launched `claude` from PATH, so a machine without Claude Code installed, such as an environment VM, listed no Claude models and could not start a turn. It now uses a configured or installed Claude Code and otherwise the platform build the Agent SDK installed.
…r-credentials # Conflicts: # docs/coordination-messages.md
Claude Code offers one model twice, with its standard and its 1M-token context window (opus and opus[1m]); names leave the window out, so both read "Opus 5.5". Where names would repeat, the row whose identifier asks for a window now says so: "Opus 5.5 (1M context)".
A Chat on a machine and the agent it started inside a stack VM run in two runtimes, so no session_child_links row joins them and the child's final report never reaches the parent. AdmitExternalChildReport lets the authenticated integration that recorded the relationship relay the report: it enters the parent's durable inbox exactly as a linked child's report does (durable_child_evidence, inert, never owner instruction), deduplicated by message identity, and the idle parent is activated to process it. The runtime advertises ExternalChildReports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A parent in another runtime needs the same report a linked parent receives. The runtime already captures each terminal turn's bounded completion and persists it with the session; keep it on LastTurn and project it as last_turn.completion through the protocol view and gRPC. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.
Purpose
Follow-up to #186: FStack previously shipped runtime
582643c98ef0f85ead9996c70dd22cea31badcf4, which contains existing provider/coordination APIs absent from main. Pinning main's #186 release fails FStack native checking with missing external-child-report, owner-Chat follow-up and turn-completion APIs.This standalone PR incorporates only that exact previously published baseline, preserving its behavior plus #186's inherited read-only PATH policy. It does not modify any other PR or branch or incorporate newer draft-branch work. Owner explicitly requested our own PR rather than changing other PRs.
Compared with the previously shipped revision, the combined tree differs only in the three reviewed #186 files and rustfmt of one existing assertion in
src/state.rs.Validation
cargo test --offline --all-targets --all-featuresrefuses missing cachedclipboard-rs; no local test pass claimed.After this PR's exact merged SHA is published as
runtime-<SHA>, FStack will pin and validate it. The older #186 release alone is not API-compatible with FStack's existing runtime baseline.