gws-axi 0.8.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -3
- package/dist/src/auth/scopes.d.ts +2 -0
- package/dist/src/auth/scopes.js +19 -2
- package/dist/src/auth/scopes.js.map +1 -1
- package/dist/src/commands/docs/download.d.ts +9 -1
- package/dist/src/commands/docs/download.js +157 -6
- package/dist/src/commands/docs/download.js.map +1 -1
- package/dist/src/commands/docs/download.test.d.ts +1 -0
- package/dist/src/commands/docs/download.test.js +41 -0
- package/dist/src/commands/docs/download.test.js.map +1 -0
- package/dist/src/commands/docs.js +4 -0
- package/dist/src/commands/docs.js.map +1 -1
- package/dist/src/commands/drive/activity.d.ts +25 -0
- package/dist/src/commands/drive/activity.js +336 -0
- package/dist/src/commands/drive/activity.js.map +1 -0
- package/dist/src/commands/drive/activity.test.d.ts +1 -0
- package/dist/src/commands/drive/activity.test.js +91 -0
- package/dist/src/commands/drive/activity.test.js.map +1 -0
- package/dist/src/commands/drive/revisions.d.ts +14 -0
- package/dist/src/commands/drive/revisions.js +181 -0
- package/dist/src/commands/drive/revisions.js.map +1 -0
- package/dist/src/commands/drive/revisions.test.d.ts +1 -0
- package/dist/src/commands/drive/revisions.test.js +66 -0
- package/dist/src/commands/drive/revisions.test.js.map +1 -0
- package/dist/src/commands/drive.js +20 -2
- package/dist/src/commands/drive.js.map +1 -1
- package/dist/src/commands/gmail/batch-modify.d.ts +2 -0
- package/dist/src/commands/gmail/batch-modify.js +158 -0
- package/dist/src/commands/gmail/batch-modify.js.map +1 -0
- package/dist/src/commands/gmail/compose.d.ts +24 -0
- package/dist/src/commands/gmail/compose.js +47 -0
- package/dist/src/commands/gmail/compose.js.map +1 -0
- package/dist/src/commands/gmail/compose.test.d.ts +1 -0
- package/dist/src/commands/gmail/compose.test.js +75 -0
- package/dist/src/commands/gmail/compose.test.js.map +1 -0
- package/dist/src/commands/gmail/draft.d.ts +3 -0
- package/dist/src/commands/gmail/draft.js +148 -0
- package/dist/src/commands/gmail/draft.js.map +1 -0
- package/dist/src/commands/gmail/filters.d.ts +6 -0
- package/dist/src/commands/gmail/filters.js +305 -0
- package/dist/src/commands/gmail/filters.js.map +1 -0
- package/dist/src/commands/gmail/label-ops.d.ts +6 -0
- package/dist/src/commands/gmail/label-ops.js +208 -0
- package/dist/src/commands/gmail/label-ops.js.map +1 -0
- package/dist/src/commands/gmail/labels-shared.d.ts +23 -0
- package/dist/src/commands/gmail/labels-shared.js +61 -0
- package/dist/src/commands/gmail/labels-shared.js.map +1 -0
- package/dist/src/commands/gmail/labels-shared.test.d.ts +1 -0
- package/dist/src/commands/gmail/labels-shared.test.js +59 -0
- package/dist/src/commands/gmail/labels-shared.test.js.map +1 -0
- package/dist/src/commands/gmail/modify.d.ts +2 -0
- package/dist/src/commands/gmail/modify.js +130 -0
- package/dist/src/commands/gmail/modify.js.map +1 -0
- package/dist/src/commands/gmail/read.d.ts +11 -1
- package/dist/src/commands/gmail/read.js +206 -5
- package/dist/src/commands/gmail/read.js.map +1 -1
- package/dist/src/commands/gmail/read.test.d.ts +1 -0
- package/dist/src/commands/gmail/read.test.js +54 -0
- package/dist/src/commands/gmail/read.test.js.map +1 -0
- package/dist/src/commands/gmail/search.js +2 -30
- package/dist/src/commands/gmail/search.js.map +1 -1
- package/dist/src/commands/gmail.js +39 -53
- package/dist/src/commands/gmail.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Agent-ergonomic CLI for Google Workspace — Gmail, Calendar, Docs, Drive, and S
|
|
|
4
4
|
|
|
5
5
|
Designed for use by AI agents. Every response is structured, every error names a specific fix, and write operations lock to the explicit account when multiple are authenticated — so two agents in parallel sessions can't silently touch the wrong mailbox.
|
|
6
6
|
|
|
7
|
-
> **Status:** Read coverage is in across all five services — Calendar, Gmail, Docs, Drive, and Slides
|
|
7
|
+
> **Status:** Read coverage is in across all five services — Calendar, Gmail, Docs, Drive, and Slides. **Calendar** and **Gmail** both have full write support: Calendar does `create` / `update` / `delete` / `respond`, and Gmail does triage (`modify`, `batch-modify`), drafting (`draft`), label CRUD (`label-create` / `label-update` / `label-delete`), and server-side filters (`filter-create` / `filter-delete` / `filter-list`). Gmail **`send` is intentionally out of scope** — gws-axi drafts mail for human review but never sends it. Docs writes (`append`, `insert-text`, `delete-range`) are the next frontier. Auth (including a single-developer `auth publish` walkthrough that retires the 7-day Testing-token expiry), doctor with live per-account API probes, and multi-account write-protection are stable.
|
|
8
8
|
|
|
9
9
|
## Requirements
|
|
10
10
|
|
|
@@ -123,6 +123,8 @@ Writes default `--send-updates` to `none` so agent-created events don't spam att
|
|
|
123
123
|
|
|
124
124
|
### Gmail
|
|
125
125
|
|
|
126
|
+
**Reads:**
|
|
127
|
+
|
|
126
128
|
```bash
|
|
127
129
|
gws-axi gmail search # in:inbox by default
|
|
128
130
|
gws-axi gmail search --query "from:alice has:attachment"
|
|
@@ -134,8 +136,41 @@ gws-axi gmail labels # list labels with IDs
|
|
|
134
136
|
gws-axi gmail download <message-id> <attachment-id> # fetch attachment bytes
|
|
135
137
|
```
|
|
136
138
|
|
|
139
|
+
**Writes** (triage, drafting, labels, filters — but never *send*):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Triage — Gmail state IS labels, so archive/read/star are label edits:
|
|
143
|
+
gws-axi gmail modify <message-id> --remove-label INBOX # archive
|
|
144
|
+
gws-axi gmail modify <message-id> --remove-label UNREAD # mark read
|
|
145
|
+
gws-axi gmail modify <message-id> --add-label STARRED # star
|
|
146
|
+
gws-axi gmail modify <message-id> --add-label "Work/Clients" --remove-label INBOX
|
|
147
|
+
gws-axi gmail modify <thread-id> --thread --remove-label UNREAD # whole thread
|
|
148
|
+
|
|
149
|
+
# Bulk triage by query:
|
|
150
|
+
gws-axi gmail batch-modify --query "from:news@x.com" --remove-label INBOX
|
|
151
|
+
gws-axi gmail batch-modify --query "is:unread older_than:30d" --remove-label UNREAD
|
|
152
|
+
|
|
153
|
+
# Drafts (composed for you; you send from Gmail):
|
|
154
|
+
gws-axi gmail draft --to alice@x.com --subject "Re: budget" --body "Approved."
|
|
155
|
+
gws-axi gmail draft --to a@x.com,b@x.com --subject Hi --body-file ./note.txt --thread <id>
|
|
156
|
+
|
|
157
|
+
# Label management:
|
|
158
|
+
gws-axi gmail label-create --name "Work/Clients"
|
|
159
|
+
gws-axi gmail label-update <label-id|name> --name "Archive"
|
|
160
|
+
gws-axi gmail label-delete <label-id|name>
|
|
161
|
+
|
|
162
|
+
# Server-side auto-sort filters:
|
|
163
|
+
gws-axi gmail filter-list
|
|
164
|
+
gws-axi gmail filter-create --from news@x.com --remove-label INBOX --add-label News
|
|
165
|
+
gws-axi gmail filter-delete <filter-id>
|
|
166
|
+
```
|
|
167
|
+
|
|
137
168
|
Bodies are decoded per declared `Content-Type` charset (UTF-8, latin-1, ascii, utf-16). HTML-only messages convert to markdown via turndown. Address headers parse with `addressparser` so display names with commas don't get split.
|
|
138
169
|
|
|
170
|
+
**On `send`:** gws-axi has no `send` command by design — an agent can triage, label, and draft replies, but a human reviews and sends from Gmail. This is a guardrail against *accidental* sends, not a hard security boundary (the OAuth token is send-capable; there is no Gmail scope that grants drafting + label edits while withholding send). `gws-axi gmail send` returns a `NOT_SUPPORTED` error pointing at `draft`.
|
|
171
|
+
|
|
172
|
+
**Scope note:** the filter commands need the `gmail.settings.basic` scope, which `gmail.modify` does not include. Accounts authenticated before this release will get a `SCOPE_MISSING` (403) on filter commands until you re-run `gws-axi auth login --account <email>` once to re-consent.
|
|
173
|
+
|
|
139
174
|
### Docs
|
|
140
175
|
|
|
141
176
|
```bash
|
|
@@ -198,8 +233,9 @@ help[2]:
|
|
|
198
233
|
|
|
199
234
|
## Known issues & roadmap
|
|
200
235
|
|
|
201
|
-
- **Gmail
|
|
202
|
-
- **Docs writes** (`append`, `insert-text`, `delete-range`, etc.): scaffolded as `NOT_IMPLEMENTED`.
|
|
236
|
+
- **Gmail `send`**: intentionally unsupported — gws-axi drafts mail but leaves sending to a human in the Gmail UI. See the Gmail section above.
|
|
237
|
+
- **Docs writes** (`append`, `insert-text`, `delete-range`, etc.): scaffolded as `NOT_IMPLEMENTED`. The next frontier.
|
|
238
|
+
- **Drive/Slides writes**: still scaffolded as `NOT_IMPLEMENTED` (reads are complete).
|
|
203
239
|
- **Testing-mode tokens** still expire every 7 days *if* you haven't published your OAuth app yet. Run `gws-axi auth publish` for the walkthrough — it covers the single-developer Production flow and removes the expiry once you've re-auth'd each account.
|
|
204
240
|
|
|
205
241
|
## Contributing
|
|
@@ -6,8 +6,10 @@ export declare const SERVICE_SCOPES: {
|
|
|
6
6
|
readonly drive: "https://www.googleapis.com/auth/drive";
|
|
7
7
|
readonly slides: "https://www.googleapis.com/auth/presentations";
|
|
8
8
|
};
|
|
9
|
+
export declare const ADDITIONAL_SCOPES: readonly ["https://www.googleapis.com/auth/gmail.settings.basic", "https://www.googleapis.com/auth/drive.activity.readonly"];
|
|
9
10
|
export type ServiceName = keyof typeof SERVICE_SCOPES;
|
|
10
11
|
export declare const SERVICES: ServiceName[];
|
|
11
12
|
export declare const REQUIRED_APIS: Record<ServiceName, string>;
|
|
13
|
+
export declare const ADDITIONAL_APIS: readonly ["driveactivity.googleapis.com"];
|
|
12
14
|
export declare function allScopes(): string[];
|
|
13
15
|
export declare function allApis(): string[];
|
package/dist/src/auth/scopes.js
CHANGED
|
@@ -6,6 +6,19 @@ export const SERVICE_SCOPES = {
|
|
|
6
6
|
drive: "https://www.googleapis.com/auth/drive",
|
|
7
7
|
slides: "https://www.googleapis.com/auth/presentations",
|
|
8
8
|
};
|
|
9
|
+
// Scopes layered on top of the representative per-service scope above.
|
|
10
|
+
// gmail.settings.basic is required for Gmail filter management
|
|
11
|
+
// (users.settings.filters.*); it is NOT covered by gmail.modify. Kept
|
|
12
|
+
// separate so the per-service probe/health checks keep keying off the
|
|
13
|
+
// single representative scope in SERVICE_SCOPES.
|
|
14
|
+
export const ADDITIONAL_SCOPES = [
|
|
15
|
+
"https://www.googleapis.com/auth/gmail.settings.basic",
|
|
16
|
+
// drive.activity.readonly powers `drive activity`; it is read-only and NOT
|
|
17
|
+
// implied by auth/drive, so it must be requested explicitly. Incremental on
|
|
18
|
+
// the already-restricted drive scope, so it doesn't worsen the consent
|
|
19
|
+
// posture. Pre-existing accounts must re-auth once to gain it.
|
|
20
|
+
"https://www.googleapis.com/auth/drive.activity.readonly",
|
|
21
|
+
];
|
|
9
22
|
export const SERVICES = [
|
|
10
23
|
"gmail",
|
|
11
24
|
"calendar",
|
|
@@ -20,10 +33,14 @@ export const REQUIRED_APIS = {
|
|
|
20
33
|
drive: "drive.googleapis.com",
|
|
21
34
|
slides: "slides.googleapis.com",
|
|
22
35
|
};
|
|
36
|
+
// APIs required beyond the per-service REQUIRED_APIS map. The Drive Activity
|
|
37
|
+
// API is a distinct service backing the `drive activity` command — it must be
|
|
38
|
+
// enabled separately from the Drive API.
|
|
39
|
+
export const ADDITIONAL_APIS = ["driveactivity.googleapis.com"];
|
|
23
40
|
export function allScopes() {
|
|
24
|
-
return [...BASE_SCOPES, ...Object.values(SERVICE_SCOPES)];
|
|
41
|
+
return [...BASE_SCOPES, ...Object.values(SERVICE_SCOPES), ...ADDITIONAL_SCOPES];
|
|
25
42
|
}
|
|
26
43
|
export function allApis() {
|
|
27
|
-
return Object.values(REQUIRED_APIS);
|
|
44
|
+
return [...Object.values(REQUIRED_APIS), ...ADDITIONAL_APIS];
|
|
28
45
|
}
|
|
29
46
|
//# sourceMappingURL=scopes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../../src/auth/scopes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,8CAA8C;IACrD,QAAQ,EAAE,0CAA0C;IACpD,IAAI,EAAE,2CAA2C;IACjD,KAAK,EAAE,uCAAuC;IAC9C,MAAM,EAAE,+CAA+C;CAC/C,CAAC;AAIX,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;IACP,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,8BAA8B;IACxC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAC7B,MAAM,EAAE,uBAAuB;CAChC,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../../src/auth/scopes.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAU,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,8CAA8C;IACrD,QAAQ,EAAE,0CAA0C;IACpD,IAAI,EAAE,2CAA2C;IACjD,KAAK,EAAE,uCAAuC;IAC9C,MAAM,EAAE,+CAA+C;CAC/C,CAAC;AAEX,uEAAuE;AACvE,+DAA+D;AAC/D,sEAAsE;AACtE,sEAAsE;AACtE,iDAAiD;AACjD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,sDAAsD;IACtD,2EAA2E;IAC3E,4EAA4E;IAC5E,uEAAuE;IACvE,+DAA+D;IAC/D,yDAAyD;CACjD,CAAC;AAIX,MAAM,CAAC,MAAM,QAAQ,GAAkB;IACrC,OAAO;IACP,UAAU;IACV,MAAM;IACN,OAAO;IACP,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAgC;IACxD,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,8BAA8B;IACxC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAC7B,MAAM,EAAE,uBAAuB;CAChC,CAAC;AAEF,6EAA6E;AAC7E,8EAA8E;AAC9E,yCAAyC;AACzC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,8BAA8B,CAAU,CAAC;AAEzE,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,GAAG,iBAAiB,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -1,2 +1,10 @@
|
|
|
1
|
-
export declare const DOWNLOAD_HELP = "usage: gws-axi docs download <documentId> [flags]\nargs[1]:\n <documentId> The Google Doc / Drive file ID (from the URL after /d/)\nflags[
|
|
1
|
+
export declare const DOWNLOAD_HELP = "usage: gws-axi docs download <documentId> [flags]\nargs[1]:\n <documentId> The Google Doc / Drive file ID (from the URL after /d/)\nflags[4]:\n --out <path> Where to save (default: ./<sanitized file name>; pass a\n directory to save inside with the native name)\n --as <mime> Export format for native Google files (default: docx for\n Docs, xlsx for Sheets, pptx for Slides, png for Drawings;\n text/markdown when --revision is set). Ignored for\n uploaded files (they download as-is).\n --revision <id> Download a specific historical revision (id from\n `gws-axi drive revisions <id>`) instead of the head.\n Native files export via that revision's links\n (markdown by default); binary files return the exact\n stored bytes for that revision.\n --account <email> Account override when 2+ are configured\nexamples:\n gws-axi docs download 1RxHZ...\n gws-axi docs download 1RxHZ... --out /tmp/source.docx\n gws-axi docs download 1Native... --as application/pdf --out ./spec.pdf\n gws-axi docs download 1Native... --revision 250\nnotes:\n Works on any Drive file, not just docs. Native Google files are exported\n on the server side (via Drive files.export); uploaded files (.docx, .pdf,\n images, etc.) are downloaded as-is. After download, agents can inspect\n the file with tools like `file`, `pandoc`, `textutil -convert html`,\n or language-specific parsers for the file's format.\n --revision content for native files is a relevance preview (markdown by\n default, lossy); binary revision content may be unavailable if it was\n purged (only pinned/keepForever revisions retain old content).\n";
|
|
2
|
+
interface ParsedFlags {
|
|
3
|
+
documentId: string;
|
|
4
|
+
out: string | undefined;
|
|
5
|
+
as: string | undefined;
|
|
6
|
+
revision: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseFlags(args: string[]): ParsedFlags;
|
|
2
9
|
export declare function docsDownloadCommand(account: string, args: string[]): Promise<string>;
|
|
10
|
+
export {};
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
import { writeFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname, extname } from "node:path";
|
|
3
3
|
import { AxiError } from "axi-sdk-js";
|
|
4
|
-
import { driveClient, translateGoogleError } from "../../google/client.js";
|
|
4
|
+
import { driveClient, oauthClientForAccount, translateGoogleError, } from "../../google/client.js";
|
|
5
5
|
import { joinBlocks, renderHelp, renderObject } from "../../output/index.js";
|
|
6
6
|
import { resolveOutputPath } from "../../util/paths.js";
|
|
7
7
|
export const DOWNLOAD_HELP = `usage: gws-axi docs download <documentId> [flags]
|
|
8
8
|
args[1]:
|
|
9
9
|
<documentId> The Google Doc / Drive file ID (from the URL after /d/)
|
|
10
|
-
flags[
|
|
10
|
+
flags[4]:
|
|
11
11
|
--out <path> Where to save (default: ./<sanitized file name>; pass a
|
|
12
12
|
directory to save inside with the native name)
|
|
13
13
|
--as <mime> Export format for native Google files (default: docx for
|
|
14
|
-
Docs, xlsx for Sheets, pptx for Slides, png for Drawings
|
|
15
|
-
|
|
14
|
+
Docs, xlsx for Sheets, pptx for Slides, png for Drawings;
|
|
15
|
+
text/markdown when --revision is set). Ignored for
|
|
16
|
+
uploaded files (they download as-is).
|
|
17
|
+
--revision <id> Download a specific historical revision (id from
|
|
18
|
+
\`gws-axi drive revisions <id>\`) instead of the head.
|
|
19
|
+
Native files export via that revision's links
|
|
20
|
+
(markdown by default); binary files return the exact
|
|
21
|
+
stored bytes for that revision.
|
|
16
22
|
--account <email> Account override when 2+ are configured
|
|
17
23
|
examples:
|
|
18
24
|
gws-axi docs download 1RxHZ...
|
|
19
25
|
gws-axi docs download 1RxHZ... --out /tmp/source.docx
|
|
20
26
|
gws-axi docs download 1Native... --as application/pdf --out ./spec.pdf
|
|
27
|
+
gws-axi docs download 1Native... --revision 250
|
|
21
28
|
notes:
|
|
22
29
|
Works on any Drive file, not just docs. Native Google files are exported
|
|
23
30
|
on the server side (via Drive files.export); uploaded files (.docx, .pdf,
|
|
24
31
|
images, etc.) are downloaded as-is. After download, agents can inspect
|
|
25
32
|
the file with tools like \`file\`, \`pandoc\`, \`textutil -convert html\`,
|
|
26
33
|
or language-specific parsers for the file's format.
|
|
34
|
+
--revision content for native files is a relevance preview (markdown by
|
|
35
|
+
default, lossy); binary revision content may be unavailable if it was
|
|
36
|
+
purged (only pinned/keepForever revisions retain old content).
|
|
27
37
|
`;
|
|
28
38
|
// Default export mime types for native Google file types.
|
|
29
39
|
const NATIVE_EXPORT_DEFAULTS = {
|
|
@@ -61,10 +71,11 @@ const EXTENSION_BY_MIME = {
|
|
|
61
71
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
|
62
72
|
"application/vnd.oasis.opendocument.text": ".odt",
|
|
63
73
|
};
|
|
64
|
-
function parseFlags(args) {
|
|
74
|
+
export function parseFlags(args) {
|
|
65
75
|
let documentId;
|
|
66
76
|
let out;
|
|
67
77
|
let as;
|
|
78
|
+
let revision;
|
|
68
79
|
for (let i = 0; i < args.length; i++) {
|
|
69
80
|
const arg = args[i];
|
|
70
81
|
const next = args[i + 1];
|
|
@@ -77,6 +88,10 @@ function parseFlags(args) {
|
|
|
77
88
|
as = next;
|
|
78
89
|
i++;
|
|
79
90
|
break;
|
|
91
|
+
case "--revision":
|
|
92
|
+
revision = next;
|
|
93
|
+
i++;
|
|
94
|
+
break;
|
|
80
95
|
default:
|
|
81
96
|
if (!arg.startsWith("--") && documentId === undefined) {
|
|
82
97
|
documentId = arg;
|
|
@@ -86,7 +101,7 @@ function parseFlags(args) {
|
|
|
86
101
|
if (!documentId) {
|
|
87
102
|
throw new AxiError("Missing documentId argument", "VALIDATION_ERROR", ["Usage: gws-axi docs download <documentId>"]);
|
|
88
103
|
}
|
|
89
|
-
return { documentId, out, as };
|
|
104
|
+
return { documentId, out, as, revision };
|
|
90
105
|
}
|
|
91
106
|
export async function docsDownloadCommand(account, args) {
|
|
92
107
|
const flags = parseFlags(args);
|
|
@@ -121,6 +136,12 @@ export async function docsDownloadCommand(account, args) {
|
|
|
121
136
|
}
|
|
122
137
|
const isNative = meta.mimeType.startsWith("application/vnd.google-apps.");
|
|
123
138
|
const nativeDefault = NATIVE_EXPORT_DEFAULTS[meta.mimeType];
|
|
139
|
+
// Revision download takes a distinct path: native files export via the
|
|
140
|
+
// revision's exportLinks (markdown default), binary files fetch the
|
|
141
|
+
// revision's stored bytes via revisions.get(alt=media).
|
|
142
|
+
if (flags.revision) {
|
|
143
|
+
return downloadRevision(api, account, flags, meta, isNative);
|
|
144
|
+
}
|
|
124
145
|
if (isNative && !nativeDefault && !flags.as) {
|
|
125
146
|
throw new AxiError(`No default export format for native mime type ${meta.mimeType}`, "EXPORT_FORMAT_REQUIRED", [
|
|
126
147
|
"Pass --as <mime> to choose an export format",
|
|
@@ -210,4 +231,134 @@ export async function docsDownloadCommand(account, args) {
|
|
|
210
231
|
blocks.push(renderHelp(suggestions));
|
|
211
232
|
return joinBlocks(...blocks);
|
|
212
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Download a specific historical revision's content. Native files export
|
|
236
|
+
* via the revision's exportLinks map (markdown default — this is a
|
|
237
|
+
* relevance preview, not a fidelity-preserving capture); binary files
|
|
238
|
+
* fetch the revision's stored bytes via revisions.get(alt=media).
|
|
239
|
+
*/
|
|
240
|
+
async function downloadRevision(api, account, flags, meta, isNative) {
|
|
241
|
+
const revisionId = flags.revision;
|
|
242
|
+
// Fetch the revision metadata: modifiedTime + (native) exportLinks.
|
|
243
|
+
let revision;
|
|
244
|
+
try {
|
|
245
|
+
const res = await api.revisions.get({
|
|
246
|
+
fileId: flags.documentId,
|
|
247
|
+
revisionId,
|
|
248
|
+
fields: "id,modifiedTime,exportLinks",
|
|
249
|
+
});
|
|
250
|
+
revision = res.data;
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
const translated = translateGoogleError(err, {
|
|
254
|
+
account,
|
|
255
|
+
operation: "drive.revisions.get",
|
|
256
|
+
});
|
|
257
|
+
if (translated.code === "NOT_FOUND") {
|
|
258
|
+
throw new AxiError(`Revision '${revisionId}' not found on file '${flags.documentId}'`, "REVISION_NOT_FOUND", [
|
|
259
|
+
`List valid revisions with \`gws-axi drive revisions ${flags.documentId}\``,
|
|
260
|
+
]);
|
|
261
|
+
}
|
|
262
|
+
throw translated;
|
|
263
|
+
}
|
|
264
|
+
let bytes;
|
|
265
|
+
let effectiveMime;
|
|
266
|
+
let extension;
|
|
267
|
+
const notes = [];
|
|
268
|
+
if (isNative) {
|
|
269
|
+
const links = revision.exportLinks ?? {};
|
|
270
|
+
const requested = flags.as ?? "text/markdown";
|
|
271
|
+
let chosen = requested;
|
|
272
|
+
let url = links[requested];
|
|
273
|
+
// Fallback chain only applies to the default (markdown); an explicit
|
|
274
|
+
// --as that isn't available is an error the caller must resolve.
|
|
275
|
+
if (!url && !flags.as) {
|
|
276
|
+
const fallback = links["text/plain"] ?? Object.values(links)[0];
|
|
277
|
+
const fallbackMime = Object.keys(links).find((k) => links[k] === fallback) ?? "";
|
|
278
|
+
if (fallback) {
|
|
279
|
+
chosen = fallbackMime;
|
|
280
|
+
url = fallback;
|
|
281
|
+
notes.push(`text/markdown not available for this revision — exported as ${fallbackMime} instead`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (!url) {
|
|
285
|
+
throw new AxiError(`Export format ${requested} not available for revision ${revisionId}`, "EXPORT_FORMAT_REQUIRED", [
|
|
286
|
+
`Available formats: ${Object.keys(links).join(", ") || "(none)"}`,
|
|
287
|
+
"Pass a supported --as <mime>",
|
|
288
|
+
]);
|
|
289
|
+
}
|
|
290
|
+
effectiveMime = chosen;
|
|
291
|
+
extension = EXTENSION_BY_MIME[chosen] ?? "";
|
|
292
|
+
// exportLinks are arbitrary URLs (not a googleapis method), so fetch
|
|
293
|
+
// directly with the account's bearer token.
|
|
294
|
+
const auth = await oauthClientForAccount(account);
|
|
295
|
+
const { token } = await auth.getAccessToken();
|
|
296
|
+
const resp = await fetch(url, {
|
|
297
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
298
|
+
});
|
|
299
|
+
if (!resp.ok) {
|
|
300
|
+
throw new AxiError(`Failed to export revision ${revisionId} as ${chosen} (HTTP ${resp.status})`, "REVISION_CONTENT_UNAVAILABLE", [
|
|
301
|
+
`List valid revisions with \`gws-axi drive revisions ${flags.documentId}\``,
|
|
302
|
+
]);
|
|
303
|
+
}
|
|
304
|
+
bytes = Buffer.from(await resp.arrayBuffer());
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
if (flags.as) {
|
|
308
|
+
throw new AxiError(`--as is only valid for native Google files; this is ${meta.mimeType}`, "VALIDATION_ERROR", ["Drop --as to download the binary revision as-is"]);
|
|
309
|
+
}
|
|
310
|
+
effectiveMime = meta.mimeType;
|
|
311
|
+
extension = extname(meta.name) || EXTENSION_BY_MIME[effectiveMime] || "";
|
|
312
|
+
try {
|
|
313
|
+
const res = await api.revisions.get({ fileId: flags.documentId, revisionId, alt: "media" }, { responseType: "arraybuffer" });
|
|
314
|
+
bytes = Buffer.from(res.data);
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
const translated = translateGoogleError(err, {
|
|
318
|
+
account,
|
|
319
|
+
operation: "drive.revisions.get(alt=media)",
|
|
320
|
+
});
|
|
321
|
+
if (translated.code === "NOT_FOUND") {
|
|
322
|
+
throw new AxiError(`Content for revision '${revisionId}' is unavailable — it may have been purged (only pinned/keepForever binary revisions retain old content)`, "REVISION_CONTENT_UNAVAILABLE", [
|
|
323
|
+
`List revisions with \`gws-axi drive revisions ${flags.documentId}\` to see which retain content`,
|
|
324
|
+
]);
|
|
325
|
+
}
|
|
326
|
+
throw translated;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// Default filename suffixes the revision so it never clobbers a head
|
|
330
|
+
// download: "<base>.r<revisionId><ext>".
|
|
331
|
+
const defaultName = `${stripExt(meta.name)}.r${revisionId}${extension}`;
|
|
332
|
+
const outPath = await resolveOutputPath(flags.out, defaultName);
|
|
333
|
+
await mkdir(dirname(outPath), { recursive: true });
|
|
334
|
+
await writeFile(outPath, bytes);
|
|
335
|
+
const blocks = [];
|
|
336
|
+
blocks.push(renderObject({ account }));
|
|
337
|
+
blocks.push(renderObject({
|
|
338
|
+
file: {
|
|
339
|
+
id: flags.documentId,
|
|
340
|
+
name: meta.name,
|
|
341
|
+
source_mime_type: meta.mimeType,
|
|
342
|
+
saved_mime_type: effectiveMime,
|
|
343
|
+
size_bytes: bytes.length,
|
|
344
|
+
revision: revisionId,
|
|
345
|
+
revision_modified: revision.modifiedTime ?? "",
|
|
346
|
+
},
|
|
347
|
+
}));
|
|
348
|
+
blocks.push(renderObject({ saved: outPath }));
|
|
349
|
+
for (const n of notes)
|
|
350
|
+
blocks.push(renderObject({ note: n }));
|
|
351
|
+
const suggestions = [];
|
|
352
|
+
if (isNative) {
|
|
353
|
+
suggestions.push(`Revision exported as ${effectiveMime} (relevance preview) — use --as <mime> for another format`);
|
|
354
|
+
}
|
|
355
|
+
suggestions.push(`List all revisions with \`gws-axi drive revisions ${flags.documentId}\``);
|
|
356
|
+
blocks.push(renderHelp(suggestions));
|
|
357
|
+
return joinBlocks(...blocks);
|
|
358
|
+
}
|
|
359
|
+
/** Strip a trailing extension from a filename, if present. */
|
|
360
|
+
function stripExt(name) {
|
|
361
|
+
const ext = extname(name);
|
|
362
|
+
return ext ? name.slice(0, -ext.length) : name;
|
|
363
|
+
}
|
|
213
364
|
//# sourceMappingURL=download.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../../src/commands/docs/download.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../../src/commands/docs/download.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { AxiError } from "axi-sdk-js";
|
|
3
|
+
import { parseFlags } from "./download.js";
|
|
4
|
+
describe("docs download parseFlags", () => {
|
|
5
|
+
it("parses a bare documentId with defaults", () => {
|
|
6
|
+
const f = parseFlags(["1RxHZ"]);
|
|
7
|
+
expect(f.documentId).toBe("1RxHZ");
|
|
8
|
+
expect(f.out).toBeUndefined();
|
|
9
|
+
expect(f.as).toBeUndefined();
|
|
10
|
+
expect(f.revision).toBeUndefined();
|
|
11
|
+
});
|
|
12
|
+
it("parses --revision", () => {
|
|
13
|
+
const f = parseFlags(["1RxHZ", "--revision", "250"]);
|
|
14
|
+
expect(f.revision).toBe("250");
|
|
15
|
+
});
|
|
16
|
+
it("parses --revision with --as and --out together", () => {
|
|
17
|
+
const f = parseFlags([
|
|
18
|
+
"1RxHZ",
|
|
19
|
+
"--revision",
|
|
20
|
+
"250",
|
|
21
|
+
"--as",
|
|
22
|
+
"application/pdf",
|
|
23
|
+
"--out",
|
|
24
|
+
"./r.pdf",
|
|
25
|
+
]);
|
|
26
|
+
expect(f.revision).toBe("250");
|
|
27
|
+
expect(f.as).toBe("application/pdf");
|
|
28
|
+
expect(f.out).toBe("./r.pdf");
|
|
29
|
+
});
|
|
30
|
+
it("throws VALIDATION_ERROR when documentId is missing", () => {
|
|
31
|
+
try {
|
|
32
|
+
parseFlags(["--revision", "250"]);
|
|
33
|
+
throw new Error("should have thrown");
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
expect(err).toBeInstanceOf(AxiError);
|
|
37
|
+
expect(err.code).toBe("VALIDATION_ERROR");
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=download.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download.test.js","sourceRoot":"","sources":["../../../../src/commands/docs/download.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7B,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,GAAG,UAAU,CAAC;YACnB,OAAO;YACP,YAAY;YACZ,KAAK;YACL,MAAM;YACN,iBAAiB;YACjB,OAAO;YACP,SAAS;SACV,CAAC,CAAC;QACH,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACrC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,IAAI,CAAC;YACH,UAAU,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,CAAE,GAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { docsCommentsCommand, COMMENTS_HELP } from "./docs/comments.js";
|
|
|
4
4
|
import { docsDownloadCommand, DOWNLOAD_HELP } from "./docs/download.js";
|
|
5
5
|
import { docsFindCommand, FIND_HELP } from "./docs/find.js";
|
|
6
6
|
import { docsReadCommand, READ_HELP } from "./docs/read.js";
|
|
7
|
+
import { driveRevisionsCommand, REVISIONS_HELP, } from "./drive/revisions.js";
|
|
7
8
|
// Write subcommands are still stubs but we keep per-command --help text
|
|
8
9
|
// so agents can plan around the future surface.
|
|
9
10
|
const APPEND_HELP = `usage: gws-axi docs append <documentId> --text <markdown> [--tab <id>] [flags]
|
|
@@ -47,6 +48,9 @@ const SUBCOMMANDS = [
|
|
|
47
48
|
{ name: "find", mutation: false, help: FIND_HELP, handler: docsFindCommand },
|
|
48
49
|
{ name: "comments", mutation: false, help: COMMENTS_HELP, handler: docsCommentsCommand },
|
|
49
50
|
{ name: "download", mutation: false, help: DOWNLOAD_HELP, handler: docsDownloadCommand },
|
|
51
|
+
// Alias for `drive revisions` — version history is a Docs-shaped mental
|
|
52
|
+
// model, but the implementation is Drive-wide (any file type).
|
|
53
|
+
{ name: "revisions", mutation: false, help: REVISIONS_HELP, handler: driveRevisionsCommand },
|
|
50
54
|
{ name: "append", mutation: true, help: APPEND_HELP },
|
|
51
55
|
{ name: "insert-text", mutation: true, help: INSERT_TEXT_HELP },
|
|
52
56
|
{ name: "delete-range", mutation: true, help: DELETE_RANGE_HELP },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/commands/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"docs.js","sourceRoot":"","sources":["../../../src/commands/docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const ACTIVITY_HELP = "usage: gws-axi drive activity <itemId> [flags]\nargs[1]:\n <itemId> A Drive file or folder ID (the portion of the URL\n after /d/ or /folders/)\nflags[5]:\n --folder Treat <itemId> as a folder: report activity for it and\n all descendants (ancestorName), not just the item itself\n --since <date> Only activity at/after this time (ISO or YYYY-MM-DD)\n --until <date> Only activity before this time (ISO or YYYY-MM-DD)\n --action <list> Comma-separated action types to include: create, edit,\n move, rename, delete, restore, permission_change,\n comment\n --limit <n> Max activities to return, newest first (default: 50)\n --account <email> Account override when 2+ are configured\nexamples:\n gws-axi drive activity 1V09rp...\n gws-axi drive activity 1AbCfolder... --folder --action permission_change,delete\n gws-axi drive activity 1V09rp... --since 2026-01-01 --until 2026-04-01\noutput:\n An `item{id,scope}` header followed by an `activities[N]{time,action,actor,target}`\n list, newest first. Actions cover create/edit/move/rename/delete/restore,\n permission changes, and comments \u2014 richer than `drive revisions` (content\n versions only).\nnotes:\n Requires the drive.activity.readonly scope (read-only). Accounts authorized\n before this command shipped must re-auth once: `gws-axi auth login --account\n <email>`. Results are limited to activity visible to the authenticated\n account \u2014 items never shared with it contribute no history. Actors are\n reported best-effort; some (anonymous/deleted/unknown) cannot be identified.\n";
|
|
2
|
+
interface ParsedFlags {
|
|
3
|
+
itemId: string;
|
|
4
|
+
folder: boolean;
|
|
5
|
+
since: string | undefined;
|
|
6
|
+
until: string | undefined;
|
|
7
|
+
actions: string[];
|
|
8
|
+
limit: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function parseFlags(args: string[]): ParsedFlags;
|
|
11
|
+
/** Build the `filter` string for the Activity query from time + action flags. */
|
|
12
|
+
export declare function buildFilter(flags: ParsedFlags): string;
|
|
13
|
+
/** The primary action label for an activity's first action with a detail. */
|
|
14
|
+
export declare function primaryActionLabel(activity: Record<string, unknown>): string;
|
|
15
|
+
/** Best-effort actor identity from an activity's actors[]. */
|
|
16
|
+
export declare function primaryActor(activity: Record<string, unknown>): string;
|
|
17
|
+
/**
|
|
18
|
+
* Best-effort target label from an activity's targets[]. Prefers the title,
|
|
19
|
+
* but always keeps the item id reachable (ids-are-first-class): renders
|
|
20
|
+
* "<title> (<id>)" when both are present, the id alone when only it is.
|
|
21
|
+
* driveItem.name has the form "items/<id>".
|
|
22
|
+
*/
|
|
23
|
+
export declare function primaryTarget(activity: Record<string, unknown>): string;
|
|
24
|
+
export declare function driveActivityCommand(account: string, args: string[]): Promise<string>;
|
|
25
|
+
export {};
|