feat: add @agentic/google-drive package for Google Drive support

pull/706/head
Travis Fischer 2025-04-10 02:37:37 +07:00
rodzic 3540b7d811
commit 946f23a5c4
16 zmienionych plików z 347 dodań i 44 usunięć

Wyświetl plik

@ -71,6 +71,7 @@
"tools/hacker-news",
"tools/gravatar",
"tools/google-custom-search",
"tools/google-drive",
"tools/hunter",
"tools/jina",
"tools/leadmagic",

Wyświetl plik

@ -0,0 +1,47 @@
---
title: Google Drive
description: Simplified Google Drive API.
---
- package: `@agentic/google-drive`
- exports: `class GoogleDriveClient`, `namespace googleDrive`
- [source](https://github.com/transitive-bullshit/agentic/blob/main/packages/google-drive/src/google-drive-client.ts)
- [google drive docs](https://developers.google.com/workspace/drive/api)
## Install
<CodeGroup>
```bash npm
npm install @agentic/google-drive google-auth-library googleapis
```
```bash yarn
yarn add @agentic/google-drive google-auth-library googleapis
```
```bash pnpm
pnpm add @agentic/google-drive google-auth-library googleapis
```
</CodeGroup>
## Example Usage
```ts
import { GoogleDriveClient } from '@agentic/google-drive'
import { GoogleAuth } from 'google-auth-library'
import { google } from 'googleapis'
const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive' })
const drive = google.drive({ version: 'v3', auth })
const client = new GoogleDriveClient({ drive })
const result = await googleDrive.listFiles()
const file = result.files[0]!
const metadata = await googleDrive.getFile({ fileId: file.id })
const content = await googleDrive.exportFile({
fileId: file.id,
mimeType: 'application/pdf'
})
```

Wyświetl plik

@ -33,8 +33,7 @@
},
"dependencies": {
"@agentic/core": "workspace:*",
"ky": "catalog:",
"p-throttle": "catalog:"
"ky": "catalog:"
},
"peerDependencies": {
"zod": "catalog:"

Wyświetl plik

@ -0,0 +1,49 @@
{
"name": "@agentic/google-drive",
"version": "7.6.3",
"description": "Agentic SDK for Google Drive.",
"author": "Travis Fischer <travis@transitivebullsh.it>",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/transitive-bullshit/agentic.git",
"directory": "packages/google-drive"
},
"type": "module",
"source": "./src/index.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"clean": "del dist",
"test": "run-s test:*",
"test:lint": "eslint .",
"test:typecheck": "tsc --noEmit"
},
"dependencies": {
"@agentic/core": "workspace:*"
},
"devDependencies": {
"google-auth-library": "catalog:",
"googleapis": "catalog:"
},
"peerDependencies": {
"google-auth-library": "catalog:",
"googleapis": "catalog:",
"zod": "catalog:"
},
"publishConfig": {
"access": "public"
}
}

Wyświetl plik

