visionclaw 0.1.26 → 0.1.28

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/dist/agent/context.d.ts +2 -0
  3. package/dist/agent/context.d.ts.map +1 -1
  4. package/dist/agent/context.js +12 -1
  5. package/dist/agent/context.js.map +1 -1
  6. package/dist/agent/loop.d.ts.map +1 -1
  7. package/dist/agent/loop.js +40 -14
  8. package/dist/agent/loop.js.map +1 -1
  9. package/dist/agent/system-prompt.d.ts.map +1 -1
  10. package/dist/agent/system-prompt.js +4 -3
  11. package/dist/agent/system-prompt.js.map +1 -1
  12. package/dist/drive/google-drive.d.ts +82 -0
  13. package/dist/drive/google-drive.d.ts.map +1 -0
  14. package/dist/drive/google-drive.js +190 -0
  15. package/dist/drive/google-drive.js.map +1 -0
  16. package/dist/obs/ui.js +4 -4
  17. package/dist/onboarding/google-auth.js +1 -1
  18. package/dist/onboarding/google-auth.js.map +1 -1
  19. package/dist/tools/drive.d.ts +29 -0
  20. package/dist/tools/drive.d.ts.map +1 -0
  21. package/dist/tools/drive.js +363 -0
  22. package/dist/tools/drive.js.map +1 -0
  23. package/dist/tools/index.d.ts.map +1 -1
  24. package/dist/tools/index.js +4 -0
  25. package/dist/tools/index.js.map +1 -1
  26. package/dist/tools/sleep-interval.d.ts +5 -0
  27. package/dist/tools/sleep-interval.d.ts.map +1 -0
  28. package/dist/tools/sleep-interval.js +25 -0
  29. package/dist/tools/sleep-interval.js.map +1 -0
  30. package/dist/tools/upgrade.d.ts.map +1 -1
  31. package/dist/tools/upgrade.js +9 -32
  32. package/dist/tools/upgrade.js.map +1 -1
  33. package/dist/tools/version-check.d.ts +25 -0
  34. package/dist/tools/version-check.d.ts.map +1 -0
  35. package/dist/tools/version-check.js +164 -0
  36. package/dist/tools/version-check.js.map +1 -0
  37. package/package.json +7 -4
