@divyacon/piece-google-drive 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.MIT-AP +24 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/action/add-permission.action.d.ts +11 -0
- package/dist/lib/action/add-permission.action.d.ts.map +1 -0
- package/dist/lib/action/add-permission.action.js +83 -0
- package/dist/lib/action/add-permission.action.js.map +1 -0
- package/dist/lib/action/create-new-folder.d.ts +12 -0
- package/dist/lib/action/create-new-folder.d.ts.map +1 -0
- package/dist/lib/action/create-new-folder.js +43 -0
- package/dist/lib/action/create-new-folder.js.map +1 -0
- package/dist/lib/action/create-new-text-file.d.ts +14 -0
- package/dist/lib/action/create-new-text-file.d.ts.map +1 -0
- package/dist/lib/action/create-new-text-file.js +81 -0
- package/dist/lib/action/create-new-text-file.js.map +1 -0
- package/dist/lib/action/delete-file.d.ts +8 -0
- package/dist/lib/action/delete-file.d.ts.map +1 -0
- package/dist/lib/action/delete-file.js +38 -0
- package/dist/lib/action/delete-file.js.map +1 -0
- package/dist/lib/action/delete-permission.action.d.ts +9 -0
- package/dist/lib/action/delete-permission.action.d.ts.map +1 -0
- package/dist/lib/action/delete-permission.action.js +84 -0
- package/dist/lib/action/delete-permission.action.js.map +1 -0
- package/dist/lib/action/drive-copy-file.d.ts +10 -0
- package/dist/lib/action/drive-copy-file.d.ts.map +1 -0
- package/dist/lib/action/drive-copy-file.js +84 -0
- package/dist/lib/action/drive-copy-file.js.map +1 -0
- package/dist/lib/action/drive-create-comment.d.ts +8 -0
- package/dist/lib/action/drive-create-comment.d.ts.map +1 -0
- package/dist/lib/action/drive-create-comment.js +60 -0
- package/dist/lib/action/drive-create-comment.js.map +1 -0
- package/dist/lib/action/drive-create-file-from-text.d.ts +10 -0
- package/dist/lib/action/drive-create-file-from-text.d.ts.map +1 -0
- package/dist/lib/action/drive-create-file-from-text.js +91 -0
- package/dist/lib/action/drive-create-file-from-text.js.map +1 -0
- package/dist/lib/action/drive-create-folder.d.ts +8 -0
- package/dist/lib/action/drive-create-folder.d.ts.map +1 -0
- package/dist/lib/action/drive-create-folder.js +48 -0
- package/dist/lib/action/drive-create-folder.js.map +1 -0
- package/dist/lib/action/drive-create-reply.d.ts +10 -0
- package/dist/lib/action/drive-create-reply.d.ts.map +1 -0
- package/dist/lib/action/drive-create-reply.js +81 -0
- package/dist/lib/action/drive-create-reply.js.map +1 -0
- package/dist/lib/action/drive-create-shared-drive.d.ts +7 -0
- package/dist/lib/action/drive-create-shared-drive.d.ts.map +1 -0
- package/dist/lib/action/drive-create-shared-drive.js +53 -0
- package/dist/lib/action/drive-create-shared-drive.js.map +1 -0
- package/dist/lib/action/drive-delete-file.d.ts +7 -0
- package/dist/lib/action/drive-delete-file.d.ts.map +1 -0
- package/dist/lib/action/drive-delete-file.js +39 -0
- package/dist/lib/action/drive-delete-file.js.map +1 -0
- package/dist/lib/action/drive-delete-reply.d.ts +9 -0
- package/dist/lib/action/drive-delete-reply.d.ts.map +1 -0
- package/dist/lib/action/drive-delete-reply.js +64 -0
- package/dist/lib/action/drive-delete-reply.js.map +1 -0
- package/dist/lib/action/drive-delete-shared-drive.d.ts +7 -0
- package/dist/lib/action/drive-delete-shared-drive.d.ts.map +1 -0
- package/dist/lib/action/drive-delete-shared-drive.js +55 -0
- package/dist/lib/action/drive-delete-shared-drive.js.map +1 -0
- package/dist/lib/action/drive-download-file.d.ts +8 -0
- package/dist/lib/action/drive-download-file.d.ts.map +1 -0
- package/dist/lib/action/drive-download-file.js +37 -0
- package/dist/lib/action/drive-download-file.js.map +1 -0
- package/dist/lib/action/drive-empty-trash.d.ts +7 -0
- package/dist/lib/action/drive-empty-trash.d.ts.map +1 -0
- package/dist/lib/action/drive-empty-trash.js +47 -0
- package/dist/lib/action/drive-empty-trash.js.map +1 -0
- package/dist/lib/action/drive-export-workspace-file.d.ts +8 -0
- package/dist/lib/action/drive-export-workspace-file.d.ts.map +1 -0
- package/dist/lib/action/drive-export-workspace-file.js +116 -0
- package/dist/lib/action/drive-export-workspace-file.js.map +1 -0
- package/dist/lib/action/drive-get-about.d.ts +5 -0
- package/dist/lib/action/drive-get-about.d.ts.map +1 -0
- package/dist/lib/action/drive-get-about.js +43 -0
- package/dist/lib/action/drive-get-about.js.map +1 -0
- package/dist/lib/action/drive-get-file.d.ts +7 -0
- package/dist/lib/action/drive-get-file.d.ts.map +1 -0
- package/dist/lib/action/drive-get-file.js +46 -0
- package/dist/lib/action/drive-get-file.js.map +1 -0
- package/dist/lib/action/drive-get-reply.d.ts +9 -0
- package/dist/lib/action/drive-get-reply.d.ts.map +1 -0
- package/dist/lib/action/drive-get-reply.js +66 -0
- package/dist/lib/action/drive-get-reply.js.map +1 -0
- package/dist/lib/action/drive-get-shared-drive.d.ts +7 -0
- package/dist/lib/action/drive-get-shared-drive.d.ts.map +1 -0
- package/dist/lib/action/drive-get-shared-drive.js +52 -0
- package/dist/lib/action/drive-get-shared-drive.js.map +1 -0
- package/dist/lib/action/drive-list-comments.d.ts +7 -0
- package/dist/lib/action/drive-list-comments.d.ts.map +1 -0
- package/dist/lib/action/drive-list-comments.js +60 -0
- package/dist/lib/action/drive-list-comments.js.map +1 -0
- package/dist/lib/action/drive-list-files.d.ts +11 -0
- package/dist/lib/action/drive-list-files.d.ts.map +1 -0
- package/dist/lib/action/drive-list-files.js +174 -0
- package/dist/lib/action/drive-list-files.js.map +1 -0
- package/dist/lib/action/drive-list-permissions.d.ts +7 -0
- package/dist/lib/action/drive-list-permissions.d.ts.map +1 -0
- package/dist/lib/action/drive-list-permissions.js +59 -0
- package/dist/lib/action/drive-list-permissions.js.map +1 -0
- package/dist/lib/action/drive-list-replies.d.ts +8 -0
- package/dist/lib/action/drive-list-replies.d.ts.map +1 -0
- package/dist/lib/action/drive-list-replies.js +65 -0
- package/dist/lib/action/drive-list-replies.js.map +1 -0
- package/dist/lib/action/drive-list-shared-drives.d.ts +8 -0
- package/dist/lib/action/drive-list-shared-drives.d.ts.map +1 -0
- package/dist/lib/action/drive-list-shared-drives.js +60 -0
- package/dist/lib/action/drive-list-shared-drives.js.map +1 -0
- package/dist/lib/action/drive-move-file.d.ts +8 -0
- package/dist/lib/action/drive-move-file.d.ts.map +1 -0
- package/dist/lib/action/drive-move-file.js +57 -0
- package/dist/lib/action/drive-move-file.js.map +1 -0
- package/dist/lib/action/drive-remove-permission.d.ts +9 -0
- package/dist/lib/action/drive-remove-permission.d.ts.map +1 -0
- package/dist/lib/action/drive-remove-permission.js +75 -0
- package/dist/lib/action/drive-remove-permission.js.map +1 -0
- package/dist/lib/action/drive-replace-file-content.d.ts +9 -0
- package/dist/lib/action/drive-replace-file-content.d.ts.map +1 -0
- package/dist/lib/action/drive-replace-file-content.js +67 -0
- package/dist/lib/action/drive-replace-file-content.js.map +1 -0
- package/dist/lib/action/drive-save-file-as-pdf.d.ts +9 -0
- package/dist/lib/action/drive-save-file-as-pdf.d.ts.map +1 -0
- package/dist/lib/action/drive-save-file-as-pdf.js +73 -0
- package/dist/lib/action/drive-save-file-as-pdf.js.map +1 -0
- package/dist/lib/action/drive-search-files.d.ts +12 -0
- package/dist/lib/action/drive-search-files.d.ts.map +1 -0
- package/dist/lib/action/drive-search-files.js +130 -0
- package/dist/lib/action/drive-search-files.js.map +1 -0
- package/dist/lib/action/drive-set-public-access.d.ts +8 -0
- package/dist/lib/action/drive-set-public-access.d.ts.map +1 -0
- package/dist/lib/action/drive-set-public-access.js +71 -0
- package/dist/lib/action/drive-set-public-access.js.map +1 -0
- package/dist/lib/action/drive-share-file.d.ts +10 -0
- package/dist/lib/action/drive-share-file.d.ts.map +1 -0
- package/dist/lib/action/drive-share-file.js +69 -0
- package/dist/lib/action/drive-share-file.js.map +1 -0
- package/dist/lib/action/drive-trash-file.d.ts +7 -0
- package/dist/lib/action/drive-trash-file.d.ts.map +1 -0
- package/dist/lib/action/drive-trash-file.js +45 -0
- package/dist/lib/action/drive-trash-file.js.map +1 -0
- package/dist/lib/action/drive-untrash-file.d.ts +7 -0
- package/dist/lib/action/drive-untrash-file.d.ts.map +1 -0
- package/dist/lib/action/drive-untrash-file.js +54 -0
- package/dist/lib/action/drive-untrash-file.js.map +1 -0
- package/dist/lib/action/drive-update-file-metadata.d.ts +10 -0
- package/dist/lib/action/drive-update-file-metadata.d.ts.map +1 -0
- package/dist/lib/action/drive-update-file-metadata.js +79 -0
- package/dist/lib/action/drive-update-file-metadata.js.map +1 -0
- package/dist/lib/action/drive-update-permission.d.ts +9 -0
- package/dist/lib/action/drive-update-permission.d.ts.map +1 -0
- package/dist/lib/action/drive-update-permission.js +93 -0
- package/dist/lib/action/drive-update-permission.js.map +1 -0
- package/dist/lib/action/drive-update-reply.d.ts +10 -0
- package/dist/lib/action/drive-update-reply.d.ts.map +1 -0
- package/dist/lib/action/drive-update-reply.js +72 -0
- package/dist/lib/action/drive-update-reply.js.map +1 -0
- package/dist/lib/action/drive-update-shared-drive.d.ts +8 -0
- package/dist/lib/action/drive-update-shared-drive.d.ts.map +1 -0
- package/dist/lib/action/drive-update-shared-drive.js +62 -0
- package/dist/lib/action/drive-update-shared-drive.js.map +1 -0
- package/dist/lib/action/drive-upload-file.d.ts +9 -0
- package/dist/lib/action/drive-upload-file.d.ts.map +1 -0
- package/dist/lib/action/drive-upload-file.js +71 -0
- package/dist/lib/action/drive-upload-file.js.map +1 -0
- package/dist/lib/action/drive-upload-from-url.d.ts +10 -0
- package/dist/lib/action/drive-upload-from-url.d.ts.map +1 -0
- package/dist/lib/action/drive-upload-from-url.js +90 -0
- package/dist/lib/action/drive-upload-from-url.js.map +1 -0
- package/dist/lib/action/duplicate-file.action.d.ts +11 -0
- package/dist/lib/action/duplicate-file.action.d.ts.map +1 -0
- package/dist/lib/action/duplicate-file.action.js +83 -0
- package/dist/lib/action/duplicate-file.action.js.map +1 -0
- package/dist/lib/action/get-file-by-id.d.ts +8 -0
- package/dist/lib/action/get-file-by-id.d.ts.map +1 -0
- package/dist/lib/action/get-file-by-id.js +45 -0
- package/dist/lib/action/get-file-by-id.js.map +1 -0
- package/dist/lib/action/list-files.action.d.ts +11 -0
- package/dist/lib/action/list-files.action.d.ts.map +1 -0
- package/dist/lib/action/list-files.action.js +165 -0
- package/dist/lib/action/list-files.action.js.map +1 -0
- package/dist/lib/action/move-file.d.ts +12 -0
- package/dist/lib/action/move-file.d.ts.map +1 -0
- package/dist/lib/action/move-file.js +52 -0
- package/dist/lib/action/move-file.js.map +1 -0
- package/dist/lib/action/read-file.d.ts +8 -0
- package/dist/lib/action/read-file.d.ts.map +1 -0
- package/dist/lib/action/read-file.js +34 -0
- package/dist/lib/action/read-file.js.map +1 -0
- package/dist/lib/action/save-file-as-pdf.action.d.ts +10 -0
- package/dist/lib/action/save-file-as-pdf.action.d.ts.map +1 -0
- package/dist/lib/action/save-file-as-pdf.action.js +72 -0
- package/dist/lib/action/save-file-as-pdf.action.js.map +1 -0
- package/dist/lib/action/search-folder-or-file.action.d.ts +15 -0
- package/dist/lib/action/search-folder-or-file.action.d.ts.map +1 -0
- package/dist/lib/action/search-folder-or-file.action.js +119 -0
- package/dist/lib/action/search-folder-or-file.action.js.map +1 -0
- package/dist/lib/action/send-to-trash.d.ts +8 -0
- package/dist/lib/action/send-to-trash.d.ts.map +1 -0
- package/dist/lib/action/send-to-trash.js +44 -0
- package/dist/lib/action/send-to-trash.js.map +1 -0
- package/dist/lib/action/set-public-access.d.ts +8 -0
- package/dist/lib/action/set-public-access.d.ts.map +1 -0
- package/dist/lib/action/set-public-access.js +66 -0
- package/dist/lib/action/set-public-access.js.map +1 -0
- package/dist/lib/action/upload-file.d.ts +13 -0
- package/dist/lib/action/upload-file.d.ts.map +1 -0
- package/dist/lib/action/upload-file.js +58 -0
- package/dist/lib/action/upload-file.js.map +1 -0
- package/dist/lib/auth.d.ts +11 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +87 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/common/get-file-content.d.ts +4 -0
- package/dist/lib/common/get-file-content.d.ts.map +1 -0
- package/dist/lib/common/get-file-content.js +69 -0
- package/dist/lib/common/get-file-content.js.map +1 -0
- package/dist/lib/common/index.d.ts +23 -0
- package/dist/lib/common/index.d.ts.map +1 -0
- package/dist/lib/common/index.js +152 -0
- package/dist/lib/common/index.js.map +1 -0
- package/dist/lib/output-schemas.d.ts +53 -0
- package/dist/lib/output-schemas.d.ts.map +1 -0
- package/dist/lib/output-schemas.js +2022 -0
- package/dist/lib/output-schemas.js.map +1 -0
- package/dist/lib/triggers/new-file.d.ts +43 -0
- package/dist/lib/triggers/new-file.d.ts.map +1 -0
- package/dist/lib/triggers/new-file.js +107 -0
- package/dist/lib/triggers/new-file.js.map +1 -0
- package/dist/lib/triggers/new-folder.d.ts +39 -0
- package/dist/lib/triggers/new-folder.d.ts.map +1 -0
- package/dist/lib/triggers/new-folder.js +71 -0
- package/dist/lib/triggers/new-folder.js.map +1 -0
- package/package.json +49 -3
- package/src/index.ts +149 -0
- package/src/lib/action/add-permission.action.ts +82 -0
- package/src/lib/action/create-new-folder.ts +42 -0
- package/src/lib/action/create-new-text-file.ts +80 -0
- package/src/lib/action/delete-file.ts +33 -0
- package/src/lib/action/delete-permission.action.ts +84 -0
- package/src/lib/action/drive-copy-file.ts +86 -0
- package/src/lib/action/drive-create-comment.ts +61 -0
- package/src/lib/action/drive-create-file-from-text.ts +99 -0
- package/src/lib/action/drive-create-folder.ts +49 -0
- package/src/lib/action/drive-create-reply.ts +84 -0
- package/src/lib/action/drive-create-shared-drive.ts +52 -0
- package/src/lib/action/drive-delete-file.ts +36 -0
- package/src/lib/action/drive-delete-reply.ts +65 -0
- package/src/lib/action/drive-delete-shared-drive.ts +57 -0
- package/src/lib/action/drive-download-file.ts +38 -0
- package/src/lib/action/drive-empty-trash.ts +47 -0
- package/src/lib/action/drive-export-workspace-file.ts +129 -0
- package/src/lib/action/drive-get-about.ts +40 -0
- package/src/lib/action/drive-get-file.ts +40 -0
- package/src/lib/action/drive-get-reply.ts +67 -0
- package/src/lib/action/drive-get-shared-drive.ts +52 -0
- package/src/lib/action/drive-list-comments.ts +61 -0
- package/src/lib/action/drive-list-files.ts +238 -0
- package/src/lib/action/drive-list-permissions.ts +60 -0
- package/src/lib/action/drive-list-replies.ts +66 -0
- package/src/lib/action/drive-list-shared-drives.ts +59 -0
- package/src/lib/action/drive-move-file.ts +56 -0
- package/src/lib/action/drive-remove-permission.ts +75 -0
- package/src/lib/action/drive-replace-file-content.ts +71 -0
- package/src/lib/action/drive-save-file-as-pdf.ts +80 -0
- package/src/lib/action/drive-search-files.ts +127 -0
- package/src/lib/action/drive-set-public-access.ts +75 -0
- package/src/lib/action/drive-share-file.ts +69 -0
- package/src/lib/action/drive-trash-file.ts +41 -0
- package/src/lib/action/drive-untrash-file.ts +54 -0
- package/src/lib/action/drive-update-file-metadata.ts +82 -0
- package/src/lib/action/drive-update-permission.ts +100 -0
- package/src/lib/action/drive-update-reply.ts +73 -0
- package/src/lib/action/drive-update-shared-drive.ts +63 -0
- package/src/lib/action/drive-upload-file.ts +80 -0
- package/src/lib/action/drive-upload-from-url.ts +107 -0
- package/src/lib/action/duplicate-file.action.ts +82 -0
- package/src/lib/action/get-file-by-id.ts +37 -0
- package/src/lib/action/list-files.action.ts +214 -0
- package/src/lib/action/move-file.ts +48 -0
- package/src/lib/action/read-file.ts +28 -0
- package/src/lib/action/save-file-as-pdf.action.ts +76 -0
- package/src/lib/action/search-folder-or-file.action.ts +112 -0
- package/src/lib/action/send-to-trash.ts +38 -0
- package/src/lib/action/set-public-access.ts +68 -0
- package/src/lib/action/upload-file.ts +55 -0
- package/src/lib/auth.ts +79 -0
- package/src/lib/common/get-file-content.ts +109 -0
- package/src/lib/common/index.ts +182 -0
- package/src/lib/output-schemas.ts +2070 -0
- package/src/lib/triggers/new-file.ts +119 -0
- package/src/lib/triggers/new-folder.ts +78 -0
- package/README.md +0 -3
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Property, createAction } from '@agnocon/pieces-framework';
|
|
2
|
+
import { googleDriveAuth, createGoogleClient } from '../auth';
|
|
3
|
+
import { drive as googleDrive } from '@googleapis/drive';
|
|
4
|
+
import { driveUpdateReplyOutputSchema } from '../output-schemas';
|
|
5
|
+
|
|
6
|
+
export const driveUpdateReply = createAction({
|
|
7
|
+
auth: googleDriveAuth,
|
|
8
|
+
name: 'drive_update_reply',
|
|
9
|
+
displayName: 'Update Reply',
|
|
10
|
+
description: 'Edit the text of an existing reply on a Drive comment.',
|
|
11
|
+
audience: 'ai',
|
|
12
|
+
aiMetadata: {
|
|
13
|
+
description:
|
|
14
|
+
'Edits the text of an existing reply by ID (resolve via drive_list_replies). Use to correct or revise a reply you control; to add a new reply instead use drive_create_reply. Safe to retry — re-applying the same content is a no-op.',
|
|
15
|
+
idempotent: true,
|
|
16
|
+
},
|
|
17
|
+
outputSchema: driveUpdateReplyOutputSchema,
|
|
18
|
+
props: {
|
|
19
|
+
file_id: Property.ShortText({
|
|
20
|
+
displayName: 'File ID',
|
|
21
|
+
description:
|
|
22
|
+
'The ID of the file the comment belongs to. Resolve it via drive_search_files or drive_get_file.',
|
|
23
|
+
required: true,
|
|
24
|
+
}),
|
|
25
|
+
comment_id: Property.ShortText({
|
|
26
|
+
displayName: 'Comment ID',
|
|
27
|
+
description: 'The ID of the parent comment. Resolve it via drive_list_comments.',
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
reply_id: Property.ShortText({
|
|
31
|
+
displayName: 'Reply ID',
|
|
32
|
+
description: 'The ID of the reply to update. Resolve it via drive_list_replies.',
|
|
33
|
+
required: true,
|
|
34
|
+
}),
|
|
35
|
+
content: Property.LongText({
|
|
36
|
+
displayName: 'Content',
|
|
37
|
+
description: 'The new plain-text content for the reply.',
|
|
38
|
+
required: true,
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
async run(context) {
|
|
42
|
+
const { file_id, comment_id, reply_id, content } = context.propsValue;
|
|
43
|
+
|
|
44
|
+
const authClient = await createGoogleClient(context.auth);
|
|
45
|
+
|
|
46
|
+
const drive = googleDrive({ version: 'v3', auth: authClient });
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
// The Drive replies endpoints require a fields parameter or the API returns 400.
|
|
50
|
+
const response = await drive.replies.update({
|
|
51
|
+
fileId: file_id,
|
|
52
|
+
commentId: comment_id,
|
|
53
|
+
replyId: reply_id,
|
|
54
|
+
fields: '*',
|
|
55
|
+
requestBody: { content },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return response.data;
|
|
59
|
+
} catch (error: any) {
|
|
60
|
+
if (error.code === 404) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`File, comment, or reply not found (file ID: ${file_id}, comment ID: ${comment_id}, reply ID: ${reply_id}). Resolve the reply ID via drive_list_replies.`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (error.code === 403) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Permission denied updating reply ${reply_id} on file ${file_id}. You can only edit your own replies.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Property, createAction } from '@agnocon/pieces-framework';
|
|
2
|
+
import { googleDriveAuth, createGoogleClient } from '../auth';
|
|
3
|
+
import { drive as googleDrive } from '@googleapis/drive';
|
|
4
|
+
import { driveUpdateSharedDriveOutputSchema } from '../output-schemas';
|
|
5
|
+
|
|
6
|
+
export const driveUpdateSharedDrive = createAction({
|
|
7
|
+
auth: googleDriveAuth,
|
|
8
|
+
name: 'drive_update_shared_drive',
|
|
9
|
+
displayName: 'Update Shared Drive',
|
|
10
|
+
description: 'Rename or update a shared drive by ID.',
|
|
11
|
+
audience: 'ai',
|
|
12
|
+
aiMetadata: {
|
|
13
|
+
description:
|
|
14
|
+
'Renames or updates a shared drive\'s settings by ID (resolve via drive_list_shared_drives). Use to rename a shared drive; to remove it entirely use drive_delete_shared_drive. Safe to retry — re-applying the same values is a no-op.',
|
|
15
|
+
idempotent: true,
|
|
16
|
+
},
|
|
17
|
+
outputSchema: driveUpdateSharedDriveOutputSchema,
|
|
18
|
+
props: {
|
|
19
|
+
drive_id: Property.ShortText({
|
|
20
|
+
displayName: 'Shared Drive ID',
|
|
21
|
+
description: 'The ID of the shared drive to update. Resolve it via drive_list_shared_drives.',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
name: Property.ShortText({
|
|
25
|
+
displayName: 'Name',
|
|
26
|
+
description: 'The new name for the shared drive. Leave empty to keep the current name.',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
async run(context) {
|
|
31
|
+
const { drive_id, name } = context.propsValue;
|
|
32
|
+
|
|
33
|
+
const authClient = await createGoogleClient(context.auth);
|
|
34
|
+
|
|
35
|
+
const drive = googleDrive({ version: 'v3', auth: authClient });
|
|
36
|
+
|
|
37
|
+
const requestBody: { name?: string } = {};
|
|
38
|
+
if (name) {
|
|
39
|
+
requestBody.name = name;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const response = await drive.drives.update({
|
|
44
|
+
driveId: drive_id,
|
|
45
|
+
requestBody,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return response.data;
|
|
49
|
+
} catch (error: any) {
|
|
50
|
+
if (error.code === 404) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`Shared drive not found (ID: ${drive_id}). Resolve a valid ID via drive_list_shared_drives.`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
if (error.code === 403) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Permission denied updating shared drive ${drive_id}. You must be an organizer of this drive.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createAction, Property } from '@agnocon/pieces-framework';
|
|
2
|
+
import {
|
|
3
|
+
httpClient,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
AuthenticationType,
|
|
6
|
+
} from '@agnocon/pieces-common';
|
|
7
|
+
import FormData from 'form-data';
|
|
8
|
+
import { googleDriveAuth, getAccessToken } from '../auth';
|
|
9
|
+
import mime from 'mime-types';
|
|
10
|
+
import { driveUploadFileOutputSchema } from '../output-schemas';
|
|
11
|
+
|
|
12
|
+
export const driveUploadFile = createAction({
|
|
13
|
+
auth: googleDriveAuth,
|
|
14
|
+
name: 'drive_upload_file',
|
|
15
|
+
displayName: 'Upload File',
|
|
16
|
+
description: 'Upload a file in your Google Drive',
|
|
17
|
+
audience: 'ai',
|
|
18
|
+
aiMetadata: {
|
|
19
|
+
description:
|
|
20
|
+
'Uploads a binary file (from a URL or base64 input) into Drive; MIME type is inferred from the extension. Use to store an existing file or attachment; for plain generated text use `drive_create_file_from_text`, and to fetch a remote URL server-side use `drive_upload_from_url`. Each call creates a new file.',
|
|
21
|
+
idempotent: false,
|
|
22
|
+
},
|
|
23
|
+
outputSchema: driveUploadFileOutputSchema,
|
|
24
|
+
props: {
|
|
25
|
+
file_name: Property.ShortText({
|
|
26
|
+
displayName: 'File name',
|
|
27
|
+
description: 'The name of the file',
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
file: Property.File({
|
|
31
|
+
displayName: 'File',
|
|
32
|
+
description: 'The file URL or base64 to upload',
|
|
33
|
+
required: true,
|
|
34
|
+
}),
|
|
35
|
+
parent_folder_id: Property.ShortText({
|
|
36
|
+
displayName: 'Parent Folder ID',
|
|
37
|
+
description:
|
|
38
|
+
'The ID of the folder to upload the file into. Leave empty to upload to the root of My Drive. Resolve a folder ID with `drive_search_files`.',
|
|
39
|
+
required: false,
|
|
40
|
+
}),
|
|
41
|
+
},
|
|
42
|
+
async run(context) {
|
|
43
|
+
const fileData = context.propsValue.file;
|
|
44
|
+
const mimeType = mime.lookup(fileData.extension ? fileData.extension : '');
|
|
45
|
+
|
|
46
|
+
const meta = {
|
|
47
|
+
mimeType: mimeType,
|
|
48
|
+
name: context.propsValue.file_name,
|
|
49
|
+
...(context.propsValue.parent_folder_id
|
|
50
|
+
? { parents: [context.propsValue.parent_folder_id] }
|
|
51
|
+
: {}),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const metaBuffer = Buffer.from(JSON.stringify(meta), 'utf-8');
|
|
55
|
+
const fileBuffer = Buffer.from(fileData.base64, 'base64');
|
|
56
|
+
|
|
57
|
+
const form = new FormData();
|
|
58
|
+
form.append('Metadata', metaBuffer, { contentType: 'application/json' });
|
|
59
|
+
form.append('Media', fileBuffer);
|
|
60
|
+
|
|
61
|
+
const result = await httpClient.sendRequest({
|
|
62
|
+
method: HttpMethod.POST,
|
|
63
|
+
url: `https://www.googleapis.com/upload/drive/v3/files`,
|
|
64
|
+
queryParams: {
|
|
65
|
+
uploadType: 'multipart',
|
|
66
|
+
supportsAllDrives: 'true',
|
|
67
|
+
},
|
|
68
|
+
body: form,
|
|
69
|
+
headers: {
|
|
70
|
+
...form.getHeaders(),
|
|
71
|
+
},
|
|
72
|
+
authentication: {
|
|
73
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
74
|
+
token: await getAccessToken(context.auth),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
return result.body;
|
|
79
|
+
},
|
|
80
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { createAction, Property } from '@agnocon/pieces-framework';
|
|
2
|
+
import {
|
|
3
|
+
httpClient,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
AuthenticationType,
|
|
6
|
+
} from '@agnocon/pieces-common';
|
|
7
|
+
import FormData from 'form-data';
|
|
8
|
+
import { googleDriveAuth, getAccessToken } from '../auth';
|
|
9
|
+
import mime from 'mime-types';
|
|
10
|
+
import { driveUploadFromUrlOutputSchema } from '../output-schemas';
|
|
11
|
+
|
|
12
|
+
export const driveUploadFromUrl = createAction({
|
|
13
|
+
auth: googleDriveAuth,
|
|
14
|
+
name: 'drive_upload_from_url',
|
|
15
|
+
displayName: 'Upload File from URL',
|
|
16
|
+
description: 'Fetch a file from a public URL and upload it into Google Drive.',
|
|
17
|
+
audience: 'ai',
|
|
18
|
+
aiMetadata: {
|
|
19
|
+
description:
|
|
20
|
+
'Fetches a file from a public URL and uploads it into Drive in one step (server-side fetch, no base64 round-trip). Use when the agent has a downloadable link rather than file bytes; for bytes already in hand use `drive_upload_file`, and for plain generated text use `drive_create_file_from_text`. Each call creates a new file.',
|
|
21
|
+
idempotent: false,
|
|
22
|
+
},
|
|
23
|
+
outputSchema: driveUploadFromUrlOutputSchema,
|
|
24
|
+
props: {
|
|
25
|
+
source_url: Property.ShortText({
|
|
26
|
+
displayName: 'Source URL',
|
|
27
|
+
description:
|
|
28
|
+
'The publicly accessible URL to fetch the file from. Only public URLs are supported (no authentication headers are sent).',
|
|
29
|
+
required: true,
|
|
30
|
+
}),
|
|
31
|
+
file_name: Property.ShortText({
|
|
32
|
+
displayName: 'File name',
|
|
33
|
+
description: 'The name to give the uploaded file in Drive.',
|
|
34
|
+
required: true,
|
|
35
|
+
}),
|
|
36
|
+
mime_type: Property.ShortText({
|
|
37
|
+
displayName: 'MIME Type',
|
|
38
|
+
description:
|
|
39
|
+
'Optional MIME type for the uploaded file (e.g. application/pdf). Provide this when the URL has no file extension; otherwise the type is inferred from the URL.',
|
|
40
|
+
required: false,
|
|
41
|
+
}),
|
|
42
|
+
parent_folder_id: Property.ShortText({
|
|
43
|
+
displayName: 'Parent Folder ID',
|
|
44
|
+
description:
|
|
45
|
+
'The ID of the folder to upload the file into. Leave empty to upload to the root of My Drive. Resolve a folder ID with `drive_search_files`.',
|
|
46
|
+
required: false,
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
async run(context) {
|
|
50
|
+
const { source_url, file_name, mime_type, parent_folder_id } =
|
|
51
|
+
context.propsValue;
|
|
52
|
+
|
|
53
|
+
// SSRF: only public URLs supported — no auth headers are forwarded and the
|
|
54
|
+
// caller is responsible for supplying a publicly reachable link.
|
|
55
|
+
let download;
|
|
56
|
+
try {
|
|
57
|
+
download = await httpClient.sendRequest<ArrayBuffer>({
|
|
58
|
+
method: HttpMethod.GET,
|
|
59
|
+
url: source_url,
|
|
60
|
+
responseType: 'arraybuffer',
|
|
61
|
+
});
|
|
62
|
+
} catch (error: any) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Failed to fetch the file from the source URL (${source_url}). Ensure it is a publicly accessible link. Underlying error: ${
|
|
65
|
+
error?.message ?? error
|
|
66
|
+
}`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Honor an explicit mime_type when the URL lacks an extension; otherwise
|
|
71
|
+
// infer it from the URL so Drive does not default everything to octet-stream.
|
|
72
|
+
const resolvedMimeType =
|
|
73
|
+
mime_type || mime.lookup(source_url) || 'application/octet-stream';
|
|
74
|
+
|
|
75
|
+
const meta = {
|
|
76
|
+
mimeType: resolvedMimeType,
|
|
77
|
+
name: file_name,
|
|
78
|
+
...(parent_folder_id ? { parents: [parent_folder_id] } : {}),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const metaBuffer = Buffer.from(JSON.stringify(meta), 'utf-8');
|
|
82
|
+
const fileBuffer = Buffer.from(download.body);
|
|
83
|
+
|
|
84
|
+
const form = new FormData();
|
|
85
|
+
form.append('Metadata', metaBuffer, { contentType: 'application/json' });
|
|
86
|
+
form.append('Media', fileBuffer, { contentType: resolvedMimeType });
|
|
87
|
+
|
|
88
|
+
const result = await httpClient.sendRequest({
|
|
89
|
+
method: HttpMethod.POST,
|
|
90
|
+
url: `https://www.googleapis.com/upload/drive/v3/files`,
|
|
91
|
+
queryParams: {
|
|
92
|
+
uploadType: 'multipart',
|
|
93
|
+
supportsAllDrives: 'true',
|
|
94
|
+
},
|
|
95
|
+
body: form,
|
|
96
|
+
headers: {
|
|
97
|
+
...form.getHeaders(),
|
|
98
|
+
},
|
|
99
|
+
authentication: {
|
|
100
|
+
type: AuthenticationType.BEARER_TOKEN,
|
|
101
|
+
token: await getAccessToken(context.auth),
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return result.body;
|
|
106
|
+
},
|
|
107
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Property, createAction } from '@agnocon/pieces-framework';
|
|
2
|
+
import { drive as googleDrive } from '@googleapis/drive';
|
|
3
|
+
import { googleDriveAuth, createGoogleClient } from '../auth';
|
|
4
|
+
import { common } from '../common';
|
|
5
|
+
import { duplicateFileActionOutputSchema } from '../output-schemas';
|
|
6
|
+
|
|
7
|
+
export const duplicateFileAction = createAction({
|
|
8
|
+
displayName: 'Duplicate File',
|
|
9
|
+
auth: googleDriveAuth,
|
|
10
|
+
name: 'duplicate_file',
|
|
11
|
+
description: 'Duplicate a file from Google Drive. Returns the new file ID.',
|
|
12
|
+
audience: 'human',
|
|
13
|
+
aiMetadata: { description: 'Copies an existing Drive file into a target folder under a new name, optionally converting it to a Google Sheet or Google Doc. Use to clone a file or create an editable Google-format copy. Requires the source file ID and destination folder ID. Not idempotent: each call creates a new copy.', idempotent: false },
|
|
14
|
+
props: {
|
|
15
|
+
fileId: Property.ShortText({
|
|
16
|
+
displayName: 'File ID',
|
|
17
|
+
description: 'The ID of the file to duplicate',
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
name: Property.ShortText({
|
|
21
|
+
displayName: 'Name',
|
|
22
|
+
description: 'The name of the new file',
|
|
23
|
+
required: true,
|
|
24
|
+
}),
|
|
25
|
+
folderId: Property.ShortText({
|
|
26
|
+
displayName: 'Folder ID',
|
|
27
|
+
description: 'The ID of the folder where the file will be duplicated',
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
mimeType: Property.StaticDropdown({
|
|
31
|
+
displayName: 'Duplicate as',
|
|
32
|
+
description: 'If left unselected the file will be duplicated as it is',
|
|
33
|
+
required: false,
|
|
34
|
+
options: {
|
|
35
|
+
options: [
|
|
36
|
+
{
|
|
37
|
+
label: 'Google Sheets',
|
|
38
|
+
value: 'application/vnd.google-apps.spreadsheet',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: 'Google Docs',
|
|
42
|
+
value: 'application/vnd.google-apps.document',
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
include_team_drives: common.properties.include_team_drives,
|
|
48
|
+
},
|
|
49
|
+
outputSchema: duplicateFileActionOutputSchema,
|
|
50
|
+
async run(context) {
|
|
51
|
+
const authClient = await createGoogleClient(context.auth);
|
|
52
|
+
|
|
53
|
+
const fileId = context.propsValue.fileId;
|
|
54
|
+
const nameForNewFile = context.propsValue.name;
|
|
55
|
+
const parentFolderId = context.propsValue.folderId;
|
|
56
|
+
const mimeType = context.propsValue.mimeType;
|
|
57
|
+
|
|
58
|
+
const drive = googleDrive({ version: 'v3', auth: authClient });
|
|
59
|
+
|
|
60
|
+
const requestBody: any = {
|
|
61
|
+
name: nameForNewFile,
|
|
62
|
+
parents: [parentFolderId],
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
if (mimeType) {
|
|
66
|
+
requestBody.mimeType = mimeType;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const response = await drive.files.copy({
|
|
70
|
+
fileId,
|
|
71
|
+
auth: authClient,
|
|
72
|
+
requestBody,
|
|
73
|
+
supportsAllDrives: context.propsValue.include_team_drives,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (response.status !== 200) {
|
|
77
|
+
throw new Error('Error duplicating file');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return response.data;
|
|
81
|
+
},
|
|
82
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { googleDriveAuth, createGoogleClient } from '../auth';
|
|
2
|
+
import { Property, createAction } from '@agnocon/pieces-framework';
|
|
3
|
+
import { drive as googleDrive } from '@googleapis/drive';
|
|
4
|
+
import { common } from '../common';
|
|
5
|
+
import { getFileOrFolderByIdActionOutputSchema } from '../output-schemas';
|
|
6
|
+
|
|
7
|
+
export const googleDriveGetResourceById = createAction({
|
|
8
|
+
auth: googleDriveAuth,
|
|
9
|
+
name: 'get-file-or-folder-by-id',
|
|
10
|
+
displayName: 'Get File Information',
|
|
11
|
+
description: 'Get a file folder for files/sub-folders',
|
|
12
|
+
audience: 'human',
|
|
13
|
+
aiMetadata: { description: 'Fetches metadata for a single file or folder in Google Drive by its exact ID (name, MIME type, parents, etc.). Use when an agent already has a file/folder ID and needs its details. Read-only and idempotent. Requires the resource ID, not a name or path.', idempotent: true },
|
|
14
|
+
props: {
|
|
15
|
+
id: Property.ShortText({
|
|
16
|
+
displayName: 'File / Folder Id',
|
|
17
|
+
description: 'The Id of the file/folder to search for.',
|
|
18
|
+
required: true,
|
|
19
|
+
}),
|
|
20
|
+
include_team_drives: common.properties.include_team_drives,
|
|
21
|
+
},
|
|
22
|
+
outputSchema: getFileOrFolderByIdActionOutputSchema,
|
|
23
|
+
async run(context) {
|
|
24
|
+
const authClient = await createGoogleClient(context.auth);
|
|
25
|
+
const drive = googleDrive({ version: 'v3', auth: authClient });
|
|
26
|
+
const response = await drive.files.get({
|
|
27
|
+
fileId: context.propsValue.id,
|
|
28
|
+
supportsAllDrives: context.propsValue.include_team_drives,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (response.data) {
|
|
32
|
+
return response.data;
|
|
33
|
+
} else {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { HttpMethod, httpClient } from '@agnocon/pieces-common';
|
|
2
|
+
import { googleDriveAuth, getAccessToken } from '../auth';
|
|
3
|
+
import { Property, createAction } from "@agnocon/pieces-framework";
|
|
4
|
+
import querystring from 'querystring';
|
|
5
|
+
import { common } from '../common';
|
|
6
|
+
import { downloadFileFromDrive } from '../common/get-file-content';
|
|
7
|
+
import { listFilesActionOutputSchema } from '../output-schemas';
|
|
8
|
+
|
|
9
|
+
interface ListFilesResult {
|
|
10
|
+
type: string;
|
|
11
|
+
incompleteSearch: boolean;
|
|
12
|
+
files: unknown[];
|
|
13
|
+
downloadedFiles?: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface FileWithLevel {
|
|
17
|
+
file: any;
|
|
18
|
+
level: number;
|
|
19
|
+
parentFolder?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function getFilesRecursively(
|
|
23
|
+
auth: any,
|
|
24
|
+
folderId: string,
|
|
25
|
+
maxLevel: number,
|
|
26
|
+
includeTrashed: boolean,
|
|
27
|
+
includeTeamDrives: boolean,
|
|
28
|
+
currentLevel = 0
|
|
29
|
+
): Promise<FileWithLevel[]> {
|
|
30
|
+
const files: FileWithLevel[] = [];
|
|
31
|
+
|
|
32
|
+
if (currentLevel > maxLevel) {
|
|
33
|
+
return files;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const accessToken = await getAccessToken(auth);
|
|
37
|
+
|
|
38
|
+
let q = `'${folderId}' in parents`;
|
|
39
|
+
if (!includeTrashed) {
|
|
40
|
+
q += ' and trashed=false';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const params: Record<string, string> = {
|
|
44
|
+
q: q,
|
|
45
|
+
fields: 'nextPageToken,files(id,kind,mimeType,name,trashed,parents)',
|
|
46
|
+
supportsAllDrives: 'true',
|
|
47
|
+
includeItemsFromAllDrives: includeTeamDrives ? 'true' : 'false',
|
|
48
|
+
corpora: includeTeamDrives ? 'allDrives' : 'user',
|
|
49
|
+
pageSize: '1000',
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
let response = await httpClient.sendRequest({
|
|
53
|
+
method: HttpMethod.GET,
|
|
54
|
+
url: `https://www.googleapis.com/drive/v3/files?${querystring.stringify(params)}`,
|
|
55
|
+
headers: {
|
|
56
|
+
Authorization: `Bearer ${accessToken}`,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Add files from current level
|
|
61
|
+
for (const file of response.body.files) {
|
|
62
|
+
files.push({
|
|
63
|
+
file,
|
|
64
|
+
level: currentLevel,
|
|
65
|
+
parentFolder: folderId
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Handle pagination for current level
|
|
70
|
+
while (response.body.nextPageToken) {
|
|
71
|
+
params.pageToken = response.body.nextPageToken;
|
|
72
|
+
response = await httpClient.sendRequest({
|
|
73
|
+
method: HttpMethod.GET,
|
|
74
|
+
url: `https://www.googleapis.com/drive/v3/files?${querystring.stringify(params)}`,
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${accessToken}`,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
for (const file of response.body.files) {
|
|
81
|
+
files.push({
|
|
82
|
+
file,
|
|
83
|
+
level: currentLevel,
|
|
84
|
+
parentFolder: folderId
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If we haven't reached max level, recursively get files from subfolders
|
|
90
|
+
if (currentLevel + 1 < maxLevel) {
|
|
91
|
+
const subfolders = files.filter(f => f.file.mimeType === 'application/vnd.google-apps.folder');
|
|
92
|
+
|
|
93
|
+
for (const subfolder of subfolders) {
|
|
94
|
+
const subfolderFiles = await getFilesRecursively(
|
|
95
|
+
auth,
|
|
96
|
+
subfolder.file.id,
|
|
97
|
+
maxLevel,
|
|
98
|
+
includeTrashed,
|
|
99
|
+
includeTeamDrives,
|
|
100
|
+
currentLevel + 1
|
|
101
|
+
);
|
|
102
|
+
files.push(...subfolderFiles);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return files;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const googleDriveListFiles = createAction({
|
|
110
|
+
auth: googleDriveAuth,
|
|
111
|
+
name: 'list-files',
|
|
112
|
+
displayName: 'List files',
|
|
113
|
+
description: 'List files from a Google Drive folder',
|
|
114
|
+
audience: 'human',
|
|
115
|
+
aiMetadata: { description: 'Lists files and subfolders inside a given Drive folder, with optional recursion to a chosen depth and optional download of each file\'s content. Use to enumerate the contents of a known folder ID. Read-only and idempotent. Requires the folder ID, not a name.', idempotent: true },
|
|
116
|
+
props: {
|
|
117
|
+
folderId: Property.ShortText({
|
|
118
|
+
displayName: 'Folder ID',
|
|
119
|
+
description: 'Folder ID coming from | New Folder -> id | (or any other source)',
|
|
120
|
+
required: true,
|
|
121
|
+
}),
|
|
122
|
+
include_team_drives: common.properties.include_team_drives,
|
|
123
|
+
|
|
124
|
+
includeTrashed: Property.Checkbox({
|
|
125
|
+
displayName: 'Include Trashed',
|
|
126
|
+
description: 'Include new files that have been trashed.',
|
|
127
|
+
required: false,
|
|
128
|
+
defaultValue: false
|
|
129
|
+
}),
|
|
130
|
+
|
|
131
|
+
depthLevel: Property.Number({
|
|
132
|
+
displayName: 'Depth Level',
|
|
133
|
+
description: 'How many levels deep to search for files. 1 = current folder only, 2 = current + next level, etc.',
|
|
134
|
+
required: false,
|
|
135
|
+
defaultValue: 1
|
|
136
|
+
}),
|
|
137
|
+
|
|
138
|
+
downloadFiles: Property.Checkbox({
|
|
139
|
+
displayName: 'Download Files',
|
|
140
|
+
description: 'Download all file contents in a list',
|
|
141
|
+
required: false,
|
|
142
|
+
defaultValue: false
|
|
143
|
+
}),
|
|
144
|
+
},
|
|
145
|
+
outputSchema: listFilesActionOutputSchema,
|
|
146
|
+
async run(context) {
|
|
147
|
+
const result: ListFilesResult = {
|
|
148
|
+
type: 'drive#fileList',
|
|
149
|
+
incompleteSearch: false,
|
|
150
|
+
files: [],
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const depthLevel = context.propsValue.depthLevel || 1;
|
|
154
|
+
|
|
155
|
+
// Get files recursively based on depth level
|
|
156
|
+
const filesWithLevel = await getFilesRecursively(
|
|
157
|
+
context.auth,
|
|
158
|
+
context.propsValue.folderId,
|
|
159
|
+
depthLevel,
|
|
160
|
+
context.propsValue.includeTrashed ?? false,
|
|
161
|
+
context.propsValue.include_team_drives ?? false
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
// Extract just the file objects for backward compatibility
|
|
165
|
+
result.files = filesWithLevel.map(f => f.file);
|
|
166
|
+
|
|
167
|
+
// If downloadFiles is enabled, download each file and add URLs to array
|
|
168
|
+
if (context.propsValue.downloadFiles) {
|
|
169
|
+
const downloadedFiles: string[] = [];
|
|
170
|
+
const extensionMap: Record<string, string> = {
|
|
171
|
+
'application/pdf': '.pdf',
|
|
172
|
+
'image/jpeg': '.jpg',
|
|
173
|
+
'image/png': '.png',
|
|
174
|
+
'image/tiff': '.tiff',
|
|
175
|
+
'text/plain': '.txt',
|
|
176
|
+
'text/csv': '.csv',
|
|
177
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',
|
|
178
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx'
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
for (const fileWithLevel of filesWithLevel) {
|
|
182
|
+
const file = fileWithLevel.file;
|
|
183
|
+
// Skip folders when downloading
|
|
184
|
+
if (file.mimeType === 'application/vnd.google-apps.folder') {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let safeName = file.name;
|
|
189
|
+
const correctExtension = extensionMap[file.mimeType];
|
|
190
|
+
if (correctExtension && !safeName.toLowerCase().endsWith(correctExtension)) {
|
|
191
|
+
// Check for the .jpeg edge case before appending .jpg
|
|
192
|
+
if (!(file.mimeType === 'image/jpeg' && safeName.toLowerCase().endsWith('.jpeg'))) {
|
|
193
|
+
safeName = safeName + correctExtension;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const fileUrl = await downloadFileFromDrive(
|
|
199
|
+
context.auth,
|
|
200
|
+
context.files,
|
|
201
|
+
file.id,
|
|
202
|
+
safeName
|
|
203
|
+
);
|
|
204
|
+
downloadedFiles.push(fileUrl);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.warn(`Failed to download file ${file.name}: ${error instanceof Error ? error.message : 'Download failed'}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
result.downloadedFiles = downloadedFiles;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
});
|