@ -0,0 +1,24 @@
<p align="center">
<a href="https://agentic.so">
<img alt="Agentic" src="https://raw.githubusercontent.com/transitive-bullshit/agentic/main/docs/media/agentic-header.jpg" width="308">
</a>
</p>
<p align="center">
<em>AI agent stdlib that works with any LLM and TypeScript AI SDK.</em>
</p>
<p align="center">
<a href="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml"><img alt="Build Status" src="https://github.com/transitive-bullshit/agentic/actions/workflows/main.yml/badge.svg" /></a>
<a href="https://www.npmjs.com/package/@agentic/stdlib"><img alt="NPM" src="https://img.shields.io/npm/v/@agentic/stdlib.svg" /></a>
<a href="https://github.com/transitive-bullshit/agentic/blob/main/license"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue" /></a>
<a href="https://prettier.io"><img alt="Prettier Code Formatting" src="https://img.shields.io/badge/code_style-prettier-brightgreen.svg" /></a>
</p>
# Agentic
**See the [github repo](https://github.com/transitive-bullshit/agentic) or [docs](https://agentic.so) for more info.**
## License
MIT © [Travis Fischer](https://x.com/transitive_bs)

Wyświetl plik

@ -0,0 +1,156 @@
import type * as google from 'googleapis'
import {
aiFunction,
AIFunctionsProvider,
pick,
pruneNullOrUndefinedDeep
} from '@agentic/core'
import { z } from 'zod'
export namespace googleDrive {
export interface File {
id?: string
name: string
mimeType: string
webViewLink?: string
webContentLink?: string
size?: string
createdTime?: string
modifiedTime?: string
parents?: string[]
}
export const fileFields: (keyof File)[] = [
'id',
'name',
'mimeType',
'webViewLink',
'webContentLink',
'size',
'createdTime',
'modifiedTime',
'parents'
]
export interface ListFilesResponse {
files: File[]
nextPageToken?: string
}
export interface DownloadResponse {
content: string
metadata: File
}
export const ListFilesParamsSchema = z.object({
folderId: z.string().optional(),
query: z.string().optional(),
pageSize: z.number().optional(),
pageToken: z.string().optional()
})
}
/**
* Simplified Drive API client.
*
* @see https://developers.google.com/workspace/drive/api
*
* @example
* ```ts
* import { GoogleAuth } from 'google-auth-library'
* import { google } from 'googleapis'
*
* const auth = new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/drive' })
* const drive = google.drive({ version: 'v3', auth })
* const client = new GoogleDriveClient({ drive })
* ```
*/
export class GoogleDriveClient extends AIFunctionsProvider {
protected readonly drive: google.drive_v3.Drive
constructor({ drive }: { drive: google.drive_v3.Drive }) {
super()
this.drive = drive
}
/**
* Lists files and folders in a Google Drive folder.
*/
@aiFunction({
name: 'google_drive_list_files',
description: 'Lists files and folders in a Google Drive folder.',
inputSchema: googleDrive.ListFilesParamsSchema
})
async listFiles(
args: {
folderId?: string
query?: string
} & google.drive_v3.Params$Resource$Files$Get
): Promise<googleDrive.ListFilesResponse> {
const { folderId, query, ...opts } = args
// Build the query conditions
const conditions = ['trashed = false'] // Always exclude trashed files
if (folderId) {
conditions.push(`'${folderId}' in parents`)
}
if (query) {
conditions.push(`name contains '${query}'`)
}
// Combine all conditions with AND
const q = conditions.join(' and ')
const { data } = await this.drive.files.list({
...opts,
q
})
const files = (data.files ?? []).map((file) =>
pick(file, ...googleDrive.fileFields)
)
return pruneNullOrUndefinedDeep({
files,
nextPageToken: data.nextPageToken
}) as any
}
/**
* Gets a file's metadata from Google Drive.
*/
@aiFunction({
name: 'google_drive_get_file',
description: "Gets a file's metadata from Google Drive.",
inputSchema: z.object({ fileId: z.string() })
})
async getFile(
opts: google.drive_v3.Params$Resource$Files$Get
): Promise<googleDrive.File> {
const { data } = await this.drive.files.get(opts)
return pruneNullOrUndefinedDeep(
pick(data, ...googleDrive.fileFields)
) as any
}
/**
* Exports a file from Google Drive.
*/
@aiFunction({
name: 'google_drive_export_file',
description: 'Exports a file from Google Drive to a given mime-type.',
inputSchema: z.object({
fileId: z.string().describe('The ID of the file to export.'),
mimeType: z
.string()
.describe('The MIME type of the format requested for this export.')
})
})
async exportFile(
opts: google.drive_v3.Params$Resource$Files$Export
): Promise<unknown> {
return this.drive.files.export(opts)
}
}

Wyświetl plik

@ -0,0 +1 @@
export * from './google-drive-client'

Wyświetl plik

@ -0,0 +1,5 @@
{
"extends": "@fisch0920/config/tsconfig-node",
"include": ["src"],
"exclude": ["node_modules", "dist"]
}

Wyświetl plik

@ -33,8 +33,7 @@
},
"dependencies": {
"@agentic/core": "workspace:*",
"ky": "catalog:",
"p-throttle": "catalog:"
"ky": "catalog:"
},
"peerDependencies": {
"zod": "catalog:"

Wyświetl plik

@ -48,6 +48,7 @@
"@agentic/firecrawl": "workspace:*",
"@agentic/github": "workspace:*",
"@agentic/google-custom-search": "workspace:*",
"@agentic/google-drive": "workspace:*",
"@agentic/gravatar": "workspace:*",
"@agentic/hacker-news": "workspace:*",
"@agentic/hunter": "workspace:*",

Wyświetl plik

@ -13,6 +13,7 @@ export * from '@agentic/exa'
export * from '@agentic/firecrawl'
export * from '@agentic/github'
export * from '@agentic/google-custom-search'
export * from '@agentic/google-drive'
export * from '@agentic/gravatar'
export * from '@agentic/hacker-news'
export * from '@agentic/hunter'

Wyświetl plik

@ -33,8 +33,7 @@
},
"dependencies": {
"@agentic/core": "workspace:*",
"ky": "catalog:",
"p-throttle": "catalog:"
"ky": "catalog:"
},
"peerDependencies": {
"zod": "catalog:"

Wyświetl plik

@ -33,8 +33,7 @@
},
"dependencies": {
"@agentic/core": "workspace:*",
"ky": "catalog:",
"p-throttle": "catalog:"
"ky": "catalog:"
},
"peerDependencies": {
"zod": "catalog:"

Wyświetl plik

@ -96,6 +96,12 @@ catalogs:
genkitx-openai:
specifier: ^0.20.2
version: 0.20.2
google-auth-library:
specifier: ^9.15.1
version: 9.15.1
googleapis:
specifier: ^148.0.0
version: 148.0.0
json-schema-to-zod:
specifier: ^2.6.1
version: 2.6.1
@ -453,9 +459,6 @@ importers:
ky:
specifier: 'catalog:'
version: 1.8.0
p-throttle:
specifier: 'catalog:'
version: 6.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
@ -699,11 +702,27 @@ importers:
version: link:../core
'@googleapis/customsearch':
specifier: 'catalog:'
version: 3.2.0(encoding@0.1.13)
version: 3.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
packages/google-drive:
dependencies:
'@agentic/core':
specifier: workspace:*
version: link:../core
zod:
specifier: 'catalog:'
version: 3.24.2
devDependencies:
google-auth-library:
specifier: 'catalog:'
version: 9.15.1(encoding@0.1.13)
googleapis:
specifier: 'catalog:'
version: 148.0.0(encoding@0.1.13)
packages/gravatar:
dependencies:
'@agentic/core':
@ -999,9 +1018,6 @@ importers:
ky:
specifier: 'catalog:'
version: 1.8.0
p-throttle:
specifier: 'catalog:'
version: 6.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
@ -1134,6 +1150,9 @@ importers:
'@agentic/google-custom-search':
specifier: workspace:*
version: link:../google-custom-search
'@agentic/google-drive':
specifier: workspace:*
version: link:../google-drive
'@agentic/gravatar':
specifier: workspace:*
version: link:../gravatar
@ -1296,9 +1315,6 @@ importers:
ky:
specifier: 'catalog:'
version: 1.8.0
p-throttle:
specifier: 'catalog:'
version: 6.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
@ -1378,9 +1394,6 @@ importers:
ky:
specifier: 'catalog:'
version: 1.8.0
p-throttle:
specifier: 'catalog:'
version: 6.2.0
zod:
specifier: 'catalog:'
version: 3.24.2
@ -4578,6 +4591,10 @@ packages:
resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==}
engines: {node: '>=14.0.0'}
googleapis@148.0.0:
resolution: {integrity: sha512-8PDG5VItm6E1TdZWDqtRrUJSlBcNwz0/MwCa6AL81y/RxPGXJRUwKqGZfCoVX1ZBbfr3I4NkDxBmeTyOAZSWqw==}
engines: {node: '>=14.0.0'}
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
@ -5045,10 +5062,6 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
ky@1.7.5:
resolution: {integrity: sha512-HzhziW6sc5m0pwi5M196+7cEBtbt0lCYi67wNsiwMUmz833wloE0gbzJPWKs1gliFKQb34huItDQX97LyOdPdA==}
engines: {node: '>=18'}
ky@1.8.0:
resolution: {integrity: sha512-DoKGmG27nT8t/1F9gV8vNzggJ3mLAyD49J8tTMWHeZvS8qLc7GlyTieicYtFzvDznMe/q2u38peOjkWc5/pjvw==}
engines: {node: '>=18'}
@ -7440,7 +7453,7 @@ snapshots:
dedent: 1.5.3
hash-object: 5.0.1
jsonrepair: 3.12.0
ky: 1.7.5
ky: 1.8.0
openai-fetch: 3.4.2
openai-zod-to-json-schema: 1.0.3(zod@3.24.2)
p-map: 7.0.3
@ -7657,7 +7670,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@googleapis/customsearch@3.2.0(encoding@0.1.13)':
'@googleapis/customsearch@3.2.0':
dependencies:
googleapis-common: 7.2.0(encoding@0.1.13)
transitivePeerDependencies:
@ -11161,6 +11174,14 @@ snapshots:
- encoding
- supports-color
googleapis@148.0.0(encoding@0.1.13):
dependencies:
google-auth-library: 9.15.1(encoding@0.1.13)
googleapis-common: 7.2.0(encoding@0.1.13)
transitivePeerDependencies:
- encoding
- supports-color
gopd@1.2.0: {}
gpt-tokenizer@2.8.1:
@ -11565,8 +11586,6 @@ snapshots:
dependencies:
json-buffer: 3.0.1
ky@1.7.5: {}
ky@1.8.0: {}
langchain@0.3.21(@langchain/core@0.3.44(openai@4.93.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.2)))(axios@1.7.9)(encoding@0.1.13)(handlebars@4.7.8)(openai@4.93.0(encoding@0.1.13)(ws@8.18.0)(zod@3.24.2))(ws@8.18.0):

