dsh-multi-router 0.3.7 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/reasoning.mjs", "../src/config.mjs"],
4
- "sourcesContent": ["export const REASONING_EFFORTS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\n// Keep declared modes only. A fixed-thinking model without a declared set uses platform default.\nexport function reasoningModes(model, provider) {\n const r = model?.reasoning;\n if (!r || (r.supports !== true && !Array.isArray(r.supported))) return [];\n const declared = r.supportedEfforts ?? r.supported ?? [];\n const disable = r.canDisableThinking === true || declared.includes('off');\n const off = disable && !(provider === 'workbuddy' && r.onlyReasoning === true);\n return REASONING_EFFORTS.filter(e => e === 'off' ? off : declared.includes(e));\n}\n\nexport function routeReasoning(models) {\n const efforts = REASONING_EFFORTS.filter(e => models.some(({ model, provider }) => reasoningModes(model, provider).includes(e)));\n if (!efforts.length) return undefined;\n return { supports: true, supportedEfforts: efforts, canDisableThinking: efforts.includes('off'),\n defaultEffort: efforts.includes('high') ? 'high' : efforts[0] };\n}\n", "import { readFile, mkdir, rename, writeFile, chmod } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { withFileLock } from '@deepseek-ai/dsh-atomic-write';\nimport { REASONING_EFFORTS } from './reasoning.mjs';\n\nexport const PROVIDERS = ['workbuddy', 'workbuddy-ai', 'trae', 'trae-global', 'qoder', 'qoder-global'];\nexport const PROVIDER_NAMES = { workbuddy: 'WorkBuddy', 'workbuddy-ai': 'WorkBuddy AI', trae: 'Trae CN',\n 'trae-global': 'Trae Global', qoder: 'Qoder CN', 'qoder-global': 'Qoder Global' };\nexport const FLASH_PRESET = {\n name: 'DeepSeek V4.1 Flash \u00B7 \u81EA\u52A8\u8DEF\u7531', contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: ['workbuddy', 'trae', 'qoder'].map(provider => ({ provider, models: provider.startsWith('qoder')\n ? ['dfmodel'] : ['deepseek-v4.1-flash', 'DeepSeek-V4.1-Flash', 'DeepSeek-V4.1-Flash-Official'] })),\n};\n// IDs differ between providers; keep precise model/version bindings, never fuzzy-match variants.\nconst sharedPreset = (name, workbuddy, trae, qoder) => ({\n name: `${name} \u00B7 \u81EA\u52A8\u8DEF\u7531`, contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: [{ provider: 'workbuddy', models: [workbuddy] }, { provider: 'trae', models: Array.isArray(trae) ? trae : [trae] }, { provider: 'qoder', models: [qoder] }],\n});\nexport const ROUTE_PRESETS = {\n free: { name: 'Free \u00B7 \u52A8\u6001\u514D\u8D39\u6A21\u578B', freeOnly: true, visible: true, contextWindow: 200000, maxTokens: 32000,\n strategy: 'failover', preferExpiringCredits: false, targets: PROVIDERS.map(provider => ({ provider })) },\n 'deepseek-v4.1-flash': FLASH_PRESET,\n 'deepseek-v4-pro': sharedPreset('DeepSeek V4 Pro', 'deepseek-v4-pro', ['DeepSeek-V4-Pro-Official', 'DeepSeek-V4-Pro'], 'dmodel'),\n 'glm-5.3': sharedPreset('GLM-5.3', 'glm-5.3', 'glm-5.3', 'gmodel'),\n 'glm-5.3-flash': sharedPreset('GLM-5.3-Flash', 'glm-5.3-flash', 'glm-5.3-flash', 'gfmodel'),\n 'kimi-k3': sharedPreset('Kimi-K3', 'kimi-k3-1', 'kimi-k3', 'kmodel_latest'),\n 'kimi-k2.8-preview': sharedPreset('Kimi-K2.8-Preview', 'kimi-k2.8-preview', 'kimi-k2.8-preview', 'kmodel'),\n 'minimax-m2.7': sharedPreset('MiniMax-M2.7', 'minimax-m2.7', 'minimax-m2.7', 'mmodel'),\n};\nexport const DEFAULT_ROUTES = {\n free: ROUTE_PRESETS.free,\n 'ds4.1f': {\n name: 'DeepSeek V4.1 Flash \u00B7 Auto', contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: PROVIDERS.map(provider => ({ provider })),\n },\n ...ROUTE_PRESETS,\n};\nconst object = x => x !== null && typeof x === 'object' && !Array.isArray(x);\nconst nonempty = x => typeof x === 'string' && x.trim().length > 0;\nconst positive = x => Number.isSafeInteger(x) && x > 0;\nexport const beijingDay = at => new Date(at).toLocaleDateString('en-CA', { timeZone: 'Asia/Shanghai' });\nexport function isFreeModel(model, now = Date.now()) {\n if (model.billing?.rateUnknown === true) return false;\n // A badge or a zero adapter cost is not an account-scoped zero billing rate.\n const rate = model.creditMultiplier ?? (/^x?(\\d+(?:\\.\\d+)?)(?:\\s+credits?)?$/i.exec(model.billing?.credits?.trim() ?? '')?.[1]);\n if (rate === undefined || !Number.isFinite(Number(rate)) || Number(rate) !== 0) return false;\n if (model.promotions?.length && !model.promotions.some(p => now >= p.start && now < p.end)) return false;\n return true;\n}\nexport function validateConfig(raw, file = resolve('router.json')) {\n if (!object(raw) || !Array.isArray(raw.accounts)) throw new Error('Config must contain an accounts array');\n const ids = new Set();\n const accounts = raw.accounts.map(account => {\n if (!object(account) || !/^[a-zA-Z0-9_-]{1,64}$/.test(account.id ?? '') || ids.has(account.id)) throw new Error('Account ids must be unique, 1\u201364 letters, digits, _ or -');\n ids.add(account.id);\n if (!PROVIDERS.includes(account.provider) || !nonempty(account.credentialFile)) throw new Error(`Invalid provider or credentialFile for ${account.id}`);\n if (account.enabled !== undefined && typeof account.enabled !== 'boolean') throw new Error(`Invalid enabled flag for ${account.id}`);\n if (account.name !== undefined && (!nonempty(account.name) || account.name.length > 100)) throw new Error(`Invalid account name for ${account.id}`);\n if (account.identityFile !== undefined && !nonempty(account.identityFile)) throw new Error(`Invalid identityFile for ${account.id}`);\n return { ...account, credentialFile: resolve(dirname(file), account.credentialFile),\n ...(account.identityFile ? { identityFile: resolve(dirname(file), account.identityFile) } : {}) };\n });\n if (!object(raw.routes ?? DEFAULT_ROUTES)) throw new Error('Routes must be an object');\n const routes = Object.fromEntries(Object.entries(raw.routes ?? DEFAULT_ROUTES).map(([id, route]) => [id, { ...route, preferExpiringCredits: route?.preferExpiringCredits ?? !route?.freeOnly, expiringWithinDays: route?.expiringWithinDays ?? 7 }]));\n for (const [alias, route] of Object.entries(routes)) {\n if (!/^[a-zA-Z0-9_.-]{1,128}$/.test(alias) || !object(route) || !Array.isArray(route.targets) || !route.targets.length) throw new Error(`Invalid route ${alias}`);\n for (const key of ['contextWindow', 'maxTokens']) if (!positive(route[key])) throw new Error(`Route ${alias} needs a positive ${key}`);\n if (route.maxTokens > route.contextWindow) throw new Error(`Route ${alias}: maxTokens exceeds contextWindow`);\n if (route.supportsImages !== undefined && typeof route.supportsImages !== 'boolean') throw new Error(`Invalid supportsImages for ${alias}`);\n if (route.visible !== undefined && typeof route.visible !== 'boolean') throw new Error(`Invalid visibility for ${alias}`);\n if (route.name !== undefined && (!nonempty(route.name) || route.name.length > 200)) throw new Error(`Invalid route name for ${alias}`);\n if (route.freeOnly !== undefined && typeof route.freeOnly !== 'boolean') throw new Error(`Invalid freeOnly for ${alias}`);\n if (route.freeModels !== undefined && (!route.freeOnly || !object(route.freeModels) || Object.entries(route.freeModels).some(([id, p]) =>\n !/^free_[a-f0-9]{24}$/.test(id) || !object(p) || Object.keys(p).some(k => !['visible', 'reasoningEffort'].includes(k))\n || (p.visible !== undefined && typeof p.visible !== 'boolean')\n || (p.reasoningEffort !== undefined && p.reasoningEffort !== null && !REASONING_EFFORTS.includes(p.reasoningEffort))))) throw new Error('\u514D\u8D39\u6A21\u578B\u5C55\u793A\u6216\u63A8\u7406\u7B49\u7EA7\u8BBE\u7F6E\u65E0\u6548');\n if (route.freeOnly && ((route.strategy && route.strategy !== 'failover') || route.preferExpiringCredits)) throw new Error('Free \u8DEF\u7531\u4EC5\u4F7F\u7528\u514D\u8D39\u6A21\u578B\u6545\u969C\u5207\u6362\uFF0C\u4E0D\u4F7F\u7528\u79EF\u5206\u6216\u989D\u5EA6\u8F6E\u6362');\n if (route.preferExpiringCredits !== undefined && typeof route.preferExpiringCredits !== 'boolean') throw new Error(`Invalid expiring credits flag in ${alias}`);\n if (route.expiringWithinDays !== undefined && (!positive(route.expiringWithinDays) || route.expiringWithinDays > 365)) throw new Error(`Invalid expiry horizon in ${alias}`);\n if (route.strategy !== undefined && !['failover', 'weighted', 'tokens', 'credits'].includes(route.strategy)) throw new Error(`Invalid strategy in ${alias}`);\n for (const target of route.targets) {\n if (!object(target)) throw new Error(`Invalid target in ${alias}`);\n if (target.weight !== undefined && (!positive(target.weight) || target.weight > 1000)) throw new Error(`Invalid target weight in ${alias}`);\n if (target.tokenBudget !== undefined && !positive(target.tokenBudget)) throw new Error(`Invalid token budget in ${alias}`);\n if (target.creditBudget !== undefined && (typeof target.creditBudget !== 'number' || !Number.isFinite(target.creditBudget) || target.creditBudget <= 0)) throw new Error(`Invalid credit budget in ${alias}`);\n if (route.strategy === 'tokens' && !positive(target.tokenBudget)) throw new Error(`Route ${alias} needs token budgets`);\n if (route.strategy === 'credits' && !(target.creditBudget > 0)) throw new Error(`Route ${alias} needs credit budgets`);\n if (!object(target) || !PROVIDERS.includes(target.provider) || (target.model !== undefined && !nonempty(target.model))) throw new Error(`Invalid target in ${alias}`);\n if (target.models !== undefined && (!Array.isArray(target.models) || !target.models.length || target.models.length > 20 || !target.models.every(nonempty))) throw new Error(`Invalid target models in ${alias}`);\n if (target.model !== undefined && target.models !== undefined) throw new Error(`Choose model or models in ${alias}`);\n if (target.account !== undefined && !accounts.some(a => a.id === target.account && a.provider === target.provider)) throw new Error(`Unknown target account in ${alias}`);\n if (!target.model && !target.models && alias !== 'ds4.1f' && !route.freeOnly) throw new Error(`Route ${alias} requires explicit target model ids`);\n }\n }\n const models = raw.models ?? {};\n if (!object(models)) throw new Error('Models must be an object');\n for (const [provider, preferences] of Object.entries(models)) {\n if (!PROVIDERS.includes(provider) || !object(preferences)) throw new Error('Invalid model provider');\n for (const [id, preference] of Object.entries(preferences)) {\n if (!nonempty(id) || id.length > 256 || !object(preference)\n || (preference.name !== undefined && (!nonempty(preference.name) || preference.name.length > 200))\n || (preference.visible !== undefined && typeof preference.visible !== 'boolean')) throw new Error('Invalid model preference');\n }\n }\n const modelVisibility = raw.modelVisibility ?? {};\n if (!object(modelVisibility) || Object.entries(modelVisibility).some(([provider, visible]) => !PROVIDERS.includes(provider) || typeof visible !== 'boolean')) throw new Error('Invalid modelVisibility');\n for (const key of ['cooldownMs', 'requestTimeoutMs', 'catalogTtlMs']) if (raw[key] !== undefined && !positive(raw[key])) throw new Error(`Invalid ${key}`);\n if (raw.retryServerErrors !== undefined && typeof raw.retryServerErrors !== 'boolean') throw new Error('Invalid retryServerErrors');\n if (raw.usageRetentionDays !== undefined && (!positive(raw.usageRetentionDays) || raw.usageRetentionDays > 365)) throw new Error('Token \u660E\u7EC6\u4FDD\u7559\u5929\u6570\u5FC5\u987B\u4E3A 1\u2013365 \u7684\u6574\u6570');\n return { ...raw, accounts, routes, models, modelVisibility, cooldownMs: raw.cooldownMs ?? 60000,\n requestTimeoutMs: raw.requestTimeoutMs ?? 300000, catalogTtlMs: raw.catalogTtlMs ?? 300000,\n retryServerErrors: raw.retryServerErrors ?? false, usageRetentionDays: raw.usageRetentionDays ?? 3 };\n}\nexport async function readConfig(file) {\n return validateConfig(JSON.parse(await readFile(file, 'utf8')), resolve(file));\n}\nexport async function ensureConfig(file) {\n try { return await readConfig(file); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n await mkdir(dirname(file), { recursive: true, mode: 0o700 });\n return withFileLock(file, async () => {\n try { return await readConfig(file); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n await writePrivateJson(file, { accounts: [], routes: ROUTE_PRESETS });\n return readConfig(file);\n }, { waitMs: 30000 });\n}\nexport async function writePrivateJson(file, value) {\n await mkdir(dirname(file), { recursive: true, mode: 0o700 });\n const temp = `${file}.${randomUUID()}.tmp`;\n await writeFile(temp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600, flag: 'wx' });\n await rename(temp, file);\n await chmod(file, 0o600);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const REASONING_EFFORTS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\n// Keep declared modes only. A fixed-thinking model without a declared set uses platform default.\nexport function reasoningModes(model, provider) {\n const r = model?.reasoning;\n if (!r || (r.supports !== true && !Array.isArray(r.supported))) return [];\n const declared = r.supportedEfforts ?? r.supported ?? [];\n const disable = r.canDisableThinking === true || declared.includes('off');\n const off = disable && !(provider === 'workbuddy' && r.onlyReasoning === true);\n return REASONING_EFFORTS.filter(e => e === 'off' ? off : declared.includes(e));\n}\n\nexport function routeReasoning(models) {\n const efforts = REASONING_EFFORTS.filter(e => models.some(({ model, provider }) => reasoningModes(model, provider).includes(e)));\n if (!efforts.length) return undefined;\n return { supports: true, supportedEfforts: efforts, canDisableThinking: efforts.includes('off'),\n defaultEffort: efforts.includes('high') ? 'high' : efforts[0] };\n}\n", "import { readFile, mkdir, rename, writeFile, chmod } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { withFileLock } from '@deepseek-ai/dsh-atomic-write';\nimport { REASONING_EFFORTS } from './reasoning.mjs';\n\nexport const PROVIDERS = ['workbuddy', 'workbuddy-ai', 'trae', 'trae-global', 'qoder', 'qoder-global'];\nexport const PROVIDER_NAMES = { workbuddy: 'WorkBuddy', 'workbuddy-ai': 'WorkBuddy AI', trae: 'Trae CN',\n 'trae-global': 'Trae Global', qoder: 'Qoder CN', 'qoder-global': 'Qoder Global' };\nexport const FLASH_PRESET = {\n name: 'DeepSeek V4.1 Flash \u00B7 \u81EA\u52A8\u8DEF\u7531', contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: ['workbuddy', 'trae', 'qoder'].map(provider => ({ provider, models: provider.startsWith('qoder')\n ? ['dfmodel'] : ['deepseek-v4.1-flash', 'DeepSeek-V4.1-Flash', 'DeepSeek-V4.1-Flash-Official'] })),\n};\n// IDs differ between providers; keep precise model/version bindings, never fuzzy-match variants.\nconst sharedPreset = (name, workbuddy, trae, qoder) => ({\n name: `${name} \u00B7 \u81EA\u52A8\u8DEF\u7531`, contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: [{ provider: 'workbuddy', models: [workbuddy] }, { provider: 'trae', models: Array.isArray(trae) ? trae : [trae] }, { provider: 'qoder', models: [qoder] }],\n});\nexport const ROUTE_PRESETS = {\n free: { name: 'Free \u00B7 \u52A8\u6001\u514D\u8D39\u6A21\u578B', freeOnly: true, visible: true, contextWindow: 200000, maxTokens: 32000,\n strategy: 'failover', preferExpiringCredits: false, targets: PROVIDERS.map(provider => ({ provider })) },\n 'deepseek-v4.1-flash': FLASH_PRESET,\n 'deepseek-v4-pro': sharedPreset('DeepSeek V4 Pro', 'deepseek-v4-pro', ['DeepSeek-V4-Pro-Official', 'DeepSeek-V4-Pro'], 'dmodel'),\n 'glm-5.3': sharedPreset('GLM-5.3', 'glm-5.3', 'glm-5.3', 'gmodel'),\n 'glm-5.3-flash': sharedPreset('GLM-5.3-Flash', 'glm-5.3-flash', 'glm-5.3-flash', 'gfmodel'),\n 'kimi-k3': sharedPreset('Kimi-K3', 'kimi-k3-1', 'kimi-k3', 'kmodel_latest'),\n 'kimi-k2.8-preview': sharedPreset('Kimi-K2.8-Preview', 'kimi-k2.8-preview', 'kimi-k2.8-preview', 'kmodel'),\n 'minimax-m2.7': sharedPreset('MiniMax-M2.7', 'minimax-m2.7', 'minimax-m2.7', 'mmodel'),\n};\nexport const DEFAULT_ROUTES = {\n free: ROUTE_PRESETS.free,\n 'ds4.1f': {\n name: 'DeepSeek V4.1 Flash \u00B7 Auto', contextWindow: 200000, maxTokens: 32000, preferExpiringCredits: true, expiringWithinDays: 7,\n targets: PROVIDERS.map(provider => ({ provider })),\n },\n ...ROUTE_PRESETS,\n};\nconst object = x => x !== null && typeof x === 'object' && !Array.isArray(x);\nconst nonempty = x => typeof x === 'string' && x.trim().length > 0;\nconst positive = x => Number.isSafeInteger(x) && x > 0;\nexport const beijingDay = at => new Date(at).toLocaleDateString('en-CA', { timeZone: 'Asia/Shanghai' });\nexport function isFreeModel(model, now = Date.now()) {\n if (model.billing?.rateUnknown === true) return false;\n // A badge or a zero adapter cost is not an account-scoped zero billing rate.\n const rate = model.creditMultiplier ?? (/^x?(\\d+(?:\\.\\d+)?)(?:\\s+credits?)?$/i.exec(model.billing?.credits?.trim() ?? '')?.[1]);\n if (rate === undefined || !Number.isFinite(Number(rate)) || Number(rate) !== 0) return false;\n if (model.promotions?.length && !model.promotions.some(p => now >= p.start && now < p.end)) return false;\n return true;\n}\nexport function validateConfig(raw, file = resolve('router.json')) {\n if (!object(raw) || !Array.isArray(raw.accounts)) throw new Error('Config must contain an accounts array');\n const ids = new Set();\n const accounts = raw.accounts.map(account => {\n if (!object(account) || !/^[a-zA-Z0-9_-]{1,64}$/.test(account.id ?? '') || ids.has(account.id)) throw new Error('Account ids must be unique, 1\u201364 letters, digits, _ or -');\n ids.add(account.id);\n if (!PROVIDERS.includes(account.provider) || !nonempty(account.credentialFile)) throw new Error(`Invalid provider or credentialFile for ${account.id}`);\n if (account.enabled !== undefined && typeof account.enabled !== 'boolean') throw new Error(`Invalid enabled flag for ${account.id}`);\n if (account.name !== undefined && (!nonempty(account.name) || account.name.length > 100)) throw new Error(`Invalid account name for ${account.id}`);\n if (account.identityFile !== undefined && !nonempty(account.identityFile)) throw new Error(`Invalid identityFile for ${account.id}`);\n return { ...account, credentialFile: resolve(dirname(file), account.credentialFile),\n ...(account.identityFile ? { identityFile: resolve(dirname(file), account.identityFile) } : {}) };\n });\n if (!object(raw.routes ?? DEFAULT_ROUTES)) throw new Error('Routes must be an object');\n const routes = Object.fromEntries(Object.entries(raw.routes ?? DEFAULT_ROUTES).map(([id, route]) => [id, { ...route, preferExpiringCredits: route?.preferExpiringCredits ?? !route?.freeOnly, expiringWithinDays: route?.expiringWithinDays ?? 7 }]));\n for (const [alias, route] of Object.entries(routes)) {\n if (!/^[a-zA-Z0-9_.-]{1,128}$/.test(alias) || !object(route) || !Array.isArray(route.targets) || !route.targets.length) throw new Error(`Invalid route ${alias}`);\n for (const key of ['contextWindow', 'maxTokens']) if (!positive(route[key])) throw new Error(`Route ${alias} needs a positive ${key}`);\n if (route.maxTokens > route.contextWindow) throw new Error(`Route ${alias}: maxTokens exceeds contextWindow`);\n if (route.supportsImages !== undefined && typeof route.supportsImages !== 'boolean') throw new Error(`Invalid supportsImages for ${alias}`);\n if (route.visible !== undefined && typeof route.visible !== 'boolean') throw new Error(`Invalid visibility for ${alias}`);\n if (route.name !== undefined && (!nonempty(route.name) || route.name.length > 200)) throw new Error(`Invalid route name for ${alias}`);\n if (route.freeOnly !== undefined && typeof route.freeOnly !== 'boolean') throw new Error(`Invalid freeOnly for ${alias}`);\n if (route.freeModels !== undefined && (!route.freeOnly || !object(route.freeModels) || Object.entries(route.freeModels).some(([id, p]) =>\n !/^free_[a-f0-9]{24}$/.test(id) || !object(p) || Object.keys(p).some(k => !['visible', 'reasoningEffort'].includes(k))\n || (p.visible !== undefined && typeof p.visible !== 'boolean')\n || (p.reasoningEffort !== undefined && p.reasoningEffort !== null && !REASONING_EFFORTS.includes(p.reasoningEffort))))) throw new Error('\u514D\u8D39\u6A21\u578B\u5C55\u793A\u6216\u63A8\u7406\u7B49\u7EA7\u8BBE\u7F6E\u65E0\u6548');\n if (route.freeOnly && ((route.strategy && route.strategy !== 'failover') || route.preferExpiringCredits)) throw new Error('Free \u8DEF\u7531\u4EC5\u4F7F\u7528\u514D\u8D39\u6A21\u578B\u6545\u969C\u5207\u6362\uFF0C\u4E0D\u4F7F\u7528\u79EF\u5206\u6216\u989D\u5EA6\u8F6E\u6362');\n if (route.preferExpiringCredits !== undefined && typeof route.preferExpiringCredits !== 'boolean') throw new Error(`Invalid expiring credits flag in ${alias}`);\n if (route.expiringWithinDays !== undefined && (!positive(route.expiringWithinDays) || route.expiringWithinDays > 365)) throw new Error(`Invalid expiry horizon in ${alias}`);\n if (route.strategy !== undefined && !['failover', 'weighted', 'tokens', 'credits'].includes(route.strategy)) throw new Error(`Invalid strategy in ${alias}`);\n for (const target of route.targets) {\n if (!object(target)) throw new Error(`Invalid target in ${alias}`);\n if (target.weight !== undefined && (!positive(target.weight) || target.weight > 1000)) throw new Error(`Invalid target weight in ${alias}`);\n if (target.tokenBudget !== undefined && !positive(target.tokenBudget)) throw new Error(`Invalid token budget in ${alias}`);\n if (target.creditBudget !== undefined && (typeof target.creditBudget !== 'number' || !Number.isFinite(target.creditBudget) || target.creditBudget <= 0)) throw new Error(`Invalid credit budget in ${alias}`);\n if (route.strategy === 'tokens' && !positive(target.tokenBudget)) throw new Error(`Route ${alias} needs token budgets`);\n if (route.strategy === 'credits' && !(target.creditBudget > 0)) throw new Error(`Route ${alias} needs credit budgets`);\n if (!object(target) || !PROVIDERS.includes(target.provider) || (target.model !== undefined && !nonempty(target.model))) throw new Error(`Invalid target in ${alias}`);\n if (target.models !== undefined && (!Array.isArray(target.models) || !target.models.length || target.models.length > 20 || !target.models.every(nonempty))) throw new Error(`Invalid target models in ${alias}`);\n if (target.model !== undefined && target.models !== undefined) throw new Error(`Choose model or models in ${alias}`);\n if (target.account !== undefined && !accounts.some(a => a.id === target.account && a.provider === target.provider)) throw new Error(`Unknown target account in ${alias}`);\n if (!target.model && !target.models && alias !== 'ds4.1f' && !route.freeOnly) throw new Error(`Route ${alias} requires explicit target model ids`);\n }\n }\n const models = raw.models ?? {};\n if (!object(models)) throw new Error('Models must be an object');\n for (const [provider, preferences] of Object.entries(models)) {\n if (!PROVIDERS.includes(provider) || !object(preferences)) throw new Error('Invalid model provider');\n for (const [id, preference] of Object.entries(preferences)) {\n if (!nonempty(id) || id.length > 256 || !object(preference)\n || (preference.name !== undefined && (!nonempty(preference.name) || preference.name.length > 200))\n || (preference.visible !== undefined && typeof preference.visible !== 'boolean')) throw new Error('Invalid model preference');\n }\n }\n const modelVisibility = raw.modelVisibility ?? {};\n if (!object(modelVisibility) || Object.entries(modelVisibility).some(([provider, visible]) => !PROVIDERS.includes(provider) || typeof visible !== 'boolean')) throw new Error('Invalid modelVisibility');\n for (const key of ['cooldownMs', 'requestTimeoutMs', 'catalogTtlMs']) if (raw[key] !== undefined && !positive(raw[key])) throw new Error(`Invalid ${key}`);\n if (raw.retryServerErrors !== undefined && typeof raw.retryServerErrors !== 'boolean') throw new Error('Invalid retryServerErrors');\n if (raw.ignoredLocalAccounts !== undefined && (!Array.isArray(raw.ignoredLocalAccounts) || raw.ignoredLocalAccounts.some(k => typeof k !== 'string' || k.length > 1024))) throw new Error('Invalid ignoredLocalAccounts');\n if (raw.usageRetentionDays !== undefined && (!positive(raw.usageRetentionDays) || raw.usageRetentionDays > 365)) throw new Error('Token \u660E\u7EC6\u4FDD\u7559\u5929\u6570\u5FC5\u987B\u4E3A 1\u2013365 \u7684\u6574\u6570');\n return { ...raw, accounts, routes, models, modelVisibility, cooldownMs: raw.cooldownMs ?? 60000,\n requestTimeoutMs: raw.requestTimeoutMs ?? 300000, catalogTtlMs: raw.catalogTtlMs ?? 300000,\n retryServerErrors: raw.retryServerErrors ?? false, usageRetentionDays: raw.usageRetentionDays ?? 3 };\n}\nexport async function readConfig(file) {\n return validateConfig(JSON.parse(await readFile(file, 'utf8')), resolve(file));\n}\nexport async function ensureConfig(file) {\n try { return await readConfig(file); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n await mkdir(dirname(file), { recursive: true, mode: 0o700 });\n return withFileLock(file, async () => {\n try { return await readConfig(file); } catch (error) { if (error.code !== 'ENOENT') throw error; }\n await writePrivateJson(file, { accounts: [], routes: ROUTE_PRESETS });\n return readConfig(file);\n }, { waitMs: 30000 });\n}\nexport async function writePrivateJson(file, value) {\n await mkdir(dirname(file), { recursive: true, mode: 0o700 });\n const temp = `${file}.${randomUUID()}.tmp`;\n await writeFile(temp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600, flag: 'wx' });\n await rename(temp, file);\n await chmod(file, 0o600);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-DNQPZMPF.js";
5
5
  import {
6
6
  RouteError
7
- } from "./chunk-3VVQXFPV.js";
7
+ } from "./chunk-GGRCX2NR.js";
8
8
  import {
9
9
  REASONING_EFFORTS
10
- } from "./chunk-HZVBEBOD.js";
10
+ } from "./chunk-XMXFIV5G.js";
11
11
 
