gogcli-mcp 1.0.5 → 1.0.6
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 +23 -125
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5340 -5393
- package/dist/lib.d.ts +6 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +30837 -0
- package/dist/runner.d.ts +12 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/tools/auth.d.ts +3 -0
- package/dist/tools/auth.d.ts.map +1 -0
- package/dist/tools/calendar.d.ts +3 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/contacts.d.ts +3 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/docs.d.ts +3 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/drive.d.ts +3 -0
- package/dist/tools/drive.d.ts.map +1 -0
- package/dist/tools/gmail.d.ts +3 -0
- package/dist/tools/gmail.d.ts.map +1 -0
- package/dist/tools/sheets.d.ts +3 -0
- package/dist/tools/sheets.d.ts.map +1 -0
- package/dist/tools/tasks.d.ts +3 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/utils.d.ts +14 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/manifest.json +1 -1
- package/package.json +6 -2
- package/src/index.ts +2 -23
- package/src/lib.ts +5 -0
- package/src/server.ts +31 -0
- package/src/tools/docs.ts +10 -76
- package/tests/tools/docs.test.ts +19 -163
- package/tsconfig.json +2 -8
- package/.github/workflows/ci.yml +0 -22
- package/.github/workflows/release.yml +0 -76
- package/.github/workflows/tag-and-bump.yml +0 -67
- package/.mcp.json +0 -13
- package/CLAUDE.md +0 -61
- package/docs/superpowers/plans/2026-04-12-gogcli-mcp.md +0 -758
- package/docs/superpowers/plans/2026-04-13-browser-auth.md +0 -450
- package/docs/superpowers/specs/2026-04-12-gogcli-mcp-design.md +0 -102
- package/docs/superpowers/specs/2026-04-13-browser-auth-design.md +0 -88
- package/gogcli-mcp-1.0.5.skill +0 -0
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
2
|
+
export type Spawner = (command: string, args: string[], options: {
|
|
3
|
+
env: NodeJS.ProcessEnv;
|
|
4
|
+
}) => ChildProcess;
|
|
5
|
+
export interface RunOptions {
|
|
6
|
+
account?: string;
|
|
7
|
+
spawner?: Spawner;
|
|
8
|
+
interactive?: boolean;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function run(args: string[], options?: RunOptions): Promise<string>;
|
|
12
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,KAChC,YAAY,CAAC;AAElB,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DnF"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE,eAAO,MAAM,OAAO,QAAmE,CAAC;AAExF,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAgBzF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwEzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/tools/calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2H7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contacts.d.ts","sourceRoot":"","sources":["../../src/tools/contacts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkE7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/tools/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoGzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../src/tools/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgH1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmail.d.ts","sourceRoot":"","sources":["../../src/tools/gmail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sheets.d.ts","sourceRoot":"","sources":["../../src/tools/sheets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAuG3D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/tools/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsF1D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type ToolResult = {
|
|
3
|
+
content: [{
|
|
4
|
+
type: 'text';
|
|
5
|
+
text: string;
|
|
6
|
+
}];
|
|
7
|
+
};
|
|
8
|
+
export declare const accountParam: z.ZodOptional<z.ZodString>;
|
|
9
|
+
export declare function toText(output: string): ToolResult;
|
|
10
|
+
export declare function toError(err: unknown): ToolResult;
|
|
11
|
+
export declare function runOrDiagnose(args: string[], options: {
|
|
12
|
+
account?: string;
|
|
13
|
+
}): Promise<ToolResult>;
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,MAAM,UAAU,GAAG;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAEvE,eAAO,MAAM,YAAY,4BAExB,CAAC;AAEF,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAEjD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAEhD;AAQD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,UAAU,CAAC,CAerB"}
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.3",
|
|
4
4
|
"name": "gogcli-mcp",
|
|
5
5
|
"display_name": "gogcli",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.6",
|
|
7
7
|
"description": "Google Sheets (and more) for Claude via gogcli — read, write, and manage spreadsheets",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "Chris Hall",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gogcli-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "MCP server wrapping gogcli for Google service access",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,9 +10,13 @@
|
|
|
10
10
|
"bin": {
|
|
11
11
|
"gogcli-mcp": "dist/index.js"
|
|
12
12
|
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./dist/index.js",
|
|
15
|
+
"./lib": "./dist/lib.js"
|
|
16
|
+
},
|
|
13
17
|
"scripts": {
|
|
14
18
|
"build": "tsc --noEmit && npm run bundle",
|
|
15
|
-
"bundle": "
|
|
19
|
+
"bundle": "node ../../scripts/bundle.js src/index.ts dist/index.js && node ../../scripts/bundle.js src/lib.ts dist/lib.js",
|
|
16
20
|
"typecheck": "tsc --noEmit",
|
|
17
21
|
"test": "vitest run",
|
|
18
22
|
"test:watch": "vitest",
|
package/src/index.ts
CHANGED
|
@@ -1,28 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import {
|
|
5
|
-
import { registerCalendarTools } from './tools/calendar.js';
|
|
6
|
-
import { registerContactsTools } from './tools/contacts.js';
|
|
7
|
-
import { registerDocsTools } from './tools/docs.js';
|
|
8
|
-
import { registerDriveTools } from './tools/drive.js';
|
|
9
|
-
import { registerGmailTools } from './tools/gmail.js';
|
|
10
|
-
import { registerSheetsTools } from './tools/sheets.js';
|
|
11
|
-
import { registerTasksTools } from './tools/tasks.js';
|
|
12
|
-
|
|
13
|
-
const server = new McpServer({ name: 'gogcli', version: '1.0.5' });
|
|
14
|
-
|
|
15
|
-
registerAuthTools(server);
|
|
16
|
-
registerCalendarTools(server);
|
|
17
|
-
registerContactsTools(server);
|
|
18
|
-
registerDocsTools(server);
|
|
19
|
-
registerDriveTools(server);
|
|
20
|
-
registerGmailTools(server);
|
|
21
|
-
registerSheetsTools(server);
|
|
22
|
-
registerTasksTools(server);
|
|
23
|
-
|
|
24
|
-
// To add more services: import registerXxxTools and call them here.
|
|
25
|
-
// Example: registerGmailTools(server);
|
|
3
|
+
import { createBaseServer } from './server.js';
|
|
26
4
|
|
|
5
|
+
const server = createBaseServer();
|
|
27
6
|
const transport = new StdioServerTransport();
|
|
28
7
|
await server.connect(transport);
|
package/src/lib.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createBaseServer, VERSION } from './server.js';
|
|
2
|
+
export { run } from './runner.js';
|
|
3
|
+
export type { RunOptions, Spawner } from './runner.js';
|
|
4
|
+
export { accountParam, runOrDiagnose, toText, toError } from './tools/utils.js';
|
|
5
|
+
export type { ToolResult } from './tools/utils.js';
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { registerAuthTools } from './tools/auth.js';
|
|
3
|
+
import { registerCalendarTools } from './tools/calendar.js';
|
|
4
|
+
import { registerContactsTools } from './tools/contacts.js';
|
|
5
|
+
import { registerDocsTools } from './tools/docs.js';
|
|
6
|
+
import { registerDriveTools } from './tools/drive.js';
|
|
7
|
+
import { registerGmailTools } from './tools/gmail.js';
|
|
8
|
+
import { registerSheetsTools } from './tools/sheets.js';
|
|
9
|
+
import { registerTasksTools } from './tools/tasks.js';
|
|
10
|
+
|
|
11
|
+
// Injected at build time by esbuild --define:GOGCLI_VERSION=...
|
|
12
|
+
declare const GOGCLI_VERSION: string;
|
|
13
|
+
export const VERSION = typeof GOGCLI_VERSION !== 'undefined' ? GOGCLI_VERSION : '0.0.0';
|
|
14
|
+
|
|
15
|
+
export function createBaseServer(options?: { name?: string; version?: string }): McpServer {
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: options?.name ?? 'gogcli',
|
|
18
|
+
version: options?.version ?? VERSION,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
registerAuthTools(server);
|
|
22
|
+
registerCalendarTools(server);
|
|
23
|
+
registerContactsTools(server);
|
|
24
|
+
registerDocsTools(server);
|
|
25
|
+
registerDriveTools(server);
|
|
26
|
+
registerGmailTools(server);
|
|
27
|
+
registerSheetsTools(server);
|
|
28
|
+
registerTasksTools(server);
|
|
29
|
+
|
|
30
|
+
return server;
|
|
31
|
+
}
|
package/src/tools/docs.ts
CHANGED
|
@@ -74,87 +74,21 @@ export function registerDocsTools(server: McpServer): void {
|
|
|
74
74
|
return runOrDiagnose(['docs', 'structure', docId], { account });
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
// --- Comments tools ---
|
|
77
|
+
// --- Comments (generic escape hatch — full comment tools are in gogcli-mcp-docs) ---
|
|
78
78
|
|
|
79
|
-
server.registerTool('
|
|
79
|
+
server.registerTool('gog_docs_comments', {
|
|
80
80
|
description:
|
|
81
|
-
'
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
includeResolved: z.boolean().optional().describe('Include resolved comments (default: false, open only)'),
|
|
86
|
-
account: accountParam,
|
|
87
|
-
},
|
|
88
|
-
}, async ({ docId, includeResolved, account }) => {
|
|
89
|
-
const args = ['docs', 'comments', 'list', docId];
|
|
90
|
-
if (includeResolved) args.push('--include-resolved');
|
|
91
|
-
return runOrDiagnose(args, { account });
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
server.registerTool('gog_docs_comments_get', {
|
|
95
|
-
description: 'Get a single comment by ID, including its replies.',
|
|
96
|
-
annotations: { readOnlyHint: true },
|
|
97
|
-
inputSchema: {
|
|
98
|
-
docId: z.string().describe('Doc ID (from the URL)'),
|
|
99
|
-
commentId: z.string().describe('Comment ID'),
|
|
100
|
-
account: accountParam,
|
|
101
|
-
},
|
|
102
|
-
}, async ({ docId, commentId, account }) => {
|
|
103
|
-
return runOrDiagnose(['docs', 'comments', 'get', docId, commentId], { account });
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
server.registerTool('gog_docs_comments_add', {
|
|
107
|
-
description:
|
|
108
|
-
'Add a comment to a Google Doc. Optionally attach quoted text that appears as the highlighted passage in the Google Docs UI.',
|
|
109
|
-
inputSchema: {
|
|
110
|
-
docId: z.string().describe('Doc ID (from the URL)'),
|
|
111
|
-
content: z.string().describe('Comment text'),
|
|
112
|
-
quoted: z.string().optional().describe('Quoted text to attach to the comment (shown in UIs when available)'),
|
|
113
|
-
account: accountParam,
|
|
114
|
-
},
|
|
115
|
-
}, async ({ docId, content, quoted, account }) => {
|
|
116
|
-
const args = ['docs', 'comments', 'add', docId, content];
|
|
117
|
-
if (quoted) args.push(`--quoted=${quoted}`);
|
|
118
|
-
return runOrDiagnose(args, { account });
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
server.registerTool('gog_docs_comments_reply', {
|
|
122
|
-
description: 'Reply to an existing comment on a Google Doc.',
|
|
123
|
-
inputSchema: {
|
|
124
|
-
docId: z.string().describe('Doc ID (from the URL)'),
|
|
125
|
-
commentId: z.string().describe('Comment ID to reply to'),
|
|
126
|
-
content: z.string().describe('Reply text'),
|
|
127
|
-
account: accountParam,
|
|
128
|
-
},
|
|
129
|
-
}, async ({ docId, commentId, content, account }) => {
|
|
130
|
-
return runOrDiagnose(['docs', 'comments', 'reply', docId, commentId, content], { account });
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
server.registerTool('gog_docs_comments_resolve', {
|
|
134
|
-
description: 'Resolve a comment (mark as done). Optionally include a closing message.',
|
|
135
|
-
annotations: { destructiveHint: true },
|
|
81
|
+
'Run a docs comments subcommand. Subcommands: list, get, add, reply, resolve, delete. ' +
|
|
82
|
+
'Examples: subcommand="list", args=["<docId>"] | subcommand="add", args=["<docId>", "<text>", "--quoted=<passage>"] | ' +
|
|
83
|
+
'subcommand="reply", args=["<docId>", "<commentId>", "<text>"]. ' +
|
|
84
|
+
'For dedicated comment tools with full parameter validation, use the gogcli-mcp-docs package.',
|
|
136
85
|
inputSchema: {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
message: z.string().optional().describe('Optional message to include when resolving'),
|
|
140
|
-
account: accountParam,
|
|
141
|
-
},
|
|
142
|
-
}, async ({ docId, commentId, message, account }) => {
|
|
143
|
-
const args = ['docs', 'comments', 'resolve', docId, commentId];
|
|
144
|
-
if (message) args.push(`--message=${message}`);
|
|
145
|
-
return runOrDiagnose(args, { account });
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
server.registerTool('gog_docs_comments_delete', {
|
|
149
|
-
description: 'Delete a comment from a Google Doc. This action is permanent.',
|
|
150
|
-
annotations: { destructiveHint: true },
|
|
151
|
-
inputSchema: {
|
|
152
|
-
docId: z.string().describe('Doc ID (from the URL)'),
|
|
153
|
-
commentId: z.string().describe('Comment ID to delete'),
|
|
86
|
+
subcommand: z.string().describe('Comments subcommand: list, get, add, reply, resolve, delete'),
|
|
87
|
+
args: z.array(z.string()).describe('Positional args and flags for the subcommand'),
|
|
154
88
|
account: accountParam,
|
|
155
89
|
},
|
|
156
|
-
}, async ({
|
|
157
|
-
return runOrDiagnose(['docs', 'comments',
|
|
90
|
+
}, async ({ subcommand, args, account }) => {
|
|
91
|
+
return runOrDiagnose(['docs', 'comments', subcommand, ...args], { account });
|
|
158
92
|
});
|
|
159
93
|
|
|
160
94
|
server.registerTool('gog_docs_run', {
|
package/tests/tools/docs.test.ts
CHANGED
|
@@ -161,190 +161,46 @@ describe('gog_docs_structure', () => {
|
|
|
161
161
|
});
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
// --- Comments
|
|
164
|
+
// --- Comments (generic escape hatch) ---
|
|
165
165
|
|
|
166
|
-
describe('
|
|
167
|
-
it('
|
|
168
|
-
vi.mocked(runner.run).mockResolvedValue('[{"id":"c1"
|
|
166
|
+
describe('gog_docs_comments', () => {
|
|
167
|
+
it('passes subcommand and args to runner', async () => {
|
|
168
|
+
vi.mocked(runner.run).mockResolvedValue('[{"id":"c1"}]');
|
|
169
169
|
const handlers = setupHandlers();
|
|
170
|
-
const result = await handlers.get('
|
|
170
|
+
const result = await handlers.get('gog_docs_comments')!({ subcommand: 'list', args: ['abc'] });
|
|
171
171
|
expect(runner.run).toHaveBeenCalledWith(['docs', 'comments', 'list', 'abc'], { account: undefined });
|
|
172
|
-
expect(result.content[0].text).toContain('
|
|
172
|
+
expect(result.content[0].text).toContain('c1');
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
-
it('
|
|
176
|
-
vi.mocked(runner.run).mockResolvedValue('[]');
|
|
177
|
-
const handlers = setupHandlers();
|
|
178
|
-
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', includeResolved: true });
|
|
179
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
180
|
-
['docs', 'comments', 'list', 'abc', '--include-resolved'],
|
|
181
|
-
{ account: undefined },
|
|
182
|
-
);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('omits --include-resolved when false', async () => {
|
|
186
|
-
vi.mocked(runner.run).mockResolvedValue('[]');
|
|
187
|
-
const handlers = setupHandlers();
|
|
188
|
-
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', includeResolved: false });
|
|
189
|
-
expect(runner.run).toHaveBeenCalledWith(['docs', 'comments', 'list', 'abc'], { account: undefined });
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('forwards account override', async () => {
|
|
193
|
-
vi.mocked(runner.run).mockResolvedValue('[]');
|
|
194
|
-
const handlers = setupHandlers();
|
|
195
|
-
await handlers.get('gog_docs_comments_list')!({ docId: 'abc', account: 'other@gmail.com' });
|
|
196
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
197
|
-
['docs', 'comments', 'list', 'abc'],
|
|
198
|
-
{ account: 'other@gmail.com' },
|
|
199
|
-
);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('returns error text on failure', async () => {
|
|
203
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('List failed'));
|
|
204
|
-
const handlers = setupHandlers();
|
|
205
|
-
const result = await handlers.get('gog_docs_comments_list')!({ docId: 'bad' });
|
|
206
|
-
expect(result.content[0].text).toContain('Error: List failed');
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
describe('gog_docs_comments_get', () => {
|
|
211
|
-
it('calls run with correct args', async () => {
|
|
212
|
-
vi.mocked(runner.run).mockResolvedValue('{"id":"c1","content":"Fix this","replies":[]}');
|
|
213
|
-
const handlers = setupHandlers();
|
|
214
|
-
const result = await handlers.get('gog_docs_comments_get')!({ docId: 'abc', commentId: 'c1' });
|
|
215
|
-
expect(runner.run).toHaveBeenCalledWith(['docs', 'comments', 'get', 'abc', 'c1'], { account: undefined });
|
|
216
|
-
expect(result.content[0].text).toContain('Fix this');
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it('returns error text on failure', async () => {
|
|
220
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('Not found'));
|
|
221
|
-
const handlers = setupHandlers();
|
|
222
|
-
const result = await handlers.get('gog_docs_comments_get')!({ docId: 'abc', commentId: 'bad' });
|
|
223
|
-
expect(result.content[0].text).toContain('Error: Not found');
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe('gog_docs_comments_add', () => {
|
|
228
|
-
it('calls run with content', async () => {
|
|
229
|
-
vi.mocked(runner.run).mockResolvedValue('{"id":"c2"}');
|
|
230
|
-
const handlers = setupHandlers();
|
|
231
|
-
await handlers.get('gog_docs_comments_add')!({ docId: 'abc', content: 'Please review' });
|
|
232
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
233
|
-
['docs', 'comments', 'add', 'abc', 'Please review'],
|
|
234
|
-
{ account: undefined },
|
|
235
|
-
);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('includes --quoted when provided', async () => {
|
|
239
|
-
vi.mocked(runner.run).mockResolvedValue('{"id":"c2"}');
|
|
240
|
-
const handlers = setupHandlers();
|
|
241
|
-
await handlers.get('gog_docs_comments_add')!({
|
|
242
|
-
docId: 'abc',
|
|
243
|
-
content: 'Typo here',
|
|
244
|
-
quoted: 'teh',
|
|
245
|
-
});
|
|
246
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
247
|
-
['docs', 'comments', 'add', 'abc', 'Typo here', '--quoted=teh'],
|
|
248
|
-
{ account: undefined },
|
|
249
|
-
);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('omits --quoted when not provided', async () => {
|
|
253
|
-
vi.mocked(runner.run).mockResolvedValue('{"id":"c2"}');
|
|
254
|
-
const handlers = setupHandlers();
|
|
255
|
-
await handlers.get('gog_docs_comments_add')!({ docId: 'abc', content: 'Nice' });
|
|
256
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
257
|
-
['docs', 'comments', 'add', 'abc', 'Nice'],
|
|
258
|
-
{ account: undefined },
|
|
259
|
-
);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it('returns error text on failure', async () => {
|
|
263
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('Add failed'));
|
|
264
|
-
const handlers = setupHandlers();
|
|
265
|
-
const result = await handlers.get('gog_docs_comments_add')!({ docId: 'bad', content: 'x' });
|
|
266
|
-
expect(result.content[0].text).toContain('Error: Add failed');
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
describe('gog_docs_comments_reply', () => {
|
|
271
|
-
it('calls run with correct args', async () => {
|
|
272
|
-
vi.mocked(runner.run).mockResolvedValue('{"id":"r1"}');
|
|
273
|
-
const handlers = setupHandlers();
|
|
274
|
-
await handlers.get('gog_docs_comments_reply')!({ docId: 'abc', commentId: 'c1', content: 'Done' });
|
|
275
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
276
|
-
['docs', 'comments', 'reply', 'abc', 'c1', 'Done'],
|
|
277
|
-
{ account: undefined },
|
|
278
|
-
);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
it('returns error text on failure', async () => {
|
|
282
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('Reply failed'));
|
|
283
|
-
const handlers = setupHandlers();
|
|
284
|
-
const result = await handlers.get('gog_docs_comments_reply')!({
|
|
285
|
-
docId: 'abc', commentId: 'c1', content: 'x',
|
|
286
|
-
});
|
|
287
|
-
expect(result.content[0].text).toContain('Error: Reply failed');
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
describe('gog_docs_comments_resolve', () => {
|
|
292
|
-
it('calls run with correct args', async () => {
|
|
293
|
-
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
294
|
-
const handlers = setupHandlers();
|
|
295
|
-
await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
296
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
297
|
-
['docs', 'comments', 'resolve', 'abc', 'c1'],
|
|
298
|
-
{ account: undefined },
|
|
299
|
-
);
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('includes --message when provided', async () => {
|
|
175
|
+
it('passes flags through args', async () => {
|
|
303
176
|
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
304
177
|
const handlers = setupHandlers();
|
|
305
|
-
await handlers.get('
|
|
306
|
-
|
|
178
|
+
await handlers.get('gog_docs_comments')!({
|
|
179
|
+
subcommand: 'add', args: ['abc', 'Nice work', '--quoted=paragraph'],
|
|
307
180
|
});
|
|
308
181
|
expect(runner.run).toHaveBeenCalledWith(
|
|
309
|
-
['docs', 'comments', '
|
|
310
|
-
{ account: undefined },
|
|
311
|
-
);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
it('omits --message when not provided', async () => {
|
|
315
|
-
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
316
|
-
const handlers = setupHandlers();
|
|
317
|
-
await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
318
|
-
expect(runner.run).toHaveBeenCalledWith(
|
|
319
|
-
['docs', 'comments', 'resolve', 'abc', 'c1'],
|
|
182
|
+
['docs', 'comments', 'add', 'abc', 'Nice work', '--quoted=paragraph'],
|
|
320
183
|
{ account: undefined },
|
|
321
184
|
);
|
|
322
185
|
});
|
|
323
186
|
|
|
324
|
-
it('
|
|
325
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('Resolve failed'));
|
|
326
|
-
const handlers = setupHandlers();
|
|
327
|
-
const result = await handlers.get('gog_docs_comments_resolve')!({ docId: 'abc', commentId: 'c1' });
|
|
328
|
-
expect(result.content[0].text).toContain('Error: Resolve failed');
|
|
329
|
-
});
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
describe('gog_docs_comments_delete', () => {
|
|
333
|
-
it('calls run with correct args', async () => {
|
|
187
|
+
it('forwards account override', async () => {
|
|
334
188
|
vi.mocked(runner.run).mockResolvedValue('{}');
|
|
335
189
|
const handlers = setupHandlers();
|
|
336
|
-
await handlers.get('
|
|
190
|
+
await handlers.get('gog_docs_comments')!({
|
|
191
|
+
subcommand: 'list', args: ['abc'], account: 'other@gmail.com',
|
|
192
|
+
});
|
|
337
193
|
expect(runner.run).toHaveBeenCalledWith(
|
|
338
|
-
['docs', 'comments', '
|
|
339
|
-
{ account:
|
|
194
|
+
['docs', 'comments', 'list', 'abc'],
|
|
195
|
+
{ account: 'other@gmail.com' },
|
|
340
196
|
);
|
|
341
197
|
});
|
|
342
198
|
|
|
343
199
|
it('returns error text on failure', async () => {
|
|
344
|
-
vi.mocked(runner.run).mockRejectedValue(new Error('
|
|
200
|
+
vi.mocked(runner.run).mockRejectedValue(new Error('Comments failed'));
|
|
345
201
|
const handlers = setupHandlers();
|
|
346
|
-
const result = await handlers.get('
|
|
347
|
-
expect(result.content[0].text).toContain('Error:
|
|
202
|
+
const result = await handlers.get('gog_docs_comments')!({ subcommand: 'list', args: ['bad'] });
|
|
203
|
+
expect(result.content[0].text).toContain('Error: Comments failed');
|
|
348
204
|
});
|
|
349
205
|
});
|
|
350
206
|
|
package/tsconfig.json
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"moduleResolution": "NodeNext",
|
|
6
4
|
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src"
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"types": ["node"]
|
|
5
|
+
"rootDir": "./src"
|
|
12
6
|
},
|
|
13
7
|
"include": ["src/**/*"],
|
|
14
8
|
"exclude": ["node_modules", "dist"]
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
workflow_call:
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
ci:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
steps:
|
|
13
|
-
- uses: actions/checkout@v6.0.2
|
|
14
|
-
|
|
15
|
-
- uses: actions/setup-node@v6.3.0
|
|
16
|
-
with:
|
|
17
|
-
node-version: 22
|
|
18
|
-
cache: npm
|
|
19
|
-
|
|
20
|
-
- run: npm ci
|
|
21
|
-
- run: npm run build
|
|
22
|
-
- run: npm test
|