Outlook agent via Entra Application (#5427)

* Outlook agent via Entra Application

* translations (#5437)
This commit is contained in:
Timothy Carambat
2026-04-14 14:05:19 -07:00
committed by GitHub
parent b7b380ac51
commit 1c0d0301b0
48 changed files with 6336 additions and 60 deletions

View File

@@ -528,6 +528,104 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "ملحق Outlook",
description:
"اسمح لمتخصصك بالتفاعل مع Microsoft Outlook - للبحث عن رسائل البريد الإلكتروني، وقراءة المحادثات، وكتابة المسودات، وإرسال رسائل البريد الإلكتروني، وإدارة صندوق الوارد الخاص بك باستخدام واجهة برمجة التطبيقات Microsoft Graph. <a>اقرأ الوثائق</a>.",
multiUserWarning:
'لا تتوفر تكامل "Outlook" في الوضع متعدد المستخدمين لأسباب تتعلق بالأمان. يرجى تعطيل الوضع متعدد المستخدمين لاستخدام هذه الميزة.',
configuration: "تكوين برنامج Outlook",
authType: "نوع الحساب",
authTypeHelp:
'اختر أنواع حسابات مايكروسوفت التي يمكنها التحقق من الهوية. "جميع الحسابات" تدعم كل من الحسابات الشخصية وحسابات العمل/المدرسة. "فقط الحسابات الشخصية" يقتصر على حسابات مايكروسوفت الشخصية فقط. "فقط الحسابات التنظيمية" يقتصر على حسابات العمل/المدرسة من مستأجر Azure AD محدد.',
authTypeCommon: "جميع الحسابات (الشخصية والعمل/التعليم)",
authTypeConsumers: "حسابات Microsoft الشخصية فقط",
authTypeOrganization: "حسابات المنظمات فقط (يتطلب معرفة المستأجر).",
clientId: "رقم تعريف العميل (المتقدم)",
clientIdHelp: "معرّف التطبيق (العميل) من تسجيل تطبيقك في Azure AD.",
tenantId: "معرّف (المستأجر)",
tenantIdHelp:
"معرّف المستأجر (Tenant ID) من تسجيل تطبيق Azure AD الخاص بك. مطلوب فقط للتحقق من الهوية داخل المؤسسة فقط.",
clientSecret: "كلمة المرور الخاصة بالعميل",
clientSecretHelp: "قيمة سرية للعميل من تسجيل تطبيق Azure AD الخاص بك",
configurationRequired:
"يرجى تكوين معرف العميل ومعرف العميل السري لتمكين ميزات Outlook.",
authRequired:
"احفظ بيانات اعتمادك أولاً، ثم قم بتسجيل الدخول باستخدام Microsoft لإكمال الإعداد.",
authenticateWithMicrosoft: "التحقق باستخدام مايكروسوفت",
authenticated:
"تم التحقق من صحة تسجيل الدخول بنجاح باستخدام Microsoft Outlook.",
revokeAccess: "إلغاء الوصول",
configured: "تم التكوين",
searchSkills: "مهارات البحث...",
noSkillsFound: "لا توجد مهارات تطابق بحثك.",
categories: {
search: {
title: "البحث عن الرسائل وقراءتها",
description:
"ابحث و اقرأ رسائل البريد الإلكتروني من صندوق الوارد الخاص بك في Outlook.",
},
drafts: {
title: "نماذج رسائل بريد إلكتروني",
description: "إنشاء، وتحرير، وإدارة مسودات الرسائل الإلكترونية.",
},
send: {
title: "إرسال رسائل بريد إلكتروني",
description:
"أرسل رسائل بريد إلكتروني جديدة أو رد على الرسائل على الفور.",
},
account: {
title: "إحصائيات التكامل",
description: "عرض إحصائيات صندوق البريد ومعلومات الحساب.",
},
},
skills: {
getInbox: {
title: "الوصول إلى صندوق الوارد",
description:
"احصل على رسائل البريد الإلكتروني الأخيرة من صندوق الوارد في Outlook.",
},
search: {
title: "البحث في رسائل البريد الإلكتروني",
description:
"ابحث في رسائل البريد الإلكتروني باستخدام تركيب جمل البحث الخاص بـ Microsoft.",
},
readThread: {
title: "اقرأ المحادثة",
description: "اقرأ سلسلة كاملة من رسائل البريد الإلكتروني.",
},
createDraft: {
title: "إنشاء مسودة",
description:
"إنشاء رسالة بريد إلكتروني جديدة أو رد مقترح على رسالة موجودة.",
},
updateDraft: {
title: "تحديث المسودة",
description: "تحديث رسالة بريد إلكتروني مُعدة مسبقًا",
},
listDrafts: {
title: "قائمة مسودات",
description: "اعرض جميع رسائل البريد الإلكتروني قيد الإنشاء.",
},
deleteDraft: {
title: "حذف المسودة",
description: "حذف رسالة بريد إلكتروني مسودة",
},
sendDraft: {
title: "إرسال مسودة",
description: "أرسل نسخة من رسالة بريد إلكتروني موجودة.",
},
sendEmail: {
title: "إرسال بريد إلكتروني",
description:
"أرسل بريدًا إلكترونيًا جديدًا أو رد على رسالة موجودة على الفور.",
},
getMailboxStats: {
title: "إحصائيات صندوق البريد",
description: "احصل على عدد المجلدات وإحصائيات صندوق البريد.",
},
},
},
},
mcp: {
title: "خوادم نظام MCP",

View File

@@ -548,6 +548,111 @@ const TRANSLATIONS = {
},
default_skill:
"Per defecte, aquesta habilitat està activada, però pots desactivar-la si no vols que estigui disponible per a l'agent.",
outlook: {
title: "Connector per a Outlook",
description:
"Permite que el teu agent interactui amb Microsoft Outlook: cerca correus electrònics, llegeix converses, redacta drafts, envia correus electrònics i gestiona la teva caixa de correu electrònic a través de l'API de Microsoft Graph. <a>Consulteu la documentació</a>.",
multiUserWarning:
"La integració d'Outlook no està disponible en mode multiusuari per raons de seguretat. Per utilitzar aquesta funció, feu que el mode multiusuari estigui desactivat.",
configuration: "Configuració d'Outlook",
authType: "Tipus de compte",
authTypeHelp:
"Seleccioneu quins tipus de comptes de Microsoft poden autenticar-se. \"Tots els comptes\" admet tant comptes personals com comptes per a l'ús laboral/escolar. \"Només comptes personals\" limita l'opció a comptes personals de Microsoft. \"Només comptes d'organització\" limita l'opció a comptes per a l'ús laboral/escolar d'un tenant específic d'Azure AD.",
authTypeCommon: "Totes les comptes (personals i laborals/escolars)",
authTypeConsumers: "Només comptes personals de Microsoft",
authTypeOrganization:
"Només comptes d'organitzacions (requereix l'ID del llogater)",
clientId: "Identificador (Client)",
clientIdHelp:
"L'ID de l'aplicació (Client) del vostre registre d'aplicació a Azure AD",
tenantId: "Identificador (del llogater)",
tenantIdHelp:
"L'ID del \"Tenant\" (inquilí) del vostre registre d'aplicació a Azure AD. És obligatori només per a l'autenticació dins de l'organització.",
clientSecret: "Secret del client",
clientSecretHelp:
"El valor secret de l'aplicació registrada a Azure AD.",
configurationRequired:
"Si us plau, configureu l'ID del client i el secret del client per habilitar les funcionalitats d'Outlook.",
authRequired:
"Primer, guarda les teves credencials, i després autentica't amb Microsoft per completar la configuració.",
authenticateWithMicrosoft: "Autentica't amb Microsoft",
authenticated: "He estat autentificat amb èxit amb Microsoft Outlook.",
revokeAccess: "Revocar l'accés",
configured: "Configurat",
searchSkills: "Habilitats de cerca...",
noSkillsFound:
"No s'han trobat perfils que coincideixin amb la vostra cerca.",
categories: {
search: {
title: "Cerca i llegeix correus electrònics",
description:
"Cerca i llegeix correus electrònics des de la teva pestanya de correus d'Outlook.",
},
drafts: {
title: "Proposals de correu electrònic",
description: "Crea, edita i gestiona els esborralls d'e-mail.",
},
send: {
title: "Enviar correus electrònics",
description:
"Envieu correus electrònics nous o respondre als missatges immediatament.",
},
account: {
title: "Estadístiques d'integració",
description:
"Visualitza les estadístiques de la caixa de correu i la informació del compte.",
},
},
skills: {
getInbox: {
title: "Accedeix a la caixa de correu",
description:
"Obteniu els correus electrònics més recents de la vostra pestanya de correu d'Outlook.",
},
search: {
title: "Cerca correus electrònics",
description:
"Cerca correus electrònics utilitzant la sintaxi de cerca de Microsoft",
},
readThread: {
title: "Llegir la conversa",
description:
"Llegeix la totalitat d'una conversa per correu electrònic.",
},
createDraft: {
title: "Crear un esborr",
description:
"Crea un nou correu electrònic o una resposta a un missatge existent.",
},
updateDraft: {
title: "Versió actualitzada",
description:
"Actualitza un correu electrònic existent que ja està redactat",
},
listDrafts: {
title: "Proposta de llistats",
description: "Mostra totes les correus electrònics en projecte.",
},
deleteDraft: {
title: "Eliminar esbor",
description: "Eliminar un correu electrònic en projecte",
},
sendDraft: {
title: "Enviar esborrany",
description: "Envia un correu electrònic existent.",
},
sendEmail: {
title: "Enviar correu electrònic",
description:
"Envieu un correu electrònic nou o respondreu a un missatge existent immediatament.",
},
getMailboxStats: {
title: "Estadístiques de la caixa de correu",
description:
"Obteniu el nombre de carpetes i les estadístiques de la caixa de correu.",
},
},
},
},
mcp: {
title: "Servidors MCP",

View File

@@ -544,6 +544,106 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Připojení k Outlooku",
description:
"Umožněte svému agentovi interakci s Microsoft Outlook vyhledávání e-mailů, čtení vláken, vytváření návrhů, odesílání e-mailů a správu vaší poštovní schránky prostřednictvím Microsoft Graph API. <a>Prostudujte dokumentaci</a>.",
multiUserWarning:
"Integrace s Outlookem 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 Outlooku",
authType: "Typ účtu",
authTypeHelp:
"Vyberte, jaké typy účtů Microsoft mohou být ověřovány. Možnost „Všechny účty“ podporuje jak osobní, tak pracovní/školní účty. Možnost „Pouze osobní účty“ omezuje na osobní účty Microsoft. Možnost „Pouze organizace“ omezuje na pracovní/školní účty z konkrétního tenantu Azure AD.",
authTypeCommon: "Všechny účty (osobní a pracovní/školní)",
authTypeConsumers: "Pouze osobní účty Microsoft",
authTypeOrganization: "Účty organizací (vyžaduje ID pronajímatele)",
clientId: "Identifikátor klienta (ID aplikace)",
clientIdHelp:
"Identifikátor aplikace (klienta) z registrace vaší aplikace v Azure AD",
tenantId: "Identifikátor (pro nájemce)",
tenantIdHelp:
"ID adresáře (uživatele) z registrace vaší aplikace v Azure AD. Je nutné pouze pro ověřování v rámci organizace.",
clientSecret: "Tajný klíč klienta",
clientSecretHelp:
"Tajná hodnota klienta z registrace vaší aplikace v Azure AD",
configurationRequired:
"Prosím, nakonfigurujte ID klienta a tajný klíč, aby bylo možné využít funkce Outlook.",
authRequired:
"Nejprve si uložte své přihlašovací údaje, a poté se ověřte u společnosti Microsoft, abyste dokončili nastavení.",
authenticateWithMicrosoft: "Ověřte se pomocí Microsoftu",
authenticated: "Úspěšně jsem se ověřil pomocí Microsoft Outlook.",
revokeAccess: "Odvolat přístup",
configured: "Konfigurováno",
searchSkills: "Dovednosti pro vyhledávání...",
noSkillsFound: "Žádné výsledky neodpovídají vašemu vyhledávání.",
categories: {
search: {
title: "Vyhledávání a čtení e-mailů",
description:
"Vyhledejte a čtěte e-maily ve vaší poštovní schránce Outlook.",
},
drafts: {
title: "Návrhy e-mailů",
description: "Vytvářejte, upravujte a spravujte návrhy e-mailů.",
},
send: {
title: "Odesílejte e-maily",
description:
"Odešlete nové e-maily nebo okamžitě odpovězte na zprávy.",
},
account: {
title: "Statistiky integrace",
description:
"Zobrazte statistiky poštovní schránky a informace o účtu.",
},
},
skills: {
getInbox: {
title: "Otevřít schránku",
description: "Získejte nejnovější e-maily z vaší schránky Outlook.",
},
search: {
title: "Vyhledávání v e-mailech",
description:
"Hledejte e-maily pomocí syntaxe pro vyhledávání od Microsoftu",
},
readThread: {
title: "Přečtěte si konverzaci",
description: "Přečtěte si kompletní vedení e-mailové konverzace.",
},
createDraft: {
title: "Vytvořit návrh",
description:
"Vytvořte nový návrh e-mailu nebo návrh odpovědi na stávající zprávu.",
},
updateDraft: {
title: "Aktualizovaná verze návrhu",
description: "Aktualizujte stávající návrh e-mailu",
},
listDrafts: {
title: "Návrhy (seznam)",
description: "Vypište všechny návrhy e-mailů.",
},
deleteDraft: {
title: "Smazat návrh",
description: "Smazat návrh e-mailu",
},
sendDraft: {
title: "Ode mne návrh",
description: "Odešlete existující návrh e-mailu",
},
sendEmail: {
title: "Odešlete e-mail",
description:
"Odešlete nový e-mail nebo odpověď na stávající zprávu okamžitě.",
},
getMailboxStats: {
title: "Statistiky poštovní schránky",
description:
"Získejte informace o počtu složek a statistiky poštovní schránky.",
},
},
},
},
mcp: {
title: "Servery společnosti MCP",

View File

@@ -530,6 +530,103 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook-forbindelse",
description:
"Giv din agent mulighed for at interagere med Microsoft Outlook søg efter e-mails, læs samtaler, oprette udkast, sende e-mails og administrer din indbakke via Microsoft Graph API. Se dokumentationen her: <a>.",
multiUserWarning:
"Integration med Outlook er ikke tilgængelig i multi-bruger-tilstand af sikkerhedsmæssige årsager. For at bruge denne funktion, bedes du deaktivere multi-bruger-tilstanden.",
configuration: "Outlook-konfiguration",
authType: "Kontotype",
authTypeHelp:
'Vælg, hvilke typer af Microsoft-konti der kan godkende. "Alle konti" understøtter både personlige og arbejds-/skolekonti. "Kun personlige konti" begrænser til kun personlige Microsoft-konti. "Kun arbejds-/skolekonti" begrænser til arbejds-/skolekonti fra en specifik Azure AD-tenant.',
authTypeCommon: "Alle konti (personlige og arbejds-/skolerelaterede)",
authTypeConsumers: "Kun personlige Microsoft-konti",
authTypeOrganization: "Kun organisationskonti (kræver lejer-ID)",
clientId: "Anvendelses-ID (kunde)",
clientIdHelp:
"Applikations-ID (også kaldet klient-ID) fra din Azure AD applikationsregistrering",
tenantId: "Identifikationsnummer (Lejer)",
tenantIdHelp:
"Identifikationsnummeret (for lejer) fra din Azure AD-applikationsregistrering. Kræves kun til autentificering, der kun er for organisationen.",
clientSecret: "Klientens hemmelige nøgle",
clientSecretHelp:
"Klientens hemmelige værdi fra din Azure AD-applikationsregistrering",
configurationRequired:
"Vær venligst oprettet Client ID og Client Secret for at aktivere Outlook-funktionaliteten.",
authRequired:
"Gem dine legitimationsoplysninger først, og derefter skal du autentificere dig hos Microsoft for at fuldføre opsætningen.",
authenticateWithMicrosoft: "Bekræft med Microsoft",
authenticated: "Succesfuldt bekræftet med Microsoft Outlook.",
revokeAccess: "Annullér adgang",
configured: "Konfigureret",
searchSkills: "Færdigheder inden for søgning...",
noSkillsFound: "Ingen resultater fundet, der matcher din søgning.",
categories: {
search: {
title: "Søg og læs e-mails",
description: "Søg og læs e-mails fra din Outlook-indbakke",
},
drafts: {
title: "Udkast til e-mails",
description: "Opret, rediger og administrer udkast til e-mails.",
},
send: {
title: "Send e-mails",
description:
"Send nye e-mails eller svar på beskeder med det samme.",
},
account: {
title: "Statistik om integration",
description: "Se statistik for din postkasse og kontoinformation.",
},
},
skills: {
getInbox: {
title: "Åbn indbakken",
description: "Få de seneste e-mails fra din Outlook-indbakke.",
},
search: {
title: "Søg i e-mails",
description:
"Søg efter e-mails ved hjælp af Microsofts søgesyntaks",
},
readThread: {
title: "Læs samtale",
description: "Læs hele e-mail-samtaletråden",
},
createDraft: {
title: "Opret udkast",
description:
"Opret et nyt udkast til en e-mail eller et udkast til et svar på en eksisterende besked.",
},
updateDraft: {
title: "Opdateret udkast",
description: "Opdater en eksisterende udkast til en e-mail",
},
listDrafts: {
title: "Udkast til lister",
description: "Vis alle udkastede e-mails",
},
deleteDraft: {
title: "Slet udkast",
description: "Slet en udkast til e-mail",
},
sendDraft: {
title: "Send udkast",
description: "Send en eksisterende udkast til en e-mail",
},
sendEmail: {
title: "Send e-mail",
description:
"Send en ny e-mail eller svar på en eksisterende besked med det samme.",
},
getMailboxStats: {
title: "Statistik for postkasse",
description: "Få antallet af mapper og statistikker for postkasser",
},
},
},
},
mcp: {
title: "MCP-servere",

View File

@@ -542,6 +542,110 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook-Verbindung",
description:
"Ermöglichen Sie Ihrem Agenten, mit Microsoft Outlook zu interagieren Suchen Sie E-Mails, lesen Sie Threads, erstellen Sie Entwürfe, senden Sie E-Mails und verwalten Sie Ihren Posteingang über die Microsoft Graph API. <a> Lesen Sie die Dokumentation</a>.",
multiUserWarning:
"Die Integration mit Outlook ist aus Sicherheitsgründen nicht im Mehrbenutzermodus verfügbar. Um diese Funktion nutzen zu können, bitte den Mehrbenutzermodus deaktivieren.",
configuration: "Konfiguration von Outlook",
authType: "Kontotyp",
authTypeHelp:
"Wählen Sie, welche Arten von Microsoft-Konten zur Authentifizierung verwendet werden können. „Alle Konten“ unterstützt sowohl persönliche als auch Arbeits-/Schulkonten. „Nur persönliche Konten“ beschränkt sich auf persönliche Microsoft-Konten. „Nur Arbeits-/Schulkonten“ beschränkt sich auf Arbeits-/Schulkonten eines bestimmten Azure AD-Mandanten.",
authTypeCommon: "Alle Konten (persönliche und Arbeits-/Schulkonten)",
authTypeConsumers: "Nur persönliche Microsoft-Konten",
authTypeOrganization:
"Nur Konten für Organisationen (benötigt eine Tenant-ID)",
clientId: "Anwendungs-ID (Kunden-ID)",
clientIdHelp:
"Die Anwendungs-ID (Client-ID) von Ihrer Azure AD-Anwendung",
tenantId: "Verzeichnis-ID (Mieter)",
tenantIdHelp:
"Die Verzeichnis-ID (für den Mieter) aus Ihrer Azure AD-App-Registrierung. Dies ist nur für die Authentifizierung innerhalb einer Organisation erforderlich.",
clientSecret: "Client-Schlüssel",
clientSecretHelp:
"Der geheime Wert, den Sie für die Registrierung Ihrer Azure AD-Anwendung festgelegt haben.",
configurationRequired:
"Bitte konfigurieren Sie die Client-ID und den Client-Schlüssel, um die Outlook-Funktionen zu aktivieren.",
authRequired:
"Speichern Sie zuerst Ihre Anmeldedaten, und anschließend melden Sie sich bei Microsoft an, um die Einrichtung abzuschließen.",
authenticateWithMicrosoft: "Mit Microsoft anmelden",
authenticated: "Erfolgreiche Authentifizierung mit Microsoft Outlook.",
revokeAccess: "Zugriff widerrufen",
configured: "Konfiguriert",
searchSkills: "Suchfähigkeiten...",
noSkillsFound:
"Keine der angebotenen Fähigkeiten passen zu Ihrer Suche.",
categories: {
search: {
title: "Nachrichten suchen und lesen",
description:
"Suchen und lesen Sie E-Mails aus Ihrem Outlook-Posteingang.",
},
drafts: {
title: "Entwurf-E-Mails",
description:
"Erstellen, bearbeiten und verwalten von E-Mail-Entwürfen",
},
send: {
title: "E-Mails versenden",
description:
"Neue E-Mails senden oder sofort auf Nachrichten antworten",
},
account: {
title: "Statistiken zur Integration",
description:
"Anzeigen von Postfachstatistiken und Kontoinformationen",
},
},
skills: {
getInbox: {
title: "E-Mail-Postfach öffnen",
description:
"Abrufen von aktuellen E-Mails aus Ihrem Outlook-Posteingang",
},
search: {
title: "E-Mails durchsuchen",
description:
"E-Mails mithilfe der Syntax von Microsoft Search durchsuchen",
},
readThread: {
title: "Lesen der Konversation",
description: "Den vollständigen E-Mail-Austausch durchlesen.",
},
createDraft: {
title: "Entwurf erstellen",
description:
"Erstellen Sie eine neue Entwurf-E-Mail oder einen Entwurf-Antwort auf eine bestehende Nachricht.",
},
updateDraft: {
title: "Entwurf aktualisieren",
description: "Aktualisieren Sie eine bestehende Entwurf-E-Mail",
},
listDrafts: {
title: "Entwurf-Listen",
description: "Zeigen Sie alle Entwurfse-Mails an",
},
deleteDraft: {
title: "Entwurf löschen",
description: "Einen Entwurf einer E-Mail löschen",
},
sendDraft: {
title: "Entwurf senden",
description: "Senden Sie eine bestehende E-Mail-Entwurf",
},
sendEmail: {
title: "E-Mail senden",
description:
"Senden Sie eine neue E-Mail oder antworten Sie sofort auf eine bestehende Nachricht.",
},
getMailboxStats: {
title: "Statistiken für den Posteingang",
description:
"Erhalten Sie Informationen über die Anzahl der Ordner und Statistiken für E-Mail-Postfächer.",
},
},
},
},
"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