12
12
  // src/shim.mjs
13
13
  import { createServer } from "node:http";
@@ -113,4 +113,4 @@ function createShim(router, { modelPrefix = "" } = {}) {
113
113
  export {
114
114
  createShim
115
115
  };
116
- //# sourceMappingURL=chunk-PD2DTHG2.js.map
116
+ //# sourceMappingURL=chunk-XY2UB22K.js.map
package/lib/cli.js CHANGED
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createAccountClient
4
- } from "./chunk-VESY2B5O.js";
4
+ } from "./chunk-UFS7ZJKY.js";
5
5
  import {
6
6
  importAccount
7
- } from "./chunk-IEN3ZQFS.js";
8
- import "./chunk-WNRHV24A.js";
7
+ } from "./chunk-3VGKH7MF.js";
8
+ import "./chunk-FTM7RHQV.js";
9
9
  import "./chunk-S5KMFAQM.js";
10
10
  import {
11
11
  Router
12
- } from "./chunk-3VVQXFPV.js";
12
+ } from "./chunk-GGRCX2NR.js";
13
13
  import {
14
14
  DEFAULT_ROUTES,
15
15
  PROVIDERS,
16
16
  validateConfig,
17
17
  writePrivateJson
18
- } from "./chunk-HZVBEBOD.js";
18
+ } from "./chunk-XMXFIV5G.js";
19
19
  import "./chunk-TEZ2FMEO.js";
