Google calendar skill (#5442)

* Google Calendar Agent

* forgot files

* Translations (#5443)
This commit is contained in:
Timothy Carambat 2026-04-14 16:39:36 -07:00 committed by GitHub
parent 177049bd4a
commit 1cea4df8e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
51 changed files with 4618 additions and 97 deletions

View File

@ -626,6 +626,87 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "موصل تقويم جوجل",
description:
"اسمح لمسؤولك بالتفاعل مع تقويم جوجل - عرض التقوائم، والحصول على الأحداث، وإنشاء وتحديث الأحداث، وإدارة الردود. <a>اقرأ الوثائق</a>.",
multiUserWarning:
"لا تتوفر تكامل تقويم Google في الوضع متعدد المستخدمين لأسباب تتعلق بالسلامة. يرجى تعطيل الوضع متعدد المستخدمين لاستخدام هذه الميزة.",
configuration: "تكوين تقويم جوجل",
deploymentId: "معرّف التوزيع",
deploymentIdHelp:
"معرّف النشر من تطبيق الويب الخاص بك في Google Apps Script",
apiKey: "مفتاح واجهة برمجة التطبيقات",
apiKeyHelp:
"مفتاح واجهة برمجة التطبيقات (API) الذي قمت بتكوينه في تطبيق Google Apps Script الخاص بك.",
configurationRequired:
"يرجى تكوين معرف النشر والمفتاح الخاص للبرنامج، وذلك لتفعيل ميزات تقويم جوجل.",
configured: "تم التكوين",
searchSkills: "مهارات البحث...",
noSkillsFound: "لا توجد مهارات تطابق بحثك.",
categories: {
calendars: {
title: "تقويمات",
description: "عرض وإدارة تقويمات Google الخاصة بك.",
},
readEvents: {
title: "قراءة الأحداث",
description: "عرض والبحث عن الأحداث في التقويم",
},
writeEvents: {
title: "إنشاء وتحديث الفعاليات",
description: "إنشاء فعاليات جديدة وتعديل الفعاليات الموجودة.",
},
rsvp: {
title: "إدارة الردود",
description: "حدد حالة استجابتك للأحداث.",
},
},
skills: {
listCalendars: {
title: "قوائم التقويمات",
description: "اذكر جميع التقاويم التي تملكها أو أنت مشترك فيها.",
},
getCalendar: {
title: "احصل على تفاصيل التقويم",
description: "احصل على معلومات تفصيلية حول تقويم معين.",
},
getEvent: {
title: "احصل على تفاصيل الحدث",
description: "احصل على معلومات تفصيلية حول حدث معين.",
},
getEventsForDay: {
title: "احصل على قائمة بالأحداث لهذا اليوم",
description: "احصل على جميع الفعاليات المجدولة ليوم محدد.",
},
getEvents: {
title: "الحصول على الأحداث (نطاق زمني)",
description: "احصل على الأحداث ضمن نطاق تاريخي محدد",
},
getUpcomingEvents: {
title: "اطلع على الفعاليات القادمة",
description:
"احصل على فعاليات اليوم، أو هذا الأسبوع، أو هذا الشهر باستخدام كلمات مفتاحية بسيطة.",
},
quickAdd: {
title: "إضافة حدث بسرعة",
description:
'إنشاء حدث من خلال اللغة الطبيعية (على سبيل المثال، "اجتماع غدًا الساعة 3 مساءً")',
},
createEvent: {
title: "إنشاء حدث",
description: "إنشاء حدث جديد مع التحكم الكامل في جميع الخصائص.",
},
updateEvent: {
title: "تحديث الحدث",
description: "تحديث حدث في التقويم الحالي",
},
setMyStatus: {
title: "تحديد حالة الرد",
description: "قبول أو رفض أو قبول بشكل مؤقت حدثًا",
},
},
},
},
mcp: {
title: "خوادم نظام MCP",

View File

@ -653,6 +653,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Connector per a Google Calendar",
description:
"Permite que el teu agent interactui amb Google Calendar: visualitza calendaris, obté esdeveniments, crea i actualitza esdeveniments, i gestiona les confirmacions de participació. <a>Consulteu la documentació</a>.",
multiUserWarning:
"La integració amb Google Calendar no està disponible en el mode multiusuari per raons de seguretat. Per utilitzar aquesta funció, feu que el mode multiusuari estigui desactivat.",
configuration: "Configuració de Google Calendar",
deploymentId: "Identificador de desplegament",
deploymentIdHelp:
"L'ID de desplegament de la vostra aplicació web de Google Apps Script",
apiKey: "Clau API",
apiKeyHelp:
"La clau API que has configurat en la implementació del teu Google Apps Script",
configurationRequired:
"Si us plau, configureu l'ID de l'implementació i la clau API per activar les funcionalitats de Google Calendar.",
configured: "Configurat",
searchSkills: "Habilitats de cerca...",
noSkillsFound:
"No s'han trobat perfils que coincideixin amb la vostra cerca.",
categories: {
calendars: {
title: "Calendari",
description: "Visualitza i gestiona els teus calendaris de Google.",
},
readEvents: {
title: "Consulta els esdeveniments",
description: "Visualitza i cerca esdeveniments del calendari",
},
writeEvents: {
title: "Crear i actualitzar esdeveniments",
description: "Crea esdeveniments nous i modifica els existents.",
},
rsvp: {
title: "Gestió de confirmacions de participació",
description: "Gestiona l'estat de resposta per als esdeveniments.",
},
},
skills: {
listCalendars: {
title: "Calendari de dates",
description:
"Enumera tots els calendaris que poseu al dia o als quals esteu subscrit.",
},
getCalendar: {
title: "Obteniu detalls del calendari",
description:
"Obteniu informació detallada sobre un calendari específic.",
},
getEvent: {
title: "Obtenir informació sobre l'esdeveniment",
description:
"Obteniu informació detallada sobre un esdeveniment específic.",
},
getEventsForDay: {
title: "Troba esdeveniments per a un dia concret",
description:
"Obteniu tots els esdeveniments programats per a un dia concret.",
},
getEvents: {
title: "Obtenir esdeveniments (interval de dates)",
description:
"Obtenir esdeveniments dins d'un interval de dates personalitzat",
},
getUpcomingEvents: {
title: "Consulta els esdeveniments pròxims",
description:
"Troba esdeveniments per avui, aquesta setmana o aquest mes utilitzant paraules clau senzilles.",
},
quickAdd: {
title: "Afegir esdeveniment de forma ràpida",
description:
'Crea un esdeveniment a partir d\'un text natural (per exemple, "Reunió demà a les 15:00")',
},
createEvent: {
title: "Crear esdeveniment",
description:
"Crea un esdeveniment nou amb control total sobre totes les propietats.",
},
updateEvent: {
title: "Actualització d'esdeveniments",
description: "Actualitza un esdeveniment existent en el calendari",
},
setMyStatus: {
title: "Estat de confirmació de participació",
description:
"Acceptar, rebutjar o acceptar de manera provisional un esdeveniment.",
},
},
},
},
mcp: {
title: "Servidors MCP",

View File

@ -644,6 +644,90 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Připojení k kalendáři Google",
description:
"Umožněte svému agentovi interakci s Google Kalendářem prohlížení kalendářů, získávání událostí, vytváření a aktualizaci událostí a správu potvrzení účasti. <a>Přečtěte si dokumentaci</a>.",
multiUserWarning:
"Integrace s Google Kalendářem není dostupná v režimu pro více uživatelů z důvodu bezpečnosti. Pro použití této funkce, prosím, deaktivujte režim pro více uživatelů.",
configuration: "Konfigurace kalendáře Google",
deploymentId: "ID nasazení",
deploymentIdHelp:
"ID nasazení z vaší webové aplikace Google Apps Script",
apiKey: "Klíč API",
apiKeyHelp:
"Klíč API, který jste nakonfigurovali ve vaší instalaci Google Apps Script",
configurationRequired:
"Prosím, nakonfigurujte ID nasazení a API klíč, abyste mohli využívat funkce Google Kalendáře.",
configured: "Konfigurováno",
searchSkills: "Dovednosti pro vyhledávání...",
noSkillsFound: "Žádné výsledky neodpovídají vašemu vyhledávání.",
categories: {
calendars: {
title: "Kalendáře",
description: "Zobrazte a spravujte své kalendáře Google.",
},
readEvents: {
title: "Seznam událostí",
description: "Zobrazte a vyhledejte události v kalendáři",
},
writeEvents: {
title: "Vytvořit a aktualizovat události",
description: "Vytvořte nové akce a upravte stávající.",
},
rsvp: {
title: "Správa odpovědí na pozvánky",
description: "Spravujte stav své odpovědi pro události",
},
},
skills: {
listCalendars: {
title: "Kalendáře v seznamu",
description:
"Vypište všechny kalendáře, které vlastníte nebo máte aktivní předplatné.",
},
getCalendar: {
title: "Získejte podrobné informace o kalendáři",
description: "Získejte podrobné informace o konkrétním kalendáři.",
},
getEvent: {
title: "Získejte informace o události",
description: "Získejte podrobné informace o konkrétním události",
},
getEventsForDay: {
title: "Získejte události pro daný den",
description:
"Získejte všechny události naplánované pro konkrétní den.",
},
getEvents: {
title: "Zobrazit události (rozsah dat)",
description: "Získejte události v definovaném časovém rozsahu",
},
getUpcomingEvents: {
title: "Zobrazit nadcházející akce",
description:
"Najděte události pro dnešek, tento týden nebo tento měsíc pomocí jednoduchých klíčových slov.",
},
quickAdd: {
title: "Rychlé přidání události",
description:
"Vytvořte událost z přirozeného jazyka (např. „Schůzka zítra ve 15:00“)",
},
createEvent: {
title: "Vytvořit událost",
description:
"Vytvořte nový event s plnou kontrolou nad všemi jeho vlastnostmi.",
},
updateEvent: {
title: "Aktualizace události",
description: "Aktualizovat existující událost v kalendáři",
},
setMyStatus: {
title: "Nastavit stav potvrzení účasti",
description: "Přijmout, zamítnout nebo přijmout událost s rezervou",
},
},
},
},
mcp: {
title: "Servery společnosti MCP",

View File

@ -627,6 +627,89 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Kalender-tilslutning",
description:
"Giv din agent mulighed for at interagere med Google Kalender se kalendere, få adgang til begivenheder, oprette og opdatere begivenheder, og administrere tilmeldinger. <a>Læs dokumentationen</a>.",
multiUserWarning:
"Integration med Google Kalender er ikke tilgængelig i multi-bruger-tilstand af sikkerhedsmæssige årsager. For at bruge denne funktion, bedes du deaktivere multi-bruger-tilstanden.",
configuration: "Konfiguration af Google Kalender",
deploymentId: "Identifikations-ID",
deploymentIdHelp: "Deployment-ID fra din Google Apps Script webapp",
apiKey: "API-nøgle",
apiKeyHelp:
"API-nøglen, du har konfigureret i din Google Apps Script-implementering.",
configurationRequired:
"Vær venligst oprettet Deployment ID og API-nøgle for at aktivere Google Calendar-funktionaliteten.",
configured: "Konfigureret",
searchSkills: "Søgeteknikker...",
noSkillsFound: "Ingen resultater matcher din søgning.",
categories: {
calendars: {
title: "Kalendere",
description: "Se og administrer dine Google Kalendere",
},
readEvents: {
title: "Læs begivenheder",
description: "Se og søg efter begivenheder i kalenderen",
},
writeEvents: {
title: "Opret og opdater begivenheder",
description: "Opret nye begivenheder og rediger eksisterende.",
},
rsvp: {
title: "Håndtering af bekræftelser",
description: "Administrer status for dine svar på begivenheder",
},
},
skills: {
listCalendars: {
title: "Kalenderlister",
description: "Vis alle kalendere, du ejer eller er abonnent på.",
},
getCalendar: {
title: "Få detaljer om kalenderen",
description: "Få detaljerede oplysninger om en bestemt kalender",
},
getEvent: {
title: "Find arrangement",
description: "Få detaljerede oplysninger om et bestemt arrangement",
},
getEventsForDay: {
title: "Find begivenheder for den pågældende dag",
description:
"Find alle begivenheder, der er planlagt til en bestemt dato.",
},
getEvents: {
title: "Find begivenheder (datointerval)",
description: "Find begivenheder inden for et angivet tidsinterval",
},
getUpcomingEvents: {
title: "Se kommende arrangementer",
description:
"Find begivenheder for i dag, denne uge eller denne måned ved hjælp af enkle søgeord.",
},
quickAdd: {
title: "Tilføj begivenhed hurtigt",
description:
'Opret et arrangement ud fra naturligt sprog (f.eks. "Møde i morgen kl. 15:00")',
},
createEvent: {
title: "Opret begivenhed",
description:
"Opret et nyt arrangement med fuld kontrol over alle indstillinger.",
},
updateEvent: {
title: "Opdatering af begivenhed",
description: "Opdater en eksisterende kalenderbegivenhed",
},
setMyStatus: {
title: "Angiv status for bekræftet deltagelse",
description:
"Accepter, afvise eller midlertidigt acceptere et arrangement",
},
},
},
},
mcp: {
title: "MCP-servere",

View File

@ -646,6 +646,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Kalender-Verbindung",
description:
"Ermöglichen Sie Ihrem Agenten, mit Google Kalender zu interagieren Kalender anzeigen, Ereignisse einsehen, erstellen und aktualisieren, sowie Rückmeldungen verwalten. <a> Lesen Sie die Dokumentation </a>.",
multiUserWarning:
"Die Integration mit Google Kalender ist aus Sicherheitsgründen nicht im Mehrbenutzermodus verfügbar. Bitte deaktivieren Sie den Mehrbenutzermodus, um diese Funktion nutzen zu können.",
configuration: "Konfiguration des Google Kalenders",
deploymentId: "Deployment-ID",
deploymentIdHelp:
"Die Bereitstellungs-ID Ihrer Google Apps Script Web-Anwendung",
apiKey: "API-Schlüssel",
apiKeyHelp:
"Der API-Schlüssel, den Sie in Ihrer Google Apps Script-Bereitstellung konfiguriert haben",
configurationRequired:
"Bitte konfigurieren Sie die Deployment-ID und den API-Schlüssel, um die Google Calendar-Funktionen zu aktivieren.",
configured: "Konfiguriert",
searchSkills: "Suchfähigkeiten...",
noSkillsFound: "Keine Übereinstimmungen zu Ihrer Suche.",
categories: {
calendars: {
title: "Kalender",
description: "Überprüfen und verwalten Sie Ihre Google-Kalender.",
},
readEvents: {
title: "Veranstaltungen lesen",
description: "Kalenderereignisse anzeigen und suchen",
},
writeEvents: {
title: "Erstellen und aktualisieren von Veranstaltungen",
description:
"Erstellen Sie neue Veranstaltungen und ändern Sie bestehende",
},
rsvp: {
title: "Verwaltung von Rückmeldungen",
description:
"Verwalten Sie den Status Ihrer Teilnahme an Veranstaltungen",
},
},
skills: {
listCalendars: {
title: "Kalenderlisten",
description:
"Listen Sie alle Kalender auf, die Sie besitzen oder für die Sie ein Abonnement haben.",
},
getCalendar: {
title: "Details zum Kalender anzeigen",
description:
"Erhalten Sie detaillierte Informationen über einen bestimmten Kalender.",
},
getEvent: {
title: "Veranstaltung finden",
description:
"Erhalten Sie detaillierte Informationen über ein bestimmtes Ereignis.",
},
getEventsForDay: {
title: "Veranstaltungen für den Tag",
description:
"Alle Veranstaltungen, die für einen bestimmten Tag geplant sind, anzeigen.",
},
getEvents: {
title: "Veranstaltungen (Zeitraum) anzeigen",
description:
"Ereignisse innerhalb eines benutzerdefinierten Datumsbereichs abrufen",
},
getUpcomingEvents: {
title: "Anstehende Veranstaltungen anzeigen",
description:
"Finden Sie Veranstaltungen für heute, diese Woche oder diesen Monat, indem Sie einfache Suchbegriffe verwenden.",
},
quickAdd: {
title: "Schnellere Veranstaltung hinzufügen",
description:
"Erstellen Sie eine Veranstaltung aus natürlicher Sprache (z. B. „Treffen morgen um 15:00 Uhr“)",
},
createEvent: {
title: "Ereignis erstellen",
description:
"Erstellen Sie ein neues Ereignis mit vollständiger Kontrolle über alle Eigenschaften.",
},
updateEvent: {
title: "Aktualisierungsereignis",
description: "Ein bestehendes Kalendereintrag aktualisieren",
},
setMyStatus: {
title: "Status der Rückmeldung",
description: "Teilen, ablehnen oder vorläufig zustimmen",
},
},
},
},
"performance-warning":
"Die Leistung von LLMs, die keine explizite Unterstützung für das Aufrufen von Tools bieten, hängt stark von den Fähigkeiten und der Genauigkeit des Modells ab. Einige Fähigkeiten können eingeschränkt oder nicht funktionsfähig sein.",

View File