Wyświetl plik

@ -6,19 +6,20 @@ updateConfig:
- p-throttle
- eslint
catalog:
'@ai-sdk/openai': ^1.3.9
'@apidevtools/swagger-parser': ^10.1.1
'@dexaai/dexter': ^4.1.1
'@e2b/code-interpreter': ^1.1.0
'@fisch0920/config': ^1.0.2
'@langchain/core': ^0.3.44
'@langchain/openai': ^0.5.5
'@mastra/core': ^0.8.1
'@modelcontextprotocol/sdk': ^1.9.0
'@nangohq/node': 0.42.22 # pinned for now
'@types/jsrsasign': ^10.5.15
'@types/node': ^22.14.0
'@xsai/tool': ^0.2.0-beta.3
"@ai-sdk/openai": ^1.3.9
"@apidevtools/swagger-parser": ^10.1.1
"@dexaai/dexter": ^4.1.1
"@e2b/code-interpreter": ^1.1.0
"@fisch0920/config": ^1.0.2
"@googleapis/customsearch": ^3.2.0
"@langchain/core": ^0.3.44
"@langchain/openai": ^0.5.5
"@mastra/core": ^0.8.1
"@modelcontextprotocol/sdk": ^1.9.0
"@nangohq/node": 0.42.22
"@types/jsrsasign": ^10.5.15
"@types/node": ^22.14.0
"@xsai/tool": ^0.2.0-beta.3
ai: ^4.3.4
bumpp: ^10.1.0
camelcase: ^8.0.0
@ -35,7 +36,8 @@ catalog:
fast-xml-parser: ^5.2.0
genkit: ^1.6.0
genkitx-openai: ^0.20.2
'@googleapis/customsearch': ^3.2.0
google-auth-library: ^9.15.1
googleapis: ^148.0.0
json-schema-to-zod: ^2.6.1
jsonrepair: ^3.12.0
jsrsasign: ^10.9.0
@ -52,7 +54,7 @@ catalog:
openai-zod-to-json-schema: ^1.0.3
openapi-types: ^12.1.3
p-map: ^7.0.3
p-throttle: 6.2.0 # pinned for now
p-throttle: 6.2.0
prettier: ^3.5.3
restore-cursor: ^5.1.0
simple-git-hooks: ^2.12.1