20
20
 
21
21
  // src/cli.mjs
package/lib/client.js CHANGED
@@ -20,18 +20,41 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/client.jsx
21
21
  var client_exports = {};
22
22
  __export(client_exports, {
23
+ RestartGuidance: () => RestartGuidance,
23
24
  RouterPage: () => RouterPage,
24
25
  apply: () => apply,
26
+ backendNeedsRestart: () => backendNeedsRestart,
25
27
  inject: () => inject,
26
28
  name: () => name,
27
29
  readManagementResponse: () => readManagementResponse
28
30
  });
29
31
  module.exports = __toCommonJS(client_exports);
30
32
  var import_react = require("react");
33
+
34
+ // package.json
35
+ var version = "0.3.8";
36
+
37
+ // src/client.jsx
31
38
  var import_jsx_runtime = require("react/jsx-runtime");
32
39
  var name = "dsh-multi-router-client";
33
40
  var inject = ["slots"];
34
41
  var ENDPOINT = "/.well-known/dsh-multi-router";
42
+ var backendNeedsRestart = (data) => !!data && data.pluginVersion !== version;
43
+ function RestartGuidance({ data, retry }) {
44
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", role: "alert", children: [
45
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: "\u9700\u8981\u91CD\u65B0\u542F\u52A8 DeepSeek Harness" }),
46
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: data ? `\u9762\u677F\u7248\u672C ${version}\uFF0C\u540E\u53F0\u7248\u672C ${data.pluginVersion || "\u65E7\u7248"}\u3002\u66F4\u65B0\u540E\u7684\u540E\u53F0\u5C1A\u672A\u91CD\u65B0\u52A0\u8F7D\u3002` : "\u63D2\u4EF6\u540E\u53F0\u5C1A\u672A\u542F\u52A8\u3002\u82E5\u521A\u5B89\u88C5\u6216\u66F4\u65B0\u63D2\u4EF6\uFF0C\u8BF7\u5B8C\u6210\u4E0B\u9762\u7684\u91CD\u542F\u6B65\u9AA4\u3002" }),
47
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
48
+ "macOS\uFF1A\u9876\u90E8\u83DC\u5355\u300CDeepSeek Harness \u2192 \u9000\u51FA DeepSeek Harness\u300D\uFF08\u2318Q\uFF09\uFF0C\u518D\u91CD\u65B0\u6253\u5F00\u5E94\u7528\u3002",
49
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
50
+ "Windows\uFF1A\u9000\u51FA\u6258\u76D8\u4E2D\u7684 DeepSeek Harness\uFF0C\u518D\u91CD\u65B0\u6253\u5F00\u3002",
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
52
+ "\u7F51\u9875\u7248\uFF1A\u91CD\u542F\u8FD0\u884C DSH \u7684\u670D\u52A1\u8FDB\u7A0B\u3002"
53
+ ] }),
54
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "notice", children: "\u5173\u95ED\u7A97\u53E3\u6216\u5237\u65B0\u9762\u677F\u4E0D\u4F1A\u91CD\u65B0\u52A0\u8F7D\u540E\u53F0\u3002\u91CD\u542F\u540E\u4F1A\u4FDD\u7559\u8D26\u53F7\u3001\u8DEF\u7531\u548C\u7528\u91CF\uFF1B\u5982\u4ECD\u63D0\u793A\u5F02\u5E38\uFF0C\u8BF7\u67E5\u770B\u4E0B\u65B9\u7EC4\u4EF6\u7684\u542F\u7528\u9519\u8BEF\u3002" }),
55
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: retry, children: "\u6211\u5DF2\u91CD\u542F\uFF0C\u91CD\u65B0\u68C0\u67E5" }) })
56
+ ] });
57
+ }
35
58
  async function readManagementResponse(res) {
36
59
  let next;
37
60
  try {
@@ -120,7 +143,7 @@ function RouterPage({ view = "page" }) {
120
143
  return () => clearInterval(timer);
121
144
  }, [view, live]);
122
145
  async function act(action) {
123
- if (busy) return false;
146
+ if (busy || backendNeedsRestart(data)) return false;
124
147
  setBusy(true);
125
148
  setError("");
126
149
  setNotice("");
@@ -129,7 +152,7 @@ function RouterPage({ view = "page" }) {
129
152
  const next = await readManagementResponse(res);
130
153
  const { exported, ...state } = next;
131
154
  setData(state);
132
- setNotice(action.action.includes("refresh") ? "\u5DF2\u5237\u65B0\u3002\u65E0\u6CD5\u83B7\u53D6\u7684\u8D26\u53F7\u4F1A\u4FDD\u7559\u4E0A\u6B21\u6570\u636E\u5E76\u6807\u8BB0\u3002" : action.action === "config.import" ? "\u914D\u7F6E\u5DF2\u5BFC\u5165\u5E76\u751F\u6548\uFF0C\u539F\u914D\u7F6E\u5DF2\u5907\u4EFD\uFF1B\u6A21\u578B\u548C\u7528\u91CF\u6B63\u5728\u540E\u53F0\u66F4\u65B0\u3002" : action.action.startsWith("config.") || action.action === "account.export" ? "" : "\u5DF2\u4FDD\u5B58\u5E76\u751F\u6548\u3002");
155
+ setNotice(action.action === "accounts.discover" || action.action === "monitor.refresh" ? "\u5DF2\u91CD\u65B0\u68C0\u6D4B\u672C\u673A\u767B\u5F55\u5E76\u5237\u65B0\u7528\u91CF\uFF1B\u68C0\u6D4B\u7ED3\u679C\u89C1\u4E0B\u65B9\u3002" : action.action.includes("refresh") ? "\u5DF2\u5237\u65B0\u3002\u65E0\u6CD5\u83B7\u53D6\u7684\u8D26\u53F7\u4F1A\u4FDD\u7559\u4E0A\u6B21\u6570\u636E\u5E76\u6807\u8BB0\u3002" : action.action === "config.import" ? "\u914D\u7F6E\u5DF2\u5BFC\u5165\u5E76\u751F\u6548\uFF0C\u539F\u914D\u7F6E\u5DF2\u5907\u4EFD\uFF1B\u6A21\u578B\u548C\u7528\u91CF\u6B63\u5728\u540E\u53F0\u66F4\u65B0\u3002" : action.action.startsWith("config.") || action.action === "account.export" ? "" : "\u5DF2\u4FDD\u5B58\u5E76\u751F\u6548\u3002");
133
156
  return next;
134
157
  } catch (e) {
135
158
  setError(e.message);
@@ -178,25 +201,32 @@ function RouterPage({ view = "page" }) {
178
201
  setNotice("");
179
202
  }, children: label }, key)) }),