@ -421,7 +421,7 @@ const TRANSLATIONS = {
},
},
gmail: {
title: "GMail Connector",
title: "GMail",
description:
"Enable your agent to interact with Gmail - search emails, read threads, compose drafts, send emails, and manage your inbox. <a>Read the documentation</a>.",
multiUserWarning:
@ -536,8 +536,90 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Calendar",
description:
"Enable your agent to interact with Google Calendar - view calendars, get events, create and update events, and manage RSVPs. <a>Read the documentation</a>.",
multiUserWarning:
"Google Calendar integration is not available in multi-user mode for security reasons. Please disable multi-user mode to use this feature.",
configuration: "Google Calendar Configuration",
deploymentId: "Deployment ID",
deploymentIdHelp:
"The deployment ID from your Google Apps Script web app",
apiKey: "API Key",
apiKeyHelp:
"The API key you configured in your Google Apps Script deployment",
configurationRequired:
"Please configure the Deployment ID and API Key to enable Google Calendar skills.",
configured: "Configured",
searchSkills: "Search skills...",
noSkillsFound: "No skills match your search.",
categories: {
calendars: {
title: "Calendars",
description: "View and manage your Google Calendars",
},
readEvents: {
title: "Read Events",
description: "View and search calendar events",
},
writeEvents: {
title: "Create & Update Events",
description: "Create new events and modify existing ones",
},
rsvp: {
title: "RSVP Management",
description: "Manage your response status for events",
},
},
skills: {
listCalendars: {
title: "List Calendars",
description: "List all calendars you own or are subscribed to",
},
getCalendar: {
title: "Get Calendar Details",
description: "Get detailed information about a specific calendar",
},
getEvent: {
title: "Get Event",
description: "Get detailed information about a specific event",
},
getEventsForDay: {
title: "Get Events for Day",
description: "Get all events scheduled for a specific day",
},
getEvents: {
title: "Get Events (Date Range)",
description: "Get events within a custom date range",
},
getUpcomingEvents: {
title: "Get Upcoming Events",
description:
"Get events for today, this week, or this month using simple keywords",
},
quickAdd: {
title: "Quick Add Event",
description:
"Create an event from natural language (e.g., 'Meeting tomorrow at 3pm')",
},
createEvent: {
title: "Create Event",
description:
"Create a new event with full control over all properties",
},
updateEvent: {
title: "Update Event",
description: "Update an existing calendar event",
},
setMyStatus: {
title: "Set RSVP Status",
description: "Accept, decline, or tentatively accept an event",
},
},
},
outlook: {
title: "Outlook Connector",
title: "Outlook",
description:
"Enable your agent to interact with Microsoft Outlook - search emails, read threads, compose drafts, send emails, and manage your inbox via Microsoft Graph API. <a>Read the documentation</a>.",
multiUserWarning:

View File

@ -655,6 +655,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Conector para Google Calendar",
description:
"Permita que su agente interactúe con Google Calendar: visualice calendarios, obtenga información sobre eventos, cree y actualice eventos, y gestione las confirmaciones de asistencia. <a>Consulte la documentación</a>.",
multiUserWarning:
"La integración con Google Calendar no está disponible en el modo de varios usuarios por razones de seguridad. Para utilizar esta función, por favor, desactive el modo de varios usuarios.",
configuration: "Configuración de Google Calendar",
deploymentId: "ID de implementación",
deploymentIdHelp:
"El ID de implementación de su aplicación web de Google Apps Script",
apiKey: "Clave de API",
apiKeyHelp:
"La clave API que configuraste en tu implementación de Google Apps Script.",
configurationRequired:
"Por favor, configure el ID de implementación y la clave de API para habilitar las funciones de Google Calendar.",
configured: "Configurado",
searchSkills: "Habilidades de búsqueda...",
noSkillsFound:
"No se encontraron resultados que coincidan con tu búsqueda.",
categories: {
calendars: {
title: "Calendarios",
description: "Visualiza y administra tus calendarios de Google.",
},
readEvents: {
title: "Leer eventos",
description: "Visualice y busque eventos en el calendario.",
},
writeEvents: {
title: "Crear y actualizar eventos",
description: "Crear nuevos eventos y modificar los existentes.",
},
rsvp: {
title: "Gestión de confirmaciones de asistencia",
description: "Gestiona el estado de tus respuestas para eventos.",
},
},
skills: {
listCalendars: {
title: "Calendarios",
description:
"Enumere todos los calendarios que posee o a los que esté suscrito.",
},
getCalendar: {
title: "Obtén los detalles del calendario",
description:
"Obtenga información detallada sobre un calendario específico.",
},
getEvent: {
title: "Obtener información del evento",
description:
"Obtenga información detallada sobre un evento específico.",
},
getEventsForDay: {
title: "Encuentra eventos para el día.",
description:
"Obtén todos los eventos programados para una fecha específica.",
},
getEvents: {
title: "Obtener eventos (rango de fechas)",
description:
"Obtener eventos dentro de un rango de fechas personalizado.",
},
getUpcomingEvents: {
title: "Consulta los próximos eventos",
description:
"Encuentre eventos para hoy, esta semana o este mes utilizando palabras clave sencillas.",
},
quickAdd: {
title: "Añadir evento rápidamente",
description:
'Crear un evento a partir de lenguaje natural (por ejemplo, "Reunión mañana a las 3 de la tarde")',
},
createEvent: {
title: "Crear evento",
description:
"Cree un nuevo evento con control total sobre todas las propiedades.",
},
updateEvent: {
title: "Actualización del evento",
description: "Actualizar un evento existente en el calendario",
},
setMyStatus: {
title: "Establecer estado de confirmación",
description:
"Aceptar, rechazar o aceptar provisionalmente un evento.",
},
},
},
},
mcp: {
title: "Servidores MCP",

View File

@ -620,6 +620,92 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Kalendri ühendaja",
description:
"Lisage oma esindajale võimalus interakteeruda Google Kalendriga vaadake kalendreid, hankige sündmusi, looge ja uuendage sündmusi ning hallake vastuvõtuid. <a>Vaadake dokumentatsiooni</a>.",
multiUserWarning:
"Google Kalendri integreerimine ei ole saadaval mitme kasutaja režiimis turvalisuse huvides. Palun deaktiveeri mitme kasutaja režiim, et kasutada seda funktsiooni.",
configuration: "Google Kalendri seadistamine",
deploymentId: "Paigutuse ID",
deploymentIdHelp: "Veebirakenduse Google Apps Scripti ID",
apiKey: "API võtme",
apiKeyHelp:
"API võti, mida olete konfigureerinud oma Google Apps Scripti rakenduses.",
configurationRequired:
'Palun konfigureerige "Deployment ID" ja API võti, et Google Calendar funktsionaalsus oleks aktiivne.',
configured: "Konfigureeritud",
searchSkills: "otsinguteadused...",
noSkillsFound: "Sellele andmetele ei leitud sobivaid tulemusi.",
categories: {
calendars: {
title: "Kalendrid",
description: "Vaata ja hallata oma Google kalendeid",
},
readEvents: {
title: "Vaata üritusi",
description: "Vaata ja otsi kalendri sündmusi",
},
writeEvents: {
title: "Loo ja uuenda üritusi",
description: "Loo uusi üritusi ja muuda olemasolevaid",
},
rsvp: {
title: "Vabatahtlikkuse registreerimise juhtimine",
description: "Halda oma vastuse staatuse sündmustele",
},
},
skills: {
listCalendars: {
title: "Kalendrid",
description:
"Loole kõik kalendrid, mille te omate või millele olete registreeritud.",
},
getCalendar: {
title: "Hankige kalendri üksikasjad",
description:
"Hankige üksikasjalikke andmeid konkreetse kalendri kohta",
},
getEvent: {
title: "Saada ürituse info",
description:
"Hankige üksikasjalikku teavet konkreetse ürituse kohta",
},
getEventsForDay: {
title: "Leidke üritused selle päeva jaoks",
description:
"Vaata kõiki üritusi, mis on planeeritud konkreetsele päeval",
},
getEvents: {
title: "Leia üritused (aegraadi)",
description: "Võtke kokku sündmused spetsifitse ajaskaala pikkusel",
},
getUpcomingEvents: {
title: "Vaata tulevasi üritusi",
description:
"Leidke sündmused täna, selle nädala või selle kuuga, kasutades lihtsaid sõnu",
},
quickAdd: {
title: "Kiirelt sisse lisada",
description:
'Loo üritus loomuliku keele alusel (nt "Koosolek homme kell 15:00")',
},
createEvent: {
title: "Loo üritus",
description:
"Loo uus üritus, mis võimaldab kontrollida kõiki selle atribuute.",
},
updateEvent: {
title: "Täiendav info",
description: "Muuda olemasoleva kalendri sündmuse",
},
setMyStatus: {
title: "Määrake vastuvõtu staatus",
description:
"Mõne sündmuse kinnitamise, kehtestamise või esialgse kinnitamise.",
},
},
},
},
mcp: {
title: "MCP-serverid",

View File

@ -623,6 +623,89 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "اتصال‌دهنده گوگل کالند",
description:
"به اپراتور خود اجازه دهید تا با گوگل کالند تعامل داشته باشد: مشاهده تقویم‌ها، دریافت رویدادها، ایجاد و به‌روزرسانی رویدادها، و مدیریت پاسخ‌های حضور و غیاب. برای اطلاعات بیشتر، به مستندات مراجعه کنید.",
multiUserWarning:
"ادغام با تقویم گوگل در حالت چند کاربر، به دلایل امنیتی، در دسترس نیست. لطفاً حالت چند کاربر را غیرفعال کنید تا از این قابلیت استفاده کنید.",
configuration: "تنظیمات تقویم گوگل",
deploymentId: "شناسه استقرار",
deploymentIdHelp:
"شناسه استقرار (Deployment ID) از برنامه وب Google Apps Script شما",
apiKey: "کلید API",
apiKeyHelp:
"کلید API که در تنظیمات اسکریپت‌های گوگل خود مشخص کرده‌اید.",
configurationRequired:
"لطفاً شناسه استقرار و کلید API را تنظیم کنید تا قابلیت‌های گوگل کالدِر فعال شوند.",
configured: "تنظیم شده",
searchSkills: "مهارت‌های جستجو...",
noSkillsFound: "هیچ یک از مهارت‌های موجود با جستجوی شما مطابقت ندارند.",
categories: {
calendars: {
title: "تقویم‌ها",
description: "مشاهده و مدیریت تقویم‌های گوگل خود",
},
readEvents: {
title: "برنامه‌ها",
description: "مشاهده و جستجو در رویدادهای تقویم",
},
writeEvents: {
title: "ایجاد و به‌روزرسانی رویدادها",
description: "ایجاد رویدادهای جدید و تغییر دادن رویدادهای موجود",
},
rsvp: {
title: "مدیریت پاسخ‌های دعوت",
description: "وضعیت پاسخ خود را برای رویدادها تعیین کنید.",
},
},
skills: {
listCalendars: {
title: "لیست تقویم‌ها",
description:
"لیستی از تمام تقویم‌هایی که مالک آن هستید یا به آن‌ها مشترک هستید، تهیه کنید.",
},
getCalendar: {
title: "جزئیات تقویم را دریافت کنید",
description: "اطلاعات دقیقی در مورد یک تقویم خاص به دست آورید.",
},
getEvent: {
title: "اطلاعات مربوط به رویداد",
description: "اطلاعات دقیقی درباره یک رویداد خاص به دست آورید.",
},
getEventsForDay: {
title: "اطلاعات رویدادهای روز",
description:
"اطلاعات مربوط به تمام رویدادهایی که در یک تاریخ خاص برنامه‌ریزی شده‌اند را دریافت کنید.",
},
getEvents: {
title: "نمایش رویدادها (محدوده تاریخ)",
description: "به دست آوردن رویدادهایی در یک بازه زمانی سفارشی",
},
getUpcomingEvents: {
title: "برنامه‌های آتی را مشاهده کنید",
description:
"برای یافتن رویدادهای امروز، این هفته یا این ماه، از کلمات کلیدی ساده استفاده کنید.",
},
quickAdd: {
title: "اضافه کردن سریع رویداد",
description:
'ایجاد یک رویداد بر اساس زبان طبیعی (به عنوان مثال، "جلسه فردا در ساعت 3 بعد از ظهر")',
},
createEvent: {
title: "ایجاد رویداد",
description: "ایجاد یک رویداد جدید با کنترل کامل بر تمام ویژگی‌ها",
},
updateEvent: {
title: "اعلام تغییرات",
description: "به‌روزرسانی یک رویداد موجود در تقویم",
},
setMyStatus: {
title: "وضعیت پاسخگویی را تعیین کنید",
description: "قبول، رد یا پذیرش موقت یک رویداد",
},
},
},
},
mcp: {
title: "سرورهای MCP",

View File

@ -643,6 +643,97 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Connecteur Google Calendar",
description:
"Permettez à votre agent d'interagir avec Google Calendar : consulter les calendriers, afficher les événements, créer et modifier des événements, et gérer les confirmations de présence. <a>Consultez la documentation</a>.",
multiUserWarning:
"L'intégration avec Google Calendar n'est pas disponible en mode multi-utilisateurs pour des raisons de sécurité. Veuillez désactiver le mode multi-utilisateurs pour utiliser cette fonctionnalité.",
configuration: "Configuration de Google Calendar",
deploymentId: "ID de déploiement",
deploymentIdHelp:
"L'identifiant de déploiement de votre application web Google Apps Script",
apiKey: "Clé API",
apiKeyHelp:
"La clé API que vous avez configurée dans votre déploiement de Google Apps Script",
configurationRequired:
"Veuillez configurer l'ID de déploiement et la clé API pour activer les fonctionnalités Google Calendar.",
configured: "Configuré",
searchSkills: "Compétences de recherche...",
noSkillsFound: "Aucun résultat correspondant à votre recherche.",
categories: {
calendars: {
title: "Calendriers",
description: "Visualisez et gérez vos calendriers Google.",
},
readEvents: {
title: "Lire les événements",
description:
"Visualiser et rechercher les événements du calendrier",
},
writeEvents: {
title: "Créer et mettre à jour des événements",
description:
"Créer de nouveaux événements et modifier les événements existants.",
},
rsvp: {
title: "Gestion des réponses",
description: "Gérez votre statut de réponse pour les événements.",
},
},
skills: {
listCalendars: {
title: "Calendriers",
description:
"Énumérez tous les calendriers que vous possédez ou auxquels vous êtes abonné.",
},
getCalendar: {
title: "Obtenir les détails du calendrier",
description:
"Obtenez des informations détaillées sur un calendrier spécifique.",
},
getEvent: {
title: "Obtenir l'événement",
description:
"Obtenez des informations détaillées sur un événement spécifique.",
},
getEventsForDay: {
title: "Obtenir les événements pour la journée",
description:
"Consultez tous les événements prévus pour une date spécifique.",
},
getEvents: {
title: "Événements (période)",
description:
"Récupérer des événements dans une plage de dates personnalisée",
},
getUpcomingEvents: {
title: "Consulter les événements à venir",
description:
"Trouvez des événements pour aujourd'hui, cette semaine ou ce mois en utilisant des mots-clés simples.",
},
quickAdd: {
title: "Ajouter un événement rapidement",
description:
"Créer un événement à partir d'une description en langage naturel (par exemple, « Réunion demain à 15h »)",
},
createEvent: {
title: "Créer un événement",
description:
"Créez un nouvel événement avec un contrôle total sur toutes les propriétés.",
},
updateEvent: {
title: "Mise à jour de l'événement",
description:
"Mettre à jour un événement existant dans le calendrier",
},
setMyStatus: {
title: "Définir le statut de réponse",
description:
"Accepter, refuser ou accepter provisoirement un événement.",
},
},
},
},
mcp: {
title: "Serveurs MCP",

View File

@ -614,6 +614,86 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "חיבור ל-Google Calendar",
description:
"אפשרו לסוכן שלכם לתקשר עם גוגל קלנדר - לצפות בקלנדרים, לקבל אירועים, ליצור ולעדכן אירועים, ולנהל אישורי השתתפות. <a>קראו את התיעוד</a>.",
multiUserWarning:
"שילוב עם גוגל קלנדר אינו זמין במצב רב-משתמשים מטעמי אבטחה. אנא כבו את מצב רב-משתמשים כדי להשתמש בתכונה זו.",
configuration: "הגדרת גלובל קלנדר",
deploymentId: "מזהה הפריסה",
deploymentIdHelp: "מזהה הפריסה מהאפליקציה שלך של Google Apps Script",
apiKey: "מפתח API",
apiKeyHelp:
"המפתח של ה-API שקבעת בהגדרות של סקריפט האפליקציות של גוגל.",
configurationRequired:
"אנא הגדירו את מזהה ההפצה ואת מפתח ה-API כדי לאפשר את הפונקציונליות של גוגל קלנדר.",
configured: "מוגדר",
searchSkills: "כישורים לחיפוש...",
noSkillsFound: "אין התאמות לחיפוש שלך.",
categories: {
calendars: {
title: "יומני",
description: "צפו ונהלו את הלוחות שלכם בגוגל",
},
readEvents: {
title: "קרא על אירועים",
description: "צפו וחפשו אירועים בלוח השנה",
},
writeEvents: {
title: "יצירה ועדכון אירועים",
description: "ליצור אירועים חדשים ולשנות את האירועים הקיימים.",
},
rsvp: {
title: "ניהול אישורי השתתפות",
description: "נהלו את סטטוס התגובה שלכם לאירועים",
},
},
skills: {
listCalendars: {
title: "רשימת לוחות",
description: "רשום את כל הקלנדרים שבבעלותך או אליהם מנויים.",
},
getCalendar: {
title: "קבל פרטים על הקלנדר",
description: "קבל מידע מפורט על לוח שנה ספציפי.",
},
getEvent: {
title: "קבל אירוע",
description: "קבל מידע מפורט על אירוע ספציפי",
},
getEventsForDay: {
title: "מצא אירועים ליום",
description: "קבלו את כל האירועים המתוכננים לתאריך ספציפי.",
},
getEvents: {
title: "קבל אירועים (טווח תאריכים)",
description: "קבל אירועים בטווח תאריכים מותאם אישית",
},
getUpcomingEvents: {
title: "רשימת אירועים עתידיים",
description:
"מצאו אירועים של היום, השבוע או החודש באמצעות מילות מפתח פשוטות.",
},
quickAdd: {
title: "הוספה מהירה של אירוע",
description:
'ליצור אירוע מתוך טקסט טבעי (למשל, "פגישה מחר בשעה 15:00")',
},
createEvent: {
title: "יצירת אירוע",
description: "צור אירוע חדש עם שליטה מלאה על כל התכונות.",
},
updateEvent: {
title: "עדכון אירוע",
description: "עדכן אירוע קיים בלוח השנה",
},
setMyStatus: {
title: "הגדר סטטוס אישור השתתפות",
description: "לקבל, לדחות, או לקבל באופן זמני אירוע",
},
},
},
},
mcp: {
title: "שרתי MCP",

View File

@ -643,6 +643,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Connettore per Google Calendar",
description:
"Permetti al tuo agente di interagire con Google Calendar: visualizza calendari, visualizza eventi, crea e aggiorna eventi, e gestisci le conferme di partecipazione. <a>Consulta la documentazione</a>.",
multiUserWarning:
"L'integrazione con Google Calendar non è disponibile in modalità multiutente per motivi di sicurezza. Per utilizzare questa funzione, è necessario disattivare la modalità multiutente.",
configuration: "Configurazione del calendario Google",
deploymentId: "ID di distribuzione",
deploymentIdHelp:
"L'ID di distribuzione dalla tua applicazione web Google Apps Script",
apiKey: "Chiave API",
apiKeyHelp:
"La chiave API che hai configurato nella tua distribuzione di Google Apps Script",
configurationRequired:
"Si prega di configurare l'ID di distribuzione e la chiave API per abilitare le funzionalità di Google Calendar.",
configured: "Configurato",
searchSkills: "Competenze di ricerca...",
noSkillsFound:
"Non sono state trovate corrispondenze per la tua ricerca.",
categories: {
calendars: {
title: "Calendari",
description: "Visualizza e gestisci i tuoi calendari Google.",
},
readEvents: {
title: "Leggi gli eventi",
description: "Visualizza e cerca eventi nel calendario",
},
writeEvents: {
title: "Creare e aggiornare eventi",
description: "Creare nuovi eventi e modificare quelli esistenti.",
},
rsvp: {
title: "Gestione delle conferme di partecipazione",
description: "Gestisci lo stato della tua risposta per gli eventi.",
},
},
skills: {
listCalendars: {
title: "Calendari personalizzati",
description:
"Elenca tutti i calendari che possiedi o a cui sei abbonato.",
},
getCalendar: {
title: "Ottieni i dettagli del calendario",
description:
"Ottenere informazioni dettagliate su un calendario specifico.",
},
getEvent: {
title: "Informazioni sull'evento",
description:
"Ottenere informazioni dettagliate su un evento specifico.",
},
getEventsForDay: {
title: "Trova eventi per il giorno specifico",
description:
"Visualizza tutti gli eventi programmati per una data specifica.",
},
getEvents: {
title: "Eventi (Intervallo di date)",
description:
"Recupera eventi all'interno di un intervallo di date personalizzato.",
},
getUpcomingEvents: {
title: "Consulta gli eventi futuri",
description:
"Trova eventi per oggi, questa settimana o questo mese utilizzando parole chiave semplici.",
},
quickAdd: {
title: "Aggiungi evento rapidamente",
description:
'Creare un evento a partire da un testo in linguaggio naturale (ad esempio, "Riunione domani alle 15:00")',
},
createEvent: {
title: "Crea evento",
description:
"Crea un nuovo evento con il pieno controllo su tutte le proprietà.",
},
updateEvent: {
title: "Aggiornamento evento",
description: "Modificare un evento esistente nel calendario",
},
setMyStatus: {
title: "Imposta lo stato della risposta",
description:
"Accettare, rifiutare o accettare con riserva un evento",
},
},
},
},
mcp: {
title: "Server MCP",

View File

@ -615,6 +615,89 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google カレンダー 連携機能",
description:
"エージェントがGoogleカレンダーと連携できるようにする - カレンダーの表示、イベントの取得、イベントの作成と更新、およびRSVPの管理を可能にする。詳細については、ドキュメントを参照してください。",
multiUserWarning:
"Google カレンダーとの連携は、セキュリティ上の理由から、複数ユーザーモードでは利用できません。この機能をご利用いただくには、複数ユーザーモードを無効にする必要があります。",
configuration: "Google カレンダーの設定",
deploymentId: "デプロイメントID",
deploymentIdHelp:
"あなたのGoogle Apps ScriptのウェブアプリケーションのデプロイID",
apiKey: "APIキー",
apiKeyHelp: "Google Apps Script のデプロイ時に設定した API キー",
configurationRequired:
"Google カレンダーの機能を使用するために、デプロイメントIDとAPIキーを設定してください。",
configured: "設定済み",
searchSkills: "検索スキル...",
noSkillsFound:
"あなたの検索条件に合致するスキルは見つかりませんでした。",
categories: {
calendars: {
title: "カレンダー",
description: "Googleカレンダーの表示と管理",
},
readEvents: {
title: "イベント情報",
description: "カレンダー上のイベントの表示と検索",
},
writeEvents: {
title: "イベントの作成と更新",
description: "新しいイベントを作成し、既存のイベントを修正する",
},
rsvp: {
title: "RSVP出欠確認管理",
description: "イベントへの参加状況を管理する",
},
},
skills: {
listCalendars: {
title: "カレンダーリスト",
description:
"所有している、または購読しているすべてのカレンダーの一覧",
},
getCalendar: {
title: "カレンダーの詳細を確認する",
description: "特定のカレンダーに関する詳細な情報த்தைப்入手する",
},
getEvent: {
title: "イベント情報を入手",
description: "特定のイベントに関する詳細な情報த்தைப்入手する",
},
getEventsForDay: {
title: "その日のイベントを検索する",
description: "特定の日に予定されているすべてのイベントを取得する",
},
getEvents: {
title: "イベント(期間指定)",
description: "指定した期間内のイベントを取得する",
},
getUpcomingEvents: {
title: "今後のイベントをチェックする",
description:
"今日、今週、または今月のイベントを、簡単なキーワードを使って検索する",
},
quickAdd: {
title: "イベントをすぐに登録",
description:
"自然言語「明日午後3時に会議」からイベントを作成する",
},
createEvent: {
title: "イベントを作成する",
description:
"すべてのプロパティを完全に制御できる、新しいイベントを作成する。",
},
updateEvent: {
title: "イベント情報更新",
description: "既存の予定を更新する",
},
setMyStatus: {
title: "返信状況を設定する",
description: "イベントへの参加、拒否、または仮の参加",
},
},
},
},
mcp: {
title: "MCP サーバー",

View File

@ -616,6 +616,87 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "구글 캘린더 연동",
description:
"에이전트가 Google 캘린더와 상호 작용할 수 있도록 설정하세요 - 캘린더 보기, 이벤트 확인, 이벤트 생성 및 업데이트, RSVP 관리 등을 수행할 수 있습니다. <a>문서를 참조하세요</a>.",
multiUserWarning:
"Google 캘린더 통합 기능은 보안상의 이유로 다중 사용자 모드에서는 사용할 수 없습니다. 이 기능을 사용하려면 다중 사용자 모드를 비활성화해주세요.",
configuration: "구글 캘린더 설정",
deploymentId: "배포 ID",
deploymentIdHelp: "당신의 구글 앱스 스크립트 웹 앱의 배포 ID",
apiKey: "API 키",
apiKeyHelp: "Google Apps Script 배포 시 설정한 API 키",
configurationRequired:
"구글 캘린더 기능을 사용하려면 배포 ID와 API 키를 설정해 주세요.",
configured: "설정됨",
searchSkills: "검색 기술...",
noSkillsFound: "검색하신 조건과 일치하는 기술이 없습니다.",
categories: {
calendars: {
title: "달력",
description: "Google 캘린더를 확인하고 관리하세요.",
},
readEvents: {
title: "이벤트 목록 보기",
description: "일정 뷰 및 검색",
},
writeEvents: {
title: "이벤트 생성 및 업데이트",
description: "새로운 이벤트를 생성하고 기존 이벤트를 수정",
},
rsvp: {
title: "참석 확인 관리",
description: "이벤트에 대한 응답 상태를 관리하세요.",
},
},
skills: {
listCalendars: {
title: "달력 목록",
description:
"자신이 소유하거나 구독하고 있는 모든 캘린더 목록을 작성하세요.",
},
getCalendar: {
title: "달력 세부 정보 보기",
description: "특정 캘린더에 대한 자세한 정보를 얻으세요.",
},
getEvent: {
title: "이벤트 정보 보기",
description: "특정 이벤트에 대한 자세한 정보를 얻으세요.",
},
getEventsForDay: {
title: "오늘의 행사 정보 보기",
description: "특정 날짜에 예정된 모든 행사 목록을 확인",
},
getEvents: {
title: "이벤트 검색 (날짜 범위)",
description: "사용자 지정 날짜 범위 내의 이벤트 가져오기",
},
getUpcomingEvents: {
title: "다가오는 행사 보기",
description:
"오늘, 이번 주 또는 이번 달의 이벤트를 간단한 키워드를 사용하여 검색",
},
quickAdd: {
title: "빠르게 이벤트 추가",
description:
'자연어 (예: "내일 오후 3시에 회의")를 사용하여 이벤트를 생성합니다.',
},
createEvent: {
title: "이벤트 생성",
description:
"모든 속성에 대한 완전한 제어 기능을 갖춘 새로운 이벤트를 생성합니다.",
},
updateEvent: {
title: "이벤트 업데이트",
description: "기존 캘린더 이벤트 업데이트",
},
setMyStatus: {
title: "RSVP 상태 설정",
description: "행사 참여 여부를 수락, 거절, 또는 잠정적으로 수락",
},
},
},
},
mcp: {
title: "MCP 서버",

View File

@ -644,6 +644,90 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "„Google Kalendoriaus“ integracija",
description:
"Įgalinkite savo agentą, kad galėtų bendradarbiauti su „Google Calendar“ peržiūrėti kalendorius, gauti renginių informaciją, kurti ir atnaujinti renginius bei tvarkyti patvirtimus. <a>Peržiūrėkite dokumentaciją</a>.",
multiUserWarning:
"„Google Kalendro“ integracija negali būti naudojama kelių vartotojų režimu dėl saugumo priežasčių. Norėdami naudoti šią funkciją, prašome išjungti kelių vartotojų režimą.",
configuration: "„Google Kalendoriaus“ konfigūracija",
deploymentId: "Įrenginio ID",
deploymentIdHelp: "Jūsų „Google Apps Script“ svetainės programos ID",
apiKey: "API raktas",
apiKeyHelp:
"„API raktas“, kurį konfigūravoje savo „Google Apps Script“ programoje.",
configurationRequired:
"Prašome nustatyti „Deployment ID“ ir API raktą, kad būtų įgalintos „Google Calendar“ funkcijos.",
configured: "Nustatytas",
searchSkills: "Paieškos įgūdžiai...",
noSkillsFound: "Nėra atitikčių jūsų paieškos kriterijams.",
categories: {
calendars: {
title: "Kalendoriai",
description: "Peržiūrėkite ir valdykite savo „Google Kalendorius“.",
},
readEvents: {
title: "Peržiūrėti renginius",
description: "Peržiūrėkite ir paieškokite kalendoriaus renginių",
},
writeEvents: {
title: "Sukurkite ir atnaujinkite renginius",
description: "Sukurkite naujas renginius ir keičkite esamus",
},
rsvp: {
title: "Patvirtinimų valdymas",
description: "Valdykite savo atsakymo statusą renginiams",
},
},
skills: {
listCalendars: {
title: "Kalendoriai",
description:
"Peržiūrėkite visus kalendorius, kuriuos turite arba kuriems yra prenumerata.",
},
getCalendar: {
title: "Gaukite kalendoriaus detales",
description:
"Gaukite išsamią informaciją apie konkrečią kalendorių",
},
getEvent: {
title: "Gaukite renginį",
description: "Gaukite išsamią informaciją apie konkrečią renginį",
},
getEventsForDay: {
title: "Rasti renginius šiam dienai",
description: "Gaukite visus įvykius, numatytus konkrečią dieną.",
},
getEvents: {
title: "Rodyti renginius (laiko intervalas)",
description: "Gauti renginius už nurodytą datų intervalą",
},
getUpcomingEvents: {
title: "Peržiūrėti ateinančias renginius",
description:
"Raskite renginius šiandien, šią savaitę arba šį mėnesį naudodami paprastus žodžius.",
},
quickAdd: {
title: "Greitas renginio pridėjimas",
description:
"Sukurkite renginį iš natūralios kalbos (pvz., „Susitikimas rytoj 15:00 val.“)",
},
createEvent: {
title: "Sukurti renginį",
description:
"Sukurkite naują renginį, turėdami visišką kontrolę per visas jo savybes.",
},
updateEvent: {
title: "Paskelbimo atnaujinimas",
description: "Redaguoti esamą kalendoriaus renginį",
},
setMyStatus: {
title: "Nurodykite atsakymo statusą",
description:
"Prisitaikyti, atsisakyti arba iš esmės pritarti renginiui.",
},
},
},
},
mcp: {
title: "MCP serveriai",

View File

@ -641,6 +641,91 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Kalendāra integrācija",
description:
"Ļauj savam pārstāvim interaktīvi darboties ar Google Kalendāru skatīt kalendārus, iegūt pasākumus, izveidot un atjaunot pasākumus, kā arī pārvaldīt reģistrāciju. <a>Lasiet dokumentāciju</a>.",
multiUserWarning:
"Google Kalendāra integrācija nav pieejama vairāku lietotāju režīmā, lai nodrošinātu drošību. Lūdzu, atgrieziet multilietotāju režīmu, lai izmantotu šo funkciju.",
configuration: "Google kalendāra konfigurācija",
deploymentId: "Ierīces identifikators",
deploymentIdHelp: "Jūsu Google Apps Script veidlapas ID",
apiKey: "API atslēga",
apiKeyHelp:
"API atslēga, ko jūs konfigurējāt savā Google Apps Script instalācijā",
configurationRequired:
'Lūdzu, konfigurējiet "Deployment ID" un API atslēgu, lai aktivizētu Google Kalendāra funkcijas.',
configured: "Ierīkots",
searchSkills: "Meklēšanas prasmes...",
noSkillsFound: "Neatrodītas atbilstības jūsu meklējumiem.",
categories: {
calendars: {
title: "Kalendāri",
description: "Skatiet un pārvaldiet savus Google kalendārus.",
},
readEvents: {
title: "Lasīt pasākumus",
description: "Skatiet un meklējiet kalendāra notikumus",
},
writeEvents: {
title: "Izveidot un atjaunināt pasākumus",
description: "Izveidot jaunas pasākumus un mainīt esošos",
},
rsvp: {
title: "Piedalīšanās reģistrācija",
description: "Pārvaldiet savu atbildes statusu pasākumiem",
},
},
skills: {
listCalendars: {
title: "Kalendāri",
description:
"Izveidojot sarakstu, norādi visus kalendārus, ko tu īpašoj un uz kuriem esi reģistrējies.",
},
getCalendar: {
title: "Iegūstiet kalendāra informāciju",
description: "Iesaļojiet detalizētus datus par konkrētu kalendāru.",
},
getEvent: {
title: "Iegūstiet pasākuma informāciju",
description:
"Iesaļojiet detalizētu informāciju par konkrētu pasākumu",
},
getEventsForDay: {
title: "Ieskats uz pasākumiem šajā dienā",
description:
"Ieskaitiet visus pasākumus, kas plānoti konkrētā datumā",
},
getEvents: {
title: "Iegūstiet pasākumus (datu diapazons)",
description:
"Iegūt pasākumus, kas notiek konkrētā datuma diapazonā",
},
getUpcomingEvents: {
title: "Uznāciet nākamo pasākumu",
description:
"Atrodiet pasākumus šodien, šajā nedēļā vai šajā mēnesī, izmantojot vienkāržus atslēvvadus.",
},
quickAdd: {
title: "Ātri pievienot pasākumu",
description:
'Izveidot pasākumu, izmantojot dabas valodu (piemēram, "Sanākšana rīt plkst. 15:00")',
},
createEvent: {
title: "Izveidot pasākumu",
description:
"Izveidot jaunu pasākumu, nodrošinot pilnu kontroli pār visām tās īpašībām.",
},
updateEvent: {
title: "Pasākuma atjauninājums",
description: "Atjaunināt esošas kalendāra notikuma informāciju",
},
setMyStatus: {
title: "Norādiet atbildes statusu",
description: "Atzīst, atgrūst vai temporāri apstiprināt pasākumu",
},
},
},
},
mcp: {
title: "MCP serveri",

View File

@ -630,6 +630,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Kalender-connector",
description:
"Maak het mogelijk voor uw agent om met Google Kalender te communiceren: kalenders bekijken, evenementen bekijken, evenementen aanmaken en bijwerken, en RSVP's beheren. <a>Lees de documentatie</a>.",
multiUserWarning:
"De integratie met Google Kalender is niet beschikbaar in de modus met meerdere gebruikers, vanwege beveiligingsredenen. Om deze functie te gebruiken, dient u de modus met meerdere gebruikers uit te schakelen.",
configuration: "Google Kalender instellingen",
deploymentId: "Identificatiecode voor de implementatie",
deploymentIdHelp: "De deployment-ID van uw Google Apps Script web-app",
apiKey: "API-sleutel",
apiKeyHelp:
"De API-sleutel die u heeft geconfigureerd in uw Google Apps Script-implementatie.",
configurationRequired:
"Configureer de Deployment ID en de API-sleutel om de Google Calendar-functionaliteit te activeren.",
configured: "Geconfigureerd",
searchSkills: "Vaardigheden op het gebied van zoeken...",
noSkillsFound:
"Geen resultaten gevonden die overeenkomen met uw zoekopdracht.",
categories: {
calendars: {
title: "Kalenders",
description: "Bekijk en beheer uw Google-agenda's",
},
readEvents: {
title: "Bekijk evenementen",
description: "Bekijk en zoek naar evenementen in de agenda",
},
writeEvents: {
title: "Maak en update evenementen",
description:
"Creëer nieuwe evenementen en wijzig bestaande evenementen.",
},
rsvp: {
title: "Beheer van RSVP-verzoeken",
description: "Beheer de status van uw reacties voor evenementen",
},
},
skills: {
listCalendars: {
title: "Agenda's",
description:
"Maak een lijst van alle kalenders die u bezit of waarvoor u een abonnement heeft.",
},
getCalendar: {
title: "Bekijk de details van de agenda",
description:
"Vind gedetailleerde informatie over een specifieke kalender.",
},
getEvent: {
title: "Evenement bekijken",
description:
"Vind gedetailleerde informatie over een specifiek evenement.",
},
getEventsForDay: {
title: "Zoek naar evenementen voor de dag",
description:
"Bekijk alle evenementen die gepland staan voor een specifieke dag.",
},
getEvents: {
title: "Evenementen (tijdsperiode)",
description:
"Haal evenementen op binnen een aangepaste datumschaal",
},
getUpcomingEvents: {
title: "Bekijk aankomende evenementen",
description:
"Zoek evenementen voor vandaag, deze week of deze maand met behulp van eenvoudige zoekwoorden.",
},
quickAdd: {
title: "Snel evenement toevoegen",
description:
"Maak een evenement op basis van natuurlijke taal (bijvoorbeeld: 'Ontmoeting morgen om 15:00 uur')",
},
createEvent: {
title: "Evenement aanmaken",
description:
"Maak een nieuw evenement en beschik over volledige controle over alle instellingen.",
},
updateEvent: {
title: "Nieuwsupdate",
description: "Wijzig een bestaand evenement in uw agenda",
},
setMyStatus: {
title: "Status van reactie bevestigd",
description:
"Accepteer, weiger of geef een voorlopige bevestiging van een evenement",
},
},
},
},
mcp: {
title: "MCP-servers",

View File

@ -646,6 +646,94 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Łącznik do Google Kalendarza",
description:
"Pozwól swojemu agentowi na interakcję z Google Calendar przeglądaj kalendarze, sprawdzaj wydarzenia, twórz i aktualizuj wydarzenia oraz zarządzaj potwierdzeniami obecności. <a>Przeczytaj dokumentację</a>.",
multiUserWarning:
"Integracja z Google Calendar nie jest dostępna w trybie wieloosobowym z powodów bezpieczeństwa. Aby korzystać z tej funkcji, należy wyłączyć tryb wieloosobowy.",
configuration: "Konfiguracja kalendarza Google",
deploymentId: "Identyfikator wdrożenia",
deploymentIdHelp:
"ID aplikacji webowej z Google Apps Script, której używasz.",
apiKey: "Klucz API",
apiKeyHelp:
"Klucz API, który skonfigurowałeś w swoim projekcie Google Apps Script",
configurationRequired:
"Prosimy o skonfigurowanie ID wdrażania i klucza API, aby włączyć funkcje związane z Google Calendar.",
configured: "Skonfigurowane",
searchSkills: "Umiejętności wyszukiwania...",
noSkillsFound:
"Nie znaleziono żadnych kandydatów, którzy spełniałyby Twoje kryteria.",
categories: {
calendars: {
title: "Kalendarze",
description: "Przeglądaj i zarządzaj swoimi kalendarzami Google.",
},
readEvents: {
title: "Sprawdź wydarzenia",
description: "Przeglądaj i wyszukuj wydarzenia w kalendarzu",
},
writeEvents: {
title: "Tworzenie i aktualizacja wydarzeń",
description: "Twórz nowe wydarzenia i modyfikuj istniejące.",
},
rsvp: {
title: "Zarządzanie rezerwacjami",
description: "Zarządzaj statusem odpowiedzi dla wydarzeń",
},
},
skills: {
listCalendars: {
title: "Kalendarze",
description:
"Wypisz wszystkie kalendarze, które posiadasz lub do których subskrybujesz.",
},
getCalendar: {
title: "Uzyskaj szczegółowe informacje o kalendarzu",
description:
"Uzyskaj szczegółowe informacje na temat konkretnego kalendarza.",
},
getEvent: {
title: "Uzyskaj informacje o wydarzeniu",
description:
"Uzyskaj szczegółowe informacje na temat konkretnego wydarzenia",
},
getEventsForDay: {
title: "Sprawdź wydarzenia na dany dzień",
description:
"Pobierz wszystkie wydarzenia zaplanowane na konkretny dzień.",
},
getEvents: {
title: "Wyszukaj wydarzenia (zakres dat)",
description: "Pobierz wydarzenia w określonym przedziale dat.",
},
getUpcomingEvents: {
title: "Sprawdź nadchodzące wydarzenia",
description:
"Znajdź wydarzenia na dzisiaj, w tym tygodniu lub w tym miesiącu, używając prostych słów kluczowych.",
},
quickAdd: {
title: "Szybkie dodanie wydarzenia",
description:
"Utwórz wydarzenie na podstawie opisu w języku naturalnym (np. „Spotkanie jutro o 15:00”)",
},
createEvent: {
title: "Utwórz wydarzenie",
description:
"Utwórz nowe wydarzenie, mając pełną kontrolę nad wszystkimi jego właściwościami.",
},
updateEvent: {
title: "Aktualizacja wydarzenia",
description: "Zaktualizuj istniejącą wydarzenie w kalendarzu",
},
setMyStatus: {
title: "Ustaw status odpowiedzi",
description:
"Przyjęć, odrzucić lub wyrazić wstępne zainteresowanie udziałem w wydarzeniu",
},
},
},
},
mcp: {
title: "Serwery MCP",

View File

@ -641,6 +641,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Conector do Google Calendar",
description:
"Permita que seu agente interaja com o Google Agenda visualize agendas, obter eventos, criar e atualizar eventos, e gerenciar confirmações de presença. <a>Leia a documentação</a>.",
multiUserWarning:
"A integração com o Google Calendar não está disponível no modo multiusuário, por razões de segurança. Por favor, desative o modo multiusuário para utilizar esta funcionalidade.",
configuration: "Configuração do Google Agenda",
deploymentId: "ID de implantação",
deploymentIdHelp:
"O ID de implantação da sua aplicação web do Google Apps Script",
apiKey: "Chave de API",
apiKeyHelp:
"A chave de API que você configurou no seu projeto Google Apps Script",
configurationRequired:
"Por favor, configure o ID de Implantação e a Chave de API para habilitar as funcionalidades do Google Calendar.",
configured: "Configurado",
searchSkills: "Habilidades de pesquisa...",
noSkillsFound:
"Não encontramos nenhum resultado que corresponda à sua pesquisa.",
categories: {
calendars: {
title: "Calendários",
description: "Visualize e gerencie seus calendários do Google.",
},
readEvents: {
title: "Ver eventos",
description: "Visualize e pesquise eventos no calendário",
},
writeEvents: {
title: "Criar e atualizar eventos",
description: "Crie novos eventos e modifique os existentes.",
},
rsvp: {
title: "Gerenciamento de confirmações de presença",
description: "Gerencie o status da sua resposta para eventos.",
},
},
skills: {
listCalendars: {
title: "Listar calendários",
description:
"Liste todos os calendários que você possui ou aos quais está inscrito.",
},
getCalendar: {
title: "Obtenha detalhes do calendário",
description:
"Obtenha informações detalhadas sobre um calendário específico.",
},
getEvent: {
title: "Obtenha informações sobre o evento",
description:
"Obtenha informações detalhadas sobre um evento específico.",
},
getEventsForDay: {
title: "Encontre eventos para o dia",
description:
"Obtenha todos os eventos agendados para uma data específica.",
},
getEvents: {
title: "Obter eventos (período de tempo)",
description:
"Obtenha eventos dentro de um intervalo de datas personalizado.",
},
getUpcomingEvents: {
title: "Veja os próximos eventos",
description:
"Encontre eventos para hoje, esta semana ou este mês utilizando palavras-chave simples.",
},
quickAdd: {
title: "Adicionar evento rapidamente",
description:
'Criar um evento a partir de linguagem natural (por exemplo, "Reunião amanhã às 15h")',
},
createEvent: {
title: "Criar evento",
description:
"Crie um novo evento com controle total sobre todas as propriedades.",
},
updateEvent: {
title: "Atualização do evento",
description: "Atualizar um evento existente no calendário",
},
setMyStatus: {
title: "Definir o status de confirmação de presença",
description:
"Aceitar, recusar ou aceitar provisoriamente um evento.",
},
},
},
},
mcp: {
title: "Servidores MCP",

View File

@ -1093,6 +1093,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Conector Google Calendar",
description:
"Permite-ți agentului să interacționeze cu Google Calendar vizualizează calendare, obține evenimente, creează și actualizează evenimente, și gestionează răspunsurile la invitații. Consultă documentația<a>.",
multiUserWarning:
"Integrarea cu Google Calendar nu este disponibilă în modul multi-utilizator, din motive de securitate. Vă rugăm să dezactivați modul multi-utilizator pentru a utiliza această funcție.",
configuration: "Configurarea calendarului Google",
deploymentId: "ID de implementare",
deploymentIdHelp:
"ID-ul de implementare al aplicației web Google Apps Script",
apiKey: "Cheia API",
apiKeyHelp:
"Cheia API pe care ați configurat în implementarea dumneavoastră de Google Apps Script",
configurationRequired:
"Vă rugăm să configurați ID-ul de implementare și cheia API pentru a activa funcționalitățile Google Calendar.",
configured: "Configurat",
searchSkills: "Abilități de căutare...",
noSkillsFound:
"Nu s-au găsit rezultate care să corespundă criteriilor dumneavoastră de căutare.",
categories: {
calendars: {
title: "Calendare",
description: "Vizualizați și gestionați calendarele Google.",
},
readEvents: {
title: "Vezi evenimente",
description: "Vizualizați și căutați evenimentele din calendar",
},
writeEvents: {
title: "Creați și actualizați evenimente",
description:
"Creați evenimente noi și modificați evenimentele existente.",
},
rsvp: {
title: "Gestionarea răspunsurilor",
description:
"Gestionați starea răspunsului dumneavoastră pentru evenimente",
},
},
skills: {
listCalendars: {
title: "Liste de calendare",
description:
"Enumerați toate calendarele pe care le dețineți sau pentru care aveți abonament.",
},
getCalendar: {
title: "Obțineți detalii despre calendar",
description:
"Obțineți informații detaliate despre un calendar specific.",
},
getEvent: {
title: "Obține evenimentul",
description:
"Obțineți informații detaliate despre un eveniment specific.",
},
getEventsForDay: {
title: "Obține evenimente pentru ziua respectivă",
description:
"Obțineți toate evenimentele programate pentru o anumită dată.",
},
getEvents: {
title: "Obține evenimente (interval de date)",
description: "Obține evenimente într-un interval de date specific",
},
getUpcomingEvents: {
title: "Vezi evenimentele viitoare",
description:
"Găsiți evenimente pentru ziua de azi, pentru această săptămână sau pentru acest lună, folosind cuvinte cheie simple.",
},
quickAdd: {
title: "Adaugă eveniment rapid",
description:
"Creați un eveniment folosind limbaj natural (de exemplu, „Întâlnire mâine la ora 15:00”)",
},
createEvent: {
title: "Creați eveniment",
description:
"Creați un eveniment nou, având control complet asupra tuturor proprietăților.",
},
updateEvent: {
title: "Actualizare eveniment",
description: "Modificați un eveniment existent din calendar",
},
setMyStatus: {
title: "Stare confirmare participare",
description: "Acceptă, refuză sau acceptă cu rezerve evenimentul",
},
},
},
},
mcp: {
title: "Servere MCP",

View File

@ -636,6 +636,95 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Коннектор для Google Календаря",
description:
"Позвольте своему агенту взаимодействовать с Google Календарем: просматривать календари, получать информацию о событиях, создавать и обновлять события, а также управлять подтверждениями участия. <a>Обратитесь к документации</a>.",
multiUserWarning:
"Интеграция с Google Календарем недоступна в многопользовательском режиме по соображениям безопасности. Пожалуйста, отключите многопользовательский режим, чтобы использовать эту функцию.",
configuration: "Настройка календаря Google",
deploymentId: "Идентификатор развертывания",
deploymentIdHelp:
"Идентификатор развертывания из вашего веб-приложения Google Apps Script",
apiKey: "Ключ API",
apiKeyHelp:
"Ключ API, который вы настроили в своей среде выполнения Google Apps Script",
configurationRequired:
"Пожалуйста, настройте идентификатор развертывания и API-ключ, чтобы активировать функциональность Google Calendar.",
configured: "Настроен",
searchSkills: "Навыки поиска...",
noSkillsFound: "Не найдено ни одного соответствующего запросу.",
categories: {
calendars: {
title: "Календари",
description:
"Просматривайте и управляйте своими календарями Google.",
},
readEvents: {
title: "Просмотр событий",
description: "Просмотр и поиск событий в календаре",
},
writeEvents: {
title: "Создание и обновление событий",
description:
"Создавайте новые мероприятия и изменяйте существующие.",
},
rsvp: {
title: "Управление RSVP (подтверждение участия)",
description: "Управляйте своим статусом участия в мероприятиях.",
},
},
skills: {
listCalendars: {
title: "Календари",
description:
"Перечислите все календари, которыми вы владеете или для которых у вас есть подписка.",
},
getCalendar: {
title: "Получить подробную информацию о календаре",
description:
"Получите подробную информацию о конкретном календаре.",
},
getEvent: {
title: "Узнать о мероприятии",
description:
"Получите подробную информацию о конкретном мероприятии.",
},
getEventsForDay: {
title: "Получите информацию о событиях на сегодня",
description:
"Получите список всех мероприятий, запланированных на конкретную дату.",
},
getEvents: {
title: "Получить события (период времени)",
description: "Получить события в указанном диапазоне дат",
},
getUpcomingEvents: {
title: "Получите информацию о предстоящих мероприятиях",
description:
"Получите информацию о событиях на сегодня, на этой неделе или в этом месяце, используя простые ключевые слова.",
},
quickAdd: {
title: "Быстрое добавление события",
description:
"Создать событие на основе естественного языка (например, «Встреча завтра в 15:00»)",
},
createEvent: {
title: "Создать мероприятие",
description:
"Создайте новое мероприятие с полным контролем над всеми его параметрами.",
},
updateEvent: {
title: "Обновление события",
description: "Обновить существующее событие в календаре",
},
setMyStatus: {
title: "Указать статус подтверждения участия",
description:
"Принять, отклонить или выразить предварительное согласие на мероприятие.",
},
},
},
},
mcp: {
title: "Серверы MCP",

View File

@ -639,6 +639,93 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google Takvim Bağlayıcı",
description:
"Ajantınızın Google Takvim ile etkileşim kurmasını sağlayın - takvimleri görüntüleyin, etkinlikleri alın, etkinlikleri oluşturun ve güncelleyin, ve katılımcıların yanıtlarını yönetin. Dokümantasyonu okuyun.",
multiUserWarning:
"Google Takvim entegrasyonu, güvenlik nedeniyle çoklu kullanıcı modunda kullanılabilmektedir. Bu özelliği kullanmak için lütfen çoklu kullanıcı modunu devre dışı bırakın.",
configuration: "Google Takvim Yapılandırması",
deploymentId: "Dağıtım Kimliği",
deploymentIdHelp:
"Google Apps Script web uygulamanızın dağıtım kimliği",
apiKey: "API Anahtarı",
apiKeyHelp:
"Google Apps Script dağıtımınızda yapılandırdığınız API anahtarı",
configurationRequired:
"Lütfen Dağıtım Kimliğini ve API Anahtarını yapılandırarak Google Takvim özelliklerini etkinleştirin.",
configured: "Yapılandırılmış",
searchSkills: "Arama becerileri...",
noSkillsFound:
"Arama sonuçlarınızda eşleşen herhangi bir beceri bulunmamaktadır.",
categories: {
calendars: {
title: "Takvimler",
description: "Google Takvimlerinizi görüntüleyin ve yönetin",
},
readEvents: {
title: "Etkinlikleri oku",
description: "Takvimdeki etkinlikleri görüntüleyin ve arayın",
},
writeEvents: {
title: "Etkinlikleri Oluştur ve Güncelle",
description:
"Yeni etkinlikler oluşturun ve mevcut olanları değiştirin.",
},
rsvp: {
title: "Katılım Yönetimi",
description: "Etkinliklere ilişkin yanıt durumunuzu yönetin",
},
},
skills: {
listCalendars: {
title: "Takvim Listeleri",
description:
"Sahip olduğunuz veya abonelik yaptığınız tüm takvimleri listeleyin.",
},
getCalendar: {
title: "Takvim Detaylarını Al",
description: "Belirli bir takvim hakkında ayrıntılı bilgi edinin.",
},
getEvent: {
title: "Etkinliği Bul",
description: "Belirli bir etkinlikle ilgili ayrıntılı bilgi edinin",
},
getEventsForDay: {
title: "Gün İçindeki Etkinlikleri Öğren",
description:
"Belirli bir güne ait tüm planlanan etkinlikleri görüntüleyin.",
},
getEvents: {
title: "Etkinlikleri (Tarih Aralığı) görüntüle",
description: "Belirli bir tarih aralığındaki etkinlikleri alın",
},
getUpcomingEvents: {
title: "Yaklaşan Etkinlikleri Görüntüleyin",
description:
"Bugün, bu hafta veya bu ay için etkinlikleri, basit anahtar kelimeler kullanarak bulun.",
},
quickAdd: {
title: "Hızlı Olay Ekle",
description:
'Doğal dilden bir etkinlik oluşturun (örneğin, "Yarın saat 15:00\'te bir toplantı")',
},
createEvent: {
title: "Etkinlik Oluştur",
description:
"Tüm özellikler üzerinde tam kontrol sağlayarak yeni bir etkinlik oluşturun.",
},
updateEvent: {
title: "Etkinlik Güncellemesi",
description: "Mevcut bir takvim olayını güncelleyin",
},
setMyStatus: {
title: "Davetiyeye Cevap Durumu Ayarla",
description:
"Bir etkinliğe katılımı kabul etmek, reddetmek veya geçici olarak katılmayı kabul etmek.",
},
},
},
},
mcp: {
title: "MCP Sunucuları",

View File

@ -625,6 +625,93 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Kết nối Google Calendar",
description:
"Cho phép đại lý của bạn tương tác với Google Calendar - xem lịch, lấy thông tin sự kiện, tạo và cập nhật sự kiện, và quản lý xác nhận tham dự. <a>Đọc tài liệu</a>.",
multiUserWarning:
"Tính năng tích hợp với Google Calendar không khả dụng ở chế độ nhiều người dùng vì lý do bảo mật. Vui lòng tắt chế độ nhiều người dùng để sử dụng tính năng này.",
configuration: "Cấu hình Google Calendar",
deploymentId: "Mã triển khai",
deploymentIdHelp:
"Mã định danh ứng dụng từ ứng dụng web Google Apps Script của bạn",
apiKey: "Khóa API",
apiKeyHelp:
"Khóa API mà bạn đã cấu hình trong quá trình triển khai Google Apps Script của mình.",
configurationRequired:
"Vui lòng cấu hình ID triển khai và khóa API để kích hoạt các tính năng của Google Calendar.",
configured: "Đã được cấu hình",
searchSkills: "Kỹ năng tìm kiếm...",
noSkillsFound:
"Không tìm thấy kết quả phù hợp với tiêu chí tìm kiếm của bạn.",
categories: {
calendars: {
title: "Lịch",
description: "Xem và quản lý lịch Google của bạn",
},
readEvents: {
title: "Xem sự kiện",
description: "Xem và tìm kiếm các sự kiện trong lịch",
},
writeEvents: {
title: "Tạo và cập nhật sự kiện",
description:
"Tạo các sự kiện mới và chỉnh sửa các sự kiện hiện có.",
},
rsvp: {
title: "Quản lý xác nhận tham dự",
description: "Quản lý trạng thái phản hồi của bạn cho các sự kiện",
},
},
skills: {
listCalendars: {
title: "Danh sách lịch",
description: "Liệt kê tất cả các lịch mà bạn sở hữu hoặc đăng ký",
},
getCalendar: {
title: "Lấy thông tin lịch",
description: "Lấy thông tin chi tiết về một lịch cụ thể",
},
getEvent: {
title: "Tìm sự kiện",
description: "Lấy thông tin chi tiết về một sự kiện cụ thể",
},
getEventsForDay: {
title: "Tìm các sự kiện cho ngày hôm nay",
description:
"Hiển thị tất cả các sự kiện được lên lịch cho một ngày cụ thể.",
},
getEvents: {
title: "Tìm sự kiện (khoảng thời gian)",
description:
"Lấy danh sách các sự kiện trong một khoảng thời gian tùy chỉnh.",
},
getUpcomingEvents: {
title: "Xem các sự kiện sắp tới",
description:
"Tìm kiếm các sự kiện diễn ra hôm nay, tuần này hoặc tháng này bằng cách sử dụng các từ khóa đơn giản.",
},
quickAdd: {
title: "Thêm sự kiện nhanh chóng",
description:
'Tạo một sự kiện từ ngôn ngữ tự nhiên (ví dụ: "Cuộc họp vào ngày mai lúc 3 giờ chiều")',
},
createEvent: {
title: "Tạo sự kiện",
description:
"Tạo một sự kiện mới với quyền kiểm soát hoàn toàn đối với tất cả các thuộc tính.",
},
updateEvent: {
title: "Cập nhật sự kiện",
description: "Cập nhật một sự kiện đã có trong lịch",
},
setMyStatus: {
title: "Đặt trạng thái xác nhận tham dự",
description:
"Chấp nhận, từ chối hoặc chấp nhận một sự kiện một cách tạm thời.",
},
},
},
},
mcp: {
title: "Máy chủ MCP",

View File

@ -597,6 +597,83 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google 日历连接器",
description:
"让您的代理能够与 Google 日历互动:查看日历、获取活动、创建和更新活动,以及管理确认回复。请参考相关文档。",
multiUserWarning:
"由于安全原因,在多用户模式下无法使用 Google 日历集成功能。请先禁用多用户模式,然后再使用此功能。",
configuration: "谷歌日历配置",
deploymentId: "部署ID",
deploymentIdHelp: "您的 Google Apps Script 网页应用的部署 ID",
apiKey: "API 密钥",
apiKeyHelp: "您在 Google Apps Script 部署中配置的 API 密钥。",
configurationRequired:
"请配置部署 ID 和 API 密钥,以启用 Google 日历功能。",
configured: "已配置",
searchSkills: "搜索技巧...",
noSkillsFound: "未找到与您搜索条件匹配的技能。",
categories: {
calendars: {
title: "日历",
description: "查看和管理您的 Google 日历",
},
readEvents: {
title: "查看活动",
description: "查看和搜索日历活动",
},
writeEvents: {
title: "创建和更新活动",
description: "创建新的活动,并修改现有的活动。",
},
rsvp: {
title: "请回复确认",
description: "管理您对活动的响应状态",
},
},
skills: {
listCalendars: {
title: "日历列表",
description: "列出您拥有的或订阅的全部日历。",
},
getCalendar: {
title: "获取日历详情",
description: "获取有关特定日历的详细信息",
},
getEvent: {
title: "获取活动",
description: "获取有关特定活动的详细信息",
},
getEventsForDay: {
title: "获取当日活动",
description: "获取指定日期的所有活动",
},
getEvents: {
title: "获取活动(日期范围)",
description: "获取指定日期范围内的活动",
},
getUpcomingEvents: {
title: "查看即将举办的活动",
description: "使用简单的关键词,查找今天、本周或本月的活动",
},
quickAdd: {
title: "快速添加活动",
description: "从自然语言例如“明天下午3点开会”创建一个活动。",
},
createEvent: {
title: "创建活动",
description: "创建一个新的活动,并完全控制所有属性。",
},
updateEvent: {
title: "活动更新",
description: "更新现有的日历事件",
},
setMyStatus: {
title: "设置回复状态",
description: "接受、拒绝或表示初步接受某个活动",
},
},
},
},
mcp: {
title: "MCP 服务器",

View File

@ -587,6 +587,84 @@ const TRANSLATIONS = {
},
},
},
googleCalendar: {
title: "Google 日曆連線",
description:
"讓您的代理能夠與 Google 日曆互動:查看日曆、取得活動資訊、創建和更新活動,以及管理確認出席。 詳情請參考<a>文件</a>。",
multiUserWarning:
"由於安全原因Google 日曆的整合功能在多使用者模式下無法使用。請先停用多使用者模式,然後再使用此功能。",
configuration: "Google 日曆設定",
deploymentId: "部署 ID",
deploymentIdHelp: "您的 Google Apps Script 網頁應用程式的部署 ID",
apiKey: "API 關鍵字",
apiKeyHelp: "您在 Google Apps Script 部署中設定的 API 金鑰。",
configurationRequired:
"請設定部署 ID 和 API 鑰,以啟用 Google 日曆功能。",
configured: "已設定",
searchSkills: "搜尋技巧...",
noSkillsFound: "沒有符合您搜尋條件的結果。",
categories: {
calendars: {
title: "日曆",
description: "檢視和管理您的 Google 日曆",
},
readEvents: {
title: "閱讀活動",
description: "查看和搜尋日曆活動",
},
writeEvents: {
title: "建立與更新活動",
description: "創建新的活動,並修改現有的活動。",
},
rsvp: {
title: "請假確認管理",
description: "管理您參加活動的回應狀態",
},
},
skills: {
listCalendars: {
title: "日曆清單",
description: "列出您擁有的或訂閱的全部日曆",
},
getCalendar: {
title: "獲取日曆細節",
description: "獲取有關特定日曆的詳細資訊",
},
getEvent: {
title: "取得活動",
description: "獲取有關特定活動的詳細資訊",
},
getEventsForDay: {
title: "獲取特定日期的活動",
description: "列出特定日期的所有活動",
},
getEvents: {
title: "取得活動(日期範圍)",
description: "取得指定日期範圍內的活動",
},
getUpcomingEvents: {
title: "查看即將到來的活動",
description: "使用簡單的關鍵字,即可查詢今日、本週或本月的活動",
},
quickAdd: {
title: "快速新增活動",
description:
"從自然語言(例如:「明天下午 3 點舉行會議」)創建活動。",
},
createEvent: {
title: "建立活動",
description: "創建一個新的活動,並擁有對所有屬性的完全控制。",
},
updateEvent: {
title: "活動更新",
description: "更新現有的日曆事件",
},
setMyStatus: {
title: "設定確認參加狀態",
description: "接受、拒絕或表示暫時接受活動",
},
},
},
},
mcp: {
title: "MCP 伺服器",

View File

@ -1,22 +0,0 @@
import { API_BASE } from "@/utils/constants";
import { baseHeaders } from "@/utils/request";
const GmailAgent = {
/**
* Get the current configuration status for Gmail.
* @returns {Promise<{success: boolean, isConfigured?: boolean, config?: {deploymentId: string, apiKey: string}, error?: string}>}
*/
getStatus: async () => {
return await fetch(`${API_BASE}/admin/agent-skills/gmail/status`, {
method: "GET",
headers: baseHeaders(),
})
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
};
export default GmailAgent;

View File

@ -0,0 +1,45 @@
import { API_BASE } from "@/utils/constants";
import { baseHeaders } from "@/utils/request";
const GoogleAgentSkills = {
gmail: {
/**
* Get the current configuration status for Gmail.
* @returns {Promise<{success: boolean, isConfigured?: boolean, config?: {deploymentId: string, apiKey: string}, error?: string}>}
*/
getStatus: async () => {
return await fetch(`${API_BASE}/admin/agent-skills/gmail/status`, {
method: "GET",
headers: baseHeaders(),
})
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
},
calendar: {
/**
* Get the current configuration status for Google Calendar.
* @returns {Promise<{success: boolean, isConfigured?: boolean, config?: {deploymentId: string, apiKey: string}, error?: string}>}
*/
getStatus: async () => {
return await fetch(
`${API_BASE}/admin/agent-skills/google-calendar/status`,
{
method: "GET",
headers: baseHeaders(),
}
)
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
},
};
export default GoogleAgentSkills;

View File

@ -19,7 +19,7 @@ import {
import GMailIcon from "./gmail.png";
import Admin from "@/models/admin";
import System from "@/models/system";
import GmailAgent from "@/models/gmailAgent";
import GoogleAgentSkills from "@/models/googleAgentSkills";
import { getGmailSkills, filterSkillCategories } from "./utils";
import { Tooltip } from "react-tooltip";
import { Link } from "react-router-dom";
@ -49,7 +49,7 @@ export default function GMailSkillPanel({
Promise.all([
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
System.keys(),
GmailAgent.getStatus(),
GoogleAgentSkills.gmail.getStatus(),
])
.then(([prefsRes, settingsRes, statusRes]) => {
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);
@ -75,7 +75,7 @@ export default function GMailSkillPanel({
if (prevHasChanges.current === true && hasChanges === false) {
Promise.all([
Admin.systemPreferencesByFields(["disabled_gmail_skills"]),
GmailAgent.getStatus(),
GoogleAgentSkills.gmail.getStatus(),
])
.then(([prefsRes, statusRes]) => {
setDisabledSkills(prefsRes?.settings?.disabled_gmail_skills ?? []);

View File

@ -5,9 +5,7 @@ import {
ChartBar,
PencilSimple,
} from "@phosphor-icons/react";
import strDistance from "js-levenshtein";
const LEVENSHTEIN_THRESHOLD = 3;
export { filterSkillCategories } from "../utils";
export const getGmailSkills = (t) => ({
search: {
@ -136,33 +134,3 @@ export const getGmailSkills = (t) => ({
],
},
});
function skillMatchesSearch(skill, searchTerm) {
if (!searchTerm) return true;
const normalizedSearch = searchTerm.toLowerCase().trim();
const titleLower = skill.title.toLowerCase();
const descLower = skill.description.toLowerCase();
if (titleLower.includes(normalizedSearch)) return true;
if (descLower.includes(normalizedSearch)) return true;
if (strDistance(titleLower, normalizedSearch) <= LEVENSHTEIN_THRESHOLD)
return true;
return false;
}
export function filterSkillCategories(skillCategories, searchTerm) {
if (!searchTerm) return skillCategories;
const filtered = {};
for (const [key, category] of Object.entries(skillCategories)) {
const matchingSkills = category.skills.filter((skill) =>
skillMatchesSearch(skill, searchTerm)
);
if (matchingSkills.length > 0) {
filtered[key] = { ...category, skills: matchingSkills };
}
}
return filtered;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,457 @@
import React, {
useEffect,
useState,
useRef,
useMemo,
useCallback,
} from "react";
import Toggle, { SimpleToggleSwitch } from "@/components/lib/Toggle";
import { Trans, useTranslation } from "react-i18next";
import debounce from "lodash.debounce";
import {
MagnifyingGlass,
CircleNotch,
Warning,
CaretDown,
CheckCircle,
Info,
} from "@phosphor-icons/react";
import Admin from "@/models/admin";
import System from "@/models/system";
import GoogleAgentSkills from "@/models/googleAgentSkills";
import { getGoogleCalendarSkills, filterSkillCategories } from "./utils";
import { Tooltip } from "react-tooltip";
import { Link } from "react-router-dom";
import paths from "@/utils/paths";
import GoogleCalendarIcon from "./google-calendar.png";
export default function GoogleCalendarSkillPanel({
title,
skill,
toggleSkill,
enabled = false,
disabled = false,
setHasChanges,
hasChanges = false,
}) {
const { t } = useTranslation();
const [disabledSkills, setDisabledSkills] = useState([]);
const [loading, setLoading] = useState(true);
const [deploymentId, setDeploymentId] = useState("");
const [apiKey, setApiKey] = useState("");
const [isMultiUserMode, setIsMultiUserMode] = useState(false);
const [configDefaultExpanded, setConfigDefaultExpanded] = useState(true);
const prevHasChanges = useRef(hasChanges);
const skillCategories = getGoogleCalendarSkills(t);
useEffect(() => {
setLoading(true);
Promise.all([
Admin.systemPreferencesByFields(["disabled_google_calendar_skills"]),
System.keys(),
GoogleAgentSkills.calendar.getStatus(),
])
.then(([prefsRes, settingsRes, statusRes]) => {
setDisabledSkills(
prefsRes?.settings?.disabled_google_calendar_skills ?? []
);
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
if (statusRes?.success && statusRes.config) {
const loadedDeploymentId = statusRes.config.deploymentId || "";
const loadedApiKey = statusRes.config.apiKey || "";
setDeploymentId(loadedDeploymentId);
setApiKey(loadedApiKey);
setConfigDefaultExpanded(!(loadedDeploymentId && loadedApiKey));
}
})
.catch(() => {
setDisabledSkills([]);
setDeploymentId("");
setApiKey("");
})
.finally(() => setLoading(false));
}, []);
useEffect(() => {
if (prevHasChanges.current === true && hasChanges === false) {
Promise.all([
Admin.systemPreferencesByFields(["disabled_google_calendar_skills"]),
GoogleAgentSkills.calendar.getStatus(),
])
.then(([prefsRes, statusRes]) => {
setDisabledSkills(
prefsRes?.settings?.disabled_google_calendar_skills ?? []
);
if (statusRes?.success && statusRes.config) {
setDeploymentId(statusRes.config.deploymentId || "");
setApiKey(statusRes.config.apiKey || "");
}
})
.catch(() => {});
}
prevHasChanges.current = hasChanges;
}, [hasChanges]);
function toggleGoogleCalendarSkill(skillName) {
setHasChanges(true);
setDisabledSkills((prev) =>
prev.includes(skillName)
? prev.filter((s) => s !== skillName)
: [...prev, skillName]
);
}
const isConfigured = deploymentId && apiKey;
return (
<div className="p-2">
<div className="flex flex-col gap-y-[18px] max-w-[500px]">
<div className="flex w-full justify-between items-center">
<div className="flex items-center gap-x-2">
<img
src={GoogleCalendarIcon}
alt="Google Calendar"
width={24}
height={24}
/>
<label className="text-theme-text-primary text-md font-bold">
{title}
</label>
</div>
<Toggle
size="lg"
enabled={enabled}
disabled={disabled || isMultiUserMode}
onChange={() => toggleSkill(skill)}
/>
</div>
{isMultiUserMode && (
<div className="flex items-center gap-x-2 p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-lg">
<Warning size={20} className="text-yellow-500 shrink-0" />
<p className="text-yellow-500 text-xs">
{t("agent.skill.googleCalendar.multiUserWarning")}
</p>
</div>
)}
<p className="text-theme-text-secondary text-opacity-60 text-xs font-medium">
<Trans
i18nKey="agent.skill.googleCalendar.description"
components={{
a: (
<Link
className="text-sky-400 hover:text-sky-500 text-xs font-medium underline"
to={paths.docs("/agent/usage/google-calendar-agent")}
target="_blank"
/>
),
}}
/>
</p>
{enabled && !isMultiUserMode && (
<>
<HiddenFormInputs
disabledSkills={disabledSkills}
deploymentId={deploymentId}
apiKey={apiKey}
/>
{loading ? (
<div className="flex items-center justify-center py-4">
<CircleNotch
size={24}
className="animate-spin text-theme-text-primary"
/>
</div>
) : (
<>
<ConfigurationSection
deploymentId={deploymentId}
setDeploymentId={setDeploymentId}
apiKey={apiKey}
setApiKey={setApiKey}
setHasChanges={setHasChanges}
isConfigured={isConfigured}
defaultExpanded={configDefaultExpanded}
/>
{isConfigured && (
<SkillsSection
skillCategories={skillCategories}
disabledSkills={disabledSkills}
onToggle={toggleGoogleCalendarSkill}
/>
)}
</>
)}
</>
)}
</div>
</div>
);
}
function ConfigurationSection({
deploymentId,
setDeploymentId,
apiKey,
setApiKey,
setHasChanges,
isConfigured,
defaultExpanded = true,
}) {
const { t } = useTranslation();
const [expanded, setExpanded] = useState(defaultExpanded);
return (
<div className="border border-theme-sidebar-border/50 rounded-lg overflow-hidden mt-2">
<button
type="button"
onClick={() => setExpanded(!expanded)}
className="border-none w-full flex items-center justify-between p-3 bg-theme-bg-secondary/30 hover:bg-theme-bg-secondary/50 transition-colors"
>
<div className="flex items-center gap-x-2">
<span className="text-theme-text-primary font-semibold text-sm">
{t("agent.skill.googleCalendar.configuration")}
</span>
{isConfigured && (
<div className="flex items-center gap-x-1">
<CheckCircle size={14} weight="fill" className="text-green-500" />
<span className="text-xs text-green-500">
{t("agent.skill.googleCalendar.configured")}
</span>
</div>
)}
</div>
<CaretDown
size={16}
className={`text-theme-text-secondary transition-transform ${expanded ? "rotate-180" : ""}`}
/>
</button>
{expanded && (
<div className="p-3 flex flex-col gap-y-4 border-t border-theme-sidebar-border/50">
<div className="flex flex-col gap-y-2">
<div className="flex items-center gap-x-2">
<label className="text-theme-text-primary text-sm font-medium">
{t("agent.skill.googleCalendar.deploymentId")}
</label>
<Info
data-tooltip-id="gcal-deployment-id-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="gcal-deployment-id-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100"
>
{t("agent.skill.googleCalendar.deploymentIdHelp")}
</Tooltip>
</div>
<input
type="text"
value={deploymentId}
onChange={(e) => {
setDeploymentId(e.target.value);
setHasChanges(true);
}}
placeholder="AKfycb..."
className="w-full px-3 py-2 bg-theme-bg-primary border border-theme-sidebar-border rounded-lg text-theme-text-primary text-sm placeholder:text-theme-text-secondary/50"
/>
</div>
<div className="flex flex-col gap-y-2">
<div className="flex items-center gap-x-2">
<label className="text-theme-text-primary text-sm font-medium">
{t("agent.skill.googleCalendar.apiKey")}
</label>
<Info
data-tooltip-id="gcal-api-key-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="gcal-api-key-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100"
>
{t("agent.skill.googleCalendar.apiKeyHelp")}
</Tooltip>
</div>
<input
type="password"
value={apiKey}
onChange={(e) => {
setApiKey(e.target.value);
setHasChanges(true);
}}
placeholder="Your API key..."
className="w-full px-3 py-2 bg-theme-bg-primary border border-theme-sidebar-border rounded-lg text-theme-text-primary text-sm placeholder:text-theme-text-secondary/50"
/>
</div>
{!isConfigured && (
<div className="flex items-center gap-x-2 p-3 bg-orange-500/10 border border-orange-500/30 rounded-lg">
<Warning size={20} className="text-orange-500 shrink-0" />
<p className="text-orange-500 text-xs">
{t("agent.skill.googleCalendar.configurationRequired")}
</p>
</div>
)}
</div>
)}
</div>
);
}
function SkillSearchInput({ onSearch }) {
const { t } = useTranslation();
const inputRef = useRef(null);
const debouncedSearch = useMemo(
() =>
debounce((value) => {
onSearch(value);
}, 300),
[onSearch]
);
useEffect(() => {
return () => {
debouncedSearch.cancel();
};
}, [debouncedSearch]);
const handleChange = (e) => {
debouncedSearch(e.target.value);
};
return (
<div className="relative">
<input
ref={inputRef}
type="search"
placeholder={t("agent.skill.googleCalendar.searchSkills")}
onChange={handleChange}
className="w-full pl-9 pr-3 py-2 bg-theme-bg-primary border border-theme-sidebar-border rounded-lg text-theme-text-primary text-sm placeholder:text-theme-text-secondary/50 search-input"
/>
<MagnifyingGlass
size={16}
className="absolute left-3 top-1/2 -translate-y-1/2 text-theme-text-secondary"
weight="bold"
/>
</div>
);
}
function SkillsSection({ skillCategories, disabledSkills, onToggle }) {
const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState("");
const handleSearch = useCallback((value) => {
setSearchTerm(value);
}, []);
const filteredCategories = useMemo(
() => filterSkillCategories(skillCategories, searchTerm),
[skillCategories, searchTerm]
);
const hasResults = Object.keys(filteredCategories).length > 0;
return (
<div className="flex flex-col mt-4 gap-y-4">
<SkillSearchInput onSearch={handleSearch} />
{hasResults ? (
<div className="flex flex-col gap-y-4">
{Object.entries(filteredCategories).map(([categoryKey, category]) => (
<CategorySection
key={categoryKey}
category={category}
disabledSkills={disabledSkills}
onToggle={onToggle}
/>
))}
</div>
) : (
<p className="text-theme-text-secondary text-sm text-center py-4">
{t("agent.skill.googleCalendar.noSkillsFound")}
</p>
)}
</div>
);
}
function CategorySection({ category, disabledSkills, onToggle }) {
const Icon = category.icon;
return (
<div className="flex flex-col gap-y-2">
<div className="flex items-center gap-x-2 px-1">
<Icon size={18} className="text-theme-text-primary" />
<span className="text-sm font-medium text-theme-text-primary">
{category.title}
</span>
</div>
<div className="flex flex-col gap-y-2">
{category.skills.map((skill) => (
<SkillRow
key={skill.name}
skill={skill}
disabled={disabledSkills.includes(skill.name)}
onToggle={() => onToggle(skill.name)}
/>
))}
</div>
</div>
);
}
function SkillRow({ skill, disabled, onToggle }) {
return (
<div
className={`flex items-center justify-between p-2 rounded-lg border ${
disabled
? "bg-theme-bg-secondary/30 border-theme-sidebar-border/30"
: "bg-theme-bg-secondary/50 border-theme-sidebar-border/50"
}`}
>
<div className="flex flex-col">
<span className="text-sm font-medium text-slate-100 light:text-slate-900">
{skill.title}
</span>
<span className="text-xs text-slate-100/50 light:text-slate-900/50">
{skill.description}
</span>
</div>
<SimpleToggleSwitch enabled={!disabled} onChange={onToggle} size="md" />
</div>
);
}
function HiddenFormInputs({ disabledSkills, deploymentId, apiKey }) {
const configJson = JSON.stringify({
deploymentId: deploymentId || "",
apiKey: apiKey || "",
});
return (
<>
<input
name="system::disabled_google_calendar_skills"
type="hidden"
value={disabledSkills.join(",")}
/>
<input
name="system::google_calendar_agent_config"
type="hidden"
value={configJson}
/>
</>
);
}

View File

@ -0,0 +1,114 @@
import {
CalendarBlank,
CalendarCheck,
CalendarPlus,
UserCircleGear,
} from "@phosphor-icons/react";
export { filterSkillCategories } from "../utils";
export const getGoogleCalendarSkills = (t) => ({
calendars: {
title: t("agent.skill.googleCalendar.categories.calendars.title"),
description: t(
"agent.skill.googleCalendar.categories.calendars.description"
),
icon: CalendarBlank,
skills: [
{
name: "gcal-list-calendars",
title: t("agent.skill.googleCalendar.skills.listCalendars.title"),
description: t(
"agent.skill.googleCalendar.skills.listCalendars.description"
),
},
{
name: "gcal-get-calendar",
title: t("agent.skill.googleCalendar.skills.getCalendar.title"),
description: t(
"agent.skill.googleCalendar.skills.getCalendar.description"
),
},
],
},
readEvents: {
title: t("agent.skill.googleCalendar.categories.readEvents.title"),
description: t(
"agent.skill.googleCalendar.categories.readEvents.description"
),
icon: CalendarCheck,
skills: [
{
name: "gcal-get-event",
title: t("agent.skill.googleCalendar.skills.getEvent.title"),
description: t(
"agent.skill.googleCalendar.skills.getEvent.description"
),
},
{
name: "gcal-get-events-for-day",
title: t("agent.skill.googleCalendar.skills.getEventsForDay.title"),
description: t(
"agent.skill.googleCalendar.skills.getEventsForDay.description"
),
},
{
name: "gcal-get-events",
title: t("agent.skill.googleCalendar.skills.getEvents.title"),
description: t(
"agent.skill.googleCalendar.skills.getEvents.description"
),
},
{
name: "gcal-get-upcoming-events",
title: t("agent.skill.googleCalendar.skills.getUpcomingEvents.title"),
description: t(
"agent.skill.googleCalendar.skills.getUpcomingEvents.description"
),
},
],
},
writeEvents: {
title: t("agent.skill.googleCalendar.categories.writeEvents.title"),
description: t(
"agent.skill.googleCalendar.categories.writeEvents.description"
),
icon: CalendarPlus,
skills: [
{
name: "gcal-quick-add",
title: t("agent.skill.googleCalendar.skills.quickAdd.title"),
description: t(
"agent.skill.googleCalendar.skills.quickAdd.description"
),
},
{
name: "gcal-create-event",
title: t("agent.skill.googleCalendar.skills.createEvent.title"),
description: t(
"agent.skill.googleCalendar.skills.createEvent.description"
),
},
{
name: "gcal-update-event",
title: t("agent.skill.googleCalendar.skills.updateEvent.title"),
description: t(
"agent.skill.googleCalendar.skills.updateEvent.description"
),
},
],
},
rsvp: {
title: t("agent.skill.googleCalendar.categories.rsvp.title"),
description: t("agent.skill.googleCalendar.categories.rsvp.description"),
icon: UserCircleGear,
skills: [
{
name: "gcal-set-my-status",
title: t("agent.skill.googleCalendar.skills.setMyStatus.title"),
description: t(
"agent.skill.googleCalendar.skills.setMyStatus.description"
),
},
],
},
});

View File

@ -4,9 +4,7 @@ import {
ChartBar,
PencilSimple,
} from "@phosphor-icons/react";
import strDistance from "js-levenshtein";
const LEVENSHTEIN_THRESHOLD = 3;
export { filterSkillCategories } from "../utils";
export const getOutlookSkills = (t) => ({
search: {
@ -90,33 +88,3 @@ export const getOutlookSkills = (t) => ({
],
},
});
function skillMatchesSearch(skill, searchTerm) {
if (!searchTerm) return true;
const normalizedSearch = searchTerm.toLowerCase().trim();
const titleLower = skill.title.toLowerCase();
const descLower = skill.description.toLowerCase();
if (titleLower.includes(normalizedSearch)) return true;
if (descLower.includes(normalizedSearch)) return true;
if (strDistance(titleLower, normalizedSearch) <= LEVENSHTEIN_THRESHOLD)
return true;
return false;
}
export function filterSkillCategories(skillCategories, searchTerm) {
if (!searchTerm) return skillCategories;
const filtered = {};
for (const [key, category] of Object.entries(skillCategories)) {
const matchingSkills = category.skills.filter((skill) =>
skillMatchesSearch(skill, searchTerm)
);
if (matchingSkills.length > 0) {
filtered[key] = { ...category, skills: matchingSkills };
}
}
return filtered;
}

View File

@ -5,6 +5,7 @@ import DefaultSkillPanel from "./DefaultSkillPanel";
import FileSystemSkillPanel from "./FileSystemSkillPanel";
import CreateFileSkillPanel from "./CreateFileSkillPanel";
import GMailSkillPanel from "./GMailSkillPanel";
import GoogleCalendarSkillPanel from "./GoogleCalendarSkillPanel";
import OutlookSkillPanel from "./OutlookSkillPanel";
import {
Brain,
@ -22,6 +23,7 @@ import GenerateSaveImages from "@/media/agents/generate-save-files.png";
import FileSystemImage from "@/media/agents/file-system.png";
import GMailIcon from "./GMailSkillPanel/gmail.png";
import OutlookIcon from "./OutlookSkillPanel/outlook.png";
import GoogleCalendarIcon from "./GoogleCalendarSkillPanel/google-calendar.png";
export const getDefaultSkills = (t) => ({
"rag-memory": {
@ -107,6 +109,21 @@ export const getAppIntegrationSkills = (t) => ({
),
mode: ["singleUserOnly"],
},
"google-calendar-agent": {
title: t("agent.skill.googleCalendar.title"),
description: t("agent.skill.googleCalendar.description"),
component: GoogleCalendarSkillPanel,
skill: "google-calendar-agent",
Icon: ({ size }) => (
<img
src={GoogleCalendarIcon}
alt="Google Calendar"
width={size}
height={size}
/>
),
mode: ["singleUserOnly"],
},
"outlook-agent": {
title: t("agent.skill.outlook.title"),
description: t("agent.skill.outlook.description"),

View File

@ -0,0 +1,33 @@
import strDistance from "js-levenshtein";
const LEVENSHTEIN_THRESHOLD = 3;
function skillMatchesSearch(skill, searchTerm) {
if (!searchTerm) return true;
const normalizedSearch = searchTerm.toLowerCase().trim();
const titleLower = skill.title.toLowerCase();
const descLower = skill.description.toLowerCase();
if (titleLower.includes(normalizedSearch)) return true;
if (descLower.includes(normalizedSearch)) return true;
if (strDistance(titleLower, normalizedSearch) <= LEVENSHTEIN_THRESHOLD)
return true;
return false;
}
export function filterSkillCategories(skillCategories, searchTerm) {
if (!searchTerm) return skillCategories;
const filtered = {};
for (const [key, category] of Object.entries(skillCategories)) {
const matchingSkills = category.skills.filter((skill) =>
skillMatchesSearch(skill, searchTerm)
);
if (matchingSkills.length > 0) {
filtered[key] = { ...category, skills: matchingSkills };
}
}
return filtered;
}

View File

@ -3,8 +3,11 @@ const {
} = require("../../utils/middleware/multiUserProtected");
const { validatedRequest } = require("../../utils/middleware/validatedRequest");
const { GmailBridge } = require("../../utils/agents/aibitat/plugins/gmail/lib");
const {
GoogleCalendarBridge,
} = require("../../utils/agents/aibitat/plugins/google-calendar/lib");
function gmailAgentEndpoints(app) {
function googleAgentSkillEndpoints(app) {
if (!app) return;
app.get(
@ -34,6 +37,34 @@ function gmailAgentEndpoints(app) {
}
}
);
app.get(
"/admin/agent-skills/google-calendar/status",
[validatedRequest, isSingleUserMode],
async (_request, response) => {
try {
const config = await GoogleCalendarBridge.getConfig();
const hasDeploymentId = !!config.deploymentId;
const hasApiKey = !!config.apiKey;
const isConfigured = hasDeploymentId && hasApiKey;
const safeConfig = {
deploymentId: config.deploymentId || "",
apiKey: hasApiKey ? "********" : "",
};
return response.status(200).json({
success: true,
isConfigured,
config: safeConfig,
});
} catch (e) {
console.error("Google Calendar status error:", e);
response.status(500).json({ success: false, error: e.message });
}
}
);
}
module.exports = { gmailAgentEndpoints };
module.exports = { googleAgentSkillEndpoints };

View File

@ -38,7 +38,9 @@ const { telegramEndpoints } = require("./endpoints/telegram");
const {
outlookAgentEndpoints,
} = require("./endpoints/utils/outlookAgentUtils");
const { gmailAgentEndpoints } = require("./endpoints/utils/gmailAgentUtils");
const {
googleAgentSkillEndpoints,
} = require("./endpoints/utils/googleAgentSkillEndpoints");
const { httpLogger } = require("./middleware/httpLogger");
const app = express();
const apiRouter = express.Router();
@ -94,7 +96,7 @@ mobileEndpoints(apiRouter);
webPushEndpoints(apiRouter);
telegramEndpoints(apiRouter);
outlookAgentEndpoints(apiRouter);
gmailAgentEndpoints(apiRouter);
googleAgentSkillEndpoints(apiRouter);
// Externally facing embedder endpoints
embeddedEndpoints(apiRouter);

View File

@ -52,6 +52,8 @@ const SystemSettings = {
"disabled_create_files_skills",
"disabled_gmail_skills",
"gmail_agent_config",
"disabled_google_calendar_skills",
"google_calendar_agent_config",
"disabled_outlook_skills",
"outlook_agent_config",
"imported_agent_skills",
@ -75,6 +77,8 @@ const SystemSettings = {
"disabled_create_files_skills",
"disabled_gmail_skills",
"gmail_agent_config",
"disabled_google_calendar_skills",
"google_calendar_agent_config",
"disabled_outlook_skills",
"outlook_agent_config",
"agent_sql_connections",
@ -236,6 +240,49 @@ const SystemSettings = {
GmailBridge.reset();
}
},
disabled_google_calendar_skills: (updates) => {
try {
const skills = updates.split(",").filter((skill) => !!skill);
return JSON.stringify(skills);
} catch {
console.error(`Could not validate disabled google calendar skills.`);
return JSON.stringify([]);
}
},
google_calendar_agent_config: async (update) => {
const GoogleCalendarBridge = require("../utils/agents/aibitat/plugins/google-calendar/lib");
try {
if (!update) return JSON.stringify({});
const newConfig =
typeof update === "string" ? safeJsonParse(update, {}) : update;
const existingConfig = safeJsonParse(
(await SystemSettings.get({ label: "google_calendar_agent_config" }))
?.value,
{}
);
const mergedConfig = { ...existingConfig };
mergeStringField(mergedConfig, newConfig, "deploymentId");
mergeStringField(
mergedConfig,
newConfig,
"apiKey",
(v) => !v.match(/^\*+$/)
);
return JSON.stringify(mergedConfig);
} catch (e) {
console.error(
`Could not validate google calendar agent config:`,
e.message
);
return JSON.stringify({});
} finally {
GoogleCalendarBridge.reset();
}
},
disabled_outlook_skills: (updates) => {
try {
const skills = updates.split(",").filter((skill) => !!skill);

View File

@ -0,0 +1,79 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalGetCalendar = {
name: "gcal-get-calendar",
plugin: function () {
return {
name: "gcal-get-calendar",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get detailed information about a specific Google Calendar by its ID. " +
"Returns calendar name, description, time zone, and settings.",
examples: [
{
prompt: "Get details for my work calendar",
call: JSON.stringify({
calendarId: "work@group.calendar.google.com",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
calendarId: {
type: "string",
description:
"The calendar ID. If omitted, returns the primary calendar.",
},
},
additionalProperties: false,
},
handler: async function ({ calendarId }) {
try {
this.super.handlerProps.log(`Using the gcal-get-calendar tool.`);
this.super.introspect(
`${this.caller}: Fetching calendar details${calendarId ? ` for ${calendarId}` : " for primary calendar"}...`
);
const result = await googleCalendarLib.getCalendar(calendarId);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get calendar - ${result.error}`
);
return `Error getting calendar: ${result.error}`;
}
const cal = result.data;
this.super.introspect(
`${this.caller}: Retrieved calendar "${cal.name}"`
);
return (
`Calendar Details:\n` +
`Name: ${cal.name}\n` +
`ID: ${cal.calendarId}\n` +
`Description: ${cal.description || "(none)"}\n` +
`Time Zone: ${cal.timeZone}\n` +
`Primary: ${cal.isPrimary ? "Yes" : "No"}\n` +
`Owned by me: ${cal.isOwnedByMe ? "Yes" : "No"}\n` +
`Hidden: ${cal.isHidden ? "Yes" : "No"}\n` +
`Selected: ${cal.isSelected ? "Yes" : "No"}`
);
} catch (e) {
this.super.handlerProps.log(
`gcal-get-calendar error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error getting calendar: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,82 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalListCalendars = {
name: "gcal-list-calendars",
plugin: function () {
return {
name: "gcal-list-calendars",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"List all Google Calendars the user owns or is subscribed to. " +
"Returns calendar names, IDs, time zones, and ownership information. " +
"Use this to discover available calendars before querying events.",
examples: [
{
prompt: "What calendars do I have?",
call: JSON.stringify({}),
},
{
prompt: "Show me all my Google Calendars",
call: JSON.stringify({}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {},
additionalProperties: false,
},
handler: async function () {
try {
this.super.handlerProps.log(
`Using the gcal-list-calendars tool.`
);
this.super.introspect(
`${this.caller}: Fetching list of Google Calendars...`
);
const result = await googleCalendarLib.listCalendars();
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to list calendars - ${result.error}`
);
return `Error listing calendars: ${result.error}`;
}
const { totalCalendars, calendars } = result.data;
this.super.introspect(
`${this.caller}: Found ${totalCalendars} calendar(s)`
);
if (totalCalendars === 0) {
return "No calendars found.";
}
const summary = calendars
.map(
(cal, i) =>
`${i + 1}. "${cal.name}"${cal.isPrimary ? " (Primary)" : ""}\n` +
` ID: ${cal.calendarId}\n` +
` Time Zone: ${cal.timeZone}\n` +
` Owned by me: ${cal.isOwnedByMe ? "Yes" : "No"}`
)
.join("\n\n");
return `Found ${totalCalendars} calendar(s):\n\n${summary}`;
} catch (e) {
this.super.handlerProps.log(
`gcal-list-calendars error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error listing calendars: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,233 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalCreateEvent = {
name: "gcal-create-event",
plugin: function () {
return {
name: "gcal-create-event",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Create a calendar event with full control over all event properties. " +
"Supports timed events, all-day events, and recurring events. " +
"For simple events, consider using gcal-quick-add instead.",
examples: [
{
prompt:
"Create a meeting called 'Team Standup' tomorrow from 9am to 9:30am",
call: JSON.stringify({
title: "Team Standup",
startTime: "2025-01-16T09:00:00",
endTime: "2025-01-16T09:30:00",
}),
},
{
prompt: "Create an all-day event for my birthday on March 15th",
call: JSON.stringify({
title: "My Birthday",
allDay: true,
date: "2025-03-15",
}),
},
{
prompt: "Create a weekly team meeting every Monday at 10am",
call: JSON.stringify({
title: "Weekly Team Meeting",
startTime: "2025-01-20T10:00:00",
endTime: "2025-01-20T11:00:00",
recurrence: {
frequency: "weekly",
daysOfWeek: ["MONDAY"],
},
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
title: {
type: "string",
description: "The event title.",
},
startTime: {
type: "string",
description:
"Start time in ISO datetime format (for timed events).",
},
endTime: {
type: "string",
description:
"End time in ISO datetime format (for timed events).",
},
allDay: {
type: "boolean",
description: "Set to true for all-day events.",
},
date: {
type: "string",
description:
"Date in YYYY-MM-DD format (required for all-day events).",
},
endDate: {
type: "string",
description:
"End date for multi-day all-day events (YYYY-MM-DD).",
},
description: {
type: "string",
description: "Event description/notes.",
},
location: {
type: "string",
description: "Event location.",
},
guests: {
type: "array",
items: { type: "string" },
description: "Array of guest email addresses.",
},
sendInvites: {
type: "boolean",
description: "Whether to send invite emails to guests.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
recurrence: {
type: "object",
description: "Recurrence configuration for recurring events.",
properties: {
frequency: {
type: "string",
enum: ["daily", "weekly", "monthly", "yearly"],
description: "How often the event repeats.",
},
interval: {
type: "number",
description: "Repeat every N periods (default 1).",
},
count: {
type: "number",
description: "Number of occurrences.",
},
until: {
type: "string",
description: "ISO date to end recurrence.",
},
daysOfWeek: {
type: "array",
items: { type: "string" },
description:
"For weekly recurrence: days like ['MONDAY', 'WEDNESDAY'].",
},
},
},
},
required: ["title"],
additionalProperties: false,
},
handler: async function (params) {
try {
this.super.handlerProps.log(`Using the gcal-create-event tool.`);
if (this.super.requestToolApproval) {
let timeInfo;
if (params.allDay) {
timeInfo = `All-day event on ${params.date}`;
if (params.endDate) timeInfo += ` to ${params.endDate}`;
} else {
timeInfo = `${params.startTime} - ${params.endTime}`;
}
const guestInfo =
params.guests?.length > 0
? ` with ${params.guests.length} guest(s): ${params.guests.join(", ")}`
: "";
const recurrenceInfo = params.recurrence
? ` (recurring: ${params.recurrence.frequency})`
: "";
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: {
title: params.title,
time: timeInfo,
guests: params.guests || [],
location: params.location,
recurrence: params.recurrence,
},
description: `Create calendar event "${params.title}" - ${timeInfo}${guestInfo}${recurrenceInfo}`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Creating event "${params.title}"...`
);
const result = await googleCalendarLib.createEvent(params);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to create event - ${result.error}`
);
return `Error creating event: ${result.error}`;
}
const isRecurring = !!result.data.eventSeries;
const eventData = result.data.event || result.data.eventSeries;
this.super.introspect(
`${this.caller}: Created ${isRecurring ? "recurring " : ""}event "${eventData.title}"`
);
let timeInfo;
if (params.allDay) {
timeInfo = `All-day event on ${params.date}`;
if (params.endDate) {
timeInfo += ` to ${params.endDate}`;
}
} else {
timeInfo = `${new Date(params.startTime).toLocaleString()} - ${new Date(params.endTime).toLocaleString()}`;
}
let response =
`Event created successfully!\n\n` +
`Title: ${eventData.title}\n` +
`${timeInfo}\n` +
`${isRecurring ? "Event Series" : "Event"} ID: ${isRecurring ? eventData.eventSeriesId : eventData.eventId}\n` +
`Calendar ID: ${eventData.calendarId}`;
if (params.location) {
response += `\nLocation: ${params.location}`;
}
if (params.guests?.length > 0) {
response += `\nGuests: ${params.guests.join(", ")}`;
}
if (isRecurring) {
response += `\nRecurrence: ${params.recurrence.frequency}`;
}
return response;
} catch (e) {
this.super.handlerProps.log(
`gcal-create-event error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error creating event: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,108 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalGetEvent = {
name: "gcal-get-event",
plugin: function () {
return {
name: "gcal-get-event",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get detailed information about a specific calendar event by its ID. " +
"Returns event title, time, location, description, guests, and RSVP status.",
examples: [
{
prompt: "Get details for event abc123",
call: JSON.stringify({ eventId: "abc123" }),
},
{
prompt: "Show me the meeting details for event xyz789",
call: JSON.stringify({ eventId: "xyz789" }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
eventId: {
type: "string",
description: "The event ID to retrieve.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
},
required: ["eventId"],
additionalProperties: false,
},
handler: async function ({ eventId, calendarId }) {
try {
this.super.handlerProps.log(`Using the gcal-get-event tool.`);
this.super.introspect(
`${this.caller}: Fetching event ${eventId}...`
);
const result = await googleCalendarLib.getEvent(
eventId,
calendarId
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get event - ${result.error}`
);
return `Error getting event: ${result.error}`;
}
const event = result.data;
this.super.introspect(
`${this.caller}: Retrieved event "${event.title}"`
);
let timeInfo;
if (event.isAllDayEvent) {
timeInfo = `All-day event: ${new Date(event.startDate).toLocaleDateString()}`;
if (event.endDate) {
timeInfo += ` to ${new Date(event.endDate).toLocaleDateString()}`;
}
} else {
timeInfo = `Time: ${new Date(event.startTime).toLocaleString()} - ${new Date(event.endTime).toLocaleString()}`;
}
const guestList =
event.guests?.length > 0
? event.guests
.map((g) => ` - ${g.name || g.email} (${g.status})`)
.join("\n")
: " (none)";
return (
`Event Details:\n` +
`Title: ${event.title}\n` +
`Event ID: ${event.eventId}\n` +
`Calendar ID: ${event.calendarId}\n` +
`${timeInfo}\n` +
`Location: ${event.location || "(none)"}\n` +
`Description: ${event.description || "(none)"}\n` +
`Recurring: ${event.isRecurringEvent ? "Yes" : "No"}\n` +
`My Status: ${event.myStatus}\n` +
`Owned by me: ${event.isOwnedByMe ? "Yes" : "No"}\n` +
`Guests:\n${guestList}\n` +
`Created: ${new Date(event.dateCreated).toLocaleString()}\n` +
`Last Updated: ${new Date(event.lastUpdated).toLocaleString()}`
);
} catch (e) {
this.super.handlerProps.log(`gcal-get-event error: ${e.message}`);
this.super.introspect(`Error: ${e.message}`);
return `Error getting event: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,109 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalGetEventsForDay = {
name: "gcal-get-events-for-day",
plugin: function () {
return {
name: "gcal-get-events-for-day",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get all calendar events for a specific day. " +
"Returns event titles, times, and IDs for the specified date.",
examples: [
{
prompt: "What events do I have on January 15th, 2025?",
call: JSON.stringify({ date: "2025-01-15" }),
},
{
prompt: "Show my schedule for March 20th",
call: JSON.stringify({ date: "2025-03-20" }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
date: {
type: "string",
description: "The date to query in ISO format (YYYY-MM-DD).",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
},
required: ["date"],
additionalProperties: false,
},
handler: async function ({ date, calendarId }) {
try {
this.super.handlerProps.log(
`Using the gcal-get-events-for-day tool.`
);
this.super.introspect(
`${this.caller}: Fetching events for ${date}...`
);
const result = await googleCalendarLib.getEventsForDay(
date,
calendarId
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get events - ${result.error}`
);
return `Error getting events: ${result.error}`;
}
const { eventCount, events } = result.data;
this.super.introspect(
`${this.caller}: Found ${eventCount} event(s) for ${date}`
);
if (eventCount === 0) {
return `No events scheduled for ${date}.`;
}
const summary = events
.map((event, i) => {
let timeStr;
if (event.isAllDayEvent) {
timeStr = "All day";
} else {
const start = new Date(event.startTime).toLocaleTimeString(
[],
{ hour: "2-digit", minute: "2-digit" }
);
const end = new Date(event.endTime).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
});
timeStr = `${start} - ${end}`;
}
return (
`${i + 1}. "${event.title}" (${timeStr})\n` +
` ID: ${event.eventId}` +
(event.location ? `\n Location: ${event.location}` : "")
);
})
.join("\n\n");
return `Events for ${date} (${eventCount} total):\n\n${summary}`;
} catch (e) {
this.super.handlerProps.log(
`gcal-get-events-for-day error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error getting events: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,137 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalGetEvents = {
name: "gcal-get-events",
plugin: function () {
return {
name: "gcal-get-events",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get calendar events within a date range, optionally filtered by search query. " +
"Returns event titles, times, and IDs. Use this for custom date ranges.",
examples: [
{
prompt: "Find all meetings next week",
call: JSON.stringify({
startDate: "2025-01-20T00:00:00",
endDate: "2025-01-27T23:59:59",
query: "meeting",
limit: 25,
}),
},
{
prompt: "Show events from January 1st to January 31st",
call: JSON.stringify({
startDate: "2025-01-01T00:00:00",
endDate: "2025-01-31T23:59:59",
limit: 50,
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
startDate: {
type: "string",
description: "Start of date range in ISO datetime format.",
},
endDate: {
type: "string",
description: "End of date range in ISO datetime format.",
},
query: {
type: "string",
description: "Optional text to search for in events.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
limit: {
type: "number",
description: "Max results to return (default 25, max 100).",
default: 25,
},
},
required: ["startDate", "endDate"],
additionalProperties: false,
},
handler: async function ({
startDate,
endDate,
query,
calendarId,
limit = 25,
}) {
try {
this.super.handlerProps.log(`Using the gcal-get-events tool.`);
this.super.introspect(
`${this.caller}: Fetching events from ${startDate} to ${endDate}${query ? ` matching "${query}"` : ""}...`
);
const result = await googleCalendarLib.getEvents(
startDate,
endDate,
calendarId,
query,
limit
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get events - ${result.error}`
);
return `Error getting events: ${result.error}`;
}
const { totalEvents, returnedEvents, events } = result.data;
this.super.introspect(
`${this.caller}: Found ${totalEvents} event(s), returning ${returnedEvents}`
);
if (totalEvents === 0) {
return `No events found between ${startDate} and ${endDate}${query ? ` matching "${query}"` : ""}.`;
}
const summary = events
.map((event, i) => {
let timeStr;
if (event.isAllDayEvent) {
timeStr = `All day (${new Date(event.startDate).toLocaleDateString()})`;
} else {
timeStr = `${new Date(event.startTime).toLocaleString()} - ${new Date(event.endTime).toLocaleString()}`;
}
return (
`${i + 1}. "${event.title}"\n` +
` ${timeStr}\n` +
` ID: ${event.eventId}` +
(event.location ? `\n Location: ${event.location}` : "")
);
})
.join("\n\n");
let response = `Found ${totalEvents} event(s)`;
if (returnedEvents < totalEvents) {
response += ` (showing ${returnedEvents})`;
}
response += `:\n\n${summary}`;
return response;
} catch (e) {
this.super.handlerProps.log(
`gcal-get-events error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error getting events: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,238 @@
const googleCalendarLib = require("../lib.js");
/**
* Helper to compute date ranges for common time periods.
* @param {string} period - "today", "week", or "month"
* @returns {{startDate: string, endDate: string, label: string}}
*/
function getDateRangeForPeriod(period) {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
let startDate, endDate, label;
switch (period.toLowerCase()) {
case "today":
startDate = new Date(today);
endDate = new Date(today);
endDate.setHours(23, 59, 59, 999);
label = "today";
break;
case "tomorrow":
startDate = new Date(today);
startDate.setDate(startDate.getDate() + 1);
endDate = new Date(startDate);
endDate.setHours(23, 59, 59, 999);
label = "tomorrow";
break;
case "week":
case "this week":
startDate = new Date(today);
endDate = new Date(today);
endDate.setDate(endDate.getDate() + 7);
endDate.setHours(23, 59, 59, 999);
label = "the next 7 days";
break;
case "next week":
startDate = new Date(today);
startDate.setDate(startDate.getDate() + 7);
endDate = new Date(startDate);
endDate.setDate(endDate.getDate() + 7);
endDate.setHours(23, 59, 59, 999);
label = "next week";
break;
case "month":
case "this month":
startDate = new Date(today);
endDate = new Date(today);
endDate.setDate(endDate.getDate() + 30);
endDate.setHours(23, 59, 59, 999);
label = "the next 30 days";
break;
case "next month":
startDate = new Date(today);
startDate.setDate(startDate.getDate() + 30);
endDate = new Date(startDate);
endDate.setDate(endDate.getDate() + 30);
endDate.setHours(23, 59, 59, 999);
label = "next month";
break;
default:
throw new Error(
`Invalid period: "${period}". Use "today", "tomorrow", "week", "this week", "next week", "month", "this month", or "next month".`
);
}
return {
startDate: startDate.toISOString(),
endDate: endDate.toISOString(),
label,
};
}
module.exports.GCalGetUpcomingEvents = {
name: "gcal-get-upcoming-events",
plugin: function () {
return {
name: "gcal-get-upcoming-events",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get upcoming calendar events using simple time period keywords. " +
"This is the preferred tool for common queries like 'what's on my calendar today?' " +
"Supports periods: 'today', 'tomorrow', 'week' (next 7 days), 'month' (next 30 days), " +
"'next week', and 'next month'. " +
"Automatically calculates the correct date range so you don't need to know the current date.",
examples: [
{
prompt: "What's on my calendar today?",
call: JSON.stringify({ period: "today" }),
},
{
prompt: "What meetings do I have this week?",
call: JSON.stringify({ period: "week", query: "meeting" }),
},
{
prompt: "Show me my schedule for the month",
call: JSON.stringify({ period: "month", limit: 50 }),
},
{
prompt: "What do I have tomorrow?",
call: JSON.stringify({ period: "tomorrow" }),
},
{
prompt: "Find all project events next week",
call: JSON.stringify({ period: "next week", query: "project" }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
period: {
type: "string",
description:
"Time period to query. Options: 'today', 'tomorrow', 'week' (next 7 days), 'this week', 'next week', 'month' (next 30 days), 'this month', 'next month'.",
enum: [
"today",
"tomorrow",
"week",
"this week",
"next week",
"month",
"this month",
"next month",
],
},
query: {
type: "string",
description: "Optional text to search for in events.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
limit: {
type: "number",
description: "Max results to return (default 25, max 100).",
default: 25,
},
},
required: ["period"],
additionalProperties: false,
},
handler: async function ({ period, query, calendarId, limit = 25 }) {
try {
this.super.handlerProps.log(
`Using the gcal-get-upcoming-events tool.`
);
const { startDate, endDate, label } =
getDateRangeForPeriod(period);
this.super.introspect(
`${this.caller}: Fetching events for ${label}${query ? ` matching "${query}"` : ""}...`
);
const result = await googleCalendarLib.getEvents(
startDate,
endDate,
calendarId,
query,
limit
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get events - ${result.error}`
);
return `Error getting events: ${result.error}`;
}
const { totalEvents, returnedEvents, events } = result.data;
this.super.introspect(
`${this.caller}: Found ${totalEvents} event(s) for ${label}`
);
if (totalEvents === 0) {
return `No events scheduled for ${label}${query ? ` matching "${query}"` : ""}.`;
}
const summary = events
.map((event, i) => {
let timeStr;
if (event.isAllDayEvent) {
timeStr = `All day (${new Date(event.startDate).toLocaleDateString()})`;
} else {
const startTime = new Date(event.startTime);
const endTime = new Date(event.endTime);
const dateStr = startTime.toLocaleDateString();
const startTimeStr = startTime.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
});
const endTimeStr = endTime.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
});
timeStr = `${dateStr} ${startTimeStr} - ${endTimeStr}`;
}
return (
`${i + 1}. "${event.title}"\n` +
` ${timeStr}\n` +
` ID: ${event.eventId}` +
(event.location ? `\n Location: ${event.location}` : "")
);
})
.join("\n\n");
let response = `Events for ${label}`;
if (returnedEvents < totalEvents) {
response += ` (${returnedEvents} of ${totalEvents})`;
} else {
response += ` (${totalEvents} total)`;
}
response += `:\n\n${summary}`;
return response;
} catch (e) {
this.super.handlerProps.log(
`gcal-get-upcoming-events error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error getting events: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,114 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalQuickAdd = {
name: "gcal-quick-add",
plugin: function () {
return {
name: "gcal-quick-add",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Create a calendar event from a natural language description. " +
"Google Calendar will parse the description to extract the event title, date, and time. " +
"Examples: 'Meeting with John tomorrow at 3pm', 'Dentist appointment on Friday at 10am'.",
examples: [
{
prompt: "Add a meeting with John tomorrow at 3pm",
call: JSON.stringify({
description: "Meeting with John tomorrow at 3pm",
}),
},
{
prompt: "Schedule lunch with Sarah next Tuesday at noon",
call: JSON.stringify({
description: "Lunch with Sarah next Tuesday at noon",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
description: {
type: "string",
description:
"Natural language description of the event including title, date, and time.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
},
required: ["description"],
additionalProperties: false,
},
handler: async function ({ description, calendarId }) {
try {
this.super.handlerProps.log(`Using the gcal-quick-add tool.`);
if (this.super.requestToolApproval) {
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: {
description,
calendarId,
},
description: `Create calendar event from: "${description}"`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Creating event from "${description}"...`
);
const result = await googleCalendarLib.quickAdd(
description,
calendarId
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to create event - ${result.error}`
);
return `Error creating event: ${result.error}`;
}
const event = result.data.event;
this.super.introspect(
`${this.caller}: Created event "${event.title}"`
);
let timeInfo;
if (event.isAllDayEvent) {
timeInfo = `All-day event on ${new Date(event.startDate).toLocaleDateString()}`;
} else {
timeInfo = `${new Date(event.startTime).toLocaleString()} - ${new Date(event.endTime).toLocaleString()}`;
}
return (
`Event created successfully!\n\n` +
`Title: ${event.title}\n` +
`${timeInfo}\n` +
`Event ID: ${event.eventId}\n` +
`Calendar ID: ${event.calendarId}`
);
} catch (e) {
this.super.handlerProps.log(`gcal-quick-add error: ${e.message}`);
this.super.introspect(`Error: ${e.message}`);
return `Error creating event: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,125 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalSetMyStatus = {
name: "gcal-set-my-status",
plugin: function () {
return {
name: "gcal-set-my-status",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Set your RSVP status for a calendar event. " +
"Use this to accept, decline, or tentatively accept meeting invitations.",
examples: [
{
prompt: "Accept the meeting invitation for event abc123",
call: JSON.stringify({ eventId: "abc123", status: "YES" }),
},
{
prompt: "Decline event xyz789",
call: JSON.stringify({ eventId: "xyz789", status: "NO" }),
},
{
prompt: "Mark myself as maybe for event def456",
call: JSON.stringify({ eventId: "def456", status: "MAYBE" }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
eventId: {
type: "string",
description: "The ID of the event to RSVP to.",
},
status: {
type: "string",
enum: ["YES", "NO", "MAYBE", "INVITED"],
description:
"Your RSVP status: YES (accept), NO (decline), MAYBE (tentative), or INVITED (reset to invited).",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
},
required: ["eventId", "status"],
additionalProperties: false,
},
handler: async function ({ eventId, status, calendarId }) {
try {
this.super.handlerProps.log(`Using the gcal-set-my-status tool.`);
const statusActions = {
YES: "accept",
NO: "decline",
MAYBE: "tentatively accept",
INVITED: "reset to invited",
};
if (this.super.requestToolApproval) {
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: {
eventId,
status,
},
description: `Set RSVP status to ${status} (${statusActions[status] || status}) for event ${eventId}`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Setting RSVP status to ${status} for event ${eventId}...`
);
const result = await googleCalendarLib.setMyStatus(
eventId,
status,
calendarId
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to set status - ${result.error}`
);
return `Error setting RSVP status: ${result.error}`;
}
this.super.introspect(
`${this.caller}: RSVP status set to ${result.data.newStatus}`
);
const statusMessages = {
YES: "accepted",
NO: "declined",
MAYBE: "marked as tentative",
INVITED: "reset to invited",
};
return (
`RSVP status updated!\n\n` +
`Event ID: ${result.data.eventId}\n` +
`Status: ${result.data.newStatus} (${statusMessages[result.data.newStatus] || result.data.newStatus})`
);
} catch (e) {
this.super.handlerProps.log(
`gcal-set-my-status error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error setting RSVP status: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,173 @@
const googleCalendarLib = require("../lib.js");
module.exports.GCalUpdateEvent = {
name: "gcal-update-event",
plugin: function () {
return {
name: "gcal-update-event",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Update an existing calendar event. " +
"You can change the title, description, location, time, or guest list. " +
"Only provide the fields you want to update.",
examples: [
{
prompt: "Change the title of event abc123 to 'Updated Meeting'",
call: JSON.stringify({
eventId: "abc123",
title: "Updated Meeting",
}),
},
{
prompt: "Move event xyz789 to 3pm",
call: JSON.stringify({
eventId: "xyz789",
startTime: "2025-01-15T15:00:00",
endTime: "2025-01-15T16:00:00",
}),
},
{
prompt: "Add a location to event abc123",
call: JSON.stringify({
eventId: "abc123",
location: "Conference Room A",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
eventId: {
type: "string",
description: "The ID of the event to update.",
},
calendarId: {
type: "string",
description:
"Optional calendar ID. If omitted, uses the primary calendar.",
},
title: {
type: "string",
description: "New event title.",
},
description: {
type: "string",
description: "New event description.",
},
location: {
type: "string",
description: "New event location.",
},
startTime: {
type: "string",
description: "New start time in ISO datetime format.",
},
endTime: {
type: "string",
description: "New end time in ISO datetime format.",
},
guests: {
type: "array",
items: { type: "string" },
description:
"New guest list (replaces existing guests). Array of email addresses.",
},
},
required: ["eventId"],
additionalProperties: false,
},
handler: async function ({
eventId,
calendarId,
title,
description,
location,
startTime,
endTime,
guests,
}) {
try {
this.super.handlerProps.log(`Using the gcal-update-event tool.`);
const updates = {};
if (title !== undefined) updates.title = title;
if (description !== undefined) updates.description = description;
if (location !== undefined) updates.location = location;
if (startTime !== undefined) updates.startTime = startTime;
if (endTime !== undefined) updates.endTime = endTime;
if (guests !== undefined) updates.guests = guests;
if (this.super.requestToolApproval) {
const updatedFields = Object.keys(updates).join(", ");
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: {
eventId,
updates,
},
description: `Update calendar event ${eventId} - changing: ${updatedFields}`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Updating event ${eventId}...`
);
const result = await googleCalendarLib.updateEvent(
eventId,
calendarId,
updates
);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to update event - ${result.error}`
);
return `Error updating event: ${result.error}`;
}
const event = result.data.event;
this.super.introspect(
`${this.caller}: Updated event "${event.title}"`
);
let timeInfo;
if (event.isAllDayEvent) {
timeInfo = `All-day event on ${new Date(event.startDate).toLocaleDateString()}`;
} else {
timeInfo = `${new Date(event.startTime).toLocaleString()} - ${new Date(event.endTime).toLocaleString()}`;
}
const updatedFields = Object.keys(updates).join(", ");
return (
`Event updated successfully!\n\n` +
`Updated fields: ${updatedFields}\n\n` +
`Title: ${event.title}\n` +
`${timeInfo}\n` +
`Location: ${event.location || "(none)"}\n` +
`Event ID: ${event.eventId}`
);
} catch (e) {
this.super.handlerProps.log(
`gcal-update-event error: ${e.message}`
);
this.super.introspect(`Error: ${e.message}`);
return `Error updating event: ${e.message}`;
}
},
});
},
};
},
};

View File

@ -0,0 +1,40 @@
const { GCalListCalendars } = require("./calendars/gcal-list-calendars.js");
const { GCalGetCalendar } = require("./calendars/gcal-get-calendar.js");
const { GCalGetEvent } = require("./events/gcal-get-event.js");
const { GCalGetEventsForDay } = require("./events/gcal-get-events-for-day.js");
const { GCalGetEvents } = require("./events/gcal-get-events.js");
const {
GCalGetUpcomingEvents,
} = require("./events/gcal-get-upcoming-events.js");
const { GCalQuickAdd } = require("./events/gcal-quick-add.js");
const { GCalCreateEvent } = require("./events/gcal-create-event.js");
const { GCalUpdateEvent } = require("./events/gcal-update-event.js");
const { GCalSetMyStatus } = require("./events/gcal-set-my-status.js");
const googleCalendarAgent = {
name: "google-calendar-agent",
startupConfig: {
params: {},
},
plugin: [
// Calendars (read-only)
GCalListCalendars,
GCalGetCalendar,
// Events - Read (read-only)
GCalGetEvent,
GCalGetEventsForDay,
GCalGetEvents,
GCalGetUpcomingEvents,
// Events - Write (modifying)
GCalQuickAdd,
GCalCreateEvent,
GCalUpdateEvent,
GCalSetMyStatus,
],
};
module.exports = {
googleCalendarAgent,
};

View File

@ -0,0 +1,288 @@
const { SystemSettings } = require("../../../../../models/systemSettings");
const { safeJsonParse } = require("../../../../http");
/**
* Google Calendar Bridge Library
* Handles communication with the AnythingLLM Google Calendar Google Apps Script deployment.
*/
class GoogleCalendarBridge {
#deploymentId = null;
#apiKey = null;
#isInitialized = false;
#log(text, ...args) {
console.log(`\x1b[35m[GoogleCalendarBridge]\x1b[0m ${text}`, ...args);
}
/**
* Resets the bridge state, forcing re-initialization on next use.
* Call this when configuration changes (e.g., deployment ID updated).
*/
reset() {
this.#deploymentId = null;
this.#apiKey = null;
this.#isInitialized = false;
}
/**
* Gets the current Google Calendar agent configuration from system settings.
* @returns {Promise<{deploymentId?: string, apiKey?: string}>}
*/
static async getConfig() {
const configJson = await SystemSettings.getValueOrFallback(
{ label: "google_calendar_agent_config" },
"{}"
);
return safeJsonParse(configJson, {});
}
/**
* Updates the Google Calendar agent configuration in system settings.
* @param {Object} updates - Fields to update
* @returns {Promise<{success: boolean, error?: string}>}
*/
static async updateConfig(updates) {
try {
await SystemSettings.updateSettings({
google_calendar_agent_config: JSON.stringify(updates),
});
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
/**
* Initializes the Google Calendar bridge by fetching configuration from system settings.
* @returns {Promise<{success: boolean, error?: string}>}
*/
async initialize() {
if (this.#isInitialized) return { success: true };
try {
const isMultiUser = await SystemSettings.isMultiUserMode();
if (isMultiUser) {
return {
success: false,
error:
"Google Calendar integration is not available in multi-user mode for security reasons.",
};
}
const config = await GoogleCalendarBridge.getConfig();
if (!config.deploymentId || !config.apiKey) {
return {
success: false,
error:
"Google Calendar integration is not configured. Please set the Deployment ID and API Key in the agent settings.",
};
}
this.#deploymentId = config.deploymentId;
this.#apiKey = config.apiKey;
this.#isInitialized = true;
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
/**
* Checks if the Google Calendar bridge is properly configured and available.
* @returns {Promise<boolean>}
*/
async isAvailable() {
const result = await this.initialize();
return result.success;
}
/**
* Checks if Google Calendar tools are available (not in multi-user mode and has configuration).
* @returns {Promise<boolean>}
*/
static async isToolAvailable() {
const isMultiUser = await SystemSettings.isMultiUserMode();
if (isMultiUser) return false;
const config = await GoogleCalendarBridge.getConfig();
return !!(config.deploymentId && config.apiKey);
}
get maskedDeploymentId() {
if (!this.#deploymentId) return "(not configured)";
return (
this.#deploymentId.substring(0, 5) +
"..." +
this.#deploymentId.substring(this.#deploymentId.length - 5)
);
}
/**
* Gets the base URL for the Google Calendar Google Apps Script deployment.
* @returns {string}
*/
#getBaseUrl() {
this.#log(`Getting base URL for deployment ID ${this.maskedDeploymentId}`);
return `https://script.google.com/macros/s/${this.#deploymentId}/exec`;
}
/**
* Makes a request to the Google Calendar Google Apps Script API.
* @param {string} action - The action to perform
* @param {object} params - Additional parameters for the action
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async request(action, params = {}) {
const initResult = await this.initialize();
if (!initResult.success) {
return { success: false, error: initResult.error };
}
try {
const response = await fetch(this.#getBaseUrl(), {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-AnythingLLM-UA": "AnythingLLM-GoogleCalendar-Agent/1.0",
},
body: JSON.stringify({
key: this.#apiKey,
action,
...params,
}),
});
if (!response.ok) {
return {
success: false,
error: `Google Calendar API request failed with status ${response.status}`,
};
}
const result = await response.json();
if (result.status === "error") {
return { success: false, error: result.error };
}
return { success: true, data: result.data };
} catch (error) {
return {
success: false,
error: `Google Calendar API request failed: ${error.message}`,
};
}
}
/**
* List all calendars the user owns or is subscribed to.
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async listCalendars() {
return this.request("list_calendars");
}
/**
* Get details of a specific calendar by ID.
* @param {string} calendarId - The calendar ID
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async getCalendar(calendarId) {
return this.request("get_calendar", { calendarId });
}
/**
* Get a single event by ID.
* @param {string} eventId - The event ID
* @param {string} calendarId - Optional calendar ID
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async getEvent(eventId, calendarId) {
return this.request("get_event", { eventId, calendarId });
}
/**
* Get all events for a specific day.
* @param {string} date - ISO date string
* @param {string} calendarId - Optional calendar ID
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async getEventsForDay(date, calendarId) {
return this.request("get_events_for_day", { date, calendarId });
}
/**
* Get events within a date range, optionally filtered by search query.
* @param {string} startDate - ISO datetime string
* @param {string} endDate - ISO datetime string
* @param {string} calendarId - Optional calendar ID
* @param {string} query - Optional search query
* @param {number} limit - Max results (default 25, max 100)
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async getEvents(startDate, endDate, calendarId, query, limit = 25) {
return this.request("get_events", {
startDate,
endDate,
calendarId,
query,
limit,
});
}
/**
* Create event from natural language description.
* @param {string} description - Natural language description
* @param {string} calendarId - Optional calendar ID
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async quickAdd(description, calendarId) {
return this.request("quick_add", { description, calendarId });
}
/**
* Create a single or recurring event (timed or all-day).
* @param {object} eventData - Event creation data
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async createEvent(eventData) {
return this.request("create_event", eventData);
}
/**
* Update an existing event.
* @param {string} eventId - The event ID
* @param {string} calendarId - Optional calendar ID
* @param {object} updates - Fields to update
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async updateEvent(eventId, calendarId, updates) {
return this.request("update_event", {
eventId,
calendarId,
...updates,
});
}
/**
* Set your RSVP status for an event.
* @param {string} eventId - The event ID
* @param {string} status - RSVP status: "YES", "NO", "MAYBE", or "INVITED"
* @param {string} calendarId - Optional calendar ID
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async setMyStatus(eventId, status, calendarId) {
return this.request("set_my_status", { eventId, status, calendarId });
}
/**
* Get API version and available actions.
* @returns {Promise<{success: boolean, data?: object, error?: string}>}
*/
async version() {
return this.request("version");
}
}
module.exports = new GoogleCalendarBridge();
module.exports.GoogleCalendarBridge = GoogleCalendarBridge;

View File

@ -10,6 +10,7 @@ const { filesystemAgent } = require("./filesystem/index.js");
const { createFilesAgent } = require("./create-files/index.js");
const { gmailAgent } = require("./gmail/index.js");
const { outlookAgent } = require("./outlook/index.js");
const { googleCalendarAgent } = require("./google-calendar/index.js");
module.exports = {
webScraping,
@ -24,6 +25,7 @@ module.exports = {
createFilesAgent,
gmailAgent,
outlookAgent,
googleCalendarAgent,
// Plugin name aliases so they can be pulled by slug as well.
[webScraping.name]: webScraping,
@ -38,4 +40,5 @@ module.exports = {
[createFilesAgent.name]: createFilesAgent,
[gmailAgent.name]: gmailAgent,
[outlookAgent.name]: outlookAgent,
[googleCalendarAgent.name]: googleCalendarAgent,
};