114 lines
4.2 KiB
JavaScript
114 lines
4.2 KiB
JavaScript
import { z } from "zod";
|
|
import { GmailBaseTool } from "./base.js";
|
|
import { SEARCH_DESCRIPTION } from "./descriptions.js";
|
|
export class GmailSearch extends GmailBaseTool {
|
|
constructor(fields) {
|
|
super(fields);
|
|
Object.defineProperty(this, "name", {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: "search_gmail"
|
|
});
|
|
Object.defineProperty(this, "schema", {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: z.object({
|
|
query: z.string(),
|
|
maxResults: z.number().optional(),
|
|
resource: z.enum(["messages", "threads"]).optional(),
|
|
})
|
|
});
|
|
Object.defineProperty(this, "description", {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: SEARCH_DESCRIPTION
|
|
});
|
|
}
|
|
async _call(arg) {
|
|
const { query, maxResults = 10, resource = "messages" } = arg;
|
|
const response = await this.gmail.users.messages.list({
|
|
userId: "me",
|
|
q: query,
|
|
maxResults,
|
|
});
|
|
const { data } = response;
|
|
if (!data) {
|
|
throw new Error("No data returned from Gmail");
|
|
}
|
|
const { messages } = data;
|
|
if (!messages) {
|
|
throw new Error("No messages returned from Gmail");
|
|
}
|
|
if (resource === "messages") {
|
|
const parsedMessages = await this.parseMessages(messages);
|
|
return `Result for the query ${query}:\n${JSON.stringify(parsedMessages)}`;
|
|
}
|
|
else if (resource === "threads") {
|
|
const parsedThreads = await this.parseThreads(messages);
|
|
return `Result for the query ${query}:\n${JSON.stringify(parsedThreads)}`;
|
|
}
|
|
throw new Error(`Invalid resource: ${resource}`);
|
|
}
|
|
async parseMessages(messages) {
|
|
const parsedMessages = await Promise.all(messages.map(async (message) => {
|
|
const messageData = await this.gmail.users.messages.get({
|
|
userId: "me",
|
|
format: "raw",
|
|
id: message.id ?? "",
|
|
});
|
|
const headers = messageData.data.payload?.headers || [];
|
|
const subject = headers.find((header) => header.name === "Subject");
|
|
const sender = headers.find((header) => header.name === "From");
|
|
let body = "";
|
|
if (messageData.data.payload?.parts) {
|
|
body = messageData.data.payload.parts
|
|
.map((part) => part.body?.data ?? "")
|
|
.join("");
|
|
}
|
|
else if (messageData.data.payload?.body?.data) {
|
|
body = messageData.data.payload.body.data;
|
|
}
|
|
return {
|
|
id: message.id,
|
|
threadId: message.threadId,
|
|
snippet: message.snippet,
|
|
body,
|
|
subject,
|
|
sender,
|
|
};
|
|
}));
|
|
return parsedMessages;
|
|
}
|
|
async parseThreads(threads) {
|
|
const parsedThreads = await Promise.all(threads.map(async (thread) => {
|
|
const threadData = await this.gmail.users.threads.get({
|
|
userId: "me",
|
|
format: "raw",
|
|
id: thread.id ?? "",
|
|
});
|
|
const headers = threadData.data.messages?.[0]?.payload?.headers || [];
|
|
const subject = headers.find((header) => header.name === "Subject");
|
|
const sender = headers.find((header) => header.name === "From");
|
|
let body = "";
|
|
if (threadData.data.messages?.[0]?.payload?.parts) {
|
|
body = threadData.data.messages[0].payload.parts
|
|
.map((part) => part.body?.data ?? "")
|
|
.join("");
|
|
}
|
|
else if (threadData.data.messages?.[0]?.payload?.body?.data) {
|
|
body = threadData.data.messages[0].payload.body.data;
|
|
}
|
|
return {
|
|
id: thread.id,
|
|
snippet: thread.snippet,
|
|
body,
|
|
subject,
|
|
sender,
|
|
};
|
|
}));
|
|
return parsedThreads;
|
|
}
|
|
}
|