180
203
  !draft && !accountModal && !presetModal && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Feedback, { error, notice }),
181
- !data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: error ? "\u63D2\u4EF6\u540E\u53F0\u6682\u4E0D\u53EF\u7528\u3002\u4FEE\u590D\u542F\u7528\u9519\u8BEF\u540E\u70B9\u51FB\u300C\u5237\u65B0\u9762\u677F\u300D\u3002" : "\u6B63\u5728\u8BFB\u53D6\u8D26\u53F7\u4E0E\u7528\u91CF\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", "aria-busy": busy, children: [
204
+ (backendNeedsRestart(data) || !data && error) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RestartGuidance, { data, retry: () => {
205
+ void load().catch((e) => setError(e.message));
206
+ } }),
207
+ !data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", children: error ? "\u63D2\u4EF6\u540E\u53F0\u6682\u4E0D\u53EF\u7528\u3002\u4FEE\u590D\u542F\u7528\u9519\u8BEF\u540E\u70B9\u51FB\u300C\u5237\u65B0\u9762\u677F\u300D\u3002" : "\u6B63\u5728\u8BFB\u53D6\u8D26\u53F7\u4E0E\u7528\u91CF\u2026" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("fieldset", { className: "stack", style: { border: 0, padding: 0, margin: 0, minWidth: 0 }, disabled: backendNeedsRestart(data), "aria-busy": busy, children: [
182
208
  tab === "overview" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Overview, { data, live, setLive, busy, act, go: (key) => setTab(key) }),
