app
Adom Google
Public Made by Adomby adom
Drive your whole Google Workspace from the terminal, run by your AI. Read Gmail, write Google Docs, build Google Sheets and Google Slides, search Google Drive, manage Google Calendar and Google Tasks, and post to Google Chat, plus any Google API and a zero-setup personal Gmail.
← Commit history
SKILL.md+7−14@@ -15,20 +15,6 @@ adom-google modular wrapper: gmail · contacts · (drive/calendar = +1 sc Google REST APIs called directly (gmail.googleapis.com, people.googleapis.com, …) ``` --## Displaying this app (REQUIRED — read before showing anything)--When showing the user a Sheet/Doc/Slide/email, open it on a proper Adom surface: the user's real signed-in browser (Adom browser extension) is BEST for Google URLs; a Hydrogen webview (`webview` skill) works for share-link previews.-- **NEVER open this app in VS Code's "Simple Browser"** — that is NOT what "webview" means- in the Adom ecosystem. Simple Browser has no live channel, no console read-back, and no- AI drivability; using it is a bug.-- The Adom surfaces for showing an app are: **wv** — a Hydrogen webview panel (load the- `webview` skill from adom-workspace-control and follow it; inside HD this is HD's pane- tab), **pup** — a pup window (`pup` skill), **nb** — the user's real signed-in browser (Adom browser- extension), and **hdbw** — HD's standalone built-in Tauri browser window- (picker: "HD Browser Window", destination id `webview-window`, only under Hydrogen- Desktop). Pick per the situation; Simple Browser is NEVER one of them.- ## Why REST-direct (not a base-CLI shim) We evaluated wrapping a base CLI — Google's `googleworkspace/cli` (`gws`, Rust,@@ -87,6 +73,13 @@ presentations, calendar, tasks, chat.messages, chat.spaces.readonly`) plus the g `adom-google api <url>` passthrough for **any** Google API. It prints a Google consent URL; the user clicks **Allow** once. +> ⚠ **Open the consent URL as ONE value — never unquoted in a shell.** It contains `&`; if you+> drop it into an unquoted shell/open command the shell truncates it at the first `&`, Google+> receives only `client_id`, and shows *"Error 400: invalid_request — missing response_type"*+> (this bit real users). Safe: hand the URL to a browser tool with the URL **inside JSON**+> (`adom-desktop nbrowser_open_window '{"sessionId":"gauth","url":"<URL>"}'`), or single-quote the+> whole URL. The `adom-google auth` output prints the ready-to-paste safe command for you.+ > ⏱ **The user has ~10 minutes to click Allow.** The gateway keeps the sign-in session alive > with a WebSocket heartbeat, so there's no rush. If they ever see a "Session Expired" page, just > re-run `adom-google auth`.
bin/adom-google+28−4@@ -258,6 +258,9 @@ Hint: Check the current provider any time with: adom-google provider show""" SETUP_HINT = """ERROR: adom-google is not authorized yet (no Google token for this container). Hint: Just run: adom-google auth Hint: It prints a Google consent URL — open it in the user's browser; they click Allow ONCE.+Hint: ⚠ That URL contains '&'. Open it as ONE value (a browser tool with the URL inside JSON, or a+Hint: SINGLE-QUOTED shell arg). If you drop it UNQUOTED into a shell, it truncates at the first+Hint: '&' and Google shows "Error 400: missing response_type". The auth output shows the safe way. Hint: Default access is FULL Workspace (Gmail, Contacts, Drive, Sheets, Docs, Slides, Calendar, Hint: Tasks, Chat + any Google API). There is NO mode question to ask the user — full is the Hint: default so the tool "just works".@@ -869,6 +872,25 @@ def _store_broker_tokens(cfg, tokens, scopes, mode): _save(cfg) +def _print_open_url(auth_link, step="1"):+ """Present the consent URL so an AI/shell can't mangle it. The URL is full of '&'; dropped+ UNQUOTED into a shell/open command the shell cuts it at the first '&', Google then receives+ only client_id and errors 'invalid_request: missing response_type' (issue #3). So lead with a+ browser-tool one-liner that carries the URL inside a JSON string (safe), and loudly warn to+ single-quote it otherwise."""+ safe = json.dumps({"sessionId": "gauth", "url": auth_link})+ print(f"{step}) Open this consent URL in the user's browser and have them click Allow.\n")+ print(" ⚠ The URL contains '&'. Open it as ONE whole value. Do NOT drop it UNQUOTED into a")+ print(" shell/open command — the shell cuts it at the first '&', Google then gets only")+ print(" client_id and shows \"Error 400: invalid_request — missing response_type\".")+ print(" SAFEST (URL rides inside JSON, so '&' can't truncate it) — paste this as-is:\n")+ print(" adom-desktop nbrowser_open_window '" + safe + "'")+ print(" # opens the user's real logged-in Chrome (add --target <name> if >1 Adom Desktop).")+ print(" # logged-out window instead: browser_open_window (add \"profile\":\"default\").\n")+ print(" Or paste the URL into the browser by hand (if via a shell, SINGLE-QUOTE the whole URL):\n")+ print(" " + auth_link + "\n")++ def cmd_auth(a): cfg = _maybe_load_raw() or {} # FULL is the default (no first-run mode quiz — issue #2). `--safe` is an advanced opt-in@@ -896,8 +918,7 @@ def cmd_auth(a): print(f"OAuth Gateway flow — {mode.upper()} access" + (" (full Workspace: Gmail/Contacts/Drive/Sheets/Docs/Slides/Calendar/Tasks/Chat + delete)" if mode == "full" else " (safe: only files this app makes; no 'delete all')") + ".\n")- print("1) Open this URL and approve with your Google Workspace account:\n")- print(" " + auth_link + "\n")+ _print_open_url(auth_link) # The gateway keeps the sign-in session alive for the full 10 min via a WS heartbeat # (gateway fix for issue #1), so the client waits the same 10 min. print("2) Waiting for your approval — you have ~10 minutes, no rush.")@@ -944,9 +965,12 @@ def _auth_manual(cfg, scopes, mode): "client_id": cid, "redirect_uri": MANUAL_REDIRECT, "response_type": "code", "scope": " ".join(scopes), "access_type": "offline", "prompt": "consent", }+ manual_link = AUTH_URL + "?" + urllib.parse.urlencode(params) print(f"Manual (desktop-client) flow — {mode.upper()} mode.\n")- print("1) Open this URL and approve:\n")- print(" " + AUTH_URL + "?" + urllib.parse.urlencode(params))+ print("1) Open this URL and approve. ⚠ It contains '&' — SINGLE-QUOTE the whole URL if you use")+ print(" any shell/open command, or the shell truncates it at the first '&' and Google shows")+ print(" \"Error 400: invalid_request — missing response_type\":\n")+ print(" " + manual_link) print("\n2) The page will fail to load (expected). Copy the `code` value from the address") print(" bar, then run:\n\n adom-google auth-code '<paste-code-here>'")
package.json+4−4@@ -1,9 +1,9 @@ { "slug": "adom-google",- "version": "0.7.8",+ "version": "0.7.9", "type": "app", "license": "MIT",- "description": "Drive your whole Google Workspace from the terminal \u2014 Gmail, Contacts, Drive, Sheets, Docs, Slides, Calendar, Tasks, Google Chat, plus a generic `api` passthrough to hit ANY Google API. Open source, ships with NO OAuth provider baked in: point it at your own token-broker gateway (`provider set`), buy a managed one, or \u2014 Adom staff \u2014 install the private adom-google-adom provider. One-click OAuth, no client secret on your machine. Full Workspace access by default (one Allow click, no mode quiz).",+ "description": "Drive your whole Google Workspace from the terminal — Gmail, Contacts, Drive, Sheets, Docs, Slides, Calendar, Tasks, Google Chat, plus a generic `api` passthrough to hit ANY Google API. Open source, ships with NO OAuth provider baked in: point it at your own token-broker gateway (`provider set`), buy a managed one, or — Adom staff — install the private adom-google-adom provider. One-click OAuth, no client secret on your machine. Full Workspace access by default (one Allow click, no mode quiz).", "keywords": [ "adom-google", "google-workspace",@@ -32,7 +32,7 @@ "hero": { "path": "screenshots/hero-grid-v4.png" },- "discovery_pitch": "Drive your whole Google Workspace from the terminal through your AI \u2014 read Gmail (and its attachments), search Drive, build Sheets/Docs/Slides, manage Calendar & Tasks, and post to Google Chat as yourself. One OAuth, any Google API.",+ "discovery_pitch": "Drive your whole Google Workspace from the terminal through your AI — read Gmail (and its attachments), search Drive, build Sheets/Docs/Slides, manage Calendar & Tasks, and post to Google Chat as yourself. One OAuth, any Google API.", "discovery_triggers": [ "read my gmail", "read my email",@@ -114,4 +114,4 @@ "prompt": "post to Google Chat that the boards shipped" } ]-}+}
page.json+1−1@@ -4,7 +4,7 @@ "slug": "adom-google", "title": "Adom Google", "brief": "Drive your whole Google Workspace from the terminal — Gmail, Drive, Sheets, Docs, Slides, Calendar, Tasks, Chat + any Google API.",- "version": "0.7.8",+ "version": "0.7.9", "visibility": "public", "install": { "binary_name": "adom-google"