-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add GmailBaseTool * Add GmailGetMessage * Fix eslint formatting errors * fix: _call returns stringified output now * feat: create gmail draft message complete * fix: remove unused parameter * fix: removed unused import statement * fix: reformatted file and made method private * Add GmailGetThread * Fixes formatting issues * Fix _call error * Add GmailSearch * Fix build error on types * Create sent_message.ts * Update sent_message.ts run the prettier to format the document * Update sent_message.ts combine the sendMessage function into _call function * Move gmail object from children to parent GmailBaseTool * Fix formatting in gmail/base.ts * fix: switched to Buffer class for base64 encode * Make fields optional and use defaults properly in constructor Previously the default values weren't being used in the constructor, this commit fixes that. Also fields are now optional in each of the gmail tool constructors since they have defaults as backups anyways * Use Zod to parse input of GmailBaseTool constructor * Update zod schema to be entirely optional for GmailBaseToolParams * Create docs for Gmail Tool * Add comment for default parameters, fix formatting * Remove model from default parameters comment * Add relavent tools in gmail example * Add index.ts for all exports and rename send_message * Add unit tests for gmail tools * Add gmail type definitions to package.json * Update typedoc.json add gmail to typedoc.json * Update create-entrypoints.js add the entrypoints for gmail tool * add description for our function add example on our description * update .gitignore * fix the entrypoint * change order * change the zod * fix the format * Update base.ts fix lint problem * Update base.ts remove the unuse comment * add description for search * fix: gmail tools extend structured tool * Update descriptions.ts * fix: tree shaking issues with zod fixed * fix: prettier formatting * Add zod back to GmailBaseTool * Fix gmail example to work for StructuredTool * Add gmail API key setup instructions in docs * Fix formatting * Fix formatting * Replace .call with .invoke in gmail example * Update gmail.ts --------- Co-authored-by: Hamoon Zamiri <[email protected]> Co-authored-by: saeedahsan <[email protected]> Co-authored-by: SeannnX <[email protected]> Co-authored-by: Hamoon <[email protected]> Co-authored-by: Ahsan Saeed <[email protected]> Co-authored-by: Jacob Lee <[email protected]>
- Loading branch information
1 parent
d1b8a58
commit 03fa76a
Showing
17 changed files
with
866 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
hide_table_of_contents: true | ||
--- | ||
|
||
import CodeBlock from "@theme/CodeBlock"; | ||
|
||
# Gmail Tool | ||
|
||
The Gmail Tool allows your agent to create and view messages from a linked email account. | ||
|
||
## Setup | ||
|
||
You will need to get an API key from [Google here](https://developers.google.com/gmail/api/guides) | ||
and [enable the new Gmail API](https://console.cloud.google.com/apis/library/gmail.googleapis.com). | ||
Then, set the environment variables for `GMAIL_CLIENT_EMAIL`, and either `GMAIL_PRIVATE_KEY`, or `GMAIL_KEYFILE`. | ||
|
||
To use the Gmail Tool you need to install the following official peer dependency: | ||
|
||
```bash npm2yarn | ||
npm install googleapis | ||
``` | ||
|
||
## Usage | ||
|
||
import ToolExample from "@examples/tools/gmail.ts"; | ||
|
||
<CodeBlock language="typescript">{ToolExample}</CodeBlock> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { initializeAgentExecutorWithOptions } from "langchain/agents"; | ||
import { OpenAI } from "langchain/llms/openai"; | ||
import { StructuredTool } from "langchain/tools"; | ||
import { | ||
GmailCreateDraft, | ||
GmailGetMessage, | ||
GmailGetThread, | ||
GmailSearch, | ||
GmailSendMessage, | ||
} from "langchain/tools/gmail"; | ||
|
||
export async function run() { | ||
const model = new OpenAI({ | ||
temperature: 0, | ||
openAIApiKey: process.env.OPENAI_API_KEY, | ||
}); | ||
|
||
// These are the default parameters for the Gmail tools | ||
// const gmailParams = { | ||
// credentials: { | ||
// clientEmail: process.env.GMAIL_CLIENT_EMAIL, | ||
// privateKey: process.env.GMAIL_PRIVATE_KEY, | ||
// }, | ||
// scopes: ["https://mail.google.com/"], | ||
// }; | ||
|
||
// For custom parameters, uncomment the code above, replace the values with your own, and pass it to the tools below | ||
const tools: StructuredTool[] = [ | ||
new GmailCreateDraft(), | ||
new GmailGetMessage(), | ||
new GmailGetThread(), | ||
new GmailSearch(), | ||
new GmailSendMessage(), | ||
]; | ||
|
||
const gmailAgent = await initializeAgentExecutorWithOptions(tools, model, { | ||
agentType: "structured-chat-zero-shot-react-description", | ||
verbose: true, | ||
}); | ||
|
||
const createInput = `Create a gmail draft for me to edit of a letter from the perspective of a sentient parrot who is looking to collaborate on some research with her estranged friend, a cat. Under no circumstances may you send the message, however.`; | ||
|
||
const createResult = await gmailAgent.invoke({ input: createInput }); | ||
// Create Result { | ||
// output: 'I have created a draft email for you to edit. The draft Id is r5681294731961864018.' | ||
// } | ||
console.log("Create Result", createResult); | ||
|
||
const viewInput = `Could you search in my drafts for the latest email?`; | ||
|
||
const viewResult = await gmailAgent.invoke({ input: viewInput }); | ||
// View Result { | ||
// output: "The latest email in your drafts is from [email protected] with the subject 'Collaboration Opportunity'. The body of the email reads: 'Dear [Friend], I hope this letter finds you well. I am writing to you in the hopes of rekindling our friendship and to discuss the possibility of collaborating on some research together. I know that we have had our differences in the past, but I believe that we can put them aside and work together for the greater good. I look forward to hearing from you. Sincerely, [Parrot]'" | ||
// } | ||
console.log("View Result", viewResult); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { gmail_v1, google } from "googleapis"; | ||
import { z } from "zod"; | ||
import { StructuredTool } from "../base.js"; | ||
import { getEnvironmentVariable } from "../../util/env.js"; | ||
|
||
export interface GmailBaseToolParams { | ||
credentials?: { | ||
clientEmail?: string; | ||
privateKey?: string; | ||
keyfile?: string; | ||
}; | ||
scopes?: string[]; | ||
} | ||
|
||
export abstract class GmailBaseTool extends StructuredTool { | ||
private CredentialsSchema = z | ||
.object({ | ||
clientEmail: z | ||
.string() | ||
.min(1) | ||
.default(getEnvironmentVariable("GMAIL_CLIENT_EMAIL") ?? ""), | ||
privateKey: z | ||
.string() | ||
.default(getEnvironmentVariable("GMAIL_PRIVATE_KEY") ?? ""), | ||
keyfile: z | ||
.string() | ||
.default(getEnvironmentVariable("GMAIL_KEYFILE") ?? ""), | ||
}) | ||
.refine( | ||
(credentials) => | ||
credentials.privateKey !== "" || credentials.keyfile !== "", | ||
{ | ||
message: | ||
"Missing GMAIL_PRIVATE_KEY or GMAIL_KEYFILE to interact with Gmail", | ||
} | ||
); | ||
|
||
private GmailBaseToolParamsSchema = z | ||
.object({ | ||
credentials: this.CredentialsSchema.default({}), | ||
scopes: z.array(z.string()).default(["https://mail.google.com/"]), | ||
}) | ||
.default({}); | ||
|
||
name = "Gmail"; | ||
|
||
description = "A tool to send and view emails through Gmail"; | ||
|
||
protected gmail: gmail_v1.Gmail; | ||
|
||
constructor(fields?: Partial<GmailBaseToolParams>) { | ||
super(...arguments); | ||
|
||
const { credentials, scopes } = | ||
this.GmailBaseToolParamsSchema.parse(fields); | ||
|
||
this.gmail = this.getGmail( | ||
scopes, | ||
credentials.clientEmail, | ||
credentials.privateKey, | ||
credentials.keyfile | ||
); | ||
} | ||
|
||
private getGmail( | ||
scopes: string[], | ||
email: string, | ||
key?: string, | ||
keyfile?: string | ||
) { | ||
const auth = new google.auth.JWT(email, keyfile, key, scopes); | ||
|
||
return google.gmail({ version: "v1", auth }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { z } from "zod"; | ||
import { GmailBaseTool, GmailBaseToolParams } from "./base.js"; | ||
import { CREATE_DRAFT_DESCRIPTION } from "./descriptions.js"; | ||
|
||
export class GmailCreateDraft extends GmailBaseTool { | ||
name = "create_gmail_draft"; | ||
|
||
schema = z.object({ | ||
message: z.string(), | ||
to: z.array(z.string()), | ||
subject: z.string(), | ||
cc: z.array(z.string()).optional(), | ||
bcc: z.array(z.string()).optional(), | ||
}); | ||
|
||
description = CREATE_DRAFT_DESCRIPTION; | ||
|
||
constructor(fields?: GmailBaseToolParams) { | ||
super(fields); | ||
} | ||
|
||
private prepareDraftMessage( | ||
message: string, | ||
to: string[], | ||
subject: string, | ||
cc?: string[], | ||
bcc?: string[] | ||
) { | ||
const draftMessage = { | ||
message: { | ||
raw: "", | ||
}, | ||
}; | ||
|
||
const email = [ | ||
`To: ${to.join(", ")}`, | ||
`Subject: ${subject}`, | ||
cc ? `Cc: ${cc.join(", ")}` : "", | ||
bcc ? `Bcc: ${bcc.join(", ")}` : "", | ||
"", | ||
message, | ||
].join("\n"); | ||
|
||
draftMessage.message.raw = Buffer.from(email).toString("base64url"); | ||
|
||
return draftMessage; | ||
} | ||
|
||
async _call(arg: z.output<typeof this.schema>) { | ||
const { message, to, subject, cc, bcc } = arg; | ||
const create_message = this.prepareDraftMessage( | ||
message, | ||
to, | ||
subject, | ||
cc, | ||
bcc | ||
); | ||
|
||
const response = await this.gmail.users.drafts.create({ | ||
userId: "me", | ||
requestBody: create_message, | ||
}); | ||
|
||
return `Draft created. Draft Id: ${response.data.id}`; | ||
} | ||
} | ||
|
||
export type CreateDraftSchema = { | ||
message: string; | ||
to: string[]; | ||
subject: string; | ||
cc?: string[]; | ||
bcc?: string[]; | ||
}; |
Oops, something went wrong.