@@ -0,0 +1,190 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { google } from "googleapis";
4
+ import { loadGoogleTokens, saveGoogleTokens } from "../config/index.js";
5
+ /**
6
+ * Wrapper around Google Drive API v3.
7
+ * Uses OAuth tokens from onboarding to manage files in the agent's Google Drive.
8
+ */
9
+ export class GoogleDriveClient {
10
+ drive;
11
+ constructor(config) {
12
+ const tokens = loadGoogleTokens();
13
+ const oauth2Client = new google.auth.OAuth2(config.googleClientId, config.googleClientSecret);
14
+ oauth2Client.setCredentials({
15
+ access_token: tokens.access_token,
16
+ refresh_token: tokens.refresh_token,
17
+ token_type: tokens.token_type,
18
+ expiry_date: tokens.expiry_date,
19
+ });
20
+ // Auto-refresh tokens
21
+ oauth2Client.on("tokens", (newTokens) => {
22
+ const existing = loadGoogleTokens();
23
+ saveGoogleTokens({
24
+ ...existing,
25
+ access_token: newTokens.access_token ?? existing.access_token,
26
+ refresh_token: newTokens.refresh_token ?? existing.refresh_token,
27
+ expiry_date: newTokens.expiry_date ?? existing.expiry_date,
28
+ });
29
+ });
30
+ this.drive = google.drive({ version: "v3", auth: oauth2Client });
31
+ }
32
+ /**
33
+ * List files in Google Drive with optional query filtering.
34
+ */
35
+ async listFiles(options) {
36
+ let q = "trashed = false";
37
+ if (options.folderId) {
38
+ q += ` and '${options.folderId}' in parents`;
39
+ }
40
+ if (options.query) {
41
+ q += ` and (${options.query})`;
42
+ }
43
+ const res = await this.drive.files.list({
44
+ q,
45
+ pageSize: options.maxResults ?? 20,
46
+ orderBy: options.orderBy ?? "modifiedTime desc",
47
+ fields: "files(id, name, mimeType, size, modifiedTime, webViewLink, parents)",
48
+ });
49
+ return (res.data.files ?? []).map((f) => ({
50
+ id: f.id ?? "",
51
+ name: f.name ?? "",
52
+ mimeType: f.mimeType ?? "",
53
+ size: f.size ?? undefined,
54
+ modifiedTime: f.modifiedTime ?? undefined,
55
+ webViewLink: f.webViewLink ?? undefined,
56
+ parents: f.parents ?? undefined,
57
+ }));
58
+ }
59
+ /**
60
+ * Get metadata for a specific file.
61
+ */
62
+ async getFile(fileId) {
63
+ const res = await this.drive.files.get({
64
+ fileId,
65
+ fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
66
+ });
67
+ const f = res.data;
68
+ return {
69
+ id: f.id ?? "",
70
+ name: f.name ?? "",
71
+ mimeType: f.mimeType ?? "",
72
+ size: f.size ?? undefined,
73
+ modifiedTime: f.modifiedTime ?? undefined,
74
+ webViewLink: f.webViewLink ?? undefined,
75
+ parents: f.parents ?? undefined,
76
+ };
77
+ }
78
+ /**
79
+ * Upload a local file to Google Drive.
80
+ */
81
+ async uploadFile(options) {
82
+ const localPath = options.localPath;
83
+ const name = options.name ?? path.basename(localPath);
84
+ const fileStream = fs.createReadStream(localPath);
85
+ const res = await this.drive.files.create({
86
+ requestBody: {
87
+ name,
88
+ parents: options.folderId ? [options.folderId] : undefined,
89
+ },
90
+ media: {
91
+ mimeType: options.mimeType ?? "application/octet-stream",
92
+ body: fileStream,
93
+ },
94
+ fields: "id, name, mimeType, size, webViewLink",
95
+ });
96
+ const f = res.data;
97
+ return {
98
+ id: f.id ?? "",
99
+ name: f.name ?? "",
100
+ mimeType: f.mimeType ?? "",
101
+ webViewLink: f.webViewLink ?? undefined,
102
+ size: f.size ?? undefined,
103
+ };
104
+ }
105
+ /**
106
+ * Download a file from Google Drive to a local path.
107
+ */
108
+ async downloadFile(options) {
109
+ const dest = fs.createWriteStream(options.localPath);
110
+ const res = await this.drive.files.get({ fileId: options.fileId, alt: "media" }, { responseType: "stream" });
111
+ await new Promise((resolve, reject) => {
112
+ res.data
113
+ .on("end", resolve)
114
+ .on("error", reject)
115
+ .pipe(dest);
116
+ });
117
+ }
118
+ /**
119
+ * Create a folder in Google Drive.
120
+ */
121
+ async createFolder(options) {
122
+ const res = await this.drive.files.create({
123
+ requestBody: {
124
+ name: options.name,
125
+ mimeType: "application/vnd.google-apps.folder",
126
+ parents: options.parentId ? [options.parentId] : undefined,
127
+ },
128
+ fields: "id, name, mimeType, webViewLink, parents",
129
+ });
130
+ const f = res.data;
131
+ return {
132
+ id: f.id ?? "",
133
+ name: f.name ?? "",
134
+ mimeType: f.mimeType ?? "",
135
+ webViewLink: f.webViewLink ?? undefined,
136
+ parents: f.parents ?? undefined,
137
+ };
138
+ }
139
+ /**
140
+ * Share a file with a specific email address.
141
+ */
142
+ async shareFile(options) {
143
+ await this.drive.permissions.create({
144
+ fileId: options.fileId,
145
+ sendNotificationEmail: options.sendNotification ?? false,
146
+ requestBody: {
147
+ type: "user",
148
+ role: options.role,
149
+ emailAddress: options.email,
150
+ },
151
+ });
152
+ }
153
+ /**
154
+ * Move a file to trash (soft delete).
155
+ */
156
+ async deleteFile(fileId) {
157
+ await this.drive.files.update({
158
+ fileId,
159
+ requestBody: { trashed: true },
160
+ });
161
+ }
162
+ /**
163
+ * Move a file to a different folder.
164
+ */
165
+ async moveFile(options) {
166
+ // Get current parents first
167
+ const current = await this.drive.files.get({
168
+ fileId: options.fileId,
169
+ fields: "parents",
170
+ });
171
+ const previousParents = (current.data.parents ?? []).join(",");
172
+ const res = await this.drive.files.update({
173
+ fileId: options.fileId,
174
+ addParents: options.newFolderId,
175
+ removeParents: previousParents,
176
+ fields: "id, name, mimeType, size, modifiedTime, webViewLink, parents",
177
+ });
178
+ const f = res.data;
179
+ return {
180
+ id: f.id ?? "",
181
+ name: f.name ?? "",
182
+ mimeType: f.mimeType ?? "",
183
+ size: f.size ?? undefined,
184
+ modifiedTime: f.modifiedTime ?? undefined,
185
+ webViewLink: f.webViewLink ?? undefined,
186
+ parents: f.parents ?? undefined,
187
+ };
188
+ }
189
+ }
190
+ //# sourceMappingURL=google-drive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-drive.js","sourceRoot":"","sources":["../../src/drive/google-drive.ts"],"names":[],"mappings":"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"}
package/dist/obs/ui.js CHANGED
@@ -7,7 +7,7 @@ export function renderIndexHtml() {
7
7
  <meta charset="utf-8" />
8
8
  <meta name="viewport" content="width=device-width, initial-scale=1" />
9
9
  <title>VisionClaw</title>
10
- <link rel="icon" type="image/png" href="https://i.imghippo.com/files/JUc3171wWQ.png" />
10
+ <link rel="icon" type="image/png" href="https://i.imghippo.com/files/HDPC2282Umg.png" />
11
11
  <style>
12
12
  :root {
13
13
  --bg: #0b1020;
@@ -24,11 +24,11 @@ export function renderIndexHtml() {
24
24
  --sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
25
25
  }
26
26
  body { margin: 0; background: radial-gradient(1200px 800px at 15% 10%, rgba(122,162,255,0.18), transparent 60%), var(--bg); color: var(--text); font-family: var(--sans); }
27
- header { position: sticky; top: 0; backdrop-filter: blur(10px); background: rgba(11,16,32,0.6); border-bottom: 1px solid var(--border); }
27
+ header { position: sticky; top: 0; backdrop-filter: blur(10px); background: rgba(22,32,55,0.55); border-bottom: 1px solid var(--border); }
28
28
  .wrap { max-width: 1200px; margin: 0 auto; padding: 6px 16px; }
29
29
  .row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
30
30
  h1 { margin: 0; font-size: 14px; letter-spacing: 0.2px; font-weight: 650; display: flex; align-items: center; gap: 6px; }
31
- .logo { width: 44px; height: 44px; border-radius: 8px; }
31
+ .logo { width: 44px; height: 44px; border-radius: 8px; background: transparent; }
32
32
  .pill { border: 1px solid var(--border); background: rgba(255,255,255,0.06); color: var(--muted); padding: 6px 10px; border-radius: 999px; font-size: 12px; }
33
33
  .pill b { color: var(--text); }
34
34
  .btn { cursor: pointer; border: 1px solid var(--border); background: rgba(255,255,255,0.06); color: var(--text); padding: 8px 10px; border-radius: 10px; font-size: 12px; }
@@ -136,7 +136,7 @@ export function renderIndexHtml() {
136
136
  <div class="wrap">
137
137
  <div class="row header-bar">
138
138
  <div class="row header-info">
139
- <h1><img class="logo" src="https://i.imghippo.com/files/JUc3171wWQ.png" alt="VisionClaw" />VisionClaw</h1>
139
+ <h1><img class="logo" src="https://i.imghippo.com/files/HDPC2282Umg.png" alt="VisionClaw" />VisionClaw</h1>
140
140
  <span class="pill">SSE: <span id="sse">connecting…</span></span>
141
141
  <span class="pill">Buffer: <b id="count">0</b></span>
142
142
  <span class="pill" id="tunnel-pill" style="display:none"><span id="tunnel-url-display"></span></span>
@@ -8,7 +8,7 @@ const SCOPES = [
8
8
  "https://www.googleapis.com/auth/gmail.send",
9
9
  "https://www.googleapis.com/auth/calendar",
10
10
  "https://www.googleapis.com/auth/calendar.events",
11
- "https://www.googleapis.com/auth/drive.file",
11
+ "https://www.googleapis.com/auth/drive",
12
12
  ];
13
13
  /**
14
14
  * Run the Google OAuth2 flow:
@@ -1 +1 @@
1
- {"version":3,"file":"google-auth.js","sourceRoot":"","sources":["../../src/onboarding/google-auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"google-auth.js","sourceRoot":"","sources":["../../src/onboarding/google-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ export declare const manageDriveTool: import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition<{
3
+ action: z.ZodEnum<{
4
+ list_files: "list_files";
5
+ get_file: "get_file";
6
+ upload_file: "upload_file";
7
+ download_file: "download_file";
8
+ create_folder: "create_folder";
9
+ share_file: "share_file";
10
+ move_file: "move_file";
11
+ delete_file: "delete_file";
12
+ }>;
13
+ file_id: z.ZodOptional<z.ZodString>;
14
+ name: z.ZodOptional<z.ZodString>;
15
+ local_path: z.ZodOptional<z.ZodString>;
16
+ mime_type: z.ZodOptional<z.ZodString>;
17
+ folder_id: z.ZodOptional<z.ZodString>;
18
+ query: z.ZodOptional<z.ZodString>;
19
+ max_results: z.ZodOptional<z.ZodNumber>;
20
+ email: z.ZodOptional<z.ZodString>;
21
+ role: z.ZodOptional<z.ZodEnum<{
22
+ reader: "reader";
23
+ writer: "writer";
24
+ commenter: "commenter";
25
+ }>>;
26
+ send_notification: z.ZodOptional<z.ZodBoolean>;
27
+ new_folder_id: z.ZodOptional<z.ZodString>;
28
+ }>;
29
+ //# sourceMappingURL=drive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drive.d.ts","sourceRoot":"","sources":["../../src/tools/drive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;EAqZ3B,CAAC"}
@@ -0,0 +1,363 @@
1
+ import { z } from "zod";
2
+ import { tool } from "@anthropic-ai/claude-agent-sdk";
3
+ import { GoogleDriveClient } from "../drive/google-drive.js";
4
+ import { getAgentState } from "../agent/loop.js";
5
+ export const manageDriveTool = tool("manage_drive", `Manage Google Drive files and folders. Use this to list, upload, download, share, move, and delete files in Google Drive.
6
+
7
+ Available actions:
8
+ - list_files: List files in Drive with optional search query and folder filter
9
+ - get_file: Get metadata for a specific file by ID
10
+ - upload_file: Upload a local file to Google Drive
11
+ - download_file: Download a file from Google Drive to a local path
12
+ - create_folder: Create a new folder in Google Drive
13
+ - share_file: Share a file or folder with another user
14
+ - move_file: Move a file to a different folder
15
+ - delete_file: Move a file to trash`, {
16
+ action: z
17
+ .enum([
18
+ "list_files",
19
+ "get_file",
20
+ "upload_file",
21
+ "download_file",
22
+ "create_folder",
23
+ "share_file",
24
+ "move_file",
25
+ "delete_file",
26
+ ])
27
+ .describe("Drive action to perform"),
28
+ file_id: z
29
+ .string()
30
+ .optional()
31
+ .describe("Google Drive file or folder ID (for get_file, download_file, share_file, move_file, delete_file)"),
32
+ name: z
33
+ .string()
34
+ .optional()
35
+ .describe("File or folder name (for create_folder; optional override for upload_file)"),
36
+ local_path: z
37
+ .string()
38
+ .optional()
39
+ .describe("Absolute path to a local file (for upload_file as source, download_file as destination)"),
40
+ mime_type: z
41
+ .string()
42
+ .optional()
43
+ .describe("MIME type of the file being uploaded (optional, e.g. 'image/png', 'application/pdf')"),
44
+ folder_id: z
45
+ .string()
46
+ .optional()
47
+ .describe("Parent folder ID in Drive (for list_files to filter by folder, upload_file or create_folder to set parent)"),
48
+ query: z
49
+ .string()
50
+ .optional()
51
+ .describe("Google Drive search query (for list_files, e.g. \"name contains 'report'\" or \"mimeType = 'application/pdf'\")"),
52
+ max_results: z
53
+ .number()
54
+ .int()
55
+ .min(1)
56
+ .max(100)
57
+ .optional()
58
+ .describe("Maximum number of files to return for list_files (default: 20)"),
59
+ email: z
60
+ .string()
61
+ .optional()
62
+ .describe("Email address to share the file with (for share_file)"),
63
+ role: z
64
+ .enum(["reader", "writer", "commenter"])
65
+ .optional()
66
+ .describe("Permission role to grant when sharing (for share_file): reader, writer, or commenter"),
67
+ send_notification: z
68
+ .boolean()
69
+ .optional()
70
+ .describe("Whether to send an email notification when sharing (for share_file, default: false)"),
71
+ new_folder_id: z
72
+ .string()
73
+ .optional()
74
+ .describe("ID of the destination folder (for move_file)"),
75
+ }, async (args) => {
76
+ try {
77
+ const state = getAgentState();
78
+ const client = new GoogleDriveClient(state.config);
79
+ switch (args.action) {
80
+ case "list_files": {
81
+ const files = await client.listFiles({
82
+ query: args.query,
83
+ maxResults: args.max_results,
84
+ folderId: args.folder_id,
85
+ });
86
+ if (files.length === 0) {
87
+ return {
88
+ content: [
89
+ {
90
+ type: "text",
91
+ text: "No files found matching the criteria.",
92
+ },
93
+ ],
94
+ };
95
+ }
96
+ const lines = files.map((f) => {
97
+ const size = f.size ? ` (${Math.round(Number(f.size) / 1024)} KB)` : "";
98
+ const modified = f.modifiedTime
99
+ ? ` — modified ${new Date(f.modifiedTime).toLocaleDateString()}`
100
+ : "";
101
+ const link = f.webViewLink ? `\n Link: ${f.webViewLink}` : "";
102
+ return `- [${f.id}] ${f.name}${size}${modified}${link}`;
103
+ });
104
+ return {
105
+ content: [
106
+ {
107
+ type: "text",
108
+ text: `Found ${files.length} file(s):\n${lines.join("\n")}`,
109
+ },
110
+ ],
111
+ };
112
+ }
113
+ case "get_file": {
114
+ if (!args.file_id) {
115
+ return {
116
+ content: [
117
+ { type: "text", text: "Error: file_id is required for get_file" },
118
+ ],
119
+ isError: true,
120
+ };
121
+ }
122
+ const file = await client.getFile(args.file_id);
123
+ const size = file.size
124
+ ? `\nSize: ${Math.round(Number(file.size) / 1024)} KB`
125
+ : "";
126
+ const modified = file.modifiedTime
127
+ ? `\nModified: ${new Date(file.modifiedTime).toLocaleString()}`
128
+ : "";
129
+ const link = file.webViewLink ? `\nLink: ${file.webViewLink}` : "";
130
+ const parents = file.parents?.length
131
+ ? `\nParent folder(s): ${file.parents.join(", ")}`
132
+ : "";
133
+ return {
134
+ content: [
135
+ {
136
+ type: "text",
137
+ text: `File: ${file.name}\nID: ${file.id}\nType: ${file.mimeType}${size}${modified}${link}${parents}`,
138
+ },
139
+ ],
140
+ };
141
+ }
142
+ case "upload_file": {
143
+ if (!args.local_path) {
144
+ return {
145
+ content: [
146
+ {
147
+ type: "text",
148
+ text: "Error: local_path is required for upload_file",
149
+ },
150
+ ],
151
+ isError: true,
152
+ };
153
+ }
154
+ const result = await client.uploadFile({
155
+ localPath: args.local_path,
156
+ name: args.name,
157
+ mimeType: args.mime_type,
158
+ folderId: args.folder_id,
159
+ });
160
+ const link = result.webViewLink ? `\nView: ${result.webViewLink}` : "";
161
+ const size = result.size
162
+ ? ` (${Math.round(Number(result.size) / 1024)} KB)`
163
+ : "";
164
+ return {
165
+ content: [
166
+ {
167
+ type: "text",
168
+ text: `File uploaded: "${result.name}"${size}\nID: ${result.id}${link}`,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ case "download_file": {
174
+ if (!args.file_id) {
175
+ return {
176
+ content: [
177
+ {
178
+ type: "text",
179
+ text: "Error: file_id is required for download_file",
180
+ },
181
+ ],
182
+ isError: true,
183
+ };
184
+ }
185
+ if (!args.local_path) {
186
+ return {
187
+ content: [
188
+ {
189
+ type: "text",
190
+ text: "Error: local_path is required for download_file",
191
+ },
192
+ ],
193
+ isError: true,
194
+ };
195
+ }
196
+ await client.downloadFile({
197
+ fileId: args.file_id,
198
+ localPath: args.local_path,
199
+ });
200
+ return {
201
+ content: [
202
+ {
203
+ type: "text",
204
+ text: `File downloaded to: ${args.local_path}`,
205
+ },
206
+ ],
207
+ };
208
+ }
209
+ case "create_folder": {
210
+ if (!args.name) {
211
+ return {
212
+ content: [
213
+ {
214
+ type: "text",
215
+ text: "Error: name is required for create_folder",
216
+ },
217
+ ],
218
+ isError: true,
219
+ };
220
+ }
221
+ const folder = await client.createFolder({
222
+ name: args.name,
223
+ parentId: args.folder_id,
224
+ });
225
+ const link = folder.webViewLink ? `\nView: ${folder.webViewLink}` : "";
226
+ return {
227
+ content: [
228
+ {
229
+ type: "text",
230
+ text: `Folder created: "${folder.name}"\nID: ${folder.id}${link}`,
231
+ },
232
+ ],
233
+ };
234
+ }
235
+ case "share_file": {
236
+ if (!args.file_id) {
237
+ return {
238
+ content: [
239
+ {
240
+ type: "text",
241
+ text: "Error: file_id is required for share_file",
242
+ },
243
+ ],
244
+ isError: true,
245
+ };
246
+ }
247
+ if (!args.email) {
248
+ return {
249
+ content: [
250
+ {
251
+ type: "text",
252
+ text: "Error: email is required for share_file",
253
+ },
254
+ ],
255
+ isError: true,
256
+ };
257
+ }
258
+ if (!args.role) {
259
+ return {
260
+ content: [
261
+ {
262
+ type: "text",
263
+ text: "Error: role is required for share_file (reader, writer, or commenter)",
264
+ },
265
+ ],
266
+ isError: true,
267
+ };
268
+ }
269
+ await client.shareFile({
270
+ fileId: args.file_id,
271
+ email: args.email,
272
+ role: args.role,
273
+ sendNotification: args.send_notification,
274
+ });
275
+ return {
276
+ content: [
277
+ {
278
+ type: "text",
279
+ text: `File ${args.file_id} shared with ${args.email} as ${args.role}.`,
280
+ },
281
+ ],
282
+ };
283
+ }
284
+ case "move_file": {
285
+ if (!args.file_id) {
286
+ return {
287
+ content: [
288
+ {
289
+ type: "text",
290
+ text: "Error: file_id is required for move_file",
291
+ },
292
+ ],
293
+ isError: true,
294
+ };
295
+ }
296
+ if (!args.new_folder_id) {
297
+ return {
298
+ content: [
299
+ {
300
+ type: "text",
301
+ text: "Error: new_folder_id is required for move_file",
302
+ },
303
+ ],
304
+ isError: true,
305
+ };
306
+ }
307
+ const moved = await client.moveFile({
308
+ fileId: args.file_id,
309
+ newFolderId: args.new_folder_id,
310
+ });
311
+ return {
312
+ content: [
313
+ {
314
+ type: "text",
315
+ text: `File "${moved.name}" moved to folder ${args.new_folder_id}.`,
316
+ },
317
+ ],
318
+ };
319
+ }
320
+ case "delete_file": {
321
+ if (!args.file_id) {
322
+ return {
323
+ content: [
324
+ {
325
+ type: "text",
326
+ text: "Error: file_id is required for delete_file",
327
+ },
328
+ ],
329
+ isError: true,
330
+ };
331
+ }
332
+ await client.deleteFile(args.file_id);
333
+ return {
334
+ content: [
335
+ {
336
+ type: "text",
337
+ text: `File ${args.file_id} moved to trash.`,
338
+ },
339
+ ],
340
+ };
341
+ }
342
+ default: {
343
+ const action = args.action;
344
+ return {
345
+ content: [{ type: "text", text: `Unknown action: ${action}` }],
346
+ isError: true,
347
+ };
348
+ }
349
+ }
350
+ }
351
+ catch (err) {
352
+ return {
353
+ content: [
354
+ {
355
+ type: "text",
356
+ text: `Drive operation failed: ${err instanceof Error ? err.message : String(err)}`,
357
+ },
358
+ ],
359
+ isError: true,
360
+ };
361
+ }
362
+ });
363
+ //# sourceMappingURL=drive.js.map