@commandable/integration-data 0.0.4 → 0.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/dist/credentials-index.d.ts.map +1 -1
- package/dist/credentials-index.js +64 -0
- package/dist/credentials-index.js.map +1 -1
- package/integrations/airtable/__tests__/get_handlers.test.ts +25 -16
- package/integrations/github/__tests__/get_handlers.test.ts +202 -7
- package/integrations/github/__tests__/write_handlers.test.ts +178 -24
- package/integrations/github/handlers/create_commit.js +5 -12
- package/integrations/github/handlers/create_pull_request_review.js +10 -0
- package/integrations/github/handlers/create_release.js +14 -0
- package/integrations/github/handlers/delete_branch.js +8 -0
- package/integrations/github/handlers/delete_file.js +9 -0
- package/integrations/github/handlers/fork_repo.js +10 -0
- package/integrations/github/handlers/get_commit.js +8 -0
- package/integrations/github/handlers/get_file_contents.js +21 -0
- package/integrations/github/handlers/get_job_logs.js +6 -0
- package/integrations/github/handlers/get_latest_release.js +4 -0
- package/integrations/github/handlers/get_me.js +4 -0
- package/integrations/github/handlers/get_pull_request.js +4 -0
- package/integrations/github/handlers/get_pull_request_diff.js +8 -0
- package/integrations/github/handlers/get_repo_tree.js +12 -0
- package/integrations/github/handlers/get_workflow_run.js +4 -0
- package/integrations/github/handlers/list_branches.js +6 -1
- package/integrations/github/handlers/list_commits.js +5 -6
- package/integrations/github/handlers/list_issue_comments.js +8 -0
- package/integrations/github/handlers/list_issues.js +5 -6
- package/integrations/github/handlers/list_labels.js +8 -0
- package/integrations/github/handlers/list_pull_request_comments.js +8 -0
- package/integrations/github/handlers/list_pull_request_files.js +8 -0
- package/integrations/github/handlers/list_pull_requests.js +7 -2
- package/integrations/github/handlers/list_releases.js +8 -0
- package/integrations/github/handlers/list_tags.js +8 -0
- package/integrations/github/handlers/list_workflow_runs.js +11 -0
- package/integrations/github/handlers/request_pull_request_reviewers.js +10 -0
- package/integrations/github/handlers/search_code.js +8 -0
- package/integrations/github/handlers/search_issues.js +8 -0
- package/integrations/github/handlers/search_pull_requests.js +8 -0
- package/integrations/github/handlers/search_repos.js +10 -0
- package/integrations/github/handlers/update_pull_request.js +13 -0
- package/integrations/github/manifest.json +58 -20
- package/integrations/github/schemas/create_pull_request_review.json +17 -0
- package/integrations/github/schemas/create_release.json +16 -0
- package/integrations/github/schemas/delete_branch.json +10 -0
- package/integrations/github/schemas/delete_file.json +13 -0
- package/integrations/github/schemas/fork_repo.json +11 -0
- package/integrations/github/schemas/get_commit.json +12 -0
- package/integrations/github/schemas/get_file_contents.json +11 -0
- package/integrations/github/schemas/get_job_logs.json +10 -0
- package/integrations/github/schemas/get_pull_request.json +10 -0
- package/integrations/github/schemas/get_pull_request_diff.json +10 -0
- package/integrations/github/schemas/get_repo_tree.json +12 -0
- package/integrations/github/schemas/get_workflow_run.json +10 -0
- package/integrations/github/schemas/list_branches.json +12 -0
- package/integrations/github/schemas/list_commits.json +5 -3
- package/integrations/github/schemas/list_issue_comments.json +12 -0
- package/integrations/github/schemas/list_issues.json +4 -2
- package/integrations/github/schemas/list_labels.json +11 -0
- package/integrations/github/schemas/list_pull_request_comments.json +12 -0
- package/integrations/github/schemas/list_pull_request_files.json +12 -0
- package/integrations/github/schemas/list_pull_requests.json +7 -1
- package/integrations/github/schemas/list_releases.json +11 -0
- package/integrations/github/schemas/list_tags.json +11 -0
- package/integrations/github/schemas/list_workflow_runs.json +18 -0
- package/integrations/github/schemas/request_pull_request_reviewers.json +20 -0
- package/integrations/github/schemas/search_code.json +10 -0
- package/integrations/github/schemas/search_issues.json +10 -0
- package/integrations/github/schemas/search_pull_requests.json +10 -0
- package/integrations/github/schemas/search_repos.json +12 -0
- package/integrations/github/schemas/update_pull_request.json +15 -0
- package/integrations/google-calendar/__tests__/write_and_admin_handlers.test.ts +0 -13
- package/integrations/google-calendar/handlers/get_event.js +5 -1
- package/integrations/google-calendar/handlers/list_events.js +2 -0
- package/integrations/google-calendar/manifest.json +17 -18
- package/integrations/google-calendar/prompt.md +68 -0
- package/integrations/google-calendar/schemas/id_calendar_event.json +4 -2
- package/integrations/google-calendar/schemas/list_events.json +10 -8
- package/integrations/google-docs/__tests__/get_handlers.test.ts +5 -20
- package/integrations/google-docs/__tests__/write_handlers.test.ts +38 -52
- package/integrations/google-docs/handlers/insert_inline_image_after_first_match.js +1 -1
- package/integrations/google-docs/handlers/read_document.js +189 -0
- package/integrations/google-docs/manifest.json +16 -31
- package/integrations/google-docs/prompt.md +49 -0
- package/integrations/google-docs/schemas/insert_inline_image_after_first_match.json +0 -1
- package/integrations/google-docs/schemas/{get_document_text.json → read_document.json} +5 -2
- package/integrations/google-docs/todo.md +18 -0
- package/integrations/google-drive/__tests__/handlers.test.ts +145 -0
- package/integrations/google-drive/__tests__/usage_parity.test.ts +9 -0
- package/integrations/google-drive/handlers/get_file.js +2 -4
- package/integrations/google-drive/handlers/get_file_content.js +41 -0
- package/integrations/google-drive/handlers/list_files.js +15 -0
- package/integrations/google-drive/handlers/search_files.js +20 -0
- package/integrations/google-drive/handlers/share_file.js +20 -0
- package/integrations/google-drive/manifest.json +37 -10
- package/integrations/google-drive/prompt.md +59 -0
- package/integrations/google-drive/schemas/get_file.json +2 -2
- package/integrations/google-drive/schemas/get_file_content.json +11 -0
- package/integrations/google-drive/schemas/list_files.json +12 -0
- package/integrations/google-drive/schemas/search_files.json +14 -0
- package/integrations/google-drive/schemas/share_file.json +23 -0
- package/integrations/google-gmail/__tests__/get_handlers.test.ts +134 -0
- package/integrations/google-gmail/__tests__/usage_parity.test.ts +9 -0
- package/integrations/google-gmail/__tests__/write_and_admin_handlers.test.ts +211 -0
- package/integrations/google-gmail/credentials.json +57 -0
- package/integrations/google-gmail/credentials_hint_oauth_token.md +8 -0
- package/integrations/google-gmail/credentials_hint_service_account.md +10 -0
- package/integrations/google-gmail/handlers/create_draft_email.js +27 -0
- package/integrations/google-gmail/handlers/create_label.js +12 -0
- package/integrations/google-gmail/handlers/delete_draft.js +13 -0
- package/integrations/google-gmail/handlers/delete_label.js +13 -0
- package/integrations/google-gmail/handlers/delete_message.js +13 -0
- package/integrations/google-gmail/handlers/delete_thread.js +13 -0
- package/integrations/google-gmail/handlers/get_draft.js +6 -0
- package/integrations/google-gmail/handlers/get_label.js +6 -0
- package/integrations/google-gmail/handlers/get_message.js +14 -0
- package/integrations/google-gmail/handlers/get_profile.js +5 -0
- package/integrations/google-gmail/handlers/get_thread.js +14 -0
- package/integrations/google-gmail/handlers/list_drafts.js +15 -0
- package/integrations/google-gmail/handlers/list_labels.js +5 -0
- package/integrations/google-gmail/handlers/list_messages.js +19 -0
- package/integrations/google-gmail/handlers/list_threads.js +19 -0
- package/integrations/google-gmail/handlers/modify_message.js +11 -0
- package/integrations/google-gmail/handlers/modify_thread.js +11 -0
- package/integrations/google-gmail/handlers/read_email.js +56 -0
- package/integrations/google-gmail/handlers/send_draft.js +15 -0
- package/integrations/google-gmail/handlers/send_email.js +22 -0
- package/integrations/google-gmail/handlers/trash_message.js +6 -0
- package/integrations/google-gmail/handlers/trash_thread.js +6 -0
- package/integrations/google-gmail/handlers/untrash_message.js +6 -0
- package/integrations/google-gmail/handlers/untrash_thread.js +6 -0
- package/integrations/google-gmail/handlers/update_label.js +15 -0
- package/integrations/google-gmail/manifest.json +33 -0
- package/integrations/google-gmail/prompt.md +52 -0
- package/integrations/google-gmail/schemas/create_draft_email.json +16 -0
- package/integrations/google-gmail/schemas/create_label.json +26 -0
- package/integrations/google-gmail/schemas/get_message.json +20 -0
- package/integrations/{google-docs/schemas/get_document_structured.json → google-gmail/schemas/get_profile.json} +4 -2
- package/integrations/google-gmail/schemas/get_thread.json +20 -0
- package/integrations/google-gmail/schemas/id_draft.json +16 -0
- package/integrations/google-gmail/schemas/id_label.json +16 -0
- package/integrations/google-gmail/schemas/id_message.json +16 -0
- package/integrations/google-gmail/schemas/id_thread.json +16 -0
- package/integrations/google-gmail/schemas/list_drafts.json +30 -0
- package/integrations/{google-sheet/schemas/get_developer_metadata.json → google-gmail/schemas/list_labels.json} +4 -3
- package/integrations/google-gmail/schemas/list_messages.json +35 -0
- package/integrations/google-gmail/schemas/list_threads.json +35 -0
- package/integrations/google-gmail/schemas/modify_message.json +24 -0
- package/integrations/google-gmail/schemas/modify_thread.json +24 -0
- package/integrations/google-gmail/schemas/read_email.json +10 -0
- package/integrations/google-gmail/schemas/send_draft.json +29 -0
- package/integrations/google-gmail/schemas/send_email.json +17 -0
- package/integrations/google-gmail/schemas/update_label.json +33 -0
- package/integrations/google-sheet/__tests__/get_handlers.test.ts +7 -52
- package/integrations/google-sheet/__tests__/write_handlers.test.ts +1 -20
- package/integrations/google-sheet/handlers/get_spreadsheet.js +2 -0
- package/integrations/google-sheet/handlers/read_sheet.js +75 -0
- package/integrations/google-sheet/manifest.json +13 -62
- package/integrations/google-sheet/prompt.md +49 -0
- package/integrations/google-sheet/schemas/get_spreadsheet.json +5 -4
- package/integrations/google-sheet/schemas/read_sheet.json +21 -0
- package/integrations/google-slides/__tests__/get_handlers.test.ts +13 -9
- package/integrations/google-slides/__tests__/write_handlers.test.ts +4 -5
- package/integrations/google-slides/handlers/read_presentation.js +51 -0
- package/integrations/google-slides/manifest.json +13 -13
- package/integrations/google-slides/prompt.md +56 -0
- package/integrations/new_integration_prompt.md +5 -1
- package/package.json +1 -1
- package/integrations/google-calendar/handlers/update_event.js +0 -5
- package/integrations/google-calendar/schemas/update_event.json +0 -10
- package/integrations/google-docs/handlers/get_document.js +0 -12
- package/integrations/google-docs/handlers/get_document_structured.js +0 -6
- package/integrations/google-docs/handlers/get_document_text.js +0 -17
- package/integrations/google-docs/schemas/get_document.json +0 -11
- package/integrations/google-sheet/handlers/batch_clear_values_by_data_filter.js +0 -6
- package/integrations/google-sheet/handlers/batch_get_values.js +0 -16
- package/integrations/google-sheet/handlers/batch_update_values_by_data_filter.js +0 -16
- package/integrations/google-sheet/handlers/get_developer_metadata.js +0 -6
- package/integrations/google-sheet/handlers/get_spreadsheet_by_data_filter.js +0 -10
- package/integrations/google-sheet/handlers/get_values.js +0 -14
- package/integrations/google-sheet/handlers/get_values_by_data_filter.js +0 -14
- package/integrations/google-sheet/handlers/search_developer_metadata.js +0 -7
- package/integrations/google-sheet/schemas/batch_clear_values_by_data_filter.json +0 -10
- package/integrations/google-sheet/schemas/batch_get_values.json +0 -13
- package/integrations/google-sheet/schemas/batch_update_values_by_data_filter.json +0 -25
- package/integrations/google-sheet/schemas/get_spreadsheet_by_data_filter.json +0 -11
- package/integrations/google-sheet/schemas/get_values.json +0 -13
- package/integrations/google-sheet/schemas/get_values_by_data_filter.json +0 -17
- package/integrations/google-sheet/schemas/search_developer_metadata.json +0 -14
- package/integrations/google-slides/handlers/get_presentation.js +0 -6
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["threadId"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"userId": { "type": "string", "description": "User email address or 'me'. Defaults to 'me'." },
|
|
7
|
+
"threadId": { "type": "string", "description": "Gmail thread ID." },
|
|
8
|
+
"addLabelIds": {
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": { "type": "string" },
|
|
11
|
+
"description": "Label IDs to add."
|
|
12
|
+
},
|
|
13
|
+
"removeLabelIds": {
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": { "type": "string" },
|
|
16
|
+
"description": "Label IDs to remove."
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"anyOf": [
|
|
20
|
+
{ "required": ["addLabelIds"] },
|
|
21
|
+
{ "required": ["removeLabelIds"] }
|
|
22
|
+
],
|
|
23
|
+
"additionalProperties": false
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["messageId"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"userId": { "type": "string", "description": "User email or 'me'. Defaults to 'me'." },
|
|
7
|
+
"messageId": { "type": "string", "description": "Gmail message ID. Obtain from list_messages or search results." }
|
|
8
|
+
},
|
|
9
|
+
"additionalProperties": false
|
|
10
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"userId": { "type": "string", "description": "User email address or 'me'. Defaults to 'me'." },
|
|
6
|
+
"draftId": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"description": "Draft ID to send."
|
|
9
|
+
},
|
|
10
|
+
"raw": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Optional base64url encoded RFC822 message string for one-off send."
|
|
13
|
+
},
|
|
14
|
+
"threadId": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Optional existing thread ID when sending a one-off draft payload."
|
|
17
|
+
},
|
|
18
|
+
"labelIds": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"items": { "type": "string" },
|
|
21
|
+
"description": "Optional label IDs when sending a one-off draft payload."
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"anyOf": [
|
|
25
|
+
{ "required": ["draftId"] },
|
|
26
|
+
{ "required": ["raw"] }
|
|
27
|
+
],
|
|
28
|
+
"additionalProperties": false
|
|
29
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["to", "subject", "body"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"userId": { "type": "string", "description": "User email or 'me'. Defaults to 'me'." },
|
|
7
|
+
"to": { "type": "string", "description": "Recipient email address. Use comma-separated values for multiple recipients (e.g. 'alice@example.com, bob@example.com')." },
|
|
8
|
+
"cc": { "type": "string", "description": "CC recipients, comma-separated." },
|
|
9
|
+
"bcc": { "type": "string", "description": "BCC recipients, comma-separated." },
|
|
10
|
+
"subject": { "type": "string", "description": "Email subject line." },
|
|
11
|
+
"body": { "type": "string", "description": "Plain text email body. Required unless htmlBody is provided." },
|
|
12
|
+
"htmlBody": { "type": "string", "description": "HTML email body. If provided, takes precedence over body and the email is sent as text/html." },
|
|
13
|
+
"replyToMessageId": { "type": "string", "description": "Message ID of the email being replied to. Sets the In-Reply-To header for proper threading. Use with threadId." },
|
|
14
|
+
"threadId": { "type": "string", "description": "Thread ID to add this message to. Required when replying so the reply appears in the same conversation." }
|
|
15
|
+
},
|
|
16
|
+
"additionalProperties": false
|
|
17
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["labelId"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"userId": { "type": "string", "description": "User email address or 'me'. Defaults to 'me'." },
|
|
7
|
+
"labelId": { "type": "string", "description": "Gmail label ID." },
|
|
8
|
+
"name": { "type": "string", "description": "Label display name." },
|
|
9
|
+
"messageListVisibility": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"enum": ["show", "hide"]
|
|
12
|
+
},
|
|
13
|
+
"labelListVisibility": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": ["labelShow", "labelShowIfUnread", "labelHide"]
|
|
16
|
+
},
|
|
17
|
+
"color": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"textColor": { "type": "string", "description": "Hex color, e.g. #000000" },
|
|
21
|
+
"backgroundColor": { "type": "string", "description": "Hex color, e.g. #ffffff" }
|
|
22
|
+
},
|
|
23
|
+
"additionalProperties": false
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"anyOf": [
|
|
27
|
+
{ "required": ["name"] },
|
|
28
|
+
{ "required": ["messageListVisibility"] },
|
|
29
|
+
{ "required": ["labelListVisibility"] },
|
|
30
|
+
{ "required": ["color"] }
|
|
31
|
+
],
|
|
32
|
+
"additionalProperties": false
|
|
33
|
+
}
|
|
@@ -21,6 +21,7 @@ suite('google-sheet read handlers (live)', () => {
|
|
|
21
21
|
const credentialStore = createCredentialStore(async () => ({
|
|
22
22
|
token: env.GOOGLE_TOKEN || '',
|
|
23
23
|
serviceAccountJson: env.GOOGLE_SERVICE_ACCOUNT_JSON || '',
|
|
24
|
+
subject: env.GOOGLE_IMPERSONATE_SUBJECT || '',
|
|
24
25
|
}))
|
|
25
26
|
const proxy = createProxy(credentialStore)
|
|
26
27
|
sheets = createToolbox('google-sheet', proxy, createIntegrationNode('google-sheet', { label: 'Google Sheets', credentialId: 'google-sheet-creds' }))
|
|
@@ -62,60 +63,14 @@ suite('google-sheet read handlers (live)', () => {
|
|
|
62
63
|
expect(result?.spreadsheetId || result?.sheets).toBeTruthy()
|
|
63
64
|
}, 30000)
|
|
64
65
|
|
|
65
|
-
it('
|
|
66
|
+
it('read_sheet returns markdown with A1 coordinates', async () => {
|
|
66
67
|
if (!spreadsheetId)
|
|
67
68
|
return expect(true).toBe(true)
|
|
68
|
-
const handler = sheets.read('
|
|
69
|
+
const handler = sheets.read('read_sheet')
|
|
69
70
|
const range = sheetTitle ? `${sheetTitle}!A1:B5` : 'A1:B5'
|
|
70
|
-
const result = await handler({ spreadsheetId, range })
|
|
71
|
-
expect(result?.range
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
it('batch_get_values returns multiple ranges', async () => {
|
|
75
|
-
if (!spreadsheetId)
|
|
76
|
-
return expect(true).toBe(true)
|
|
77
|
-
const handler = sheets.read('batch_get_values')
|
|
78
|
-
const aTitle = sheetTitle || 'Sheet1'
|
|
79
|
-
const result = await handler({ spreadsheetId, ranges: [`${aTitle}!A1:A3`, `${aTitle}!B1:B3`] })
|
|
80
|
-
expect(Array.isArray(result?.valueRanges)).toBe(true)
|
|
81
|
-
}, 30000)
|
|
82
|
-
|
|
83
|
-
it('get_spreadsheet_by_data_filter returns metadata', async () => {
|
|
84
|
-
if (!spreadsheetId)
|
|
85
|
-
return expect(true).toBe(true)
|
|
86
|
-
const handler = sheets.read('get_spreadsheet_by_data_filter')
|
|
87
|
-
const aTitle = sheetTitle || 'Sheet1'
|
|
88
|
-
const result = await handler({ spreadsheetId, dataFilters: [{ a1Range: `${aTitle}!A1:A1` }] })
|
|
89
|
-
expect(result?.spreadsheetId || result?.sheets).toBeTruthy()
|
|
90
|
-
}, 30000)
|
|
91
|
-
|
|
92
|
-
it('get_values_by_data_filter returns values', async () => {
|
|
93
|
-
if (!spreadsheetId)
|
|
94
|
-
return expect(true).toBe(true)
|
|
95
|
-
const handler = sheets.read('get_values_by_data_filter')
|
|
96
|
-
const aTitle = sheetTitle || 'Sheet1'
|
|
97
|
-
const result = await handler({ spreadsheetId, dataFilters: [{ a1Range: `${aTitle}!A1:B2` }] })
|
|
98
|
-
expect(Array.isArray(result?.valueRanges)).toBe(true)
|
|
99
|
-
}, 30000)
|
|
100
|
-
|
|
101
|
-
it('search_developer_metadata returns results or empty', async () => {
|
|
102
|
-
if (!spreadsheetId)
|
|
103
|
-
return expect(true).toBe(true)
|
|
104
|
-
const handler = sheets.read('search_developer_metadata')
|
|
105
|
-
const result = await handler({ spreadsheetId, dataFilters: [{ developerMetadataLookup: { visibility: 'DOCUMENT' } }] })
|
|
106
|
-
expect(result !== undefined).toBe(true)
|
|
107
|
-
}, 30000)
|
|
108
|
-
|
|
109
|
-
it('get_developer_metadata retrieves by id when available', async () => {
|
|
110
|
-
if (!spreadsheetId)
|
|
111
|
-
return expect(true).toBe(true)
|
|
112
|
-
const search = sheets.read('search_developer_metadata')
|
|
113
|
-
const list = await search({ spreadsheetId, dataFilters: [{ developerMetadataLookup: { visibility: 'DOCUMENT' } }] })
|
|
114
|
-
const first = list?.matchedDeveloperMetadata?.[0]?.developerMetadata || list?.developerMetadata?.[0]
|
|
115
|
-
if (!first?.metadataId)
|
|
116
|
-
return expect(true).toBe(true)
|
|
117
|
-
const getdm = sheets.read('get_developer_metadata')
|
|
118
|
-
const got = await getdm({ spreadsheetId, metadataId: first.metadataId })
|
|
119
|
-
expect(got?.metadataId).toBe(first.metadataId)
|
|
71
|
+
const result = await handler({ spreadsheetId, range, valueRenderOption: 'FORMATTED_VALUE' })
|
|
72
|
+
expect(result?.range).toBeTruthy()
|
|
73
|
+
expect(typeof result?.markdown).toBe('string')
|
|
74
|
+
expect(result?.columnCount >= 1).toBe(true)
|
|
120
75
|
}, 30000)
|
|
121
76
|
})
|
|
@@ -27,6 +27,7 @@ suite('google-sheet write handlers (live)', () => {
|
|
|
27
27
|
const credentialStore = createCredentialStore(async () => ({
|
|
28
28
|
token: env.GOOGLE_TOKEN || '',
|
|
29
29
|
serviceAccountJson: env.GOOGLE_SERVICE_ACCOUNT_JSON || '',
|
|
30
|
+
subject: env.GOOGLE_IMPERSONATE_SUBJECT || '',
|
|
30
31
|
}))
|
|
31
32
|
const proxy = createProxy(credentialStore)
|
|
32
33
|
sheets = createToolbox('google-sheet', proxy, createIntegrationNode('google-sheet', { label: 'Google Sheets', credentialId: 'google-sheet-creds' }))
|
|
@@ -109,17 +110,6 @@ suite('google-sheet write handlers (live)', () => {
|
|
|
109
110
|
expect(res?.totalUpdatedCells >= 0 || res?.spreadsheetId).toBeTruthy()
|
|
110
111
|
}, 60000)
|
|
111
112
|
|
|
112
|
-
it('batch_update_values_by_data_filter updates via filters', async () => {
|
|
113
|
-
if (!ctx.spreadsheetId)
|
|
114
|
-
return expect(true).toBe(true)
|
|
115
|
-
const aTitle = sheetTitle || 'Sheet1'
|
|
116
|
-
const batch_update_values_by_data_filter = sheets.write('batch_update_values_by_data_filter')
|
|
117
|
-
const res = await batch_update_values_by_data_filter({ spreadsheetId: ctx.spreadsheetId, data: [
|
|
118
|
-
{ dataFilter: { a1Range: `${aTitle}!D1:D1` }, values: [[`CmdTestDF ${Date.now()}`]] },
|
|
119
|
-
], valueInputOption: 'USER_ENTERED' })
|
|
120
|
-
expect(res?.totalUpdatedCells >= 0 || res?.spreadsheetId).toBeTruthy()
|
|
121
|
-
}, 60000)
|
|
122
|
-
|
|
123
113
|
it('batch_clear_values clears multiple ranges', async () => {
|
|
124
114
|
if (!ctx.spreadsheetId)
|
|
125
115
|
return expect(true).toBe(true)
|
|
@@ -129,15 +119,6 @@ suite('google-sheet write handlers (live)', () => {
|
|
|
129
119
|
expect(Boolean(res?.spreadsheetId) || Array.isArray(res?.clearedRanges)).toBe(true)
|
|
130
120
|
}, 60000)
|
|
131
121
|
|
|
132
|
-
it('batch_clear_values_by_data_filter clears via filters', async () => {
|
|
133
|
-
if (!ctx.spreadsheetId)
|
|
134
|
-
return expect(true).toBe(true)
|
|
135
|
-
const aTitle = sheetTitle || 'Sheet1'
|
|
136
|
-
const batch_clear_values_by_data_filter = sheets.write('batch_clear_values_by_data_filter')
|
|
137
|
-
const res = await batch_clear_values_by_data_filter({ spreadsheetId: ctx.spreadsheetId, dataFilters: [{ a1Range: `${aTitle}!E1:E2` }] })
|
|
138
|
-
expect(Boolean(res?.spreadsheetId) || Array.isArray(res?.clearedRanges)).toBe(true)
|
|
139
|
-
}, 60000)
|
|
140
|
-
|
|
141
122
|
it('batch_update handles a trivial request (no-op findReplace)', async () => {
|
|
142
123
|
if (!ctx.spreadsheetId)
|
|
143
124
|
return expect(true).toBe(true)
|
|
@@ -5,6 +5,8 @@ async (input) => {
|
|
|
5
5
|
params.set('includeGridData', String(includeGridData))
|
|
6
6
|
if (Array.isArray(ranges))
|
|
7
7
|
ranges.forEach(r => params.append('ranges', String(r)))
|
|
8
|
+
if (input.fields)
|
|
9
|
+
params.set('fields', input.fields)
|
|
8
10
|
const qs = params.toString()
|
|
9
11
|
const path = `/spreadsheets/${encodeURIComponent(spreadsheetId)}${qs ? `?${qs}` : ''}`
|
|
10
12
|
const res = await integration.fetch(path)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
async (input) => {
|
|
2
|
+
const toColumnName = (index) => {
|
|
3
|
+
let n = index + 1
|
|
4
|
+
let out = ''
|
|
5
|
+
while (n > 0) {
|
|
6
|
+
const rem = (n - 1) % 26
|
|
7
|
+
out = String.fromCharCode(65 + rem) + out
|
|
8
|
+
n = Math.floor((n - 1) / 26)
|
|
9
|
+
}
|
|
10
|
+
return out
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const columnNameToIndex = (name) => {
|
|
14
|
+
let value = 0
|
|
15
|
+
for (const ch of name.toUpperCase()) {
|
|
16
|
+
const code = ch.charCodeAt(0)
|
|
17
|
+
if (code < 65 || code > 90) continue
|
|
18
|
+
value = value * 26 + (code - 64)
|
|
19
|
+
}
|
|
20
|
+
return Math.max(0, value - 1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const parseResolvedRange = (resolvedRange) => {
|
|
24
|
+
// Examples: "Sheet1!A1:D5", "Sheet1!B:B", "Sheet1!2:9"
|
|
25
|
+
const a1 = String(resolvedRange || '').split('!')[1] || ''
|
|
26
|
+
const [start = 'A1'] = a1.split(':')
|
|
27
|
+
const letters = (start.match(/[A-Za-z]+/) || ['A'])[0]
|
|
28
|
+
const rowDigits = (start.match(/\d+/) || ['1'])[0]
|
|
29
|
+
return {
|
|
30
|
+
startColumn: columnNameToIndex(letters),
|
|
31
|
+
startRow: Math.max(1, parseInt(rowDigits, 10) || 1),
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const escapeCell = (value) =>
|
|
36
|
+
String(value ?? '')
|
|
37
|
+
.replace(/\|/g, '\\|')
|
|
38
|
+
.replace(/\r?\n/g, '<br>')
|
|
39
|
+
|
|
40
|
+
const spreadsheetId = input.spreadsheetId
|
|
41
|
+
const range = input.range || 'A1:Z1000'
|
|
42
|
+
const params = new URLSearchParams()
|
|
43
|
+
if (input.valueRenderOption) params.set('valueRenderOption', input.valueRenderOption)
|
|
44
|
+
|
|
45
|
+
const qs = params.toString()
|
|
46
|
+
const path = `/spreadsheets/${encodeURIComponent(spreadsheetId)}/values/${encodeURIComponent(range)}${qs ? `?${qs}` : ''}`
|
|
47
|
+
const res = await integration.fetch(path)
|
|
48
|
+
const payload = await res.json()
|
|
49
|
+
|
|
50
|
+
const values = Array.isArray(payload?.values) ? payload.values : []
|
|
51
|
+
const resolvedRange = payload?.range || range
|
|
52
|
+
const { startColumn, startRow } = parseResolvedRange(resolvedRange)
|
|
53
|
+
|
|
54
|
+
const width = Math.max(1, ...values.map((row) => (Array.isArray(row) ? row.length : 0)))
|
|
55
|
+
const headerCells = Array.from({ length: width }, (_, i) => toColumnName(startColumn + i))
|
|
56
|
+
const lines = [
|
|
57
|
+
`| | ${headerCells.join(' | ')} |`,
|
|
58
|
+
`|---|${Array(width).fill('---').join('|')}|`,
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
62
|
+
const row = Array.isArray(values[i]) ? values[i] : []
|
|
63
|
+
const padded = [...row, ...Array(width - row.length).fill('')]
|
|
64
|
+
const escaped = padded.map((cell) => escapeCell(cell))
|
|
65
|
+
lines.push(`| ${startRow + i} | ${escaped.join(' | ')} |`)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
spreadsheetId,
|
|
70
|
+
range: resolvedRange,
|
|
71
|
+
rowCount: values.length,
|
|
72
|
+
columnCount: width,
|
|
73
|
+
markdown: lines.join('\n'),
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -4,119 +4,70 @@
|
|
|
4
4
|
"tools": [
|
|
5
5
|
{
|
|
6
6
|
"name": "get_spreadsheet",
|
|
7
|
-
"description": "Retrieve spreadsheet metadata and
|
|
7
|
+
"description": "Retrieve spreadsheet metadata including all sheet names, IDs, and properties. Set includeGridData=false (the default) to get only metadata without cell values. Use read_sheet for cell content. Use the 'fields' parameter to limit the response (e.g. fields='sheets.properties' to get only sheet names and IDs). The spreadsheetId appears in the URL: https://docs.google.com/spreadsheets/d/{spreadsheetId}/.",
|
|
8
8
|
"inputSchema": "schemas/get_spreadsheet.json",
|
|
9
9
|
"handler": "handlers/get_spreadsheet.js",
|
|
10
10
|
"scope": "read"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
|
-
"name": "
|
|
14
|
-
"description": "
|
|
15
|
-
"inputSchema": "schemas/
|
|
16
|
-
"handler": "handlers/
|
|
17
|
-
"scope": "read"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"name": "get_values",
|
|
21
|
-
"description": "Get values from a single A1 range.",
|
|
22
|
-
"inputSchema": "schemas/get_values.json",
|
|
23
|
-
"handler": "handlers/get_values.js",
|
|
24
|
-
"scope": "read"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"name": "batch_get_values",
|
|
28
|
-
"description": "Batch get values for multiple A1 ranges.",
|
|
29
|
-
"inputSchema": "schemas/batch_get_values.json",
|
|
30
|
-
"handler": "handlers/batch_get_values.js",
|
|
31
|
-
"scope": "read"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"name": "get_values_by_data_filter",
|
|
35
|
-
"description": "Batch get values using DataFilters.",
|
|
36
|
-
"inputSchema": "schemas/get_values_by_data_filter.json",
|
|
37
|
-
"handler": "handlers/get_values_by_data_filter.js",
|
|
38
|
-
"scope": "read"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"name": "search_developer_metadata",
|
|
42
|
-
"description": "Search developer metadata in a spreadsheet.",
|
|
43
|
-
"inputSchema": "schemas/search_developer_metadata.json",
|
|
44
|
-
"handler": "handlers/search_developer_metadata.js",
|
|
45
|
-
"scope": "read"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"name": "get_developer_metadata",
|
|
49
|
-
"description": "Get a developer metadata entry by ID.",
|
|
50
|
-
"inputSchema": "schemas/get_developer_metadata.json",
|
|
51
|
-
"handler": "handlers/get_developer_metadata.js",
|
|
13
|
+
"name": "read_sheet",
|
|
14
|
+
"description": "Read cell values from a sheet range and return as a Markdown table with A1 column headers and row numbers. Use this to read and understand spreadsheet data -- the coordinates in the output can be used directly with update_values and append_values for writes. Supports optional valueRenderOption for formulas or raw numbers. Use get_spreadsheet first to discover sheet names.",
|
|
15
|
+
"inputSchema": "schemas/read_sheet.json",
|
|
16
|
+
"handler": "handlers/read_sheet.js",
|
|
52
17
|
"scope": "read"
|
|
53
18
|
},
|
|
54
19
|
{
|
|
55
20
|
"name": "create_spreadsheet",
|
|
56
|
-
"description": "Create a new spreadsheet.",
|
|
21
|
+
"description": "Create a new Google Spreadsheet. Accepts a full spreadsheet resource body, allowing you to specify the title, initial sheets, and cell data. Minimum: provide {title: 'My Spreadsheet'}. Returns the created spreadsheet including its spreadsheetId.",
|
|
57
22
|
"inputSchema": "schemas/create_spreadsheet.json",
|
|
58
23
|
"handler": "handlers/create_spreadsheet.js",
|
|
59
24
|
"scope": "write"
|
|
60
25
|
},
|
|
61
26
|
{
|
|
62
27
|
"name": "update_values",
|
|
63
|
-
"description": "
|
|
28
|
+
"description": "Write values to a specific A1 range, replacing existing content. Use valueInputOption='USER_ENTERED' to parse values as the user would type them (supports formulas, dates, currency). Use 'RAW' to store values as literal strings. Provide values as a 2D array (rows of columns).",
|
|
64
29
|
"inputSchema": "schemas/update_values.json",
|
|
65
30
|
"handler": "handlers/update_values.js",
|
|
66
31
|
"scope": "write"
|
|
67
32
|
},
|
|
68
33
|
{
|
|
69
34
|
"name": "append_values",
|
|
70
|
-
"description": "Append values after the last row of a range.",
|
|
35
|
+
"description": "Append rows of values after the last row of existing data in a range. Useful for adding new rows to a table without knowing the exact next row number. Uses USER_ENTERED valueInputOption by default. The range determines which sheet to append to.",
|
|
71
36
|
"inputSchema": "schemas/append_values.json",
|
|
72
37
|
"handler": "handlers/append_values.js",
|
|
73
38
|
"scope": "write"
|
|
74
39
|
},
|
|
75
40
|
{
|
|
76
41
|
"name": "batch_update_values",
|
|
77
|
-
"description": "
|
|
42
|
+
"description": "Write values to multiple A1 ranges in a single API call. More efficient than calling update_values multiple times. Provide a data array where each item has range and values. Use valueInputOption='USER_ENTERED' for formulas and dates.",
|
|
78
43
|
"inputSchema": "schemas/batch_update_values.json",
|
|
79
44
|
"handler": "handlers/batch_update_values.js",
|
|
80
45
|
"scope": "write"
|
|
81
46
|
},
|
|
82
|
-
{
|
|
83
|
-
"name": "batch_update_values_by_data_filter",
|
|
84
|
-
"description": "Batch update values using DataFilters.",
|
|
85
|
-
"inputSchema": "schemas/batch_update_values_by_data_filter.json",
|
|
86
|
-
"handler": "handlers/batch_update_values_by_data_filter.js",
|
|
87
|
-
"scope": "write"
|
|
88
|
-
},
|
|
89
47
|
{
|
|
90
48
|
"name": "clear_values",
|
|
91
|
-
"description": "Clear values in the specified range.",
|
|
49
|
+
"description": "Clear all values (but not formatting) in the specified A1 range. The cells remain but their content is removed. To clear formatting as well, use batch_update with a repeatCell request.",
|
|
92
50
|
"inputSchema": "schemas/clear_values.json",
|
|
93
51
|
"handler": "handlers/clear_values.js",
|
|
94
52
|
"scope": "write"
|
|
95
53
|
},
|
|
96
54
|
{
|
|
97
55
|
"name": "batch_clear_values",
|
|
98
|
-
"description": "
|
|
56
|
+
"description": "Clear values from multiple A1 ranges in a single API call. More efficient than calling clear_values multiple times.",
|
|
99
57
|
"inputSchema": "schemas/batch_clear_values.json",
|
|
100
58
|
"handler": "handlers/batch_clear_values.js",
|
|
101
59
|
"scope": "write"
|
|
102
60
|
},
|
|
103
|
-
{
|
|
104
|
-
"name": "batch_clear_values_by_data_filter",
|
|
105
|
-
"description": "Batch clear values using DataFilters.",
|
|
106
|
-
"inputSchema": "schemas/batch_clear_values_by_data_filter.json",
|
|
107
|
-
"handler": "handlers/batch_clear_values_by_data_filter.js",
|
|
108
|
-
"scope": "write"
|
|
109
|
-
},
|
|
110
61
|
{
|
|
111
62
|
"name": "batch_update",
|
|
112
|
-
"description": "Send a batchUpdate request
|
|
63
|
+
"description": "Send a spreadsheets.batchUpdate request for structural changes such as addSheet, deleteSheet, duplicateSheet, insertDimension, deleteDimension, mergeCells, sortRange, addConditionalFormatRule, and more. Accepts a requests array. Use update_values or batch_update_values for writing cell data.",
|
|
113
64
|
"inputSchema": "schemas/batch_update.json",
|
|
114
65
|
"handler": "handlers/batch_update.js",
|
|
115
66
|
"scope": "write"
|
|
116
67
|
},
|
|
117
68
|
{
|
|
118
69
|
"name": "copy_to_spreadsheet",
|
|
119
|
-
"description": "Copy a sheet to another spreadsheet.",
|
|
70
|
+
"description": "Copy a specific sheet (tab) from one spreadsheet to another. Provide the source spreadsheetId, the sheetId (integer, from get_spreadsheet), and the destination spreadsheetId. Returns the copied sheet's properties in the destination spreadsheet.",
|
|
120
71
|
"inputSchema": "schemas/copy_to_spreadsheet.json",
|
|
121
72
|
"handler": "handlers/copy_to_spreadsheet.js",
|
|
122
73
|
"scope": "write"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
## A1 notation
|
|
2
|
+
|
|
3
|
+
Ranges use A1 notation: `SheetName!StartCell:EndCell`
|
|
4
|
+
|
|
5
|
+
Examples:
|
|
6
|
+
- `Sheet1!A1:D10` — cells A1 to D10 on Sheet1
|
|
7
|
+
- `Sheet1!A:A` — entire column A
|
|
8
|
+
- `Sheet1!1:5` — rows 1 through 5
|
|
9
|
+
- `Sheet1` — entire sheet (all data)
|
|
10
|
+
- `A1:D10` — if the spreadsheet has only one sheet, sheet name can be omitted
|
|
11
|
+
- `'My Sheet'!A1:B5` — sheet names with spaces must be quoted with single quotes
|
|
12
|
+
|
|
13
|
+
Use `get_spreadsheet` with `fields='sheets.properties'` first to discover all sheet names and their IDs.
|
|
14
|
+
|
|
15
|
+
## valueInputOption
|
|
16
|
+
|
|
17
|
+
Controls how input values are interpreted in `update_values`, `append_values`, and `batch_update_values`:
|
|
18
|
+
|
|
19
|
+
- `USER_ENTERED` *(recommended)* — values are parsed as if a user typed them. Supports formulas (`=SUM(A1:A10)`), dates (`1/15/2024`), currency (`$1,234.56`), and percentages (`50%`)
|
|
20
|
+
- `RAW` — values are stored as literal strings, no parsing. Use when you want exact string storage
|
|
21
|
+
|
|
22
|
+
## valueRenderOption
|
|
23
|
+
|
|
24
|
+
Controls how values are returned in `read_sheet`:
|
|
25
|
+
|
|
26
|
+
- `FORMATTED_VALUE` *(default)* — returns values as displayed in the UI (e.g. `"$1,234.56"`, `"50%"`)
|
|
27
|
+
- `UNFORMATTED_VALUE` — returns raw numbers (e.g. `1234.56`, `0.5`)
|
|
28
|
+
- `FORMULA` — returns formulas as strings (e.g. `"=SUM(A1:A10)"`)
|
|
29
|
+
|
|
30
|
+
## Recommended workflow
|
|
31
|
+
|
|
32
|
+
1. Call `get_spreadsheet` with `fields='sheets.properties'` to get sheet names and sheetIds
|
|
33
|
+
2. Use `read_sheet` with an A1 range to read data as markdown plus explicit row/column coordinates
|
|
34
|
+
3. Use the coordinates from `read_sheet` output (e.g. `B3`) with `update_values` or `append_values` for writes
|
|
35
|
+
|
|
36
|
+
## Structural changes
|
|
37
|
+
|
|
38
|
+
For adding/removing sheets, inserting/deleting rows or columns, or formatting cells, use `batch_update` with the appropriate request types:
|
|
39
|
+
- `addSheet` — add a new tab
|
|
40
|
+
- `deleteSheet` — remove a tab (requires sheetId, not name)
|
|
41
|
+
- `insertDimension` — insert rows or columns
|
|
42
|
+
- `deleteDimension` — delete rows or columns
|
|
43
|
+
- `repeatCell` — apply formatting to a range
|
|
44
|
+
|
|
45
|
+
## Large spreadsheets
|
|
46
|
+
|
|
47
|
+
Avoid calling `get_spreadsheet` with `includeGridData=true` on large spreadsheets -- it can return megabytes of data. Instead:
|
|
48
|
+
- Use `read_sheet` with specific ranges
|
|
49
|
+
- Use `get_spreadsheet` with `fields='sheets.properties'` to get sheet metadata only
|
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
"type": "object",
|
|
4
4
|
"required": ["spreadsheetId"],
|
|
5
5
|
"properties": {
|
|
6
|
-
"spreadsheetId": { "type": "string", "description": "ID
|
|
7
|
-
"includeGridData": { "type": "boolean", "description": "Whether to include grid data" },
|
|
6
|
+
"spreadsheetId": { "type": "string", "description": "Spreadsheet ID. Found in the spreadsheet URL: https://docs.google.com/spreadsheets/d/{spreadsheetId}/." },
|
|
7
|
+
"includeGridData": { "type": "boolean", "description": "Whether to include cell grid data. Defaults to false. Set to true only when you need cell values -- use get_values or batch_get_values for targeted range reads instead." },
|
|
8
8
|
"ranges": {
|
|
9
9
|
"type": "array",
|
|
10
10
|
"items": { "type": "string" },
|
|
11
|
-
"description": "Optional A1 ranges to include"
|
|
12
|
-
}
|
|
11
|
+
"description": "Optional A1 notation ranges to include when includeGridData is true. Example: ['Sheet1!A1:D10', 'Sheet2!A:A']."
|
|
12
|
+
},
|
|
13
|
+
"fields": { "type": "string", "description": "Partial response fields selector to reduce response size. Example: 'sheets.properties' to get only sheet names and IDs without cell data. See Sheets API fields reference." }
|
|
13
14
|
},
|
|
14
15
|
"additionalProperties": false
|
|
15
16
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": ["spreadsheetId"],
|
|
5
|
+
"properties": {
|
|
6
|
+
"spreadsheetId": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"description": "Spreadsheet ID from URL: https://docs.google.com/spreadsheets/d/{spreadsheetId}/edit"
|
|
9
|
+
},
|
|
10
|
+
"range": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "A1 notation range to read, e.g. 'Sheet1!A1:D20'. Defaults to 'A1:Z1000'."
|
|
13
|
+
},
|
|
14
|
+
"valueRenderOption": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"enum": ["FORMATTED_VALUE", "UNFORMATTED_VALUE", "FORMULA"],
|
|
17
|
+
"description": "How values should be represented in the output."
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"additionalProperties": false
|
|
21
|
+
}
|
|
@@ -20,6 +20,7 @@ suite('google-slides read handlers (live)', () => {
|
|
|
20
20
|
const credentialStore = createCredentialStore(async () => ({
|
|
21
21
|
token: env.GOOGLE_TOKEN || '',
|
|
22
22
|
serviceAccountJson: env.GOOGLE_SERVICE_ACCOUNT_JSON || '',
|
|
23
|
+
subject: env.GOOGLE_IMPERSONATE_SUBJECT || '',
|
|
23
24
|
}))
|
|
24
25
|
const proxy = createProxy(credentialStore)
|
|
25
26
|
slides = createToolbox('google-slides', proxy, createIntegrationNode('google-slides', { label: 'Google Slides', credentialId: 'google-slides-creds' }))
|
|
@@ -46,25 +47,28 @@ suite('google-slides read handlers (live)', () => {
|
|
|
46
47
|
await safeCleanup(async () => drive.write('delete_file')({ fileId: folderId }))
|
|
47
48
|
}, 60000)
|
|
48
49
|
|
|
49
|
-
it('
|
|
50
|
+
it('read_presentation returns human-readable content', async () => {
|
|
50
51
|
if (!presentationId)
|
|
51
52
|
return expect(true).toBe(true)
|
|
52
|
-
const handler = slides.read('
|
|
53
|
+
const handler = slides.read('read_presentation')
|
|
53
54
|
const result = await handler({ presentationId })
|
|
54
|
-
expect(
|
|
55
|
+
expect(typeof result).toBe('string')
|
|
56
|
+
expect(String(result)).toContain('Presentation:')
|
|
55
57
|
}, 30000)
|
|
56
58
|
|
|
57
59
|
it('get_page_thumbnail returns URL data', async () => {
|
|
58
60
|
if (!presentationId)
|
|
59
61
|
return expect(true).toBe(true)
|
|
60
|
-
//
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
62
|
+
// Query the readable summary and parse "Slide 1: ID <objectId>, ..."
|
|
63
|
+
const readPresentation = slides.read('read_presentation')
|
|
64
|
+
const summary = await readPresentation({ presentationId })
|
|
65
|
+
const text = String(summary || '')
|
|
66
|
+
const match = text.match(/Slide 1: ID ([^,\n]+)/)
|
|
67
|
+
const firstSlideObjectId = match?.[1]
|
|
68
|
+
if (!firstSlideObjectId)
|
|
65
69
|
return expect(true).toBe(true)
|
|
66
70
|
const handler = slides.read('get_page_thumbnail')
|
|
67
|
-
const result = await handler({ presentationId, 'pageObjectId':
|
|
71
|
+
const result = await handler({ presentationId, 'pageObjectId': firstSlideObjectId, 'thumbnailProperties.thumbnailSize': 'MEDIUM', 'thumbnailProperties.mimeType': 'PNG' })
|
|
68
72
|
expect(typeof result?.contentUrl === 'string' || typeof result?.thumbnailUrl === 'string').toBe(true)
|
|
69
73
|
}, 30000)
|
|
70
74
|
})
|
|
@@ -21,6 +21,7 @@ suite('google-slides write handlers (live)', () => {
|
|
|
21
21
|
const credentialStore = createCredentialStore(async () => ({
|
|
22
22
|
token: env.GOOGLE_TOKEN || '',
|
|
23
23
|
serviceAccountJson: env.GOOGLE_SERVICE_ACCOUNT_JSON || '',
|
|
24
|
+
subject: env.GOOGLE_IMPERSONATE_SUBJECT || '',
|
|
24
25
|
}))
|
|
25
26
|
const proxy = createProxy(credentialStore)
|
|
26
27
|
slides = createToolbox('google-slides', proxy, createIntegrationNode('google-slides', { label: 'Google Slides', credentialId: 'google-slides-creds' }))
|
|
@@ -95,13 +96,11 @@ suite('google-slides write handlers (live)', () => {
|
|
|
95
96
|
}, 60000)
|
|
96
97
|
|
|
97
98
|
it('insert_image_after_first_match inserts an image when allowed', async () => {
|
|
98
|
-
|
|
99
|
-
if (!ctx.presentationId || !env.GSLIDES_TEST_IMAGE_URI)
|
|
100
|
-
return expect(true).toBe(true)
|
|
101
|
-
if (!ctx.anchorText)
|
|
99
|
+
if (!ctx.presentationId || !ctx.anchorText)
|
|
102
100
|
return expect(true).toBe(true)
|
|
101
|
+
const imageUri = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
|
|
103
102
|
const handler = slides.write('insert_image_after_first_match')
|
|
104
|
-
const res = await handler({ presentationId: ctx.presentationId, findText: ctx.anchorText, uri:
|
|
103
|
+
const res = await handler({ presentationId: ctx.presentationId, findText: ctx.anchorText, uri: imageUri })
|
|
105
104
|
expect(res?.presentationId || Array.isArray(res?.replies)).toBeTruthy()
|
|
106
105
|
}, 60000)
|
|
107
106
|
|