gws-axi 0.11.0 → 0.13.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 +10 -2
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +6 -3
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/drive/mkdir.d.ts +7 -0
- package/dist/src/commands/drive/mkdir.js +101 -0
- package/dist/src/commands/drive/mkdir.js.map +1 -0
- package/dist/src/commands/drive/mkdir.test.d.ts +1 -0
- package/dist/src/commands/drive/mkdir.test.js +40 -0
- package/dist/src/commands/drive/mkdir.test.js.map +1 -0
- package/dist/src/commands/drive.js +11 -6
- package/dist/src/commands/drive.js.map +1 -1
- package/dist/src/commands/setup.d.ts +2 -0
- package/dist/src/commands/setup.js +25 -0
- package/dist/src/commands/setup.js.map +1 -0
- package/dist/src/commands/setup.test.d.ts +1 -0
- package/dist/src/commands/setup.test.js +27 -0
- package/dist/src/commands/setup.test.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ I want to authenticate the following Google accounts:
|
|
|
37
37
|
- personal@gmail.com
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
The explicit `gws-axi auth setup` in the prompt matters: this is your very first session, so the agent doesn't yet have any ambient context about `gws-axi`. Naming the first command gets the agent into the structured flow, where the CLI's output takes over.
|
|
40
|
+
The explicit `gws-axi auth setup` in the prompt matters: this is your very first session, so the agent doesn't yet have any ambient context about `gws-axi`. Naming the first command gets the agent into the structured flow, where the CLI's output takes over. Once you install the SessionStart hook (see [step 4](#4-make-gws-axi-your-agents-default-for-google-workspace)), every subsequent session auto-loads a compact `gws-axi` status line — so after that, you can skip the command and just say "use gws-axi to ..." and the agent knows.
|
|
41
41
|
|
|
42
42
|
Expect ~10 minutes end-to-end for a fresh Google Cloud project; ~3 minutes if you already have one you want to reuse.
|
|
43
43
|
|
|
@@ -54,7 +54,15 @@ gws-axi calendar events # upcoming 7 days on your primary calen
|
|
|
54
54
|
|
|
55
55
|
### 4. Make gws-axi your agent's default for Google Workspace
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
gws-axi gives agents two complementary ways to pick up ambient context (per [AXI principle 7](https://axi.md) — context is delivered through hooks and installable skills, and installation is always explicit opt-in, never a side effect of ordinary commands):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
gws-axi setup hooks
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This installs a **SessionStart hook** into your agent's config — Claude Code (`~/.claude/settings.json`), Codex (`~/.codex/hooks.json`), and OpenCode. From then on, every new agent session sees a compact `gws-axi` status line in ambient context — authenticated accounts, write-protection status, setup health. The command is idempotent and self-repairing: re-run it any time (e.g. after upgrading or moving the install) and it repairs a stale executable path without duplicating entries. There is no auto-install — the hook only appears when you run `setup hooks`.
|
|
64
|
+
|
|
65
|
+
The hook and an installable skill are the two ambient-context paths: the hook injects current state at session start, while a skill can teach the agent the full command surface on demand. Run `gws-axi setup hooks` to get the hook in place.
|
|
58
66
|
|
|
59
67
|
To make sure agents reach for `gws-axi` instead of stale alternatives, also consider:
|
|
60
68
|
|
package/dist/src/cli.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const TOP_HELP = "usage: gws-axi [command] [args] [flags]\ncommands[
|
|
1
|
+
export declare const TOP_HELP = "usage: gws-axi [command] [args] [flags]\ncommands[9]:\n (none)=home, auth, doctor, calendar, gmail, docs, drive, slides, setup\nflags[2]:\n --help, -v/-V/--version\nexamples:\n gws-axi\n gws-axi auth setup\n gws-axi doctor\n gws-axi calendar events\n gws-axi setup hooks\n";
|
|
2
2
|
export declare function main(): Promise<void>;
|
package/dist/src/cli.js
CHANGED
|
@@ -10,11 +10,12 @@ import { gmailCommand } from "./commands/gmail.js";
|
|
|
10
10
|
import { docsCommand } from "./commands/docs.js";
|
|
11
11
|
import { driveCommand } from "./commands/drive.js";
|
|
12
12
|
import { slidesCommand } from "./commands/slides.js";
|
|
13
|
+
import { setupCommand, SETUP_HELP } from "./commands/setup.js";
|
|
13
14
|
const DESCRIPTION = "Agent ergonomic CLI for Google Workspace. Unified interface for Gmail, Calendar, Docs, Drive, and Slides with agent-guided OAuth setup.";
|
|
14
15
|
const VERSION = readPackageVersion();
|
|
15
16
|
export const TOP_HELP = `usage: gws-axi [command] [args] [flags]
|
|
16
|
-
commands[
|
|
17
|
-
(none)=home, auth, doctor, calendar, gmail, docs, drive, slides
|
|
17
|
+
commands[9]:
|
|
18
|
+
(none)=home, auth, doctor, calendar, gmail, docs, drive, slides, setup
|
|
18
19
|
flags[2]:
|
|
19
20
|
--help, -v/-V/--version
|
|
20
21
|
examples:
|
|
@@ -22,6 +23,7 @@ examples:
|
|
|
22
23
|
gws-axi auth setup
|
|
23
24
|
gws-axi doctor
|
|
24
25
|
gws-axi calendar events
|
|
26
|
+
gws-axi setup hooks
|
|
25
27
|
`;
|
|
26
28
|
// Services that have real subcommand dispatchers handle --help themselves
|
|
27
29
|
// (so `<service> <sub> --help` shows subcommand-specific help). For stubs
|
|
@@ -29,13 +31,13 @@ examples:
|
|
|
29
31
|
const COMMAND_HELP = {
|
|
30
32
|
auth: AUTH_HELP,
|
|
31
33
|
doctor: DOCTOR_HELP,
|
|
34
|
+
setup: SETUP_HELP,
|
|
32
35
|
};
|
|
33
36
|
export async function main() {
|
|
34
37
|
await runAxiCli({
|
|
35
38
|
description: DESCRIPTION,
|
|
36
39
|
version: VERSION,
|
|
37
40
|
topLevelHelp: TOP_HELP,
|
|
38
|
-
...(process.env.GWS_AXI_DISABLE_HOOKS === "1" ? { hooks: false } : {}),
|
|
39
41
|
home: async () => homeCommand(),
|
|
40
42
|
commands: {
|
|
41
43
|
auth: authCommand,
|
|
@@ -45,6 +47,7 @@ export async function main() {
|
|
|
45
47
|
docs: docsCommand,
|
|
46
48
|
drive: driveCommand,
|
|
47
49
|
slides: slidesCommand,
|
|
50
|
+
setup: setupCommand,
|
|
48
51
|
},
|
|
49
52
|
getCommandHelp: (command) => COMMAND_HELP[command],
|
|
50
53
|
});
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,GACf,yIAAyI,CAAC;AAE5I,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;CAWvB,CAAC;AAEF,0EAA0E;AAC1E,0EAA0E;AAC1E,iEAAiE;AACjE,MAAM,YAAY,GAA2B;IAC3C,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,UAAU;CAClB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,IAAI;IACxB,MAAM,SAAS,CAAC;QACd,WAAW,EAAE,WAAW;QACxB,OAAO,EAAE,OAAO;QAChB,YAAY,EAAE,QAAQ;QACtB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE;QAC/B,QAAQ,EAAE;YACR,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,aAAa;YACrB,QAAQ,EAAE,eAAe;YACzB,KAAK,EAAE,YAAY;YACnB,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,aAAa;YACrB,KAAK,EAAE,YAAY;SACpB;QACD,cAAc,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;KACnD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAErD,KAAK,MAAM,SAAS,IAAI;QACtB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;KACvC,EAAE,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAEzD,CAAC;QACF,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpE,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const MKDIR_HELP = "usage: gws-axi drive mkdir <name> [flags]\nargs[1]:\n <name> REQUIRED \u2014 the folder name\nflags[2]:\n --parent <folder-id> Parent folder ID (default: My Drive root)\n --account <email> REQUIRED when 2+ accounts are authenticated\nexamples:\n gws-axi drive mkdir \"Q2 Reports\"\n gws-axi drive mkdir Invoices --parent 1AbC...\nnotes:\n Drive allows duplicate folder names \u2014 re-running creates ANOTHER folder.\n Capture the returned id to nest uploads with `drive upload --parent <id>`.\noutput:\n An `action: created` line plus a `folder{...}` object with id, name,\n parents, and web_view_link.\n";
|
|
2
|
+
export interface ParsedFlags {
|
|
3
|
+
name: string | undefined;
|
|
4
|
+
parent: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseFlags(args: string[]): ParsedFlags;
|
|
7
|
+
export declare function driveMkdirCommand(account: string, args: string[]): Promise<string>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { AxiError } from "axi-sdk-js";
|
|
2
|
+
import { driveClient, translateGoogleError } from "../../google/client.js";
|
|
3
|
+
import { joinBlocks, renderHelp, renderObject } from "../../output/index.js";
|
|
4
|
+
export const MKDIR_HELP = `usage: gws-axi drive mkdir <name> [flags]
|
|
5
|
+
args[1]:
|
|
6
|
+
<name> REQUIRED — the folder name
|
|
7
|
+
flags[2]:
|
|
8
|
+
--parent <folder-id> Parent folder ID (default: My Drive root)
|
|
9
|
+
--account <email> REQUIRED when 2+ accounts are authenticated
|
|
10
|
+
examples:
|
|
11
|
+
gws-axi drive mkdir "Q2 Reports"
|
|
12
|
+
gws-axi drive mkdir Invoices --parent 1AbC...
|
|
13
|
+
notes:
|
|
14
|
+
Drive allows duplicate folder names — re-running creates ANOTHER folder.
|
|
15
|
+
Capture the returned id to nest uploads with \`drive upload --parent <id>\`.
|
|
16
|
+
output:
|
|
17
|
+
An \`action: created\` line plus a \`folder{...}\` object with id, name,
|
|
18
|
+
parents, and web_view_link.
|
|
19
|
+
`;
|
|
20
|
+
const FOLDER_MIME = "application/vnd.google-apps.folder";
|
|
21
|
+
const MKDIR_FIELDS = "id,name,parents,webViewLink";
|
|
22
|
+
export function parseFlags(args) {
|
|
23
|
+
const flags = { name: undefined, parent: undefined };
|
|
24
|
+
for (let i = 0; i < args.length; i++) {
|
|
25
|
+
const arg = args[i];
|
|
26
|
+
const next = args[i + 1];
|
|
27
|
+
switch (arg) {
|
|
28
|
+
case "--parent":
|
|
29
|
+
flags.parent = next;
|
|
30
|
+
i++;
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
if (!arg.startsWith("--") && flags.name === undefined) {
|
|
34
|
+
flags.name = arg;
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return flags;
|
|
40
|
+
}
|
|
41
|
+
export async function driveMkdirCommand(account, args) {
|
|
42
|
+
const flags = parseFlags(args);
|
|
43
|
+
if (!flags.name) {
|
|
44
|
+
throw new AxiError("Missing folder name", "VALIDATION_ERROR", [
|
|
45
|
+
"Usage: gws-axi drive mkdir <name> [--parent <folder-id>]",
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
const api = await driveClient(account);
|
|
49
|
+
const requestBody = {
|
|
50
|
+
name: flags.name,
|
|
51
|
+
mimeType: FOLDER_MIME,
|
|
52
|
+
};
|
|
53
|
+
if (flags.parent)
|
|
54
|
+
requestBody.parents = [flags.parent];
|
|
55
|
+
let folder;
|
|
56
|
+
try {
|
|
57
|
+
const res = await api.files.create({
|
|
58
|
+
requestBody,
|
|
59
|
+
fields: MKDIR_FIELDS,
|
|
60
|
+
supportsAllDrives: true,
|
|
61
|
+
});
|
|
62
|
+
folder = res.data;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const translated = translateGoogleError(err, {
|
|
66
|
+
account,
|
|
67
|
+
operation: "drive.files.create",
|
|
68
|
+
});
|
|
69
|
+
if (translated.code === "NOT_FOUND") {
|
|
70
|
+
throw new AxiError(`Parent folder '${flags.parent}' not found (or ${account} can't write to it)`, "FILE_NOT_FOUND", [
|
|
71
|
+
"Verify the --parent ID is correct (from a Drive URL or `drive ls` / `drive search`)",
|
|
72
|
+
`Confirm ${account} has edit access`,
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
throw translated;
|
|
76
|
+
}
|
|
77
|
+
const id = folder.id ?? "";
|
|
78
|
+
const details = {
|
|
79
|
+
id,
|
|
80
|
+
name: folder.name ?? flags.name,
|
|
81
|
+
parents: folder.parents?.length ? folder.parents.join(", ") : "",
|
|
82
|
+
};
|
|
83
|
+
if (folder.webViewLink)
|
|
84
|
+
details.web_view_link = folder.webViewLink;
|
|
85
|
+
const blocks = [];
|
|
86
|
+
blocks.push(renderObject({ action: "created", account }));
|
|
87
|
+
blocks.push(renderObject({ folder: details }));
|
|
88
|
+
const suggestions = [
|
|
89
|
+
`Run \`gws-axi drive upload <file> --parent ${id}\` to put a file in this folder`,
|
|
90
|
+
`Run \`gws-axi drive ls ${id}\` to list its contents`,
|
|
91
|
+
`Run \`gws-axi drive get ${id}\` for full metadata`,
|
|
92
|
+
`Run \`gws-axi drive permissions ${id}\` to see / change who has access`,
|
|
93
|
+
`Re-running creates another folder (Drive allows duplicate names) — capture this id to reuse it`,
|
|
94
|
+
];
|
|
95
|
+
if (folder.webViewLink) {
|
|
96
|
+
suggestions.push(`Open in browser: ${folder.webViewLink}`);
|
|
97
|
+
}
|
|
98
|
+
blocks.push(renderHelp(suggestions));
|
|
99
|
+
return joinBlocks(...blocks);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=mkdir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mkdir.js","sourceRoot":"","sources":["../../../../src/commands/drive/mkdir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE7E,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;CAezB,CAAC;AAEF,MAAM,WAAW,GAAG,oCAAoC,CAAC;AACzD,MAAM,YAAY,GAAG,6BAA6B,CAAC;AAOnD,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,UAAU;gBACb,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;gBACpB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACR;gBACE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBACtD,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC;gBACnB,CAAC;gBACD,MAAM;QACV,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,IAAc;IAEd,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,kBAAkB,EAAE;YAC5D,0DAA0D;SAC3D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,WAAW,GAAyB;QACxC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,WAAW;KACtB,CAAC;IACF,IAAI,KAAK,CAAC,MAAM;QAAE,WAAW,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAEvD,IAAI,MAA4B,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;YACjC,WAAW;YACX,MAAM,EAAE,YAAY;YACpB,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;IACpB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,oBAAoB,CAAC,GAAG,EAAE;YAC3C,OAAO;YACP,SAAS,EAAE,oBAAoB;SAChC,CAAC,CAAC;QACH,IAAI,UAAU,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACpC,MAAM,IAAI,QAAQ,CAChB,kBAAkB,KAAK,CAAC,MAAM,mBAAmB,OAAO,qBAAqB,EAC7E,gBAAgB,EAChB;gBACE,qFAAqF;gBACrF,WAAW,OAAO,kBAAkB;aACrC,CACF,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,CAAC;IACnB,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IAC3B,MAAM,OAAO,GAA4B;QACvC,EAAE;QACF,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;KACjE,CAAC;IACF,IAAI,MAAM,CAAC,WAAW;QAAE,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC;IAEnE,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAE/C,MAAM,WAAW,GAAa;QAC5B,8CAA8C,EAAE,iCAAiC;QACjF,0BAA0B,EAAE,yBAAyB;QACrD,2BAA2B,EAAE,sBAAsB;QACnD,mCAAmC,EAAE,mCAAmC;QACxE,gGAAgG;KACjG,CAAC;IACF,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,WAAW,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACrC,OAAO,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { AxiError } from "axi-sdk-js";
|
|
3
|
+
import { parseFlags, driveMkdirCommand } from "./mkdir.js";
|
|
4
|
+
describe("drive mkdir parseFlags", () => {
|
|
5
|
+
it("parses a bare name with no parent", () => {
|
|
6
|
+
const f = parseFlags(["Reports"]);
|
|
7
|
+
expect(f.name).toBe("Reports");
|
|
8
|
+
expect(f.parent).toBeUndefined();
|
|
9
|
+
});
|
|
10
|
+
it("parses a quoted multi-word name and --parent", () => {
|
|
11
|
+
const f = parseFlags(["Q2 Reports", "--parent", "1AbC"]);
|
|
12
|
+
expect(f.name).toBe("Q2 Reports");
|
|
13
|
+
expect(f.parent).toBe("1AbC");
|
|
14
|
+
});
|
|
15
|
+
it("takes the first positional as the name, ignoring later ones", () => {
|
|
16
|
+
const f = parseFlags(["first", "second"]);
|
|
17
|
+
expect(f.name).toBe("first");
|
|
18
|
+
});
|
|
19
|
+
it("leaves name undefined when only flags are given", () => {
|
|
20
|
+
const f = parseFlags(["--parent", "1AbC"]);
|
|
21
|
+
expect(f.name).toBeUndefined();
|
|
22
|
+
expect(f.parent).toBe("1AbC");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("drive mkdir command validation", () => {
|
|
26
|
+
it("throws VALIDATION_ERROR when the name is missing", async () => {
|
|
27
|
+
await expect(driveMkdirCommand("a@b.com", ["--parent", "1AbC"])).rejects.toMatchObject({ code: "VALIDATION_ERROR" });
|
|
28
|
+
});
|
|
29
|
+
it("rejects with an AxiError (not a raw throw) on missing name", async () => {
|
|
30
|
+
try {
|
|
31
|
+
await driveMkdirCommand("a@b.com", []);
|
|
32
|
+
throw new Error("should have thrown");
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
expect(err).toBeInstanceOf(AxiError);
|
|
36
|
+
expect(err.code).toBe("VALIDATION_ERROR");
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=mkdir.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mkdir.test.js","sourceRoot":"","sources":["../../../../src/commands/drive/mkdir.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,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE3D,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CACpF,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,iBAAiB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACvC,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"}
|
|
@@ -8,6 +8,7 @@ import { driveActivityCommand, ACTIVITY_HELP } from "./drive/activity.js";
|
|
|
8
8
|
import { driveRevisionsCommand, REVISIONS_HELP, } from "./drive/revisions.js";
|
|
9
9
|
import { driveSearchCommand, SEARCH_HELP } from "./drive/search.js";
|
|
10
10
|
import { driveUploadCommand, UPLOAD_HELP } from "./drive/upload.js";
|
|
11
|
+
import { driveMkdirCommand, MKDIR_HELP } from "./drive/mkdir.js";
|
|
11
12
|
// Drive `download` shares the docs/download.ts implementation — same code
|
|
12
13
|
// path handles native Google file export + uploaded-file media fetch.
|
|
13
14
|
const DOWNLOAD_HELP = `usage: gws-axi drive download <file-id> [flags]
|
|
@@ -46,9 +47,6 @@ status: planned for v1 writes — not yet implemented
|
|
|
46
47
|
const DELETE_HELP = `usage: gws-axi drive delete <file-id> [flags]
|
|
47
48
|
status: planned for v1 writes — not yet implemented
|
|
48
49
|
`;
|
|
49
|
-
const MKDIR_HELP = `usage: gws-axi drive mkdir --name <name> --parent <folder-id> [flags]
|
|
50
|
-
status: planned for v1 writes — not yet implemented
|
|
51
|
-
`;
|
|
52
50
|
const SUBCOMMANDS = [
|
|
53
51
|
{ name: "search", mutation: false, help: SEARCH_HELP, handler: driveSearchCommand },
|
|
54
52
|
{ name: "get", mutation: false, help: GET_HELP, handler: driveGetCommand },
|
|
@@ -89,7 +87,12 @@ const SUBCOMMANDS = [
|
|
|
89
87
|
{ name: "move", mutation: true, help: MOVE_HELP },
|
|
90
88
|
{ name: "rename", mutation: true, help: RENAME_HELP },
|
|
91
89
|
{ name: "delete", mutation: true, help: DELETE_HELP },
|
|
92
|
-
{
|
|
90
|
+
{
|
|
91
|
+
name: "mkdir",
|
|
92
|
+
mutation: true,
|
|
93
|
+
help: MKDIR_HELP,
|
|
94
|
+
handler: driveMkdirCommand,
|
|
95
|
+
},
|
|
93
96
|
];
|
|
94
97
|
const SUB_BY_NAME = Object.fromEntries(SUBCOMMANDS.map((s) => [s.name, s]));
|
|
95
98
|
function parseAccountFlag(args) {
|
|
@@ -116,8 +119,8 @@ writes[${writes.length}]:
|
|
|
116
119
|
notes:
|
|
117
120
|
Writes require --account <email> when 2+ accounts are authenticated.
|
|
118
121
|
Reads use the default account when --account is not provided.
|
|
119
|
-
upload
|
|
120
|
-
next slice and throw NOT_IMPLEMENTED after account resolution runs.
|
|
122
|
+
upload and mkdir are live; the remaining write subcommands are scaffolded
|
|
123
|
+
for the next slice and throw NOT_IMPLEMENTED after account resolution runs.
|
|
121
124
|
subcommand help:
|
|
122
125
|
gws-axi drive ls --help for folder listing (incl. --recursive)
|
|
123
126
|
gws-axi drive get --help for full file metadata
|
|
@@ -125,6 +128,7 @@ subcommand help:
|
|
|
125
128
|
gws-axi drive permissions --help for access / sharing
|
|
126
129
|
gws-axi drive download --help for fetching bytes (alias of docs download)
|
|
127
130
|
gws-axi drive upload --help for uploading a local file (incl. --convert)
|
|
131
|
+
gws-axi drive mkdir --help for creating a folder
|
|
128
132
|
examples:
|
|
129
133
|
gws-axi drive ls
|
|
130
134
|
gws-axi drive ls <folder-id> --recursive
|
|
@@ -132,6 +136,7 @@ examples:
|
|
|
132
136
|
gws-axi drive get <file-id>
|
|
133
137
|
gws-axi drive permissions <file-id>
|
|
134
138
|
gws-axi drive upload ./report.pdf --account you@example.com
|
|
139
|
+
gws-axi drive mkdir "Q2 Reports" --account you@example.com
|
|
135
140
|
`;
|
|
136
141
|
export async function driveCommand(args) {
|
|
137
142
|
if (args.length === 0 || (args.length === 1 && args[0] === "--help")) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../src/commands/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EACL,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"drive.js","sourceRoot":"","sources":["../../../src/commands/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EACL,qBAAqB,EACrB,cAAc,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AASjE,0EAA0E;AAC1E,sEAAsE;AACtE,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;CAmBrB,CAAC;AAEF,2EAA2E;AAC3E,MAAM,WAAW,GAAG;;CAEnB,CAAC;AACF,MAAM,SAAS,GAAG;;CAEjB,CAAC;AACF,MAAM,SAAS,GAAG;;CAEjB,CAAC;AACF,MAAM,WAAW,GAAG;;CAEnB,CAAC;AACF,MAAM,WAAW,GAAG;;CAEnB,CAAC;AAEF,MAAM,WAAW,GAAsB;IACrC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE;IACnF,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE;IAC1E,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE;IACvE;QACE,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,uBAAuB;KACjC;IACD;QACE,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,aAAa;QACnB,oEAAoE;QACpE,OAAO,EAAE,mBAAmB;KAC7B;IACD;QACE,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,qBAAqB;KAC/B;IACD;QACE,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,oBAAoB;KAC9B;IACD;QACE,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,kBAAkB;KAC5B;IACD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;IACjD,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;IACjD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE;IACrD;QACE,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,iBAAiB;KAC3B;CACF,CAAC;AAEF,MAAM,WAAW,GAAoC,MAAM,CAAC,WAAW,CACrE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACpC,CAAC;AAEF,SAAS,gBAAgB,CAAC,IAAc;IAItC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAA2B,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvC,OAAO,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACtB,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAExE,MAAM,CAAC,MAAM,UAAU,GAAG;QAClB,KAAK,CAAC,MAAM;IAChB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,MAAM;IAClB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;CAsBpB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc;IAC/C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACrE,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,QAAQ,CAChB,6BAA6B,GAAG,EAAE,EAClC,kBAAkB,EAClB,CAAC,2DAA2D,CAAC,CAC9D,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzE,MAAM,UAAU,GAAG,cAAc,CAAC,WAAW,EAAE;QAC7C,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,SAAS,GAAG,EAAE;KAC5B,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAChB,iBAAiB,GAAG,yBAAyB,EAC7C,iBAAiB,EACjB;YACE,8CAA8C,UAAU,CAAC,OAAO,EAAE;YAClE,uBAAuB,GAAG,mCAAmC;SAC9D,CACF,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const SETUP_HELP = "usage: gws-axi setup hooks\nInstall or repair agent SessionStart hooks so each session starts with gws-axi's\nhome view (Google Workspace state \u2014 authenticated accounts, write-protection status,\nsetup/health) as ambient context. Installs to Claude Code, Codex, and OpenCode.\nIdempotent; repairs a stale executable path.\nexamples:\n gws-axi setup hooks";
|
|
2
|
+
export declare function setupCommand(args: string[]): Promise<string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AxiError, installSessionStartHooks } from "axi-sdk-js";
|
|
2
|
+
import { joinBlocks, renderHelp, renderObject } from "../output/index.js";
|
|
3
|
+
export const SETUP_HELP = `usage: gws-axi setup hooks
|
|
4
|
+
Install or repair agent SessionStart hooks so each session starts with gws-axi's
|
|
5
|
+
home view (Google Workspace state — authenticated accounts, write-protection status,
|
|
6
|
+
setup/health) as ambient context. Installs to Claude Code, Codex, and OpenCode.
|
|
7
|
+
Idempotent; repairs a stale executable path.
|
|
8
|
+
examples:
|
|
9
|
+
gws-axi setup hooks`;
|
|
10
|
+
export async function setupCommand(args) {
|
|
11
|
+
if (args.includes("--help"))
|
|
12
|
+
return SETUP_HELP;
|
|
13
|
+
if (args[0] !== "hooks") {
|
|
14
|
+
throw new AxiError(`Unknown setup action: ${args[0] ?? "(none)"}`, "VALIDATION_ERROR", [
|
|
15
|
+
"Run `gws-axi setup hooks`",
|
|
16
|
+
]);
|
|
17
|
+
}
|
|
18
|
+
const errors = [];
|
|
19
|
+
installSessionStartHooks({ marker: "gws-axi", timeoutSeconds: 10, onError: (m) => errors.push(m) });
|
|
20
|
+
if (errors.length > 0) {
|
|
21
|
+
throw new AxiError("Hook installation reported problems", "HOOK_INSTALL_FAILED", errors);
|
|
22
|
+
}
|
|
23
|
+
return joinBlocks(renderObject({ hooks: { status: "installed", integrations: "Claude Code, Codex, OpenCode", marker: "gws-axi" } }), renderHelp(["Restart your agent session to receive gws-axi ambient context"]));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/commands/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE1E,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;sBAMJ,CAAC;AAEvB,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAc;IAC/C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,UAAU,CAAC;IAC/C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,QAAQ,CAAC,yBAAyB,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE,EAAE,kBAAkB,EAAE;YACrF,2BAA2B;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,wBAAwB,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACpG,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,QAAQ,CAAC,qCAAqC,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO,UAAU,CACf,YAAY,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,EACjH,UAAU,CAAC,CAAC,+DAA+D,CAAC,CAAC,CAC9E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { AxiError } from "axi-sdk-js";
|
|
3
|
+
import { setupCommand, SETUP_HELP } from "./setup.js";
|
|
4
|
+
describe("setup command", () => {
|
|
5
|
+
it("returns help for --help without installing", async () => {
|
|
6
|
+
await expect(setupCommand(["--help"])).resolves.toBe(SETUP_HELP);
|
|
7
|
+
});
|
|
8
|
+
it("rejects an unknown action with VALIDATION_ERROR", async () => {
|
|
9
|
+
await expect(setupCommand(["frobnicate"])).rejects.toMatchObject({
|
|
10
|
+
code: "VALIDATION_ERROR",
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
it("rejects a missing action with VALIDATION_ERROR (AxiError)", async () => {
|
|
14
|
+
try {
|
|
15
|
+
await setupCommand([]);
|
|
16
|
+
throw new Error("should have thrown");
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
expect(err).toBeInstanceOf(AxiError);
|
|
20
|
+
expect(err.code).toBe("VALIDATION_ERROR");
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
it("SETUP_HELP documents the single `setup hooks` action", () => {
|
|
24
|
+
expect(SETUP_HELP).toContain("gws-axi setup hooks");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=setup.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.test.js","sourceRoot":"","sources":["../../../src/commands/setup.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,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtD,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;YAC/D,IAAI,EAAE,kBAAkB;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,IAAI,CAAC;YACH,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;YACvB,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;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gws-axi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "AXI-compliant Google Workspace CLI — token-efficient TOON output, agent-guided auth setup, unified interface for Gmail, Calendar, Docs, Drive, Slides",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|