Repository navigation
Google operator CLIs: dapier gmail, gdrive, calendar - #36
Merged
Merged
Conversation
/api/agent/gmail/* and /api/agent/gdrive/* operator routes over the stored Google connections, mirroring the slack agent-proxy pattern: token stays server-side, every route is operator-gated and audited. Account selection is the single gate (google_accounts): --account matches a verified email, connection id, or unique fragment; multiple connected accounts require the explicit choice and ambiguity is rejected with the candidates — never a silent default. Gmail: search/list/read messages, threads, labels, attachments, drafts create/update/delete/send with attachments, direct send, replies as direct send or reply draft (In-Reply-To/References/Re:/threadId preserved, reply-all minus self), mark read/unread/archive/trash/label. MIME rides the engine's raw builder. Drive: list/search/meta, download/export (native docs to PDF/CSV/PNG), multipart upload, update, copy, move, share, trash (recoverable or --permanent), restore, mkdir; files move as base64 through the JSON API. Granted scopes are honored as-is — provider 403s relay with a connections-edit --scopes hint.
Thin JSON clients over the new agent routes (the slack pattern): every command carries --account, bodies ride stdin/--file, attachments are read from disk as base64 (PATH[;MIME]), downloads land on disk, pagination is bounded with --page-token passthrough, and write verbs accept --preview — the exact request body prints with payloads shown as sizes, nothing is sent. gdrive covers list/search/meta/download/upload/update/copy/move/ share/trash/restore/mkdir; gmail covers accounts/search/list/read/ attachment/threads/labels/mark/send/reply/draft.
/api/agent/calendar/* and dapier calendar: accounts, the account's calendar list, events list/search in bounded windows (time_min/time_max required, inverted ranges rejected, span capped at 366 days, occurrences expanded in start order), one-event reads, free/busy, and event create/update/delete — structured fields (summary, ISO start/end, timezone, attendees, RRULE recurrence, reminder overrides, attachment links, all-day) or a reviewed JSON event resource via --event-file, never both. Guest email is explicit: every write carries Google's sendUpdates and defaults to none, so invitations never go out by accident; sendUpdates is validated against all/externalOnly/none. Same account-selection gate, operator gating, audit, and provider-403 scope hint as gmail/gdrive.
Document the new nouns, the explicit --account rules, scope-honoring behavior, sendUpdates discipline, --preview, and drive restore; register the new command groups in the dapier-cli skill with recipes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Operator CLI nouns
dapier gmail,dapier gdrive,dapier calendarover new operator-gated/api/agent/gmail|gdrive|calendar/*routes, following the existingdapier slackagent-proxy pattern (connection tokens stay server-side; every route operator-gated + audited).Account selection (all three nouns):
--account <email-or-connection-id>on every operation — matched by verified email, connection id, or unique fragment. With several connected Google accounts the choice is required; ambiguous or missing selections are rejected naming the candidates. No silent defaults, no wrong-account writes.Gmail: search/list/read messages, threads, labels, attachments (save by id or bulk), mark read/unread/archive/trash/label, drafts create/update/delete with attachments, direct send with attachments, replies as direct send or
--draftreply draft (In-Reply-To/References,Re:subject, original threadId; reply-all excludes self), send existing draft.Drive: list/search/meta, download/export (Google-native → PDF/CSV/PNG,
--export-mime), upload (file/stdin), update (rename/content), copy, move, share (permissions), trash (recoverable,--permanentdestroys), restore, mkdir.Calendar: calendar list, events list/search in bounded windows (
--time-min/--time-maxrequired, ≤ 366 days, occurrences expanded), free/busy, create/update/delete with attendees, RRULE recurrence, timezones, reminder overrides, attachment links, all-day form, or reviewed JSON via--event-file. Guest email is explicit: writes carry Google'ssendUpdates, defaulting tonone.Previews: write verbs accept
--preview— the exact JSON request body prints (payloads shown as sizes, not bytes), nothing is sent.Safety
dapier connections edit --scopeshint.Tests
tests/test_google_account_selection.py— listing, id/email/fragment resolution, ambiguity rejection, disconnected-duplicate handling, no-account errors.tests/test_gmail_gdrive_ops_cli.py— wrong-account isolation (per-connection bearers), provider errors (403 hint, 404), MIME construction (Unicode subject/body, binary attachment round-trip), reply threading (In-Reply-To/References/reply-all), draft lifecycle, modify label mapping, drive multipart upload, export/download, share/trash/restore/move semantics, route gating/audit/error mapping.tests/test_gmail_gdrive_cli.py,tests/test_calendar_agent_cli.py— thin-client path/body shapes,--previewsends nothing, calendar window bounds and sendUpdates discipline.make testgreen (4792 passed).Parity
No console surface added; the console manages the underlying Google connections via
/api/admin/*as before. These nouns follow thedapier slackoperator-agent category; parity audit re-run (no console call to the new routes, no console-only action introduced).