mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-13 04:14:42 +00:00
Name accounts in the connect wizard and rename them in the drawer
The connect wizard asks for an optional account name (keys and sign-ins alike) and sets it once the account exists. In the connector drawer a named account shows its name with the account under it, and Rename in the account menu changes or clears the name.
This commit is contained in:
1 parent
bdcb88866a
commit
d633560d7a
14 files changed
+334
-17
No files matched your search
@@ -69,6 +69,9 @@ const connectorsService = {
|
||||
token,
|
||||
),
|
||||
),
|
||||
/** Name an account ("Alerts bot"); an empty name clears it. */
|
||||
renameConnection: async (id: string, name: string, token: string | null) =>
|
||||
json(await apiClient.patch(endpoints.USER.CONNECTION(id), { name }, token)),
|
||||
disconnect: async (id: string, token: string | null) =>
|
||||
json(
|
||||
await apiClient.post(endpoints.USER.CONNECTION_DISCONNECT(id), {}, token),
|
||||
|
||||
@@ -20,6 +20,7 @@ const service = vi.hoisted(() => ({
|
||||
listConnections: vi.fn(),
|
||||
setToolPermissions: vi.fn(),
|
||||
pickerToken: vi.fn(),
|
||||
renameConnection: vi.fn(),
|
||||
}));
|
||||
vi.mock('../api/services/connectorsService', () => ({ default: service }));
|
||||
|
||||
@@ -271,6 +272,60 @@ describe('ConnectWizard', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('names the account when the user gives it a name', async () => {
|
||||
service.createConnection.mockResolvedValue({
|
||||
success: true,
|
||||
connection: { id: 'conn-1' },
|
||||
});
|
||||
service.renameConnection.mockResolvedValue({ success: true });
|
||||
service.setup.mockResolvedValue({ success: true, tools: [], sources: [] });
|
||||
await render(base);
|
||||
await typeInto(
|
||||
document.body.querySelector<HTMLInputElement>('input[type="password"]')!,
|
||||
'123:abc',
|
||||
);
|
||||
await typeInto(
|
||||
document.body.querySelector<HTMLInputElement>('#connect-account-name')!,
|
||||
' Alerts bot ',
|
||||
);
|
||||
await click('settings.connectors.status.connect');
|
||||
expect(service.renameConnection).toHaveBeenCalledWith(
|
||||
'conn-1',
|
||||
'Alerts bot',
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
it('leaves an unnamed account alone', async () => {
|
||||
service.createConnection.mockResolvedValue({
|
||||
success: true,
|
||||
connection: { id: 'conn-1' },
|
||||
});
|
||||
service.setup.mockResolvedValue({ success: true, tools: [], sources: [] });
|
||||
await render(base);
|
||||
await typeInto(
|
||||
document.body.querySelector<HTMLInputElement>('input[type="password"]')!,
|
||||
'123:abc',
|
||||
);
|
||||
await click('settings.connectors.status.connect');
|
||||
expect(service.renameConnection).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('names a signed-in account after the sign-in', async () => {
|
||||
service.renameConnection.mockResolvedValue({ success: true });
|
||||
await render(drive);
|
||||
await typeInto(
|
||||
document.body.querySelector<HTMLInputElement>('#connect-account-name')!,
|
||||
'Work',
|
||||
);
|
||||
await click('settings.connectors.wizard.signIn');
|
||||
expect(service.renameConnection).toHaveBeenCalledWith(
|
||||
'conn-drive',
|
||||
'Work',
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
it('shows the default-key refusal in the form', async () => {
|
||||
service.createConnection.mockResolvedValue({
|
||||
success: false,
|
||||
|
||||
@@ -44,6 +44,7 @@ import {
|
||||
} from '../preferences/preferenceSlice';
|
||||
import type { AppDispatch } from '../store';
|
||||
import { formatCount } from '../utils/dateTimeUtils';
|
||||
import { ACCOUNT_NAME_MAX } from './accounts';
|
||||
import ConnectorIcon from './ConnectorIcon';
|
||||
import CredentialForm, { credentialsComplete } from './CredentialForm';
|
||||
import { loadConnectors, selectConnections } from './connectorsSlice';
|
||||
@@ -107,6 +108,7 @@ export default function ConnectWizard({
|
||||
initialConnectionId,
|
||||
);
|
||||
const [credentials, setCredentials] = useState<Record<string, string>>({});
|
||||
const [accountName, setAccountName] = useState('');
|
||||
const [setupValues, setSetupValues] = useState<Record<string, string>>({});
|
||||
const [pending, setPending] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
@@ -156,8 +158,22 @@ export default function ConnectWizard({
|
||||
|
||||
const refresh = () => dispatch(loadConnectors({ token }));
|
||||
|
||||
// A name tells two accounts of one service apart ("Alerts bot"). It is
|
||||
// set once the account exists, so it works the same for keys and sign-ins.
|
||||
const canName =
|
||||
mode === 'connect' &&
|
||||
(connector.auth_kind === 'api_key' || connector.auth_kind === 'oauth');
|
||||
|
||||
const afterSignIn = async (id: string) => {
|
||||
setConnectionId(id);
|
||||
const name = accountName.trim();
|
||||
if (canName && name) {
|
||||
try {
|
||||
await connectorsService.renameConnection(id, name, token);
|
||||
} catch {
|
||||
// The account works without a name; it can be named in the drawer.
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
if (mode === 'reconnect') {
|
||||
setStep('done');
|
||||
@@ -495,6 +511,20 @@ export default function ConnectWizard({
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{canName && (
|
||||
<FormField
|
||||
label={t('settings.connectors.wizard.accountName')}
|
||||
hint={t('settings.connectors.wizard.accountNameHint')}
|
||||
>
|
||||
<Input
|
||||
id="connect-account-name"
|
||||
autoComplete="off"
|
||||
maxLength={ACCOUNT_NAME_MAX}
|
||||
value={accountName}
|
||||
onChange={(e) => setAccountName(e.target.value)}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ const connectors = vi.hoisted(() => ({
|
||||
getCatalog: vi.fn(async () => ({ success: true, connectors: [] })),
|
||||
listConnections: vi.fn(async () => ({ success: true, connections: [] })),
|
||||
setup: vi.fn(),
|
||||
renameConnection: vi.fn(),
|
||||
}));
|
||||
vi.mock('../api/services/connectorsService', () => ({ default: connectors }));
|
||||
|
||||
@@ -209,6 +210,58 @@ describe('ConnectionDrawer', () => {
|
||||
).not.toBeNull();
|
||||
});
|
||||
|
||||
const openAccountMenu = async () => {
|
||||
const trigger = document.body.querySelector<HTMLButtonElement>(
|
||||
'[aria-label="settings.connectors.detail.accountMenu"]',
|
||||
)!;
|
||||
await act(async () => {
|
||||
trigger.dispatchEvent(
|
||||
new PointerEvent('pointerdown', { bubbles: true, button: 0 }),
|
||||
);
|
||||
trigger.click();
|
||||
});
|
||||
};
|
||||
|
||||
it('shows the name an account was given, with the account under it', async () => {
|
||||
connectors.getConnection.mockResolvedValue({
|
||||
success: true,
|
||||
connection: { ...DETAIL, account_name: 'Work' },
|
||||
});
|
||||
await render();
|
||||
const text = document.body.textContent ?? '';
|
||||
expect(text).toContain('Work');
|
||||
expect(text).toContain('settings.connectors.detail.connectedAs');
|
||||
});
|
||||
|
||||
it('renames an account from its menu', async () => {
|
||||
connectors.renameConnection.mockResolvedValue({
|
||||
success: true,
|
||||
connection: { ...DETAIL, account_name: 'Work' },
|
||||
});
|
||||
await render();
|
||||
await openAccountMenu();
|
||||
const item = Array.from(
|
||||
document.body.querySelectorAll<HTMLElement>('[role="menuitem"]'),
|
||||
).find((el) => el.textContent === 'settings.connectors.detail.rename')!;
|
||||
await act(async () => item.click());
|
||||
const input =
|
||||
document.body.querySelector<HTMLInputElement>('#rename-account')!;
|
||||
const setter = Object.getOwnPropertyDescriptor(
|
||||
HTMLInputElement.prototype,
|
||||
'value',
|
||||
)!.set!;
|
||||
await act(async () => {
|
||||
setter.call(input, 'Work');
|
||||
input.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
await act(async () => button('settings.connectors.rename.save').click());
|
||||
expect(connectors.renameConnection).toHaveBeenCalledWith(
|
||||
'conn-1',
|
||||
'Work',
|
||||
null,
|
||||
);
|
||||
});
|
||||
|
||||
it('labels synced content as Knowledge from this connection', async () => {
|
||||
await render();
|
||||
expect(document.body.textContent).toContain(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
CircleAlert,
|
||||
Pencil,
|
||||
Plus,
|
||||
RefreshCw,
|
||||
RotateCw,
|
||||
@@ -20,6 +21,7 @@ import { Card } from '../components/ui/card';
|
||||
import { ActionMenu, type MenuOption } from '../components/ui/dropdown-menu';
|
||||
import { EmptyState } from '../components/ui/empty-state';
|
||||
import { FormField } from '../components/ui/form-field';
|
||||
import { Input } from '../components/ui/input';
|
||||
import { ListRow, ListRows } from '../components/ui/list-row';
|
||||
import { LoadingState } from '../components/ui/loading-state';
|
||||
import { Modal, ModalActions } from '../components/ui/modal';
|
||||
@@ -37,6 +39,7 @@ import { showActionToast } from '../notifications/actionToastSlice';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import type { AppDispatch } from '../store';
|
||||
import { formatCount, formatDateTime } from '../utils/dateTimeUtils';
|
||||
import { ACCOUNT_NAME_MAX } from './accounts';
|
||||
import { CapabilityBadges } from './ConnectorCard';
|
||||
import ConnectorIcon from './ConnectorIcon';
|
||||
import ConnectorSetupNotice from './ConnectorSetupNotice';
|
||||
@@ -211,6 +214,82 @@ function RemoveConnectionModal({
|
||||
);
|
||||
}
|
||||
|
||||
/** Names an account ("Alerts bot"), so two accounts of a service read apart. */
|
||||
function RenameAccountModal({
|
||||
detail,
|
||||
onClose,
|
||||
onRenamed,
|
||||
}: {
|
||||
detail: ConnectionDetail;
|
||||
onClose: () => void;
|
||||
onRenamed: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const token = useSelector(selectToken);
|
||||
const [name, setName] = useState(detail.account_name ?? '');
|
||||
const [pending, setPending] = useState(false);
|
||||
const [failed, setFailed] = useState(false);
|
||||
|
||||
const save = () => {
|
||||
setPending(true);
|
||||
setFailed(false);
|
||||
connectorsService
|
||||
.renameConnection(detail.id, name.trim(), token)
|
||||
.then((data) => {
|
||||
if (!data?.success) throw new Error('rename failed');
|
||||
onRenamed();
|
||||
})
|
||||
.catch(() => setFailed(true))
|
||||
.finally(() => setPending(false));
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open
|
||||
size="sm"
|
||||
onOpenChange={(open) => !open && onClose()}
|
||||
title={t('settings.connectors.rename.title')}
|
||||
description={t('settings.connectors.rename.description')}
|
||||
footer={
|
||||
<ModalActions
|
||||
cancelLabel={t('cancel')}
|
||||
onCancel={onClose}
|
||||
submitLabel={t('settings.connectors.rename.save')}
|
||||
onSubmit={save}
|
||||
pending={pending}
|
||||
disabled={name.trim() === (detail.account_name ?? '')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className="flex flex-col gap-5">
|
||||
{failed && (
|
||||
<Alert variant="destructive">
|
||||
<CircleAlert />
|
||||
<AlertDescription>
|
||||
{t('settings.connectors.rename.failed')}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<Input
|
||||
id="rename-account"
|
||||
label={t('settings.connectors.rename.label')}
|
||||
autoComplete="off"
|
||||
maxLength={ACCOUNT_NAME_MAX}
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (
|
||||
e.key === 'Enter' &&
|
||||
name.trim() !== (detail.account_name ?? '')
|
||||
)
|
||||
save();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
/** A connection tool's on/off switch: the one place it is turned on or off. */
|
||||
function ToolSwitch({
|
||||
tool,
|
||||
@@ -244,6 +323,7 @@ function AccountSection({
|
||||
onReconnect,
|
||||
onDisconnect,
|
||||
onRemove,
|
||||
onRename,
|
||||
onSyncMore,
|
||||
onRefreshTools,
|
||||
onToggleTool,
|
||||
@@ -255,6 +335,7 @@ function AccountSection({
|
||||
onReconnect: (detail: ConnectionDetail) => void;
|
||||
onDisconnect: (detail: ConnectionDetail) => void;
|
||||
onRemove: (detail: ConnectionDetail) => void;
|
||||
onRename: (detail: ConnectionDetail) => void;
|
||||
onSyncMore: (detail: ConnectionDetail) => void;
|
||||
onRefreshTools: (detail: ConnectionDetail) => Promise<void>;
|
||||
/** Turns a tool of this connection on or off for agents and chat. */
|
||||
@@ -276,7 +357,13 @@ function AccountSection({
|
||||
detail.status === 'connected';
|
||||
const canSync = connector.setup.sync !== 'off' && !!connector.sync_ingestor;
|
||||
const isMcp = detail.tools.some((tool) => tool.name === 'mcp_tool');
|
||||
const menu: MenuOption[] = [];
|
||||
const menu: MenuOption[] = [
|
||||
{
|
||||
icon: Pencil,
|
||||
label: t('settings.connectors.detail.rename'),
|
||||
onClick: () => onRename(detail),
|
||||
},
|
||||
];
|
||||
if (detail.status !== 'disconnected') {
|
||||
menu.push({
|
||||
icon: Unplug,
|
||||
@@ -303,9 +390,11 @@ function AccountSection({
|
||||
<Card variant="subtle" padding="none">
|
||||
<ListRows>
|
||||
<ListRow
|
||||
title={accountTitle(detail)}
|
||||
title={detail.account_name || accountTitle(detail)}
|
||||
description={
|
||||
!broken && detail.last_error ? (
|
||||
detail.account_name ? (
|
||||
accountTitle(detail)
|
||||
) : !broken && detail.last_error ? (
|
||||
<span title={detail.last_error}>{detail.last_error}</span>
|
||||
) : undefined
|
||||
}
|
||||
@@ -532,6 +621,7 @@ export default function ConnectionDrawer({
|
||||
null,
|
||||
);
|
||||
const [toRemove, setToRemove] = useState<ConnectionDetail | null>(null);
|
||||
const [toRename, setToRename] = useState<ConnectionDetail | null>(null);
|
||||
|
||||
const keys = [connector?.key, ...parts.map((part) => part.key)];
|
||||
const accountIds = connections
|
||||
@@ -807,6 +897,7 @@ export default function ConnectionDrawer({
|
||||
onReconnect={reconnect}
|
||||
onDisconnect={setToDisconnect}
|
||||
onRemove={setToRemove}
|
||||
onRename={setToRename}
|
||||
onSyncMore={(d) =>
|
||||
onConnect(connector, {
|
||||
mode: 'sync',
|
||||
@@ -856,6 +947,7 @@ export default function ConnectionDrawer({
|
||||
onReconnect={reconnect}
|
||||
onDisconnect={setToDisconnect}
|
||||
onRemove={setToRemove}
|
||||
onRename={setToRename}
|
||||
onSyncMore={(d) =>
|
||||
onConnect(part, { mode: 'sync', connectionId: d.id })
|
||||
}
|
||||
@@ -886,6 +978,16 @@ export default function ConnectionDrawer({
|
||||
submitLabel={t('settings.connectors.detail.disconnect')}
|
||||
variant="destructive"
|
||||
/>
|
||||
{toRename && (
|
||||
<RenameAccountModal
|
||||
detail={toRename}
|
||||
onClose={() => setToRename(null)}
|
||||
onRenamed={() => {
|
||||
setToRename(null);
|
||||
refresh();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{toRemove && (
|
||||
<RemoveConnectionModal
|
||||
detail={toRemove}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/** The longest account name the server keeps (`ACCOUNT_NAME_MAX`). */
|
||||
export const ACCOUNT_NAME_MAX = 80;
|
||||
@@ -82,6 +82,8 @@ export type Connection = {
|
||||
display_name: string | null;
|
||||
icon: string;
|
||||
account_label: string;
|
||||
/** What the owner calls the account; `account_label` stays its identity. */
|
||||
account_name?: string | null;
|
||||
auth_kind: ConnectorAuthKind | null;
|
||||
status: ConnectionStatus;
|
||||
server_url: string | null;
|
||||
|
||||
@@ -1201,7 +1201,8 @@
|
||||
"broken": "Diese Verbindung funktioniert nicht mehr. Verbinde neu, um es erneut zu versuchen.",
|
||||
"addTools": "Werkzeuge hinzufügen",
|
||||
"noTools": "Noch keine Werkzeuge aus dieser Verbindung.",
|
||||
"addToolsFailed": "Die Werkzeuge konnten nicht hinzugefügt werden. Versuche es erneut."
|
||||
"addToolsFailed": "Die Werkzeuge konnten nicht hinzugefügt werden. Versuche es erneut.",
|
||||
"rename": "Umbenennen"
|
||||
},
|
||||
"permission": {
|
||||
"always": "Erlauben",
|
||||
@@ -1281,7 +1282,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "Agenten können Dinge nachschlagen. Sie können nichts ändern.",
|
||||
"readWrite": "Agenten können Dinge nachschlagen und ändern. Änderungen brauchen deine Freigabe."
|
||||
}
|
||||
},
|
||||
"accountName": "Konto benennen",
|
||||
"accountNameHint": "Optional. Unterscheidet deine Konten, für dich und die KI, z. B. Alarm-Bot."
|
||||
},
|
||||
"remove": {
|
||||
"title": "{{name}} entfernen?",
|
||||
@@ -1362,6 +1365,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "Optional. Nachrichten gehen an diesen Chat, und die KI kann keinen anderen wählen. Füge den Bot zum Chat hinzu, sende ihm eine Nachricht und finde die ID des Chats unter https://api.telegram.org/bot<token>/getUpdates."
|
||||
},
|
||||
"rename": {
|
||||
"title": "Konto umbenennen",
|
||||
"description": "Der Name unterscheidet dieses Konto von deinen anderen Konten desselben Dienstes, für dich und die KI. Lass ihn leer, um das Konto selbst anzuzeigen.",
|
||||
"label": "Kontoname",
|
||||
"save": "Speichern",
|
||||
"failed": "Das Konto konnte nicht umbenannt werden. Versuche es erneut."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1207,7 +1207,8 @@
|
||||
"broken": "This connection stopped working. Reconnect to try again.",
|
||||
"addTools": "Add tools",
|
||||
"noTools": "No tools from this connection yet.",
|
||||
"addToolsFailed": "Could not add the tools. Try again."
|
||||
"addToolsFailed": "Could not add the tools. Try again.",
|
||||
"rename": "Rename"
|
||||
},
|
||||
"permission": {
|
||||
"always": "Allow",
|
||||
@@ -1287,7 +1288,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "Agents can look things up. They cannot change anything.",
|
||||
"readWrite": "Agents can look things up and make changes. Changes need your approval."
|
||||
}
|
||||
},
|
||||
"accountName": "Name this account",
|
||||
"accountNameHint": "Optional. Tells your accounts apart, for you and the AI, e.g. Alerts bot."
|
||||
},
|
||||
"remove": {
|
||||
"title": "Remove {{name}}?",
|
||||
@@ -1368,6 +1371,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "Optional. Messages go to this chat, and the AI cannot pick another. Add the bot to the chat, send it a message, then find the chat's id in https://api.telegram.org/bot<token>/getUpdates."
|
||||
},
|
||||
"rename": {
|
||||
"title": "Rename account",
|
||||
"description": "The name tells this account apart from your other accounts of the same service, for you and the AI. Leave it empty to show the account itself.",
|
||||
"label": "Account name",
|
||||
"save": "Save",
|
||||
"failed": "Could not rename the account. Try again."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1201,7 +1201,8 @@
|
||||
"broken": "Esta conexión dejó de funcionar. Reconecta para intentarlo de nuevo.",
|
||||
"addTools": "Añadir herramientas",
|
||||
"noTools": "Todavía no hay herramientas de esta conexión.",
|
||||
"addToolsFailed": "No se pudieron añadir las herramientas. Inténtalo de nuevo."
|
||||
"addToolsFailed": "No se pudieron añadir las herramientas. Inténtalo de nuevo.",
|
||||
"rename": "Cambiar nombre"
|
||||
},
|
||||
"permission": {
|
||||
"always": "Permitir",
|
||||
@@ -1281,7 +1282,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "Los agentes pueden consultar información. No pueden cambiar nada.",
|
||||
"readWrite": "Los agentes pueden consultar información y hacer cambios. Los cambios necesitan tu aprobación."
|
||||
}
|
||||
},
|
||||
"accountName": "Nombre de esta cuenta",
|
||||
"accountNameHint": "Opcional. Distingue tus cuentas, para ti y para la IA; por ejemplo, Bot de alertas."
|
||||
},
|
||||
"remove": {
|
||||
"title": "¿Eliminar {{name}}?",
|
||||
@@ -1362,6 +1365,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "Opcional. Los mensajes van a este chat y la IA no puede elegir otro. Añade el bot al chat, envíale un mensaje y busca el id del chat en https://api.telegram.org/bot<token>/getUpdates."
|
||||
},
|
||||
"rename": {
|
||||
"title": "Cambiar el nombre de la cuenta",
|
||||
"description": "El nombre distingue esta cuenta de tus otras cuentas del mismo servicio, para ti y para la IA. Déjalo vacío para mostrar la cuenta en sí.",
|
||||
"label": "Nombre de la cuenta",
|
||||
"save": "Guardar",
|
||||
"failed": "No se pudo cambiar el nombre de la cuenta. Inténtalo de nuevo."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1192,7 +1192,8 @@
|
||||
"broken": "この接続は動作しなくなりました。再接続してもう一度お試しください。",
|
||||
"addTools": "ツールを追加",
|
||||
"noTools": "この接続のツールはまだありません。",
|
||||
"addToolsFailed": "ツールを追加できませんでした。もう一度お試しください。"
|
||||
"addToolsFailed": "ツールを追加できませんでした。もう一度お試しください。",
|
||||
"rename": "名前を変更"
|
||||
},
|
||||
"permission": {
|
||||
"always": "許可",
|
||||
@@ -1267,7 +1268,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "エージェントは情報を参照できます。変更はできません。",
|
||||
"readWrite": "エージェントは情報の参照と変更ができます。変更にはあなたの承認が必要です。"
|
||||
}
|
||||
},
|
||||
"accountName": "このアカウントの名前",
|
||||
"accountNameHint": "任意。あなたと AI がアカウントを区別できるようにします。例: 通知ボット"
|
||||
},
|
||||
"remove": {
|
||||
"title": "{{name}} を削除しますか?",
|
||||
@@ -1343,6 +1346,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "任意。メッセージはこのチャットに送られ、AI は別のチャットを選べません。ボットをチャットに追加してメッセージを送り、https://api.telegram.org/bot<token>/getUpdates でチャットの id を確認してください。"
|
||||
},
|
||||
"rename": {
|
||||
"title": "アカウント名を変更",
|
||||
"description": "この名前で、同じサービスの他のアカウントと区別できます(あなたと AI の両方)。空欄にするとアカウントそのものが表示されます。",
|
||||
"label": "アカウント名",
|
||||
"save": "保存",
|
||||
"failed": "アカウント名を変更できませんでした。もう一度お試しください。"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1257,7 +1257,8 @@
|
||||
"broken": "Это подключение перестало работать. Переподключите, чтобы попробовать снова.",
|
||||
"addTools": "Добавить инструменты",
|
||||
"noTools": "У этого подключения пока нет инструментов.",
|
||||
"addToolsFailed": "Не удалось добавить инструменты. Попробуйте ещё раз."
|
||||
"addToolsFailed": "Не удалось добавить инструменты. Попробуйте ещё раз.",
|
||||
"rename": "Переименовать"
|
||||
},
|
||||
"permission": {
|
||||
"always": "Разрешать",
|
||||
@@ -1347,7 +1348,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "Агенты могут находить информацию. Изменять ничего не могут.",
|
||||
"readWrite": "Агенты могут находить информацию и вносить изменения. Изменения требуют вашего одобрения."
|
||||
}
|
||||
},
|
||||
"accountName": "Название аккаунта",
|
||||
"accountNameHint": "Необязательно. Помогает вам и ИИ различать аккаунты, например «Бот оповещений»."
|
||||
},
|
||||
"remove": {
|
||||
"title": "Удалить {{name}}?",
|
||||
@@ -1438,6 +1441,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "Необязательно. Сообщения уходят в этот чат, и ИИ не может выбрать другой. Добавьте бота в чат, отправьте ему сообщение и найдите id чата на https://api.telegram.org/bot<token>/getUpdates."
|
||||
},
|
||||
"rename": {
|
||||
"title": "Переименовать аккаунт",
|
||||
"description": "Название отличает этот аккаунт от других ваших аккаунтов того же сервиса, для вас и для ИИ. Оставьте поле пустым, чтобы показывать сам аккаунт.",
|
||||
"label": "Название аккаунта",
|
||||
"save": "Сохранить",
|
||||
"failed": "Не удалось переименовать аккаунт. Попробуйте ещё раз."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1192,7 +1192,8 @@
|
||||
"broken": "此連線已停止運作。重新連線以再試一次。",
|
||||
"addTools": "新增工具",
|
||||
"noTools": "此連線還沒有工具。",
|
||||
"addToolsFailed": "無法新增工具。請再試一次。"
|
||||
"addToolsFailed": "無法新增工具。請再試一次。",
|
||||
"rename": "重新命名"
|
||||
},
|
||||
"permission": {
|
||||
"always": "允許",
|
||||
@@ -1267,7 +1268,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "代理可以查詢資訊,但無法做任何變更。",
|
||||
"readWrite": "代理可以查詢資訊並進行變更。變更需要你的核准。"
|
||||
}
|
||||
},
|
||||
"accountName": "為此帳戶命名",
|
||||
"accountNameHint": "選填。讓你和 AI 區分你的帳戶,例如「警示機器人」。"
|
||||
},
|
||||
"remove": {
|
||||
"title": "要移除 {{name}} 嗎?",
|
||||
@@ -1343,6 +1346,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "選填。訊息會傳送到此聊天,AI 無法選擇其他聊天。將機器人加入聊天並傳送一則訊息給它,然後在 https://api.telegram.org/bot<token>/getUpdates 中找到該聊天的 id。"
|
||||
},
|
||||
"rename": {
|
||||
"title": "重新命名帳戶",
|
||||
"description": "此名稱可讓你和 AI 將此帳戶與同一服務的其他帳戶區分開來。留空則顯示帳戶本身。",
|
||||
"label": "帳戶名稱",
|
||||
"save": "儲存",
|
||||
"failed": "無法重新命名帳戶。請再試一次。"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1192,7 +1192,8 @@
|
||||
"broken": "此连接已停止工作。重新连接以再试一次。",
|
||||
"addTools": "添加工具",
|
||||
"noTools": "此连接还没有工具。",
|
||||
"addToolsFailed": "无法添加工具。请重试。"
|
||||
"addToolsFailed": "无法添加工具。请重试。",
|
||||
"rename": "重命名"
|
||||
},
|
||||
"permission": {
|
||||
"always": "允许",
|
||||
@@ -1267,7 +1268,9 @@
|
||||
"addToolsDescription": {
|
||||
"read": "智能体可以查询信息,但不能做任何更改。",
|
||||
"readWrite": "智能体可以查询信息并进行更改。更改需要你的批准。"
|
||||
}
|
||||
},
|
||||
"accountName": "为此账户命名",
|
||||
"accountNameHint": "可选。让你和 AI 区分你的账户,例如“告警机器人”。"
|
||||
},
|
||||
"remove": {
|
||||
"title": "移除 {{name}}?",
|
||||
@@ -1343,6 +1346,13 @@
|
||||
},
|
||||
"fieldHints": {
|
||||
"telegram_chat_id": "可选。消息会发送到此聊天,AI 无法选择其他聊天。将机器人加入聊天并给它发一条消息,然后在 https://api.telegram.org/bot<token>/getUpdates 中找到该聊天的 id。"
|
||||
},
|
||||
"rename": {
|
||||
"title": "重命名账户",
|
||||
"description": "此名称可让你和 AI 将此账户与同一服务的其他账户区分开。留空则显示账户本身。",
|
||||
"label": "账户名称",
|
||||
"save": "保存",
|
||||
"failed": "无法重命名账户。请重试。"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user