Repository navigation
v0.0.3
[0.0.3] - 2026-11-13
Added
-
The
jellysettings declare their choices:accessis drawn as Allowed, Ask before changes or Read only, with Jelly's own line for each (needs a jelly that includes app#1301). -
The
uiActionsoption, empty (off) by default, and Jelly'scommitaction: a person can approve a Sheets value update (sheets.spreadsheets.values.update, the only value the option takes) from a UI an agent made in Jelly. The action is plan-shaped: its input is a gws plan request, its preview, the new read-only methodplan.preview(permissiongws.plan), is gws's own dry run of that exact request with every cell it writes (the spreadsheet, range and cells quoted, and control, line-separator and bidi characters shown as escapes, so no field can fake or reorder a line; it needs no grant and writes no audit record), and Jelly asks every time (confirm: "always") from an owner device only (class: "local"). The plugin checks Jelly's single-use action grant (its key, this plugin and action, the digest of exactly this input, at most a minute old, never used before, an owner device's class), then refuses when the option does not list the operation (UI_ACTION_OFF), whenaccessisread-only, for any other operation, forUSER_ENTEREDvalues, extra fields or more than 100 rows of 26 cells, and for a preview over Jelly's 4,000 characters (UI_ACTION_REFUSED); a bad grant isUI_GRANT_REFUSED. It then plans and commits the change as the person through the normal plan and commit path, soaccess, policy and the admin gate apply (the person's OpenCode permission rules for agents are not consulted: no agent makes the call), and answers what Google says changed. Each call writes aui.actaudit record withcaller: "person", the Jelly member and the grant's id, as do the plan and commit records. The declaration adds the action (tool: "gws.write"), the preview method and a minimal settings page,views/ui-changes.html, which Jelly's schema needs until it relaxes its rule for agent-UI actions (In Jelly). -
images.read, a read-only method for Jelly on the RPC named after the package, so a Google Drive or Workspace picture an agent puts in a UI is drawn. It takes{ url }and answers{ mime, base64 }: a PNG, JPEG, GIF or WebP of at most 1 MB, its type judged from its first bytes, never SVG. A Drive file link is read through gws as the account (drive.files.get, then its bytes withalt=mediain a private directory removed at once, or else its thumbnail); any other address must be https on one of Google's own image servers (lh3tolh7,lh7-rt,lh7-usundergoogleusercontent.com), with no user name, port or IP address, and is fetched with no redirect followed and the size checked while it streams; every othergoogleusercontent.comname, which anyone can hold, is refused before any fetch. The account's token goes only for an address Google returned to that account in this process, in a field Google fills itself (thumbnailLink,contentUriand the like, never text people write); any other image-server address is fetched without credentials. The account is the one Google returned the address to, or else the only account that enablesdrive, or elsedefault; otherwiseIMAGE_ACCOUNT_AMBIGUOUS. New codesIMAGE_HOST_REFUSED,IMAGE_TYPE_REFUSED,IMAGE_TOO_LARGEandIMAGE_UNAVAILABLE, animages.readaudit record, and the declaration'simageHosts(exactlydrive.google.comand those image servers) andimageRead(In Jelly). Jelly's host currently refuses any RPC answer over 64 KB, so until Jelly lifts that only pictures up to about 47 KB show there.
Known limits
- Platforms. macOS (arm64, x64) and Linux (glibc, arm64, x64) only. Windows and musl have no release binary, so the tools refuse with
GWS_UNAVAILABLEunlessbinary.pathnames agws0.22.5 executable. - Operations. The tools are the operations in the manifest generated from the pinned
gws0.22.5. A method that a latergwsadds arrives with a plugin release, andgws_cataloglists only the manifest. - Services the default sign-in leaves out. Keep needs domain-wide delegation that a Workspace admin sets up, admin reports need a Workspace admin account, and Model Armor cannot run. A method that only a Chat app or a Classroom add-on can run (
appOnly) fails withAUTH_SCOPE_MISSINGunder a Google sign-in. - Unverified OAuth apps. An External client left in Testing shows unverified-app warnings, and its refresh tokens expire after 7 days, so each account signs in again weekly.
- A cancelled commit may have been applied.
CANCELLEDmeans the call stopped whilegwsran. Check the state withgws_readbefore planning the change again. - Asks need an answerer. At
access: "ask-changes",opencode runand scripts cannot answer a prompt, so a commit there needs an allow rule for it, oraccess: "all". - Output and time limits. A result that is too large stops with
OUTPUT_LIMIT, and a slow call withTIMEOUT. Narrow the request withfields, a smaller page size,maxPagesormaxItems. - Changes from an agent's UI in Jelly. Off by default, and only Sheets value updates: RAW values (never formulas), at most 100 rows of 26 cells, with a preview that fits Jelly's 4,000-character confirmation. The preview shows the new values, not the cells' current ones. It works only in Jelly, which holds the key its grants are signed with; Jelly's grant does not yet say how Jelly asked, so the plugin relies on Jelly for asking every time.
/gws-statusdoes not show the option yet. - Pictures in Jelly over about 47 KB.
images.readanswers pictures up to 1 MB, as Jelly's picture contract allows, but Jelly's host currently refuses any plugin RPC answer over 64 KB of JSON (VIEW_DATA_MAX_BYTES), so a picture over about 47 KB shows no picture in Jelly until Jelly lifts that limit for pictures. That limit is Jelly's, not the plugin's. - Jelly. The
accesssetting declares its choices, which only a Jelly that includes app#1301 reads; an older Jelly refuses the plugin's declaration. - Tested hosts. Tested on OpenCode 2.2.3, 2.2.4, 2.2.5 and 2.2.6. A later 2.2 release loads, and
/gws-statusmarks it untested. - Audit lines can drop. The audit log is written off the call path, with a 100 ms budget per line. A write that stalls past it is abandoned: its line and any queued behind it are lost. The call's result is not affected. The sink then stops writing until the plugin reloads, and
/gws-statusshows that some audit records could not be saved. - Updates are not automatic for a Git install, and
opencode plugin updateandopencode plugin checkdo not work on one: to move to a newer release, remove the old entry and add the new tag.