183
209
  tab === "usage" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UsageDetails, { data, busy, act }),
184
210
  tab === "accounts" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "stack", children: [
185
211
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
186
212
  providerSelect,
187
213
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "row", children: [
214
+ !provider.startsWith("qoder") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
215
+ void act({ action: "accounts.discover", provider });
216
+ }, children: "\u91CD\u65B0\u68C0\u6D4B\u672C\u673A\u767B\u5F55" }),
188
217
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { disabled: busy, onClick: () => {
189
218
  void act({ action: "monitor.refresh", provider });
190
219
  }, children: "\u5237\u65B0\u767B\u5F55\u4E0E\u7528\u91CF" }),
191
220
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "primary", disabled: busy, onClick: () => openAccount("add"), children: "\u6DFB\u52A0\u8D26\u53F7" })
192
221
  ] })
193
222
  ] }),
194
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "\u6DFB\u52A0\u8D26\u53F7 \u2192 \u4E00\u952E\u8BFB\u53D6\u672C\u673A\u767B\u5F55\uFF0C\u6216\u624B\u52A8\u586B\u5199\u51ED\u8BC1 \u2192 \u4FDD\u5B58\u5230\u8D26\u53F7\u6C60\u3002\u6BCF\u4E2A\u8D26\u53F7\u72EC\u7ACB\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u8865\u5145\u6216\u66F4\u65B0\u51ED\u8BC1\u3002" }),
195
- !accounts.length && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "box empty", children: [
196
- "\u8FD8\u6CA1\u6709 ",
197
- p?.name,
198
- " \u8D26\u53F7\u3002\u70B9\u51FB\u300C\u6DFB\u52A0\u8D26\u53F7\u300D\u5F00\u59CB\u3002"
199
- ] }),
223
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "steps", children: "WorkBuddy \u4E0E Trae \u542F\u52A8\u65F6\u81EA\u52A8\u8BFB\u53D6\u672C\u673A\u5DF2\u767B\u5F55\u8D26\u53F7\uFF0C\u6BCF\u5206\u949F\u91CD\u65B0\u68C0\u6D4B\uFF1BTrae \u81EA\u52A8\u8BC6\u522B CN\u3001Global \u4E0E SOLO\u3002\u4E5F\u53EF\u6DFB\u52A0\u624B\u52A8\u51ED\u8BC1\u6216\u5BFC\u5165\u5176\u5B83\u8BBE\u5907\u8D26\u53F7\u3002\u5404\u8D26\u53F7\u4FDD\u7559\u72EC\u7ACB\u526F\u672C\u3002" }),
224
+ data.localDiscovery?.filter((s) => s.provider === provider).map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "notice", children: [
225
+ s.state === "found" ? "\u5DF2\u53D1\u73B0\u672C\u673A\u5BA2\u6237\u7AEF\u767B\u5F55\u3002" : s.state === "unreadable" ? "\u672C\u673A\u767B\u5F55\u6587\u4EF6\u65E0\u6CD5\u8BFB\u53D6\u3002\u8BF7\u5728\u5B98\u65B9\u5BA2\u6237\u7AEF\u91CD\u65B0\u767B\u5F55\u540E\u91CD\u8BD5\uFF0C\u6216\u5728\u300C\u6DFB\u52A0\u8D26\u53F7\u300D\u4E2D\u624B\u52A8\u586B\u5199\u51ED\u8BC1\u3002" : "\u672A\u627E\u5230\u672C\u673A\u5DF2\u767B\u5F55\u8D26\u53F7\u3002\u8BF7\u5148\u5B89\u88C5\u5E76\u767B\u5F55\u5BF9\u5E94\u533A\u57DF\u7684\u5B98\u65B9\u5BA2\u6237\u7AEF\uFF0C\u7136\u540E\u91CD\u65B0\u68C0\u6D4B\u3002",
226
+ " \xB7 ",
227
+ when(s.checkedAt)
228
+ ] }, s.provider)),
229
+ !accounts.length && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "box empty", children: provider.startsWith("qoder") ? "Qoder \u9700\u8981\u6DFB\u52A0 PAT\uFF0C\u6216\u8BFB\u53D6\u539F\u8FDE\u63A5\u5668\u5DF2\u4FDD\u5B58\u7684 PAT\u3002" : `\u8FD8\u6CA1\u6709 ${p?.name} \u8D26\u53F7\u3002\u767B\u5F55\u5B98\u65B9\u5BA2\u6237\u7AEF\u540E\u4F1A\u81EA\u52A8\u68C0\u6D4B\uFF0C\u4E5F\u53EF\u70B9\u51FB\u300C\u6DFB\u52A0\u8D26\u53F7\u300D\u624B\u52A8\u5BFC\u5165\u3002` }),
200
230
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid", children: accounts.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "box stack", children: [
201
231
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "bar", children: [
202
232
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
@@ -821,7 +851,7 @@ function CredentialTransfer({ account, busy, act }) {
821
851
  function CredentialForm({ modal, provider, data, busy, act, close, error, notice }) {
822
852
  const replacing = modal.mode === "credentials";
823
853
  const [selected, setSelected] = (0, import_react.useState)(modal.account?.provider || provider), [mode, setMode] = (0, import_react.useState)("client"), [localError, setLocalError] = (0, import_react.useState)(""), [json, setJson] = (0, import_react.useState)("");
824
- const [edition, setEdition] = (0, import_react.useState)(modal.account?.login?.edition || (selected === "trae-global" ? "sg" : "cn"));
854
+ const [edition, setEdition] = (0, import_react.useState)(modal.account?.login?.edition || "auto");
825
855
  const isTrae = selected.startsWith("trae"), isQoder = selected.startsWith("qoder"), global = selected === "trae-global" || selected === "workbuddy-ai" || selected === "qoder-global";
826
856
  const field = (label, name2, type = "text", required = true, value) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
827
857
  label,
@@ -889,7 +919,7 @@ function CredentialForm({ modal, provider, data, busy, act, close, error, notice
889
919
  "\u4F9B\u5E94\u5546 / \u533A\u57DF",
890
920
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { disabled: busy || replacing, value: selected, onChange: (e) => {
891
921
  setSelected(e.target.value);
892
- setEdition(e.target.value === "trae-global" ? "sg" : "cn");
922
+ setEdition("auto");
893
923
  setJson("");
894
924
  setLocalError("");
895
925
  }, children: data.providers.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: p.id, children: p.name }, p.id)) })
@@ -897,13 +927,14 @@ function CredentialForm({ modal, provider, data, busy, act, close, error, notice
897
927
  field("\u8D26\u53F7\u540D\u79F0\uFF08\u53EF\u9009\uFF09", "name", "text", false, modal.account?.name),
898
928
  isTrae && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
899
929
  "\u767B\u5F55\u7684\u5BA2\u6237\u7AEF",
900
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { value: edition, disabled: busy, onChange: (e) => setEdition(e.target.value), children: (global ? [["sg", "Trae Global"], ["solo-sg", "TRAE SOLO Global"]] : [["cn", "Trae CN"], ["solo", "TRAE SOLO CN"]]).map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: label }, id)) })
930
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { value: edition, disabled: busy, onChange: (e) => setEdition(e.target.value), children: (mode === "client" ? [["auto", "\u81EA\u52A8\u8BC6\u522B\uFF08\u63A8\u8350\uFF09"], ...global ? [["sg", "Trae Global"], ["solo-sg", "TRAE SOLO Global"]] : [["cn", "Trae CN"], ["solo", "TRAE SOLO CN"]]] : global ? [["sg", "Trae Global"], ["solo-sg", "TRAE SOLO Global"]] : [["cn", "Trae CN"], ["solo", "TRAE SOLO CN"]]).map(([id, label]) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: id, children: label }, id)) })
901
931
  ] })
902
932
  ] }),
903
933
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { children: [
904
934
  "\u51ED\u8BC1\u6DFB\u52A0\u65B9\u5F0F",
905
935
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { disabled: busy, value: mode, onChange: (e) => {
906
936
  setMode(e.target.value);
937
+ if (e.target.value !== "client" && edition === "auto") setEdition(global ? "sg" : "cn");
907
938
  setJson("");
908
939
  setLocalError("");
909
940
  }, children: [