Repository navigation
Releases
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.
v0.0.2
[0.0.2] - 2026-11-12
Added
-
The
rpcCommitsoption, off by default. When a host turns it on, because it confirms each change on its own screen before it calls the RPC, the six commit tools are also tools RPC methods (write,send,share,delete,exportandadmin), so a script can commit a plan with{ planId }. Plans stay single-use and bound to their session, agent and account, andaccessstill decides each commit: at"ask-changes"the RPC refuses it. With the option off nothing changes: a commit method answersrpc.method_not_found. -
Status names each interactive account's signed-in
email(when Google has verified it) and Workspacedomain(Google'shd; absent for a consumer account), read from theid_tokenof the sign-in and of each refresh, only when its claims check out:issis Google's,audis the OAuth client the sign-in used, andexphas not passed.gws_statusand the status RPC carry them;/gws-statusand the status dialog do not show them. A sign-in from before this release shows them once a token refresh returns anid_token, or after signing in again. -
Status shows whether
rpcCommitsis on:rpcCommitsingws_statusand the status RPC, and a Script commits row in/gws-statusand the status dialog. When it is on, the row,gws_status(rpcCommitsUnguardedAgents) and each commit method'sdescribedescription name the agents without the default rules, whose scripts commit without asking; the status RPC names them inunguardedAgents. -
calendar.today, a read-only method for Jelly's calendar, on an RPC named after the package (@joe-broadhead/opencode-gws), where Jelly calls a view's methods. It takes{}and answers{ account, at, state, events }: today's entries on one account's primary calendar (the implicitdefaultaccount, or else the first account that enablescalendar), today being midnight to midnight in that calendar's own time zone, at most 50, not yet ended, each with its id, title, start, end,allDay, location and https links only. It reads through the plugin's own read path with the account's sign-in, never writes, never downloads gws, and returns no descriptions or guests. A reading is kept in memory for a minute, and when a later read fails its events of the same day come back asstale; an answer stays within 60 KB of JSON (Jelly refuses one over 64 KB) by leaving out its latest-starting events, which the audit counts asomittedon acalendar.todayrecord; a read that takes more than eight seconds is abandoned; with nothing kept, it fails with the plugin's code,AUTH_REQUIREDwhen the account must sign in, or the newCALENDAR_UNAVAILABLEwhen no account enablescalendar. -
The
jellydeclaration names it:rpcdeclarescalendar.todayread-only under the existinggws.readpermission, a Today Home tile (views/calendar.html, a sealed page with only therpcgrant) calls it, andnativeDatapoints Jelly's native calendar at that tile's read (In Jelly).
Fixed
- A commit's audit record carries
caller: "rpc"when a script made it, as a script's reads and plans already did.
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. - 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.
v0.0.1
[0.0.1] - 2026-11-12
Fixed
- An interactive account without
enabledServices, with or withoutmode, gets the services the default account enables: every manifest service exceptkeep,admin-reportsandmodelarmor. Its sign-in form starts on Read-only and still offers Read and write, unless itsaccesssays otherwise. Jelly adds each named account as thejellydeclaration says,{ "mode": "interactive" }, and the plugin refused that withOPTIONS_INVALID(accounts.<alias>.enabledServices), so OpenCode did not load it and Google Workspace could not be signed in to at all. A headless account still names its services. (#26) /gws-installnames gws once: "gws 0.22.5 is installed and verified.", not "gws gws 0.22.5 …". The version it reports is the binary's own--versionline, which already starts withgws, as/gws-status,gws_statusand the status dialog show it. (#29)
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. - 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.
v0.0.0
[0.0.0] - 2026-11-10
Changed
- The Code Mode catalogue no longer pins
catalogorplan. The Workspace skills describe call shapes, and Code Mode search finds full signatures. Both skills explain how to connect an account. - Every tool is allowed by default. The plugin inserts an allow for each of its actions, the six commit tools and
thegws.*namespace included, so a tool a later release adds runs at once. The newaccessoption restricts it:
"ask-changes"asks before each commit, and"read-only"denies the commits while every read still runs. A commit
still needs its plan andplanId.gws_status, the status RPC and the dialog show the value. - The tools RPC follows the same default: a script runs every method unless a rule says otherwise.
- The tools RPC,
google-workspace.gws.tools, follows the family's shared v2.1 module (src/host/tools-rpc.ts). Its methods are the read tools,status,catalog,schema,read,planandevents_list, each with its input and output schema. The six commit tools are not methods: a script can plan a change, and a commit runs only from the model's approved tool. A call resolves the rule before dispatch: anaskis refused, and adenyis refused, with no gws call and no prompt. With a session,describereports each method's class and resolvedpermission. events_listis a read, so it is allowed at everyaccessvalue, as the other reads are.- A saved "Always allow" no longer authorises an ad-hoc script. A script's grant is a rule in config, or a Jobs run
session;docs/scripting.mdsays so, and names the Jobs one-off as the way to get an approval-bound grant. - The permissions a script's calls assert now carry the same tool source id as a model call, so an inner
ask, such
as a plan's read of an event's guests, is refused and named instead of waiting for a prompt. - The gws binary is no longer an npm optional package. The plugin downloads the pinned, unmodified
gws0.22.5 for the platform on first use from this repository's GitHub Release, checks it against the release manifest and the upstream SHA-256, and caches it. The download is a change underaccess:alldownloads,ask-changesasks, andread-onlyrefuses with/gws-installas the next step. /gws-installdownloads and verifies the binary on request.- Setup runs no binary and makes no network call; the first tool call resolves it.
gws_statusreports the cached binary, or an empty path when none is cached, and never downloads. - The licence and notice of the gws executable ship in
licenses/gws. - Installed from GitHub, not npm:
opencode plugin add github:joe-broadhead/opencode-gws#v0.0.0. The npm releases below are history.
Fixed
/gws-statussays whataccessdecides for a pending commit: it runs without a prompt at"all", asks at"ask-changes", and is denied at"read-only". The line used to say approval happens only in the permission prompt, which is false at"all".
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. - 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.