mcp-google-multi 6.0.0-beta.2 → 6.0.0-beta.4
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 +5 -5
- package/dist/accounts.d.ts +20 -4
- package/dist/accounts.js +68 -44
- package/dist/api-probe.d.ts +5 -0
- package/dist/api-probe.js +20 -15
- package/dist/arg-normalize.js +19 -38
- package/dist/arg-strict.d.ts +7 -0
- package/dist/arg-strict.js +38 -28
- package/dist/auth.d.ts +5 -4
- package/dist/auth.js +16 -23
- package/dist/boot-gates.d.ts +26 -0
- package/dist/boot-gates.js +36 -0
- package/dist/cimd-cache.d.ts +38 -0
- package/dist/cimd-cache.js +111 -0
- package/dist/client-config.d.ts +2 -2
- package/dist/client-config.js +8 -14
- package/dist/client.d.ts +32 -2
- package/dist/client.js +0 -0
- package/dist/compose.d.ts +18 -0
- package/dist/compose.js +109 -0
- package/dist/config-file.d.ts +13 -0
- package/dist/config-file.js +41 -10
- package/dist/discover.js +7 -10
- package/dist/discovery-client.d.ts +3 -0
- package/dist/discovery-client.js +36 -32
- package/dist/doctor.d.ts +9 -5
- package/dist/doctor.js +119 -29
- package/dist/env-load.js +2 -5
- package/dist/executor.d.ts +3 -0
- package/dist/executor.js +6 -6
- package/dist/fanout.d.ts +9 -1
- package/dist/fanout.js +47 -22
- package/dist/fs-atomic.d.ts +8 -0
- package/dist/fs-atomic.js +216 -29
- package/dist/hint-provider.d.ts +129 -0
- package/dist/hint-provider.js +58 -0
- package/dist/http-config.d.ts +2 -2
- package/dist/http-config.js +3 -7
- package/dist/http-transport.d.ts +67 -9
- package/dist/http-transport.js +318 -52
- package/dist/identity.d.ts +6 -3
- package/dist/identity.js +24 -8
- package/dist/index.js +76 -160
- package/dist/master-key.d.ts +3 -3
- package/dist/master-key.js +16 -19
- package/dist/mcp-token.d.ts +126 -19
- package/dist/mcp-token.js +557 -76
- package/dist/metrics-cli.d.ts +1 -1
- package/dist/metrics-cli.js +1 -1
- package/dist/metrics-tap.js +2 -5
- package/dist/migrate-config.d.ts +1 -2
- package/dist/migrate-config.js +5 -7
- package/dist/net-tuning.js +2 -4
- package/dist/oauth-as.d.ts +104 -4
- package/dist/oauth-as.js +368 -114
- package/dist/oauth-consent.d.ts +10 -0
- package/dist/oauth-consent.js +20 -10
- package/dist/outbound-allowlist.js +9 -11
- package/dist/reauth-hint.d.ts +1 -1
- package/dist/reauth-hint.js +11 -10
- package/dist/registry-transfer.d.ts +5 -0
- package/dist/registry-transfer.js +63 -11
- package/dist/registry.d.ts +13 -4
- package/dist/registry.js +100 -72
- package/dist/scope-catalog.d.ts +16 -0
- package/dist/scope-catalog.js +40 -13
- package/dist/scope-observability.d.ts +10 -9
- package/dist/scope-observability.js +34 -24
- package/dist/services.d.ts +18 -10
- package/dist/services.js +61 -22
- package/dist/ssrf-guard.d.ts +23 -9
- package/dist/ssrf-guard.js +106 -78
- package/dist/tenant-purge.d.ts +26 -0
- package/dist/tenant-purge.js +65 -0
- package/dist/token-store.d.ts +20 -2
- package/dist/token-store.js +0 -0
- package/dist/tools/_coerce.d.ts +4 -4
- package/dist/tools/_errors.d.ts +3 -0
- package/dist/tools/_errors.js +72 -60
- package/dist/tools/_local-files.d.ts +9 -0
- package/dist/tools/_local-files.js +22 -8
- package/dist/tools/account-wizard.d.ts +13 -3
- package/dist/tools/account-wizard.js +107 -56
- package/dist/tools/accounts-tool.d.ts +8 -1
- package/dist/tools/accounts-tool.js +35 -19
- package/dist/tools/admin.d.ts +10 -1
- package/dist/tools/admin.js +14 -11
- package/dist/tools/analytics.d.ts +10 -1
- package/dist/tools/analytics.js +14 -10
- package/dist/tools/calendar.d.ts +2 -1
- package/dist/tools/calendar.js +19 -18
- package/dist/tools/chat.d.ts +10 -1
- package/dist/tools/chat.js +12 -8
- package/dist/tools/contacts.d.ts +2 -1
- package/dist/tools/contacts.js +22 -19
- package/dist/tools/docs.d.ts +2 -1
- package/dist/tools/docs.js +35 -36
- package/dist/tools/drive.d.ts +2 -1
- package/dist/tools/drive.js +80 -74
- package/dist/tools/forms.d.ts +10 -1
- package/dist/tools/forms.js +18 -12
- package/dist/tools/generated/_shared.d.ts +2 -1
- package/dist/tools/generated/_shared.js +7 -3
- package/dist/tools/generated/admin.d.ts +2 -1
- package/dist/tools/generated/admin.js +265 -265
- package/dist/tools/generated/analytics.d.ts +2 -1
- package/dist/tools/generated/analytics.js +125 -125
- package/dist/tools/generated/appsmarket.d.ts +2 -1
- package/dist/tools/generated/appsmarket.js +5 -5
- package/dist/tools/generated/calendar.d.ts +2 -1
- package/dist/tools/generated/calendar.js +55 -55
- package/dist/tools/generated/chat.d.ts +2 -1
- package/dist/tools/generated/chat.js +95 -95
- package/dist/tools/generated/classroom.d.ts +2 -1
- package/dist/tools/generated/classroom.js +209 -209
- package/dist/tools/generated/cloudidentity.d.ts +2 -1
- package/dist/tools/generated/cloudidentity.js +133 -133
- package/dist/tools/generated/cloudsearch.d.ts +2 -1
- package/dist/tools/generated/cloudsearch.js +99 -99
- package/dist/tools/generated/contacts.d.ts +2 -1
- package/dist/tools/generated/contacts.js +29 -29
- package/dist/tools/generated/drive.d.ts +2 -1
- package/dist/tools/generated/drive.js +71 -71
- package/dist/tools/generated/driveactivity.d.ts +2 -1
- package/dist/tools/generated/driveactivity.js +3 -3
- package/dist/tools/generated/drivelabels.d.ts +2 -1
- package/dist/tools/generated/drivelabels.js +53 -53
- package/dist/tools/generated/forms.d.ts +2 -1
- package/dist/tools/generated/forms.js +7 -7
- package/dist/tools/generated/gmail.d.ts +2 -1
- package/dist/tools/generated/gmail.js +117 -117
- package/dist/tools/generated/groupsmigration.d.ts +2 -1
- package/dist/tools/generated/groupsmigration.js +3 -3
- package/dist/tools/generated/groupssettings.d.ts +2 -1
- package/dist/tools/generated/groupssettings.js +7 -7
- package/dist/tools/generated/index.d.ts +2 -1
- package/dist/tools/generated/keep.d.ts +2 -1
- package/dist/tools/generated/keep.js +15 -15
- package/dist/tools/generated/licensing.d.ts +2 -1
- package/dist/tools/generated/licensing.js +15 -15
- package/dist/tools/generated/meet.d.ts +2 -1
- package/dist/tools/generated/meet.js +27 -27
- package/dist/tools/generated/postmaster.d.ts +2 -1
- package/dist/tools/generated/postmaster.js +9 -9
- package/dist/tools/generated/reseller.d.ts +2 -1
- package/dist/tools/generated/reseller.js +35 -35
- package/dist/tools/generated/script.d.ts +2 -1
- package/dist/tools/generated/script.js +33 -33
- package/dist/tools/generated/searchconsole.d.ts +2 -1
- package/dist/tools/generated/searchconsole.js +3 -3
- package/dist/tools/generated/sheets.d.ts +2 -1
- package/dist/tools/generated/sheets.js +15 -15
- package/dist/tools/generated/tasks.d.ts +2 -1
- package/dist/tools/generated/tasks.js +5 -5
- package/dist/tools/generated/vault.d.ts +2 -1
- package/dist/tools/generated/vault.js +67 -67
- package/dist/tools/generated/workspaceevents.d.ts +2 -1
- package/dist/tools/generated/workspaceevents.js +31 -31
- package/dist/tools/gmail-mime.d.ts +1 -1
- package/dist/tools/gmail-mime.js +7 -12
- package/dist/tools/gmail.d.ts +4 -3
- package/dist/tools/gmail.js +67 -69
- package/dist/tools/google-api.d.ts +2 -3
- package/dist/tools/google-api.js +34 -22
- package/dist/tools/meet.d.ts +10 -1
- package/dist/tools/meet.js +12 -9
- package/dist/tools/searchconsole.d.ts +2 -1
- package/dist/tools/searchconsole.js +16 -13
- package/dist/tools/sheets.d.ts +2 -1
- package/dist/tools/sheets.js +35 -32
- package/dist/tools/slides.d.ts +10 -1
- package/dist/tools/slides.js +16 -10
- package/dist/tools/tasks.d.ts +2 -1
- package/dist/tools/tasks.js +18 -15
- package/dist/trim.d.ts +5 -0
- package/dist/trim.js +19 -0
- package/dist/usage-metrics.d.ts +23 -0
- package/dist/usage-metrics.js +67 -56
- package/dist/write-control.d.ts +4 -8
- package/dist/write-control.js +13 -6
- package/package.json +47 -21
|
@@ -2,11 +2,14 @@ import { z } from 'zod';
|
|
|
2
2
|
import { coerceArray, coerceJson } from './_coerce.js';
|
|
3
3
|
import { searchconsole as searchconsoleClient } from '@googleapis/searchconsole';
|
|
4
4
|
import { webmasters as webmastersClient } from '@googleapis/webmasters';
|
|
5
|
-
import {
|
|
5
|
+
import { accountArgLive } from '../accounts.js';
|
|
6
6
|
import { getClient } from '../client.js';
|
|
7
7
|
import { handleGoogleApiError } from './_errors.js';
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
export function registerSearchConsoleTools(server, deps = {}) {
|
|
9
|
+
// Per-registry, live account enum + injectable client: the schema follows
|
|
10
|
+
// the registry's account view at parse time, not a process-global default.
|
|
11
|
+
const accountEnum = accountArgLive(() => server.accountAliases()).optional();
|
|
12
|
+
const getClientFn = deps.getClientFn ?? getClient;
|
|
10
13
|
// ─── Sites ───────────────────────────────────────────────
|
|
11
14
|
server.registerTool('searchconsole_sites_list', {
|
|
12
15
|
description: 'List all sites (properties) the account has access to in Google Search Console',
|
|
@@ -15,7 +18,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
15
18
|
},
|
|
16
19
|
}, async ({ account }) => {
|
|
17
20
|
try {
|
|
18
|
-
const auth = await
|
|
21
|
+
const auth = await getClientFn(account);
|
|
19
22
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
20
23
|
const res = await wm.sites.list();
|
|
21
24
|
return {
|
|
@@ -34,7 +37,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
34
37
|
},
|
|
35
38
|
}, async ({ account, siteUrl }) => {
|
|
36
39
|
try {
|
|
37
|
-
const auth = await
|
|
40
|
+
const auth = await getClientFn(account);
|
|
38
41
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
39
42
|
const res = await wm.sites.get({ siteUrl });
|
|
40
43
|
return {
|
|
@@ -53,7 +56,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
53
56
|
},
|
|
54
57
|
}, async ({ account, siteUrl }) => {
|
|
55
58
|
try {
|
|
56
|
-
const auth = await
|
|
59
|
+
const auth = await getClientFn(account);
|
|
57
60
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
58
61
|
await wm.sites.add({ siteUrl });
|
|
59
62
|
return {
|
|
@@ -72,7 +75,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
72
75
|
},
|
|
73
76
|
}, async ({ account, siteUrl }) => {
|
|
74
77
|
try {
|
|
75
|
-
const auth = await
|
|
78
|
+
const auth = await getClientFn(account);
|
|
76
79
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
77
80
|
await wm.sites.delete({ siteUrl });
|
|
78
81
|
return {
|
|
@@ -92,7 +95,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
92
95
|
},
|
|
93
96
|
}, async ({ account, siteUrl }) => {
|
|
94
97
|
try {
|
|
95
|
-
const auth = await
|
|
98
|
+
const auth = await getClientFn(account);
|
|
96
99
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
97
100
|
const res = await wm.sitemaps.list({ siteUrl });
|
|
98
101
|
return {
|
|
@@ -112,7 +115,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
112
115
|
},
|
|
113
116
|
}, async ({ account, siteUrl, feedpath }) => {
|
|
114
117
|
try {
|
|
115
|
-
const auth = await
|
|
118
|
+
const auth = await getClientFn(account);
|
|
116
119
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
117
120
|
const res = await wm.sitemaps.get({ siteUrl, feedpath });
|
|
118
121
|
return {
|
|
@@ -132,7 +135,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
132
135
|
},
|
|
133
136
|
}, async ({ account, siteUrl, feedpath }) => {
|
|
134
137
|
try {
|
|
135
|
-
const auth = await
|
|
138
|
+
const auth = await getClientFn(account);
|
|
136
139
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
137
140
|
await wm.sitemaps.submit({ siteUrl, feedpath });
|
|
138
141
|
return {
|
|
@@ -152,7 +155,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
152
155
|
},
|
|
153
156
|
}, async ({ account, siteUrl, feedpath }) => {
|
|
154
157
|
try {
|
|
155
|
-
const auth = await
|
|
158
|
+
const auth = await getClientFn(account);
|
|
156
159
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
157
160
|
await wm.sitemaps.delete({ siteUrl, feedpath });
|
|
158
161
|
return {
|
|
@@ -195,7 +198,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
195
198
|
},
|
|
196
199
|
}, async ({ account, siteUrl, startDate, endDate, dimensions, type, dimensionFilterGroups, rowLimit, startRow, aggregationType, dataState }) => {
|
|
197
200
|
try {
|
|
198
|
-
const auth = await
|
|
201
|
+
const auth = await getClientFn(account);
|
|
199
202
|
const wm = webmastersClient({ version: 'v3', auth });
|
|
200
203
|
const requestBody = { startDate, endDate };
|
|
201
204
|
if (dimensions)
|
|
@@ -237,7 +240,7 @@ export function registerSearchConsoleTools(server) {
|
|
|
237
240
|
},
|
|
238
241
|
}, async ({ account, siteUrl, inspectionUrl, languageCode }) => {
|
|
239
242
|
try {
|
|
240
|
-
const auth = await
|
|
243
|
+
const auth = await getClientFn(account);
|
|
241
244
|
const searchconsole = searchconsoleClient({ version: 'v1', auth });
|
|
242
245
|
const res = await searchconsole.urlInspection.index.inspect({
|
|
243
246
|
requestBody: {
|
package/dist/tools/sheets.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
|
-
|
|
2
|
+
import { type CuratedToolDeps } from '../client.js';
|
|
3
|
+
export declare function registerSheetsTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
|
|
3
4
|
export declare function buildCellFormat(input: {
|
|
4
5
|
backgroundColor?: {
|
|
5
6
|
red?: number;
|
package/dist/tools/sheets.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceArray, coerceBoolean, coerceJson } from './_coerce.js';
|
|
3
3
|
import { sheets as sheetsClient } from '@googleapis/sheets';
|
|
4
|
-
import {
|
|
4
|
+
import { accountArgLive } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError, invalidParams } from './_errors.js';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
export function registerSheetsTools(server, deps = {}) {
|
|
8
|
+
// Per-registry, live account enum + injectable client: the schema follows
|
|
9
|
+
// the registry's account view at parse time, not a process-global default.
|
|
10
|
+
const accountEnum = accountArgLive(() => server.accountAliases()).optional();
|
|
11
|
+
const getClientFn = deps.getClientFn ?? getClient;
|
|
9
12
|
server.registerTool('sheets_create', {
|
|
10
13
|
description: 'Create a new Google Sheets spreadsheet',
|
|
11
14
|
inputSchema: {
|
|
@@ -16,7 +19,7 @@ export function registerSheetsTools(server) {
|
|
|
16
19
|
},
|
|
17
20
|
}, async ({ account, title, sheetTitles }) => {
|
|
18
21
|
try {
|
|
19
|
-
const auth = await
|
|
22
|
+
const auth = await getClientFn(account);
|
|
20
23
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
21
24
|
const requestBody = {
|
|
22
25
|
properties: { title },
|
|
@@ -48,7 +51,7 @@ export function registerSheetsTools(server) {
|
|
|
48
51
|
},
|
|
49
52
|
}, async ({ account, spreadsheetId }) => {
|
|
50
53
|
try {
|
|
51
|
-
const auth = await
|
|
54
|
+
const auth = await getClientFn(account);
|
|
52
55
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
53
56
|
const res = await sheets.spreadsheets.get({
|
|
54
57
|
spreadsheetId,
|
|
@@ -85,7 +88,7 @@ export function registerSheetsTools(server) {
|
|
|
85
88
|
},
|
|
86
89
|
}, async ({ account, spreadsheetId, range, valueRenderOption }) => {
|
|
87
90
|
try {
|
|
88
|
-
const auth = await
|
|
91
|
+
const auth = await getClientFn(account);
|
|
89
92
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
90
93
|
const res = await sheets.spreadsheets.values.get({
|
|
91
94
|
spreadsheetId,
|
|
@@ -115,7 +118,7 @@ export function registerSheetsTools(server) {
|
|
|
115
118
|
},
|
|
116
119
|
}, async ({ account, spreadsheetId, range, values, valueInputOption }) => {
|
|
117
120
|
try {
|
|
118
|
-
const auth = await
|
|
121
|
+
const auth = await getClientFn(account);
|
|
119
122
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
120
123
|
const res = await sheets.spreadsheets.values.update({
|
|
121
124
|
spreadsheetId,
|
|
@@ -148,7 +151,7 @@ export function registerSheetsTools(server) {
|
|
|
148
151
|
},
|
|
149
152
|
}, async ({ account, spreadsheetId, range, values, valueInputOption }) => {
|
|
150
153
|
try {
|
|
151
|
-
const auth = await
|
|
154
|
+
const auth = await getClientFn(account);
|
|
152
155
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
153
156
|
const res = await sheets.spreadsheets.values.append({
|
|
154
157
|
spreadsheetId,
|
|
@@ -179,7 +182,7 @@ export function registerSheetsTools(server) {
|
|
|
179
182
|
},
|
|
180
183
|
}, async ({ account, spreadsheetId, range }) => {
|
|
181
184
|
try {
|
|
182
|
-
const auth = await
|
|
185
|
+
const auth = await getClientFn(account);
|
|
183
186
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
184
187
|
const res = await sheets.spreadsheets.values.clear({
|
|
185
188
|
spreadsheetId,
|
|
@@ -208,7 +211,7 @@ export function registerSheetsTools(server) {
|
|
|
208
211
|
},
|
|
209
212
|
}, async ({ account, spreadsheetId, ranges, valueRenderOption }) => {
|
|
210
213
|
try {
|
|
211
|
-
const auth = await
|
|
214
|
+
const auth = await getClientFn(account);
|
|
212
215
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
213
216
|
const res = await sheets.spreadsheets.values.batchGet({
|
|
214
217
|
spreadsheetId,
|
|
@@ -241,7 +244,7 @@ export function registerSheetsTools(server) {
|
|
|
241
244
|
},
|
|
242
245
|
}, async ({ account, spreadsheetId, data, valueInputOption }) => {
|
|
243
246
|
try {
|
|
244
|
-
const auth = await
|
|
247
|
+
const auth = await getClientFn(account);
|
|
245
248
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
246
249
|
const res = await sheets.spreadsheets.values.batchUpdate({
|
|
247
250
|
spreadsheetId,
|
|
@@ -277,7 +280,7 @@ export function registerSheetsTools(server) {
|
|
|
277
280
|
},
|
|
278
281
|
}, async ({ account, spreadsheetId, title, rowCount, columnCount }) => {
|
|
279
282
|
try {
|
|
280
|
-
const auth = await
|
|
283
|
+
const auth = await getClientFn(account);
|
|
281
284
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
282
285
|
const res = await sheets.spreadsheets.batchUpdate({
|
|
283
286
|
spreadsheetId,
|
|
@@ -318,7 +321,7 @@ export function registerSheetsTools(server) {
|
|
|
318
321
|
},
|
|
319
322
|
}, async ({ account, spreadsheetId, sheetId }) => {
|
|
320
323
|
try {
|
|
321
|
-
const auth = await
|
|
324
|
+
const auth = await getClientFn(account);
|
|
322
325
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
323
326
|
await sheets.spreadsheets.batchUpdate({
|
|
324
327
|
spreadsheetId,
|
|
@@ -343,7 +346,7 @@ export function registerSheetsTools(server) {
|
|
|
343
346
|
},
|
|
344
347
|
}, async ({ account, spreadsheetId, sourceSheetId, newSheetName, insertSheetIndex }) => {
|
|
345
348
|
try {
|
|
346
|
-
const auth = await
|
|
349
|
+
const auth = await getClientFn(account);
|
|
347
350
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
348
351
|
const res = await sheets.spreadsheets.batchUpdate({
|
|
349
352
|
spreadsheetId,
|
|
@@ -383,7 +386,7 @@ export function registerSheetsTools(server) {
|
|
|
383
386
|
},
|
|
384
387
|
}, async ({ account, spreadsheetId, sheetId, title, index, hidden, tabColor, frozenRowCount, frozenColumnCount, rowCount, columnCount }) => {
|
|
385
388
|
try {
|
|
386
|
-
const auth = await
|
|
389
|
+
const auth = await getClientFn(account);
|
|
387
390
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
388
391
|
const properties = { sheetId };
|
|
389
392
|
const fields = [];
|
|
@@ -475,7 +478,7 @@ export function registerSheetsTools(server) {
|
|
|
475
478
|
},
|
|
476
479
|
}, async ({ account, spreadsheetId, range, ...format }) => {
|
|
477
480
|
try {
|
|
478
|
-
const auth = await
|
|
481
|
+
const auth = await getClientFn(account);
|
|
479
482
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
480
483
|
const built = buildCellFormat(format);
|
|
481
484
|
if (built.fields.length === 0) {
|
|
@@ -516,7 +519,7 @@ export function registerSheetsTools(server) {
|
|
|
516
519
|
},
|
|
517
520
|
}, async ({ account, spreadsheetId, range, top, bottom, left, right, innerHorizontal, innerVertical }) => {
|
|
518
521
|
try {
|
|
519
|
-
const auth = await
|
|
522
|
+
const auth = await getClientFn(account);
|
|
520
523
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
521
524
|
const borders = { range };
|
|
522
525
|
if (top)
|
|
@@ -556,7 +559,7 @@ export function registerSheetsTools(server) {
|
|
|
556
559
|
},
|
|
557
560
|
}, async ({ account, spreadsheetId, range, mergeType }) => {
|
|
558
561
|
try {
|
|
559
|
-
const auth = await
|
|
562
|
+
const auth = await getClientFn(account);
|
|
560
563
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
561
564
|
await sheets.spreadsheets.batchUpdate({
|
|
562
565
|
spreadsheetId,
|
|
@@ -581,7 +584,7 @@ export function registerSheetsTools(server) {
|
|
|
581
584
|
},
|
|
582
585
|
}, async ({ account, spreadsheetId, range }) => {
|
|
583
586
|
try {
|
|
584
|
-
const auth = await
|
|
587
|
+
const auth = await getClientFn(account);
|
|
585
588
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
586
589
|
await sheets.spreadsheets.batchUpdate({
|
|
587
590
|
spreadsheetId,
|
|
@@ -628,7 +631,7 @@ export function registerSheetsTools(server) {
|
|
|
628
631
|
if (!booleanRule && !gradientRule) {
|
|
629
632
|
return invalidParams(account, 'A conditional format rule needs a rule body: neither booleanRule nor gradientRule was supplied.', 'Pass booleanRule for a condition-based rule, or gradientRule for a color scale.');
|
|
630
633
|
}
|
|
631
|
-
const auth = await
|
|
634
|
+
const auth = await getClientFn(account);
|
|
632
635
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
633
636
|
const rule = { ranges };
|
|
634
637
|
if (booleanRule) {
|
|
@@ -692,7 +695,7 @@ export function registerSheetsTools(server) {
|
|
|
692
695
|
},
|
|
693
696
|
}, async ({ account, spreadsheetId, range, sortSpecs }) => {
|
|
694
697
|
try {
|
|
695
|
-
const auth = await
|
|
698
|
+
const auth = await getClientFn(account);
|
|
696
699
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
697
700
|
await sheets.spreadsheets.batchUpdate({
|
|
698
701
|
spreadsheetId,
|
|
@@ -724,7 +727,7 @@ export function registerSheetsTools(server) {
|
|
|
724
727
|
},
|
|
725
728
|
}, async ({ account, spreadsheetId, range, sortSpecs, filterSpecs }) => {
|
|
726
729
|
try {
|
|
727
|
-
const auth = await
|
|
730
|
+
const auth = await getClientFn(account);
|
|
728
731
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
729
732
|
const filter = { range };
|
|
730
733
|
if (sortSpecs)
|
|
@@ -766,7 +769,7 @@ export function registerSheetsTools(server) {
|
|
|
766
769
|
},
|
|
767
770
|
}, async ({ account, spreadsheetId, sheetId }) => {
|
|
768
771
|
try {
|
|
769
|
-
const auth = await
|
|
772
|
+
const auth = await getClientFn(account);
|
|
770
773
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
771
774
|
await sheets.spreadsheets.batchUpdate({
|
|
772
775
|
spreadsheetId,
|
|
@@ -799,7 +802,7 @@ export function registerSheetsTools(server) {
|
|
|
799
802
|
},
|
|
800
803
|
}, async ({ account, spreadsheetId, find, replacement, scope, sheetId, range, matchCase, matchEntireCell, searchByRegex, includeFormulas }) => {
|
|
801
804
|
try {
|
|
802
|
-
const auth = await
|
|
805
|
+
const auth = await getClientFn(account);
|
|
803
806
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
804
807
|
const findReplace = {
|
|
805
808
|
find,
|
|
@@ -855,7 +858,7 @@ export function registerSheetsTools(server) {
|
|
|
855
858
|
},
|
|
856
859
|
}, async ({ account, spreadsheetId, sheetId, dimension, startIndex, endIndex }) => {
|
|
857
860
|
try {
|
|
858
|
-
const auth = await
|
|
861
|
+
const auth = await getClientFn(account);
|
|
859
862
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
860
863
|
const dimensions = { sheetId, dimension };
|
|
861
864
|
if (startIndex !== undefined)
|
|
@@ -887,7 +890,7 @@ export function registerSheetsTools(server) {
|
|
|
887
890
|
},
|
|
888
891
|
}, async ({ account, spreadsheetId, sheetId, dimension, startIndex, endIndex, inheritFromBefore }) => {
|
|
889
892
|
try {
|
|
890
|
-
const auth = await
|
|
893
|
+
const auth = await getClientFn(account);
|
|
891
894
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
892
895
|
await sheets.spreadsheets.batchUpdate({
|
|
893
896
|
spreadsheetId,
|
|
@@ -920,7 +923,7 @@ export function registerSheetsTools(server) {
|
|
|
920
923
|
},
|
|
921
924
|
}, async ({ account, spreadsheetId, sheetId, dimension, startIndex, endIndex }) => {
|
|
922
925
|
try {
|
|
923
|
-
const auth = await
|
|
926
|
+
const auth = await getClientFn(account);
|
|
924
927
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
925
928
|
await sheets.spreadsheets.batchUpdate({
|
|
926
929
|
spreadsheetId,
|
|
@@ -955,7 +958,7 @@ export function registerSheetsTools(server) {
|
|
|
955
958
|
},
|
|
956
959
|
}, async ({ account, spreadsheetId, range, conditionType, conditionValues, inputMessage, strict, showCustomUi }) => {
|
|
957
960
|
try {
|
|
958
|
-
const auth = await
|
|
961
|
+
const auth = await getClientFn(account);
|
|
959
962
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
960
963
|
const rule = {
|
|
961
964
|
condition: {
|
|
@@ -993,7 +996,7 @@ export function registerSheetsTools(server) {
|
|
|
993
996
|
},
|
|
994
997
|
}, async ({ account, spreadsheetId, name, range }) => {
|
|
995
998
|
try {
|
|
996
|
-
const auth = await
|
|
999
|
+
const auth = await getClientFn(account);
|
|
997
1000
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
998
1001
|
const res = await sheets.spreadsheets.batchUpdate({
|
|
999
1002
|
spreadsheetId,
|
|
@@ -1019,7 +1022,7 @@ export function registerSheetsTools(server) {
|
|
|
1019
1022
|
},
|
|
1020
1023
|
}, async ({ account, spreadsheetId, namedRangeId }) => {
|
|
1021
1024
|
try {
|
|
1022
|
-
const auth = await
|
|
1025
|
+
const auth = await getClientFn(account);
|
|
1023
1026
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
1024
1027
|
await sheets.spreadsheets.batchUpdate({
|
|
1025
1028
|
spreadsheetId,
|
|
@@ -1043,7 +1046,7 @@ export function registerSheetsTools(server) {
|
|
|
1043
1046
|
},
|
|
1044
1047
|
}, async ({ account, spreadsheetId, ranges }) => {
|
|
1045
1048
|
try {
|
|
1046
|
-
const auth = await
|
|
1049
|
+
const auth = await getClientFn(account);
|
|
1047
1050
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
1048
1051
|
const res = await sheets.spreadsheets.values.batchClear({
|
|
1049
1052
|
spreadsheetId,
|
|
@@ -1073,7 +1076,7 @@ export function registerSheetsTools(server) {
|
|
|
1073
1076
|
},
|
|
1074
1077
|
}, async ({ account, spreadsheetId, requests, includeSpreadsheetInResponse, responseRanges, responseIncludeGridData }) => {
|
|
1075
1078
|
try {
|
|
1076
|
-
const auth = await
|
|
1079
|
+
const auth = await getClientFn(account);
|
|
1077
1080
|
const sheets = sheetsClient({ version: 'v4', auth });
|
|
1078
1081
|
const res = await sheets.spreadsheets.batchUpdate({
|
|
1079
1082
|
spreadsheetId,
|
package/dist/tools/slides.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
|
-
|
|
2
|
+
import type { Account } from '../accounts.js';
|
|
3
|
+
import { type CuratedToolDeps } from '../client.js';
|
|
4
|
+
export declare function registerSlidesTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
|
|
3
5
|
export declare function extractPageText(elements: Array<Record<string, any>> | undefined): string;
|
|
4
6
|
export declare function summarizePresentation(p: Record<string, any>): Record<string, unknown>;
|
|
7
|
+
export declare function handleSlidesError(error: any, account: Account): {
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
isError: true;
|
|
13
|
+
};
|
package/dist/tools/slides.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { slides as slidesClient } from '@googleapis/slides';
|
|
3
|
-
import {
|
|
3
|
+
import { accountArgLive } from '../accounts.js';
|
|
4
4
|
import { getClient } from '../client.js';
|
|
5
5
|
import { handleGoogleApiError } from './_errors.js';
|
|
6
6
|
import { coerceArray, coerceBoolean, coerceJson } from './_coerce.js';
|
|
7
7
|
import { sliceClean } from '../trim.js';
|
|
8
|
-
const accountEnum = accountAliasSchema.optional();
|
|
9
8
|
const SLIDE_TEXT_DIGEST_CHARS = 200;
|
|
10
|
-
export function registerSlidesTools(server) {
|
|
9
|
+
export function registerSlidesTools(server, deps = {}) {
|
|
10
|
+
// Per-registry, live account enum + injectable client: the schema follows
|
|
11
|
+
// the registry's account view at parse time, not a process-global default.
|
|
12
|
+
const accountEnum = accountArgLive(() => server.accountAliases()).optional();
|
|
13
|
+
const getClientFn = deps.getClientFn ?? getClient;
|
|
11
14
|
server.registerTool('slides_create', {
|
|
12
15
|
description: 'Create a new Google Slides presentation (starts with one blank slide)',
|
|
13
16
|
inputSchema: {
|
|
@@ -16,7 +19,7 @@ export function registerSlidesTools(server) {
|
|
|
16
19
|
},
|
|
17
20
|
}, async ({ account, title }) => {
|
|
18
21
|
try {
|
|
19
|
-
const auth = await
|
|
22
|
+
const auth = await getClientFn(account);
|
|
20
23
|
const slides = slidesClient({ version: 'v1', auth });
|
|
21
24
|
const res = await slides.presentations.create({ requestBody: { title } });
|
|
22
25
|
return {
|
|
@@ -41,7 +44,7 @@ export function registerSlidesTools(server) {
|
|
|
41
44
|
},
|
|
42
45
|
}, async ({ account, presentationId, full }) => {
|
|
43
46
|
try {
|
|
44
|
-
const auth = await
|
|
47
|
+
const auth = await getClientFn(account);
|
|
45
48
|
const slides = slidesClient({ version: 'v1', auth });
|
|
46
49
|
const res = await slides.presentations.get({ presentationId });
|
|
47
50
|
const payload = full ? res.data : summarizePresentation(res.data);
|
|
@@ -62,7 +65,7 @@ export function registerSlidesTools(server) {
|
|
|
62
65
|
},
|
|
63
66
|
}, async ({ account, presentationId, pageObjectId }) => {
|
|
64
67
|
try {
|
|
65
|
-
const auth = await
|
|
68
|
+
const auth = await getClientFn(account);
|
|
66
69
|
const slides = slidesClient({ version: 'v1', auth });
|
|
67
70
|
const res = await slides.presentations.pages.get({ presentationId, pageObjectId });
|
|
68
71
|
return {
|
|
@@ -85,7 +88,7 @@ export function registerSlidesTools(server) {
|
|
|
85
88
|
},
|
|
86
89
|
}, async ({ account, presentationId, pageObjectId, mimeType, thumbnailSize }) => {
|
|
87
90
|
try {
|
|
88
|
-
const auth = await
|
|
91
|
+
const auth = await getClientFn(account);
|
|
89
92
|
const slides = slidesClient({ version: 'v1', auth });
|
|
90
93
|
const res = await slides.presentations.pages.getThumbnail({
|
|
91
94
|
presentationId,
|
|
@@ -116,7 +119,7 @@ export function registerSlidesTools(server) {
|
|
|
116
119
|
},
|
|
117
120
|
}, async ({ account, presentationId, requests, writeControl }) => {
|
|
118
121
|
try {
|
|
119
|
-
const auth = await
|
|
122
|
+
const auth = await getClientFn(account);
|
|
120
123
|
const slides = slidesClient({ version: 'v1', auth });
|
|
121
124
|
const res = await slides.presentations.batchUpdate({
|
|
122
125
|
presentationId,
|
|
@@ -180,6 +183,9 @@ export function summarizePresentation(p) {
|
|
|
180
183
|
hint: 'Pass full:true for the raw Presentation JSON, or slides_page_get for one slide.',
|
|
181
184
|
};
|
|
182
185
|
}
|
|
183
|
-
function handleSlidesError(error, account) {
|
|
184
|
-
return handleGoogleApiError(error, account,
|
|
186
|
+
export function handleSlidesError(error, account) {
|
|
187
|
+
return handleGoogleApiError(error, account, {
|
|
188
|
+
scope: "Slides tools require the optional \"slides\" scope bundle. Add GOOGLE_OPTIONAL_SCOPES=slides (or include \"slides\" in the list) and re-auth.",
|
|
189
|
+
bundle: 'slides',
|
|
190
|
+
});
|
|
185
191
|
}
|
package/dist/tools/tasks.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { ToolRegistry } from '../registry.js';
|
|
2
|
-
|
|
2
|
+
import { type CuratedToolDeps } from '../client.js';
|
|
3
|
+
export declare function registerTasksTools(server: ToolRegistry, deps?: CuratedToolDeps): void;
|
package/dist/tools/tasks.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { coerceBoolean } from './_coerce.js';
|
|
3
3
|
import { tasks as tasksClient } from '@googleapis/tasks';
|
|
4
|
-
import {
|
|
4
|
+
import { accountArgLive } from '../accounts.js';
|
|
5
5
|
import { getClient } from '../client.js';
|
|
6
6
|
import { handleGoogleApiError, invalidParams } from './_errors.js';
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
export function registerTasksTools(server, deps = {}) {
|
|
8
|
+
// Per-registry, live account enum + injectable client: the schema follows
|
|
9
|
+
// the registry's account view at parse time, not a process-global default.
|
|
10
|
+
const accountEnum = accountArgLive(() => server.accountAliases()).optional();
|
|
11
|
+
const getClientFn = deps.getClientFn ?? getClient;
|
|
9
12
|
// ─── Tasklists ─────────────────────────────────────────────────────────
|
|
10
13
|
server.registerTool('tasks_lists_list', {
|
|
11
14
|
description: 'List all tasklists (the user\'s top-level task containers)',
|
|
@@ -16,7 +19,7 @@ export function registerTasksTools(server) {
|
|
|
16
19
|
},
|
|
17
20
|
}, async ({ account, maxResults, pageToken }) => {
|
|
18
21
|
try {
|
|
19
|
-
const auth = await
|
|
22
|
+
const auth = await getClientFn(account);
|
|
20
23
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
21
24
|
const res = await tasks.tasklists.list({
|
|
22
25
|
maxResults: maxResults ?? 100,
|
|
@@ -38,7 +41,7 @@ export function registerTasksTools(server) {
|
|
|
38
41
|
},
|
|
39
42
|
}, async ({ account, tasklistId }) => {
|
|
40
43
|
try {
|
|
41
|
-
const auth = await
|
|
44
|
+
const auth = await getClientFn(account);
|
|
42
45
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
43
46
|
const res = await tasks.tasklists.get({ tasklist: tasklistId });
|
|
44
47
|
return {
|
|
@@ -57,7 +60,7 @@ export function registerTasksTools(server) {
|
|
|
57
60
|
},
|
|
58
61
|
}, async ({ account, title }) => {
|
|
59
62
|
try {
|
|
60
|
-
const auth = await
|
|
63
|
+
const auth = await getClientFn(account);
|
|
61
64
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
62
65
|
const res = await tasks.tasklists.insert({
|
|
63
66
|
requestBody: { title },
|
|
@@ -79,7 +82,7 @@ export function registerTasksTools(server) {
|
|
|
79
82
|
},
|
|
80
83
|
}, async ({ account, tasklistId, title }) => {
|
|
81
84
|
try {
|
|
82
|
-
const auth = await
|
|
85
|
+
const auth = await getClientFn(account);
|
|
83
86
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
84
87
|
const res = await tasks.tasklists.patch({
|
|
85
88
|
tasklist: tasklistId,
|
|
@@ -101,7 +104,7 @@ export function registerTasksTools(server) {
|
|
|
101
104
|
},
|
|
102
105
|
}, async ({ account, tasklistId }) => {
|
|
103
106
|
try {
|
|
104
|
-
const auth = await
|
|
107
|
+
const auth = await getClientFn(account);
|
|
105
108
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
106
109
|
await tasks.tasklists.delete({ tasklist: tasklistId });
|
|
107
110
|
return {
|
|
@@ -132,7 +135,7 @@ export function registerTasksTools(server) {
|
|
|
132
135
|
},
|
|
133
136
|
}, async ({ account, tasklistId, ...params }) => {
|
|
134
137
|
try {
|
|
135
|
-
const auth = await
|
|
138
|
+
const auth = await getClientFn(account);
|
|
136
139
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
137
140
|
const res = await tasks.tasks.list({
|
|
138
141
|
tasklist: tasklistId,
|
|
@@ -155,7 +158,7 @@ export function registerTasksTools(server) {
|
|
|
155
158
|
},
|
|
156
159
|
}, async ({ account, tasklistId, taskId }) => {
|
|
157
160
|
try {
|
|
158
|
-
const auth = await
|
|
161
|
+
const auth = await getClientFn(account);
|
|
159
162
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
160
163
|
const res = await tasks.tasks.get({ tasklist: tasklistId, task: taskId });
|
|
161
164
|
return {
|
|
@@ -180,7 +183,7 @@ export function registerTasksTools(server) {
|
|
|
180
183
|
},
|
|
181
184
|
}, async ({ account, tasklistId, title, notes, due, status, parent, previous }) => {
|
|
182
185
|
try {
|
|
183
|
-
const auth = await
|
|
186
|
+
const auth = await getClientFn(account);
|
|
184
187
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
185
188
|
const requestBody = { title };
|
|
186
189
|
if (notes !== undefined)
|
|
@@ -216,7 +219,7 @@ export function registerTasksTools(server) {
|
|
|
216
219
|
},
|
|
217
220
|
}, async ({ account, tasklistId, taskId, title, notes, due, status }) => {
|
|
218
221
|
try {
|
|
219
|
-
const auth = await
|
|
222
|
+
const auth = await getClientFn(account);
|
|
220
223
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
221
224
|
const requestBody = {};
|
|
222
225
|
if (title !== undefined)
|
|
@@ -252,7 +255,7 @@ export function registerTasksTools(server) {
|
|
|
252
255
|
},
|
|
253
256
|
}, async ({ account, tasklistId, taskId }) => {
|
|
254
257
|
try {
|
|
255
|
-
const auth = await
|
|
258
|
+
const auth = await getClientFn(account);
|
|
256
259
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
257
260
|
await tasks.tasks.delete({ tasklist: tasklistId, task: taskId });
|
|
258
261
|
return {
|
|
@@ -275,7 +278,7 @@ export function registerTasksTools(server) {
|
|
|
275
278
|
},
|
|
276
279
|
}, async ({ account, tasklistId, taskId, parent, previous, destinationTasklist }) => {
|
|
277
280
|
try {
|
|
278
|
-
const auth = await
|
|
281
|
+
const auth = await getClientFn(account);
|
|
279
282
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
280
283
|
const res = await tasks.tasks.move({
|
|
281
284
|
tasklist: tasklistId,
|
|
@@ -300,7 +303,7 @@ export function registerTasksTools(server) {
|
|
|
300
303
|
},
|
|
301
304
|
}, async ({ account, tasklistId }) => {
|
|
302
305
|
try {
|
|
303
|
-
const auth = await
|
|
306
|
+
const auth = await getClientFn(account);
|
|
304
307
|
const tasks = tasksClient({ version: 'v1', auth });
|
|
305
308
|
await tasks.tasks.clear({ tasklist: tasklistId });
|
|
306
309
|
return {
|
package/dist/trim.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ export interface CappedText {
|
|
|
6
6
|
}
|
|
7
7
|
export declare function capText(text: string, maxChars: number, offset?: number): CappedText;
|
|
8
8
|
export declare function sliceClean(text: string, max: number): string;
|
|
9
|
+
/** An untrusted value made fit for one log line: never throws, at most `max`
|
|
10
|
+
* characters of it (then `...(len=N)`), each unsafe character as a literal
|
|
11
|
+
* `\uXXXX`. Backslash stays as is, so a value already through here comes back
|
|
12
|
+
* unchanged and a clean short value keeps its exact text. */
|
|
13
|
+
export declare function logSafe(value: unknown, max: number): string;
|
|
9
14
|
/** Largest prefix whose JSON encoding (the wrapping quotes included) fits
|
|
10
15
|
* `maxEncoded`. Slicing raw characters overshoots whenever the text contains
|
|
11
16
|
* quotes or backslashes, which JSON.stringify doubles: the escape hatch's
|
package/dist/trim.js
CHANGED
|
@@ -11,6 +11,25 @@ export function sliceClean(text, max) {
|
|
|
11
11
|
const sliced = text.slice(0, max);
|
|
12
12
|
return /[\uD800-\uDBFF]$/.test(sliced) ? sliced.slice(0, -1) : sliced;
|
|
13
13
|
}
|
|
14
|
+
// C0/C1/DEL can end a line or drive a terminal; bidi/invisible format
|
|
15
|
+
// controls make a line read differently from its bytes.
|
|
16
|
+
const LOG_UNSAFE = /[\p{Cc}\u061c\u200e\u200f\u202a-\u202e\u2028\u2029\u2066-\u2069]/gu;
|
|
17
|
+
/** An untrusted value made fit for one log line: never throws, at most `max`
|
|
18
|
+
* characters of it (then `...(len=N)`), each unsafe character as a literal
|
|
19
|
+
* `\uXXXX`. Backslash stays as is, so a value already through here comes back
|
|
20
|
+
* unchanged and a clean short value keeps its exact text. */
|
|
21
|
+
export function logSafe(value, max) {
|
|
22
|
+
let text;
|
|
23
|
+
try {
|
|
24
|
+
text = String(value);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return '<unprintable>';
|
|
28
|
+
}
|
|
29
|
+
const cut = text.length > max ? sliceClean(text, max) : text;
|
|
30
|
+
const escaped = cut.replace(LOG_UNSAFE, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);
|
|
31
|
+
return cut === text ? escaped : `${escaped}...(len=${text.length})`;
|
|
32
|
+
}
|
|
14
33
|
/** Largest prefix whose JSON encoding (the wrapping quotes included) fits
|
|
15
34
|
* `maxEncoded`. Slicing raw characters overshoots whenever the text contains
|
|
16
35
|
* quotes or backslashes, which JSON.stringify doubles: the escape hatch's
|