Wyświetl plik

@ -194,6 +194,7 @@ Full docs are available at [agentic.so](https://agentic.so).
| [Exa](https://docs.exa.ai) | `@agentic/exa` | [docs](https://agentic.so/tools/exa) | Web search tailored for LLMs. |
| [Firecrawl](https://www.firecrawl.dev) | `@agentic/firecrawl` | [docs](https://agentic.so/tools/firecrawl) | Website scraping and structured data extraction. |
| [Google Custom Search](https://developers.google.com/custom-search/v1/overview) | `@agentic/google-custom-search` | [docs](https://agentic.so/tools/google-custom-search) | Official Google Custom Search API. |
| [Google Drive](https://developers.google.com/workspace/drive/api) | `@agentic/google-drive` | [docs](https://agentic.so/tools/google-drive) | Simplified Google Drive API. |
| [Gravatar](https://docs.gravatar.com/api/profiles/rest-api/) | `@agentic/gravatar` | [docs](https://agentic.so/tools/gravatar) | Gravatar profile API. |
| [HackerNews](https://github.com/HackerNews/API) | `@agentic/hacker-news` | [docs](https://agentic.so/tools/hacker-news) | Official HackerNews API. |
| [Hunter](https://hunter.io) | `@agentic/hunter` | [docs](https://agentic.so/tools/hunter) | Email finder, verifier, and enrichment. |