diff --git a/ts-langchain/src/lib/agent.ts b/ts-langchain/src/lib/agent.ts index 8bc6173..578b331 100644 --- a/ts-langchain/src/lib/agent.ts +++ b/ts-langchain/src/lib/agent.ts @@ -4,13 +4,12 @@ import { InMemoryStore, MemorySaver } from '@langchain/langgraph'; import { Calculator } from '@langchain/community/tools/calculator'; import { SerpAPI } from '@langchain/community/tools/serpapi'; import { GmailCreateDraft, GmailSearch } from '@langchain/community/tools/gmail'; -import { GoogleCalendarCreateTool, GoogleCalendarViewTool } from '@langchain/community/tools/google_calendar'; -import { getAccessToken, withCalendar, withGmailRead, withGmailWrite, withAsyncAuthorization } from './auth0-ai'; +import { withCalendar, withGmailRead, withGmailWrite, withAsyncAuthorization } from './auth0-ai'; import { getUserInfoTool } from './tools/user-info'; import { shopOnlineTool } from './tools/shop-online'; import { getContextDocumentsTool } from './tools/context-docs'; -import { getCalendarEventsTool } from './tools/google-calender'; +import { getCalendarEventsTool, createCalendarEventsTool } from './tools/google-calender'; const date = new Date().toISOString(); @@ -24,23 +23,21 @@ const llm = new ChatOpenAI({ // Provide the access token to the Gmail tools const gmailParams = { credentials: { - accessToken: getAccessToken, + accessToken: async () => { + const { getAccessToken } = await import('./auth0-ai'); + return getAccessToken(); + }, }, }; -const googleCalendarParams = { - credentials: { accessToken: getAccessToken, calendarId: 'primary' }, - model: llm, -}; const tools = [ new Calculator(), // Requires process.env.SERPAPI_API_KEY to be set: https://serpapi.com/ new SerpAPI(), withGmailRead(new GmailSearch(gmailParams)), withGmailWrite(new GmailCreateDraft(gmailParams)), - withCalendar(new GoogleCalendarCreateTool(googleCalendarParams)), - withCalendar(new GoogleCalendarViewTool(googleCalendarParams)), withCalendar(getCalendarEventsTool), + withCalendar(createCalendarEventsTool), getUserInfoTool, withAsyncAuthorization(shopOnlineTool), getContextDocumentsTool, diff --git a/ts-langchain/src/lib/tools/google-calender.ts b/ts-langchain/src/lib/tools/google-calender.ts index 4cfcbaa..225bbb1 100644 --- a/ts-langchain/src/lib/tools/google-calender.ts +++ b/ts-langchain/src/lib/tools/google-calender.ts @@ -72,3 +72,74 @@ export const getCalendarEventsTool = tool( }), }, ); + +export const createCalendarEventsTool = tool( + async ({ summary, description, startDateTime, endDateTime, location, attendees }) => { + // Get the access token from Auth0 AI + const accessToken = await getAccessToken(); + + // Google SDK + try { + const calendar = google.calendar('v3'); + const auth = new google.auth.OAuth2(); + + auth.setCredentials({ + access_token: accessToken, + }); + + // Create the event + const response = await calendar.events.insert({ + auth, + calendarId: 'primary', + requestBody: { + summary, + description, + location, + start: { + dateTime: startDateTime, + timeZone: 'UTC', + }, + end: { + dateTime: endDateTime, + timeZone: 'UTC', + }, + attendees: attendees?.map((email) => ({ email })), + }, + }); + + const event = response.data; + + return { + success: true, + eventId: event.id, + summary: event.summary, + description: event.description, + startTime: event.start?.dateTime || event.start?.date, + endTime: event.end?.dateTime || event.end?.date, + location: event.location, + htmlLink: event.htmlLink, + message: `Successfully created calendar event: ${event.summary}`, + }; + } catch (error) { + if (error instanceof GaxiosError) { + if (error.status === 401) { + throw new TokenVaultError(`Authorization required to access the Token Vault connection.`); + } + } + + throw error; + } + }, + { + name: 'create_calendar_event', + description: `Create a new event in the user's Google Calendar. Use this tool to schedule meetings, appointments, or reminders.`, + schema: z.object({ + summary: z.string().describe('The title/summary of the event'), + description: z.string().optional().describe('Detailed description of the event'), + startDateTime: z.string().describe('Start date and time in ISO 8601 format (e.g., 2025-11-12T14:00:00Z)'), + endDateTime: z.string().describe('End date and time in ISO 8601 format (e.g., 2025-11-12T15:00:00Z)'), + location: z.string().optional().describe('Location of the event'), + attendees: z.array(z.string()).optional().describe('Array of email addresses of attendees to invite'), + }), + }, +);