refactor: restructure project for multi-agent extensibility
- Migrate source to packages/client and packages/server directories - Namespace all Hermes-specific code under hermes/ subdirectories (api/hermes/, components/hermes/, views/hermes/, stores/hermes/) - Add hermes.* route names and /hermes/* path prefixes - Upgrade @koa/router to v15, adapt path-to-regexp v8 syntax - Fix proxy path rewriting: /api/hermes/v1/* → /v1/*, /api/hermes/* → /api/* - Fix frontend API paths to match backend /api/hermes/* routes - Fix WebSocket terminal path to /api/hermes/terminal - Add proxyMiddleware for reliable unmatched route proxying - Add profiles route module and hermes-cli profile commands - Update CLAUDE.md development guide with new architecture - Add Chinese README (README_zh.md) - Add Web Terminal feature to README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,385 @@
|
||||
export default {
|
||||
// Login
|
||||
login: {
|
||||
title: 'Hermes Web UI',
|
||||
description: 'Enter your access token to continue. Find it in the server startup logs.',
|
||||
placeholder: 'Access token',
|
||||
submit: 'Login',
|
||||
tokenRequired: 'Please enter your access token',
|
||||
invalidToken: 'Invalid token',
|
||||
connectionFailed: 'Cannot connect to server',
|
||||
},
|
||||
|
||||
// Common
|
||||
common: {
|
||||
loading: 'Loading...',
|
||||
cancel: 'Cancel',
|
||||
delete: 'Delete',
|
||||
edit: 'Edit',
|
||||
save: 'Save',
|
||||
saved: 'Saved',
|
||||
update: 'Update',
|
||||
create: 'Create',
|
||||
saveFailed: 'Save failed',
|
||||
ok: 'OK',
|
||||
copied: 'Copied',
|
||||
copy: 'Copy',
|
||||
noData: 'No data',
|
||||
fetch: 'Fetch',
|
||||
add: 'Add',
|
||||
enable: 'Enable',
|
||||
disable: 'Disable',
|
||||
configured: 'Configured',
|
||||
notConfigured: 'Not configured',
|
||||
},
|
||||
|
||||
// Sidebar
|
||||
sidebar: {
|
||||
chat: 'Chat',
|
||||
jobs: 'Jobs',
|
||||
models: 'Models',
|
||||
skills: 'Skills',
|
||||
memory: 'Memory',
|
||||
logs: 'Logs',
|
||||
usage: 'Usage',
|
||||
channels: 'Channels',
|
||||
terminal: 'Terminal',
|
||||
settings: 'Settings',
|
||||
connected: 'Connected',
|
||||
disconnected: 'Disconnected',
|
||||
},
|
||||
|
||||
// Chat
|
||||
chat: {
|
||||
emptyState: 'Start a conversation with Hermes Agent',
|
||||
inputPlaceholder: 'Type a message... (Enter to send, Shift+Enter for new line)',
|
||||
attachFiles: 'Attach files',
|
||||
stop: 'Stop',
|
||||
send: 'Send',
|
||||
contextUsed: 'Context used:',
|
||||
sessions: 'Sessions',
|
||||
noSessions: 'No sessions',
|
||||
newChat: 'New Chat',
|
||||
deleteSession: 'Delete this session?',
|
||||
sessionDeleted: 'Session deleted',
|
||||
rename: 'Rename',
|
||||
copySessionId: 'Copy Session ID',
|
||||
renamed: 'Renamed',
|
||||
renameFailed: 'Rename failed',
|
||||
renameSession: 'Rename Session',
|
||||
enterNewTitle: 'Enter new title',
|
||||
other: 'Other',
|
||||
runFailed: 'Run failed',
|
||||
error: 'Error',
|
||||
tool: 'Tool',
|
||||
arguments: 'Arguments',
|
||||
result: 'Result',
|
||||
truncated: '... (truncated)',
|
||||
},
|
||||
|
||||
// Jobs
|
||||
jobs: {
|
||||
title: 'Scheduled Jobs',
|
||||
createJob: 'Create Job',
|
||||
editJob: 'Edit Job',
|
||||
noJobs: 'No scheduled jobs yet. Create one to get started.',
|
||||
name: 'Name',
|
||||
namePlaceholder: 'Job name',
|
||||
schedule: 'Schedule (Cron Expression)',
|
||||
schedulePlaceholder: 'e.g. 0 9 * * *',
|
||||
quickPresets: 'Quick Presets',
|
||||
selectPreset: 'Select a preset...',
|
||||
presetEveryMinute: 'Every minute',
|
||||
presetEvery5Min: 'Every 5 minutes',
|
||||
presetEveryHour: 'Every hour',
|
||||
presetEveryDay: 'Every day at 00:00',
|
||||
presetEveryDay9: 'Every day at 09:00',
|
||||
presetEveryMonday: 'Every Monday at 09:00',
|
||||
presetEveryMonth: 'Every month 1st at 09:00',
|
||||
prompt: 'Prompt',
|
||||
promptPlaceholder: 'The prompt to execute',
|
||||
deliverTarget: 'Deliver Target',
|
||||
origin: 'Origin',
|
||||
local: 'Local',
|
||||
repeatCount: 'Repeat Count (optional)',
|
||||
repeatPlaceholder: 'Leave empty for infinite',
|
||||
jobCreated: 'Job created',
|
||||
jobUpdated: 'Job updated',
|
||||
nameRequired: 'Name is required',
|
||||
scheduleRequired: 'Schedule is required',
|
||||
loadFailed: 'Failed to load job',
|
||||
jobPaused: 'Job paused',
|
||||
jobResumed: 'Job resumed',
|
||||
jobTriggered: 'Job triggered',
|
||||
jobDeleted: 'Job deleted',
|
||||
status: {
|
||||
running: 'Running',
|
||||
paused: 'Paused',
|
||||
disabled: 'Disabled',
|
||||
scheduled: 'Scheduled',
|
||||
},
|
||||
info: {
|
||||
schedule: 'Schedule',
|
||||
lastRun: 'Last Run',
|
||||
nextRun: 'Next Run',
|
||||
deliver: 'Deliver',
|
||||
repeat: 'Repeat',
|
||||
},
|
||||
action: {
|
||||
pause: 'Pause',
|
||||
pauseJob: 'Pause job',
|
||||
resume: 'Resume',
|
||||
resumeJob: 'Resume job',
|
||||
runNow: 'Run Now',
|
||||
triggerImmediately: 'Trigger immediately',
|
||||
},
|
||||
},
|
||||
|
||||
// Skills
|
||||
skills: {
|
||||
title: 'Skills',
|
||||
searchPlaceholder: 'Search skills...',
|
||||
noMatch: 'No skills match your search',
|
||||
noSkills: 'No skills found',
|
||||
backTo: 'Back to',
|
||||
attachedFiles: 'Attached Files',
|
||||
loadFailed: 'Failed to load skill',
|
||||
fileLoadFailed: 'Failed to load file',
|
||||
toggleFailed: 'Failed to toggle skill',
|
||||
},
|
||||
|
||||
// Memory
|
||||
memory: {
|
||||
title: 'Memory',
|
||||
refresh: 'Refresh',
|
||||
loadFailed: 'Failed to load memory',
|
||||
myNotes: 'My Notes',
|
||||
noNotes: 'No notes yet.',
|
||||
notesPlaceholder: 'Write your notes...',
|
||||
userProfile: 'User Profile',
|
||||
noProfile: 'No profile yet.',
|
||||
profilePlaceholder: 'Write your profile...',
|
||||
},
|
||||
|
||||
// Models
|
||||
models: {
|
||||
title: 'Models',
|
||||
addProvider: 'Add Provider',
|
||||
providerType: 'Provider Type',
|
||||
preset: 'Preset',
|
||||
custom: 'Custom',
|
||||
selectProvider: 'Select Provider',
|
||||
chooseProvider: 'Choose a provider...',
|
||||
name: 'Name',
|
||||
autoGeneratedName: 'Auto-generated from Base URL',
|
||||
baseUrl: 'Base URL',
|
||||
baseUrlPlaceholder: 'e.g. https://api.example.com/v1',
|
||||
apiKey: 'API Key',
|
||||
apiKeyPlaceholder: 'sk-...',
|
||||
defaultModel: 'Default Model',
|
||||
selectModel: 'Select a model...',
|
||||
providerAdded: 'Provider added',
|
||||
providerDeleted: 'Provider deleted',
|
||||
deleteProvider: 'Delete Provider',
|
||||
deleteConfirm: 'Are you sure you want to delete "{name}"?',
|
||||
noProviders: 'No providers found. Add a custom provider to get started.',
|
||||
builtIn: 'Built-in',
|
||||
customType: 'Custom',
|
||||
provider: 'Provider',
|
||||
local: 'Local ({host})',
|
||||
selectProviderRequired: 'Please select a provider',
|
||||
baseUrlRequired: 'Base URL is required',
|
||||
apiKeyRequired: 'API Key is required',
|
||||
modelRequired: 'Default Model is required',
|
||||
enterBaseUrl: 'Please enter Base URL first',
|
||||
unexpectedFormat: 'Unexpected response format',
|
||||
foundModels: 'Found {count} models',
|
||||
fetchFailed: 'Failed to fetch models',
|
||||
},
|
||||
|
||||
// Logs
|
||||
logs: {
|
||||
title: 'Logs',
|
||||
all: 'All',
|
||||
searchPlaceholder: 'Search...',
|
||||
refresh: 'Refresh',
|
||||
noEntries: 'No log entries',
|
||||
},
|
||||
|
||||
// Settings
|
||||
settings: {
|
||||
title: 'Settings',
|
||||
saved: 'Saved',
|
||||
saveFailed: 'Save failed',
|
||||
tabs: {
|
||||
display: 'Display',
|
||||
agent: 'Agent',
|
||||
memory: 'Memory',
|
||||
session: 'Session',
|
||||
privacy: 'Privacy',
|
||||
apiServer: 'API Server',
|
||||
},
|
||||
display: {
|
||||
streaming: 'Stream Responses',
|
||||
streamingHint: 'Show AI replies in real-time',
|
||||
compact: 'Compact Mode',
|
||||
compactHint: 'Reduce message spacing',
|
||||
showReasoning: 'Show Reasoning',
|
||||
showReasoningHint: 'Show model thinking process',
|
||||
showCost: 'Show Cost',
|
||||
showCostHint: 'Show token usage in replies',
|
||||
inlineDiffs: 'Inline Diffs',
|
||||
inlineDiffsHint: 'Show code changes inline',
|
||||
bellOnComplete: 'Completion Sound',
|
||||
bellOnCompleteHint: 'Play sound when AI finishes',
|
||||
busyInputMode: 'Busy Input Mode',
|
||||
busyInputModeHint: 'Allow input while AI is processing',
|
||||
},
|
||||
agent: {
|
||||
maxTurns: 'Max Turns',
|
||||
maxTurnsHint: 'Maximum interaction rounds per conversation',
|
||||
gatewayTimeout: 'Gateway Timeout',
|
||||
gatewayTimeoutHint: 'Request timeout in seconds',
|
||||
restartDrainTimeout: 'Restart Drain Timeout',
|
||||
restartDrainTimeoutHint: 'Drain timeout before restart in seconds',
|
||||
toolEnforcement: 'Tool Enforcement',
|
||||
toolEnforcementHint: 'Control tool call execution mode',
|
||||
auto: 'Auto',
|
||||
always: 'Always',
|
||||
never: 'Never',
|
||||
},
|
||||
memory: {
|
||||
enabled: 'Enable Memory',
|
||||
enabledHint: 'Allow AI to remember conversation context',
|
||||
userProfile: 'User Profile',
|
||||
userProfileHint: 'Allow AI to remember user preferences',
|
||||
charLimit: 'Memory Char Limit',
|
||||
charLimitHint: 'Max characters for MEMORY.md',
|
||||
userCharLimit: 'User Profile Char Limit',
|
||||
userCharLimitHint: 'Max characters for USER.md',
|
||||
},
|
||||
session: {
|
||||
mode: 'Reset Mode',
|
||||
modeHint: 'Trigger condition for session reset',
|
||||
modeBoth: 'Idle + Scheduled',
|
||||
modeIdle: 'Idle Only',
|
||||
modeHourly: 'Scheduled Only',
|
||||
idleMinutes: 'Idle Timeout',
|
||||
idleMinutesHint: 'Wait time before auto-reset (minutes)',
|
||||
atHour: 'Scheduled Reset Time',
|
||||
atHourHint: 'Reset session at this hour daily',
|
||||
},
|
||||
privacy: {
|
||||
redactPii: 'Redact PII',
|
||||
redactPiiHint: 'Auto-detect and hide sensitive info (passwords, keys, etc.)',
|
||||
},
|
||||
apiServer: {
|
||||
enable: 'Enable',
|
||||
enableHint: 'Enable API server',
|
||||
host: 'Host',
|
||||
hostHint: 'Listen address',
|
||||
port: 'Port',
|
||||
portHint: 'Listen port',
|
||||
key: 'Key',
|
||||
keyHint: 'API access key',
|
||||
cors: 'CORS Origins',
|
||||
corsHint: 'Allowed cross-origin sources',
|
||||
},
|
||||
},
|
||||
|
||||
// Platform channel settings
|
||||
platform: {
|
||||
requireMention: "Require {'@'}Mention",
|
||||
requireMentionGroup: "Require {'@'}mention in groups to respond",
|
||||
requireMentionChannel: "Require {'@'}mention in channels to respond",
|
||||
requireMentionRoom: "Require {'@'}mention in rooms to respond",
|
||||
reactions: 'Reactions',
|
||||
reactionsHint: 'React to messages with emoji',
|
||||
freeResponseChats: 'Free Response Chats',
|
||||
freeResponseChatsHint: "Chat IDs that respond without {'@'}mention (comma-separated)",
|
||||
freeResponseChannels: 'Free Response Channels',
|
||||
freeResponseChannelsHint: "Channel IDs that respond without {'@'}mention (comma-separated)",
|
||||
freeResponseRooms: 'Free Response Rooms',
|
||||
freeResponseRoomsHint: "Room IDs that respond without {'@'}mention (comma-separated)",
|
||||
mentionPatterns: 'Custom Mention Patterns',
|
||||
mentionPatternsHint: 'Additional trigger patterns',
|
||||
autoThread: 'Auto Thread',
|
||||
autoThreadHint: "Auto-create reply threads after {'@'}mention",
|
||||
autoThreadHintRoom: 'Auto-create reply threads in rooms',
|
||||
dmMentionThreads: 'DM Mention Threads',
|
||||
dmMentionThreadsHint: 'Use thread replies for mentions in DMs',
|
||||
allowBots: 'Allow Bot Messages',
|
||||
allowBotsHint: 'Respond to messages from other bots',
|
||||
allowedChannels: 'Allowed Channels',
|
||||
allowedChannelsHint: 'Whitelist channel IDs (comma-separated)',
|
||||
ignoredChannels: 'Ignored Channels',
|
||||
ignoredChannelsHint: 'Channels where bot never responds (comma-separated)',
|
||||
noThreadChannels: 'No-Thread Channels',
|
||||
noThreadChannelsHint: 'Channels where bot responds without threads (comma-separated)',
|
||||
botToken: 'Bot Token',
|
||||
botTokenHint: 'Bot token from developer portal',
|
||||
accessToken: 'Access Token',
|
||||
accessTokenHint: 'Matrix access token',
|
||||
homeserver: 'Homeserver URL',
|
||||
homeserverHint: 'Matrix homeserver URL',
|
||||
appId: 'App ID',
|
||||
appIdHint: 'Feishu App ID',
|
||||
appSecret: 'App Secret',
|
||||
appSecretHint: 'Feishu App Secret',
|
||||
clientId: 'Client ID',
|
||||
clientIdHint: 'DingTalk Client ID',
|
||||
clientSecret: 'Client Secret',
|
||||
clientSecretHint: 'DingTalk Client Secret',
|
||||
botId: 'Bot ID',
|
||||
botIdHint: 'WeCom Bot ID',
|
||||
wecomSecretHint: 'WeCom Bot Secret',
|
||||
waEnabled: 'Enable WhatsApp',
|
||||
waEnabledHint: 'Enable WhatsApp via QR code pairing',
|
||||
weixinToken: 'Weixin Token',
|
||||
weixinTokenHint: 'From weixin CLI QR login (hermes weixin)',
|
||||
accountId: 'Account ID',
|
||||
accountIdHint: 'Weixin account ID',
|
||||
qrLogin: 'QR Login',
|
||||
qrRelogin: 'Re-login',
|
||||
qrFetching: 'Fetching QR code...',
|
||||
qrScanHint: 'Scan with WeChat to login',
|
||||
qrScanedHint: 'Scaned, please confirm on phone...',
|
||||
},
|
||||
|
||||
// Language
|
||||
language: {
|
||||
label: 'Language',
|
||||
zh: '中文',
|
||||
en: 'English',
|
||||
},
|
||||
|
||||
// Terminal
|
||||
terminal: {
|
||||
sessions: 'Sessions',
|
||||
newTab: 'New Terminal',
|
||||
closeSession: 'Close this session?',
|
||||
sessionExited: 'Exited',
|
||||
processExited: 'Process exited with code {code}',
|
||||
},
|
||||
|
||||
// Usage
|
||||
usage: {
|
||||
title: 'Usage Statistics',
|
||||
refresh: 'Refresh',
|
||||
totalTokens: 'Total Tokens',
|
||||
inputTokens: 'Input',
|
||||
outputTokens: 'Output',
|
||||
totalSessions: 'Total Sessions',
|
||||
avgPerDay: '~{n}/day avg',
|
||||
estimatedCost: 'Est. Cost',
|
||||
cacheHitRate: 'Cache Hit Rate',
|
||||
modelBreakdown: 'Model Breakdown',
|
||||
dailyTrend: 'Daily Usage (Last 30 Days)',
|
||||
date: 'Date',
|
||||
tokens: 'Tokens',
|
||||
cache: 'Cache',
|
||||
sessions: 'Sessions',
|
||||
cost: 'Cost',
|
||||
noData: 'No usage data',
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
export default {
|
||||
// 登录
|
||||
login: {
|
||||
title: 'Hermes Web UI',
|
||||
description: '输入访问令牌以继续。令牌在服务端启动日志中查看。',
|
||||
placeholder: '访问令牌',
|
||||
submit: '登录',
|
||||
tokenRequired: '请输入访问令牌',
|
||||
invalidToken: '令牌无效',
|
||||
connectionFailed: '无法连接到服务器',
|
||||
},
|
||||
|
||||
// 通用
|
||||
common: {
|
||||
loading: '加载中...',
|
||||
cancel: '取消',
|
||||
delete: '删除',
|
||||
edit: '编辑',
|
||||
save: '保存',
|
||||
saved: '已保存',
|
||||
saveFailed: '保存失败',
|
||||
ok: '确定',
|
||||
copied: '已复制',
|
||||
copy: '复制',
|
||||
update: '更新',
|
||||
create: '创建',
|
||||
noData: '暂无数据',
|
||||
fetch: '获取',
|
||||
add: '添加',
|
||||
enable: '启用',
|
||||
disable: '禁用',
|
||||
configured: '已配置',
|
||||
notConfigured: '未配置',
|
||||
},
|
||||
|
||||
// 侧边栏
|
||||
sidebar: {
|
||||
chat: '对话',
|
||||
jobs: '任务',
|
||||
models: '模型',
|
||||
skills: '技能',
|
||||
memory: '记忆',
|
||||
logs: '日志',
|
||||
usage: '用量',
|
||||
channels: '频道',
|
||||
terminal: '终端',
|
||||
settings: '设置',
|
||||
connected: '已连接',
|
||||
disconnected: '未连接',
|
||||
},
|
||||
|
||||
// 对话
|
||||
chat: {
|
||||
emptyState: '开始与 Hermes Agent 对话',
|
||||
inputPlaceholder: '输入消息... (Enter 发送,Shift+Enter 换行)',
|
||||
attachFiles: '添加附件',
|
||||
stop: '停止',
|
||||
send: '发送',
|
||||
contextUsed: '上下文已用:',
|
||||
sessions: '会话',
|
||||
noSessions: '暂无会话',
|
||||
newChat: '新建对话',
|
||||
deleteSession: '确定删除此会话?',
|
||||
sessionDeleted: '会话已删除',
|
||||
rename: '重命名',
|
||||
copySessionId: '复制会话 ID',
|
||||
renamed: '已重命名',
|
||||
renameFailed: '重命名失败',
|
||||
renameSession: '重命名会话',
|
||||
enterNewTitle: '输入新标题',
|
||||
other: '其他',
|
||||
runFailed: '运行失败',
|
||||
error: '错误',
|
||||
tool: '工具',
|
||||
arguments: '参数',
|
||||
result: '结果',
|
||||
truncated: '... (已截断)',
|
||||
},
|
||||
|
||||
// 定时任务
|
||||
jobs: {
|
||||
title: '定时任务',
|
||||
createJob: '创建任务',
|
||||
editJob: '编辑任务',
|
||||
noJobs: '暂无定时任务,创建一个开始吧。',
|
||||
name: '名称',
|
||||
namePlaceholder: '任务名称',
|
||||
schedule: '调度表达式 (Cron)',
|
||||
schedulePlaceholder: '例如 0 9 * * *',
|
||||
quickPresets: '快速预设',
|
||||
selectPreset: '选择预设...',
|
||||
presetEveryMinute: '每分钟',
|
||||
presetEvery5Min: '每 5 分钟',
|
||||
presetEveryHour: '每小时',
|
||||
presetEveryDay: '每天 00:00',
|
||||
presetEveryDay9: '每天 09:00',
|
||||
presetEveryMonday: '每周一 09:00',
|
||||
presetEveryMonth: '每月 1 日 09:00',
|
||||
prompt: '提示词',
|
||||
promptPlaceholder: '要执行的内容',
|
||||
deliverTarget: '投递目标',
|
||||
origin: '来源',
|
||||
local: '本地',
|
||||
repeatCount: '重复次数(可选)',
|
||||
repeatPlaceholder: '留空表示无限重复',
|
||||
jobCreated: '任务已创建',
|
||||
jobUpdated: '任务已更新',
|
||||
nameRequired: '名称为必填项',
|
||||
scheduleRequired: '调度表达式为必填项',
|
||||
loadFailed: '加载任务失败',
|
||||
jobPaused: '任务已暂停',
|
||||
jobResumed: '任务已恢复',
|
||||
jobTriggered: '任务已触发',
|
||||
jobDeleted: '任务已删除',
|
||||
status: {
|
||||
running: '运行中',
|
||||
paused: '已暂停',
|
||||
disabled: '已禁用',
|
||||
scheduled: '已调度',
|
||||
},
|
||||
info: {
|
||||
schedule: '调度',
|
||||
lastRun: '上次运行',
|
||||
nextRun: '下次运行',
|
||||
deliver: '投递',
|
||||
repeat: '重复',
|
||||
},
|
||||
action: {
|
||||
pause: '暂停',
|
||||
pauseJob: '暂停任务',
|
||||
resume: '恢复',
|
||||
resumeJob: '恢复任务',
|
||||
runNow: '立即运行',
|
||||
triggerImmediately: '立即触发',
|
||||
},
|
||||
},
|
||||
|
||||
// 技能
|
||||
skills: {
|
||||
title: '技能',
|
||||
searchPlaceholder: '搜索技能...',
|
||||
noMatch: '没有匹配的技能',
|
||||
noSkills: '暂无技能',
|
||||
backTo: '返回',
|
||||
attachedFiles: '附件文件',
|
||||
loadFailed: '加载技能失败',
|
||||
fileLoadFailed: '加载文件失败',
|
||||
toggleFailed: '切换技能状态失败',
|
||||
},
|
||||
|
||||
// 记忆
|
||||
memory: {
|
||||
title: '记忆',
|
||||
refresh: '刷新',
|
||||
loadFailed: '加载记忆失败',
|
||||
myNotes: '我的笔记',
|
||||
noNotes: '暂无笔记。',
|
||||
notesPlaceholder: '输入笔记内容...',
|
||||
userProfile: '用户画像',
|
||||
noProfile: '暂无画像。',
|
||||
profilePlaceholder: '输入用户画像...',
|
||||
},
|
||||
|
||||
// 模型
|
||||
models: {
|
||||
title: '模型',
|
||||
addProvider: '添加 Provider',
|
||||
providerType: 'Provider 类型',
|
||||
preset: '预设',
|
||||
custom: '自定义',
|
||||
selectProvider: '选择 Provider',
|
||||
chooseProvider: '选择一个 provider...',
|
||||
name: '名称',
|
||||
autoGeneratedName: '根据 Base URL 自动生成',
|
||||
baseUrl: 'Base URL',
|
||||
baseUrlPlaceholder: '例如 https://api.example.com/v1',
|
||||
apiKey: 'API Key',
|
||||
apiKeyPlaceholder: 'sk-...',
|
||||
defaultModel: '默认模型',
|
||||
selectModel: '选择模型...',
|
||||
providerAdded: 'Provider 已添加',
|
||||
providerDeleted: 'Provider 已删除',
|
||||
deleteProvider: '删除 Provider',
|
||||
deleteConfirm: '确定删除 "{name}" 吗?',
|
||||
noProviders: '暂无 Provider,添加一个开始吧。',
|
||||
builtIn: '内置',
|
||||
customType: '自定义',
|
||||
provider: 'Provider',
|
||||
local: '本地 ({host})',
|
||||
selectProviderRequired: '请选择 Provider',
|
||||
baseUrlRequired: 'Base URL 为必填项',
|
||||
apiKeyRequired: 'API Key 为必填项',
|
||||
modelRequired: '默认模型为必填项',
|
||||
enterBaseUrl: '请先输入 Base URL',
|
||||
unexpectedFormat: '响应格式异常',
|
||||
foundModels: '找到 {count} 个模型',
|
||||
fetchFailed: '获取模型失败',
|
||||
},
|
||||
|
||||
// 日志
|
||||
logs: {
|
||||
title: '日志',
|
||||
all: '全部',
|
||||
searchPlaceholder: '搜索...',
|
||||
refresh: '刷新',
|
||||
noEntries: '暂无日志',
|
||||
},
|
||||
|
||||
// 设置
|
||||
settings: {
|
||||
title: '设置',
|
||||
saved: '已保存',
|
||||
saveFailed: '保存失败',
|
||||
tabs: {
|
||||
display: '显示',
|
||||
agent: '代理',
|
||||
memory: '记忆',
|
||||
session: '会话',
|
||||
privacy: '隐私',
|
||||
apiServer: 'API 服务器',
|
||||
},
|
||||
display: {
|
||||
streaming: '流式响应',
|
||||
streamingHint: '实时显示 AI 回复',
|
||||
compact: '紧凑模式',
|
||||
compactHint: '减少消息间距',
|
||||
showReasoning: '显示推理过程',
|
||||
showReasoningHint: '展示模型思考过程',
|
||||
showCost: '显示费用',
|
||||
showCostHint: '在回复中显示 token 使用量',
|
||||
inlineDiffs: '内联差异',
|
||||
inlineDiffsHint: '代码变更以内联方式显示',
|
||||
bellOnComplete: '完成提示音',
|
||||
bellOnCompleteHint: 'AI 回复完成时播放提示音',
|
||||
busyInputMode: '忙碌输入模式',
|
||||
busyInputModeHint: 'AI 处理中仍可输入',
|
||||
},
|
||||
agent: {
|
||||
maxTurns: '最大轮次',
|
||||
maxTurnsHint: '单次对话最大交互轮数',
|
||||
gatewayTimeout: '网关超时',
|
||||
gatewayTimeoutHint: '单次请求超时时间(秒)',
|
||||
restartDrainTimeout: '重启排空超时',
|
||||
restartDrainTimeoutHint: '重启前排空请求的超时时间(秒)',
|
||||
toolEnforcement: '工具执行策略',
|
||||
toolEnforcementHint: '控制工具调用的执行模式',
|
||||
auto: '自动',
|
||||
always: '始终',
|
||||
never: '从不',
|
||||
},
|
||||
memory: {
|
||||
enabled: '启用记忆',
|
||||
enabledHint: '允许 AI 记住对话上下文',
|
||||
userProfile: '用户画像',
|
||||
userProfileHint: '允许 AI 记住用户偏好信息',
|
||||
charLimit: '记忆字符上限',
|
||||
charLimitHint: 'MEMORY.md 最大字符数',
|
||||
userCharLimit: '用户画像字符上限',
|
||||
userCharLimitHint: 'USER.md 最大字符数',
|
||||
},
|
||||
session: {
|
||||
mode: '重置模式',
|
||||
modeHint: '会话重置的触发条件',
|
||||
modeBoth: '空闲 + 定时',
|
||||
modeIdle: '仅空闲',
|
||||
modeHourly: '仅定时',
|
||||
idleMinutes: '空闲超时',
|
||||
idleMinutesHint: '无操作后自动重置的等待时间(分钟)',
|
||||
atHour: '定时重置时间',
|
||||
atHourHint: '每天在指定小时重置会话',
|
||||
},
|
||||
privacy: {
|
||||
redactPii: '脱敏 PII',
|
||||
redactPiiHint: '自动检测并隐藏敏感信息(密码、密钥等)',
|
||||
},
|
||||
apiServer: {
|
||||
enable: '启用',
|
||||
enableHint: '启用 API 服务器',
|
||||
host: '主机',
|
||||
hostHint: '监听地址',
|
||||
port: '端口',
|
||||
portHint: '监听端口',
|
||||
key: '密钥',
|
||||
keyHint: 'API 访问密钥',
|
||||
cors: 'CORS 来源',
|
||||
corsHint: '允许的跨域来源',
|
||||
},
|
||||
},
|
||||
|
||||
// 平台频道设置
|
||||
platform: {
|
||||
requireMention: "需要 {'@'}提及",
|
||||
requireMentionGroup: "群组中需要 {'@'}机器人 才会响应",
|
||||
requireMentionChannel: "频道中需要 {'@'}机器人 才会响应",
|
||||
requireMentionRoom: "房间中需要 {'@'}机器人 才会响应",
|
||||
reactions: '表情回应',
|
||||
reactionsHint: '对消息添加表情回应',
|
||||
freeResponseChats: '自由响应聊天',
|
||||
freeResponseChatsHint: "不需要 {'@'}提及即响应的聊天 ID(逗号分隔)",
|
||||
freeResponseChannels: '自由响应频道',
|
||||
freeResponseChannelsHint: "不需要 {'@'}提及即响应的频道 ID(逗号分隔)",
|
||||
freeResponseRooms: '自由响应房间',
|
||||
freeResponseRoomsHint: "不需要 {'@'}提及即响应的房间 ID(逗号分隔)",
|
||||
mentionPatterns: '自定义提及模式',
|
||||
mentionPatternsHint: '额外的触发模式列表',
|
||||
autoThread: '自动创建线程',
|
||||
autoThreadHint: "{'@'}提及 后自动创建回复线程",
|
||||
autoThreadHintRoom: '在房间中自动创建回复线程',
|
||||
dmMentionThreads: 'DM 提及线程',
|
||||
dmMentionThreadsHint: '在私聊中也使用线程回复提及',
|
||||
allowBots: '允许机器人消息',
|
||||
allowBotsHint: '响应其他机器人发送的消息',
|
||||
allowedChannels: '允许的频道',
|
||||
allowedChannelsHint: '白名单频道 ID(逗号分隔)',
|
||||
ignoredChannels: '忽略的频道',
|
||||
ignoredChannelsHint: '不响应的频道 ID(逗号分隔)',
|
||||
noThreadChannels: '无线程频道',
|
||||
noThreadChannelsHint: '不创建线程的频道 ID(逗号分隔)',
|
||||
botToken: 'Bot Token',
|
||||
botTokenHint: '开发者门户获取的 Bot Token',
|
||||
accessToken: 'Access Token',
|
||||
accessTokenHint: 'Matrix Access Token',
|
||||
homeserver: 'Homeserver URL',
|
||||
homeserverHint: 'Matrix 服务器地址',
|
||||
appId: 'App ID',
|
||||
appIdHint: '飞书 App ID',
|
||||
appSecret: 'App Secret',
|
||||
appSecretHint: '飞书 App Secret',
|
||||
clientId: 'Client ID',
|
||||
clientIdHint: '钉钉 Client ID',
|
||||
clientSecret: 'Client Secret',
|
||||
clientSecretHint: '钉钉 Client Secret',
|
||||
botId: 'Bot ID',
|
||||
botIdHint: '企业微信 Bot ID',
|
||||
wecomSecretHint: '企业微信 Bot Secret',
|
||||
waEnabled: '启用 WhatsApp',
|
||||
waEnabledHint: '通过二维码配对启用 WhatsApp',
|
||||
weixinToken: '微信 Token',
|
||||
weixinTokenHint: '通过 weixin CLI 扫码登录获取 (hermes weixin)',
|
||||
accountId: 'Account ID',
|
||||
accountIdHint: '微信 Account ID',
|
||||
qrLogin: '扫码登录',
|
||||
qrRelogin: '重新登录',
|
||||
qrFetching: '正在获取二维码...',
|
||||
qrScanHint: '使用微信扫描二维码登录',
|
||||
qrScanedHint: '已扫描,请在手机上确认...',
|
||||
},
|
||||
|
||||
// 语言
|
||||
language: {
|
||||
label: '语言',
|
||||
zh: '中文',
|
||||
en: 'English',
|
||||
},
|
||||
|
||||
// 终端
|
||||
terminal: {
|
||||
sessions: '会话',
|
||||
newTab: '新建终端',
|
||||
closeSession: '关闭此会话?',
|
||||
sessionExited: '已退出',
|
||||
processExited: '进程已退出,代码 {code}',
|
||||
},
|
||||
|
||||
// 用量统计
|
||||
usage: {
|
||||
title: '用量统计',
|
||||
refresh: '刷新',
|
||||
totalTokens: '总 Token 数',
|
||||
inputTokens: '输入',
|
||||
outputTokens: '输出',
|
||||
totalSessions: '总会话数',
|
||||
avgPerDay: '日均 ~{n}',
|
||||
estimatedCost: '预估费用',
|
||||
cacheHitRate: '缓存命中率',
|
||||
modelBreakdown: '模型分布',
|
||||
dailyTrend: '每日用量(近 30 天)',
|
||||
date: '日期',
|
||||
tokens: 'Token',
|
||||
cache: '缓存',
|
||||
sessions: '会话',
|
||||
cost: '费用',
|
||||
noData: '暂无用量数据',
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user