From 3b1288097da457752cc4b6624f4ea53e22c4be32 Mon Sep 17 00:00:00 2001 From: arc53-machine <232052973+arc53-machine@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:31:26 +0100 Subject: [PATCH] One vocabulary: Knowledge, tools, and connectors in plain words - Sources (the collection) are called Knowledge: the settings page (now /settings/knowledge; /settings/sources redirects), the composer and agent pickers, Add knowledge, and "syncs into Knowledge" on connectors. Citations keep "sources". All seven locales. - Connector cards describe what they do ("Syncs into Knowledge", "Looks things up", "Takes actions") and drop publisher labels ("Built in", "Preset"). Filters read "Files & storage" and "Docs & wikis" so "knowledge" means one thing. - Custom tools are tools: "Add custom tool". The agent picker no longer splits built-in tools into "Built-in" and "Default". - Confluence is one card: syncing pages into Knowledge and the Jira & Confluence MCP actions (part_of on the preset) share a page. The part shows on its own when Confluence sync is not set up. --- docs/content/Guides/Connectors.mdx | 4 +- docsgpt/connectors/catalog.py | 5 ++ docsgpt/connectors/presets/mcp.yaml | 4 +- .../components/SourcesPopoverFooter.test.tsx | 2 +- .../src/components/SourcesPopoverFooter.tsx | 2 +- .../message-input/SourcesTrigger.tsx | 2 +- frontend/src/connectors/ConnectionDrawer.tsx | 73 ++++++++++++++--- frontend/src/connectors/ConnectorCard.tsx | 19 ++--- frontend/src/connectors/types.ts | 2 + frontend/src/locale/de.json | 64 ++++++++------- frontend/src/locale/en.json | 64 ++++++++------- frontend/src/locale/es.json | 64 ++++++++------- frontend/src/locale/jp.json | 64 ++++++++------- frontend/src/locale/ru.json | 64 ++++++++------- frontend/src/locale/zh-TW.json | 64 ++++++++------- frontend/src/locale/zh.json | 64 ++++++++------- frontend/src/navigation/sections.ts | 2 +- frontend/src/settings/Connectors.test.tsx | 78 ++++++++++++++++++- frontend/src/settings/Connectors.tsx | 43 +++++++++- frontend/src/settings/index.tsx | 12 ++- tests/connectors/test_catalog.py | 10 +++ 21 files changed, 462 insertions(+), 244 deletions(-) diff --git a/docs/content/Guides/Connectors.mdx b/docs/content/Guides/Connectors.mdx index 6cb651e4..5cd658c8 100644 --- a/docs/content/Guides/Connectors.mdx +++ b/docs/content/Guides/Connectors.mdx @@ -1,6 +1,6 @@ --- title: Connectors -description: Connect DocsGPT to the services your team uses. One connection can sync content into Sources and give agents tools, with credentials encrypted on the server. +description: Connect DocsGPT to the services your team uses. One connection can sync content into Knowledge and give agents tools, with credentials encrypted on the server. --- import { Callout } from 'nextra/components' @@ -20,7 +20,7 @@ Open **Settings > Connectors**. Filters narrow the list by category, and **Conne 2. Choose what the connection sets up. File services offer a synced source (pick files or folders, then how often to sync: never, daily, weekly or monthly). Tool services create their tools right away. 3. Adjust what the tools may do. Each action is **Read** or **Write**, and each can be **Always allow**, **Needs approval** or **Off**. Writes default to needing approval. -The **Add Source** and **Add Tool** dialogs, the composer's Sources and Tools menus, and the agent builder all start the same flow, and list tools grouped by the connection they use. +**Knowledge** (formerly Sources) is what the assistant searches: uploads, links, and content synced from your connections. The **Add knowledge** and **Add Tool** dialogs, the composer's Knowledge and Tools menus, and the agent builder all start the same flow, and list tools grouped by the connection they use. A service offered two ways appears as one card: Confluence syncs pages into Knowledge and, through **Jira & Confluence**, lets agents search and update Jira and Confluence. Click a connected card to see its account, the sources and tools that use it, and to **Reconnect** or **Disconnect**. Disconnecting keeps a source's indexed content but stops its sync. diff --git a/docsgpt/connectors/catalog.py b/docsgpt/connectors/catalog.py index dcc4e39a..1f0f5925 100644 --- a/docsgpt/connectors/catalog.py +++ b/docsgpt/connectors/catalog.py @@ -76,6 +76,8 @@ class ConnectorDefinition: publisher: ``built_in``, ``preset`` or ``custom``. docs_url: Setup guide for admins. oauth_scopes: Scopes an MCP preset requests. + part_of: Another connector this one is shown under, for one service + offered two ways (the Atlassian MCP preset under Confluence). """ key: str @@ -96,6 +98,7 @@ class ConnectorDefinition: publisher: str = "built_in" docs_url: Optional[str] = None oauth_scopes: tuple[str, ...] = () + part_of: Optional[str] = None @property def missing_settings(self) -> list[str]: @@ -132,6 +135,7 @@ class ConnectorDefinition: "publisher": self.publisher, "docs_url": self.docs_url, "oauth_scopes": list(self.oauth_scopes), + "part_of": self.part_of, } @@ -328,6 +332,7 @@ def _load_presets(path: Optional[Path] = None) -> tuple[ConnectorDefinition, ... publisher="preset", docs_url=entry.get("docs_url"), oauth_scopes=tuple(entry.get("oauth_scopes") or ()), + part_of=entry.get("part_of"), ) ) return tuple(presets) diff --git a/docsgpt/connectors/presets/mcp.yaml b/docsgpt/connectors/presets/mcp.yaml index c9642c80..96d984c9 100644 --- a/docsgpt/connectors/presets/mcp.yaml +++ b/docsgpt/connectors/presets/mcp.yaml @@ -31,10 +31,12 @@ docs_url: https://linear.app/docs/mcp - key: mcp:atlassian - name: Atlassian (Jira and Confluence) + name: Jira & Confluence description: Search and update Jira issues and Confluence pages. icon: atlassian category: dev + # Shown on the Confluence card, next to syncing pages into Knowledge. + part_of: confluence mcp_url: https://mcp.atlassian.com/v1/mcp auth_kind: mcp_oauth capabilities: [read, write] diff --git a/frontend/src/components/SourcesPopoverFooter.test.tsx b/frontend/src/components/SourcesPopoverFooter.test.tsx index 4ed7e827..5e7db7b5 100644 --- a/frontend/src/components/SourcesPopoverFooter.test.tsx +++ b/frontend/src/components/SourcesPopoverFooter.test.tsx @@ -54,7 +54,7 @@ describe('SourcesPopoverFooter', () => { it('renders the sources link as an inline link Button', async () => { await renderFooter(); const [link, connect] = Array.from(container.querySelectorAll('a')); - expect(link.getAttribute('href')).toBe('/settings/sources'); + expect(link.getAttribute('href')).toBe('/settings/knowledge'); expect(connect.getAttribute('href')).toBe( '/settings/connectors?capability=sync', ); diff --git a/frontend/src/components/SourcesPopoverFooter.tsx b/frontend/src/components/SourcesPopoverFooter.tsx index 27378bad..441de6f1 100644 --- a/frontend/src/components/SourcesPopoverFooter.tsx +++ b/frontend/src/components/SourcesPopoverFooter.tsx @@ -26,7 +26,7 @@ export default function SourcesPopoverFooter({
} diff --git a/frontend/src/connectors/ConnectionDrawer.tsx b/frontend/src/connectors/ConnectionDrawer.tsx index c820027b..ffc9d510 100644 --- a/frontend/src/connectors/ConnectionDrawer.tsx +++ b/frontend/src/connectors/ConnectionDrawer.tsx @@ -381,10 +381,13 @@ function AccountSection({ */ export default function ConnectionDrawer({ connector, + parts = [], onClose, onConnect, }: { connector: ConnectorDefinition | null; + /** The same service offered another way, shown here (Jira & Confluence). */ + parts?: ConnectorDefinition[]; onClose: () => void; onConnect: (connector: ConnectorDefinition, options?: LaunchOptions) => void; }) { @@ -401,8 +404,9 @@ export default function ConnectionDrawer({ ); const [toRemove, setToRemove] = useState(null); + const keys = [connector?.key, ...parts.map((part) => part.key)]; const accountIds = connections - .filter((connection) => connection.connector_key === connector?.key) + .filter((connection) => keys.includes(connection.connector_key)) .map((connection) => `${connection.id}:${connection.status}`) .join(','); @@ -458,8 +462,12 @@ export default function ConnectionDrawer({ const reconnect = (detail: ConnectionDetail) => { if (!connector) return; + // A part's account (Jira & Confluence under Confluence) reconnects + // through its own connector. + const target = + parts.find((part) => part.key === detail.connector_key) ?? connector; const mcpTool = detail.tools.find((tool) => tool.name === 'mcp_tool'); - onConnect(connector, { + onConnect(target, { mode: 'reconnect', connectionId: detail.id, mcpServer: @@ -497,6 +505,9 @@ export default function ConnectionDrawer({ if (!connector) return null; const name = connectorName(t, connector); + const ownDetails = details.filter( + (detail) => detail.connector_key === connector.key, + ); return ( <> @@ -509,16 +520,11 @@ export default function ConnectionDrawer({ >
{/* pr-12 keeps the header clear of the close X. */} -
+
-
- {name} -

- {t(`settings.connectors.publisher.${connector.publisher}`)} -

-
+ {name}
{connectorDescription(t, connector)} @@ -544,7 +550,7 @@ export default function ConnectionDrawer({ size="xs" title={t('settings.connectors.detail.accounts')} actions={ - connector.available && details.length > 0 ? ( + connector.available && ownDetails.length > 0 ? ( + ) : undefined + } + /> + + {partDetails.map((detail) => ( + + onConnect(part, { mode: 'sync', connectionId: d.id }) + } + onRefreshTools={refreshTools} + /> + ))} + + ); + })}
diff --git a/frontend/src/connectors/ConnectorCard.tsx b/frontend/src/connectors/ConnectorCard.tsx index 9f73188a..30c14b12 100644 --- a/frontend/src/connectors/ConnectorCard.tsx +++ b/frontend/src/connectors/ConnectorCard.tsx @@ -22,10 +22,10 @@ export function CapabilityBadges({ return (
{capabilities.map((capability) => ( - // Capabilities are categories, not states: neutral, so the status - // hues stay free for the state badge (DESIGN.md "Colour tokens"). + // What it does, in plain words; categories, not states, so neutral and + // the status hues stay free for the state badge. - {t(`settings.connectors.capability.${capability}`)} + {t(`settings.connectors.capabilityPlain.${capability}`)} ))}
@@ -108,16 +108,9 @@ export default function ConnectorCard({ > - - - {name} - - {connector.publisher !== 'built_in' && ( - - {t(`settings.connectors.publisher.${connector.publisher}`)} - - )} - + + {name} + {connectorDescription(t, connector)} diff --git a/frontend/src/connectors/types.ts b/frontend/src/connectors/types.ts index 557e4491..0d17d464 100644 --- a/frontend/src/connectors/types.ts +++ b/frontend/src/connectors/types.ts @@ -51,6 +51,8 @@ export type ConnectorDefinition = { publisher: 'built_in' | 'preset' | 'custom'; docs_url: string | null; oauth_scopes: string[]; + /** Shown under this connector's card (one service offered two ways). */ + part_of?: string | null; available: boolean; disabled: boolean; needs_setup: boolean; diff --git a/frontend/src/locale/de.json b/frontend/src/locale/de.json index 1bfaebdc..7c8970a5 100644 --- a/frontend/src/locale/de.json +++ b/frontend/src/locale/de.json @@ -98,15 +98,15 @@ "sources": { "title": "Hier kannst du alle verfügbaren Quelldateien verwalten, die dir zur Verfügung stehen und die du hochgeladen hast.", "subtitle": "Inhalte, die DocsGPT durchsuchen und zitieren kann: Uploads, Websites, Wikis und aus deinen Verbindungen synchronisierte Inhalte.", - "label": "Quellen", + "label": "Wissen", "name": "Quellenname", "date": "Vektor-Datum", "type": "Typ", "tokenUsage": "Token-Verbrauch", - "noData": "Keine vorhandenen Quellen", + "noData": "Noch kein Wissen", "searchPlaceholder": "Suchen...", "addNew": "Neu hinzufügen", - "addSource": "Quelle hinzufügen", + "addSource": "Wissen hinzufügen", "addChunk": "Chunk hinzufügen", "preLoaded": "Vorgeladen", "private": "Privat", @@ -294,7 +294,7 @@ "chunks": "Chunks", "noChunks": "Keine Chunks gefunden", "noChunksAlt": "Keine Chunks gefunden", - "goToSources": "Zu den Quellen", + "goToSources": "Zum Wissen", "uploadNew": "Neu hochladen", "noResults": "Keine Ergebnisse gefunden", "fileName": "Name", @@ -1093,9 +1093,9 @@ }, "connectors": { "label": "Konnektoren", - "subtitle": "Verbinde DocsGPT mit den Diensten, die dein Team nutzt. Eine Verbindung kann Inhalte in Quellen synchronisieren und Agenten Werkzeuge geben.", + "subtitle": "Verbinde DocsGPT mit den Diensten, die dein Team nutzt. Eine Verbindung kann Inhalte ins Wissen synchronisieren und Agenten Werkzeuge geben.", "search": "Konnektoren suchen...", - "addCustom": "Eigenen Konnektor hinzufügen", + "addCustom": "Eigenes Werkzeug hinzufügen", "custom": { "custom_mcp": "MCP-Server", "custom_openapi": "OpenAPI / REST" @@ -1104,8 +1104,8 @@ "categories": { "all": "Alle", "connected": "Verbunden", - "files": "Dateien und Dokumente", - "knowledge": "Wissensdatenbanken", + "files": "Dateien & Speicher", + "knowledge": "Dokus & Wikis", "dev": "Entwicklerwerkzeuge", "messaging": "Nachrichten", "database": "Datenbanken", @@ -1139,11 +1139,11 @@ "custom": "Eigener" }, "descriptions": { - "google_drive": "Docs, Tabellen und PDFs in Quellen synchronisieren.", - "share_point": "Dateien aus SharePoint-Sites und OneDrive in Quellen synchronisieren.", - "confluence": "Confluence-Bereiche und -Seiten in Quellen synchronisieren.", - "s3": "Dokumente aus einem S3-Bucket in Quellen synchronisieren.", - "reddit": "Reddit-Beiträge zu deinen Suchen in Quellen synchronisieren.", + "google_drive": "Docs, Tabellen und PDFs ins Wissen synchronisieren.", + "share_point": "Dateien aus SharePoint-Sites und OneDrive ins Wissen synchronisieren.", + "confluence": "Confluence-Bereiche und -Seiten ins Wissen synchronisieren.", + "s3": "Dokumente aus einem S3-Bucket ins Wissen synchronisieren.", + "reddit": "Reddit-Beiträge zu deinen Suchen ins Wissen synchronisieren.", "brave": "Web und Bilder mit der Brave Search API durchsuchen.", "telegram": "Nachrichten und Bilder an einen Telegram-Chat senden.", "ntfy": "Push-Benachrichtigungen über einen ntfy-Server senden.", @@ -1168,7 +1168,7 @@ "accounts": "Konten", "connectedAs": "Verbunden als {{account}}", "connectAnother": "Weiteres Konto verbinden", - "sources": "Quellen aus dieser Verbindung", + "sources": "Wissen aus dieser Verbindung", "tools": "Werkzeuge aus dieser Verbindung", "noAccounts": "Noch kein Konto verbunden.", "failed": "Diese Verbindung konnte nicht geladen werden.", @@ -1284,17 +1284,22 @@ }, "createFailed": "Der Konnektor konnte nicht hinzugefügt werden. Versuche es erneut.", "capabilityFilter": { - "sync": "Angezeigt werden Konnektoren, die Inhalte in Quellen synchronisieren.", + "sync": "Angezeigt werden Konnektoren, die Inhalte ins Wissen synchronisieren.", "tools": "Angezeigt werden Konnektoren, die Agenten Werkzeuge geben.", "showAll": "Alle anzeigen" + }, + "capabilityPlain": { + "sync": "Synchronisiert ins Wissen", + "read": "Schlägt nach", + "write": "Führt Aktionen aus" } } }, "modals": { "uploadDoc": { - "label": "Quelle hinzufügen", + "label": "Wissen hinzufügen", "select": "Wähle, wie du dein Dokument zu DocsGPT hochladen möchtest", - "selectSource": "Quelle hinzufügen", + "selectSource": "Wissen hinzufügen", "selectedFiles": "Ausgewählte Dateien", "noFilesSelected": "Keine Dateien ausgewählt", "file": "Vom Gerät hochladen", @@ -1309,7 +1314,7 @@ "filesRejected": "Nicht hinzugefügt (größer als 25 MB oder kein unterstützter Dateityp): {{files}}", "uploadedFiles": "Hochgeladene Dateien", "cancel": "Abbrechen", - "train": "Quelle hinzufügen", + "train": "Zum Wissen hinzufügen", "create": "Erstellen", "link": "Link", "urlLink": "URL-Link", @@ -1659,17 +1664,18 @@ }, "sources": { "title": "Quellen", - "text": "Wähle deine Quellen", + "text": "Wissen auswählen", "link": "Quellen-Link", "view_more_one": "{{count}} weitere Quelle", "view_more_other": "{{count}} weitere Quellen", - "noSourcesAvailable": "Keine Quellen verfügbar", + "noSourcesAvailable": "Noch kein Wissen", "selectedCount": "{{count}} Quellen ausgewählt", "groupOwn": "Deine Quellen", "groupTeam": "Mit dem Team geteilt", "connectMore": "Weitere verbinden", "fromConnector": "Aus {{name}}", - "fromConnectorTitle": "Aus {{name}}: {{title}}" + "fromConnectorTitle": "Aus {{name}}: {{title}}", + "knowledge": "Wissen" }, "attachments": { "attach": "Anhängen", @@ -1894,7 +1900,7 @@ "placeholders": { "agentName": "Agentenname", "describeAgent": "Beschreibe deinen Agenten", - "selectSources": "Quellen auswählen", + "selectSources": "Wissen auswählen", "chunksPerQuery": "Chunks pro Anfrage", "selectType": "Typ auswählen", "selectTools": "Werkzeuge auswählen", @@ -1904,19 +1910,19 @@ "enterRequestLimit": "Anfrage-Limit eingeben" }, "sourcePopup": { - "title": "Quellen auswählen", - "searchPlaceholder": "Quellen suchen...", - "noOptionsMessage": "Keine Quellen verfügbar", + "title": "Wissen auswählen", + "searchPlaceholder": "Wissen durchsuchen...", + "noOptionsMessage": "Noch kein Wissen", "groupOwn": "Deine Quellen", "groupTeam": "Mit dem Team geteilt", - "noSourceHint": "Optional. Ohne Quelle antwortet der Agent nur anhand des Modells und seiner Werkzeuge." + "noSourceHint": "Optional. Ohne Wissen antwortet der Agent nur mit dem Modell und seinen Werkzeugen." }, "toolsPopup": { "title": "Werkzeuge auswählen", "searchPlaceholder": "Werkzeuge suchen...", "noOptionsMessage": "Keine Werkzeuge verfügbar", "groupBuiltin": "Integriert", - "groupDefault": "Standard", + "groupDefault": "Integriert", "groupCustom": "Benutzerdefiniert", "groupConnection": "{{name}} · {{account}}" }, @@ -1938,7 +1944,7 @@ "defaultModel": "Standardmodell", "name": "Name", "description": "Beschreibung", - "sources": "Quellen", + "sources": "Wissen", "avatar": "Avatar" }, "advanced": { @@ -2317,7 +2323,7 @@ "outputVariable": "Ausgabevariable", "outputVariablePlaceholder": "Variablenname für die Ausgabe", "streamToUser": "Ausgabe an Nutzer streamen", - "sources": "Quellen", + "sources": "Wissen", "documents": "Dokumente", "documentsHint": "Dokumente, die diesem Agenten aus Uploads oder vorgelagerten Knoten übergeben werden.", "filePassing": "Dateiübergabe", diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index 2281af8f..53ea673c 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -102,15 +102,15 @@ "sources": { "title": "Here you can manage all of the source file that are available to you and those you have uploaded.", "subtitle": "Content DocsGPT can search and cite: uploads, websites, wikis and content synced from your connections.", - "label": "Sources", + "label": "Knowledge", "name": "Source Name", "date": "Vector Date", "type": "Type", "tokenUsage": "Token Usage", - "noData": "No existing Sources", + "noData": "No knowledge yet", "searchPlaceholder": "Search...", "addNew": "Add New", - "addSource": "Add Source", + "addSource": "Add knowledge", "addChunk": "Add Chunk", "preLoaded": "Pre-loaded", "private": "Private", @@ -299,7 +299,7 @@ "chunks": "Chunks", "noChunks": "No chunks found", "noChunksAlt": "No chunks found", - "goToSources": "Go to Sources", + "goToSources": "Go to Knowledge", "uploadNew": "Upload new", "noResults": "No results found", "fileName": "Name", @@ -1099,9 +1099,9 @@ }, "connectors": { "label": "Connectors", - "subtitle": "Connect DocsGPT to the services your team uses. A connection can sync content into Sources and give agents tools.", + "subtitle": "Connect DocsGPT to the services your team uses. A connection can sync content into Knowledge and give agents tools.", "search": "Search connectors...", - "addCustom": "Add custom connector", + "addCustom": "Add custom tool", "custom": { "custom_mcp": "MCP server", "custom_openapi": "OpenAPI / REST" @@ -1110,8 +1110,8 @@ "categories": { "all": "All", "connected": "Connected", - "files": "Files and docs", - "knowledge": "Knowledge bases", + "files": "Files & storage", + "knowledge": "Docs & wikis", "dev": "Developer tools", "messaging": "Messaging", "database": "Databases", @@ -1145,11 +1145,11 @@ "custom": "Custom" }, "descriptions": { - "google_drive": "Sync Docs, Sheets and PDFs into Sources.", - "share_point": "Sync files from SharePoint sites and OneDrive into Sources.", - "confluence": "Sync Confluence spaces and pages into Sources.", - "s3": "Sync documents from an S3 bucket into Sources.", - "reddit": "Sync Reddit posts that match your searches into Sources.", + "google_drive": "Sync Docs, Sheets and PDFs into Knowledge.", + "share_point": "Sync files from SharePoint sites and OneDrive into Knowledge.", + "confluence": "Sync Confluence spaces and pages into Knowledge.", + "s3": "Sync documents from an S3 bucket into Knowledge.", + "reddit": "Sync Reddit posts that match your searches into Knowledge.", "brave": "Search the web and images with the Brave Search API.", "telegram": "Send messages and images to a Telegram chat.", "ntfy": "Send push notifications through an ntfy server.", @@ -1174,7 +1174,7 @@ "accounts": "Accounts", "connectedAs": "Connected as {{account}}", "connectAnother": "Connect another account", - "sources": "Sources from this connection", + "sources": "Knowledge from this connection", "tools": "Tools from this connection", "noAccounts": "No account connected yet.", "failed": "Could not load this connection.", @@ -1290,17 +1290,22 @@ }, "createFailed": "Could not add the connector. Try again.", "capabilityFilter": { - "sync": "Showing connectors that sync content into Sources.", + "sync": "Showing connectors that sync content into Knowledge.", "tools": "Showing connectors that give agents tools.", "showAll": "Show all" + }, + "capabilityPlain": { + "sync": "Syncs into Knowledge", + "read": "Looks things up", + "write": "Takes actions" } } }, "modals": { "uploadDoc": { - "label": "Add a source", + "label": "Add knowledge", "select": "Choose how to upload your document to DocsGPT", - "selectSource": "Add a source", + "selectSource": "Add knowledge", "selectedFiles": "Selected Files", "noFilesSelected": "No files selected", "file": "Upload from device", @@ -1315,7 +1320,7 @@ "filesRejected": "Not added (over 25 MB or not a supported type): {{files}}", "uploadedFiles": "Uploaded Files", "cancel": "Cancel", - "train": "Add source", + "train": "Add to Knowledge", "create": "Create", "link": "Link", "urlLink": "URL Link", @@ -1665,17 +1670,18 @@ }, "sources": { "title": "Sources", - "text": "Choose Your Sources", + "text": "Choose knowledge", "link": "Source link", "view_more_one": "{{count}} more source", "view_more_other": "{{count}} more sources", - "noSourcesAvailable": "No sources available", + "noSourcesAvailable": "No knowledge yet", "selectedCount": "{{count}} sources selected", "groupOwn": "Your sources", "groupTeam": "Shared with team", "connectMore": "Connect more", "fromConnector": "From {{name}}", - "fromConnectorTitle": "From {{name}}: {{title}}" + "fromConnectorTitle": "From {{name}}: {{title}}", + "knowledge": "Knowledge" }, "attachments": { "attach": "Attach", @@ -1910,7 +1916,7 @@ "placeholders": { "agentName": "Agent name", "describeAgent": "Describe your agent", - "selectSources": "Select sources", + "selectSources": "Select knowledge", "chunksPerQuery": "Chunks per query", "selectType": "Select type", "selectTools": "Select tools", @@ -1920,19 +1926,19 @@ "enterRequestLimit": "Enter request limit" }, "sourcePopup": { - "title": "Select Sources", - "searchPlaceholder": "Search sources...", - "noOptionsMessage": "No sources available", + "title": "Select knowledge", + "searchPlaceholder": "Search knowledge...", + "noOptionsMessage": "No knowledge yet", "groupOwn": "Your sources", "groupTeam": "Shared with team", - "noSourceHint": "Optional. Without a source the agent answers from the model and its tools only." + "noSourceHint": "Optional. Without knowledge the agent answers from the model and its tools only." }, "toolsPopup": { "title": "Select Tools", "searchPlaceholder": "Search tools...", "noOptionsMessage": "No tools available", "groupBuiltin": "Built-in", - "groupDefault": "Default", + "groupDefault": "Built-in", "groupCustom": "Custom", "groupConnection": "{{name}} · {{account}}" }, @@ -1954,7 +1960,7 @@ "defaultModel": "Default Model", "name": "Name", "description": "Description", - "sources": "Sources", + "sources": "Knowledge", "avatar": "Avatar" }, "advanced": { @@ -2352,7 +2358,7 @@ "outputVariable": "Output Variable", "outputVariablePlaceholder": "Variable name for output", "streamToUser": "Stream output to user", - "sources": "Sources", + "sources": "Knowledge", "documents": "Documents", "documentsHint": "Documents passed to this agent from uploads or upstream nodes.", "filePassing": "File passing", diff --git a/frontend/src/locale/es.json b/frontend/src/locale/es.json index 767ce974..37cc4b8b 100644 --- a/frontend/src/locale/es.json +++ b/frontend/src/locale/es.json @@ -98,15 +98,15 @@ "sources": { "title": "Aquí puedes gestionar todos los archivos fuente que están disponibles para ti y los que has subido.", "subtitle": "Contenido que DocsGPT puede buscar y citar: archivos subidos, sitios web, wikis y contenido sincronizado desde tus conexiones.", - "label": "Fuentes", + "label": "Conocimiento", "name": "Nombre de la Fuente", "date": "Fecha de Vector", "type": "Tipo", "tokenUsage": "Uso de Tokens", - "noData": "No hay fuentes existentes", + "noData": "Aún no hay conocimiento", "searchPlaceholder": "Buscar...", "addNew": "Agregar Nuevo", - "addSource": "Agregar Fuente", + "addSource": "Añadir conocimiento", "addChunk": "Agregar Fragmento", "preLoaded": "Precargado", "private": "Privado", @@ -294,7 +294,7 @@ "chunks": "Fragmentos", "noChunks": "No se encontraron fragmentos", "noChunksAlt": "No se encontraron fragmentos", - "goToSources": "Ir a Fuentes", + "goToSources": "Ir a Conocimiento", "uploadNew": "Subir nuevo", "noResults": "No se encontraron resultados", "fileName": "Nombre", @@ -1093,9 +1093,9 @@ }, "connectors": { "label": "Conectores", - "subtitle": "Conecta DocsGPT a los servicios que usa tu equipo. Una conexión puede sincronizar contenido en Fuentes y dar herramientas a los agentes.", + "subtitle": "Conecta DocsGPT a los servicios que usa tu equipo. Una conexión puede sincronizar contenido en Conocimiento y dar herramientas a los agentes.", "search": "Buscar conectores...", - "addCustom": "Añadir conector personalizado", + "addCustom": "Añadir herramienta propia", "custom": { "custom_mcp": "Servidor MCP", "custom_openapi": "OpenAPI / REST" @@ -1104,8 +1104,8 @@ "categories": { "all": "Todos", "connected": "Conectados", - "files": "Archivos y documentos", - "knowledge": "Bases de conocimiento", + "files": "Archivos y almacenamiento", + "knowledge": "Documentos y wikis", "dev": "Herramientas de desarrollo", "messaging": "Mensajería", "database": "Bases de datos", @@ -1139,11 +1139,11 @@ "custom": "Personalizado" }, "descriptions": { - "google_drive": "Sincroniza Docs, Hojas de cálculo y PDF en Fuentes.", - "share_point": "Sincroniza archivos de sitios de SharePoint y OneDrive en Fuentes.", - "confluence": "Sincroniza espacios y páginas de Confluence en Fuentes.", - "s3": "Sincroniza documentos de un bucket de S3 en Fuentes.", - "reddit": "Sincroniza en Fuentes las publicaciones de Reddit que coinciden con tus búsquedas.", + "google_drive": "Sincroniza Docs, Hojas de cálculo y PDF en Conocimiento.", + "share_point": "Sincroniza archivos de sitios de SharePoint y OneDrive en Conocimiento.", + "confluence": "Sincroniza espacios y páginas de Confluence en Conocimiento.", + "s3": "Sincroniza documentos de un bucket de S3 en Conocimiento.", + "reddit": "Sincroniza publicaciones de Reddit que coinciden con tus búsquedas en Conocimiento.", "brave": "Busca en la web e imágenes con la API de Brave Search.", "telegram": "Envía mensajes e imágenes a un chat de Telegram.", "ntfy": "Envía notificaciones push mediante un servidor ntfy.", @@ -1168,7 +1168,7 @@ "accounts": "Cuentas", "connectedAs": "Conectado como {{account}}", "connectAnother": "Conectar otra cuenta", - "sources": "Fuentes de esta conexión", + "sources": "Conocimiento de esta conexión", "tools": "Herramientas de esta conexión", "noAccounts": "Aún no hay ninguna cuenta conectada.", "failed": "No se pudo cargar esta conexión.", @@ -1284,17 +1284,22 @@ }, "createFailed": "No se pudo añadir el conector. Inténtalo de nuevo.", "capabilityFilter": { - "sync": "Se muestran los conectores que sincronizan contenido en Fuentes.", + "sync": "Se muestran los conectores que sincronizan contenido en Conocimiento.", "tools": "Se muestran los conectores que dan herramientas a los agentes.", "showAll": "Mostrar todos" + }, + "capabilityPlain": { + "sync": "Sincroniza en Conocimiento", + "read": "Consulta datos", + "write": "Realiza acciones" } } }, "modals": { "uploadDoc": { - "label": "Añadir una fuente", + "label": "Añadir conocimiento", "select": "Elige cómo cargar tu documento en DocsGPT", - "selectSource": "Añadir una fuente", + "selectSource": "Añadir conocimiento", "selectedFiles": "Archivos Seleccionados", "noFilesSelected": "No hay archivos seleccionados", "file": "Subir desde el dispositivo", @@ -1309,7 +1314,7 @@ "filesRejected": "No se añadieron (más de 25 MB o tipo no admitido): {{files}}", "uploadedFiles": "Archivos Subidos", "cancel": "Cancelar", - "train": "Añadir fuente", + "train": "Añadir al conocimiento", "create": "Crear", "link": "Enlace", "urlLink": "Enlace URL", @@ -1659,17 +1664,18 @@ }, "sources": { "title": "Fuentes", - "text": "Elegir tus fuentes", + "text": "Elegir conocimiento", "link": "Enlace fuente", "view_more_one": "Ver {{count}} fuente más", "view_more_other": "Ver {{count}} fuentes más", - "noSourcesAvailable": "No hay fuentes disponibles", + "noSourcesAvailable": "Aún no hay conocimiento", "selectedCount": "{{count}} fuentes seleccionadas", "groupOwn": "Tus fuentes", "groupTeam": "Compartidas con el equipo", "connectMore": "Conectar más", "fromConnector": "De {{name}}", - "fromConnectorTitle": "De {{name}}: {{title}}" + "fromConnectorTitle": "De {{name}}: {{title}}", + "knowledge": "Conocimiento" }, "attachments": { "attach": "Adjuntar", @@ -1894,7 +1900,7 @@ "placeholders": { "agentName": "Nombre del agente", "describeAgent": "Describe tu agente", - "selectSources": "Seleccionar fuentes", + "selectSources": "Seleccionar conocimiento", "chunksPerQuery": "Fragmentos por consulta", "selectType": "Seleccionar tipo", "selectTools": "Seleccionar herramientas", @@ -1904,19 +1910,19 @@ "enterRequestLimit": "Ingresar límite de solicitudes" }, "sourcePopup": { - "title": "Seleccionar Fuentes", - "searchPlaceholder": "Buscar fuentes...", - "noOptionsMessage": "No hay fuentes disponibles", + "title": "Seleccionar conocimiento", + "searchPlaceholder": "Buscar conocimiento...", + "noOptionsMessage": "Aún no hay conocimiento", "groupOwn": "Tus fuentes", "groupTeam": "Compartidas con el equipo", - "noSourceHint": "Opcional. Sin una fuente, el agente responde solo con el modelo y sus herramientas." + "noSourceHint": "Opcional. Sin conocimiento, el agente responde solo con el modelo y sus herramientas." }, "toolsPopup": { "title": "Seleccionar Herramientas", "searchPlaceholder": "Buscar herramientas...", "noOptionsMessage": "No hay herramientas disponibles", "groupBuiltin": "Integradas", - "groupDefault": "Predeterminadas", + "groupDefault": "Integradas", "groupCustom": "Personalizadas", "groupConnection": "{{name}} · {{account}}" }, @@ -1938,7 +1944,7 @@ "defaultModel": "Modelo Predeterminado", "name": "Nombre", "description": "Descripción", - "sources": "Fuentes", + "sources": "Conocimiento", "avatar": "Avatar" }, "advanced": { @@ -2317,7 +2323,7 @@ "outputVariable": "Variable de salida", "outputVariablePlaceholder": "Nombre de la variable de salida", "streamToUser": "Transmitir la salida al usuario", - "sources": "Fuentes", + "sources": "Conocimiento", "documents": "Documentos", "documentsHint": "Documentos que se pasan a este agente desde cargas o nodos anteriores.", "filePassing": "Paso de archivos", diff --git a/frontend/src/locale/jp.json b/frontend/src/locale/jp.json index e634e8bd..e4fd81f4 100644 --- a/frontend/src/locale/jp.json +++ b/frontend/src/locale/jp.json @@ -98,15 +98,15 @@ "sources": { "title": "ここでは、利用可能なすべてのソースファイルとアップロードしたファイルを管理できます。", "subtitle": "DocsGPT が検索・引用できるコンテンツ:アップロード、ウェブサイト、Wiki、接続から同期したコンテンツ。", - "label": "ソース", + "label": "ナレッジ", "name": "ソース名", "date": "ベクトル日付", "type": "タイプ", "tokenUsage": "トークン使用量", - "noData": "既存のソースがありません", + "noData": "ナレッジはまだありません", "searchPlaceholder": "検索...", "addNew": "新規追加", - "addSource": "ソースを追加", + "addSource": "ナレッジを追加", "addChunk": "チャンクを追加", "preLoaded": "プリロード済み", "private": "プライベート", @@ -287,7 +287,7 @@ "chunks": "チャンク", "noChunks": "チャンクが見つかりません", "noChunksAlt": "チャンクが見つかりません", - "goToSources": "ソースへ移動", + "goToSources": "ナレッジへ移動", "uploadNew": "新規アップロード", "noResults": "結果が見つかりません", "fileName": "名前", @@ -1084,9 +1084,9 @@ }, "connectors": { "label": "コネクタ", - "subtitle": "DocsGPT をチームで使っているサービスに接続します。接続ごとに、コンテンツをソースへ同期したり、エージェントにツールを提供したりできます。", + "subtitle": "DocsGPT をチームで使っているサービスに接続します。接続ごとに、コンテンツをナレッジへ同期したり、エージェントにツールを提供したりできます。", "search": "コネクタを検索...", - "addCustom": "カスタムコネクタを追加", + "addCustom": "カスタムツールを追加", "custom": { "custom_mcp": "MCP サーバー", "custom_openapi": "OpenAPI / REST" @@ -1095,8 +1095,8 @@ "categories": { "all": "すべて", "connected": "接続済み", - "files": "ファイルとドキュメント", - "knowledge": "ナレッジベース", + "files": "ファイルとストレージ", + "knowledge": "ドキュメントと Wiki", "dev": "開発者ツール", "messaging": "メッセージ", "database": "データベース", @@ -1130,11 +1130,11 @@ "custom": "カスタム" }, "descriptions": { - "google_drive": "ドキュメント、スプレッドシート、PDF をソースに同期します。", - "share_point": "SharePoint サイトと OneDrive のファイルをソースに同期します。", - "confluence": "Confluence のスペースとページをソースに同期します。", - "s3": "S3 バケットのドキュメントをソースに同期します。", - "reddit": "検索に一致する Reddit の投稿をソースに同期します。", + "google_drive": "ドキュメント、スプレッドシート、PDF をナレッジに同期します。", + "share_point": "SharePoint サイトと OneDrive のファイルをナレッジに同期します。", + "confluence": "Confluence のスペースとページをナレッジに同期します。", + "s3": "S3 バケットのドキュメントをナレッジに同期します。", + "reddit": "検索条件に一致する Reddit の投稿をナレッジに同期します。", "brave": "Brave Search API でウェブと画像を検索します。", "telegram": "Telegram のチャットにメッセージや画像を送信します。", "ntfy": "ntfy サーバー経由でプッシュ通知を送信します。", @@ -1159,7 +1159,7 @@ "accounts": "アカウント", "connectedAs": "{{account}} として接続中", "connectAnother": "別のアカウントを接続", - "sources": "この接続のソース", + "sources": "この接続からのナレッジ", "tools": "この接続のツール", "noAccounts": "まだアカウントが接続されていません。", "failed": "この接続を読み込めませんでした。", @@ -1268,17 +1268,22 @@ }, "createFailed": "コネクタを追加できませんでした。もう一度お試しください。", "capabilityFilter": { - "sync": "ソースにコンテンツを同期するコネクタを表示しています。", + "sync": "ナレッジにコンテンツを同期するコネクタを表示しています。", "tools": "エージェントにツールを提供するコネクタを表示しています。", "showAll": "すべて表示" + }, + "capabilityPlain": { + "sync": "ナレッジに同期", + "read": "情報を調べる", + "write": "操作を行う" } } }, "modals": { "uploadDoc": { - "label": "ソースを追加", + "label": "ナレッジを追加", "select": "ドキュメントを DocsGPT にアップロードする方法を選択します", - "selectSource": "ソースを追加", + "selectSource": "ナレッジを追加", "selectedFiles": "選択されたファイル", "noFilesSelected": "ファイルが選択されていません", "file": "デバイスからアップロード", @@ -1293,7 +1298,7 @@ "filesRejected": "追加されませんでした(25 MB を超えているか、未対応の形式です): {{files}}", "uploadedFiles": "アップロードされたファイル", "cancel": "キャンセル", - "train": "ソースを追加", + "train": "ナレッジに追加", "create": "作成", "link": "リンク", "urlLink": "URLリンク", @@ -1642,16 +1647,17 @@ }, "sources": { "title": "ソース", - "text": "ソーステキスト", + "text": "ナレッジを選択", "link": "ソースリンク", "view_more": "さらに{{count}}個のソース", - "noSourcesAvailable": "利用可能なソースがありません", + "noSourcesAvailable": "ナレッジはまだありません", "selectedCount": "{{count}} 件のソースを選択中", "groupOwn": "自分のソース", "groupTeam": "チームと共有", "connectMore": "さらに接続", "fromConnector": "{{name}} から", - "fromConnectorTitle": "{{name}} から: {{title}}" + "fromConnectorTitle": "{{name}} から: {{title}}", + "knowledge": "ナレッジ" }, "attachments": { "attach": "添付", @@ -1875,7 +1881,7 @@ "placeholders": { "agentName": "エージェント名", "describeAgent": "エージェントを説明してください", - "selectSources": "ソースを選択", + "selectSources": "ナレッジを選択", "chunksPerQuery": "クエリごとのチャンク数", "selectType": "タイプを選択", "selectTools": "ツールを選択", @@ -1885,19 +1891,19 @@ "enterRequestLimit": "リクエスト制限を入力" }, "sourcePopup": { - "title": "ソースを選択", - "searchPlaceholder": "ソースを検索...", - "noOptionsMessage": "利用可能なソースがありません", + "title": "ナレッジを選択", + "searchPlaceholder": "ナレッジを検索...", + "noOptionsMessage": "ナレッジはまだありません", "groupOwn": "自分のソース", "groupTeam": "チームと共有", - "noSourceHint": "任意。ソースがない場合、エージェントはモデルとツールのみで回答します。" + "noSourceHint": "任意です。ナレッジがない場合、エージェントはモデルとツールだけで回答します。" }, "toolsPopup": { "title": "ツールを選択", "searchPlaceholder": "ツールを検索...", "noOptionsMessage": "利用可能なツールがありません", "groupBuiltin": "ビルトイン", - "groupDefault": "デフォルト", + "groupDefault": "組み込み", "groupCustom": "カスタム", "groupConnection": "{{name}} · {{account}}" }, @@ -1919,7 +1925,7 @@ "defaultModel": "デフォルトモデル", "name": "名前", "description": "説明", - "sources": "ソース", + "sources": "ナレッジ", "avatar": "アバター" }, "advanced": { @@ -2297,7 +2303,7 @@ "outputVariable": "出力変数", "outputVariablePlaceholder": "出力の変数名", "streamToUser": "出力をユーザーにストリーミング", - "sources": "ソース", + "sources": "ナレッジ", "documents": "ドキュメント", "documentsHint": "アップロードまたは上流ノードからこのエージェントに渡されるドキュメント。", "filePassing": "ファイルの受け渡し", diff --git a/frontend/src/locale/ru.json b/frontend/src/locale/ru.json index 7869d5b9..f50b79cc 100644 --- a/frontend/src/locale/ru.json +++ b/frontend/src/locale/ru.json @@ -98,15 +98,15 @@ "sources": { "title": "Здесь вы можете управлять всеми исходными файлами, которые доступны вам и которые вы загрузили.", "subtitle": "Контент, по которому DocsGPT может искать и который может цитировать: загрузки, сайты, вики и контент, синхронизированный из ваших подключений.", - "label": "Источники", + "label": "Знания", "name": "Название источника", "date": "Дата вектора", "type": "Тип", "tokenUsage": "Использование токена", - "noData": "Нет существующих источников", + "noData": "Знаний пока нет", "searchPlaceholder": "Поиск...", "addNew": "добавить новый", - "addSource": "Добавить источник", + "addSource": "Добавить знания", "addChunk": "Добавить фрагмент", "preLoaded": "Предзагруженный", "private": "Частный", @@ -318,7 +318,7 @@ "chunks": "Фрагменты", "noChunks": "Фрагменты не найдены", "noChunksAlt": "Фрагменты не найдены", - "goToSources": "Перейти к источникам", + "goToSources": "К знаниям", "uploadNew": "Загрузить новый", "noResults": "Результаты не найдены", "fileName": "Имя", @@ -1149,9 +1149,9 @@ }, "connectors": { "label": "Коннекторы", - "subtitle": "Подключите DocsGPT к сервисам, которыми пользуется ваша команда. Подключение может синхронизировать контент в Источники и давать агентам инструменты.", + "subtitle": "Подключите DocsGPT к сервисам, которыми пользуется ваша команда. Подключение может синхронизировать содержимое в знания и давать агентам инструменты.", "search": "Поиск коннекторов...", - "addCustom": "Добавить свой коннектор", + "addCustom": "Добавить свой инструмент", "custom": { "custom_mcp": "MCP-сервер", "custom_openapi": "OpenAPI / REST" @@ -1160,8 +1160,8 @@ "categories": { "all": "Все", "connected": "Подключённые", - "files": "Файлы и документы", - "knowledge": "Базы знаний", + "files": "Файлы и хранилища", + "knowledge": "Документы и вики", "dev": "Инструменты разработчика", "messaging": "Сообщения", "database": "Базы данных", @@ -1195,11 +1195,11 @@ "custom": "Свой" }, "descriptions": { - "google_drive": "Синхронизирует Документы, Таблицы и PDF в Источники.", - "share_point": "Синхронизирует файлы с сайтов SharePoint и из OneDrive в Источники.", - "confluence": "Синхронизирует пространства и страницы Confluence в Источники.", - "s3": "Синхронизирует документы из бакета S3 в Источники.", - "reddit": "Синхронизирует в Источники посты Reddit по вашим поисковым запросам.", + "google_drive": "Синхронизирует Документы, Таблицы и PDF в знания.", + "share_point": "Синхронизирует файлы с сайтов SharePoint и из OneDrive в знания.", + "confluence": "Синхронизирует пространства и страницы Confluence в знания.", + "s3": "Синхронизирует документы из бакета S3 в знания.", + "reddit": "Синхронизирует публикации Reddit по вашим запросам в знания.", "brave": "Поиск в интернете и по картинкам через Brave Search API.", "telegram": "Отправляет сообщения и изображения в чат Telegram.", "ntfy": "Отправляет push-уведомления через сервер ntfy.", @@ -1224,7 +1224,7 @@ "accounts": "Аккаунты", "connectedAs": "Подключено как {{account}}", "connectAnother": "Подключить другой аккаунт", - "sources": "Источники из этого подключения", + "sources": "Знания из этого подключения", "tools": "Инструменты из этого подключения", "noAccounts": "Аккаунт ещё не подключён.", "failed": "Не удалось загрузить это подключение.", @@ -1354,17 +1354,22 @@ }, "createFailed": "Не удалось добавить коннектор. Попробуйте ещё раз.", "capabilityFilter": { - "sync": "Показаны коннекторы, которые синхронизируют содержимое в источники.", + "sync": "Показаны коннекторы, которые синхронизируют содержимое в знания.", "tools": "Показаны коннекторы, которые дают агентам инструменты.", "showAll": "Показать все" + }, + "capabilityPlain": { + "sync": "Синхронизирует в знания", + "read": "Ищет информацию", + "write": "Выполняет действия" } } }, "modals": { "uploadDoc": { - "label": "Добавить источник", + "label": "Добавить знания", "select": "Выберите способ загрузки документа в DocsGPT", - "selectSource": "Добавить источник", + "selectSource": "Добавить знания", "selectedFiles": "Выбранные файлы", "noFilesSelected": "Файлы не выбраны", "file": "Загрузить с устройства", @@ -1379,7 +1384,7 @@ "filesRejected": "Не добавлены (больше 25 МБ или неподдерживаемый формат): {{files}}", "uploadedFiles": "Загруженные файлы", "cancel": "Отмена", - "train": "Добавить источник", + "train": "Добавить в знания", "create": "Создать", "link": "Ссылка", "urlLink": "URL ссылка", @@ -1731,19 +1736,20 @@ }, "sources": { "title": "Источники", - "text": "Выберите ваши источники", + "text": "Выберите знания", "link": "Ссылка на источник", "view_more_one": "ещё {{count}} источник", "view_more_few": "ещё {{count}} источника", "view_more_many": "ещё {{count}} источников", "view_more_other": "ещё {{count}} источников", - "noSourcesAvailable": "Нет доступных источников", + "noSourcesAvailable": "Знаний пока нет", "selectedCount": "Выбрано источников: {{count}}", "groupOwn": "Ваши источники", "groupTeam": "Общие с командой", "connectMore": "Подключить ещё", "fromConnector": "Из {{name}}", - "fromConnectorTitle": "Из {{name}}: {{title}}" + "fromConnectorTitle": "Из {{name}}: {{title}}", + "knowledge": "Знания" }, "attachments": { "attach": "Прикрепить", @@ -1970,7 +1976,7 @@ "placeholders": { "agentName": "Имя агента", "describeAgent": "Опишите вашего агента", - "selectSources": "Выберите источники", + "selectSources": "Выберите знания", "chunksPerQuery": "Фрагментов на запрос", "selectType": "Выберите тип", "selectTools": "Выберите инструменты", @@ -1980,19 +1986,19 @@ "enterRequestLimit": "Введите лимит запросов" }, "sourcePopup": { - "title": "Выберите Источники", - "searchPlaceholder": "Поиск источников...", - "noOptionsMessage": "Нет доступных источников", + "title": "Выберите знания", + "searchPlaceholder": "Поиск по знаниям...", + "noOptionsMessage": "Знаний пока нет", "groupOwn": "Ваши источники", "groupTeam": "Общие с командой", - "noSourceHint": "Необязательно. Без источника агент отвечает только на основе модели и своих инструментов." + "noSourceHint": "Необязательно. Без знаний агент отвечает только с помощью модели и своих инструментов." }, "toolsPopup": { "title": "Выберите Инструменты", "searchPlaceholder": "Поиск инструментов...", "noOptionsMessage": "Нет доступных инструментов", "groupBuiltin": "Встроенные", - "groupDefault": "По умолчанию", + "groupDefault": "Встроенные", "groupCustom": "Пользовательские", "groupConnection": "{{name}} · {{account}}" }, @@ -2014,7 +2020,7 @@ "defaultModel": "Модель по умолчанию", "name": "Имя", "description": "Описание", - "sources": "Источники", + "sources": "Знания", "avatar": "Аватар" }, "advanced": { @@ -2401,7 +2407,7 @@ "outputVariable": "Выходная переменная", "outputVariablePlaceholder": "Имя переменной для вывода", "streamToUser": "Передавать вывод пользователю потоком", - "sources": "Источники", + "sources": "Знания", "documents": "Документы", "documentsHint": "Документы, передаваемые этому агенту из загрузок или предыдущих узлов.", "filePassing": "Передача файлов", diff --git a/frontend/src/locale/zh-TW.json b/frontend/src/locale/zh-TW.json index abb97e28..23cb4023 100644 --- a/frontend/src/locale/zh-TW.json +++ b/frontend/src/locale/zh-TW.json @@ -98,15 +98,15 @@ "sources": { "title": "在這裡您可以管理所有可用的來源檔案以及您上傳的檔案。", "subtitle": "DocsGPT 可以搜尋和引用的內容:上傳的檔案、網站、Wiki,以及從連線同步的內容。", - "label": "來源", + "label": "知識庫", "name": "來源名稱", "date": "向量日期", "type": "類型", "tokenUsage": "Token 使用量", - "noData": "沒有現有的來源", + "noData": "還沒有知識", "searchPlaceholder": "搜尋...", "addNew": "新增文件", - "addSource": "新增來源", + "addSource": "新增知識", "addChunk": "新增區塊", "preLoaded": "預載入", "private": "私人", @@ -287,7 +287,7 @@ "chunks": "文本塊", "noChunks": "未找到文本塊", "noChunksAlt": "未找到文本塊", - "goToSources": "前往來源", + "goToSources": "前往知識庫", "uploadNew": "上傳新文件", "noResults": "未找到結果", "fileName": "名稱", @@ -1084,9 +1084,9 @@ }, "connectors": { "label": "連接器", - "subtitle": "將 DocsGPT 連接到團隊使用的服務。一個連線可以把內容同步到來源,也可以為代理提供工具。", + "subtitle": "將 DocsGPT 連接到團隊使用的服務。一個連線可以把內容同步到知識庫,也可以為代理提供工具。", "search": "搜尋連接器...", - "addCustom": "新增自訂連接器", + "addCustom": "新增自訂工具", "custom": { "custom_mcp": "MCP 伺服器", "custom_openapi": "OpenAPI / REST" @@ -1095,8 +1095,8 @@ "categories": { "all": "全部", "connected": "已連線", - "files": "檔案和文件", - "knowledge": "知識庫", + "files": "檔案與儲存", + "knowledge": "文件與 Wiki", "dev": "開發者工具", "messaging": "訊息", "database": "資料庫", @@ -1130,11 +1130,11 @@ "custom": "自訂" }, "descriptions": { - "google_drive": "將文件、試算表和 PDF 同步到來源。", - "share_point": "將 SharePoint 網站和 OneDrive 中的檔案同步到來源。", - "confluence": "將 Confluence 空間和頁面同步到來源。", - "s3": "將 S3 儲存貯體中的文件同步到來源。", - "reddit": "將符合搜尋條件的 Reddit 貼文同步到來源。", + "google_drive": "將文件、試算表和 PDF 同步到知識庫。", + "share_point": "將 SharePoint 網站和 OneDrive 中的檔案同步到知識庫。", + "confluence": "將 Confluence 空間和頁面同步到知識庫。", + "s3": "將 S3 儲存貯體中的文件同步到知識庫。", + "reddit": "將符合你搜尋條件的 Reddit 貼文同步到知識庫。", "brave": "使用 Brave Search API 搜尋網頁和圖片。", "telegram": "傳送訊息和圖片到 Telegram 聊天。", "ntfy": "透過 ntfy 伺服器傳送推播通知。", @@ -1159,7 +1159,7 @@ "accounts": "帳號", "connectedAs": "已以 {{account}} 連線", "connectAnother": "連線其他帳號", - "sources": "來自此連線的來源", + "sources": "來自此連線的知識", "tools": "來自此連線的工具", "noAccounts": "尚未連線帳號。", "failed": "無法載入此連線。", @@ -1268,17 +1268,22 @@ }, "createFailed": "無法新增連接器。請再試一次。", "capabilityFilter": { - "sync": "正在顯示將內容同步到來源的連接器。", + "sync": "正在顯示將內容同步到知識庫的連接器。", "tools": "正在顯示為代理提供工具的連接器。", "showAll": "顯示全部" + }, + "capabilityPlain": { + "sync": "同步到知識庫", + "read": "查詢資訊", + "write": "執行操作" } } }, "modals": { "uploadDoc": { - "label": "新增來源", + "label": "新增知識", "select": "選擇如何將文件上傳到 DocsGPT", - "selectSource": "新增來源", + "selectSource": "新增知識", "selectedFiles": "已選擇的檔案", "noFilesSelected": "未選擇檔案", "file": "從檔案", @@ -1293,7 +1298,7 @@ "filesRejected": "未新增(超過 25 MB 或不支援的類型):{{files}}", "uploadedFiles": "已上傳檔案", "cancel": "取消", - "train": "新增來源", + "train": "新增到知識庫", "create": "建立", "link": "連結", "urlLink": "URL 連結", @@ -1642,16 +1647,17 @@ }, "sources": { "title": "來源", - "text": "來源文字", + "text": "選擇知識", "link": "來源連結", "view_more": "查看更多 {{count}} 個來源", - "noSourcesAvailable": "沒有可用的來源", + "noSourcesAvailable": "還沒有知識", "selectedCount": "已選擇 {{count}} 個來源", "groupOwn": "我的來源", "groupTeam": "團隊共享", "connectMore": "連線更多", "fromConnector": "來自 {{name}}", - "fromConnectorTitle": "來自 {{name}}:{{title}}" + "fromConnectorTitle": "來自 {{name}}:{{title}}", + "knowledge": "知識庫" }, "attachments": { "attach": "附件", @@ -1875,7 +1881,7 @@ "placeholders": { "agentName": "代理名稱", "describeAgent": "描述您的代理", - "selectSources": "選擇來源", + "selectSources": "選擇知識", "chunksPerQuery": "每次查詢的區塊數", "selectType": "選擇類型", "selectTools": "選擇工具", @@ -1885,19 +1891,19 @@ "enterRequestLimit": "輸入請求限制" }, "sourcePopup": { - "title": "選擇來源", - "searchPlaceholder": "搜尋來源...", - "noOptionsMessage": "沒有可用的來源", + "title": "選擇知識", + "searchPlaceholder": "搜尋知識...", + "noOptionsMessage": "還沒有知識", "groupOwn": "我的來源", "groupTeam": "團隊共享", - "noSourceHint": "可選。未選擇來源時,代理僅根據模型和工具作答。" + "noSourceHint": "選填。沒有知識時,代理只用模型和它的工具回答。" }, "toolsPopup": { "title": "選擇工具", "searchPlaceholder": "搜尋工具...", "noOptionsMessage": "沒有可用的工具", "groupBuiltin": "內建", - "groupDefault": "預設", + "groupDefault": "內建", "groupCustom": "自訂", "groupConnection": "{{name}} · {{account}}" }, @@ -1919,7 +1925,7 @@ "defaultModel": "預設模型", "name": "名稱", "description": "描述", - "sources": "來源", + "sources": "知識庫", "avatar": "頭像" }, "advanced": { @@ -2297,7 +2303,7 @@ "outputVariable": "輸出變數", "outputVariablePlaceholder": "輸出的變數名稱", "streamToUser": "將輸出串流給使用者", - "sources": "來源", + "sources": "知識庫", "documents": "文件", "documentsHint": "從上傳或上游節點傳給此代理的文件。", "filePassing": "檔案傳遞", diff --git a/frontend/src/locale/zh.json b/frontend/src/locale/zh.json index b6865ab8..a6c82d8b 100644 --- a/frontend/src/locale/zh.json +++ b/frontend/src/locale/zh.json @@ -98,15 +98,15 @@ "sources": { "title": "在这里您可以管理所有可用的源文件以及您上传的文件。", "subtitle": "DocsGPT 可以搜索和引用的内容:上传的文件、网站、Wiki,以及从连接同步的内容。", - "label": "来源", + "label": "知识库", "name": "来源名称", "date": "向量日期", "type": "类型", "tokenUsage": "令牌使用", - "noData": "没有现有的来源", + "noData": "还没有知识", "searchPlaceholder": "搜索...", "addNew": "添加新文档", - "addSource": "添加来源", + "addSource": "添加知识", "addChunk": "添加块", "preLoaded": "预加载", "private": "私有", @@ -287,7 +287,7 @@ "chunks": "文本块", "noChunks": "未找到文本块", "noChunksAlt": "未找到文本块", - "goToSources": "前往来源", + "goToSources": "前往知识库", "uploadNew": "上传新文档", "noResults": "未找到结果", "fileName": "名称", @@ -1084,9 +1084,9 @@ }, "connectors": { "label": "连接器", - "subtitle": "将 DocsGPT 连接到团队使用的服务。一个连接可以把内容同步到来源,也可以为智能体提供工具。", + "subtitle": "将 DocsGPT 连接到团队使用的服务。一个连接可以把内容同步到知识库,也可以为智能体提供工具。", "search": "搜索连接器...", - "addCustom": "添加自定义连接器", + "addCustom": "添加自定义工具", "custom": { "custom_mcp": "MCP 服务器", "custom_openapi": "OpenAPI / REST" @@ -1095,8 +1095,8 @@ "categories": { "all": "全部", "connected": "已连接", - "files": "文件和文档", - "knowledge": "知识库", + "files": "文件与存储", + "knowledge": "文档与 Wiki", "dev": "开发者工具", "messaging": "消息", "database": "数据库", @@ -1130,11 +1130,11 @@ "custom": "自定义" }, "descriptions": { - "google_drive": "将文档、表格和 PDF 同步到来源。", - "share_point": "将 SharePoint 站点和 OneDrive 中的文件同步到来源。", - "confluence": "将 Confluence 空间和页面同步到来源。", - "s3": "将 S3 存储桶中的文档同步到来源。", - "reddit": "将符合搜索条件的 Reddit 帖子同步到来源。", + "google_drive": "将文档、表格和 PDF 同步到知识库。", + "share_point": "将 SharePoint 站点和 OneDrive 中的文件同步到知识库。", + "confluence": "将 Confluence 空间和页面同步到知识库。", + "s3": "将 S3 存储桶中的文档同步到知识库。", + "reddit": "将符合你搜索条件的 Reddit 帖子同步到知识库。", "brave": "使用 Brave Search API 搜索网页和图片。", "telegram": "向 Telegram 聊天发送消息和图片。", "ntfy": "通过 ntfy 服务器发送推送通知。", @@ -1159,7 +1159,7 @@ "accounts": "账号", "connectedAs": "已作为 {{account}} 连接", "connectAnother": "连接其他账号", - "sources": "来自此连接的来源", + "sources": "来自此连接的知识", "tools": "来自此连接的工具", "noAccounts": "尚未连接账号。", "failed": "无法加载此连接。", @@ -1268,17 +1268,22 @@ }, "createFailed": "无法添加连接器。请重试。", "capabilityFilter": { - "sync": "正在显示将内容同步到来源的连接器。", + "sync": "正在显示将内容同步到知识库的连接器。", "tools": "正在显示为智能体提供工具的连接器。", "showAll": "显示全部" + }, + "capabilityPlain": { + "sync": "同步到知识库", + "read": "查找信息", + "write": "执行操作" } } }, "modals": { "uploadDoc": { - "label": "添加来源", + "label": "添加知识", "select": "选择如何将文档上传到 DocsGPT", - "selectSource": "添加来源", + "selectSource": "添加知识", "selectedFiles": "已选择的文件", "noFilesSelected": "未选择文件", "file": "从设备上传", @@ -1293,7 +1298,7 @@ "filesRejected": "未添加(超过 25 MB 或不支持的类型):{{files}}", "uploadedFiles": "已上传文件", "cancel": "取消", - "train": "添加来源", + "train": "添加到知识库", "create": "创建", "link": "链接", "urlLink": "URL 链接", @@ -1642,16 +1647,17 @@ }, "sources": { "title": "来源", - "text": "来源文本", + "text": "选择知识", "link": "来源链接", "view_more": "还有{{count}}个来源", - "noSourcesAvailable": "没有可用的来源", + "noSourcesAvailable": "还没有知识", "selectedCount": "已选择 {{count}} 个来源", "groupOwn": "我的来源", "groupTeam": "团队共享", "connectMore": "连接更多", "fromConnector": "来自 {{name}}", - "fromConnectorTitle": "来自 {{name}}:{{title}}" + "fromConnectorTitle": "来自 {{name}}:{{title}}", + "knowledge": "知识库" }, "attachments": { "attach": "附件", @@ -1875,7 +1881,7 @@ "placeholders": { "agentName": "代理名称", "describeAgent": "描述您的代理", - "selectSources": "选择来源", + "selectSources": "选择知识", "chunksPerQuery": "每次查询的块数", "selectType": "选择类型", "selectTools": "选择工具", @@ -1885,19 +1891,19 @@ "enterRequestLimit": "输入请求限制" }, "sourcePopup": { - "title": "选择来源", - "searchPlaceholder": "搜索来源...", - "noOptionsMessage": "没有可用的来源", + "title": "选择知识", + "searchPlaceholder": "搜索知识...", + "noOptionsMessage": "还没有知识", "groupOwn": "我的来源", "groupTeam": "团队共享", - "noSourceHint": "可选。未选择来源时,智能体仅根据模型和工具作答。" + "noSourceHint": "可选。没有知识时,智能体只用模型和它的工具回答。" }, "toolsPopup": { "title": "选择工具", "searchPlaceholder": "搜索工具...", "noOptionsMessage": "没有可用的工具", "groupBuiltin": "内置", - "groupDefault": "默认", + "groupDefault": "内置", "groupCustom": "自定义", "groupConnection": "{{name}} · {{account}}" }, @@ -1919,7 +1925,7 @@ "defaultModel": "默认模型", "name": "名称", "description": "描述", - "sources": "来源", + "sources": "知识库", "avatar": "头像" }, "advanced": { @@ -2297,7 +2303,7 @@ "outputVariable": "输出变量", "outputVariablePlaceholder": "输出的变量名", "streamToUser": "将输出流式传输给用户", - "sources": "来源", + "sources": "知识库", "documents": "文档", "documentsHint": "从上传或上游节点传给此智能体的文档。", "filePassing": "文件传递", diff --git a/frontend/src/navigation/sections.ts b/frontend/src/navigation/sections.ts index b2eb6e66..06a54b90 100644 --- a/frontend/src/navigation/sections.ts +++ b/frontend/src/navigation/sections.ts @@ -114,7 +114,7 @@ export const SETTINGS_SECTION: Section = { items: [ { key: 'sources', - path: '/settings/sources', + path: '/settings/knowledge', labelKey: 'settings.sources.label', icon: Database, }, diff --git a/frontend/src/settings/Connectors.test.tsx b/frontend/src/settings/Connectors.test.tsx index b301be8a..c83e4369 100644 --- a/frontend/src/settings/Connectors.test.tsx +++ b/frontend/src/settings/Connectors.test.tsx @@ -168,8 +168,9 @@ describe('Connectors page', () => { 'settings.connectors.status.disabledByAdmin', ); expect(card('brave')!.disabled).toBe(true); - expect(card('custom_mcp')!.textContent).toContain( - 'settings.connectors.publisher.custom', + // No publisher jargon ("Preset", "Built in") on cards. + expect(card('custom_mcp')!.textContent).not.toContain( + 'settings.connectors.publisher', ); }); @@ -186,10 +187,10 @@ describe('Connectors page', () => { it('shows capability chips', async () => { await render(); expect(card('google_drive')!.textContent).toContain( - 'settings.connectors.capability.sync', + 'settings.connectors.capabilityPlain.sync', ); expect(card('telegram')!.textContent).toContain( - 'settings.connectors.capability.write', + 'settings.connectors.capabilityPlain.write', ); }); @@ -246,6 +247,75 @@ describe('Connectors page', () => { expect(pills).not.toContain('settings.connectors.categories.messaging'); }); + const ATLASSIAN = definition({ + key: 'mcp:atlassian', + name: 'Jira & Confluence', + description: 'Search and update Jira issues.', + category: 'dev', + auth_kind: 'mcp_oauth', + capabilities: ['read', 'write'], + publisher: 'preset', + part_of: 'confluence', + }); + + it('shows one Confluence card that also does what its MCP part does', async () => { + service.getCatalog.mockResolvedValue({ + success: true, + connectors: [...CATALOG, ATLASSIAN], + }); + await render(); + expect(card('mcp:atlassian')).toBeNull(); + const confluence = card('confluence')!; + expect(confluence.textContent).toContain( + 'settings.connectors.capabilityPlain.sync', + ); + expect(confluence.textContent).toContain( + 'settings.connectors.capabilityPlain.write', + ); + }); + + it("finds the merged card by its part's name", async () => { + service.getCatalog.mockResolvedValue({ + success: true, + connectors: [...CATALOG, ATLASSIAN], + }); + await render(); + const input = container.querySelector( + '#connector-search-input', + )!; + const setter = Object.getOwnPropertyDescriptor( + HTMLInputElement.prototype, + 'value', + )!.set!; + await act(async () => { + setter.call(input, 'jira'); + input.dispatchEvent(new Event('input', { bubbles: true })); + }); + expect(card('confluence')).not.toBeNull(); + }); + + it('shows the part on its own when its parent is not listed', async () => { + service.getCatalog.mockResolvedValue({ + success: true, + connectors: [...CATALOG.filter((c) => c.key !== 'confluence'), ATLASSIAN], + }); + await render(); + expect(card('mcp:atlassian')).not.toBeNull(); + }); + + it("opens the merged card's page with a section for its part", async () => { + service.getCatalog.mockResolvedValue({ + success: true, + connectors: [...CATALOG, ATLASSIAN], + }); + await render(); + await act(async () => card('confluence')!.click()); + expect(document.body.textContent).toContain('Jira & Confluence'); + expect(document.body.textContent).toContain( + 'settings.connectors.descriptions.mcp_atlassian', + ); + }); + it('shows a retry when the catalog fails to load', async () => { service.getCatalog.mockResolvedValue({ success: false }); await render(); diff --git a/frontend/src/settings/Connectors.tsx b/frontend/src/settings/Connectors.tsx index 1c402780..1a776fb3 100644 --- a/frontend/src/settings/Connectors.tsx +++ b/frontend/src/settings/Connectors.tsx @@ -90,6 +90,30 @@ export default function Connectors() { const custom = catalog.filter((c) => c.publisher === 'custom'); const openConnector = catalog.find((c) => c.key === openKey) ?? null; + // One service offered two ways (Confluence sync and the Jira & Confluence + // MCP actions) is one card. A part is shown on its own only when its + // parent is not listed (not set up, or turned off). + const partsOf = (key: string) => catalog.filter((c) => c.part_of === key); + const isShownUnderParent = (connector: ConnectorDefinition) => + !!connector.part_of && catalog.some((c) => c.key === connector.part_of); + const merged = (connector: ConnectorDefinition): ConnectorDefinition => { + const parts = partsOf(connector.key); + if (parts.length === 0) return connector; + const all = [connector, ...parts]; + const state = all.some((c) => c.state === 'reconnect') + ? 'reconnect' + : all.some((c) => c.state === 'connected') + ? 'connected' + : connector.state; + return { + ...connector, + capabilities: Array.from(new Set(all.flatMap((c) => c.capabilities))), + connection_count: all.reduce((n, c) => n + c.connection_count, 0), + connected_count: all.reduce((n, c) => n + c.connected_count, 0), + state, + }; + }; + // "Connect more" in the composer opens the connectors that can do what the // picker is for: sync content, or give tools. const capability = searchParams.get('capability'); @@ -101,7 +125,10 @@ export default function Connectors() { // Only categories that have something in them once the composer's // capability filter applies (hidden connectors can empty one too), so no // pill leads to an empty page. - const withCapability = catalog.filter((connector) => + const cards = catalog + .filter((connector) => !isShownUnderParent(connector)) + .map(merged); + const withCapability = cards.filter((connector) => capability === 'sync' ? connector.capabilities.includes('sync') : capability === 'tools' @@ -128,14 +155,21 @@ export default function Connectors() { .filter( (connector) => !query || - connectorName(t, connector).toLowerCase().includes(query) || - connectorDescription(t, connector).toLowerCase().includes(query), + [connector, ...partsOf(connector.key)].some( + (c) => + connectorName(t, c).toLowerCase().includes(query) || + connectorDescription(t, c).toLowerCase().includes(query), + ), ) .sort((a, b) => STATE_ORDER[a.state] - STATE_ORDER[b.state]); }, [withCapability, filter, search, t]); const open = (connector: ConnectorDefinition) => { - if (connector.state === 'available' || connector.state === 'custom') { + const hasParts = partsOf(connector.key).length > 0; + if ( + !hasParts && + (connector.state === 'available' || connector.state === 'custom') + ) { launch(connector); return; } @@ -283,6 +317,7 @@ export default function Connectors() { { closeDrawer(); diff --git a/frontend/src/settings/index.tsx b/frontend/src/settings/index.tsx index 589280ac..340547ed 100644 --- a/frontend/src/settings/index.tsx +++ b/frontend/src/settings/index.tsx @@ -76,8 +76,10 @@ export default function Settings() { } /> } /> + {/* Sources are called Knowledge now; old links keep working. */} + } /> ); } + +/** `/settings/sources` from before the rename, query string kept. */ +function SourcesRedirect() { + const { search, hash } = useLocation(); + return ( + + ); +} diff --git a/tests/connectors/test_catalog.py b/tests/connectors/test_catalog.py index 37e3b86e..78d73e6f 100644 --- a/tests/connectors/test_catalog.py +++ b/tests/connectors/test_catalog.py @@ -114,3 +114,13 @@ class TestPresets: def test_base_url(self): assert catalog.base_url("https://a.example.com:8443/x/y") == "https://a.example.com:8443" assert catalog.base_url("not a url") == "" + + +def test_atlassian_preset_is_part_of_confluence(): + """One Confluence card: syncing pages and the Jira/Confluence agent actions.""" + from docsgpt.connectors import catalog + + atlassian = catalog.get_definition("mcp:atlassian") + assert atlassian.part_of == "confluence" + assert atlassian.to_dict()["part_of"] == "confluence" + assert catalog.get_definition("confluence").to_dict()["part_of"] is None