@@ -536,6 +536,101 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook Connector",
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:
"Outlook integration is not available in multi-user mode for security reasons. Please disable multi-user mode to use this feature.",
configuration: "Outlook Configuration",
authType: "Account Type",
authTypeHelp:
"Choose which types of Microsoft accounts can authenticate. 'All accounts' supports both personal and work/school accounts. 'Personal only' restricts to personal Microsoft accounts. 'Organization only' restricts to work/school accounts from a specific Azure AD tenant.",
authTypeCommon: "All accounts (personal & work/school)",
authTypeConsumers: "Personal Microsoft accounts only",
authTypeOrganization: "Organization accounts only (requires Tenant ID)",
clientId: "Application (Client) ID",
clientIdHelp:
"The Application (Client) ID from your Azure AD app registration",
tenantId: "Directory (Tenant) ID",
tenantIdHelp:
"The Directory (Tenant) ID from your Azure AD app registration. Required only for organization-only authentication.",
clientSecret: "Client Secret",
clientSecretHelp:
"The client secret value from your Azure AD app registration",
configurationRequired:
"Please configure the Client ID and Client Secret to enable Outlook skills.",
authRequired:
"Save your credentials first, then authenticate with Microsoft to complete the setup.",
authenticateWithMicrosoft: "Authenticate with Microsoft",
authenticated: "Successfully authenticated with Microsoft Outlook.",
revokeAccess: "Revoke Access",
configured: "Configured",
searchSkills: "Search skills...",
noSkillsFound: "No skills match your search.",
categories: {
search: {
title: "Search & Read Emails",
description: "Search and read emails from your Outlook inbox",
},
drafts: {
title: "Draft Emails",
description: "Create, edit, and manage email drafts",
},
send: {
title: "Send Emails",
description: "Send new emails or reply to messages immediately",
},
account: {
title: "Integration Statistics",
description: "View mailbox statistics and account information",
},
},
skills: {
getInbox: {
title: "Get Inbox",
description: "Get recent emails from your Outlook inbox",
},
search: {
title: "Search Emails",
description: "Search emails using Microsoft Search syntax",
},
readThread: {
title: "Read Conversation",
description: "Read a full email conversation thread",
},
createDraft: {
title: "Create Draft",
description:
"Create a new draft email or draft reply to an existing message",
},
updateDraft: {
title: "Update Draft",
description: "Update an existing draft email",
},
listDrafts: {
title: "List Drafts",
description: "List all draft emails",
},
deleteDraft: {
title: "Delete Draft",
description: "Delete a draft email",
},
sendDraft: {
title: "Send Draft",
description: "Send an existing draft email",
},
sendEmail: {
title: "Send Email",
description:
"Send a new email or reply to an existing message immediately",
},
getMailboxStats: {
title: "Mailbox Stats",
description: "Get folder counts and mailbox statistics",
},
},
},
default_skill:
"By default, this skill is enabled, but you can disable it if you don't want it to be available to the agent.",
},

View File

