refine oauth model selection and provider inputs

This commit is contained in:
lpf
2026-03-11 19:48:10 +08:00
parent b3c0f58998
commit 5d74dba0b8
8 changed files with 381 additions and 215 deletions

View File

@@ -54,8 +54,6 @@ const resources = {
channelFieldMaixCamAllowFromHint: 'Only these device or sender IDs can invoke the channel when set.',
channelFieldEnableGroupsHint: 'Allow messages coming from group chats.',
channelFieldRequireMentionHint: 'When enabled, group messages must mention the bot before they are accepted.',
whatsappBridgeRunning: 'Bridge Running',
whatsappBridgeStopped: 'Bridge Stopped',
whatsappBridgeURL: 'Bridge URL',
whatsappBridgeAccount: 'Linked Account',
whatsappBridgeLastEvent: 'Last Event',
@@ -71,8 +69,6 @@ const resources = {
whatsappQRCodeHint: 'If you are already linked, no QR is shown.\nIf the QR code does not appear, confirm the gateway is running and the WhatsApp channel is enabled.',
whatsappStateAwaitingScan: 'Awaiting Scan',
whatsappStateDisconnected: 'Disconnected',
whatsappBridgeDevHintTitle: 'How to use',
whatsappBridgeDevHint: '1. Start the gateway and enable the WhatsApp channel.\n2. Scan the QR code here with WhatsApp.\n3. Keep ClawGo running to receive WhatsApp messages.',
whatsappFieldEnabledHint: 'Master switch for receiving WhatsApp messages through the bridge.',
whatsappFieldBridgeURLHint: 'Optional. Leave empty to use the gateway embedded WhatsApp bridge at /whatsapp/ws.',
whatsappFieldAllowFromHint: 'One sender JID per line. Only these senders can trigger ClawGo.',
@@ -108,14 +104,11 @@ const resources = {
nodesFilterPlaceholder: 'Filter by node id, name, or tag',
agentTree: 'Agent Tree',
noAgentTree: 'No agent tree available.',
readonlyMirror: 'Read-only mirror',
localControl: 'Local control',
logs: 'Real-time Logs',
logCodes: 'Log Codes',
skills: 'Skills',
memory: 'Memory',
taskAudit: 'Task Audit',
tasks: 'Tasks',
subagentProfiles: 'Subagent Profiles',
subagentsRuntime: 'Agents',
nodeP2P: 'Node P2P',
@@ -136,59 +129,23 @@ const resources = {
zoomIn: 'Zoom In',
zoomOut: 'Zoom Out',
fitView: 'Fit View',
childrenCount: 'children',
'topologyFilter.all': 'All',
'topologyFilter.running': 'Running',
'topologyFilter.failed': 'Failed',
'topologyFilter.local': 'Local',
'topologyFilter.remote': 'Remote',
noLiveTasks: 'No live tasks',
remoteTasksUnavailable: 'Remote task details are not mirrored yet.',
subagentDetail: 'Subagent Detail',
spawnSubagent: 'Spawn Subagent',
dispatchAndWait: 'Dispatch And Wait',
dispatchReply: 'Dispatch Reply',
mergedResult: 'Merged Result',
configSubagentDraft: 'Config Subagent',
agentRegistry: 'Agent Registry',
loadDraft: 'Load Draft',
enableAgent: 'Enable Agent',
disableAgent: 'Disable Agent',
deleteAgent: 'Delete Agent',
deleteAgentConfirm: 'Delete agent "{{id}}" from config.json permanently?',
noRegistryAgents: 'No configured agents.',
saveToConfig: 'Save To Config',
configSubagentSaved: 'Subagent config saved and runtime updated.',
promptFileEditor: 'Prompt File Editor',
promptFileEditorPlaceholder: 'Edit the AGENT.md content for this subagent.',
bootstrapPromptFile: 'Bootstrap AGENT.md',
savePromptFile: 'Save AGENT.md',
promptFileSaved: 'Prompt file saved.',
promptFileBootstrapped: 'Prompt file template created.',
promptFileReady: 'AGENT.md ready',
promptFileMissing: 'AGENT.md missing',
threadTrace: 'Thread Trace',
threadMessages: 'Thread Messages',
inbox: 'Inbox',
reply: 'Reply',
ack: 'Ack',
steerMessage: 'Steering message',
newProfile: 'New Profile',
spawn: 'Spawn',
kill: 'Kill',
send: 'Send',
dispatch: 'Dispatch',
toolAllowlist: 'Tool Allowlist',
memoryNamespace: 'Memory Namespace',
subagentDeleteConfirmTitle: 'Delete Subagent Profile',
subagentDeleteConfirmMessage: 'Delete subagent profile "{{id}}" permanently?',
sidebarCore: 'Core',
sidebarMain: 'Main',
sidebarAgents: 'Agents',
sidebarRuntime: 'Runtime',
sidebarConfig: 'Configuration',
sidebarKnowledge: 'Knowledge',
sidebarSystem: 'System',
sidebarOps: 'Operations',
sidebarInsights: 'Insights',
ekg: 'EKG',
@@ -198,9 +155,7 @@ const resources = {
ekgTopProvidersWorkload: 'Top Providers (workload)',
ekgTopProvidersAll: 'Top Providers (all)',
ekgTopErrsigWorkload: 'Top Error Signatures (workload)',
ekgTopErrsigHeartbeat: 'Top Error Signatures (heartbeat)',
ekgTopErrsigAll: 'Top Error Signatures (all)',
taskList: 'Task List',
taskDetail: 'Task Detail',
taskQueue: 'Task Queue',
taskLogs: 'Task Logs',
@@ -231,9 +186,6 @@ const resources = {
nodeActions: 'Node Actions',
nodeModels: 'Node Models',
nodeAgents: 'Node Agents',
nodesOnline: 'Nodes Online',
recentCron: 'Recent Cron Jobs',
nodesSnapshot: 'Nodes Snapshot',
refreshAll: 'Refresh All',
refresh: 'Refresh',
dashboardNodeP2PDetail: '{{transport}} · {{sessions}} active · {{retries}} retries',
@@ -292,7 +244,6 @@ const resources = {
noNodes: 'No nodes available',
allActions: 'All Actions',
allTransports: 'All Transports',
sessions: 'Sessions',
mainChat: 'Main Chat',
internalStream: 'Internal Stream',
enable: 'Enable',
@@ -330,18 +281,13 @@ const resources = {
rawJson: 'Raw JSON',
reload: 'Reload',
saveChanges: 'Save Changes',
gatewaySettings: 'Gateway Settings',
host: 'Host',
port: 'Port',
token: 'Token',
agentDefaults: 'Agent Defaults',
maxToolIterations: 'Max Tool Iterations',
maxTokens: 'Max Tokens',
providers: 'Providers',
providersIntroBefore: 'Select a provider tab, then set auth to ',
providersIntroMiddle: ' or ',
providersIntroAfter: '. The OAuth fields, login link flow, callback paste step, and account list appear in that provider card.',
providersBuiltinCannotDelete: 'The built-in provider "proxy" cannot be deleted.',
providersQwenLabelTitle: 'Qwen Account Label',
providersQwenLabelMessage: 'Qwen OAuth may not return an email. Enter an email or alias to identify this account.',
providersQwenImportLabelMessage: 'Enter an email or alias for this imported Qwen account.',
@@ -357,10 +303,17 @@ const resources = {
providersOAuthCallbackPlaceholder: 'http://localhost:1455/auth/callback?code=...&state=...',
providersOAuthAddedTitle: 'OAuth Added',
providersOAuthAddedMessage: 'Account: {{account}}',
providersOAuthAddedWithModel: 'Account: {{account}}\nModel: {{model}}',
providersOAuthAddedFallback: 'OAuth account added.',
providersAuthJsonImportedTitle: 'auth.json Imported',
providersAuthJsonImportedMessage: 'OAuth auth.json imported.',
providersImportingAuthJson: 'Importing auth.json',
providersSavingSelectedModel: 'Saving selected model',
providersSelectModelTitle: 'Choose Model',
providersSelectModelMessage: 'OAuth login fetched the provider models. Choose the model this provider should use.',
providersSelectModelSearchPlaceholder: 'Search model id',
providersSelectModelConfirm: 'Use this model',
providersSelectModelEmpty: 'No models match the current search.',
providersRefreshingOAuthAccount: 'Refreshing OAuth account',
providersDeleteOAuthAccountTitle: 'Delete OAuth Account',
providersDeletingOAuthAccount: 'Deleting OAuth account',
@@ -376,7 +329,8 @@ const resources = {
providersApiBase: 'API base',
providersApiKey: 'API key',
providersModels: 'models',
providersModelsHelp: 'Comma separated model ids used by this provider.',
providersModelsHelp: 'Press Enter to add a model id for this provider.',
providersModelsEnterHint: 'Type model id and press Enter',
providersAuthMode: 'auth mode',
providersAuthModeHelp: 'Choose bearer for API key only, oauth for OAuth only, hybrid to use both.',
providersRuntimePersist: 'runtime persist',
@@ -407,10 +361,7 @@ const resources = {
providersOAuthAccounts: 'OAuth Accounts',
providersRefreshList: 'Refresh List',
providersNoOAuthAccounts: 'No imported OAuth accounts yet.',
proxyTimeout: 'Proxy Timeout (sec)',
system: 'System',
enableShellTools: 'Enable Shell Tools',
enableLogging: 'Enable Logging',
pauseJob: 'Pause Job',
startJob: 'Start Job',
deleteJob: 'Delete Job',
@@ -420,7 +371,6 @@ const resources = {
editJob: 'Edit Job',
jobName: 'Job Name',
kind: 'Kind',
everyMs: 'Interval (ms)',
cronExpression: 'Cron Expression',
runAt: 'Run At',
message: 'Message',
@@ -445,15 +395,12 @@ const resources = {
level: 'Level',
code: 'Code',
template: 'Template',
content: 'Content',
id: 'ID',
files: 'Files',
close: 'Close',
path: 'Path',
before: 'Before',
after: 'After',
hide: 'Hide',
show: 'Show',
clear: 'Clear',
pause: 'Pause',
resume: 'Resume',
@@ -464,7 +411,6 @@ const resources = {
appName: 'ClawGo',
webui: 'WebUI',
node: 'Node',
unknownIp: 'Unknown IP',
memoryFiles: 'Memory Files',
memoryFileNamePrompt: 'Memory file name',
noFileSelected: 'No file selected',
@@ -580,8 +526,6 @@ const resources = {
cronDisableConfirmMessage: 'Pause this cron job now?',
memoryDeleteConfirmTitle: 'Delete Memory File',
memoryDeleteConfirmMessage: 'Delete memory file "{{path}}" permanently?',
taskDeleteConfirmTitle: 'Delete Task',
taskDeleteConfirmMessage: 'Delete task "{{id}}" permanently?',
logsClearConfirmTitle: 'Clear Logs',
logsClearConfirmMessage: 'Clear current log list from this page?',
configDeleteProviderConfirmTitle: 'Delete Provider',
@@ -827,8 +771,6 @@ const resources = {
channelFieldMaixCamAllowFromHint: '设置后,仅允许这些设备或发送者 ID 调用该通道。',
channelFieldEnableGroupsHint: '允许接收来自群聊的消息。',
channelFieldRequireMentionHint: '开启后,群聊消息必须先 @ 机器人才会被接收。',
whatsappBridgeRunning: 'Bridge 运行中',
whatsappBridgeStopped: 'Bridge 未运行',
whatsappBridgeURL: 'Bridge 地址',
whatsappBridgeAccount: '关联账号',
whatsappBridgeLastEvent: '最近事件',
@@ -844,8 +786,6 @@ const resources = {
whatsappQRCodeHint: '如果已经关联成功,就不会显示二维码。\n如果二维码没有出现请确认 gateway 已启动且 WhatsApp 通道已启用。',
whatsappStateAwaitingScan: '等待扫码',
whatsappStateDisconnected: '已断开',
whatsappBridgeDevHintTitle: '使用方式',
whatsappBridgeDevHint: '1. 先启动 gateway并启用 WhatsApp 通道。\n2. 在这里用 WhatsApp 扫描二维码。\n3. 保持 ClawGo 运行以接收 WhatsApp 消息。',
whatsappFieldEnabledHint: '总开关,控制是否通过 bridge 接收 WhatsApp 消息。',
whatsappFieldBridgeURLHint: '可选。留空时自动使用当前 Gateway 内嵌的 /whatsapp/ws 地址。',
whatsappFieldAllowFromHint: '每行一个发送者 JID只有这些发送者可以触发 ClawGo。',
@@ -881,14 +821,11 @@ const resources = {
nodesFilterPlaceholder: '按节点 ID、名称或标签筛选',
agentTree: '代理树',
noAgentTree: '当前没有可用的代理树。',
readonlyMirror: '只读镜像',
localControl: '本地控制',
logs: '实时日志',
logCodes: '日志编号',
skills: '技能管理',
memory: '记忆文件',
taskAudit: '任务审计',
tasks: '任务管理',
subagentProfiles: '子代理档案',
subagentsRuntime: 'Agents',
nodeP2P: '节点 P2P',
@@ -909,59 +846,23 @@ const resources = {
zoomIn: '放大',
zoomOut: '缩小',
fitView: '适应视图',
childrenCount: '子节点',
'topologyFilter.all': '全部',
'topologyFilter.running': '运行中',
'topologyFilter.failed': '失败',
'topologyFilter.local': '本地',
'topologyFilter.remote': '远端',
noLiveTasks: '当前没有活动任务',
remoteTasksUnavailable: '远端任务细节暂未镜像回来。',
subagentDetail: '子代理详情',
spawnSubagent: '创建子代理任务',
dispatchAndWait: '派发并等待',
dispatchReply: '派发回复',
mergedResult: '汇总结果',
configSubagentDraft: '配置子代理',
agentRegistry: '代理注册表',
loadDraft: '载入配置',
enableAgent: '启用代理',
disableAgent: '停用代理',
deleteAgent: '删除代理',
deleteAgentConfirm: '确认从 config.json 中永久删除代理 "{{id}}" 吗?',
noRegistryAgents: '当前没有已配置代理。',
saveToConfig: '写入配置',
configSubagentSaved: '子代理配置已写入并刷新运行态。',
promptFileEditor: '提示词文件编辑器',
promptFileEditorPlaceholder: '编辑该子代理对应的 AGENT.md 内容。',
bootstrapPromptFile: '生成 AGENT.md 模板',
savePromptFile: '保存 AGENT.md',
promptFileSaved: '提示词文件已保存。',
promptFileBootstrapped: '提示词模板已创建。',
promptFileReady: 'AGENT.md 已就绪',
promptFileMissing: 'AGENT.md 缺失',
threadTrace: '线程追踪',
threadMessages: '线程消息',
inbox: '收件箱',
reply: '回复',
ack: '确认',
steerMessage: '引导消息',
newProfile: '新建档案',
spawn: '创建',
kill: '终止',
send: '发送',
dispatch: '派发',
toolAllowlist: '工具白名单',
memoryNamespace: '记忆命名空间',
subagentDeleteConfirmTitle: '删除子代理档案',
subagentDeleteConfirmMessage: '确认永久删除子代理档案 "{{id}}"',
sidebarCore: '核心',
sidebarMain: '主入口',
sidebarAgents: 'Agents',
sidebarRuntime: '运行态',
sidebarConfig: '配置',
sidebarKnowledge: '知识与调试',
sidebarSystem: '系统',
sidebarOps: '运维',
sidebarInsights: '洞察',
ekg: 'EKG',
@@ -971,9 +872,7 @@ const resources = {
ekgTopProvidersWorkload: 'Top Providers业务负载',
ekgTopProvidersAll: 'Top Providers全量',
ekgTopErrsigWorkload: 'Top 错误签名(业务负载)',
ekgTopErrsigHeartbeat: 'Top 错误签名(心跳)',
ekgTopErrsigAll: 'Top 错误签名(全量)',
taskList: '任务列表',
taskDetail: '任务详情',
taskQueue: '任务队列',
taskLogs: '任务日志',
@@ -1004,9 +903,6 @@ const resources = {
nodeActions: '节点动作',
nodeModels: '节点模型',
nodeAgents: '节点 Agents',
nodesOnline: '在线节点',
recentCron: '最近定时任务',
nodesSnapshot: '节点快照',
refreshAll: '刷新全部',
refresh: '刷新',
dashboardNodeP2PDetail: '{{transport}} · {{sessions}} 个活跃会话 · {{retries}} 次重试',
@@ -1065,7 +961,6 @@ const resources = {
noNodes: '无可用节点',
allActions: '全部动作',
allTransports: '全部传输',
sessions: '会话',
mainChat: '主对话',
internalStream: '内部流',
enable: '启用',
@@ -1103,18 +998,13 @@ const resources = {
rawJson: '原始 JSON',
reload: '重新加载',
saveChanges: '保存更改',
gatewaySettings: '网关设置',
host: '主机',
port: '端口',
token: '令牌',
agentDefaults: '代理默认值',
maxToolIterations: '最大工具迭代次数',
maxTokens: '最大 Token 数',
providers: '提供商',
providersIntroBefore: '先选择一个 provider 标签,再把认证模式切到 ',
providersIntroMiddle: ' 或 ',
providersIntroAfter: '。对应 provider 卡片里会出现 OAuth 字段、登录链接流程、回调地址回填和账号列表。',
providersBuiltinCannotDelete: '内置 provider “proxy” 不能删除。',
providersQwenLabelTitle: 'Qwen 账号标识',
providersQwenLabelMessage: 'Qwen OAuth 可能不会返回邮箱,请输入一个邮箱或别名来标识该账号。',
providersQwenImportLabelMessage: '请为导入的 Qwen 账号输入邮箱或别名。',
@@ -1130,10 +1020,17 @@ const resources = {
providersOAuthCallbackPlaceholder: 'http://localhost:1455/auth/callback?code=...&state=...',
providersOAuthAddedTitle: 'OAuth 已添加',
providersOAuthAddedMessage: '账号:{{account}}',
providersOAuthAddedWithModel: '账号:{{account}}\n模型{{model}}',
providersOAuthAddedFallback: 'OAuth 账号已添加。',
providersAuthJsonImportedTitle: 'auth.json 已导入',
providersAuthJsonImportedMessage: 'OAuth auth.json 已导入。',
providersImportingAuthJson: '正在导入 auth.json',
providersSavingSelectedModel: '正在保存所选模型',
providersSelectModelTitle: '选择模型',
providersSelectModelMessage: 'OAuth 登录已经拉取到服务商模型,请选择这个 provider 要使用的模型。',
providersSelectModelSearchPlaceholder: '搜索模型 ID',
providersSelectModelConfirm: '使用这个模型',
providersSelectModelEmpty: '当前搜索没有匹配到模型。',
providersRefreshingOAuthAccount: '正在刷新 OAuth 账号',
providersDeleteOAuthAccountTitle: '删除 OAuth 账号',
providersDeletingOAuthAccount: '正在删除 OAuth 账号',
@@ -1149,7 +1046,8 @@ const resources = {
providersApiBase: 'API 基础地址',
providersApiKey: 'API 密钥',
providersModels: '模型列表',
providersModelsHelp: '用逗号分隔这个 provider 要使用的模型 ID。',
providersModelsHelp: '输入模型 ID 后按回车添加到这个 provider。',
providersModelsEnterHint: '输入模型 ID 后按回车',
providersAuthMode: '认证模式',
providersAuthModeHelp: 'bearer 表示只用 API keyoauth 表示只用 OAuthhybrid 表示两者混用。',
providersRuntimePersist: '运行态持久化',
@@ -1180,10 +1078,7 @@ const resources = {
providersOAuthAccounts: 'OAuth 账号',
providersRefreshList: '刷新列表',
providersNoOAuthAccounts: '当前还没有导入 OAuth 账号。',
proxyTimeout: '代理超时 (秒)',
system: '系统',
enableShellTools: '启用 Shell 工具',
enableLogging: '启用日志',
pauseJob: '暂停任务',
startJob: '启动任务',
deleteJob: '删除任务',
@@ -1193,7 +1088,6 @@ const resources = {
editJob: '编辑任务',
jobName: '任务名称',
kind: '类型',
everyMs: '间隔 (毫秒)',
cronExpression: 'Cron 表达式',
runAt: '执行时间',
message: '消息',
@@ -1218,15 +1112,12 @@ const resources = {
level: '级别',
code: '代码',
template: '模板',
content: '内容',
id: 'ID',
files: '文件',
close: '关闭',
path: '路径',
before: '变更前',
after: '变更后',
hide: '隐藏',
show: '显示',
clear: '清空',
pause: '暂停',
resume: '继续',
@@ -1237,7 +1128,6 @@ const resources = {
appName: 'ClawGo',
webui: 'WebUI',
node: '节点',
unknownIp: '未知 IP',
memoryFiles: '记忆文件',
memoryFileNamePrompt: '记忆文件名',
noFileSelected: '未选择文件',
@@ -1353,8 +1243,6 @@ const resources = {
cronDisableConfirmMessage: '确认暂停该定时任务吗?',
memoryDeleteConfirmTitle: '删除记忆文件',
memoryDeleteConfirmMessage: '确认永久删除记忆文件“{{path}}”吗?',
taskDeleteConfirmTitle: '删除任务',
taskDeleteConfirmMessage: '确认永久删除任务“{{id}}”吗?',
logsClearConfirmTitle: '清空日志',
logsClearConfirmMessage: '确认清空当前页面中的日志列表吗?',
configDeleteProviderConfirmTitle: '删除 Provider',