docs: 将仓库代码注释统一为中文
CI / docs-check (push) Canceled after 0s
CI / backend-test (push) Canceled after 0s
CI / service-test (push) Canceled after 0s
CI / frontend-test (push) Canceled after 0s
CI / rust-core (push) Canceled after 0s
CI / docs-check (pull_request) Canceled after 0s
CI / backend-test (pull_request) Canceled after 0s
CI / service-test (pull_request) Canceled after 0s
CI / frontend-test (pull_request) Canceled after 0s
CI / rust-core (pull_request) Canceled after 0s

This commit is contained in:
2026-09-10 00:40:56 +08:00
parent 51c592841d
commit d703ab64e3
249 changed files with 707 additions and 900 deletions
+2 -4
View File
@@ -115,8 +115,7 @@ function formPayload(): McpServerInput {
function payload(requireConnection = true): McpServerInput {
const { config, secrets } = editorMode.value === 'form'
? normalizeMcpConfig(formPayload(), '', requireConnection) : parseMcpJson(rawConfig.value, form.name, requireConnection)
// Keep only still-declared drafts. A mode switch must not discard imported keys,
// and editing the declaration must not later send a removed key to the Secret API.
// 仅保留仍声明的草稿。模式开关不得丢弃导入的密钥,并且编辑声明后不得将删除的密钥发送到 Secret API。
importedSecrets.value = mergeImportedSecrets(config, importedSecrets.value, secrets)
if (editingId.value) config.version = form.version
if (editorMode.value === 'json') rawConfig.value = JSON.stringify(config, null, 2)
@@ -149,8 +148,7 @@ async function save() {
if (editingOriginal.value && executionChanged(editingOriginal.value, input) && !(await askConfirm(t('连接命令、地址或认证配置已变化,保存后旧测试与授权会失效。是否保存?', 'The command, address, or authentication settings changed. Previous tests and authorization will be invalidated. Save?')))) return
busy.value = 'save'
saved = editingId.value ? await service.updateMcpServer(editingId.value, input) : await service.createMcpServer(input)
// Commit the returned ID/version before saving secrets so a partial failure can
// retry this server instead of creating a duplicate or sending a stale version.
// 在保存机密之前提交返回的 ID/版本,以便部分失败可以重试此服务器,而不是创建重复版本或发送过时的版本。
editingId.value = saved.server_id
editingOriginal.value = saved
resetEditor({ ...input, version: saved.version })
+5 -8
View File
@@ -11,8 +11,7 @@ export function mergeImportedSecrets(config: McpServerInput, previous: ImportedS
const keys = item.kind === 'header' ? config.secret_header_keys : config.secret_environment_keys
const declared = keys.find(key => normalize(key) === normalize(item.key))
if (declared === undefined) continue
// HTTP identity is case-insensitive, but the Secret API requires the current
// declared spelling. New inline values replace older drafts of that identity.
// HTTP 身份不区分大小写,但 Secret API 需要当前声明的拼写。新的内联值取代了该身份的旧草稿。
merged.set(`${item.kind}:${normalize(declared)}`, { ...item, key: declared })
}
return [...merged.values()]
@@ -50,7 +49,7 @@ function timeout(value: unknown, fallback: number, max: number, label: string):
return value
}
// Do not silently rewrite executable arguments or secret values copied from chat.
// 不要默默地重写从聊天复制的可执行参数或秘密值。
function checkUrl(value: string, label: string) {
if (/^\[https?:\/\//i.test(value)) throw new Error(`${label}${t('请填写纯 URL,不要粘贴 Markdown 链接', ': enter a plain URL instead of a Markdown link')}`)
}
@@ -62,9 +61,7 @@ export function parseMcpJson(raw: string, fallbackName = '', requireConnection =
return normalizeMcpConfig(parsed, fallbackName, requireConnection)
}
/** Normalize external client JSON before it reaches either the form or the API.
* Inline secrets leave the public config here and are sent only to the Secret API.
*/
/** 在外部客户端 JSON 到达表单或 API 之前对其进行标准化。内联机密在此处保留公共配置,并且仅发送到机密 API。 */
export function normalizeMcpConfig(parsed: unknown, fallbackName = '', requireConnection = true) {
let raw = object(parsed, t('服务器配置', 'Server configuration'))
if ('mcpServers' in raw) {
@@ -75,7 +72,7 @@ export function normalizeMcpConfig(parsed: unknown, fallbackName = '', requireCo
}
const allowed = new Set([...Object.keys(emptyMcpConfig()), 'version', 'env', 'type', 'timeout', 'sse_read_timeout'])
if (Object.keys(raw).some(key => !allowed.has(key))) {
// Never echo arbitrary unknown keys: pasted secrets sometimes become JSON keys.
// 永远不要回显任意未知密钥:粘贴的秘密有时会变成 JSON 密钥。
throw new Error(t('服务器配置含不支持的字段;API Key 请放在 env/environment 的对应变量中,不要放在顶层', 'The server configuration contains unsupported fields. Put API keys in the corresponding env/environment variables, not at the top level.'))
}
if (raw.env !== undefined && raw.environment !== undefined) throw new Error(t('env 与 environment 请只保留一个,避免覆盖配置', 'Keep either env or environment, not both'))
@@ -100,7 +97,7 @@ export function normalizeMcpConfig(parsed: unknown, fallbackName = '', requireCo
config.secret_header_keys = [...new Set(strings(raw.secret_header_keys, 'secret_header_keys'))]
config.permissions = strings(raw.permissions, 'permissions')
config.startup_timeout_seconds = timeout(raw.startup_timeout_seconds ?? raw.timeout, 15, 120, t('启动超时', 'Startup timeout'))
// Compatibility policy: legacy read timeout becomes the tool wait budget, not an SSE transport setting.
// 兼容性策略:旧的读取超时成为工具等待预算,而不是 SSE 传输设置。
config.tool_timeout_seconds = timeout(raw.tool_timeout_seconds ?? raw.sse_read_timeout, 30, 300, t('工具超时', 'Tool timeout'))
if (config.transport === 'stdio') {
if (requireConnection && !config.command) throw new Error(t('stdio 配置必须填写 command', 'stdio configuration requires command'))