sak-runner runs agy accounts through agy and signs them in, in a home whose keychain holds the login #162
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "task/3841-sak-runner-runs-gemini-through-the-agy-h"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Tracker: #3841
The runner speaks a fourth harness,
agy: Google's Antigravity CLI, through which runs use the Gemini models. A runner on macOS withagyon its run PATH registers it with its version. An account of harnessagysigns in through the runner, taking the code pasted in sak, and serves only the Gemini models. A run whose model an agy account serves runs through agy. Its shapes were read from agy 1.4.5 on s32.agy is offered only on macOS. An agy run's home keeps its login in a macOS keychain (see below), so a runner on any other platform does not look for agy (
config.unrunnable, runner/config.sx). It leaves agy out of its offers, at its start and in each rescan after an install. Its scan line reads✗ agy: macOS only. The deps summary leaves agy out of what it offers, and the running view's header shows✗ agy, as for any harness not offered.sak-runner-livenow takes its platform as the runner does, so it still resolves agy on macOS.The adapter (
runner/agy.sx).agy -p= --input-format stream-json --output-format stream-json --model <model> --effort <effort>, plus--dangerously-skip-permissionsunder the new--agy-permission allow(the default).reject, agy's headless mode (request-review) denies every tool call that needs a permission. With the flag, the mode readsalways-proceed, and a file read went through.-ptakes the next argument as its prompt, so the empty prompt is given inline.{"event":"user","message":{…}}line. agy runs each line as a turn of its own, once the turn before it ends.init'sconversation_idis the session id.user_inputstep after the prompt's is the replay of a handed message.resultends a turn.ERRORresult before anyinit(no login, unknown model) fails the run withsession failed: <error>. AnERRORresult inside a session ends only its turn.The run home (
src/home.sx). agy keeps its login in the OS keyring: on macOS, the generic password with servicegeminiand accountantigravity, stored asgo-keyring-base64:followed by the login in base64.Library/Keychains/sak.keychain-db, with no password and no lock timeout, and sets it as the keychain that home searches and writes to.securitykeeps that setting in the home'sLibrary/Preferences, which has to exist first.security -i's stdin, so it never appears on a command line.loginprints the login back, including a renewal agy writes, without the newlinesecurityends it with.teardowndeletes the keychain, then removes the home.Sign-in (
runner/sign_in.sx). agy has no login command: its interface signs in first when its home holds no login, and stays up once signed in. The runner runsagywith no arguments on the sign-in's pseudo-terminal (50 × 1000), in a home whose keychain holds no login yet.Select login methodit presses Enter, which takes the first entry, Google OAuth.https://word oncepaste the authorization codeshows below it.token exchange failedon the screen ends the sign-incode_refused.agy models, one<id>\t<label>line each. Each id is a model and an effort joined by a dash (gemini-3.8-flash-lowisgemini-3.8-flashatlow), so ids group into a model with its efforts. The listing is whole once agy's output ends.gemini-. agy 1.4.7 also lists two Anthropic models at three efforts each, and gpt-oss-120b. Those ids are the ones other harnesses' accounts serve, and sak takes the first serving account by position whatever its harness, so runs meant for those accounts could otherwise be claimed on the agy account.POST /api/sign-ins/:id/codetakes a pasted code for an agy sign-in, as it does for the other harness whose login takes one.BROWSER: it opens its link withopenon the runner's host as well as showing it.TERM. The sign-in took Google OAuth and reported Google's whole OAuth link with no code. A wrong code ended itcode_refused. Signing in with a real Google account was not run.The web. The sign-in dialog offers agy beside the other harnesses. A waiting agy sign-in shows its link and the paste field, as any sign-in with a link and no code does.
The schema. Migration 54 rebuilds
account,run_requestandsign_inwithagyin theirharnesschecks.run_requestkeeps every column and index master's migrations 50–53 gave it (kept_head,resume_ref,resume_head,cancelled,place,run_request_place). The store accepts agy offers, accounts and sign-ins.sqlite3 .schema, equal). Against master's, the three tables have the same columns, types, defaults and indexes; only theirharnesschecks name agy.Regressions, each failing before its fix.
tests/stub_sign_in.shnow lists two non-Gemini ids among Gemini ones. In agit archivearm ofdaeadc9bcarrying only the new tests,tests/sign_in.sxprintedSIGN IN FAIL (1 checks), the failing check being "the agy account serves only the Gemini models agy lists, at the efforts their ids end in". At7f8f82f9it printsSIGN IN OK.tests/runner_core.sxfailed "a runner off macOS leaves agy out of its offers, at its start and in a rescan, and its scan line says why". At7f8f82f9that check passes.fullgate below and in the arm of the head.harness_cannot_sign_in. In agit archivearm of201f9b2acarrying only the new tests,tests/sign_in.sxprintedSIGN IN FAIL (11 checks), every agy check failing, from "the agy sign-in takes its login's first way to sign in…" to "and its login is ended and its home removed". Atdaeadc9bit printedSIGN IN OK.tests/runner_core.sxprintedRUNNER CORE FAIL (1 checks), the failing check being "a login agy left as the run's home was given it is no renewal". Atdaeadc9bit printedRUNNER CORE OK(508 ok).Tests.
tests/runner_agy.sxdrives the adapter with lines recorded from agy 1.4.5.tests/stub_agy.shstands in for agy intests/runner_core.sx, which pins:--agy-permissionflag;tests/runner_core.sxalso registers a runner whose platform islinux-x86_64, and pins that agy is left out of its offers and named in its scan line as macOS only.tests/stub_sign_in.shstands in for agy's login and listing intests/sign_in.sx. It pins the menu, the bare link, the pasted code, the login read from the home's keychain while the login stays up, the Gemini models grouped by effort with the others left out, a refused code, and the home removed.web/e2e/runner/wizard.spec.tsgives the runner a stub agy, as it gives the other harnesses, and reads✓ agy 1.4.5in the scan line.Goldens. The sign-in dialog's harness picker gains a fourth segment, so these goldens changed, each light and dark at 1280×800 and 390×844:
accounts-sign-inaccounts-pasted-codeaccounts-sign-in-expiredaccounts-no-runnerThe merge of master
45028434took master's goldens where master had re-recorded them (14 of the 16), and one full run of the main config at the merge (--update-snapshots=changed, 777 passed, 1 skipped) re-recorded exactly those 14 and no other golden. Against master's, each of the 16 changes only a 56×28 px box at the picker's right end, where agy's segment is.Docs. runner/README.md (Harnesses, the harness scan, the flags table, the sign-in steps, the running view's sample, the tests) and docs/api.md (the harness lists, the sign-ins, the code route, the registration, the run-home table) name agy. Both say that an agy account serves only the Gemini models and that agy is offered only on macOS.
Not in this PR.
Gates.
fullgate run 814 passed at the head,d3875b7d, on a clean tree (14:05–14:49 EET on 2026-10-29). The head holds master at45028434. The gate ran:npm run buildand the libc grep;Before the gate, the 69 tests/*.sx files the loop runs each printed OK from a
git archivearm of the merge (runner_core,sign_in,runner_agy,deployed_upgradeand the roll-backs inflows,tools,utf8_textandfile_keysamong them).The runner speaks agy's print-mode stream-json through one adapterto sak-runner runs agy accounts through agy, in a home whose keychain holds the loginsak-runner runs agy accounts through agy, in a home whose keychain holds the loginto sak-runner runs agy accounts through agy and signs them in, in a home whose keychain holds the login