Skip to content

Commit e85022c

Browse files
kevin9327claudedavidmckayv
authored
Reach files in shared drives from the Google Drive connector (#589)
Drive leaves shared drive items out of any files.get or files.list that does not say it supports shared drives, and none of the connector's requests said so. A document the person could open in a shared drive was File not found by id and never appeared in a search or the recent list. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: David McKay <david@copilotkit.ai>
1 parent 0b40968 commit e85022c

3 files changed

Lines changed: 73 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
88

99
## Unreleased
1010

11+
### The Google Drive connector reaches files in shared drives
12+
13+
Drive leaves shared drive items out of any `files.get` or `files.list` request that does not say it
14+
supports shared drives, and none of the connector's requests said so. A document the person could
15+
open in a shared drive was "File not found" to `get_file_metadata` and `read_file_content`, and never
16+
appeared in `search_files` or `list_recent_files`. Those requests now say they support shared drives,
17+
and the listings ask for shared drive items. Listings keep Drive's default `user` scope rather than
18+
searching every shared drive.
1119
### Google Drive search and recent files leave out what is in the trash
1220

1321
Drive's `files.list` returns trashed files unless the query excludes them, and neither `search_files`

server/src/plugins/google-drive-rest.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ const PAGE_SIZE = 25;
4545
const FILE_FIELDS =
4646
"id,name,mimeType,modifiedTime,webViewLink,size,owners(emailAddress)";
4747

48+
/**
49+
* Shared drives as well as My Drive.
50+
*
51+
* Drive leaves shared drive items out of every `files.get` and `files.list` that does not say it
52+
* supports them. A company's documents often live in shared drives, so a file the person could open
53+
* came back from `get_file_metadata` and `read_file_content` as a 404 "File not found", and never
54+
* came back from a search at all. The listing also has to ask for those items. It keeps Drive's
55+
* default `user` corpus, which Google recommends over `allDrives`.
56+
*/
57+
const SHARED_DRIVES = { supportsAllDrives: "true" } as const;
58+
const SHARED_DRIVE_ITEMS = {
59+
...SHARED_DRIVES,
60+
includeItemsFromAllDrives: "true",
61+
} as const;
62+
4863
/**
4964
* Google's editor formats, and the plain-text export each one has.
5065
*
@@ -343,6 +358,7 @@ export async function callTool(
343358
}
344359

345360
const result = await request(connection, "/files", {
361+
...SHARED_DRIVE_ITEMS,
346362
pageSize: String(PAGE_SIZE),
347363
fields: `files(${FILE_FIELDS})`,
348364
// Drive's own ordering for "recent". Search leaves it to relevance.
@@ -364,7 +380,7 @@ export async function callTool(
364380
const result = await request(
365381
connection,
366382
`/files/${encodeURIComponent(fileId)}`,
367-
{ fields: FILE_FIELDS },
383+
{ ...SHARED_DRIVES, fields: FILE_FIELDS },
368384
);
369385
if (!result.ok) return failure(result.message);
370386

@@ -393,7 +409,7 @@ export async function callTool(
393409
const metadata = await request(
394410
connection,
395411
`/files/${encodeURIComponent(fileId)}`,
396-
{ fields: "id,name,mimeType" },
412+
{ ...SHARED_DRIVES, fields: "id,name,mimeType" },
397413
);
398414
if (!metadata.ok) return failure(metadata.message);
399415
const file = (await metadata.response.json()) as DriveFile;
@@ -426,6 +442,7 @@ export async function callTool(
426442
{ mimeType: exportAs },
427443
)
428444
: await request(connection, `/files/${encodeURIComponent(fileId)}`, {
445+
...SHARED_DRIVES,
429446
alt: "media",
430447
});
431448
if (!content.ok) return failure(content.message);

server/tests/google-drive-rest.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,49 @@ describe("reading a file asks Drive what it is first", () => {
399399
expect(result.text.split("\n\n[truncated")[0]).toBe(`${heading}${filler}`);
400400
});
401401
});
402+
403+
/*
404+
* Drive leaves shared drive items out of any `files.get` or `files.list` that does not say it supports
405+
* them. Without these parameters a document the person could open in a shared drive was a 404 by id
406+
* and missing from every search, and shared drives are where many companies keep their documents.
407+
*/
408+
describe("a file in a shared drive is reached like one in My Drive", () => {
409+
test("both listings ask Drive for shared drive items", async () => {
410+
const calls = stubFetch({ files: [] });
411+
await callTool(connection, "search_files", { query: "roadmap" });
412+
await callTool(connection, "list_recent_files", {});
413+
414+
expect(calls).toHaveLength(2);
415+
for (const call of calls) {
416+
const params = new URL(call.url).searchParams;
417+
expect(params.get("supportsAllDrives")).toBe("true");
418+
expect(params.get("includeItemsFromAllDrives")).toBe("true");
419+
}
420+
});
421+
422+
test("looking a file up says the caller supports shared drives", async () => {
423+
const calls = stubFetch({ id: "shared1", name: "Plan" });
424+
await callTool(connection, "get_file_metadata", { fileId: "shared1" });
425+
426+
expect(calls).toHaveLength(1);
427+
expect(new URL(calls[0].url).searchParams.get("supportsAllDrives")).toBe(
428+
"true",
429+
);
430+
});
431+
432+
test("reading a file says so on the lookup and on the download", async () => {
433+
const calls = stubFetch({
434+
id: "shared2",
435+
name: "notes.txt",
436+
mimeType: "text/plain",
437+
});
438+
await callTool(connection, "read_file_content", { fileId: "shared2" });
439+
440+
expect(calls).toHaveLength(2);
441+
for (const call of calls) {
442+
expect(new URL(call.url).searchParams.get("supportsAllDrives")).toBe(
443+
"true",
444+
);
445+
}
446+
});
447+
});

0 commit comments

Comments
 (0)