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
Merge PR #45: chat send: stamp clientAssignedMessageId so agent-sent messages are detectable
2 files changed
+20−4
SKILL.md+8@@ -193,6 +193,14 @@ adom-google chat send --to <space-id|email> "here's the clip" --attach demo.webm # attaches it. Repeatable for several files. Text is optional when attaching. Same # chat.messages scope as a text post, so no re-consent. adom-google chat read --from <space-id|email> [--limit N] [--json] # recent messages+# Every post is stamped clientAssignedMessageId=client-agent-<20 hex> so the RECEIVING+# side can tell an agent-sent message from a hand-typed one. Chat shows an "Adom Google"+# attribution badge in the UI for anything posted through the API with user credentials,+# but exposes that attribution NOWHERE in the REST API — not on Message/User/Annotation,+# not in searchMessages filters, not in the Workspace Events payload, not in the Admin SDK+# chat audit log. The marker is the only durable signal, and it is invisible in the UI.+# Read it back with: adom-google api <message-url> | jq -r .clientAssignedMessageId+# Suppress it with --no-agent-marker. adom-google auth --admin # ALSO request the Workspace ADMIN bundle in the SAME consent: # admin.directory.group + .group.member + .user.readonly + apps.groups.settings.
bin/adom-google+12−4@@ -789,11 +789,19 @@ def cmd_chat_send(a): attachments = [_chat_upload(cfg, space, p) for p in (getattr(a, "attach", None) or [])] if attachments: body["attachment"] = [{"attachmentDataRef": ref} for ref in attachments]- params = None+ params = {} if a.thread: body["thread"] = {"threadKey": a.thread}- params = {"messageReplyOption": "REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"}- msg = _chat(cfg, f"{space}/messages", method="POST", body=body, params=params)+ params["messageReplyOption"] = "REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD"+ # Stamp agent-sent messages so the RECEIVING side can detect them exactly.+ # Google Chat renders an app-attribution badge ("Adom Google") in the UI for+ # anything posted through the API with user credentials, but exposes that+ # attribution NOWHERE in the REST API. A custom clientAssignedMessageId is+ # the only durable, machine-readable signal, and it is invisible in the UI.+ # Opt out with --no-agent-marker.+ if not getattr(a, "no_agent_marker", False):+ params["messageId"] = "client-agent-" + secrets.token_hex(10)+ msg = _chat(cfg, f"{space}/messages", method="POST", body=body, params=params or None) uri = sp.get("spaceUri", "") who = (msg.get("sender") or {}).get("displayName") or "you" print(msg.get("name", "") + (f" · {uri}" if uri else ""))@@ -1937,7 +1945,7 @@ def main(): ch = sub.add_parser("chat"); chx = ch.add_subparsers(dest="sub") x = chx.add_parser("spaces"); x.add_argument("--json", action="store_true"); x.set_defaults(fn=cmd_chat_spaces) x = chx.add_parser("dm"); x.add_argument("email"); x.add_argument("--json", action="store_true"); x.set_defaults(fn=cmd_chat_dm)- x = chx.add_parser("send"); x.add_argument("--to", required=True, help="spaces/XXX id OR an email (auto-resolves the DM)"); x.add_argument("text", nargs="?", default="", help="message text, or '-' for stdin, or '@file' (optional when --attach is used)"); x.add_argument("--thread", help="threadKey for a threaded reply"); x.add_argument("--attach", action="append", metavar="PATH", help="attach a local file (image/video/PDF/any); repeatable"); x.set_defaults(fn=cmd_chat_send)+ x = chx.add_parser("send"); x.add_argument("--to", required=True, help="spaces/XXX id OR an email (auto-resolves the DM)"); x.add_argument("text", nargs="?", default="", help="message text, or '-' for stdin, or '@file' (optional when --attach is used)"); x.add_argument("--thread", help="threadKey for a threaded reply"); x.add_argument("--attach", action="append", metavar="PATH", help="attach a local file (image/video/PDF/any); repeatable"); x.add_argument("--no-agent-marker", action="store_true", help="don't stamp clientAssignedMessageId=client-agent-*"); x.set_defaults(fn=cmd_chat_send) x = chx.add_parser("read"); x.add_argument("--from", dest="frm", required=True, help="spaces/XXX id OR an email"); x.add_argument("--limit", type=int, default=20); x.add_argument("--json", action="store_true"); x.set_defaults(fn=cmd_chat_read) # Calendar (issue #662)