@@ -550,6 +550,111 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Conector de Outlook",
description:
"Permita que su agente interactúe con Microsoft Outlook: buscar correos electrónicos, leer hilos, redactar borradores, enviar correos electrónicos y administrar su bandeja de entrada a través de la API de Microsoft Graph. Consulte la documentación.",
multiUserWarning:
"La integración con Outlook no está disponible en el modo multiusuario por razones de seguridad. Para utilizar esta función, por favor, desactive el modo multiusuario.",
configuration: "Configuración de Outlook",
authType: "Tipo de cuenta",
authTypeHelp:
'Seleccione qué tipos de cuentas de Microsoft pueden autenticarse. "Todas las cuentas" admite tanto cuentas personales como cuentas de trabajo/escuela. "Solo cuentas personales" se limita a cuentas personales de Microsoft. "Solo cuentas de organización" se limita a cuentas de trabajo/escuela de un inquilino específico de Azure AD.',
authTypeCommon: "Todas las cuentas (personales y de trabajo/escuela)",
authTypeConsumers: "Cuentas personales de Microsoft únicamente.",
authTypeOrganization:
"Cuentas de organizaciones únicamente (requiere el ID del inquilino)",
clientId: "Identificador del cliente (solicitante)",
clientIdHelp:
"El ID de la aplicación (cliente) de su registro de aplicación en Azure AD",
tenantId: "ID del inquilino",
tenantIdHelp:
"El ID del directorio (del inquilino) de su registro de aplicación en Azure AD. Es necesario únicamente para la autenticación dentro de una organización.",
clientSecret: "Clave secreta",
clientSecretHelp:
"El valor secreto del cliente de su registro de aplicación en Azure AD.",
configurationRequired:
"Por favor, configure el ID del cliente y la clave secreta para habilitar las funciones de Outlook.",
authRequired:
"Primero, guarde sus credenciales, y luego, utilice las credenciales para autenticarse con Microsoft y completar la configuración.",
authenticateWithMicrosoft: "Autenticarse con Microsoft",
authenticated: "Autenticación exitosa con Microsoft Outlook.",
revokeAccess: "Revocar el acceso",
configured: "Configurado",
searchSkills: "Habilidades de búsqueda...",
noSkillsFound:
"No se encontraron resultados que coincidan con tu búsqueda.",
categories: {
search: {
title: "Buscar y leer correos electrónicos",
description:
"Busque y lea correos electrónicos desde su bandeja de entrada de Outlook.",
},
drafts: {
title: "Borradores de correos electrónicos",
description:
"Crea, edita y gestiona borradores de correos electrónicos.",
},
send: {
title: "Enviar correos electrónicos",
description:
"Envía nuevos correos electrónicos o responde a los mensajes de inmediato.",
},
account: {
title: "Estadísticas de integración",
description:
"Visualice las estadísticas de la bandeja de entrada y la información de la cuenta.",
},
},
skills: {
getInbox: {
title: "Acceder a la bandeja de entrada",
description:
"Consigue los últimos correos electrónicos de tu bandeja de entrada de Outlook.",
},
search: {
title: "Buscar correos electrónicos",
description:
"Busque correos electrónicos utilizando la sintaxis de búsqueda de Microsoft.",
},
readThread: {
title: "Leer la conversación",
description: "Leer toda la conversación por correo electrónico.",
},
createDraft: {
title: "Crear borrador",
description:
"Cree un nuevo borrador de correo electrónico o un borrador de respuesta a un mensaje existente.",
},
updateDraft: {
title: "Versión actualizada del borrador",
description:
"Actualizar un borrador de correo electrónico existente",
},
listDrafts: {
title: "Borradores",
description: "Enumere todas las correos electrónicos en borrador.",
},
deleteDraft: {
title: "Eliminar borrador",
description: "Eliminar un borrador de correo electrónico",
},
sendDraft: {
title: "Enviar borrador",
description: "Enviar un borrador de correo electrónico existente",
},
sendEmail: {
title: "Enviar correo electrónico",
description:
"Envía un nuevo correo electrónico o responde a un mensaje existente de inmediato.",
},
getMailboxStats: {
title: "Estadísticas de la bandeja de entrada",
description:
"Obtén el número de carpetas y estadísticas de la bandeja de entrada.",
},
},
},
},
mcp: {
title: "Servidores MCP",

View File

@@ -523,6 +523,103 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlooki ühineja",
description:
"Laske oma agentil interakteeruda Microsoft Outlookiga otsida e-kirju, lugeda teemasid, luua esialgseid versioone, saata e-kirju ja hallata oma postkasti Microsoft Graph API kaudu. <a>Vaata dokumentatsiooni</a>.",
multiUserWarning:
"Outlooki integratsioon ei ole saadaval mitme kasutaja režiimis turvalisuse huvides. Palun deaktiveeri mitme kasutaja režiim, et kasutada seda funktsiooni.",
configuration: "Outlooki seadistamine",
authType: "Kontoti tüüp",
authTypeHelp:
'Valige, milliseid Microsofti kontode tüüpe saab autentida. "Kõik kontod" toetab nii isiklikke kui ka töö- või kooli kontode. " ainult isiklikud kontod" piirab kasutamise ainult isikliktega Microsofti kontodega. " ainult organisatsioonile kuuluvad kontod" piirab kasutamise ainult töö- või kooli kontodega, mis kuuluvad konkreetsele Azure AD kliendile.',
authTypeCommon: "Kõik kontod (personaalsed ja töö/kooli kontod)",
authTypeConsumers: "V ainult isiklikud Microsofti kontod",
authTypeOrganization:
"Vain organisatsioonide kontod (vajalik Rentniku ID)",
clientId: "Rakenduse (kliendi) ID",
clientIdHelp:
"Rakenduse (kliendi) ID, mis on teie Azure AD rakenduse registreerimisel saadud",
tenantId: "Kinnitusnumber (kasutaja)",
tenantIdHelp:
'"Kinnitusnumber (kasutaja) teie Azure AD rakenduse registreerimise kohta. Nii on vaja ainult organisatsioonide enda autentimiseks."',
clientSecret: "Klientide andmetest saadava teabe turvaandlik kood",
clientSecretHelp:
"Klientide andmevara, mis on saadaval teie Azure AD rakenduse registreerimisel",
configurationRequired:
"Palun konfigureerige kliendi ID ja kliendi salavai, et Outlooki funktsioonid oleksid saadaval.",
authRequired:
"Esiteks salvestage oma andmed, seejärel käivitage Microsoftiga autentimine, et lõpule viia seadistamine.",
authenticateWithMicrosoft:
"Veenduge, et olete Microsoftiga sisselogitud",
authenticated: "Eduka autentimine Microsoft Outlook-iga.",
revokeAccess: "Tõsta juurdepääsu kaotamine",
configured: "Konfigureeritud",
searchSkills: "otsinguteadused...",
noSkillsFound: "Sellele andmetele ei leitud sobivaid tulemusi.",
categories: {
search: {
title: "Abi otsimiseks ja e-kirjade lugemiseks",
description: "Kavatu ja loe oma Outlooki postkasti e-kirju",
},
drafts: {
title: "Esimesed kirjad",
description: "Loo, muuda ja hallata e-kirjade plaane",
},
send: {
title: "Saada e-kirju",
description: "Saada uusi e-kirju või vastata teatele kohe",
},
account: {
title: "Integreerimise statistika",
description: "Vaata postkasti statistikat ja kontoinformatsiooni",
},
},
skills: {
getInbox: {
title: "Ava postkasti",
description: "Vaata viimaseid e-kirju oma Outlook postkasti",
},
search: {
title: "E-kirjade otsing",
description: "Kõnede otsimiseks kasutage Microsofti otsingusünkt.",
},
readThread: {
title: "Loe vestluse",
description: "Vaata kogu e-kirjade vestluse täisteksti",
},
createDraft: {
title: "Loo esialgne versioon",
description:
"Loo uus e-kirja versioon või uus vastamine olemasolevale kirja kohta.",
},
updateDraft: {
title: "Versiooni uuendamine",
description: "Värskendada olemasolevat e-kirja versiooni",
},
listDrafts: {
title: "Esialgne versioon",
description: "Loeda kõik eelnevate kirjade nimekiri",
},
deleteDraft: {
title: "Hüvata projekti",
description: "Hüvida kirjalik e-kiri",
},
sendDraft: {
title: "Saada esialgne versioon",
description: "Saada olemasolev e-kirja esialgne versioon",
},
sendEmail: {
title: "Saada e-kiri",
description:
"Saada uus e-kiri või vastata olemasolevale sõnule kohe",
},
getMailboxStats: {
title: "Postkasti statistika",
description: "Vaata kaustade arvu ja postkasti statistikat",
},
},
},
},
mcp: {
title: "MCP-serverid",

View File

@@ -526,6 +526,103 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "اتصال دهنده Outlook",
description:
"به اپراتور خود اجازه دهید تا با استفاده از Microsoft Outlook ارتباط برقرار کند: جستجو در ایمیل‌ها، خواندن موضوعات، نوشتن پیش‌نویس‌ها، ارسال ایمیل‌ها و مدیریت صندوق ورودی خود از طریق Microsoft Graph API. برای اطلاعات بیشتر، مستندات را مطالعه کنید.",
multiUserWarning:
"ادغام با Outlook در حالت چند کاربر به دلایل امنیتی در دسترس نیست. لطفاً حالت چند کاربر را غیرفعال کنید تا از این ویژگی استفاده کنید.",
configuration: "تنظیمات Outlook",
authType: "نوع حساب",
authTypeHelp:
'انتخاب کنید که کدام نوع از حساب‌های مایکروسافت قابلیت احراز هویت را دارند. گزینه "همه حساب‌ها" از هر دو نوع حساب شخصی و کاری/تحصیلی پشتیبانی می‌کند. گزینه "فقط حساب‌های شخصی" محدود به حساب‌های مایکروسافت شخصی است. گزینه "فقط حساب‌های کاری/تحصیلی" محدود به حساب‌های کاری/تحصیلی از یکテナنت خاص از Azure AD است.',
authTypeCommon: "تمام حساب‌ها (شخصی و مربوط به کار/مدرسه)",
authTypeConsumers: "فقط حساب‌های شخصی مایکروسافت",
authTypeOrganization: "فقط حساب‌های سازمانی (نیاز به شناسه مستاجر)",
clientId: "شناسه کاربر (درخواست)",
clientIdHelp: "شناسه برنامه (کاربر) از ثبت‌نام برنامه در Azure AD",
tenantId: "شناسه (مستأجر)",
tenantIdHelp:
"شناسه (کاربر) از دایرکتوری (Azure AD) که در هنگام ثبت‌نام برنامه شما در Azure AD دریافت کرده‌اید. این شناسه فقط برای احراز هویت در سطح سازمان مورد نیاز است.",
clientSecret: "کلید خصوصی",
clientSecretHelp: "مقدار کلیدی مشتری از ثبت‌نام برنامه شما در Azure AD",
configurationRequired:
"لطفاً شناسه و کلید مخفی (Client ID و Client Secret) را تنظیم کنید تا قابلیت‌های Outlook فعال شوند.",
authRequired:
"ابتدا اطلاعات خود را ذخیره کنید، سپس برای تکمیل فرآیند، با مایکروسافت احراز هویت کنید.",
authenticateWithMicrosoft: "احراز هویت با مایکروسافت",
authenticated: "با موفقیت با Microsoft Outlook احراز هویت شد.",
revokeAccess: "لغو دسترسی",
configured: "تنظیم‌شده",
searchSkills: "مهارت‌های جستجو...",
noSkillsFound: "هیچ یک از مهارت‌های موجود با جستجوی شما مطابقت ندارند.",
categories: {
search: {
title: "جستجو و خواندن ایمیل‌ها",
description: "جستجو و خواندن ایمیل‌ها از صندوق ورودی Outlook",
},
drafts: {
title: "پیش‌نویس ایمیل‌ها",
description: "ایجاد، ویرایش و مدیریت پیش‌نویس‌های ایمیل",
},
send: {
title: "ارسال ایمیل",
description:
"ایمیل‌های جدید را ارسال کنید یا بلافاصله به پیام‌ها پاسخ دهید.",
},
account: {
title: "آمار ادغام",
description: "مشاهده آمار صندوق ایمیل و اطلاعات حساب",
},
},
skills: {
getInbox: {
title: "دسترسی به صندوق ورودی ایمیل",
description:
"آخرین ایمیل‌های خود را از صندوق ورودی Outlook دریافت کنید.",
},
search: {
title: "جستجو در ایمیل‌ها",
description:
"جستجوی ایمیل‌ها با استفاده از دستورالعمل‌های جستجوی مایکروسافت",
},
readThread: {
title: "خواندن مکالمه",
description: "خواندن کل یک مجموعه پیام‌های ایمیلی",
},
createDraft: {
title: "ایجاد پیش‌نویس",
description:
"یک پیش‌نویس ایمیل جدید ایجاد کنید یا یک پاسخ پیش‌نویس برای یک پیام موجود تهیه کنید.",
},
updateDraft: {
title: "نسخه جدید",
description: "به‌روزرسانی یک ایمیل پیش‌نویس موجود",
},
listDrafts: {
title: "فهرست پیش‌نویس‌ها",
description: "لیستی از تمام ایمیل‌های پیش‌نویس تهیه کنید.",
},
deleteDraft: {
title: "حذف پیش‌نویس",
description: "حذف یک پیش‌نویس ایمیل",
},
sendDraft: {
title: "ارسال پیش‌نویس",
description: "یک پیش‌نویس ایمیل موجود را ارسال کنید.",
},
sendEmail: {
title: "ارسال ایمیل",
description:
"یک ایمیل جدید ارسال کنید یا بلافاصله به یک پیام موجود پاسخ دهید.",
},
getMailboxStats: {
title: "آمار صندوق ایمیل",
description:
"تعداد پوشه‌ها و آمار صندوق‌های ایمیل را به دست آورید.",
},
},
},
},
mcp: {
title: "سرورهای MCP",

View File

@@ -539,6 +539,110 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Connecteur Outlook",
description:
"Permettez à votre agent d'interagir avec Microsoft Outlook : rechercher des e-mails, lire les fils de discussion, rédiger des brouillons, envoyer des e-mails et gérer votre boîte de réception via l'API Microsoft Graph. <a>Consultez la documentation</a>.",
multiUserWarning:
"L'intégration avec Outlook n'est pas disponible en mode multi-utilisateurs pour des raisons de sécurité. Veuillez désactiver le mode multi-utilisateurs afin d'utiliser cette fonctionnalité.",
configuration: "Configuration de Outlook",
authType: "Type de compte",
authTypeHelp:
"Choisissez quels types de comptes Microsoft peuvent être utilisés pour l'authentification. « Tous les comptes » prend en charge à la fois les comptes personnels et les comptes professionnels/scolaires. « Seulement les comptes personnels » limite l'utilisation aux comptes Microsoft personnels. « Seulement les comptes professionnels/scolaires » limite l'utilisation aux comptes provenant d'un tenant Azure AD spécifique.",
authTypeCommon:
"Tous les comptes (personnels et professionnels/scolaires)",
authTypeConsumers: "Seuls les comptes Microsoft personnels",
authTypeOrganization:
"Comptes d'organisations uniquement (nécessite l'identifiant du locataire)",
clientId: "Identifiant (Client)",
clientIdHelp:
"L'identifiant de l'application (client) provenant de votre enregistrement d'application dans Azure AD.",
tenantId: "Identifiant (locataire)",
tenantIdHelp:
"L'ID du répertoire (utilisateur) provenant de votre inscription d'application dans Azure AD. Nécessaire uniquement pour l'authentification au sein d'une seule organisation.",
clientSecret: "Clé secrète",
clientSecretHelp:
"La valeur secrète du client provenant de l'enregistrement de votre application Azure AD.",
configurationRequired:
"Veuillez configurer l'ID client et le secret client afin d'activer les fonctionnalités Outlook.",
authRequired:
"Enregistrez d'abord vos informations d'identification, puis authentifiez-vous auprès de Microsoft pour finaliser la configuration.",
authenticateWithMicrosoft: "S'authentifier auprès de Microsoft",
authenticated: "Connexion réussie avec Microsoft Outlook.",
revokeAccess: "Retirer l'accès",
configured: "Configuré",
searchSkills: "Compétences de recherche...",
noSkillsFound: "Aucun résultat correspondant à votre recherche.",
categories: {
search: {
title: "Rechercher et lire des e-mails",
description:
"Recherchez et lisez vos e-mails dans votre boîte de réception Outlook.",
},
drafts: {
title: "Modèles de courriels",
description:
"Créer, modifier et gérer des brouillons de courriels.",
},
send: {
title: "Envoyer des e-mails",
description:
"Envoyer de nouveaux courriels ou répondre immédiatement aux messages.",
},
account: {
title: "Statistiques d'intégration",
description:
"Consultez les statistiques de votre boîte de réception et les informations de votre compte.",
},
},
skills: {
getInbox: {
title: "Accéder à la boîte de réception",
description:
"Récupérez les e-mails récents de votre boîte de réception Outlook.",
},
search: {
title: "Rechercher des e-mails",
description:
"Recherchez des e-mails à l'aide de la syntaxe de recherche de Microsoft.",
},
readThread: {
title: "Lire la conversation",
description: "Lire l'intégralité d'une conversation par e-mail.",
},
createDraft: {
title: "Créer une version préliminaire",
description:
"Créez une nouvelle version d'un courriel ou une réponse à un courriel existant.",
},
updateDraft: {
title: "Version actuelle",
description: "Mettre à jour un brouillon de courriel existant",
},
listDrafts: {
title: "Propositions préliminaires",
description: "Énumérez tous les courriels en brouillon.",
},
deleteDraft: {
title: "Supprimer la version brouillon",
description: "Supprimer une brouillon de courriel",
},
sendDraft: {
title: "Envoyer une version préliminaire",
description: "Envoyer une version existante d'un e-mail",
},
sendEmail: {
title: "Envoyer un e-mail",
description:
"Envoyez un nouvel e-mail ou répondez immédiatement à un message existant.",
},
getMailboxStats: {
title: "Statistiques de la boîte de réception",
description:
"Obtenez le nombre de dossiers et les statistiques des boîtes aux lettres.",
},
},
},
},
mcp: {
title: "Serveurs MCP",

View File

@@ -522,6 +522,98 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "חיבור ל-Outlook",
description:
'אפשר לאגנט שלכם לתקשר עם Microsoft Outlook לחפש הודעות דוא"ל, לקרוא דיונים, ליצור טיוטות, לשלוח הודעות דוא"ל ולנהל תיבת הדואר שלכם באמצעות Microsoft Graph API. <a>קראו את התיעוד</a>.',
multiUserWarning:
"שילוב עם Outlook אינו זמין במצב רב-משתמשים מטעמי אבטחה. אנא בטל את מצב רב-משתמשים כדי להשתמש בתכונה זו.",
configuration: "הגדרת תצורה (Outlook)",
authType: "סוג חשבון",
authTypeHelp:
'בחר איזה סוגי חשבונות מיקרוסופט יכולים לאמת. "כל החשבונות" תומך הן בחשבונות אישיים והן בחשבונות עבודה/לימודים. "רק חשבונות אישיים" מגביל את השימוש לחשבונות מיקרוסופט אישיים בלבד. "רק חשבונות ארגוניים" מגביל את השימוש לחשבונות עבודה/לימודים מחשבון Azure AD ספציפי.',
authTypeCommon: "כל החשבונות (אישיים וקשורים לעבודה/לימודים)",
authTypeConsumers: "חשבונות אישיים של מיקרוסופט בלבד",
authTypeOrganization: "חשבונות רק עבור ארגונים (דורש מזהה שוכר)",
clientId: "מספר זיהוי של לקוח (יישום)",
clientIdHelp: "מזהה היישום (לקוח) מההרשמה של היישום שלך ב-Azure AD",
tenantId: "מספר מזהה (שוכר)",
tenantIdHelp:
"מזהה ה-ID של הלקוח (שוכר) מההרשמה של היישום שלך ב-Azure AD. נדרש רק לאימות מתוך הארגון בלבד.",
clientSecret: "סוד לקוח",
clientSecretHelp:
"הערך הסודי של הלקוח מההרשמה של היישום שלך ב-Azure AD",
configurationRequired:
"אנא הגדירו את מזהה הלקוח והסיסמה כדי לאפשר את יכולות Outlook.",
authRequired:
"שמרו את הפרטים שלכם תחילה, ולאחר מכן השתמשו באימות של מיקרוסופט כדי להשלים את ההגדרה.",
authenticateWithMicrosoft: "אימות באמצעות מיקרוסופט",
authenticated: "התחברות מוצלחת עם Microsoft Outlook.",
revokeAccess: "ביטול גישה",
configured: "מוגדר",
searchSkills: "כישורים במחקר...",
noSkillsFound: "אין התאמות לחיפוש שלך.",
categories: {
search: {
title: 'חיפוש וקריאת הודעות דוא"ל',
description: 'חפש וקרא הודעות דוא"ל מהתיבת הדוא"ל של Outlook שלך.',
},
drafts: {
title: 'הודעות דוא"ל לדוגמה',
description: 'יצירה, עריכה וניהול של טיוטות של הודעות דוא"ל',
},
send: {
title: 'שלח הודעות דוא"ל',
description: "שלחו מיילים חדשים או הגיבו למיילים באופן מיידי.",
},
account: {
title: "נתוני אינטגרציה",
description: "צפו בסטטיסטיקות של תיבת הדואר ובמידע על החשבון.",
},
},
skills: {
getInbox: {
title: "קבל תיבת דואר",
description: "קבל מיילים חדשים מהתיבת הדואר שלך ב-Outlook.",
},
search: {
title: 'חיפוש הודעות דוא"ל',
description: 'חיפוש הודעות דוא"ל באמצעות תחביר החיפוש של Microsoft',
},
readThread: {
title: "קרא שיחה",
description: 'קראו את כל רצף ההודעות בדוא"ל.',
},
createDraft: {
title: "יצירת טיוטה",
description: "צור טיוטת מייל חדשה או טיוטת תגובה למייל קיים.",
},
updateDraft: {
title: "גרסה עדכנית",
description: 'עדכן הודעת דוא"ל קיימת',
},
listDrafts: {
title: "גרסאות ראשוניות",
description: "רשום את כל ההודעות המיילים המוצעות",
},
deleteDraft: {
title: "מחיקת טיוטה",
description: "מחיקת טיוטת אימייל",
},
sendDraft: {
title: "שלח טיוטה",
description: "שלח גרסה קיימת של מייל",
},
sendEmail: {
title: "שלח מייל",
description: "שלח מייל חדש או הגיב למייל קיים באופן מיידי.",
},
getMailboxStats: {
title: "סטטיסטיקות של תיבת דואר",
description: "קבל ספירת תיקיות ונתונים סטטיסטיים עבור תיבות דואר.",
},
},
},
},
mcp: {
title: "שרתי MCP",

View File

@@ -540,6 +540,109 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Connettore Outlook",
description:
"Permetti al tuo agente di interagire con Microsoft Outlook: ricerca email, leggi conversazioni, crea bozze, invia email e gestisci la tua casella di posta elettronica tramite l'API Microsoft Graph. Consulta la documentazione.",
multiUserWarning:
"L'integrazione con Outlook non è disponibile in modalità multiutente per motivi di sicurezza. Per utilizzare questa funzione, è necessario disattivare la modalità multiutente.",
configuration: "Configurazione di Outlook",
authType: "Tipo di account",
authTypeHelp:
"Seleziona quali tipi di account Microsoft possono essere utilizzati per l'autenticazione. L'opzione \"Tutti gli account\" supporta sia account personali che account di lavoro/scuola. L'opzione \"Solo account personali\" limita l'autenticazione a soli account Microsoft personali. L'opzione \"Solo account di organizzazione\" limita l'autenticazione a soli account di lavoro/scuola appartenenti a un tenant specifico di Azure AD.",
authTypeCommon: "Tutti i conti (personali e relativi al lavoro/scuola)",
authTypeConsumers: "Solo account Microsoft personali",
authTypeOrganization:
"Solo account per organizzazioni (richiede l'ID del cliente)",
clientId: "ID del cliente (richiesta)",
clientIdHelp:
"L'ID dell'applicazione (Client ID) dal registro della tua app in Azure AD.",
tenantId: "ID del locatore",
tenantIdHelp:
"L'ID del \"Tenant\" (inquilino) dal registro della tua applicazione Azure AD. È necessario solo per l'autenticazione all'interno di un'organizzazione.",
clientSecret: "Chiave segreta del cliente",
clientSecretHelp:
"Il valore segreto fornito dall'applicazione registrata nel tuo Azure AD",
configurationRequired:
"Si prega di configurare l'ID del cliente e la chiave segreta per abilitare le funzionalità di Outlook.",
authRequired:
"Salva prima le tue credenziali, quindi effettua l'autenticazione con Microsoft per completare la configurazione.",
authenticateWithMicrosoft: "Autenticarsi con Microsoft",
authenticated: "Autenticazione riuscita con Microsoft Outlook.",
revokeAccess: "Revoca l'accesso",
configured: "Configurato",
searchSkills: "Competenze di ricerca...",
noSkillsFound:
"Non sono state trovate corrispondenze per i tuoi criteri di ricerca.",
categories: {
search: {
title: "Cerca e leggi le email",
description:
"Cerca e leggi le e-mail nella tua casella di posta di Outlook.",
},
drafts: {
title: "Bozze di email",
description: "Crea, modifica e gestisci bozze di email.",
},
send: {
title: "Inviare e-mail",
description:
"Invia nuove email o rispondi immediatamente ai messaggi ricevuti.",
},
account: {
title: "Statistiche sull'integrazione",
description:
"Visualizza le statistiche della casella di posta e le informazioni sull'account.",
},
},
skills: {
getInbox: {
title: "Accedi alla casella di posta",
description:
"Recupera le ultime email dalla tua casella di posta di Outlook.",
},
search: {
title: "Cerca nelle email",
description:
"Cerca email utilizzando la sintassi di ricerca di Microsoft",
},
readThread: {
title: "Leggi la conversazione",
description: "Leggi l'intera conversazione via email.",
},
createDraft: {
title: "Crea una bozza",
description:
"Crea una nuova bozza di email o una bozza di risposta a un messaggio esistente.",
},
updateDraft: {
title: "Versione aggiornata",
description: "Aggiornare una bozza di email esistente",
},
listDrafts: {
title: "Proposte",
description: "Elenca tutte le email in bozza.",
},
deleteDraft: {
title: "Elimina bozza",
description: "Elimina una bozza di email",
},
sendDraft: {
title: "Invia bozza",
description: "Invia una bozza di email esistente.",
},
sendEmail: {
title: "Invia e-mail",
description:
"Invia una nuova email o rispondi a un messaggio esistente immediatamente.",
},
getMailboxStats: {
title: "Statistiche della casella di posta",
description:
"Ottieni il numero di cartelle e le statistiche della casella di posta.",
},
},
},
},
mcp: {
title: "Server MCP",

View File

@@ -519,6 +519,102 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook 連携機能",
description:
"エージェントがMicrosoft Outlookと連携できるようにする - Microsoft Graph APIを使用して、メールの検索、スレッドの閲覧、ドラフトの作成、メールの送信、およびインボックスの管理を行う。詳細については、ドキュメントを参照してください。",
multiUserWarning:
"Outlookとの連携は、セキュリティ上の理由から、複数ユーザーモードでは利用できません。この機能を使い始めるには、複数ユーザーモードを無効にする必要があります。",
configuration: "Outlook の設定",
authType: "アカウントの種類",
authTypeHelp:
"認証に使用できるMicrosoftアカウントの種類を選択します。「すべて」は、個人用アカウントと職場/学校用アカウントの両方をサポートします。「個人用のみ」は、個人用Microsoftアカウントに限定されます。「職場/学校用のみ」は、特定のAzure ADテナントからの職場/学校用アカウントに限定されます。",
authTypeCommon: "すべての口座(個人用および仕事/学校用)",
authTypeConsumers: "個人のMicrosoftアカウントのみ",
authTypeOrganization: "組織アカウントのみテナントIDが必要です",
clientId: "アプリケーションクライアントID",
clientIdHelp:
"あなたのAzure ADアプリケーションの「アプリケーションクライアントID」",
tenantId: "テナントID",
tenantIdHelp:
"あなたの Azure AD アプリの登録から取得した「ディレクトリテナントID」。組織での認証のみに必要です。",
clientSecret: "クライアントの秘密",
clientSecretHelp:
"Azure AD アプリの登録から取得したクライアントのシークレット値",
configurationRequired:
"Outlook の機能を有効にするには、クライアント ID とクライアントシークレットを設定してください。",
authRequired:
"まず、認証情報を保存し、その後、Microsoftとの認証を行い、設定を完了してください。",
authenticateWithMicrosoft: "マイクロソフトとの認証",
authenticated: "Microsoft Outlookとの認証に成功しました。",
revokeAccess: "アクセス権を停止する",
configured: "設定済み",
searchSkills: "検索スキル...",
noSkillsFound: "検索条件に一致するスキルは見つかりませんでした。",
categories: {
search: {
title: "メールの検索と閲覧",
description: "Outlook の受信トレイから、メールを検索して読み取る。",
},
drafts: {
title: "サンプルメール",
description: "メールの作成、編集、および管理",
},
send: {
title: "メールの送信",
description:
"新しいメールを送信するか、すぐにメッセージに返信してください。",
},
account: {
title: "統合に関する統計",
description: "メールボックスの統計情報とアカウント情報を確認する",
},
},
skills: {
getInbox: {
title: "受信トレイを開く",
description: "Outlook の受信トレイから、最近のメールを取得する",
},
search: {
title: "メールを検索する",
description: "Microsoft の検索構文を使用してメールを検索する",
},
readThread: {
title: "会話の内容を読み取る",
description: "メールのやり取り全体を読み込む",
},
createDraft: {
title: "ドラフト作成",
description:
"新しいメールの草案を作成するか、既存のメッセージへの返信の草案を作成する。",
},
updateDraft: {
title: "ドラフトの更新",
description: "既存のメールドラフトを更新する",
},
listDrafts: {
title: "ドラフト案リスト",
description: "すべての草案メールの一覧",
},
deleteDraft: {
title: "草案を削除",
description: "草案のメールを削除する",
},
sendDraft: {
title: "草案を送信",
description: "既存のメールの草稿を送信する",
},
sendEmail: {
title: "メールを送信する",
description:
"新しいメールを作成するか、既存のメッセージにすぐに返信してください。",
},
getMailboxStats: {
title: "メールボックスの統計",
description: "フォルダの数とメールボックスの統計情報を取得する",
},
},
},
},
mcp: {
title: "MCP サーバー",

View File

@@ -523,6 +523,99 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "아웃룩 연결",
description:
"Microsoft Outlook와 상호 작용할 수 있도록 에이전트에게 Microsoft Graph API를 사용하도록 설정합니다. 이메일 검색, 스레드 읽기, 초안 작성, 이메일 전송, 그리고 Microsoft Graph API를 통해 이메일함을 관리할 수 있습니다. 자세한 내용은 <a>문서를 참조하세요</a>.",
multiUserWarning:
"Outlook 통합 기능은 보안상의 이유로 다중 사용자 모드에서는 사용할 수 없습니다. 이 기능을 사용하려면 다중 사용자 모드를 비활성화해 주십시오.",
configuration: "아웃룩 설정",
authType: "계정 유형",
authTypeHelp:
"인증할 수 있는 Microsoft 계정 유형을 선택합니다. '모든 계정'은 개인 및 업무/학교 계정을 모두 지원합니다. '개인 계정만'은 개인 Microsoft 계정에만 적용됩니다. '특정 Azure AD 테넌트의 계정만'은 특정 Azure AD 테넌트의 업무/학교 계정에만 적용됩니다.",
authTypeCommon: "모든 계정 (개인 계정 및 직장/학교 계정)",
authTypeConsumers: "개인 Microsoft 계정만 해당",
authTypeOrganization: "단순히 조직 계정만 (세입자 ID 필요)",
clientId: "애플리케이션 (고객) ID",
clientIdHelp:
"당신의 Azure AD 애플리케이션 등록 시 얻은 애플리케이션(클라이언트) ID",
tenantId: "임대인 ID",
tenantIdHelp:
"Azure AD 애플리케이션 등록 시 얻은 (임차인) ID. 조직 내 사용자만 인증하는 경우에만 필요합니다.",
clientSecret: "고객 비밀",
clientSecretHelp: "Azure AD 애플리케이션 등록 시 얻은 클라이언트 비밀",
configurationRequired:
"아웃룩 기능을 사용하려면 클라이언트 ID와 클라이언트 비밀을 설정해 주세요.",
authRequired:
"먼저 사용자 정보를 저장한 다음, Microsoft를 통해 계정을 인증하여 설정 과정을 완료하십시오.",
authenticateWithMicrosoft: "마이크로소프트와 인증",
authenticated: "Microsoft Outlook와 성공적으로 인증되었습니다.",
revokeAccess: "접근 권한 취소",
configured: "설정됨",
searchSkills: "검색 기술...",
noSkillsFound: "검색하신 조건과 일치하는 기술이 없습니다.",
categories: {
search: {
title: "이메일 검색 및 읽기",
description: "Outlook 계정의 이메일을 검색하고 읽으세요.",
},
drafts: {
title: "샘플 이메일",
description: "이메일 초안을 작성, 편집 및 관리",
},
send: {
title: "이메일 보내기",
description: "새로운 이메일을 보내거나, 즉시 메시지에 응답",
},
account: {
title: "통합 통계",
description: "메일함 통계 및 계정 정보 확인",
},
},
skills: {
getInbox: {
title: "메일함 보기",
description: "최근에 받은 이메일을 Outlook 계정에서 확인",
},
search: {
title: "이메일 검색",
description: "Microsoft 검색 구문을 사용하여 이메일 검색",
},
readThread: {
title: "대화 내용 읽기",
description: "전체 이메일 대화 내용을 읽기",
},
createDraft: {
title: "초안 작성",
description:
"새로운 이메일 초안을 작성하거나 기존 메시지에 대한 답변 초안을 작성합니다.",
},
updateDraft: {
title: "초안 업데이트",
description: "기존 이메일 초안을 업데이트합니다.",
},
listDrafts: {
title: "초안 목록",
description: "모든 초안 이메일 목록을 표시",
},
deleteDraft: {
title: "초안 삭제",
description: "초안 이메일을 삭제",
},
sendDraft: {
title: "초안 보내기",
description: "기존 이메일 초안을 보내기",
},
sendEmail: {
title: "이메일 보내기",
description: "새로운 이메일을 보내거나 기존 메시지에 즉시 응답",
},
getMailboxStats: {
title: "메일함 통계",
description: "폴더 수와 메일함 통계 정보를 확인합니다.",
},
},
},
},
mcp: {
title: "MCP 서버",

View File

@@ -542,6 +542,108 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "„Outlook“ integracija",
description:
"Įgalinkite savo agentą, kad galėtų bendrauti su „Microsoft Outlook“ ieškoti pašto, skaityti pokalbį, kurti projektus, siųsti paštą ir valdyti savo pašto dėžę per „Microsoft Graph“ API. <a>Peržiūrėkite dokumentaciją</a>.",
multiUserWarning:
"„Outlook“ integracija negalima naudoti kelių vartotojų režimu dėl saugumo priežasčių. Norėdami naudoti šią funkciją, prašome išjungti kelių vartotojų režimą.",
configuration: "Outlook konfigūracija",
authType: "Sąskaitos tipas",
authTypeHelp:
"Pasirinkite, kokie Microsoft sąskaitos gali būti patvirtintos. „Visi“ palaiko tiek asmenines, tiek darbo/mokyklos sąskaitas. „Tik asmeninės“ riboja pasirinkimą iki asmeninių Microsoft sąskaitų. „Tik organizacijos“ riboja pasirinkimą iki darbo/mokyklos sąskaitų iš konkretaus „Azure AD“ kliento.",
authTypeCommon: "Visos sąskaitos (asmeninės ir darbo/mokyklos)",
authTypeConsumers: "Tiesiog asmeninės Microsoft paskyros",
authTypeOrganization:
"Tiesiog organizacijos sąskaitos (reikia užpildyti „Užimtojo ID“ laukelį)",
clientId: "Programos (kliento) ID",
clientIdHelp:
"Programos (kliento) ID, gautas iš jūsų „Azure AD“ programos registracijos",
tenantId: "Identifikavimo numeris (nuomininkas)",
tenantIdHelp:
"„Tenant“ ID iš jūsų „Azure AD“ programos registracijos. Reikalingas tik, jei autentifikacija vykdoma tik organizacijos naudotojams.",
clientSecret: "Kliento slaptas kodas",
clientSecretHelp:
"Kliento paslaptas reikalas, gautas iš jūsų „Azure AD“ programos registracijos",
configurationRequired:
"Prašome nustatyti kliento ID ir kliento slaptažodį, kad būtų įgalintos Outlook funkcijos.",
authRequired:
"Pirmiausia, išsaugokite savo duomenis, o tada, kad užbaigtumėte konfigūraciją, prisijunkite prie „Microsoft“.",
authenticateWithMicrosoft: "Patvirtinkite naudodami Microsoft",
authenticated: "Sėkmingai prisijungta prie „Microsoft Outlook“.",
revokeAccess: "Atšalinti prieigą",
configured: "Nustatytas",
searchSkills: "Paieškos įgūdžiai...",
noSkillsFound: "Nėra atitikčių jūsų paieškai.",
categories: {
search: {
title: "Paieškos ir skaitymas el. paštą",
description:
"Paieškokite ir skaitykite el. pašto laiškus iš savo Outlook sąrašo",
},
drafts: {
title: "Pasiūlytų el. pašto laiškų",
description: "Sukurkite, redaguo, ir valdykite el. pašto rašinius.",
},
send: {
title: "Siųstis el. pašto žinutes",
description:
"Siųkite naujus el. laiškus arba atsakykite į pranešimus nedelskant",
},
account: {
title: "Integracijos statistika",
description:
"Peržiūrėkite pašto dėžės statistikos ir sąskaitos informaciją.",
},
},
skills: {
getInbox: {
title: "Peržiūrėti pašto dėžę",
description:
"Gaukite naujausius el. pašto laiškus iš savo Outlook sąvejos.",
},
search: {
title: "Paieškos el. paštu",
description:
"Paieškokite el. laiškus naudodami „Microsoft Search“ sintaksę.",
},
readThread: {
title: "Perskaitykite pokalbį",
description: "Perskaitykite visą el. pašto pokalbio seką.",
},
createDraft: {
title: "Sukurti projekto variantą",
description:
"Sukurkite naują el. pašto projekto arba atsakymo projekto į esamą pranešimą.",
},
updateDraft: {
title: "Paskaitos projekto atnaujinimas",
description: "Atnaujinkite esamą el. pašto projekto",
},
listDrafts: {
title: "Paskaitų planas",
description: "Parodykite visus projekto el. laiškus",
},
deleteDraft: {
title: "Ištrinkti projekto",
description: "Ištrinkite projekto el. laišką",
},
sendDraft: {
title: "Siųstis projekto",
description: "Siųstis jau esančią el. pašto projekto versiją",
},
sendEmail: {
title: "Siųstis el. paštą",
description:
"Siųstinkite naują el. laišką arba atsakykite į esamą pranešimą nedelsdami.",
},
getMailboxStats: {
title: "Pašto dėžės statistika",
description:
"Gaukite folderių skaičius ir pašto dėžutės statistikos duomenis.",
},
},
},
},
mcp: {
title: "MCP serveriai",

View File

@@ -538,6 +538,109 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook savienojums",
description:
"Ļaujiet savam pārstāvim interaktīvi darboties ar Microsoft Outlook meklēt e-pasta ziņojus, lasīt diskusijas, veidot projektejus, nosūtīt e-pasta ziņojus un pārvaldīt savu e-pasta skapis, izmantojot Microsoft Graph API. <a>Izlasiet dokumentāciju</a>.",
multiUserWarning:
'"Outlook 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: "Outlook iestatījumu konfigurēšana",
authType: "Aģenta veids",
authTypeHelp:
'Izvēlieties, kādas Microsoft kontu tipus var autentificēt. "Visas kontas" atbalsta gan personiskus, gan darba/skolas kontus. "Tikai personiskie konti" ierobežo izmantošanu tikai ar personiskiem Microsoft kontiem. "Tikai organizācijas konti" ierobežo izmantošanu tikai ar darba/skolas kontiem no konkrēta Azure AD klienta.',
authTypeCommon: "Visas kontas (personālās un darba/skolas)",
authTypeConsumers: "Personiskas Microsoft kontas tikai",
authTypeOrganization:
"Tikai organizācijas konti (nepieciešams īpašnieka ID)",
clientId: "Pieteikuma (Klienta) ID",
clientIdHelp:
"Pieteikuma (klienta) ID no jūsu Azure AD lietojamās programmas reģistrācijas",
tenantId: "Reģistrācijas numurs (īres lietotājs)",
tenantIdHelp:
'"Klienta" ID no jūsu Azure AD lietojumprogrammas reģistrācijas. Nepieciešams tikai, ja tiek izmantota tikai organizācijas autentifikācija.',
clientSecret: "Klienta slepšvārds",
clientSecretHelp:
"Klienta slepenas vērtība, kas iegūta no jūsu Azure AD lietojamās programmas reģistrācijas",
configurationRequired:
"Lūdzu, konfigurējiet klienta ID un klienta sleptu atslēgu, lai iespējotu Outlook funkcijas.",
authRequired:
"Pirms sākat, saglabājiet savus autentifikācijas datus, un pēc tam veiciet autentifikāciju, lai pabeigtu konfigurēšanu.",
authenticateWithMicrosoft: "Autentizējieties ar Microsoft",
authenticated: "Izdevīgi sarakstījies ar Microsoft Outlook.",
revokeAccess: "Atcel piekļuvi",
configured: "Ierādīts",
searchSkills: "Meklēšanas prasmes...",
noSkillsFound: "Neatrastas atbilstošas prasmes jūsu meklējumiem.",
categories: {
search: {
title: "Meklē un lasiet e-pastus",
description:
"Meklējiet un lasiet e-pasta ziņojus no jūsu Outlook skapis",
},
drafts: {
title: "Pamatraksti e-pasta vēstījumiem",
description: "Izveidot, rediģēt un pārvaldīt e-pasta rakstus",
},
send: {
title: "Nosūtīt e-pastus",
description:
"Sūtiet jaunas e-pasta vēstules vai atbildiet uz saņemtajām vēstnēm nekavējoties.",
},
account: {
title: "Integrācijas statistika",
description:
"Apskatiet pasta kastes statistiku un konta informāciju.",
},
},
skills: {
getInbox: {
title: "Atsvērt e-pasta skatīšanās reklāžu",
description:
"Iegūstiet jaunākos e-pasta ziņojus no jūsu Outlook skapis",
},
search: {
title: "Meklē e-pastus",
description:
"Meklē e-pasta ziņojus, izmantojot Microsoft meklēšanas sintaksi",
},
readThread: {
title: "Izlasiet sarunu",
description: "Izlasiet pilnu e-pasta sarunu",
},
createDraft: {
title: "Izveidot projekta versiju",
description:
"Izveidot jaunu e-pasta projekta rakstu vai atbildes projektu esošam ziņojumam.",
},
updateDraft: {
title: "Pēcmājas projekts",
description: "Atjaunināt esošo e-pasta projekta",
},
listDrafts: {
title: "Izstrādāto variantu saraksts",
description:
"Izveidot sarakstu ar visiem izstrādātajiem e-pasta vēstījumiem",
},
deleteDraft: {
title: "Dzēst projekta versiju",
description: "Dzēst izstrādāto e-pastu",
},
sendDraft: {
title: "Nosūtīt projekta versiju",
description: "Nosūtiet esošā e-pasta projekta versiju",
},
sendEmail: {
title: "Sūtīt e-pastu",
description:
"Sūtiet jaunu e-pastu vai atbildiet uz esošu ziņu nekavējoties.",
},
getMailboxStats: {
title: "Pasta kastes statistika",
description:
"Iesaļojiet mapeņu skaitu un e-pasta kontu statistiku.",
},
},
},
},
mcp: {
title: "MCP serveri",

View File

@@ -530,6 +530,106 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook-connector",
description:
"Laat uw agent in staat zijn om met Microsoft Outlook te communiceren: e-mails zoeken, threads lezen, concepten opstellen, e-mails versturen en uw inbox beheren via de Microsoft Graph API. Raadpleeg de documentatie.",
multiUserWarning:
"De integratie met Outlook is niet beschikbaar in de modus voor meerdere gebruikers, vanwege veiligheidsoverwegingen. Om deze functie te gebruiken, moet u de modus voor meerdere gebruikers uitschakelen.",
configuration: "Outlook-configuratie",
authType: "Type account",
authTypeHelp:
'Kies welke soorten Microsoft-accounts kunnen worden gebruikt voor authenticatie. "Alle accounts" ondersteunt zowel persoonlijke als werk-/schoolaccounts. "Alleen persoonlijke accounts" beperkt zich tot persoonlijke Microsoft-accounts. "Alleen werk-/schoolaccounts" beperkt zich tot werk-/schoolaccounts van een specifieke Azure AD-tenant.',
authTypeCommon:
"Alle rekeningen (persoonlijke en zakelijke/schoolrekeningen)",
authTypeConsumers: "Alleen persoonlijke Microsoft-accounts",
authTypeOrganization:
"Alleen accounts voor organisaties (vereist Tenant-ID)",
clientId: "Toepassings-ID (klant)",
clientIdHelp:
"De applicatie-ID (ook wel Client ID genoemd) van uw Azure AD-applicatie.",
tenantId: "Identificatienummer (huurder)",
tenantIdHelp:
"De Directory (Tenant) ID uit uw Azure AD-appregistratie. Vereist alleen voor authenticatie binnen een organisatie.",
clientSecret: "Geheime sleutel",
clientSecretHelp: "De geheime waarde van uw Azure AD-appregistratie",
configurationRequired:
"Configureer de Client ID en Client Secret om de Outlook-functionaliteit te activeren.",
authRequired:
"Sla eerst uw gegevens op, en voer vervolgens de authenticatie uit bij Microsoft om het proces te voltooien.",
authenticateWithMicrosoft: "Authenticeer met Microsoft",
authenticated: "Succesvol verbonden met Microsoft Outlook.",
revokeAccess: "Toegang intrekken",
configured: "Geconfigureerd",
searchSkills: "Vaardigheden op het gebied van zoeken...",
noSkillsFound:
"Geen overeenkomende vaardigheden zijn gevonden op basis van uw zoekopdracht.",
categories: {
search: {
title: "Zoeken en e-mails lezen",
description: "Zoek en lees e-mails uit uw Outlook inbox.",
},
drafts: {
title: "Voorbeeld e-mails",
description: "Maak, bewerk en beheer e-mailvoorstellen.",
},
send: {
title: "Verzend e-mails",
description:
"Verzend nieuwe e-mails of reageer onmiddellijk op berichten.",
},
account: {
title: "Statistieken over integratie",
description:
"Bekijk statistieken en accountinformatie van uw e-mail.",
},
},
skills: {
getInbox: {
title: "Open de inbox",
description: "Bekijk recente e-mails uit uw Outlook inbox.",
},
search: {
title: "Zoeken in e-mails",
description:
"Zoek naar e-mails met behulp van de syntax van Microsoft Search",
},
readThread: {
title: "Lees het gesprek",
description: "Lees het volledige e-mailgesprek",
},
createDraft: {
title: "Maak een concept",
description:
"Maak een nieuwe concept-e-mail of een concept-antwoord op een bestaande bericht.",
},
updateDraft: {
title: "Versie",
description: "Pas een bestaand concept e-mail aan",
},
listDrafts: {
title: "Ontwerpen",
description: "Maak een lijst van alle concept-e-mails.",
},
deleteDraft: {
title: "Verwijder concept",
description: "Verwijder een concept-e-mail",
},
sendDraft: {
title: "Verzend concept",
description: "Verzend een bestaand e-mailontwerp.",
},
sendEmail: {
title: "Stuur e-mail",
description:
"Verzend een nieuw e-mail of reageer direct op een bestaande bericht.",
},
getMailboxStats: {
title: "Statistieken van de e-mailbox",
description: "Haal de aantallen mappen en mailbox-statistieken op.",
},
},
},
},
mcp: {
title: "MCP-servers",

View File

@@ -542,6 +542,110 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Łącznik Outlook",
description:
"Pozwól swojemu agentowi na interakcję z Microsoft Outlook wyszukiwanie wiadomości e-mail, czytanie wątków, tworzenie projektów, wysyłanie wiadomości e-mail oraz zarządzanie skrzynką odbiorczą za pomocą Microsoft Graph API. <a>Przeczytaj dokumentację</a>.",
multiUserWarning:
"Integracja z Outlookiem nie jest dostępna w trybie wieloosobowym z powodów bezpieczeństwa. Aby skorzystać z tej funkcji, należy wyłączyć tryb wieloosobowy.",
configuration: "Konfiguracja Outlooka",
authType: "Typ konta",
authTypeHelp:
"Wybierz, które typy kont Microsoft mogą być używane do logowania. Opcja „Wszystkie konta” obsługuje zarówno konta osobiste, jak i konta związane z pracą/szkołą. Opcja „Tylko konta osobiste” ogranicza się do kont Microsoft stworzonych przez użytkowników. Opcja „Tylko konta organizacji” ogranicza się do kont z określonego tenanta Azure AD.",
authTypeCommon: "Wszystkie konta (osobiste i związane z pracą/szkołą)",
authTypeConsumers:
"Tylko konta Microsoft dla pojedynczych użytkowników.",
authTypeOrganization:
"Konta tylko dla organizacji (wymaga identyfikatora najemcy)",
clientId: "Identyfikator klienta (zwrócony przez aplikację)",
clientIdHelp:
"Identyfikator aplikacji (klienta) z rejestracji w Azure AD",
tenantId: "Identyfikator (osoby wynajmującej)",
tenantIdHelp:
"Identyfikator (dla najemcy) z rejestracji aplikacji w Azure AD. Wymagany tylko w przypadku uwierzytelniania tylko dla danej organizacji.",
clientSecret: "Klucz API",
clientSecretHelp:
"Wartość klienta, którą podali podczas rejestracji aplikacji w Azure AD",
configurationRequired:
"Prosimy o skonfigurowanie identyfikatora klienta i sekretu klienta, aby włączyć funkcje Outlook.",
authRequired:
"Najpierw zapisz swoje dane, a następnie zaloguj się przez Microsoft, aby dokończyć konfigurację.",
authenticateWithMicrosoft: "Zaloguj się przy użyciu konta Microsoft",
authenticated: "Pomyślnie uwierzytelniono w Microsoft Outlook.",
revokeAccess: "Wydać uprawnienia",
configured: "Skonfigurowany",
searchSkills: "Umiejętności wyszukiwania...",
noSkillsFound:
"Nie znaleziono żadnych kandydatów, którzy spełniałyby Twoje kryteria.",
categories: {
search: {
title: "Wyszukaj i przeczytaj wiadomości e-mail",
description: "Wyszukuj i czytaj e-maile z swojej poczty Outlook.",
},
drafts: {
title: "Proponowane wiadomości e-mail",
description: "Twórz, edytuj i zarządzaj wersjami e-maili.",
},
send: {
title: "Wysyłaj e-maile",
description:
"Wysyłaj nowe wiadomości e-mail lub odpowiadaj na wiadomości natychmiast.",
},
account: {
title: "Statystyki dotyczące integracji",
description:
"Przejrzyj statystyki skrzynki pocztowej oraz informacje dotyczące konta.",
},
},
skills: {
getInbox: {
title: "Otwórz skrzynkę odbiorczą",
description:
"Otrzymuj najnowsze wiadomości e-mail ze swojej poczty Outlook.",
},
search: {
title: "Wyszukaj wiadomości",
description:
"Wyszukuj wiadomości e-mail, używając składni wyszukiwania Microsoft",
},
readThread: {
title: "Przeczytaj rozmowę",
description: "Przeczytaj pełną korespondencję mailową.",
},
createDraft: {
title: "Stwórz wersję roboczą",
description:
"Utwórz nowy projekt wiadomości e-mail lub zaproponowany odpowiedź na istniejącą wiadomość.",
},
updateDraft: {
title: "Aktualizacja wersji roboczej",
description: "Zaktualizuj istniejący projekt wiadomości e-mail",
},
listDrafts: {
title: "Proponowane wersje",
description:
"Wyświetl wszystkie wersje e-maili w trakcie tworzenia.",
},
deleteDraft: {
title: "Usuń wersję roboczą",
description: "Usuń wersję roboczą wiadomości e-mail",
},
sendDraft: {
title: "Wyślij wersję roboczą",
description: "Wyślij istniejący projekt wiadomości e-mail",
},
sendEmail: {
title: "Wyślij e-mail",
description:
"Wyślij nową wiadomość e-mail lub odpowiedz na istniejącą wiadomość natychmiast.",
},
getMailboxStats: {
title: "Statystyki skrzynki pocztowej",
description:
"Uzyskaj liczbę folderów oraz statystyki dotyczące skrzynki pocztowej.",
},
},
},
},
mcp: {
title: "Serwery MCP",

View File

@@ -539,6 +539,108 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Conector do Outlook",
description:
"Permita que seu agente interaja com o Microsoft Outlook: pesquise e-mails, leia conversas, crie rascunhos, envie e-mails e gerencie sua caixa de entrada através da API Microsoft Graph. <a>Leia a documentação</a>.",
multiUserWarning:
"A integração com o Outlook 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 Outlook",
authType: "Tipo de conta",
authTypeHelp:
'Selecione quais tipos de contas Microsoft podem ser autenticadas. "Todas as contas" suporta tanto contas pessoais quanto contas de trabalho/escola. "Apenas contas pessoais" restringe a contas Microsoft pessoais. "Apenas contas de organização" restringe a contas de trabalho/escola de um tenant específico do Azure AD.',
authTypeCommon: "Todas as contas (pessoais e de trabalho/escola)",
authTypeConsumers: "Contas pessoais da Microsoft",
authTypeOrganization: "Contas de organizações (requer ID do inquilino)",
clientId: "Identificador do Cliente",
clientIdHelp:
"O ID da aplicação (cliente) do seu registo de aplicação no Azure AD",
tenantId: "ID do Inquilino",
tenantIdHelp:
"O ID do diretório (do inquilino) da sua aplicação no Azure AD. É necessário apenas para a autenticação dentro de uma única organização.",
clientSecret: "Chave Secreta do Cliente",
clientSecretHelp:
"O valor secreto do cliente da sua aplicação registada no Azure AD",
configurationRequired:
"Por favor, configure o ID do Cliente e o Segredo do Cliente para habilitar as funcionalidades do Outlook.",
authRequired:
"Primeiro, salve suas credenciais, e então autentique-se com a Microsoft para concluir a configuração.",
authenticateWithMicrosoft: "Autentique-se com a Microsoft",
authenticated: "Autenticação bem-sucedida com o Microsoft Outlook.",
revokeAccess: "Revogar o acesso",
configured: "Configurado",
searchSkills: "Habilidades de pesquisa...",
noSkillsFound:
"Não encontramos nenhuma correspondência com os seus critérios de pesquisa.",
categories: {
search: {
title: "Pesquisar e ler e-mails",
description:
"Pesquise e leia e-mails da sua caixa de entrada do Outlook.",
},
drafts: {
title: "Rascunhos de e-mails",
description: "Crie, edite e gerencie rascunhos de e-mails.",
},
send: {
title: "Enviar e-mails",
description:
"Envie novos e-mails ou responda às mensagens imediatamente.",
},
account: {
title: "Estatísticas de integração",
description:
"Visualize estatísticas da caixa de correio e informações da conta.",
},
},
skills: {
getInbox: {
title: "Acesse a caixa de entrada",
description:
"Acesse e-mails recentes da sua caixa de entrada do Outlook.",
},
search: {
title: "Pesquisar e-mails",
description:
"Pesquise e-mails usando a sintaxe de pesquisa do Microsoft.",
},
readThread: {
title: "Leia a conversa",
description: "Leia toda a sequência de e-mails.",
},
createDraft: {
title: "Criar rascunho",
description:
"Crie um novo rascunho de e-mail ou um rascunho de resposta a uma mensagem existente.",
},
updateDraft: {
title: "Versão atualizada",
description: "Atualizar um rascunho de e-mail existente",
},
listDrafts: {
title: "Rascunhos",
description: "Liste todos os e-mails em rascunho.",
},
deleteDraft: {
title: "Excluir rascunho",
description: "Excluir uma versão preliminar de um e-mail",
},
sendDraft: {
title: "Enviar rascunho",
description: "Envie uma versão prévia de um e-mail existente",
},
sendEmail: {
title: "Enviar e-mail",
description:
"Envie um novo e-mail ou responda a uma mensagem existente imediatamente.",
},
getMailboxStats: {
title: "Estatísticas da caixa de correio",
description:
"Obtenha o número de pastas e estatísticas da caixa de correio.",
},
},
},
},
mcp: {
title: "Servidores MCP",

View File

@@ -989,6 +989,110 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Conector Outlook",
description:
"Permiteți-i agentului dumneavoastră să interacționeze cu Microsoft Outlook să caute e-mailuri, să citească conversații, să redacteze proiecte, să trimită e-mailuri și să gestioneze folderul de intrare, folosind Microsoft Graph API. Consultați documentația aici.",
multiUserWarning:
"Integrarea cu Outlook nu este disponibilă în modul pentru utilizatori multipli, din motive de securitate. Vă rugăm să dezactivați modul pentru utilizatori multipli pentru a utiliza această funcție.",
configuration: "Configurarea Outlook-ului",
authType: "Tip de cont",
authTypeHelp:
"Selectați ce tipuri de conturi Microsoft pot fi utilizate pentru autentificare. Opțiunea „Toate conturile” permite autentificarea atât pentru conturi personale, cât și pentru conturi de lucru/școlare. Opțiunea „Doar conturi personale” limitează autentificarea la conturi Microsoft personale. Opțiunea „Doar conturi de organizație” limitează autentificarea la conturi de lucru/școlare dintr-un anumit tenant Azure AD.",
authTypeCommon:
"Toate conturile (personale și cele legate de muncă/școală)",
authTypeConsumers: "Conturile personale Microsoft sunt acceptate.",
authTypeOrganization:
"Conturi pentru organizații (necesită ID-ul chiriașului)",
clientId: "Identificator (pentru client)",
clientIdHelp:
"Identificatorul aplicației (Client) din înregistrarea aplicației dumneavoastră Azure AD",
tenantId: "Codul identificator (pentru chiriaș)",
tenantIdHelp:
"ID-ul din director (pentru chiriaș) din înregistrarea aplicației dumneavoastră Azure AD. Este necesar doar pentru autentificare, utilizată exclusiv de organizație.",
clientSecret: "Confidențialitatea clientului",
clientSecretHelp:
"Valoarea secretă a clientului, obținută în urma înregistrării aplicației dvs. în Azure AD",
configurationRequired:
"Vă rugăm să configurați ID-ul clientului și Secretul clientului pentru a activa funcționalitățile Outlook.",
authRequired:
"În primul rând, salvați-vă datele de autentificare, apoi autentificați-vă cu Microsoft pentru a finaliza configurarea.",
authenticateWithMicrosoft: "Autentificați-vă cu Microsoft",
authenticated: "Autentificare reușită cu Microsoft Outlook.",
revokeAccess: "Anula accesul",
configured: "Configurat",
searchSkills: "Abilități de căutare...",
noSkillsFound:
"Nu s-au găsit rezultate care să corespundă criteriilor dumneavoastră de căutare.",
categories: {
search: {
title: "Caută și citește e-mailuri",
description:
"Căutați și citiți e-mailuri din folderul dumneavoastră Outlook",
},
drafts: {
title: "Propuneri de e-mail",
description: "Creați, editați și gestionați schițele de e-mail.",
},
send: {
title: "Trimite e-mailuri",
description:
"Trimiteți e-mailuri noi sau răspundeți imediat la mesajele primite.",
},
account: {
title: "Statistici privind integrarea",
description:
"Vizualizați statistici privind cutia poștală și informații despre cont",
},
},
skills: {
getInbox: {
title: "Accesați inbox-ul",
description:
"Accesați email-urile recente din dosarul dvs. Outlook.",
},
search: {
title: "Căutați în e-mailuri",
description:
"Căutați în e-mailuri folosind sintaxa de căutare Microsoft",
},
readThread: {
title: "Citește conversația",
description: "Citește întreaga corespondență prin e-mail.",
},
createDraft: {
title: "Creați o versiune preliminară",
description:
"Creați un e-mail nou sau un răspuns la un e-mail existent.",
},
updateDraft: {
title: "Actualizare proiect",
description: "Actualizați un e-mail existent, draft",
},
listDrafts: {
title: "Propuneri",
description: "Enumerați toate e-mailurile draft",
},
deleteDraft: {
title: "Șterge schița",
description: "Șterge un proiect de e-mail",
},
sendDraft: {
title: "Trimite versiunea preliminară",
description: "Trimite un e-mail existent, draft",
},
sendEmail: {
title: "Trimite e-mail",
description:
"Trimiteți un nou e-mail sau răspundeți imediat la un mesaj existent.",
},
getMailboxStats: {
title: "Statistici cutie poștală",
description:
"Obține numărul de foldere și statisticile pentru cutiile de e-mail.",
},
},
},
},
mcp: {
title: "Servere MCP",

View File

@@ -533,6 +533,109 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Подключение к Outlook",
description:
"Позвольте своему агенту взаимодействовать с Microsoft Outlook: искать электронные письма, читать цепочки сообщений, создавать черновики, отправлять электронные письма и управлять своей почтой через Microsoft Graph API. <a>Обратитесь к документации</a>.",
multiUserWarning:
"Интеграция с Outlook недоступна в многопользовательском режиме из соображений безопасности. Пожалуйста, отключите многопользовательский режим, чтобы использовать эту функцию.",
configuration: "Настройка Outlook",
authType: "Тип аккаунта",
authTypeHelp:
"Выберите, какие типы учетных записей Microsoft могут использоваться для аутентификации. «Все учетные записи» поддерживает как личные, так и рабочие/учебные учетные записи. «Только личные» ограничивается личными учетными записями Microsoft. «Только для организации» ограничивается учетными записями из определенного экземпляра Azure AD.",
authTypeCommon: "Все счета (личные и рабочие/учебные)",
authTypeConsumers: "Личные учетные записи Microsoft",
authTypeOrganization:
"Данные только для организаций (требуется идентификатор арендатора)",
clientId: "Идентификатор клиента (для заявки)",
clientIdHelp:
"Идентификатор приложения (клиента), полученный при регистрации вашего приложения в Azure AD.",
tenantId: "Идентификатор (для арендатора)",
tenantIdHelp:
"Идентификатор (для арендатора) из вашей регистрации приложения в Azure AD. Требуется только для аутентификации, осуществляемой только внутри организации.",
clientSecret: "Секретный ключ",
clientSecretHelp:
"Секретный ключ, полученный при регистрации вашего приложения в Azure AD.",
configurationRequired:
"Пожалуйста, настройте идентификатор клиента и секретный ключ, чтобы активировать функции Outlook.",
authRequired:
"Сначала сохраните свои учетные данные, а затем выполните аутентификацию в Microsoft, чтобы завершить настройку.",
authenticateWithMicrosoft: "Авторизуйтесь через Microsoft",
authenticated: "Успешно установлено соединение с Microsoft Outlook.",
revokeAccess: "Отменить доступ",
configured: "Настроен",
searchSkills: "Навыки поиска...",
noSkillsFound: "Не найдено ни одного соответствующего запросу.",
categories: {
search: {
title: "Поиск и чтение электронных писем",
description:
"Поиск и чтение электронных писем из вашей почтовой ящика Outlook",
},
drafts: {
title: "Черновики электронных писем",
description:
"Создавайте, редактируйте и управляйте черновиками электронных писем.",
},
send: {
title: "Отправлять электронные письма",
description:
"Отправьте новые электронные письма или ответьте на сообщения немедленно.",
},
account: {
title: "Статистика интеграции",
description:
"Просмотр статистики почтового ящика и информации об аккаунте",
},
},
skills: {
getInbox: {
title: "Открыть входящие сообщения",
description:
"Получите последние письма из вашей почтовой ящика Outlook.",
},
search: {
title: "Поиск в электронных письмах",
description:
"Ищите электронные письма, используя синтаксис поиска Microsoft.",
},
readThread: {
title: "Прочитать диалог",
description: "Прочитать полный перечень электронных писем.",
},
createDraft: {
title: "Создать черновик",
description:
"Создайте новый черновик письма или черновик ответа на существующее сообщение.",
},
updateDraft: {
title: "Обновить черновик",
description: "Обновить существующий черновик письма",
},
listDrafts: {
title: "Черновики",
description: "Перечислите все черновики электронных писем.",
},
deleteDraft: {
title: "Удалить черновик",
description: "Удалить черновик письма",
},
sendDraft: {
title: "Отправить черновик",
description: "Отправить существующий черновик письма",
},
sendEmail: {
title: "Отправить электронное письмо",
description:
"Отправьте новое электронное письмо или ответьте на существующее сообщение немедленно.",
},
getMailboxStats: {
title: "Статистика почтового ящика",
description:
"Получите информацию о количестве папок и статистику использования почтового ящика.",
},
},
},
},
mcp: {
title: "Серверы MCP",

View File

@@ -535,6 +535,110 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook Bağlayıcı",
description:
"Ajantınızın Microsoft Outlook ile etkileşim kurmasını sağlayın: e-postaları arayın, tartışmaları okuyun, taslaklar oluşturun, e-posta gönderin ve Microsoft Graph API aracılığıyla posta kutunuzu yönetin. Dokümantasyonu okuyun.",
multiUserWarning:
"Outlook entegrasyonu, güvenlik nedenleriyle çoklu kullanıcı modunda mevcut değildir. Bu özelliği kullanmak için lütfen çoklu kullanıcı modunu devre dışı bırakın.",
configuration: "Outlook Yapılandırması",
authType: "Hesap Türü",
authTypeHelp:
'Hangi tür Microsoft hesaplarının kimlik doğrulamasına izin verileceğini seçin. "Tüm hesaplar" hem kişisel hem de iş/okul hesaplarını destekler. "Sadece kişisel hesaplar" yalnızca kişisel Microsoft hesaplarını kısıtlar. "Sadece kuruluş hesapları" belirli bir Azure AD kiracısından iş/okul hesaplarını kısıtlar.',
authTypeCommon: "Tüm hesaplar (kişisel ve iş/okul)",
authTypeConsumers: "Sadece bireysel Microsoft hesapları",
authTypeOrganization:
"Sadece kuruluş hesapları (Kira sahibi kimlik numarası gerektirir)",
clientId: "Uygulama (Müşteri) Kimliği",
clientIdHelp:
"Azure AD uygulamanızın kaydından elde ettiğiniz Uygulama (Müşteri) Kimliği",
tenantId: "Kiralık Konut Kimlik No",
tenantIdHelp:
"Azure AD uygulamanızın kayıt bilgilerinden elde edilen (Kiralık Alan) Kimliği. Sadece kuruluş içi kimlik doğrulama için gereklidir.",
clientSecret: "Müşteri sırrı",
clientSecretHelp:
"Azure AD uygulamanızın kaydından elde edilen istemci sır değeri",
configurationRequired:
"Lütfen, Outlook işlevlerini etkinleştirmek için Client ID ve Client Secret değerlerini yapılandırın.",
authRequired:
"Öncelikle kimlik bilgilerinizi kaydedin, ardından kurulumu tamamlamak için Microsoft ile kimliğinizi doğrulayın.",
authenticateWithMicrosoft: "Microsoft ile kimliğinizi doğrulayın",
authenticated:
"Microsoft Outlook ile başarılı bir şekilde kimlik doğrulaması tamamlandı.",
revokeAccess: "Erişi İptal Et",
configured: "Yapılandırılmış",
searchSkills: "Arama becerileri...",
noSkillsFound:
"Belirttiğiniz kriterlere uyan herhangi bir sonuç bulunamadı.",
categories: {
search: {
title: "E-postaları arayın ve okuyun",
description:
"Outlook posta kutunuzdan e-postaları arayın ve okuyun.",
},
drafts: {
title: "Örnek E-postalar",
description: "E-posta taslaklarını oluştur, düzenle ve yönet",
},
send: {
title: "E-posta gönderme",
description:
"Yeni e-postalar gönderin veya mesajlara anında cevap verin.",
},
account: {
title: "Entegrasyon İstatistikleri",
description:
"Post kutunuzdaki istatistikleri ve hesap bilgilerinizi görüntüleyin.",
},
},
skills: {
getInbox: {
title: "Gelen kutusuna eriş",
description:
"En son gelen e-postalarınızı Outlook posta kutunuzdan alın.",
},
search: {
title: "E-postaları arayın",
description:
"Microsoft arama sözdizimi kullanarak e-postaları arayın",
},
readThread: {
title: "Sohbeti okuyun",
description: "Tam bir e-posta konuşma dizisini okuyun.",
},
createDraft: {
title: "Taslak Oluştur",
description:
"Yeni bir e-posta taslağı oluşturun veya mevcut bir mesajın yanıtını taslağına ekleyin.",
},
updateDraft: {
title: "Taslak Güncelleme",
description: "Mevcut bir e-posta taslağını güncelleyin",
},
listDrafts: {
title: "Taslaklar",
description: "Tüm taslak e-postaları listele",
},
deleteDraft: {
title: "Taslak Sil",
description: "Bir taslak e-postayı sil",
},
sendDraft: {
title: "Taslak Gönder",
description: "Mevcut bir e-posta taslağını gönderin",
},
sendEmail: {
title: "E-posta gönder",
description:
"Yeni bir e-posta gönderin veya mevcut bir mesajı hemen yanıtlayın.",
},
getMailboxStats: {
title: "Post kutusu istatistikleri",
description:
"Klasörlerin ve posta kutusu istatistiklerinin sayısını alın.",
},
},
},
},
mcp: {
title: "MCP Sunucuları",

View File

@@ -527,6 +527,104 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Kết nối Outlook",
description:
"Cho phép đại lý của bạn tương tác với Microsoft Outlook tìm kiếm email, đọc các cuộc thảo luận, soạn thảo bản nháp, gửi email và quản lý hộp thư đến thông qua Microsoft Graph API. Đọc tài liệu hướng dẫn <a>.",
multiUserWarning:
"Tính năng tích hợp với Outlook không khả dụng trong 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 Outlook",
authType: "Loại tài khoản",
authTypeHelp:
'Chọn loại tài khoản Microsoft nào có thể xác thực. "Tất cả các tài khoản" hỗ trợ cả tài khoản cá nhân và tài khoản làm việc/học. "Chỉ tài khoản cá nhân" giới hạn chỉ ở tài khoản Microsoft cá nhân. "Chỉ tài khoản tổ chức" giới hạn ở tài khoản làm việc/học từ một tenant cụ thể của Azure AD.',
authTypeCommon:
"Tất cả các tài khoản (cá nhân và tài khoản liên quan đến công việc/học tập)",
authTypeConsumers: "Chỉ dành cho tài khoản Microsoft cá nhân",
authTypeOrganization:
"Chỉ dành cho tài khoản tổ chức (cần ID của người thuê).",
clientId: "Mã định danh của khách hàng",
clientIdHelp:
"Mã định danh ứng dụng (Client ID) từ quá trình đăng ký ứng dụng của bạn trong Azure AD",
tenantId: "Mã định danh (cho người thuê)",
tenantIdHelp:
"Mã định danh (Tenant ID) từ ứng dụng Azure AD của bạn. Yêu cầu chỉ khi thực hiện xác thực cho riêng tổ chức.",
clientSecret: "Mật khẩu",
clientSecretHelp: "Giá trị bí mật của ứng dụng Azure AD của bạn",
configurationRequired:
"Vui lòng cấu hình ID và bí mật của ứng dụng để kích hoạt các tính năng của Outlook.",
authRequired:
"Trước tiên, hãy lưu thông tin đăng nhập của bạn, sau đó xác thực với Microsoft để hoàn thành quá trình thiết lập.",
authenticateWithMicrosoft: "Xác minh bằng Microsoft",
authenticated: "Đã xác thực thành công với Microsoft Outlook.",
revokeAccess: "Thu hồi quyền truy cập",
configured: "Đã được cấu hình",
searchSkills: "Kỹ năng tìm kiếm...",
noSkillsFound: "Không có kết quả nào khớp với tìm kiếm của bạn.",
categories: {
search: {
title: "Tìm kiếm và đọc email",
description:
"Tìm kiếm và đọc các email trong hộp thư Outlook của bạn.",
},
drafts: {
title: "Mẫu email",
description: "Tạo, chỉnh sửa và quản lý bản nháp email",
},
send: {
title: "Gửi email",
description: "Gửi email mới hoặc trả lời tin nhắn ngay lập tức.",
},
account: {
title: "Thống kê tích hợp",
description: "Xem thống kê hộp thư và thông tin tài khoản",
},
},
skills: {
getInbox: {
title: "Truy cập hộp thư",
description: "Lấy các email mới nhất từ hộp thư Outlook của bạn",
},
search: {
title: "Tìm kiếm trong thư điện tử",
description:
"Tìm kiếm trong các email bằng cú pháp tìm kiếm của Microsoft",
},
readThread: {
title: "Đọc cuộc hội thoại",
description: "Đọc toàn bộ chuỗi email.",
},
createDraft: {
title: "Tạo bản nháp",
description:
"Tạo một bản nháp email mới hoặc một bản nháp trả lời cho một tin nhắn hiện có.",
},
updateDraft: {
title: "Cập nhật bản nháp",
description: "Cập nhật một bản nháp email đã có",
},
listDrafts: {
title: "Danh sách dự thảo",
description: "Liệt kê tất cả các email đang soạn thảo.",
},
deleteDraft: {
title: "Xóa bản nháp",
description: "Xóa bản nháp email",
},
sendDraft: {
title: "Gửi bản nháp",
description: "Gửi một bản nháp email đã có",
},
sendEmail: {
title: "Gửi email",
description:
"Gửi một email mới hoặc trả lời một tin nhắn hiện có ngay lập tức.",
},
getMailboxStats: {
title: "Thống kê hộp thư",
description: "Lấy số lượng thư mục và thống kê hộp thư.",
},
},
},
},
mcp: {
title: "Máy chủ MCP",

View File

@@ -506,6 +506,97 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook 连接器",
description:
"让您的代理通过 Microsoft Graph API 与 Microsoft Outlook 交互——搜索邮件、阅读邮件线程、撰写草稿、发送邮件以及管理您的收件箱。请查阅相关文档。",
multiUserWarning:
"由于安全原因,在多用户模式下无法使用 Outlook 集成功能。请先关闭多用户模式,然后再使用此功能。",
configuration: "Outlook 设置",
authType: "账户类型",
authTypeHelp:
'选择哪些类型的 Microsoft 账户可以进行身份验证。 "所有账户" 支持个人账户和工作/学校账户。 "仅限个人账户" 仅限于个人 Microsoft 账户。 "仅限工作/学校账户" 仅限于特定 Azure AD 租户的工作/学校账户。',
authTypeCommon: "所有账户(包括个人账户和工作/学习账户)",
authTypeConsumers: "仅限个人 Microsoft 账户",
authTypeOrganization: "仅限组织账户 (需要租户 ID)",
clientId: "申请人客户ID",
clientIdHelp: "您 Azure AD 应用程序注册的应用程序 ID",
tenantId: "租户 ID",
tenantIdHelp:
"您的 Azure AD 应用注册的“租户 ID”。仅在组织内部身份验证时需要。",
clientSecret: "客户端密钥",
clientSecretHelp: "您的 Azure AD 应用程序注册的客户端机密值",
configurationRequired:
"请配置客户端 ID 和客户端密钥,以便启用 Outlook 相关功能。",
authRequired:
"首先保存您的凭据,然后通过 Microsoft 进行身份验证以完成设置。",
authenticateWithMicrosoft: "使用 Microsoft 身份验证",
authenticated: "已成功与 Microsoft Outlook 认证。",
revokeAccess: "撤销权限",
configured: "已配置",
searchSkills: "搜索技巧...",
noSkillsFound: "未找到与您的搜索条件匹配的技能。",
categories: {
search: {
title: "搜索和阅读电子邮件",
description: "搜索并阅读您 Outlook 收件箱中的电子邮件。",
},
drafts: {
title: "草稿邮件",
description: "创建、编辑和管理电子邮件草稿",
},
send: {
title: "发送电子邮件",
description: "立即发送新邮件或回复消息",
},
account: {
title: "集成统计",
description: "查看邮件收件箱统计数据和账户信息",
},
},
skills: {
getInbox: {
title: "查看收件箱",
description: "从您的 Outlook 收件箱获取最近的邮件",
},
search: {
title: "搜索邮件",
description: "使用 Microsoft 搜索语法搜索电子邮件",
},
readThread: {
title: "阅读对话",
description: "阅读完整的电子邮件对话记录",
},
createDraft: {
title: "创建草稿",
description: "创建一个新的电子邮件草稿,或回复一个已存在的邮件。",
},
updateDraft: {
title: "更新草稿",
description: "更新已有的电子邮件草稿",
},
listDrafts: {
title: "草稿清单",
description: "列出所有草稿邮件",
},
deleteDraft: {
title: "删除草稿",
description: "删除草稿邮件",
},
sendDraft: {
title: "发送草稿",
description: "发送已有的邮件草稿",
},
sendEmail: {
title: "发送电子邮件",
description: "立即发送一封新的电子邮件,或回复已存在的消息。",
},
getMailboxStats: {
title: "邮件收件统计",
description: "获取文件夹数量和邮箱统计信息",
},
},
},
},
mcp: {
title: "MCP 服务器",

View File

@@ -496,6 +496,97 @@ const TRANSLATIONS = {
},
},
},
outlook: {
title: "Outlook 連接器",
description:
"讓您的代理能夠與 Microsoft Outlook 互動 - 搜尋郵件、閱讀討論串、撰寫草稿、發送郵件,以及透過 Microsoft Graph API 管理您的收件匣。 詳情請參考<a>相關文件</a>。",
multiUserWarning:
"由於安全原因Outlook 整合功能在多使用者模式下無法使用。請先停用多使用者模式,才能使用此功能。",
configuration: "視圖配置",
authType: "帳戶類型",
authTypeHelp:
"選擇哪些類型的 Microsoft 帳戶可以進行驗證。「所有帳戶」支援個人帳戶和工作/學校帳戶。「僅限個人帳戶」僅支援個人 Microsoft 帳戶。「僅限組織帳戶」僅支援特定 Azure AD 租戶中的工作/學校帳戶。",
authTypeCommon: "所有帳戶(個人帳戶及工作/學校帳戶)",
authTypeConsumers: "僅限個人 Microsoft 帳戶",
authTypeOrganization: "僅限於組織帳戶(需要租戶 ID",
clientId: "申請者(客戶)編號",
clientIdHelp: "您的 Azure AD 應用程式註冊產生的應用程式 ID",
tenantId: "租戶編號",
tenantIdHelp:
"您的 Azure AD 應用程式註冊的「租戶 ID」。僅用於組織內單向驗證。",
clientSecret: "客戶密鑰",
clientSecretHelp: "您的 Azure AD 應用程式註冊時所使用的客戶端秘密值",
configurationRequired:
"請設定 Client ID 和 Client Secret以便啟用 Outlook 相關功能。",
authRequired:
"首先儲存您的帳戶資訊,然後再透過 Microsoft 進行驗證,以完成設定。",
authenticateWithMicrosoft: "使用 Microsoft 驗證",
authenticated: "已成功與 Microsoft Outlook 驗證連線。",
revokeAccess: "撤銷權限",
configured: "設定",
searchSkills: "搜尋技巧...",
noSkillsFound: "沒有符合您搜尋條件的結果。",
categories: {
search: {
title: "搜尋和閱讀電子郵件",
description: "搜尋並閱讀您 Outlook 收件匣中的電子郵件",
},
drafts: {
title: "草稿郵件",
description: "創建、編輯和管理電子郵件草稿",
},
send: {
title: "發送電子郵件",
description: "即時發送新的電子郵件或回覆訊息",
},
account: {
title: "整合統計數據",
description: "查看郵箱統計資料和帳戶資訊",
},
},
skills: {
getInbox: {
title: "開啟收件匣",
description: "從您的 Outlook 郵箱取得最近的郵件",
},
search: {
title: "搜尋電子郵件",
description: "使用 Microsoft 搜尋語法來搜尋電子郵件",
},
readThread: {
title: "閱讀對話",
description: "閱讀完整的電子郵件對話紀錄",
},
createDraft: {
title: "建立草稿",
description: "建立新的電子郵件草稿,或回覆現有訊息的草稿。",
},
updateDraft: {
title: "更新草稿",
description: "更新現有電子郵件草稿",
},
listDrafts: {
title: "草稿清單",
description: "列出所有草稿電子郵件",
},
deleteDraft: {
title: "刪除草稿",
description: "刪除草稿郵件",
},
sendDraft: {
title: "發送草稿",
description: "發送現有電子郵件草稿",
},
sendEmail: {
title: "發送電子郵件",
description: "發送新的電子郵件或立即回覆現有訊息",
},
getMailboxStats: {
title: "郵箱統計",
description: "取得資料夾數量和郵箱統計數據",
},
},
},
},
mcp: {
title: "MCP 伺服器",

View File

@@ -0,0 +1,65 @@
import { API_BASE } from "@/utils/constants";
import { baseHeaders } from "@/utils/request";
const OutlookAgent = {
/**
* Save Outlook credentials and get the OAuth authorization URL.
* @param {Object} credentials - The credentials to save
* @param {string} credentials.clientId - Application (Client) ID
* @param {string} credentials.tenantId - Directory (Tenant) ID
* @param {string} credentials.clientSecret - Client Secret
* @param {string} credentials.authType - Authentication type (organization, common, consumers)
* @returns {Promise<{success: boolean, url?: string, error?: string}>}
*/
saveCredentialsAndGetAuthUrl: async ({
clientId,
tenantId,
clientSecret,
authType,
}) => {
return await fetch(`${API_BASE}/admin/agent-skills/outlook/auth-url`, {
method: "POST",
headers: baseHeaders(),
body: JSON.stringify({ clientId, tenantId, clientSecret, authType }),
})
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
/**
* Get the current authentication status for Outlook.
* @returns {Promise<{success: boolean, isConfigured?: boolean, hasCredentials?: boolean, isAuthenticated?: boolean, tokenExpiry?: number, config?: {clientId: string, tenantId: string, clientSecret: string}, error?: string}>}
*/
getStatus: async () => {
return await fetch(`${API_BASE}/admin/agent-skills/outlook/status`, {
method: "GET",
headers: baseHeaders(),
})
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
/**
* Revoke the Outlook authentication tokens.
* @returns {Promise<{success: boolean, error?: string}>}
*/
revokeAccess: async () => {
return await fetch(`${API_BASE}/admin/agent-skills/outlook/revoke`, {
method: "POST",
headers: baseHeaders(),
})
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { success: false, error: e.message };
});
},
};
export default OutlookAgent;

View File

@@ -0,0 +1,667 @@
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,
ArrowSquareOut,
XCircle,
} from "@phosphor-icons/react";
import Admin from "@/models/admin";
import System from "@/models/system";
import OutlookAgent from "@/models/outlookAgent";
import { getOutlookSkills, filterSkillCategories } from "./utils";
import OutlookIcon from "./outlook.png";
import { Tooltip } from "react-tooltip";
import { Link } from "react-router-dom";
import paths from "@/utils/paths";
export default function OutlookSkillPanel({
title,
skill,
toggleSkill,
enabled = false,
disabled = false,
setHasChanges,
hasChanges = false,
}) {
const { t } = useTranslation();
const [disabledSkills, setDisabledSkills] = useState([]);
const [loading, setLoading] = useState(true);
const [clientId, setClientId] = useState("");
const [tenantId, setTenantId] = useState("");
const [clientSecret, setClientSecret] = useState("");
const [authType, setAuthType] = useState("common");
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [authLoading, setAuthLoading] = useState(false);
const [isMultiUserMode, setIsMultiUserMode] = useState(false);
const [configDefaultExpanded, setConfigDefaultExpanded] = useState(true);
const prevHasChanges = useRef(hasChanges);
const skillCategories = getOutlookSkills(t);
const fetchStatus = async () => {
try {
const data = await OutlookAgent.getStatus();
if (data.success) {
setIsAuthenticated(data.isAuthenticated);
// Load config from status endpoint
if (data.config) {
setClientId(data.config.clientId || "");
setTenantId(data.config.tenantId || "");
setClientSecret(data.config.clientSecret || "");
setAuthType(data.config.authType || "common");
setConfigDefaultExpanded(
!(data.config.clientId && data.config.clientSecret)
);
}
}
} catch (e) {
console.error("Failed to fetch Outlook status:", e);
}
};
useEffect(() => {
setLoading(true);
Promise.all([
Admin.systemPreferencesByFields(["disabled_outlook_skills"]),
System.keys(),
OutlookAgent.getStatus(),
])
.then(([prefsRes, settingsRes, statusRes]) => {
setDisabledSkills(prefsRes?.settings?.disabled_outlook_skills ?? []);
setIsMultiUserMode(settingsRes?.MultiUserMode ?? false);
// Load config from status endpoint
if (statusRes?.success) {
setIsAuthenticated(statusRes.isAuthenticated);
if (statusRes.config) {
setClientId(statusRes.config.clientId || "");
setTenantId(statusRes.config.tenantId || "");
setClientSecret(statusRes.config.clientSecret || "");
setAuthType(statusRes.config.authType || "common");
setConfigDefaultExpanded(
!(statusRes.config.clientId && statusRes.config.clientSecret)
);
}
}
})
.catch(() => {
setDisabledSkills([]);
setClientId("");
setTenantId("");
setClientSecret("");
setAuthType("common");
})
.finally(() => setLoading(false));
const urlParams = new URLSearchParams(window.location.search);
const outlookAuth = urlParams.get("outlook_auth");
if (outlookAuth === "success") {
fetchStatus();
window.history.replaceState({}, document.title, window.location.pathname);
} else if (outlookAuth === "error") {
const message = urlParams.get("message");
console.error("Outlook auth error:", message);
window.history.replaceState({}, document.title, window.location.pathname);
}
}, []);
useEffect(() => {
if (prevHasChanges.current === true && hasChanges === false) {
Promise.all([
Admin.systemPreferencesByFields(["disabled_outlook_skills"]),
OutlookAgent.getStatus(),
])
.then(([prefsRes, statusRes]) => {
setDisabledSkills(prefsRes?.settings?.disabled_outlook_skills ?? []);
if (statusRes?.success) {
setIsAuthenticated(statusRes.isAuthenticated);
if (statusRes.config) {
setClientId(statusRes.config.clientId || "");
setTenantId(statusRes.config.tenantId || "");
setClientSecret(statusRes.config.clientSecret || "");
setAuthType(statusRes.config.authType || "common");
}
}
})
.catch(() => {});
}
prevHasChanges.current = hasChanges;
}, [hasChanges]);
function toggleOutlookSkill(skillName) {
setHasChanges(true);
setDisabledSkills((prev) =>
prev.includes(skillName)
? prev.filter((s) => s !== skillName)
: [...prev, skillName]
);
}
const handleStartAuth = async () => {
setAuthLoading(true);
try {
const data = await OutlookAgent.saveCredentialsAndGetAuthUrl({
clientId,
tenantId,
clientSecret,
authType,
});
if (data.success && data.url) {
window.open(data.url, "_blank");
} else {
console.error("Failed to get auth URL:", data.error);
}
} catch (e) {
console.error("Auth error:", e);
} finally {
setAuthLoading(false);
}
};
const handleRevokeAuth = async () => {
setAuthLoading(true);
try {
const data = await OutlookAgent.revokeAccess();
if (data.success) {
setIsAuthenticated(false);
}
} catch (e) {
console.error("Revoke error:", e);
} finally {
setAuthLoading(false);
}
};
// For organization auth type, tenant ID is required; for others it's optional
const hasCredentials =
authType === "organization"
? clientId && tenantId && clientSecret
: clientId && clientSecret;
const isConfigured = hasCredentials && isAuthenticated;
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={OutlookIcon} alt="Outlook" className="w-6 h-6" />
<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.outlook.multiUserWarning")}
</p>
</div>
)}
<p className="text-theme-text-secondary text-opacity-60 text-xs font-medium">
<Trans
i18nKey="agent.skill.outlook.description"
components={{
a: (
<Link
className="text-sky-400 hover:text-sky-500 text-xs font-medium underline"
to={paths.docs("/features/outlook-agent")}
target="_blank"
/>
),
}}
/>
</p>
{enabled && !isMultiUserMode && (
<>
<HiddenFormInputs disabledSkills={disabledSkills} />
{loading ? (
<div className="flex items-center justify-center py-4">
<CircleNotch
size={24}
className="animate-spin text-theme-text-primary"
/>
</div>
) : (
<>
<ConfigurationSection
clientId={clientId}
setClientId={setClientId}
tenantId={tenantId}
setTenantId={setTenantId}
clientSecret={clientSecret}
setClientSecret={setClientSecret}
authType={authType}
setAuthType={setAuthType}
setHasChanges={setHasChanges}
hasCredentials={hasCredentials}
isAuthenticated={isAuthenticated}
isConfigured={isConfigured}
defaultExpanded={configDefaultExpanded}
onStartAuth={handleStartAuth}
onRevokeAuth={handleRevokeAuth}
authLoading={authLoading}
/>
{isConfigured && (
<SkillsSection
skillCategories={skillCategories}
disabledSkills={disabledSkills}
onToggle={toggleOutlookSkill}
/>
)}
</>
)}
</>
)}
</div>
</div>
);
}
function ConfigurationSection({
clientId,
setClientId,
tenantId,
setTenantId,
clientSecret,
setClientSecret,
authType,
setAuthType,
setHasChanges,
hasCredentials,
isAuthenticated,
isConfigured,
defaultExpanded = true,
onStartAuth,
onRevokeAuth,
authLoading,
}) {
const { t } = useTranslation();
const [expanded, setExpanded] = useState(defaultExpanded);
const showTenantId = authType === "organization";
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.outlook.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.outlook.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.outlook.authType")}
</label>
<Info
data-tooltip-id="auth-type-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="auth-type-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100 max-w-xs"
>
{t("agent.skill.outlook.authTypeHelp")}
</Tooltip>
</div>
<select
value={authType}
onChange={(e) => {
setAuthType(e.target.value);
setHasChanges(true);
}}
className="w-full px-3 py-2 bg-theme-bg-primary border border-theme-sidebar-border rounded-lg text-theme-text-primary text-sm"
>
<option value="common">
{t("agent.skill.outlook.authTypeCommon")}
</option>
<option value="consumers">
{t("agent.skill.outlook.authTypeConsumers")}
</option>
<option value="organization">
{t("agent.skill.outlook.authTypeOrganization")}
</option>
</select>
</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.outlook.clientId")}
</label>
<Info
data-tooltip-id="client-id-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="client-id-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100"
>
{t("agent.skill.outlook.clientIdHelp")}
</Tooltip>
</div>
<input
type="text"
value={clientId}
onChange={(e) => {
setClientId(e.target.value);
setHasChanges(true);
}}
placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
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>
{showTenantId && (
<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.outlook.tenantId")}
</label>
<Info
data-tooltip-id="tenant-id-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="tenant-id-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100"
>
{t("agent.skill.outlook.tenantIdHelp")}
</Tooltip>
</div>
<input
type="text"
value={tenantId}
onChange={(e) => {
setTenantId(e.target.value);
setHasChanges(true);
}}
placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
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.outlook.clientSecret")}
</label>
<Info
data-tooltip-id="client-secret-tooltip"
size={16}
className="text-theme-text-secondary"
/>
<Tooltip
id="client-secret-tooltip"
place="top"
delayShow={300}
className="tooltip !text-xs !opacity-100"
>
{t("agent.skill.outlook.clientSecretHelp")}
</Tooltip>
</div>
<input
type="password"
value={clientSecret}
onChange={(e) => {
setClientSecret(e.target.value);
setHasChanges(true);
}}
placeholder="Your client secret..."
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>
{!hasCredentials && (
<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.outlook.configurationRequired")}
</p>
</div>
)}
{hasCredentials && !isAuthenticated && (
<div className="flex flex-col gap-y-3">
<div className="flex items-center gap-x-2 p-3 bg-blue-500/10 border border-blue-500/30 rounded-lg">
<Info size={20} className="text-blue-500 shrink-0" />
<p className="text-blue-500 text-xs">
{t("agent.skill.outlook.authRequired")}
</p>
</div>
<button
type="button"
onClick={onStartAuth}
disabled={authLoading}
className="flex items-center justify-center gap-x-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-600/50 text-white text-sm font-medium rounded-lg transition-colors"
>
{authLoading ? (
<CircleNotch size={16} className="animate-spin" />
) : (
<ArrowSquareOut size={16} />
)}
{t("agent.skill.outlook.authenticateWithMicrosoft")}
</button>
</div>
)}
{hasCredentials && isAuthenticated && (
<div className="flex flex-col gap-y-3">
<div className="flex items-center gap-x-2 p-3 bg-green-500/10 border border-green-500/30 rounded-lg">
<CheckCircle
size={20}
weight="fill"
className="text-green-500 shrink-0"
/>
<p className="text-green-500 text-xs">
{t("agent.skill.outlook.authenticated")}
</p>
</div>
<button
type="button"
onClick={onRevokeAuth}
disabled={authLoading}
className="flex items-center justify-center gap-x-2 px-4 py-2 bg-red-600/20 hover:bg-red-600/30 border border-red-600/50 text-red-500 text-sm font-medium rounded-lg transition-colors"
>
{authLoading ? (
<CircleNotch size={16} className="animate-spin" />
) : (
<XCircle size={16} />
)}
{t("agent.skill.outlook.revokeAccess")}
</button>
</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.outlook.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.outlook.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 }) {
return (
<input
name="system::disabled_outlook_skills"
type="hidden"
value={disabledSkills.join(",")}
/>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,122 @@
import {
MagnifyingGlass,
PaperPlaneTilt,
ChartBar,
PencilSimple,
} from "@phosphor-icons/react";
import strDistance from "js-levenshtein";
const LEVENSHTEIN_THRESHOLD = 3;
export const getOutlookSkills = (t) => ({
search: {
title: t("agent.skill.outlook.categories.search.title"),
description: t("agent.skill.outlook.categories.search.description"),
icon: MagnifyingGlass,
skills: [
{
name: "outlook-get-inbox",
title: t("agent.skill.outlook.skills.getInbox.title"),
description: t("agent.skill.outlook.skills.getInbox.description"),
},
{
name: "outlook-search",
title: t("agent.skill.outlook.skills.search.title"),
description: t("agent.skill.outlook.skills.search.description"),
},
{
name: "outlook-read-thread",
title: t("agent.skill.outlook.skills.readThread.title"),
description: t("agent.skill.outlook.skills.readThread.description"),
},
],
},
drafts: {
title: t("agent.skill.outlook.categories.drafts.title"),
description: t("agent.skill.outlook.categories.drafts.description"),
icon: PencilSimple,
skills: [
{
name: "outlook-create-draft",
title: t("agent.skill.outlook.skills.createDraft.title"),
description: t("agent.skill.outlook.skills.createDraft.description"),
},
{
name: "outlook-update-draft",
title: t("agent.skill.outlook.skills.updateDraft.title"),
description: t("agent.skill.outlook.skills.updateDraft.description"),
},
{
name: "outlook-list-drafts",
title: t("agent.skill.outlook.skills.listDrafts.title"),
description: t("agent.skill.outlook.skills.listDrafts.description"),
},
{
name: "outlook-delete-draft",
title: t("agent.skill.outlook.skills.deleteDraft.title"),
description: t("agent.skill.outlook.skills.deleteDraft.description"),
},
{
name: "outlook-send-draft",
title: t("agent.skill.outlook.skills.sendDraft.title"),
description: t("agent.skill.outlook.skills.sendDraft.description"),
},
],
},
send: {
title: t("agent.skill.outlook.categories.send.title"),
description: t("agent.skill.outlook.categories.send.description"),
icon: PaperPlaneTilt,
skills: [
{
name: "outlook-send-email",
title: t("agent.skill.outlook.skills.sendEmail.title"),
description: t("agent.skill.outlook.skills.sendEmail.description"),
},
],
},
account: {
title: t("agent.skill.outlook.categories.account.title"),
description: t("agent.skill.outlook.categories.account.description"),
icon: ChartBar,
skills: [
{
name: "outlook-get-mailbox-stats",
title: t("agent.skill.outlook.skills.getMailboxStats.title"),
description: t(
"agent.skill.outlook.skills.getMailboxStats.description"
),
},
],
},
});
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 OutlookSkillPanel from "./OutlookSkillPanel";
import {
Brain,
File,
@@ -13,6 +14,7 @@ import {
FolderOpen,
FilePlus,
EnvelopeSimple,
MicrosoftOutlookLogo,
} from "@phosphor-icons/react";
import RAGImage from "@/media/agents/rag-memory.png";
import SummarizeImage from "@/media/agents/view-summarize.png";
@@ -100,4 +102,12 @@ export const getConfigurableSkills = (
icon: EnvelopeSimple,
mode: ["singleUserOnly"],
},
"outlook-agent": {
title: t("agent.skill.outlook.title"),
description: t("agent.skill.outlook.description"),
component: OutlookSkillPanel,
skill: "outlook-agent",
icon: MicrosoftOutlookLogo,
mode: ["singleUserOnly"],
},
});

View File

@@ -412,6 +412,9 @@ function adminEndpoints(app) {
case "disabled_gmail_skills":
requestedSettings[label] = safeJsonParse(setting?.value, []);
break;
case "disabled_outlook_skills":
requestedSettings[label] = safeJsonParse(setting?.value, []);
break;
case "gmail_deployment_id":
requestedSettings[label] = setting?.value || null;
break;

View File

@@ -0,0 +1,190 @@
const { reqBody } = require("../../utils/http");
const {
isSingleUserMode,
} = require("../../utils/middleware/multiUserProtected");
const { validatedRequest } = require("../../utils/middleware/validatedRequest");
/**
* Constructs the OAuth redirect URI from the request headers.
* @param {Object} request - Express request object
* @returns {string} The redirect URI for OAuth callback
*/
function getOutlookRedirectUri(request) {
const protocol = request.headers["x-forwarded-proto"] || request.protocol;
const host = request.headers["x-forwarded-host"] || request.get("host");
return `${protocol}://${host}/api/agent-skills/outlook/auth-callback`;
}
function outlookAgentEndpoints(app) {
if (!app) return;
app.post(
"/admin/agent-skills/outlook/auth-url",
[validatedRequest, isSingleUserMode],
async (request, response) => {
try {
const { clientId, tenantId, clientSecret, authType } = reqBody(request);
if (!clientId || !clientSecret) {
return response.status(400).json({
success: false,
error: "Client ID and Client Secret are required.",
});
}
const outlookLib = require("../../utils/agents/aibitat/plugins/outlook/lib");
const { AUTH_TYPES } = outlookLib;
const validAuthType = Object.values(AUTH_TYPES).includes(authType)
? authType
: AUTH_TYPES.common;
if (validAuthType === AUTH_TYPES.organization && !tenantId) {
return response.status(400).json({
success: false,
error:
"Tenant ID is required for organization-only authentication.",
});
}
const existingConfig = await outlookLib.OutlookBridge.getConfig();
const configUpdate = {
...existingConfig,
clientId: clientId.trim(),
tenantId: tenantId?.trim() || "",
authType: validAuthType,
};
if (!/^\*+$/.test(clientSecret))
configUpdate.clientSecret = clientSecret.trim();
// If auth type changed, clear tokens as they won't work with different authority
if (
existingConfig.authType &&
existingConfig.authType !== validAuthType
) {
delete configUpdate.accessToken;
delete configUpdate.refreshToken;
delete configUpdate.tokenExpiry;
}
await outlookLib.OutlookBridge.updateConfig(configUpdate);
outlookLib.reset();
const redirectUri = getOutlookRedirectUri(request);
const result = await outlookLib.getAuthUrl(redirectUri);
if (!result.success) {
return response
.status(400)
.json({ success: false, error: result.error });
}
return response.status(200).json({ success: true, url: result.url });
} catch (e) {
console.error("Outlook auth URL error:", e);
response.status(500).json({ success: false, error: e.message });
}
}
);
app.get(
"/agent-skills/outlook/auth-callback",
[validatedRequest, isSingleUserMode],
async (request, response) => {
try {
const { code, error, error_description } = request.query;
if (error) {
console.error("Outlook OAuth error:", error, error_description);
return response.redirect(
`/?outlook_auth=error&message=${encodeURIComponent(error_description || error)}`
);
}
if (!code) {
return response.redirect(
"/?outlook_auth=error&message=No authorization code received"
);
}
const outlookLib = require("../../utils/agents/aibitat/plugins/outlook/lib");
const redirectUri = getOutlookRedirectUri(request);
const result = await outlookLib.exchangeCodeForToken(code, redirectUri);
const frontendUrl =
process.env.NODE_ENV === "development" ? "http://localhost:3000" : "";
if (!result.success) {
return response.redirect(
`${frontendUrl}/settings/agents?outlook_auth=error&message=${encodeURIComponent(result.error)}`
);
}
return response.redirect(
`${frontendUrl}/settings/agents?outlook_auth=success`
);
} catch (e) {
console.error("Outlook OAuth callback error:", e);
response.redirect(
`/?outlook_auth=error&message=${encodeURIComponent(e.message)}`
);
}
}
);
app.get(
"/admin/agent-skills/outlook/status",
[validatedRequest, isSingleUserMode],
async (_request, response) => {
try {
const outlookLib = require("../../utils/agents/aibitat/plugins/outlook/lib");
const { AUTH_TYPES, normalizeTokenExpiry } = outlookLib;
const config = await outlookLib.OutlookBridge.getConfig();
const isConfigured = await outlookLib.OutlookBridge.isToolAvailable();
const authType = config.authType || AUTH_TYPES.common;
let hasCredentials = !!(config.clientId && config.clientSecret);
if (authType === AUTH_TYPES.organization) {
hasCredentials = hasCredentials && !!config.tenantId;
}
const safeConfig = {
clientId: config.clientId || "",
tenantId: config.tenantId || "",
clientSecret: config.clientSecret ? "********" : "",
authType: config.authType || AUTH_TYPES.common,
};
return response.status(200).json({
success: true,
isConfigured,
hasCredentials,
isAuthenticated: !!config.accessToken,
tokenExpiry: normalizeTokenExpiry(config.tokenExpiry),
config: safeConfig,
});
} catch (e) {
console.error("Outlook status error:", e);
response.status(500).json({ success: false, error: e.message });
}
}
);
app.post(
"/admin/agent-skills/outlook/revoke",
[validatedRequest, isSingleUserMode],
async (_request, response) => {
try {
const outlookLib = require("../../utils/agents/aibitat/plugins/outlook/lib");
const { SystemSettings } = require("../../models/systemSettings");
await SystemSettings.delete({ label: "outlook_agent_config" });
outlookLib.reset();
return response.status(200).json({ success: true });
} catch (e) {
console.error("Outlook revoke error:", e);
response.status(500).json({ success: false, error: e.message });
}
}
);
}
module.exports = { outlookAgentEndpoints };

View File

@@ -35,6 +35,9 @@ const { mcpServersEndpoints } = require("./endpoints/mcpServers");
const { mobileEndpoints } = require("./endpoints/mobile");
const { webPushEndpoints } = require("./endpoints/webPush");
const { telegramEndpoints } = require("./endpoints/telegram");
const {
outlookAgentEndpoints,
} = require("./endpoints/utils/outlookAgentUtils");
const { httpLogger } = require("./middleware/httpLogger");
const app = express();
const apiRouter = express.Router();
@@ -89,6 +92,7 @@ mcpServersEndpoints(apiRouter);
mobileEndpoints(apiRouter);
webPushEndpoints(apiRouter);
telegramEndpoints(apiRouter);
outlookAgentEndpoints(apiRouter);
// Externally facing embedder endpoints
embeddedEndpoints(apiRouter);

View File

@@ -18,6 +18,21 @@ function isNullOrNaN(value) {
return isNaN(value);
}
/**
* Merges a string field from source to target if it passes validation.
* @param {Object} target - The target object to merge into
* @param {Object} source - The source object to read from
* @param {string} fieldName - The field name to merge
* @param {Function|null} validator - Optional validator function that returns false to reject the value
*/
function mergeStringField(target, source, fieldName, validator = null) {
const value = source[fieldName];
if (value && typeof value === "string" && value.trim()) {
if (validator && !validator(value)) return;
target[fieldName] = value.trim();
}
}
const SystemSettings = {
/** A default system prompt that is used when no other system prompt is set or available to the function caller. */
saneDefaultSystemPrompt:
@@ -38,6 +53,8 @@ const SystemSettings = {
"disabled_gmail_skills",
"gmail_deployment_id",
"gmail_api_key",
"disabled_outlook_skills",
"outlook_agent_config",
"imported_agent_skills",
"custom_app_name",
"feature_flags",
@@ -60,6 +77,8 @@ const SystemSettings = {
"disabled_gmail_skills",
"gmail_deployment_id",
"gmail_api_key",
"disabled_outlook_skills",
"outlook_agent_config",
"agent_sql_connections",
"custom_app_name",
"default_system_prompt",
@@ -207,6 +226,56 @@ const SystemSettings = {
GmailBridge.reset();
}
},
disabled_outlook_skills: (updates) => {
try {
const skills = updates.split(",").filter((skill) => !!skill);
return JSON.stringify(skills);
} catch {
console.error(`Could not validate disabled outlook skills.`);
return JSON.stringify([]);
}
},
outlook_agent_config: async (update) => {
const OutlookBridge = require("../utils/agents/aibitat/plugins/outlook/lib");
try {
if (!update) return JSON.stringify({});
const newConfig =
typeof update === "string" ? safeJsonParse(update, {}) : update;
const existingConfig = safeJsonParse(
(await SystemSettings.get({ label: "outlook_agent_config" }))?.value,
{}
);
const mergedConfig = { ...existingConfig };
mergeStringField(mergedConfig, newConfig, "clientId");
mergeStringField(mergedConfig, newConfig, "tenantId");
mergeStringField(
mergedConfig,
newConfig,
"clientSecret",
(v) => !v.match(/^\*+$/)
);
if (newConfig.accessToken !== undefined) {
mergedConfig.accessToken = newConfig.accessToken;
}
if (newConfig.refreshToken !== undefined) {
mergedConfig.refreshToken = newConfig.refreshToken;
}
if (newConfig.tokenExpiry !== undefined) {
mergedConfig.tokenExpiry = newConfig.tokenExpiry;
}
return JSON.stringify(mergedConfig);
} catch (e) {
console.error(`Could not validate outlook agent config:`, e.message);
return JSON.stringify({});
} finally {
OutlookBridge.reset();
}
},
agent_sql_connections: async (updates) => {
const existingConnections = safeJsonParse(
(await SystemSettings.get({ label: "agent_sql_connections" }))?.value,
@@ -434,6 +503,18 @@ const SystemSettings = {
return this._updateSettings(updates);
},
delete: async function (clause = {}) {
try {
if (!Object.keys(clause).length)
throw new Error("Clause cannot be empty");
await prisma.system_settings.deleteMany({ where: clause });
return true;
} catch (error) {
console.error(error.message);
return false;
}
},
// Explicit update of settings + key validations.
// Only use this method when directly setting a key value
// that takes no user input for the keys being modified.

View File

@@ -9,6 +9,7 @@ const { sqlAgent } = require("./sql-agent/index.js");
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");
module.exports = {
webScraping,
@@ -22,6 +23,7 @@ module.exports = {
filesystemAgent,
createFilesAgent,
gmailAgent,
outlookAgent,
// Plugin name aliases so they can be pulled by slug as well.
[webScraping.name]: webScraping,
@@ -35,4 +37,5 @@ module.exports = {
[filesystemAgent.name]: filesystemAgent,
[createFilesAgent.name]: createFilesAgent,
[gmailAgent.name]: gmailAgent,
[outlookAgent.name]: outlookAgent,
};

View File

@@ -0,0 +1,78 @@
const outlookLib = require("../lib.js");
const { handleSkillError } = outlookLib;
module.exports.OutlookGetMailboxStats = {
name: "outlook-get-mailbox-stats",
plugin: function () {
return {
name: "outlook-get-mailbox-stats",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get Outlook mailbox statistics including folder counts and user profile information. " +
"Returns the total and unread counts for inbox, drafts, sent items, and deleted items.",
examples: [
{
prompt: "How many unread emails do I have?",
call: JSON.stringify({}),
},
{
prompt: "Show me my mailbox statistics",
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 outlook-get-mailbox-stats tool.`
);
this.super.introspect(
`${this.caller}: Getting Outlook mailbox statistics...`
);
const result = await outlookLib.getMailboxStats();
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get mailbox stats - ${result.error}`
);
return `Error getting mailbox statistics: ${result.error}`;
}
const { email, displayName, folders } = result.data;
this.super.introspect(
`${this.caller}: Successfully retrieved mailbox statistics`
);
let folderStats = "";
if (folders.inbox)
folderStats += `\nInbox: ${folders.inbox.total} total, ${folders.inbox.unread} unread`;
if (folders.drafts)
folderStats += `\nDrafts: ${folders.drafts.total} total`;
if (folders.sentitems)
folderStats += `\nSent Items: ${folders.sentitems.total} total`;
if (folders.deleteditems)
folderStats += `\nDeleted Items: ${folders.deleteditems.total} total`;
return (
`Outlook Mailbox Statistics:\n` +
`\nAccount: ${displayName} (${email})\n` +
`\nFolder Statistics:${folderStats}`
);
} catch (e) {
return handleSkillError(this, "outlook-get-mailbox-stats", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,232 @@
const outlookLib = require("../lib.js");
const { prepareAttachmentsWithValidation, handleSkillError } = outlookLib;
module.exports.OutlookCreateDraft = {
name: "outlook-create-draft",
plugin: function () {
return {
name: "outlook-create-draft",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Create a new draft email in Outlook. The draft will be saved but not sent. " +
"Can also create a draft reply to an existing message by providing replyToMessageId. " +
"You can optionally include CC, BCC recipients, HTML body content, and file attachments.",
examples: [
{
prompt:
"Create a draft email to john@example.com about the meeting",
call: JSON.stringify({
to: "john@example.com",
subject: "Meeting Tomorrow",
body: "Hi John,\n\nJust wanted to confirm our meeting tomorrow at 2pm.\n\nBest regards",
}),
},
{
prompt: "Create a draft reply to message AAMkAGI2...",
call: JSON.stringify({
replyToMessageId: "AAMkAGI2...",
body: "Thanks for the update. I'll review and get back to you.",
}),
},
{
prompt: "Create a draft reply-all to message AAMkAGI2...",
call: JSON.stringify({
replyToMessageId: "AAMkAGI2...",
body: "Thanks everyone for your input.",
replyAll: true,
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
replyToMessageId: {
type: "string",
description:
"Message ID to reply to. If provided, creates a draft reply instead of a new draft. " +
"When replying, 'to' and 'subject' are optional (inherited from original).",
},
replyAll: {
type: "boolean",
description:
"When replying, whether to reply to all recipients. Defaults to false.",
default: false,
},
to: {
type: "string",
description:
"Recipient email address(es). Required for new drafts, optional for replies.",
},
subject: {
type: "string",
description:
"Email subject line. Required for new drafts, optional for replies.",
},
body: {
type: "string",
description: "Email body content.",
},
cc: {
type: "string",
description: "CC recipient email address(es). Optional.",
},
bcc: {
type: "string",
description: "BCC recipient email address(es). Optional.",
},
isHtml: {
type: "boolean",
description:
"Whether the body is HTML content. Defaults to false.",
default: false,
},
attachments: {
type: "array",
items: { type: "string" },
description:
"Array of absolute file paths to attach to the draft.",
},
},
required: ["body"],
additionalProperties: false,
},
handler: async function ({
replyToMessageId,
replyAll = false,
to,
subject,
body,
cc,
bcc,
isHtml,
attachments,
}) {
try {
this.super.handlerProps.log(
`Using the outlook-create-draft tool.`
);
const isReply = !!replyToMessageId;
if (!isReply && (!to || !subject)) {
return "Error: 'to' and 'subject' are required for new drafts. For draft replies, provide 'replyToMessageId'.";
}
if (!body) {
return "Error: 'body' is required.";
}
const attachmentResult = await prepareAttachmentsWithValidation(
this,
attachments
);
if (!attachmentResult.success) {
return `Error with attachment: ${attachmentResult.error}`;
}
const {
attachments: preparedAttachments,
summaries: attachmentSummaries,
} = attachmentResult;
if (this.super.requestToolApproval) {
const attachmentNote =
preparedAttachments.length > 0
? ` with ${preparedAttachments.length} attachment(s): ${attachmentSummaries.join(", ")}`
: "";
const description = isReply
? `Create draft ${replyAll ? "reply-all" : "reply"} to message ${replyToMessageId}${attachmentNote}`
: `Create Outlook draft to "${to}" with subject "${subject}"${attachmentNote}`;
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: isReply
? { replyToMessageId, replyAll }
: {
to,
subject,
attachmentCount: preparedAttachments.length,
},
description,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
let result;
if (isReply) {
this.super.introspect(
`${this.caller}: Creating draft ${replyAll ? "reply-all" : "reply"} to message...`
);
result = await outlookLib.createDraftReply(
replyToMessageId,
body,
replyAll
);
} else {
this.super.introspect(
`${this.caller}: Creating Outlook draft to ${to}${preparedAttachments.length > 0 ? ` with ${preparedAttachments.length} attachment(s)` : ""}`
);
const options = { isHtml };
if (cc) options.cc = cc;
if (bcc) options.bcc = bcc;
if (preparedAttachments.length > 0) {
options.attachments = preparedAttachments;
}
result = await outlookLib.createDraft(
to,
subject,
body,
options
);
}
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to create draft - ${result.error}`
);
return `Error creating draft: ${result.error}`;
}
const draft = result.data;
this.super.introspect(
`${this.caller}: Successfully created draft (ID: ${draft.draftId})`
);
if (isReply) {
return (
`Successfully created draft ${replyAll ? "reply-all" : "reply"}:\n` +
`Draft ID: ${draft.draftId}\n` +
`Subject: ${draft.subject}\n` +
`Type: ${replyAll ? "Reply All" : "Reply"}\n` +
`\nThe draft reply has been saved and can be edited or sent later.`
);
}
return (
`Successfully created Outlook draft:\n` +
`Draft ID: ${draft.draftId}\n` +
`To: ${to}\n` +
`Subject: ${subject}\n` +
(preparedAttachments.length > 0
? `Attachments: ${attachmentSummaries.join(", ")}\n`
: "") +
`\nThe draft has been saved and can be edited or sent later.`
);
} catch (e) {
return handleSkillError(this, "outlook-create-draft", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,86 @@
const outlookLib = require("../lib.js");
const { handleSkillError } = outlookLib;
module.exports.OutlookDeleteDraft = {
name: "outlook-delete-draft",
plugin: function () {
return {
name: "outlook-delete-draft",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Delete a draft email from Outlook. " +
"This permanently removes the draft and cannot be undone.",
examples: [
{
prompt: "Delete the draft with ID AAMkAGI2...",
call: JSON.stringify({
draftId: "AAMkAGI2...",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
draftId: {
type: "string",
description: "The ID of the draft to delete.",
},
},
required: ["draftId"],
additionalProperties: false,
},
handler: async function ({ draftId }) {
try {
this.super.handlerProps.log(
`Using the outlook-delete-draft tool.`
);
if (!draftId) {
return "Error: 'draftId' is required.";
}
if (this.super.requestToolApproval) {
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: { draftId },
description: `Delete draft ${draftId}? This cannot be undone.`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Deleting draft ${draftId}...`
);
const result = await outlookLib.deleteDraft(draftId);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to delete draft - ${result.error}`
);
return `Error deleting draft: ${result.error}`;
}
this.super.introspect(
`${this.caller}: Successfully deleted draft`
);
return `Successfully deleted draft (ID: ${draftId}).`;
} catch (e) {
return handleSkillError(this, "outlook-delete-draft", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,80 @@
const outlookLib = require("../lib.js");
const { handleSkillError } = outlookLib;
module.exports.OutlookListDrafts = {
name: "outlook-list-drafts",
plugin: function () {
return {
name: "outlook-list-drafts",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"List all draft emails in Outlook. " +
"Returns a summary of each draft including ID, subject, recipients, and last modified date.",
examples: [
{
prompt: "Show me my draft emails",
call: JSON.stringify({ limit: 25 }),
},
{
prompt: "List drafts",
call: JSON.stringify({ limit: 10 }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
limit: {
type: "number",
description:
"Maximum number of drafts to return (1-50). Defaults to 25.",
default: 25,
},
},
additionalProperties: false,
},
handler: async function ({ limit = 25 }) {
try {
this.super.handlerProps.log(
`Using the outlook-list-drafts tool.`
);
this.super.introspect(
`${this.caller}: Listing Outlook drafts...`
);
const result = await outlookLib.listDrafts(limit);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to list drafts - ${result.error}`
);
return `Error listing drafts: ${result.error}`;
}
const { drafts, count } = result.data;
this.super.introspect(`${this.caller}: Found ${count} drafts`);
if (count === 0) {
return "No drafts found.";
}
const summary = drafts
.map(
(d, i) =>
`${i + 1}. "${d.subject || "(No Subject)"}" to ${d.to || "(No Recipients)"}\n ID: ${d.id}\n Last Modified: ${new Date(d.lastModified).toLocaleString()}\n Preview: ${d.preview?.substring(0, 100) || "(No preview)"}...`
)
.join("\n\n");
return `Found ${count} drafts:\n\n${summary}\n\nUse the draft ID with outlook-get-draft to see full content, outlook-update-draft to modify, or outlook-send-draft to send.`;
} catch (e) {
return handleSkillError(this, "outlook-list-drafts", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,82 @@
const outlookLib = require("../lib.js");
const { handleSkillError } = outlookLib;
module.exports.OutlookSendDraft = {
name: "outlook-send-draft",
plugin: function () {
return {
name: "outlook-send-draft",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Send an existing draft email from Outlook. " +
"This action sends the email immediately and cannot be undone.",
examples: [
{
prompt: "Send the draft with ID AAMkAGI2...",
call: JSON.stringify({
draftId: "AAMkAGI2...",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
draftId: {
type: "string",
description: "The ID of the draft to send.",
},
},
required: ["draftId"],
additionalProperties: false,
},
handler: async function ({ draftId }) {
try {
this.super.handlerProps.log(`Using the outlook-send-draft tool.`);
if (!draftId) {
return "Error: 'draftId' is required.";
}
if (this.super.requestToolApproval) {
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: { draftId },
description: `Send draft ${draftId}? This will send the email immediately.`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Sending draft ${draftId}...`
);
const result = await outlookLib.sendDraft(draftId);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to send draft - ${result.error}`
);
return `Error sending draft: ${result.error}`;
}
this.super.introspect(`${this.caller}: Successfully sent draft`);
return `Successfully sent draft (ID: ${draftId}). The email has been delivered.`;
} catch (e) {
return handleSkillError(this, "outlook-send-draft", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,132 @@
const outlookLib = require("../lib.js");
const { handleSkillError } = outlookLib;
module.exports.OutlookUpdateDraft = {
name: "outlook-update-draft",
plugin: function () {
return {
name: "outlook-update-draft",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Update an existing draft email in Outlook. " +
"You can modify the recipients, subject, or body of the draft.",
examples: [
{
prompt: "Update the draft subject",
call: JSON.stringify({
draftId: "AAMkAGI2...",
subject: "Updated Meeting - Tomorrow at 3pm",
}),
},
{
prompt: "Change the draft body and add CC",
call: JSON.stringify({
draftId: "AAMkAGI2...",
body: "Updated content here.",
cc: "manager@example.com",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
draftId: {
type: "string",
description: "The ID of the draft to update.",
},
to: {
type: "string",
description: "New recipient email address(es). Optional.",
},
subject: {
type: "string",
description: "New email subject. Optional.",
},
body: {
type: "string",
description: "New email body content. Optional.",
},
cc: {
type: "string",
description: "New CC recipient email address(es). Optional.",
},
isHtml: {
type: "boolean",
description:
"Whether the body is HTML content. Defaults to false.",
default: false,
},
},
required: ["draftId"],
additionalProperties: false,
},
handler: async function ({ draftId, to, subject, body, cc, isHtml }) {
try {
this.super.handlerProps.log(
`Using the outlook-update-draft tool.`
);
if (!draftId) {
return "Error: 'draftId' is required.";
}
if (!to && !subject && !body && !cc) {
return "Error: At least one field to update (to, subject, body, cc) is required.";
}
if (this.super.requestToolApproval) {
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: { draftId, hasChanges: { to, subject, body, cc } },
description: `Update draft ${draftId}`,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
this.super.introspect(
`${this.caller}: Updating draft ${draftId}...`
);
const updates = { isHtml };
if (to) updates.to = to;
if (subject) updates.subject = subject;
if (body) updates.body = body;
if (cc) updates.cc = cc;
const result = await outlookLib.updateDraft(draftId, updates);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to update draft - ${result.error}`
);
return `Error updating draft: ${result.error}`;
}
this.super.introspect(
`${this.caller}: Successfully updated draft`
);
return (
`Successfully updated draft:\n` +
`Draft ID: ${result.data.draftId}\n` +
`Subject: ${result.data.subject}\n` +
`\nThe draft has been updated.`
);
} catch (e) {
return handleSkillError(this, "outlook-update-draft", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,45 @@
const { OutlookGetInbox } = require("./search/outlook-get-inbox.js");
const { OutlookSearch } = require("./search/outlook-search.js");
const { OutlookReadThread } = require("./search/outlook-read-thread.js");
const { OutlookCreateDraft } = require("./drafts/outlook-create-draft.js");
const { OutlookUpdateDraft } = require("./drafts/outlook-update-draft.js");
const { OutlookListDrafts } = require("./drafts/outlook-list-drafts.js");
const { OutlookDeleteDraft } = require("./drafts/outlook-delete-draft.js");
const { OutlookSendDraft } = require("./drafts/outlook-send-draft.js");
const { OutlookSendEmail } = require("./send/outlook-send-email.js");
const {
OutlookGetMailboxStats,
} = require("./account/outlook-get-mailbox-stats.js");
const outlookAgent = {
name: "outlook-agent",
startupConfig: {
params: {},
},
plugin: [
// Inbox & Search (read-only)
OutlookGetInbox,
OutlookSearch,
OutlookReadThread,
// Drafts (create-draft also supports replies via replyToMessageId)
OutlookCreateDraft,
OutlookUpdateDraft,
OutlookListDrafts,
OutlookDeleteDraft,
OutlookSendDraft,
// Send (send-email also supports replies via replyToMessageId)
OutlookSendEmail,
// Account (read-only)
OutlookGetMailboxStats,
],
};
module.exports = {
outlookAgent,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
const outlookLib = require("../lib.js");
const { formatMessageSummary, handleSkillError } = outlookLib;
module.exports.OutlookGetInbox = {
name: "outlook-get-inbox",
plugin: function () {
return {
name: "outlook-get-inbox",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Get recent emails from the Outlook inbox. " +
"Returns a list of recent messages with subject, sender, date, and read status. " +
"Use this to quickly see what's in the inbox.",
examples: [
{
prompt: "Show me my recent emails",
call: JSON.stringify({ limit: 10 }),
},
{
prompt: "What's in my inbox?",
call: JSON.stringify({ limit: 25 }),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
limit: {
type: "number",
description:
"Maximum number of messages to return (1-50). Defaults to 25.",
default: 25,
},
},
additionalProperties: false,
},
handler: async function ({ limit = 25 }) {
try {
this.super.handlerProps.log(`Using the outlook-get-inbox tool.`);
this.super.introspect(
`${this.caller}: Fetching Outlook inbox...`
);
const result = await outlookLib.getInbox(limit);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to get inbox - ${result.error}`
);
return `Error getting Outlook inbox: ${result.error}`;
}
const { messages, resultCount } = result.data;
this.super.introspect(
`${this.caller}: Found ${resultCount} messages in inbox`
);
if (resultCount === 0) {
return "No messages found in inbox.";
}
const summary = formatMessageSummary(messages);
return `Found ${resultCount} messages in inbox:\n\n${summary}\n\nUse the conversation ID with outlook-read-thread to read the full conversation.`;
} catch (e) {
return handleSkillError(this, "outlook-get-inbox", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,114 @@
const outlookLib = require("../lib.js");
const { handleAttachments, handleSkillError } = outlookLib;
module.exports.OutlookReadThread = {
name: "outlook-read-thread",
plugin: function () {
return {
name: "outlook-read-thread",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Read a full email conversation thread by its conversation ID. " +
"Returns all messages in the thread including sender, recipients, subject, body, date, and attachment information. " +
"Use this after searching to read the full conversation.",
examples: [
{
prompt: "Read the email thread with conversation ID AAQkAGI2...",
call: JSON.stringify({
conversationId: "AAQkAGI2...",
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
conversationId: {
type: "string",
description: "The Outlook conversation ID to read.",
},
},
required: ["conversationId"],
additionalProperties: false,
},
handler: async function ({ conversationId }) {
try {
this.super.handlerProps.log(
`Using the outlook-read-thread tool.`
);
if (!conversationId) {
return "Error: conversationId is required.";
}
this.super.introspect(
`${this.caller}: Reading Outlook conversation...`
);
const result = await outlookLib.readThread(conversationId);
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to read thread - ${result.error}`
);
return `Error reading Outlook thread: ${result.error}`;
}
const thread = result.data;
const { allAttachments, parsedContent: parsedAttachmentContent } =
await handleAttachments(this, thread.messages);
const messagesFormatted = thread.messages
.map((msg, i) => {
let attachmentInfo = "";
if (msg.attachments?.length > 0) {
attachmentInfo = `\n Attachments: ${msg.attachments.map((a) => `${a.name} (${a.contentType}, ${(a.size / 1024).toFixed(1)}KB)`).join(", ")}`;
}
const bodyContent =
msg.bodyType === "html"
? msg.body
.replace(/<[^>]*>/g, " ")
.replace(/\s+/g, " ")
.trim()
: msg.body;
return (
`--- Message ${i + 1} ---\n` +
`From: ${msg.fromName} <${msg.from}>\n` +
`To: ${msg.to}\n` +
(msg.cc ? `CC: ${msg.cc}\n` : "") +
`Date: ${new Date(msg.date).toLocaleString()}\n` +
`Subject: ${msg.subject}\n` +
`Status: ${msg.isRead ? "READ" : "UNREAD"}\n` +
`\n${bodyContent}` +
attachmentInfo
);
})
.join("\n\n");
this.super.introspect(
`${this.caller}: Successfully read thread with ${thread.messageCount} messages`
);
return (
`Thread: "${thread.subject}"\n` +
`Conversation ID: ${thread.conversationId}\n` +
`Messages: ${thread.messageCount}\n` +
`Total Attachments: ${allAttachments.length}\n\n` +
messagesFormatted +
parsedAttachmentContent
);
} catch (e) {
return handleSkillError(this, "outlook-read-thread", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,101 @@
const outlookLib = require("../lib.js");
const { formatMessageSummary, handleSkillError } = outlookLib;
module.exports.OutlookSearch = {
name: "outlook-search",
plugin: function () {
return {
name: "outlook-search",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Search emails in Outlook using Microsoft Search syntax. " +
"Supports searching by keywords, sender, subject, and more. " +
"Common search terms: 'from:email', 'subject:word', 'hasAttachments:true'. " +
"Returns message summaries with ID, subject, date, and read status.",
examples: [
{
prompt: "Search for emails about the project",
call: JSON.stringify({
query: "project update",
limit: 10,
}),
},
{
prompt: "Find emails from john@example.com",
call: JSON.stringify({
query: "from:john@example.com",
limit: 20,
}),
},
{
prompt: "Search for emails with attachments about invoices",
call: JSON.stringify({
query: "hasAttachments:true invoice",
limit: 15,
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
query: {
type: "string",
description:
"Search query. Use Microsoft Search syntax like 'from:email', 'subject:keyword', etc.",
},
limit: {
type: "number",
description:
"Maximum number of results to return (1-50). Defaults to 10.",
default: 10,
},
skip: {
type: "number",
description:
"Number of results to skip for pagination. Defaults to 0.",
default: 0,
},
},
required: ["query"],
additionalProperties: false,
},
handler: async function ({ query, limit = 10, skip = 0 }) {
try {
this.super.handlerProps.log(`Using the outlook-search tool.`);
this.super.introspect(
`${this.caller}: Searching Outlook with query "${query}"`
);
const result = await outlookLib.search(query, limit, skip);
if (!result.success) {
this.super.introspect(
`${this.caller}: Outlook search failed - ${result.error}`
);
return `Error searching Outlook: ${result.error}`;
}
const { messages, resultCount } = result.data;
this.super.introspect(
`${this.caller}: Found ${resultCount} messages matching query`
);
if (resultCount === 0) {
return `No emails found matching query "${query}".`;
}
const summary = formatMessageSummary(messages);
return `Found ${resultCount} messages:\n\n${summary}\n\nUse the conversation ID with outlook-read-thread to read the full conversation.`;
} catch (e) {
return handleSkillError(this, "outlook-search", e);
}
},
});
},
};
},
};

View File

@@ -0,0 +1,222 @@
const outlookLib = require("../lib.js");
const { prepareAttachmentsWithValidation, handleSkillError } = outlookLib;
module.exports.OutlookSendEmail = {
name: "outlook-send-email",
plugin: function () {
return {
name: "outlook-send-email",
setup(aibitat) {
aibitat.function({
super: aibitat,
name: this.name,
description:
"Send an email immediately through Outlook. " +
"This action sends the email right away and cannot be undone. " +
"Can also reply to an existing message by providing replyToMessageId. " +
"For composing emails that need review before sending, use outlook-create-draft instead.",
examples: [
{
prompt: "Send an email to john@example.com about the project",
call: JSON.stringify({
to: "john@example.com",
subject: "Project Update",
body: "Hi John,\n\nHere's the latest update on the project.\n\nBest regards",
}),
},
{
prompt: "Reply to message AAMkAGI2...",
call: JSON.stringify({
replyToMessageId: "AAMkAGI2...",
body: "Thanks for the update. I'll review and get back to you.",
}),
},
{
prompt: "Reply all to message AAMkAGI2...",
call: JSON.stringify({
replyToMessageId: "AAMkAGI2...",
body: "Thanks everyone for your input.",
replyAll: true,
}),
},
],
parameters: {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
replyToMessageId: {
type: "string",
description:
"Message ID to reply to. If provided, sends a reply instead of a new email. " +
"When replying, 'to' and 'subject' are optional (inherited from original).",
},
replyAll: {
type: "boolean",
description:
"When replying, whether to reply to all recipients. Defaults to false.",
default: false,
},
to: {
type: "string",
description:
"Recipient email address(es). Required for new emails, optional for replies.",
},
subject: {
type: "string",
description:
"Email subject line. Required for new emails, optional for replies.",
},
body: {
type: "string",
description: "Email body content.",
},
cc: {
type: "string",
description: "CC recipient email address(es). Optional.",
},
bcc: {
type: "string",
description: "BCC recipient email address(es). Optional.",
},
isHtml: {
type: "boolean",
description:
"Whether the body is HTML content. Defaults to false.",
default: false,
},
attachments: {
type: "array",
items: { type: "string" },
description:
"Array of absolute file paths to attach to the email.",
},
},
required: ["body"],
additionalProperties: false,
},
handler: async function ({
replyToMessageId,
replyAll = false,
to,
subject,
body,
cc,
bcc,
isHtml,
attachments,
}) {
try {
this.super.handlerProps.log(`Using the outlook-send-email tool.`);
const isReply = !!replyToMessageId;
if (!isReply && (!to || !subject)) {
return "Error: 'to' and 'subject' are required for new emails. For replies, provide 'replyToMessageId'.";
}
if (!body) {
return "Error: 'body' is required.";
}
const attachmentResult = await prepareAttachmentsWithValidation(
this,
attachments,
{ requireApprovalPerFile: true, recipientInfo: to }
);
if (!attachmentResult.success) {
return `Error with attachment: ${attachmentResult.error}`;
}
const {
attachments: preparedAttachments,
summaries: attachmentSummaries,
} = attachmentResult;
if (this.super.requestToolApproval) {
const attachmentNote =
preparedAttachments.length > 0
? ` with ${preparedAttachments.length} attachment(s): ${attachmentSummaries.join(", ")}`
: "";
const description = isReply
? `Send ${replyAll ? "reply-all" : "reply"} to message ${replyToMessageId}${attachmentNote}? This will send immediately.`
: `Send email to "${to}" with subject "${subject}"${attachmentNote} - This will send immediately`;
const approval = await this.super.requestToolApproval({
skillName: this.name,
payload: isReply
? { replyToMessageId, replyAll }
: {
to,
subject,
attachmentCount: preparedAttachments.length,
},
description,
});
if (!approval.approved) {
this.super.introspect(
`${this.caller}: User rejected the ${this.name} request.`
);
return approval.message;
}
}
let result;
if (isReply) {
this.super.introspect(
`${this.caller}: Sending ${replyAll ? "reply-all" : "reply"} to message...`
);
result = await outlookLib.replyToMessage(
replyToMessageId,
body,
replyAll
);
} else {
this.super.introspect(
`${this.caller}: Sending email to ${to}${preparedAttachments.length > 0 ? ` with ${preparedAttachments.length} attachment(s)` : ""}`
);
const options = { isHtml };
if (cc) options.cc = cc;
if (bcc) options.bcc = bcc;
if (preparedAttachments.length > 0) {
options.attachments = preparedAttachments;
}
result = await outlookLib.sendEmail(to, subject, body, options);
}
if (!result.success) {
this.super.introspect(
`${this.caller}: Failed to send - ${result.error}`
);
return `Error sending: ${result.error}`;
}
if (isReply) {
this.super.introspect(
`${this.caller}: Successfully sent ${replyAll ? "reply-all" : "reply"}`
);
return `Successfully sent ${replyAll ? "reply-all" : "reply"} to message (ID: ${replyToMessageId}). The reply has been delivered.`;
}
this.super.introspect(
`${this.caller}: Successfully sent email to ${to}`
);
return (
`Successfully sent email:\n` +
`To: ${to}\n` +
`Subject: ${subject}\n` +
(cc ? `CC: ${cc}\n` : "") +
(preparedAttachments.length > 0
? `Attachments: ${attachmentSummaries.join(", ")}\n`
: "") +
`\nThe email has been sent.`
);
} catch (e) {
return handleSkillError(this, "outlook-send-email", e);
}
},
});
},
};
},
};

View File

@@ -13,6 +13,33 @@ const DEFAULT_SKILLS = [
AgentPlugins.webScraping.name,
];
/**
* Configuration for agent skills that require availability checks and disabled sub-skill lists.
* Each entry maps a skill name to its availability checker and disabled skills list key.
*/
const SKILL_FILTER_CONFIG = {
"filesystem-agent": {
getAvailability: () =>
require("./aibitat/plugins/filesystem/lib").isToolAvailable(),
disabledSettingKey: "disabled_filesystem_skills",
},
"create-files-agent": {
getAvailability: () =>
require("./aibitat/plugins/create-files/lib").isToolAvailable(),
disabledSettingKey: "disabled_create_files_skills",
},
"gmail-agent": {
getAvailability: async () =>
require("./aibitat/plugins/gmail/lib").GmailBridge.isToolAvailable(),
disabledSettingKey: "disabled_gmail_skills",
},
"outlook-agent": {
getAvailability: async () =>
require("./aibitat/plugins/outlook/lib").OutlookBridge.isToolAvailable(),
disabledSettingKey: "disabled_outlook_skills",
},
};
const USER_AGENT = {
name: "USER",
getDefinition: () => {
@@ -72,33 +99,6 @@ async function agentSkillsFromSystemSettings() {
systemFunctions.push(AgentPlugins[skill].name);
});
// Load disabled filesystem sub-skills
const _disabledFilesystemSkills = safeJsonParse(
await SystemSettings.getValueOrFallback(
{ label: "disabled_filesystem_skills" },
"[]"
),
[]
);
// Load disabled create-files sub-skills
const _disabledCreateFilesSkills = safeJsonParse(
await SystemSettings.getValueOrFallback(
{ label: "disabled_create_files_skills" },
"[]"
),
[]
);
// Load disabled gmail sub-skills
const _disabledGmailSkills = safeJsonParse(
await SystemSettings.getValueOrFallback(
{ label: "disabled_gmail_skills" },
"[]"
),
[]
);
// Load non-imported built-in skills that are configurable.
const _setting = safeJsonParse(
await SystemSettings.getValueOrFallback(
@@ -108,11 +108,21 @@ async function agentSkillsFromSystemSettings() {
[]
);
// Pre-check gmail availability once (async) to avoid await inside loop
let gmailAvailable = false;
if (_setting.includes("gmail-agent")) {
const gmailTool = require("./aibitat/plugins/gmail/lib");
gmailAvailable = await gmailTool.GmailBridge.isToolAvailable();
// Pre-load disabled sub-skills and availability for configured skills
const skillFilterState = {};
for (const skillName of Object.keys(SKILL_FILTER_CONFIG)) {
if (!_setting.includes(skillName)) continue;
const config = SKILL_FILTER_CONFIG[skillName];
skillFilterState[skillName] = {
available: await config.getAvailability(),
disabledSubSkills: safeJsonParse(
await SystemSettings.getValueOrFallback(
{ label: config.disabledSettingKey },
"[]"
),
[]
),
};
}
for (const skillName of _setting) {
@@ -122,34 +132,11 @@ async function agentSkillsFromSystemSettings() {
// need to be named via `${parent}#${child}` naming convention
if (Array.isArray(AgentPlugins[skillName].plugin)) {
for (const subPlugin of AgentPlugins[skillName].plugin) {
/**
* If the filesystem tool is not available, or the sub-skill is explicitly disabled, skip it
* This is a docker specific skill so it cannot be used in other environments.
*/
if (skillName === "filesystem-agent") {
const filesystemTool = require("./aibitat/plugins/filesystem/lib");
if (!filesystemTool.isToolAvailable()) continue;
if (_disabledFilesystemSkills.includes(subPlugin.name)) continue;
}
/**
* If the create-files tool is not available, or the sub-skill is explicitly disabled, skip it
* This is a docker specific skill so it cannot be used in other environments.
*/
if (skillName === "create-files-agent") {
const createFilesTool = require("./aibitat/plugins/create-files/lib");
if (!createFilesTool.isToolAvailable()) continue;
if (_disabledCreateFilesSkills.includes(subPlugin.name)) continue;
}
/**
* If the gmail tool is not available (multi-user mode or missing config),
* or the sub-skill is explicitly disabled, skip it.
* Gmail integration is only available in single-user mode for security reasons.
*/
if (skillName === "gmail-agent") {
if (!gmailAvailable) continue;
if (_disabledGmailSkills.includes(subPlugin.name)) continue;
// Check if this skill has filter configuration
const filterState = skillFilterState[skillName];
if (filterState) {
if (!filterState.available) continue;
if (filterState.disabledSubSkills.includes(subPlugin.name)) continue;
}
systemFunctions.push(